Browse Source

Working on new gui system on the C side.

Beoran 7 years ago
parent
commit
e8a4ffc282
9 changed files with 461 additions and 42 deletions
  1. 2 0
      .gitignore
  2. 4 2
      CMakeLists.txt
  3. 10 7
      data/map/map_0001_tiled11.tmx
  4. 18 1
      include/miao.h
  5. 140 23
      include/zori.h
  6. 18 1
      src/state.c
  7. 226 3
      src/zori.c
  8. 1 1
      test/cmake_install.cmake
  9. 42 4
      test/test_miao.c

+ 2 - 0
.gitignore

@@ -28,3 +28,5 @@ build
 doc/nd
 doc/nd_project
 
+*.geany
+*.log

+ 4 - 2
CMakeLists.txt

@@ -20,17 +20,19 @@ include(CheckCXXSourceCompiles)
 
 if(CMAKE_COMPILER_IS_GNUCC)
 set(COMPILER_GCC 1)
-set(CMAKE_C_FLAGS "-W -Wall -wunused -Wno-unused -Wno-unknown-pragmas -g -std=c99 -ffast-math -fsanitize=address -fstrict-aliasing -Wstrict-aliasing=2")
+set(CMAKE_C_FLAGS "-W -Wall -Wno-unused -Wno-unknown-pragmas -g3 -gdwarf-2 -std=c99 -ffast-math -fsanitize=address -fstrict-aliasing -Wstrict-aliasing=2")
 # set(CMAKE_LD_FLAGS "-pg")
 # always use gnu99, debugging, all warnings except unused and unknown pragmas.
 # when compiling with gnu compiler.  
 # Warn about alisasing because otherwise aliasing problems it may not be detected.
+else(CMAKE_COMPILER_IS_GNUCC)
+set(CMAKE_C_FLAGS "-W -Wall -Wno-unused -Wno-unknown-pragmas -g -std=c99 -ffast-math -fstrict-aliasing -Wstrict-aliasing=2")
 endif(CMAKE_COMPILER_IS_GNUCC)
 
 # or for PCC
 # set(CMAKE_C_FLAGS "-fpic -fPIC")  
 
-set(CMAKE_C_FLAGS "-W -Wall -Wno-unused -Wno-unknown-pragmas -g -std=c99 -ffast-math -fstrict-aliasing -Wstrict-aliasing=2")
+
 
 find_package(Mruby REQUIRED)
 

+ 10 - 7
data/map/map_0001_tiled11.tmx

@@ -1,7 +1,10 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <map version="1.0" orientation="orthogonal" renderorder="right-down" width="100" height="100" tilewidth="32" tileheight="32" backgroundcolor="#55aaff" nextobjectid="11">
- <tileset firstgid="1" name="town" tilewidth="32" tileheight="32">
+ <tileset firstgid="1" name="town" tilewidth="32" tileheight="32" tilecount="225" columns="15">
   <image source="tiles_village_1000.png" width="480" height="480"/>
+  <terraintypes>
+   <terrain name="Grass" tile="-1"/>
+  </terraintypes>
   <tile id="0">
    <properties>
     <property name="blend" value="20"/>
@@ -15,7 +18,7 @@
     <property name="blendmask" value="0"/>
    </properties>
   </tile>
-  <tile id="2">
+  <tile id="2" terrain="0,0,0,0">
    <properties>
     <property name="blend" value="17"/>
     <property name="blendmask" value="2"/>
@@ -153,7 +156,7 @@
   </tile>
  </tileset>
  <imagelayer name="background">
-  <image source="../image/background/bluesky2.jpg"/>
+  <image source="../image/background/bluesky2.jpg" width="640" height="240"/>
   <properties>
    <property name="parallax" value="1"/>
   </properties>
@@ -367,18 +370,18 @@
 </data>
  </layer>
  <objectgroup name="object_0">
-  <object id="1" name="start" type="start" gid="35" x="96" y="128">
+  <object id="1" name="start" type="start" gid="35" x="96" y="128" width="32" height="32">
    <properties>
     <property name="script" value="particle_burst(3, 4, 10)"/>
    </properties>
   </object>
-  <object id="2" name="warp_1" type="warp" gid="35" x="416" y="416">
+  <object id="2" name="warp_1" type="warp" gid="35" x="416" y="416" width="32" height="32">
    <properties>
     <property name="id" value="1"/>
     <property name="to" value="2"/>
    </properties>
   </object>
-  <object id="3" name="warp_2" type="warp" gid="35" x="448" y="1312">
+  <object id="3" name="warp_2" type="warp" gid="35" x="448" y="1312" width="32" height="32">
    <properties>
     <property name="id" value="2"/>
     <property name="to" value="1"/>
@@ -391,7 +394,7 @@
    <polyline points="0,0 -277,271"/>
   </object>
   <object id="6" type="foe" x="320" y="448" width="32" height="32"/>
-  <object id="7" type="foe" gid="42" x="192" y="448"/>
+  <object id="7" type="foe" gid="42" x="192" y="448" width="32" height="32"/>
  </objectgroup>
  <layer name="layer_2" width="100" height="100">
   <data encoding="csv">

+ 18 - 1
include/miao.h

@@ -43,7 +43,7 @@
 #define miao_pop(ARR, DEFAULT) (((ARR)->n > 0) ? miao_unsafe_pop(ARR) : DEFAULT)
 #define miao_pop_ptr(ARR) (((ARR)->n > 0) ? miao_unsafe_pop_ptr(ARR) : NULL)
 
-#define miao_unsafe_push(ARR, VAL) ((ARR)->n++, (ARR)->a[(ARR)->n] = (VAL)) 
+#define miao_unsafe_push(ARR, VAL) ((ARR)->n++, (ARR)->a[(ARR)->n] = (VAL), &(VAL)) 
 
 #define miao_push(ARR, VAL)                                           \
           (miao_grow(ARR, ((ARR)->n + 1)) ? miao_unsafe_push(ARR, VAL) : NULL)
@@ -109,5 +109,22 @@
     }                                                                         \
   } while(0);
     
+#define miao_delete(ARR, INDEX)                                               \
+  ( miao_out_of_bounds(ARR, ((size_t)INDEX)) ? 0 :                            \
+    /* Copy over everything from index + 1 */                                 \
+    (memmove(ARR->a + INDEX, ARR->a + INDEX + 1,                              \
+      (ARR->n - INDEX - 1) * sizeof(ARR->n) ) ,                               \
+    (1 + ARR->n--))                                                           \
+  )
+
+#define miao_index_of(ARR, ENTRY) ( (ENTRY) - ((ARR)->a) )
+
+#define miao_delete_entry(ARR, ENTRY)                                          \
+  ( miao_delete(ARR, miao_index_of(ARR, ENTRY)) )
+
+#define miao_delete_bsearch(ARR, COMPARE, ENTRY)                               \
+  ( ARR->aux = miao_bsearch(ARR, COMPARE, ENTRY) ,                             \
+    ARR->aux ?  miao_delete_entry(ARR, ARR->aux)   : 0  )
+
 
 #endif

+ 140 - 23
include/zori.h

@@ -6,9 +6,9 @@
 #include "miao.h"
 
 /* Typedefs for possible later portability. */
-typedef ALLEGRO_COLOR zori_color ;
-typedef ALLEGRO_BITMAP zori_bitmap ;
-typedef ALLEGRO_FONT zori_font ;
+typedef ALLEGRO_COLOR  zori_color;
+typedef ALLEGRO_BITMAP zori_bitmap;
+typedef ALLEGRO_FONT   zori_font;
 
 typedef ALLEGRO_EVENT zori_system_event;
 typedef ALLEGRO_EVENT_TYPE zori_event_type;
@@ -25,6 +25,27 @@ typedef int zori_id;
 #define ZORI_ID_EINVAL    ((zori_id)(-3))
 
 
+
+/* Macro: ZORI_CONTAINER_OF(PTR, TYPE, MEMBER)
+ This macro returns, for the given pointer, a pointer to a containing struct
+ of type TYPE, in which PTR is a member named MEMBER. 
+ This enables cool ways of type genericity and extension in plain C.
+ It does not run afoul of strict aliasing since it passes over a char * pointer 
+ and  a pointer of a containing struct or union.
+*/
+
+#define ZORI_CONTAINER_OF(PTR, TYPE, MEMBER) \
+        ((TYPE *)(((char *)(PTR)) - offsetof(TYPE, MEMBER)))
+
+
+/** Custom event types, used in conjunction with Allegro event types. */
+enum zori_custom_event_type {
+  ZORI_EVENT_CUSTOM = ALLEGRO_GET_EVENT_TYPE('z', 'o', 'r', 'i'),
+  ZORI_EVENT_UPDATE,
+  ZORI_EVENT_DRAW,
+};
+
+
 struct zori_widget;
 
 struct zori_event {
@@ -44,12 +65,14 @@ struct zori_style {
   struct zori_stylepart fore;
   struct zori_stylepart back;
   struct zori_stylepart text;
+  struct zori_stylepart border;
 };
 
 struct zori_widget;
 
 typedef int zori_handler_func(struct zori_event * event);
 
+/* A single event handler */
 struct zori_handler {
   zori_event_type type;
   zori_handler_func * handler;
@@ -57,15 +80,28 @@ struct zori_handler {
 };
 
 
-/* System event handlers. */
+/* A dynamic array of event handlers event handlers. */
 struct zori_handlers miao_of_type(struct zori_handler);
 
-/*
-struct zori_handlers {
-  size_t size;  
-  struct zori_handler * handlers;
+
+/* An entry in a widget registry.  */
+struct zori_registry_entry {
+  zori_id              id;
+  struct zori_widget * widget;
+};
+
+/* A widget registry as a dynamic array of entries. */
+struct zori_registry miao_of_type(struct zori_registry_entry);
+
+/* Generic flags for several zori structs. */
+enum zori_flag {
+  /* The object is not visible, though it may still be interacted with.*/ 
+  ZORI_FLAG_HIDDEN      = 1 << 0,
+  /* The object cannot be interacted with, though it is still visible. */
+  ZORI_FLAG_DISABLED    = 1 << 1,
+  /* The object is both hidden and disabled. */
+  ZORI_FLAG_DEACTIVATED = ZORI_FLAG_HIDDEN | ZORI_FLAG_DISABLED,
 };
-*/
 
 
 /* Mouse or keyboard/joystick cursor. */
@@ -74,6 +110,7 @@ struct zori_cursor {
   struct zori_widget * hover;
   struct zori_widget * focus;
   zori_bitmap        * bitmap;
+  enum zori_flag       flags;
 };
 
 
@@ -121,38 +158,118 @@ struct zori_widget {
   struct zori_widget * parent;
   struct zori_widget * child;
   struct zori_widget * sibling;
+  
+  /* Flags. */
+  enum zori_flag       flags;
 };
 
 
 /* An array of widget pointers. */
-struct zori_widget_array {
-  struct zori_widget * array;
-  size_t size;
-};
+struct zori_widget_array miao_of_type(struct zori_widget *);
 
-/* Root level widget. */
-struct zori_root {  
+/* forward declaration. */
+struct zori_screen;
+
+/* 
+ * Root level widget, my spread out over several displays. 
+ * In Zori, there can only be a single root level widget active.
+ * It's ID is always 0;
+*/
+struct zori_root {
   /* A root is a widget. */ 
   struct zori_widget widget;
-  /* It also manages the cursors*/
-  struct zori_cursors cursors;
-  /* It has an array of all widgets it manages. */
+  /* It has an array of all GUI widgets it manages. */
   struct zori_widget_array * widgets;
-  /* It is linked to a particular display. */
-  zori_display * display;  
+  /* Current active screen widget if any. */
+  struct zori_screen * active_screen;
 };
 
+/* Forward declaration of a page. */
+struct zori_page;
 
+/* The top level widget for a single display. */
+struct zori_screen { 
+  /* A screen is a widget. */ 
+  struct zori_widget widget;
+  /* It also manages the cursors. */
+  struct zori_cursors cursors;
+  /* Display this screen is on. */
+  zori_display * display; 
+  /* The GUI page that is active on this screen if any. */
+  struct zori_page * active_page; 
+};
+
+
+/* In Zori, the GUI is paginated. This means that on any 
+ * screen, only a single GUI page can be active. The intent is to 
+ * support different GUI modes such as startup screen, status view, 
+ * settings, HUD, and so on between which can be switched easily. */
+struct zori_page {
+  /* A page is a widget. */
+  struct zori_widget widget;
+};
+
+/* Initializes Zori and creates a top level widget. Returns 0 on success 
+ * or negative on error. The style will be copied and set as default 
+ * if it is not NULL. Otherwise a built-in style will be used. 
+ * Not that ZORI will NOT clean up any images or fonts it uses by itself.
+ */
+zori_id zori_start(struct zori_style * default_style);
+
+/* Shut down Zori and destroys all widgets. Return 0 on succes or 
+ * negative on error.
+ */
+zori_id zori_shutdown();
+
+/* Creates a new screen widget. Normally this should be the first widget 
+ * you create after zori_start.  */
+zori_id zori_new_screen(zori_display * display);
+
+/* Creates a new page widget on the given screen. The page is not 
+ * made the active page, unless if it is the first one created. */
+zori_id zori_new_page(zori_id screen);
+
+/* Activates the page on it's display. All other pages are dectivated and 
+ * hidden. */
+zori_id zori_activate_page(zori_id page);
 
+/* Creates a new generic widget on the given screen with the given
+ * dimensions. */
+zori_id zori_new(zori_id screen, zori_rebox * box);
+
+/* Sets the flags of a widget.  */
+zori_id zori_set_flags(zori_id widget, enum zori_flag flags);
+
+
+/* Sets the whole style of a widget. */
+zori_id zori_set_style(zori_id id, struct zori_style * style);
+
+/* Sets the background color of the widget. */
 zori_id zori_set_background_color(zori_id id, zori_color color);
+
+/* Sets the foreground color of the widget. */
 zori_id zori_set_foreground_color(zori_id id, zori_color color);
-zori_id zori_new_root_widget(const struct zori_style * style);
-zori_id zori_new_frame_widget(zori_id parent);
 
+/* Creates a new frame widget. */
+zori_id zori_new_frame_widget(zori_id parent, zori_rebox box);
 
-zori_id zori_register(zori_id id,  zori_event_type type, zori_handler_func handler, void * extra);
+/* Creates a new (vertical) menu widget. */
+zori_id zori_new_menu_widget(zori_id parent, zori_rebox box, char * text);
+
+/* Creates a new button widget. */
+zori_id zori_new_button_widget(zori_id parent, zori_rebox box, char * text);
+
+/* Creates a new conversation widget. */
+zori_id zori_new_conversation_widget(zori_id parent, zori_rebox box, char * text);
 
+/* Draws the whole UI and all visible parts. */
+void zori_draw_all(void);
 
+/* Updates the state of the UI. Pass in the time passed since last update. */
+void zori_update(double dt);
+
+/* Registers an event handler for a widget. */
+zori_id zori_register(zori_id id,  zori_event_type type, zori_handler_func handler, void * extra);
 
 
 

+ 18 - 1
src/state.c

@@ -20,6 +20,7 @@
 #include "monolog.h"
 #include "callrb.h"
 #include "store.h"
+#include "zori.h"
 
 /* The data struct contains all global state and other data of the application.
 */
@@ -226,6 +227,8 @@ void state_free(State * self) {
   self->area    = NULL;
   /* Disable the active tile map */
   state_active_map_id_(self, -1);
+  /* Disable gui. */
+  zori_shutdown();
   
   rh_free(self->ruby);
   bbconsole_free((BBWidget *)self->console, NULL);
@@ -622,6 +625,18 @@ State * state_init(State * self, BOOL fullscreen) {
   if(!self->camera) {
       return state_errmsg_(self, "Out of memory when allocating camera.");
   }
+  /* Set up Zori GUI. */
+  {
+    struct zori_style style;
+    memset(&style, 0, sizeof(style));
+    style.text.font  = self->font;
+    style.text.color = color_rgb(255,255,255);
+    style.back.color = color_rgba(64,0,0, 191);
+    if ( !ZORI_ID_OK_P(zori_start(&style)) ) {
+        return state_errmsg_(self, "Out of memory when allocating GUI.");
+    }
+  }
+  
   /* Set up console. */
   {
     Style   style = { color_rgb(255,255,255), color_rgba(64,0,0, 191), 
@@ -731,7 +746,7 @@ void state_draw(State * self) {
     
     /* Draw UI scene graph */
     if (self->show_graph) { 
-      scegra_draw();
+      zori_draw_all();
     }
     /* Draw the particles from the particle engine. */
     // alpsshower_draw(&shower, state_camera(state));
@@ -775,6 +790,8 @@ void state_update(State * self) {
   // effect immediately.
   scegra_update(state_frametime(self));
   
+  zori_update(state_frametime(self));
+  
 }
 
 

+ 226 - 3
src/zori.c

@@ -1,12 +1,77 @@
 
 #include "zori.h"
 #include "miao.h"
+#include <allegro5/allegro_color.h>
 
 /*
 * Pardon the pun name, but Zori is the submodule that handles the user
 * interface and the menus. 
 */
 
+/* registry functionality */
+
+/** Compare registry entries. */
+int zori_registry_entry_compare(const void * v1, const void * v2) {
+  const struct zori_registry_entry * entry1 = v1;
+  const struct zori_registry_entry * entry2 = v2;
+  return (entry2->id - entry1->id);
+}
+
+/** Initialize the registry. */
+zori_id zori_registry_init(struct zori_registry * registry) {
+  miao_init(registry);
+  return ZORI_ID_OK;
+}
+
+
+/** Add an entry to the registry. */
+zori_id 
+zori_registry_add(struct zori_registry * registry, zori_id id, 
+struct zori_widget * widget) {
+  struct zori_registry_entry entry = { id, widget };
+  if (miao_push(registry, entry)) { 
+    miao_qsort(registry, zori_registry_entry_compare);
+    return ZORI_ID_OK;
+  }
+  return ZORI_ID_ENOMEM;
+}
+
+/** Look up an entry in the registry. */
+struct zori_registry_entry *  
+zori_registry_lookup_entry(struct zori_registry * registry, zori_id id) {
+  struct zori_registry_entry key = { id, NULL };
+  return miao_bsearch(registry, zori_registry_entry_compare, &key);
+}
+
+
+/** Look up a widget in the registry. */
+struct zori_widget *  
+zori_registry_lookup(struct zori_registry * registry, zori_id id) {
+  struct zori_widget * result = NULL;
+  struct zori_registry_entry * entry = NULL;
+  
+  entry = zori_registry_lookup_entry(registry, id);
+  if (entry) { 
+    result = entry->widget;
+  }
+  return result;
+}
+
+/** Remove an entry from the registry. */
+zori_id 
+zori_registry_remove(struct zori_registry * registry, zori_id id) {
+  struct zori_registry_entry * entry = NULL;
+  entry = zori_registry_lookup_entry(registry, id);
+  if (entry) {
+    miao_delete_entry(registry, entry);
+  }
+  return ZORI_ID_OK;
+}
+
+
+
+/** Handler functionality */
+
 int zori_handler_compare(const void * v1, const void * v2) {
   const struct zori_handler * h1 = v1;
   const struct zori_handler * h2 = v2;
@@ -57,12 +122,170 @@ int zori_handlers_handle(struct zori_handlers * me,  struct zori_event * event,
   return handler->handler(event);
 }
 
-struct zori_root zori_the_root = {0};
+static struct zori_root * the_zori_root = NULL;
+
+static struct zori_style * the_default_style = NULL;
+
+static struct zori_registry * the_zori_registry = NULL;
+
+
+int zori_widget_compare(const void * v1, const void * v2) {
+  const struct zori_widget * w1 = v1, * w2 = v2;
+  return (w2->id - w1->id);
+}
+
+
+struct zori_widget * zori_get_widget(zori_id id) {
+  struct zori_widget key = {0};
+  key.id = id;
+  return miao_bsearch(the_zori_root->widgets, zori_widget_compare, &key);
+}
+
+zori_id zori_get_unused_id(void) {
+  zori_id id = -1;
+  struct zori_widget * found;
+  do {
+    id++;
+    if (id == INT_MAX) { return ZORI_ID_ERROR; }
+    found = zori_get_widget(id);
+  } while(found);
+    
+  return id;
+}
+
+zori_id zori_start(struct zori_style * default_style) {
+  if (the_zori_root) return ZORI_ID_OK;
+  the_zori_root = calloc(1, sizeof(*the_zori_root));
+  if (!the_zori_root) return ZORI_ID_ENOMEM;
+  the_default_style = calloc(1, sizeof(*the_default_style));
+  if (!the_default_style) return ZORI_ID_ENOMEM;
+  the_zori_registry = calloc(1, sizeof(*the_zori_registry));
+  if (!the_zori_registry) return ZORI_ID_ENOMEM;
+  
+ 
+  the_default_style->text.font      = al_create_builtin_font();  
+  the_default_style->text.color     = al_color_name("white");  
+  the_default_style->border.color   = al_color_name("white");  
+  the_default_style->back.color     = al_color_name("green");  
+  
+  if (default_style) {
+    the_zori_root->widget.style = *default_style;
+  } else {
+    the_zori_root->widget.style = *the_default_style;
+  }
+  
+  miao_init(the_zori_root->widgets);
+  the_zori_root->widget.id = 0;
+  zori_registry_add(the_zori_registry, the_zori_root->widget.id, &the_zori_root->widget);
+  
+  /*
+   * miao_push(the_zori_root->widgets, &the_zori_root->widget);
+   * miao_qsort(the_zori_root->widgets, zori_widget_compare);
+   */
+  
+  
+  return the_zori_root->widget.id;  
+}
+
+void zori_widget_free(struct zori_widget * widget);
+
+struct zori_widget * zori_widget_done(struct zori_widget * widget) {
+  struct zori_widget * aid, * next;
+  if (!widget) return widget;
+  
+  if (widget->child) {
+    /* Free all children. */
+    aid  = widget->child;
+    while (aid) {
+      next = aid->sibling;
+      zori_widget_free(aid);
+      aid  = next;
+    }
+  }
+  return widget;
+}
+
+void zori_widget_free(struct zori_widget * widget) {
+  /* XXX remove from widget registry too... */
+  return free(zori_widget_done(widget));
+}
+
 
-int zori_init() {
-  return 0;
+/* Shut down Zori and destroys all widgets. Return 0 on succes or 
+ * negative on error.
+ */
+zori_id zori_shutdown() {
+  miao_done(the_zori_registry);
+  free(the_zori_registry);
+  the_zori_registry = NULL;
+  free(the_default_style);
+  the_default_style = NULL;
+  assert((void *)(&the_zori_root->widget) == (void *)the_zori_root);
+  zori_widget_free(&the_zori_root->widget);
+  the_zori_root = NULL;
+  return ZORI_ID_OK;
 }
 
+/* Creates a new screen widget. Normally this should be the first widget 
+ * you create after zori_start.  */
+zori_id zori_new_screen(zori_display * display);
+
+/* Creates a new page widget on the given screen. The page is not 
+ * made the active page, unless if it is the first one created. */
+zori_id zori_new_page(zori_id screen);
+
+/* Activates the page on it's display. All other pages are dectivated and 
+ * hidden. */
+zori_id zori_activate_page(zori_id page);
+
+/* Creates a new generic widget on the given screen with the given
+ * dimensions. */
+zori_id zori_new(zori_id screen, zori_rebox * box);
+
+/* Sets the flags of a widget.  */
+zori_id zori_set_flags(zori_id widget, enum zori_flag flags);
+
+
+/* Sets the whole style of a widget. */
+zori_id zori_set_style(zori_id id, struct zori_style * style);
+
+/* Sets the background color of the widget. */
+zori_id zori_set_background_color(zori_id id, zori_color color);
+
+/* Sets the foreground color of the widget. */
+zori_id zori_set_foreground_color(zori_id id, zori_color color);
+
+/* Creates a new frame widget. */
+zori_id zori_new_frame_widget(zori_id parent, zori_rebox box);
+
+/* Creates a new (vertical) menu widget. */
+zori_id zori_new_menu_widget(zori_id parent, zori_rebox box, char * text);
+
+/* Creates a new button widget. */
+zori_id zori_new_button_widget(zori_id parent, zori_rebox box, char * text);
+
+/* Creates a new conversation widget. */
+zori_id zori_new_conversation_widget(zori_id parent, zori_rebox box, char * text);
+
+/* Draws the whole UI and all visible parts. */
+void zori_draw_all(void) {
+
+}
+
+/* Updates the state of the UI. Pass in the time passed since last update. */
+void zori_update(double dt) 
+{
+  struct zori_event event;
+  event.sysev.type = ZORI_EVENT_UPDATE;
+  event.sysev.user.data1 = (intptr_t)&dt;
+  zori_handlers_handle(&the_zori_root->widget.handlers, &event, &the_zori_root->widget);
+}
+
+/* Registers an event handler for a widget. */
+zori_id zori_register(zori_id id,  zori_event_type type, zori_handler_func handler, void * extra);
+
+
+
 
 
 

+ 1 - 1
test/cmake_install.cmake

@@ -1,4 +1,4 @@
-# Install script for directory: /home/bjorn/src/eruta/test
+# Install script for directory: /home/bjorn/src/eruta-bs/test
 
 # Set the install prefix
 IF(NOT DEFINED CMAKE_INSTALL_PREFIX)

+ 42 - 4
test/test_miao.c

@@ -22,17 +22,17 @@ int foo_compare(const void * v1, const void * v2)
 }
 
 int foo_each_ptr(size_t i, const struct foo * f, FILE * extra) {
-  fprintf(extra, "%u => %s\n", i, f->s);
+  fprintf(extra, "%u => %s\n", (unsigned int)i, f->s);
   return 0;
 }
 
 int foo_each(size_t i, struct foo f, FILE * extra) {
-  fprintf(extra, "%u => %s\n", i, f.s);
+  fprintf(extra, "%u => %s\n", (unsigned int)i, f.s);
   return 0;
 }
 
 struct foo * foo_each_ptr_with_result(size_t i, struct foo * f, char * extra) {
-  printf("%u => %s\n", i, f->s);
+  printf("%u => %s\n", (unsigned int)i, f->s);
   return f;
 }
 
@@ -41,7 +41,7 @@ int foo_check_ptr(const struct foo * f, char * extra) {
 }  
 
 struct foo foo_each_with_result(size_t i, struct foo f, char * extra) {
-  printf("%u => %s\n", i, f.s);
+  printf("%u => %s\n", (unsigned int)i, f.s);
   return f;
 }
 
@@ -101,9 +101,47 @@ TEST_FUNC(miao) {
   TEST_ZERO(miao_size(a)); 
   TEST_DONE();
 }  
+
+TEST_FUNC(miao_delete) {
+  struct foo f1, f2 , f3;
+  struct foo * e1, * e2, *e3;
+  struct foo_array a[1];
+  struct foo_array d[1];
+  
+  miao_init(a);
+  e1 = miao_push_ptr(a);
+  e1->s = "0 zero";
+  e1 = miao_push_ptr(a);
+  e1->s = "1 one";
+  e1 = miao_push_ptr(a);
+  e1->s = "2 two";
+  e1 = miao_push_ptr(a);
+  e1->s = "3 three";
+  e1 = miao_push_ptr(a);
+  e1->s = "4 four";
+  e1 = miao_push_ptr(a);
+  e1->s = "5 five";
+ 
+  miao_qsort(a, foo_compare);
+  miao_each_with_result(a, foo_each_with_result, f3, foo_check, "foo");
+  f1.s = "3 three";
+  e1 = miao_bsearch(a, foo_compare, &f1);
+  TEST_NOTNULL(e1);  
+  TEST_INTNEQ(0, miao_delete_entry(a, e1));
+  TEST_INTEQ(5, miao_size(a));
+  miao_each_with_result(a, foo_each_with_result, f3, foo_check, "foo");
+
+  f1.s = "2 two";
+  TEST_INTNEQ(0, miao_delete_bsearch(a, foo_compare, &f1));
+  TEST_INTEQ(4, miao_size(a));
+  miao_each_with_result(a, foo_each_with_result, f3, foo_check, "foo");
+  
+  TEST_DONE();
+}
   
 int main(void) {
   TEST_INIT();
+  TEST_RUN(miao_delete);
   TEST_RUN(miao);
   TEST_REPORT();
 }