Browse Source

Work on moving the Zori GUI from Ruby down to C.

Beoran 6 years ago
parent
commit
e48416cf1d

+ 1 - 0
include/ui.h

@@ -28,6 +28,7 @@ struct ui_state {
   
   /* HUD page and widgets */
   struct ui_state_hud {
+    int background_image;
     zori_id page;
     zori_id dialog;
   } hud;

+ 16 - 3
include/zori/zori.h

@@ -432,8 +432,8 @@ struct zori_widget;
 
 /* Event handler results. */
 enum zori_handle_result {
-  ZORI_HANDLE_ERROR   = -1, /* An error ocurred, stop propagating to children.*/ 
-  ZORI_HANDLE_DONE    = 0, /* The event was handled and consumed, no need to propagate to children automatically (widget may re-send event manually to children.)*/
+  ZORI_HANDLE_ERROR   = -1, /* An error ocurred, stop propagating to siblings as wel.*/ 
+  ZORI_HANDLE_DONE    = 0, /* The event was handled and consumed, no need to propagate to children automatically (widget may re-send event manually to children.) Sibling still receive the event. */
   ZORI_HANDLE_IGNORE  = 1, /* Event wasn't handled, propagate to children. */
   ZORI_HANDLE_PASS    = 2, /* Event was handled, but needs to be propagated.*/
 };
@@ -620,6 +620,17 @@ struct zori_widget_array miao_of_type(struct zori_widget *);
 struct zori_screen;
 struct zori_console;
 
+/** Icons of the root style (see below) */
+struct zori_root_style_icons {
+  zori_bitmap * paused;
+};
+
+/* Style elements specific for the root element. These are global to the 
+ * whole GUI under the given root.*/
+struct zori_root_style {
+  struct zori_root_style_icons icons;
+};
+
 /* 
  * Root level widget, my spread out over several displays. 
  * In Zori, there can only be a single root level widget active.
@@ -631,7 +642,9 @@ struct zori_root {
   /* Current active screen widget if any. */
   struct zori_screen * active_screen;
   /* Current active console if any. */
-  struct zori_console * console;
+  struct zori_console * console;  
+  /*- Style elements for all the GUI, not per widget.  */
+  struct zori_root_style style;
 };
 
 /* Forward declaration of a page. */

+ 52 - 10
include/zori/zori_longtext.h

@@ -5,24 +5,66 @@
 
 #define ZORI_WIDGET_TYPE_LONGTEXT ZORI_WIDGET_TYPE('z','l','t','x')
 
+/* A descriptor for the current state of the longtext */
+struct zori_longtext_state {
+  /*- Time waited between display of characters */
+  double wait;
+  
+  /*- Virtual text page we are currently on. */
+  int page;
+  
+  /*- Line of text we are currently on. */
+  int line;
+  
+  /*- Currently paused or not. */
+  int paused;
+  
+  /*- Total amount of lines to display for this text. */
+  int total;
+  
+  /*- Current position in current line. */
+  int position;
+  
+  /*- Animation timer. */
+  double anitime;
+  
+}; 
+
+
+/** Flags for the settings of a longtext widget.*/
+enum zori_longtext_setting_flag {
+    /*- Disable animation of pause marker. */
+    ZORI_LONGTEXT_SETTING_FLAG_STATIC_MARKER  = 1 << 0,
+    /*- Show letters oneby one in stead of space separated words.  */
+    ZORI_LONGTEXT_SETTING_FLAG_SHOW_LETTERS  = 1 << 1,
+};
+
+/* A descriptor for the configurable size settings of a 
+ * longtext. */
+struct zori_longtext_settings {
+  /*- Amount of lines to display in one virtual page of text. */
+  int lines;
+  /*- Vertcal spacing between lines.  */
+  int spacing;
+  /*- Delay between display of the individual characters. */
+  double delay;  
+  /*- Several flags that modify the behavior of the box. */
+  enum zori_longtext_setting_flag flags;
+};
+
 struct zori_longtext {
   struct zori_widget widget;
   int                align;
   zori_string      * caption;
   zori_string      * text;
   
-  int line_start, line_stop, line_pos; /* Current text "window". */
-  int line_max, line_height;           /* text constants. */
-  int page_lines;                      
-  /* Text "window" size for one "page" of text in amount of lines. */
-  int paused;
-  double delay;
-  double delay_total;
+  /*- Configurable settings. */
+  struct zori_longtext_settings settings;  
+  /*- Current state. */
+  struct zori_longtext_state    state;
 };
  
-
-#include "zori_longtext_proto.h" 
- 
+#include "zori_longtext_proto.h"
 
 #endif
 

+ 1 - 7
include/zori/zori_page.h

@@ -15,13 +15,7 @@ struct zori_page {
 };
 
 
-struct zori_page * zori_widget_to_page(struct zori_widget * widget);
-
-
-struct zori_page * zori_page_new(zori_id id, struct zori_widget * parent);
-
-zori_id zori_new_page(zori_id id, zori_id parent_id);
-
+#include "zori_page_proto.h"
 
 #endif
 

+ 13 - 0
include/zori/zori_page_proto.h

@@ -0,0 +1,13 @@
+/* This file was generated by runcprotoall */
+
+#ifndef CPROTO /* Needed to protect cproto from itself. */
+#ifndef zori_page_proto_included
+/* src/zori/zori_page.c */
+struct zori_page *zori_widget_to_page(struct zori_widget *widget);
+struct zori_page *zori_id_to_page(zori_id id);
+int zori_page_on_draw(union zori_event *event);
+struct zori_page *zori_page_new(zori_id id, struct zori_widget *parent);
+zori_id zori_new_page(zori_id id, zori_id parent_id);
+
+#endif /* zori_page_proto_included */ 
+#endif /* CPROTO */

+ 4 - 5
include/zori/zori_screen.h

@@ -3,7 +3,9 @@
 
 #include "zori.h"
 
-#define ZORI_WIDGET_TYPE_SCREEN ZORI_WIDGET_TYPE('z','s','c','r')
+enum {
+   ZORI_WIDGET_TYPE_SCREEN = ZORI_WIDGET_TYPE('z','s','c','r')
+};
 
 /* The top level widget for a single display. */
 struct zori_screen { 
@@ -18,10 +20,7 @@ struct zori_screen {
 };
 
 
-zori_id zori_new_screen(zori_id id, zori_display * display);
-
-struct zori_screen * zori_widget_to_screen(struct zori_widget * widget);
-
+#include "zori_screen_proto.h"
 
 #endif
 

+ 25 - 0
include/zori/zori_screen_proto.h

@@ -0,0 +1,25 @@
+/* This file was generated by runcprotoall */
+
+#ifndef CPROTO /* Needed to protect cproto from itself. */
+#ifndef zori_screen_proto_included
+/* src/zori/zori_screen.c */
+struct zori_screen *zori_widget_to_screen(struct zori_widget *widget);
+struct zori_screen *zori_get_screen(zori_id id);
+int zori_screen_on_mouse_axes(union zori_event *event);
+int zori_screen_on_sysevent(union zori_event *event);
+void zori_draw_cursor(const struct zori_cursor *cursor);
+void zori_draw_cursors(const struct zori_cursors *cursors);
+int zori_screen_on_overdraw(union zori_event *event);
+struct zori_screen *zori_screen_init(struct zori_screen *screen, zori_display *display);
+struct zori_screen *zori_screen_new(zori_id id, zori_display *display);
+zori_id zori_new_screen(zori_id id, zori_display *display);
+zori_id zori_active_page(zori_id screen_id);
+zori_id zori_screen_go(zori_id screen_id, zori_id page_id, void *data);
+struct zori_cursor *zori_cursor_set_style(struct zori_cursor *cursor, struct zori_style style);
+struct zori_screen *zori_screen_set_keyjoy_cursor_style(struct zori_screen *screen, struct zori_style style);
+struct zori_screen *zori_screen_set_mouse_cursor_style(struct zori_screen *screen, struct zori_style style);
+zori_id zori_set_keyjoy_cursor_style(zori_id id, struct zori_style style);
+zori_id zori_set_mouse_cursor_style(zori_id id, struct zori_style style);
+
+#endif /* zori_screen_proto_included */ 
+#endif /* CPROTO */

+ 1 - 64
include/zori/zori_widget.h

@@ -3,70 +3,7 @@
 
 struct zori_widget;
 
-void zori_widget_cleanup_widget_only(struct zori_widget * widget);
-void zori_widget_destroy_widget_only(struct zori_widget * widget);
-void zori_widget_call_destructor_and_destroy(struct zori_widget * widget);
-void zori_widget_destroy(struct zori_widget * widget);
-int zori_widget_accepts_event(struct zori_widget *widget, union zori_event *event);
-int zori_widget_self_raise_event(struct zori_widget *widget, union zori_event *event);
-int zori_widget_raise_event(struct zori_widget *widget, union zori_event *event);
-int zori_widget_raise_system_event(struct zori_widget *widget, zori_system_event *sysev);
-int zori_widget_raise_draw_event(struct zori_widget *widget);
-int zori_widget_raise_overdraw_event(struct zori_widget *widget);
-int zori_widget_raise_done_event(struct zori_widget *widget);
-int zori_widget_raise_free_event(struct zori_widget *widget);
-int zori_widget_raise_update_event(struct zori_widget *widget, double dt);
-int zori_widget_raise_action_event(struct zori_widget *widget);
-int zori_widget_raise_internal_action_event(struct zori_widget * widget);
-int zori_widget_raise_internal_close_event(struct zori_widget * widget);
-int zori_widget_raise_close_event(struct zori_widget *widget, struct zori_widget *from);
-int zori_widget_compare(const void *v1, const void *v2);
-struct zori_handler *zori_widget_add_handler(struct zori_widget *widget, zori_event_type type, zori_handler_func *handler, void *data);
-struct zori_handler *zori_widget_add_handlers(struct zori_widget *widget, struct zori_handler *handlers, size_t amount);
-struct zori_widget *zori_widget_done(struct zori_widget *widget);
-void zori_widget_free(struct zori_widget *widget);
-struct zori_widget *zori_widget_add_child(struct zori_widget *parent, struct zori_widget *child);
-zori_id zori_widget_margins_(struct zori_widget *widget, int left, int top, int right, int bottom);
-zori_id zori_widget_margin_(struct zori_widget *widget, int size);
-void zori_widget_draw_background(struct zori_widget *widget);
-enum zori_handle_result 
-zori_widget_must_draw_children(struct zori_widget * widget);
-int zori_widget_visible(struct zori_widget *widget);
-int zori_widget_active(struct zori_widget *widget);
-int zori_widget_active_(struct zori_widget *widget, int set);
-int zori_widget_visible_(struct zori_widget *widget, int set);
-int zori_widget_hover(struct zori_widget *widget);
-int zori_widget_hover_(struct zori_widget *widget, int set);
-int zori_widget_marked(struct zori_widget *widget);
-int zori_widget_marked_(struct zori_widget *widget, int set);
-int zori_widget_ready(struct zori_widget *widget);
-int zori_widget_ready_(struct zori_widget *widget, int set);
-int zori_xy_inside_widget_p(struct zori_widget *widget, double x, double y);
-zori_font *zori_widget_font(struct zori_widget *widget);
-zori_color zori_widget_forecolor(struct zori_widget *widget);
-zori_color zori_widget_backcolor(struct zori_widget *widget);
-int zori_widget_h(struct zori_widget *widget);
-int zori_widget_w(struct zori_widget *widget);
-int zori_widget_x(struct zori_widget *widget);
-int zori_widget_y(struct zori_widget *widget);
-int zori_widget_count_children(struct zori_widget *widget);
-struct zori_widget *zori_widget_get_child(struct zori_widget *widget, int index);
-zori_id zori_widget_paddings_(struct zori_widget *widget, int left, int top, int right, int bottom);
-zori_id zori_widget_padding_(struct zori_widget *widget, int size);
-zori_font *zori_widget_text_font(struct zori_widget *widget);
-struct zori_widget *zori_widget_init(struct zori_widget *widget, zori_widget_type type, zori_id id, struct zori_widget *parent, zori_rebox *box, struct zori_style *style);
-struct zori_widget *zori_widget_initall(struct zori_widget *widget, zori_widget_type type, int id, struct zori_widget *parent, zori_rebox *box, struct zori_style *style, struct zori_handler *handlers, size_t amount);
-void zori_widget_handle_event(struct zori_widget *widget, union zori_event *event);
-struct zori_widget *zori_widget_find_parent(struct zori_widget *widget, _Bool (*predicate)(struct zori_widget *parent, void *extra), void *extra);
-bool zori_widget_is_type(struct zori_widget * widget, zori_widget_type type);
-_Bool zori_widget_is_type_predicate(struct zori_widget *widget, void *extra);
-struct zori_widget *zori_widget_get_parent_of_type(struct zori_widget *widget, zori_widget_type type);
-struct zori_screen *zori_widget_get_screen(struct zori_widget *widget);
-int zori_mark_widget(struct zori_widget *widget);
-zori_id zori_widget_set_int_result(struct zori_widget * widget, int value);
-zori_id zori_widget_set_string_result(struct zori_widget * widget, zori_string * value);
-zori_id zori_widget_set_closed_result(struct zori_widget * widget, int value);
-
+#include "zori_widget_proto.h"
 
 #endif
 

+ 78 - 0
include/zori/zori_widget_proto.h

@@ -0,0 +1,78 @@
+/* This file was generated by runcprotoall */
+
+#ifndef CPROTO /* Needed to protect cproto from itself. */
+#ifndef zori_widget_proto_included
+/* src/zori/zori_widget.c */
+_Bool zori_widget_is_type(struct zori_widget *widget, zori_widget_type type);
+_Bool zori_widget_is_type_predicate(struct zori_widget *widget, void *extra);
+struct zori_widget *zori_widget_get_parent_of_type(struct zori_widget *widget, zori_widget_type type);
+struct zori_screen *zori_widget_get_screen(struct zori_widget *widget);
+int zori_widget_accepts_event(struct zori_widget *widget, union zori_event *event);
+int zori_widget_self_raise_event(struct zori_widget *widget, union zori_event *event);
+int zori_widget_raise_event(struct zori_widget *widget, union zori_event *event);
+int zori_widget_raise_system_event(struct zori_widget *widget, zori_system_event *sysev);
+int zori_widget_raise_draw_event(struct zori_widget *widget);
+int zori_widget_raise_overdraw_event(struct zori_widget *widget);
+int zori_widget_raise_done_event(struct zori_widget *widget);
+int zori_widget_raise_free_event(struct zori_widget *widget);
+int zori_widget_raise_update_event(struct zori_widget *widget, double dt);
+int zori_widget_raise_action_event(struct zori_widget *widget);
+int zori_widget_raise_internal_action_event(struct zori_widget *widget);
+int zori_widget_raise_close_event(struct zori_widget *widget, struct zori_widget *from);
+int zori_widget_compare(const void *v1, const void *v2);
+struct zori_handler *zori_widget_add_handler(struct zori_widget *widget, zori_event_type type, zori_handler_func *handler, void *data);
+struct zori_handler *zori_widget_add_handlers(struct zori_widget *widget, struct zori_handler *handlers, size_t amount);
+struct zori_style *zori_widget_get_mark_style(struct zori_widget *widget);
+struct zori_style *zori_widget_get_hover_style(struct zori_widget *widget);
+struct zori_widget *zori_widget_done(struct zori_widget *widget);
+void zori_widget_free(struct zori_widget *widget);
+struct zori_widget *zori_widget_add_child(struct zori_widget *parent, struct zori_widget *child);
+zori_id zori_widget_margins_(struct zori_widget *widget, int left, int top, int right, int bottom);
+zori_id zori_widget_margin_(struct zori_widget *widget, int size);
+void zori_widget_draw_background(struct zori_widget *widget);
+enum zori_handle_result zori_widget_must_draw_children(struct zori_widget *widget);
+int zori_widget_visible(struct zori_widget *widget);
+int zori_widget_active(struct zori_widget *widget);
+int zori_widget_active_(struct zori_widget *widget, int set);
+int zori_widget_visible_(struct zori_widget *widget, int set);
+int zori_widget_live(struct zori_widget *widget);
+int zori_widget_live_(struct zori_widget *widget, int set);
+int zori_widget_hover(struct zori_widget *widget);
+int zori_widget_hover_(struct zori_widget *widget, int set);
+int zori_widget_marked(struct zori_widget *widget);
+int zori_widget_marked_(struct zori_widget *widget, int set);
+int zori_widget_ready(struct zori_widget *widget);
+int zori_widget_ready_(struct zori_widget *widget, int set);
+int zori_xy_inside_widget_p(struct zori_widget *widget, double x, double y);
+zori_font *zori_widget_font(struct zori_widget *widget);
+zori_color zori_widget_forecolor(struct zori_widget *widget);
+zori_color zori_widget_backcolor(struct zori_widget *widget);
+int zori_widget_h(struct zori_widget *widget);
+int zori_widget_w(struct zori_widget *widget);
+int zori_widget_x(struct zori_widget *widget);
+int zori_widget_y(struct zori_widget *widget);
+int zori_widget_count_children(struct zori_widget *widget);
+struct zori_widget *zori_widget_get_child(struct zori_widget *widget, int index);
+zori_id zori_widget_paddings_(struct zori_widget *widget, int left, int top, int right, int bottom);
+zori_id zori_widget_padding_(struct zori_widget *widget, int size);
+zori_font *zori_widget_text_font(struct zori_widget *widget);
+struct zori_widget *zori_widget_init(struct zori_widget *widget, zori_widget_type type, zori_id id, struct zori_widget *parent, zori_rebox *box, struct zori_style *style);
+struct zori_widget *zori_widget_initall(struct zori_widget *widget, zori_widget_type type, int id, struct zori_widget *parent, zori_rebox *box, struct zori_style *style, struct zori_handler *handlers, size_t amount);
+void zori_widget_handle_event(struct zori_widget *widget, union zori_event *event);
+struct zori_widget *zori_widget_find_parent(struct zori_widget *widget, _Bool (*predicate)(struct zori_widget *parent, void *extra), void *extra);
+int zori_mark_widget(struct zori_widget *widget);
+zori_id zori_widget_set_int_result(struct zori_widget *widget, int value);
+zori_id zori_widget_set_string_result(struct zori_widget *widget, zori_string *value);
+zori_id zori_widget_set_closed_result(struct zori_widget *widget, int value);
+zori_id zori_set_mark_style(zori_id id, struct zori_style style);
+zori_id zori_set_hover_style(zori_id id, struct zori_style style);
+void zori_widget_move_self_by(struct zori_widget *widget, int dx, int dy);
+void zori_widget_resize_self_by(struct zori_widget *widget, int dw, int dh);
+void zori_widget_move_by(struct zori_widget *widget, int dx, int dy);
+void zori_widget_move_to(struct zori_widget *widget, int x, int y);
+void zori_widget_move_self_to(struct zori_widget *widget, int x, int y);
+void zori_widget_resize_self_to(struct zori_widget *widget, int w, int h);
+void zori_widget_fit_to_children(struct zori_widget *widget);
+
+#endif /* zori_widget_proto_included */ 
+#endif /* CPROTO */

+ 2 - 1
src/glh.c

@@ -3,7 +3,7 @@
 #include "mem.h"
 #include "monolog.h"
 
-
+/*
 GLuint glh_shader_make(GLenum type, char * data) {
   const GLchar * gldata = (const GLchar *) data;
   GLint status;
@@ -63,3 +63,4 @@ GLuint gl_program_make(GLuint * shaders, int amount) {
   
   return program;
 }
+*/

+ 22 - 9
src/monolog.c

@@ -255,34 +255,47 @@ int monolog_log(char * file, int line, char * level, char * format, ...) {
 }
 
 
+/* Log function helper. */
+static int monolog_log_to_stdio(
+  FILE * fout, char * file, int line, char * level, char * format, 
+  va_list args) {
+  int res;
+  if (fout) {
+    fprintf(fout, "%s: %s: %d: ", level, file, line);
+    res = vfprintf(fout, format, args);
+    if (format[strlen(format) - 1] != '\n') {
+      fputc('\n', fout);
+    }
+    return res;
+  }
+  return -1;
+}
+
+
 /* Log function for logger that logs to stdout. */
 int monolog_stdout_logger
   (char * file, int line, char * level, void * data, char * format, va_list args)
 {
   (void) data;
-  printf("%s: %s: %d: ", level, file, line);
-  return vprintf(format, args);
+  return monolog_log_to_stdio(stdout, file, line, level, format, args);
 }
 
 /* Log function for logger that logs to stderr. */
 int monolog_stderr_logger
   (char * file, int line, char * level, void * data, char * format, va_list args)
 {
+  int res;
   (void) data;
-  fprintf(stderr, "%s: %s: %d: ", level, file, line);
-  return vfprintf(stderr, format, args);
+  return monolog_log_to_stdio(stderr, file, line, level, format, args);
 }
 
 
 /** Log function for logger that logs to a FILE. */
 int monolog_file_logger
 (char * file, int line, char * level, void * data, char * format, va_list args) {
+  int res;
   FILE * fout = data;
-  if (fout) {
-    fprintf(fout, "%s: %s: %d: ", level, file, line);
-    return vfprintf(fout, format, args);
-  }
-  return -1;
+   return monolog_log_to_stdio(fout, file, line, level, format, args);
 }
 
 

+ 2 - 2
src/state.c

@@ -607,7 +607,7 @@ State * state_init(State * self, BOOL fullscreen) {
   #define STATE_FONTNAME        "GranaPadano.ttf"
   #define STATE_FONT_INDEX      20000
   
-  if(!store_load_ttf_font(STATE_FONT_INDEX, "font/" STATE_FONTNAME, -16, 0)) {
+  if(!store_load_ttf_font(STATE_FONT_INDEX, "font/" STATE_FONTNAME, -24, 0)) {
     return state_errmsg_(self, "Error loading " STATE_FONTNAME);
   }
   
@@ -654,7 +654,7 @@ State * state_init(State * self, BOOL fullscreen) {
     style.text.color = color_rgb(255,255,255);
     style.back.color = color_rgba(64,0,0, 191);
     Rebox  bounds = { {20, 20} , {600, 400} }; 
-    self->console = zori_console_new(1, &bounds, &style);
+    self->console = zori_console_new(-1, &bounds, &style);
     if(!self->console) {
       return state_errmsg_(self, "Out of memory when allocating console.");
     }

+ 35 - 16
src/ui.c

@@ -19,17 +19,19 @@
 
 static struct ui_state the_ui_state;
 
-char POEM_TEXT[] = "After mankind's summer, winter suddenly came"
-              "Most reached for the stars, but some remained"
-              "The earth scarred by the Ancients unhostpitable"
-              "The hopes low, and so much wisdom forgotten"
-              "Yet when it seemed the last hour struck"
-              "Our hope returned, a savior arose"
-              "Lord Kei, who by Creator's grace"
-              "Restored the Trees that guard us all from harm"
-              "Thus ushered in a new millennial spring"
-              "Lord Kei, watch over us and protect us"
-              "Until the Travellers return with bounty of the stars";
+char POEM_TEXT[] = 
+              "µµµµµ µµµµµµµµµ µµµµµµµ µµµµµµ µµµµµµµµ µµµµ\n"
+              "After mankind's summer, winter suddenly came\n"
+              "Most reached for the stars, but some remained\n"
+              "The earth scarred by the Ancients unhostpitable\n"
+              "The hopes low, and so much wisdom forgotten\n"
+              "Yet when it seemed the last hour struck\n"
+              "Our hope returned, a savior arose\n"
+              "Lord Kei, who by Absolute grace\n"
+              "Restored the Trees that guard us all from harm\n"
+              "Thus ushered in a new millennial spring\n"
+              "Lord Kei, watch over us and protect us\n"
+              "Until the Travellers return with bounty of the stars\n";
 
 char INTRO_TEXT[] = "Millennia have passed since mankind first traveled to the moon. "
                "Civilizations rose as never before, yet to fall again. " 
@@ -51,7 +53,11 @@ void ui_state_init_hud(struct ui_state * ui,
   ui->hud.page = zori_new_page(-1, ui->screen);
   LOG_NOTE("HUD page: %d\n", ui->hud.page);
   box = rebox_make(10, 300, 620, 200);
-  ui->hud.dialog = zori_new_longtext(-1, ui->hud.page, &box, INTRO_TEXT);
+  ui->hud.dialog = zori_new_longtext(-1, ui->hud.page, &box, POEM_TEXT);
+  ui->hud.background_image =  ui->main.background_image;
+  /*  store_load_bitmap_id(1004,  "/image/background/bluesky2.jpg"); */
+  zori_set_background_bitmap(ui->hud.page, 
+                            store_get_bitmap(ui->hud.background_image));  
 }
 
 /* Set up Zori GUI. */
@@ -80,8 +86,8 @@ zori_font * font
   }
   
   ui->main.background_image = store_load_bitmap_id(1000,  "/image/background/eruta_mainmenu.png");
-  ui->mouse_image = store_load_bitmap_id(1001, "image/gin/fountain-pen_32.png");
-  ui->keyjoy_image = store_load_bitmap_id(1002, "image/gin/fountain-pen_32.png");
+  ui->mouse_image = store_load_bitmap_id(1001, "/image/gin/fountain-pen_32.png");
+  ui->keyjoy_image = store_load_bitmap_id(1002, "/image/gin/fountain-pen_32.png");
   
   
   
@@ -134,6 +140,7 @@ zori_font * font
   }
   
   ui_state_init_hud(ui, display, font);
+  zori_screen_go(ui->screen, ui->main.page, NULL);
   
 }
 
@@ -144,16 +151,28 @@ void ui_handle_main_menu(struct ui_state * ui, int selected) {
     LOG_NOTE("Resume");
   } else if (selected == ui->main.button.new) {
     LOG_NOTE("New");
+    zori_screen_go(ui->screen, ui->hud.page, NULL);
   }
 }
 
+void ui_handle_dialog_text(struct ui_state * ui, int selected) {
+  LOG_NOTE("Dialog finished: %d\n", selected);
+}
+
+
 void ui_state_update(struct ui_state * ui, 
   zori_display * display, zori_font * font) {
 
   int value = 0;
-  if ((value = zori_result(ui->main.menu))) {
+  value = zori_result(ui->main.menu);
+  if (value) {
     ui_handle_main_menu(ui, value);
-  }  
+  }
+  
+  value = zori_result(ui->hud.dialog);  
+  if (value) {
+    ui_handle_dialog_text(ui, value);
+  }
 }
 
 

+ 1 - 1
src/utf8.c

@@ -37,7 +37,7 @@ static char utf8_length_table[256] = {
 
 
 /* Returns the length of the utf8 character that starts at 
- * str, or negative if str doesn ot point to the beginning byte of 
+ * str, or negative if str does not point to the beginning byte of 
  * of a valid utf8 character.
  */
 int utf8_decode_length(char * str) {  

+ 13 - 4
src/zori/zori.c

@@ -110,6 +110,7 @@ zori_id zori_initialize_root(void) {
   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_zori_root->style.icons.paused = NULL;
   return ZORI_ID_OK;
 } 
 
@@ -304,8 +305,8 @@ void zori_draw_all(void) {
 
 /* Dispatches system events throughout the GUI.  */
 int zori_handle_system_event(zori_system_event * sysev) {
-  /* All events are passed on to the console regardless if it is active. 
-   * Otherwise, theget events go into the system. */
+  /* All events are passed on to the console if it is active. 
+   * Otherwise, the events are passed to the root widget. */
   if (!the_zori_root) {
     return ZORI_ID_EINVAL;
   } 
@@ -373,5 +374,13 @@ int zori_result_string(zori_id id, char ** result, size_t * size);
 int zori_result_buffer(zori_id id, char ** result, size_t * size);
 
 
-
-
+int zori_mouse_button_event_unpack
+(const union zori_event * event, float * x, float * y, int * b) {
+    int ok = event->type == ZORI_SYSTEM_EVENT_MOUSE_BUTTON_DOWN;
+    ok  = ok || (event->type == ZORI_SYSTEM_EVENT_MOUSE_BUTTON_UP);
+    if (!ok) return 0;
+    * x = event->sys.ev->mouse.x;
+    * y = event->sys.ev->mouse.y;
+    * b = event->sys.ev->mouse.button;
+    return event->sys.ev->mouse.button + 1;
+}

+ 1 - 2
src/zori/zori_console.c

@@ -313,8 +313,7 @@ int zori_console_draw(union zori_event * zevent) {
 /** Activates or deactivates the console. */
 void zori_console_active_(struct zori_console * self, int active) {
   if(!self) return;
-  zori_widget_active_(&self->widget, active);
-  zori_widget_visible_(&self->widget, active);
+  zori_widget_live_(&self->widget, active);
 }
 
 /** Returns nonzero if console is active zero if not. */

+ 276 - 126
src/zori/zori_longtext.c

@@ -6,9 +6,15 @@
 #include "zori_widget.h"
 #include "zori_caption.h"
 #include "zori_longtext.h"
+#include "zori_page.h"
+#include <math.h>
 
 
 #define ZORI_LONGTEXT_LINE_POS_MAX 99999
+#define ZORI_LONGTEXT_ANIMATION_CYCLE_TIME 4.0
+#define ZORI_LONGTEXT_PAUSE_MARKER_DAMPER 2.0
+#define ZORI_LONGTEXT_PAUSE_MARKER_SCALE 0.75
+#define ZORI_LONGTEXT_DEFAULT_DELAY 0.2
 
 
 struct zori_longtext * zori_widget_to_longtext(struct zori_widget * widget) {
@@ -17,17 +23,43 @@ struct zori_longtext * zori_widget_to_longtext(struct zori_widget * widget) {
 }
 
 
+
+static bool 
+zori_longtext_calculate_lines_aid(int line_num, const zori_string *line, void * extra) {
+  struct zori_longtext * longtext = extra;
+  longtext->state.total = line_num + 1;
+  return true;
+}
+
+/** Calculates the amount of lines needed for the longtext as per al_do_multiline_text 
+ * The value is set in longtext->state.total and returned;
+ */
+
+int zori_longtext_calculate_lines(struct zori_longtext * longtext) {
+  double width = longtext->widget.inner.size.x;
+  longtext->state.total = 0;
+  al_do_multiline_ustr(zori_widget_font(&longtext->widget), width,
+       longtext->text, zori_longtext_calculate_lines_aid, longtext);
+  return longtext->state.total;
+}
+
 struct zori_longtext *
 zori_longtext_set(struct zori_longtext * longtext, const zori_string * text) {
   if (longtext) {
     if (longtext->text) {
       ustr_free(longtext->text);
       longtext->text = NULL;
+      longtext->state.total = 0;
     }
     if (text) { 
       longtext->text = ustr_dup(text);
       if (!longtext->text) {
-        LOG_ERROR("Out of memory in longtext setup.");
+        longtext->state.total = 0;
+        LOG_ERROR("Out of memory in longtext setup.\n");
+        return NULL;
+      } else {
+        zori_longtext_calculate_lines(longtext);
+        LOG_DEBUG("Longtext lines: %d\n", longtext->state.total);
       }
     }
   }
@@ -53,40 +85,74 @@ void zori_longtext_done(struct zori_longtext * longtext) {
   zori_longtext_set(longtext, NULL);
 }
 
+/** Gets the number of lines in one page. Always returns at least 1. */
+int zori_longtext_page_lines(struct zori_longtext * longtext) {    
+  if (!longtext) return 1;
+  if (longtext->settings.lines > 1) {
+    return longtext->settings.lines;
+  }
+  return 1;  
+}
+
 
-/** Gets the current text page for a longtext. */
+/** Sets the number of lines in one page. Sets at least 1. */
+int zori_longtext_page_lines_(struct zori_longtext * longtext, int pl) {    
+  if (!longtext) return -1;
+  if (pl < 1) {
+    pl = 1;
+  }
+  longtext->settings.lines = pl;
+  return longtext->settings.lines;
+}
+
+
+/** Gets the current text page for a longtext. Page 0 is the first page, etc.*/
 int zori_longtext_page(struct zori_longtext * longtext) {
+  int pl = 1;
   if (!longtext) return -2;
-  return longtext->line_start / longtext->page_lines;
+  return longtext->state.page;
 }
 
 
-/** Gets the last page number for a longtext or negative on error. */
+/** Gets the last page number (inclusive) for a longtext or negative on error. */
 int zori_longtext_last_page(struct zori_longtext * longtext) {
+  int pl = 1;
   if (!longtext) return -2;
-  return longtext->line_max / longtext->page_lines;
+  pl = zori_longtext_page_lines(longtext);
+  return longtext->state.total / pl;
 }
 
+
+
+
 /** Advances long text to the given page. Automatically unpauses as well. */
 int zori_longtext_page_(struct zori_longtext * longtext, int page) {
+  int pl = 1;
+  int line = 1;
+  if (!longtext) return -2;
   if (!longtext) return -2;
   if (page < 0) return -3;  
-  int line  = page * longtext->page_lines;
+  pl    = zori_longtext_page_lines(longtext);  
+  line  = page * pl;
   /* Check for page overflow. */
-  if (line >= longtext->line_max) {
-    return -5;    
+  LOG_NOTE("Selecting page nr %d, line nr %d, limit of %d", page, line, longtext->state.total);
+  
+
+  if (line >= longtext->state.total) {
+    LOG_WARNING("Cannot select page nr %d, line nr %d, more than limit of %d", 
+      page, line, longtext->state.total);
+    return -5;
   }
    
-  longtext->paused     = false;
-  longtext->line_start = line;
+  longtext->state.paused  = false;
+  longtext->state.line    = line;
+  longtext->state.page    = page;
 
   /* Negative delay is instant display. */
-  if (longtext->delay < 0) {  
-    longtext->line_stop  = longtext->line_start + longtext->page_lines;
-    longtext->line_pos   = ZORI_LONGTEXT_LINE_POS_MAX;
+  if (longtext->settings.delay < 0) {  
+    longtext->state.position = ZORI_LONGTEXT_LINE_POS_MAX;
   } else {
-    longtext->line_stop  = longtext->line_start + 1;
-    longtext->line_pos   = 0;
+    longtext->state.position = 0;
   }  
   return page;  
 }
@@ -95,8 +161,8 @@ int zori_longtext_page_(struct zori_longtext * longtext, int page) {
  * false if not (more text to display) */
 int zori_longtext_at_end(struct zori_longtext * longtext) {
   if (!longtext) return FALSE;
-  return  ((longtext->line_stop >= longtext->line_max) &&
-           (longtext->line_pos >= ZORI_LONGTEXT_LINE_POS_MAX));
+  return  ((longtext->state.line >= longtext->state.total)
+   /* && (longtext->state.position >= ZORI_LONGTEXT_LINE_POS_MAX) */);
 }
 
 
@@ -105,35 +171,58 @@ int zori_longtext_at_end(struct zori_longtext * longtext) {
  * updating scrolled/partial text for Longtexts. 
  */
 static bool 
-zori_longtext_update_custom_partial_text(int line_num, const char *line, int size, void * extra) {
+zori_longtext_update_custom_partial_text(int line_num, const zori_text *line, void * extra) {
   struct zori_longtext * longtext = extra;
-  longtext->line_max = line_num;
-
+  int last_line   = line_num;
+  int start_line  = longtext->state.page * longtext->settings.lines;
+  int stop_line   = (longtext->state.page + 1) * longtext->settings.lines;
+  int line_length  = al_ustr_length(line);
+  
   /* Don't draw lines before start but keep on drawing (for later lines) */
-  if (line_num < longtext->line_start) return true;
+  if (line_num < start_line) return true;
   /* Don't draw lines after stop, but keep calculating to get correct amount of lines */
-  if (line_num >= longtext->line_stop) return true;
+  if (line_num >= stop_line) return true;
   /* Reveal letter by letter on last line */
-  if (line_num == (longtext->line_stop - 1)) {
+  if (line_num == longtext->state.line) {
     /* Advance the position automatically if not paused. */
-    if (!longtext->paused) {
-      longtext->line_pos++;
+    if (!longtext->state.paused) {
+      if (longtext->settings.flags & ZORI_LONGTEXT_SETTING_FLAG_SHOW_LETTERS) {
+        al_ustr_next(line, &longtext->state.position);
+      } else {
+        int next_word = al_ustr_find_set_cstr(line, longtext->state.position + 1, " \t\r\n");
+        if (next_word > 0) {
+          longtext->state.position = next_word;
+        } else if (longtext->state.position < (line_length -1)) { /* skip almost to the end of the line. */
+          longtext->state.position = line_length;
+        } else { /* Advance, to end of line. */
+          al_ustr_next(line, &longtext->state.position);
+        }
+      }
     }
     /* Reached eol, advance to next line. */
-    if (longtext->line_pos >= size) {
+    if (longtext->state.position >= line_length) {
+      int pl = zori_longtext_page_lines(longtext);
       /* Is if the text window is full, pause, otherwise show the next line. */
-      if ((longtext->line_stop - longtext->line_start) >= longtext->page_lines) {
-        longtext->paused = true;
-      } else { 
-        longtext->line_stop++;
-        longtext->line_pos = 0;
+      if (longtext->state.line >= (stop_line-1)) {
+        longtext->state.paused = true;
+      } else {
+        longtext->state.line++;
+        longtext->state.position = 0;
       }
-    } 
+    }
   }
-  (void) line;
   return true;
 }
 
+
+/* Rerurns whether or no t the end of a page is reached on a longtext */
+int zori_longtext_end_of_page(struct zori_longtext * longtext) {
+  int limit;
+  if (zori_longtext_at_end(longtext)) return TRUE;
+  limit = (longtext->state.page + 1) * longtext->settings.lines;
+  return (longtext->state.line >= limit);
+}
+
 /* Updates the longtext, enables scrolling and per character display. */
 void zori_longtext_update_longtext(struct zori_longtext * longtext, double dt) {
   float width = longtext->widget.inner.size.x;
@@ -143,31 +232,28 @@ void zori_longtext_update_longtext(struct zori_longtext * longtext, double dt) {
     LOG_WARNING("Attempted to update a NULL longtext.");
     return;
   }
-
-  /* Delay advance of characters somewhat. */
-  longtext->delay_total += dt;
-  if (longtext->delay_total < longtext->delay) return;
-  longtext->delay_total = 0;
   
-  longtext->line_max = 0;
-  al_do_multiline_text(zori_widget_font(&longtext->widget), width,
-      (const char *) text, zori_longtext_update_custom_partial_text, longtext);
-  longtext->line_max++;
+  longtext->state.anitime += dt;
+  if (longtext->state.anitime > ZORI_LONGTEXT_ANIMATION_CYCLE_TIME) {
+     longtext->state.anitime = 0;
+  }
   
-  /* pause if the last line is reached, and prevent overflow. */
-  if (longtext->line_stop > longtext->line_max) {
-    longtext->paused    = true;
-    longtext->line_pos  = ZORI_LONGTEXT_LINE_POS_MAX;
-    longtext->line_stop = longtext->line_max;
+  /* Delay advance of characters somewhat if requested. */
+  if (longtext->settings.delay > 0.0) {
+    longtext->state.wait += dt;
+    if (longtext->state.wait < longtext->settings.delay) return;
+    longtext->state.wait = 0;
   }
-
-}
-
-/* Returns TRUE if the longtext node is at the end of the text to display,
- * false if not (more text to display) */
-int zori_longtext_longtext_at_end(struct zori_longtext * longtext) {
-  return  ((longtext->line_stop >= longtext->line_max) &&
-           (longtext->line_pos >= ZORI_LONGTEXT_LINE_POS_MAX));
+  
+  al_do_multiline_ustr(zori_widget_font(&longtext->widget), width,
+      text, zori_longtext_update_custom_partial_text, longtext);
+  
+  /* pause if the last line of the page is reached, and prevent overflow. */
+  if (zori_longtext_end_of_page(longtext)) {
+    longtext->state.paused    = TRUE;
+    longtext->state.position  = ZORI_LONGTEXT_LINE_POS_MAX;
+  }
+  
 }
 
 /* Calculates the x and y position where to draw text, taking alignment and
@@ -187,6 +273,7 @@ zori_longtext_calculate_text_position(struct zori_longtext * longtext) {
   return result;
 }
 
+/* Draws the longtext, if it has a single line.. */
 void zori_longtext_draw_text(struct zori_longtext * longtext) {
   zori_font * font;
   int flags;
@@ -205,18 +292,59 @@ void zori_longtext_draw_text(struct zori_longtext * longtext) {
 }
 
 
+/**
+ * Draws the paused marker if needed.
+ */
+static void zori_longtext_draw_paused_marker(const struct zori_longtext * longtext) {
+  struct zori_root * root = zori_get_root();
+  int line_skip;
+  float x, y, x1, y1, x2, y2, x3, y3, sp, ms;
+  
+  if (!longtext->state.paused) return; 
+    
+  line_skip = (longtext->state.page + 1 * longtext->settings.lines);
+  x   = longtext->widget.inner.at.x ; 
+  y   = longtext->widget.inner.at.y ;
+  sp  = longtext->settings.spacing;
+  y  += line_skip * sp;
+  ms  = sp * ZORI_LONGTEXT_PAUSE_MARKER_SCALE;
+  
+  /* Animate marker by varying its y position */
+  y -= sin(longtext->state.anitime * ALLEGRO_PI) * ms / ZORI_LONGTEXT_PAUSE_MARKER_DAMPER;
+  
+  if (root->style.icons.paused) { 
+    al_draw_bitmap(root->style.icons.paused, x, y, 0);
+  } else {   
+    y2 = y  + ms;
+    x2 = x + longtext->widget.inner.size.x;
+    x1 = x2 - ms;
+    y1 = y2;
+    x3 = x2 - ms / 2.0;
+    y3 = y2 + ms;
+    al_draw_filled_triangle(x1, y1, x2, y2, x3, y3, longtext->widget.style.text.color);
+  }
+}
+
+
 /* This function is the helper callback that implements the actual drawing
  * for zori_longtext_draw_partial_text.
  */
-static bool zori_longtext_draw_custom_partial_text(int line_num, const char *line,
-  int size, void *extra) {
+static bool zori_longtext_draw_custom_partial_text(int line_num, const zori_text *line, 
+  void *extra) {
   float x, y;
   struct zori_longtext * longtext = extra;  
   ALLEGRO_USTR_INFO info;
-  int real_size, flags;
-  double width;
+  const ALLEGRO_USTR * subline;
+  int real_length, flags;
   ALLEGRO_FONT * font;
   BeVec pos;
+  int sublength   = al_ustr_length(line);
+  int last_line   = line_num;
+  int start_line  = longtext->state.page * longtext->settings.lines;
+  int stop_line   = longtext->state.line + 1;
+  if (stop_line >= longtext->state.total) {
+    stop_line = longtext->state.total;
+  }
   
   font      = zori_widget_font(&longtext->widget);
   flags     = longtext->widget.style.text.flags | ALLEGRO_ALIGN_INTEGER;
@@ -225,39 +353,42 @@ static bool zori_longtext_draw_custom_partial_text(int line_num, const char *lin
 
   
   /* Don't draw lines before start but keep on drawing (for later lines) */
-  if (line_num < longtext->line_start) return true;
+  if (line_num < start_line) return true;
   /* Don't draw lines after stop, drawing is done */
-  if (line_num >= longtext->line_stop) return false;
-  real_size = size;
-  /* calculate position */
+  if (line_num >= stop_line) return false;
+  
+  real_length = sublength;
+  
+  /* Reveal letter by letter on currently active line */
+  if (line_num == (longtext->state.line)) { 
+    real_length = (longtext->state.position < sublength) ? longtext->state.position : sublength;
+  }
+  
+  
   x  = pos.x;
-  y  = pos.y + (longtext->line_height * (line_num - longtext->line_start));
+  y  = pos.y + (longtext->settings.spacing * (line_num - start_line));
 
-  /* Reveal letter by letter on last line */
-  if (line_num == (longtext->line_stop - 1)) { 
-    real_size = (longtext->line_pos < size) ? longtext->line_pos : size;
-
-    /* Draw continuation marker if paused. XXX... this needs to be done 
-     * better... Maybe a bitmap member or so? */
-    if (longtext->paused) {
-      float x1, y1, x2, y2, x3, y3;
-      y2 = y  + 8;
-      x2 = x + longtext->widget.inner.size.x;
-      x1 = x2 - 8;
-      y1 = y2;
-      x3 = x2 - 4;
-      y3 = y2 + 8;
-      al_draw_filled_triangle(x1, y1, x2, y2, x3, y3, longtext->widget.style.text.color);
-    }
+    
+  /* calculate position of subline */
+  subline = al_ref_ustr(&info, line, 0, al_ustr_offset(line, real_length));
+
+  
+  if (flags & ALLEGRO_ALIGN_CENTER) {    
+    /* x -= al_get_ustr_width(font, subline) / 2; */
+  } else if (flags & ALLEGRO_ALIGN_RIGHT) {
+    x -= al_get_ustr_width(font, subline);
   }
+
+  
+  
+  
+  // real_size = size;
   
   zori_color shadow = longtext->widget.style.back.color;
   zori_color fore   = longtext->widget.style.text.color;
   
-  al_draw_ustr(font, shadow,
-      x + 1, y + 1, flags, al_ref_buffer(&info, line, real_size));
-  al_draw_ustr(font, fore,
-      x, y, flags, al_ref_buffer(&info, line, real_size));
+  al_draw_ustr(font, shadow, x + 1, y + 1, flags, subline);
+  al_draw_ustr(font, fore, x, y, flags, subline);
                 
   return true;
 }
@@ -266,47 +397,34 @@ static bool zori_longtext_draw_custom_partial_text(int line_num, const char *lin
 /* Allows to draw a multi line text partially, from line_start up to
  * line_stop. Draws scrolling text from a prefilled struct. */ 
 void zori_longtext_draw_partial_text(struct zori_longtext * longtext) {
-  float width = longtext->widget.inner.size.x;
+  float width = longtext->widget.inner.size.x - 20; 
   zori_font * font = zori_widget_font(&longtext->widget);
   
   if (!longtext->text) {
     LOG_WARNING("Trying to draw a NULL longtext.");
     return;
   }
-  
-  const char * text = ustr_c(longtext->text);
-  
-  /* It's a bit of a hack that this ends up here... */
-  if (longtext->line_height < 1.0) {
-    longtext->line_height = al_get_font_line_height(font);
-  }
-  
-  al_do_multiline_text(font, width,
-      (const char *) text, zori_longtext_draw_custom_partial_text, longtext);  
+      
+  al_do_multiline_ustr(font, width,
+      longtext->text, zori_longtext_draw_custom_partial_text, longtext);  
 }
 
 
 void zori_draw_longtext(struct zori_longtext * longtext) {
+  zori_widget_draw_background(&longtext->widget);
   zori_longtext_draw_partial_text(longtext);
+  zori_longtext_draw_paused_marker(longtext);
 }
 
 
 /** Sets the last line to display for a long text */
 zori_id zori_set_line_stop(zori_id index, int stop) {
-  struct zori_widget * widget = zori_get_widget(index);
-  struct zori_longtext * longtext = zori_widget_to_longtext(widget);
-  if (!longtext) return ZORI_ID_EINVAL; 
-  longtext->line_stop = stop;
-  return index;
+  return ZORI_ID_EINVAL;
 }
 
 /** Sets the first line to display for a long text */
 zori_id zori_line_start_(zori_id index, int start) {
-struct zori_widget * widget = zori_get_widget(index);
-  struct zori_longtext * longtext = zori_widget_to_longtext(widget);
-  if (!longtext) return ZORI_ID_EINVAL; 
-  longtext->line_start = start;
-  return index;
+  return ZORI_ID_EINVAL;
 }
 
 /** Sets display delay between individual characters for a long text */
@@ -314,43 +432,34 @@ int zori_delay_(zori_id index, double delay) {
   struct zori_widget * widget = zori_get_widget(index);
   struct zori_longtext * longtext = zori_widget_to_longtext(widget);
   if (!longtext) return ZORI_ID_EINVAL; 
-  longtext->delay = delay;
+  longtext->settings.delay = delay;
   return index;
 }
 
-
-
 /** Gets the last line to display for a long text  or negative on error*/
 int zori_line_stop(int index) {
-  struct zori_widget * widget = zori_get_widget(index);
-  struct zori_longtext * longtext = zori_widget_to_longtext(widget);
-  if (!longtext) return ZORI_ID_EINVAL;
-  return longtext->line_stop;
+  return ZORI_ID_EINVAL;
 }
 
 /** Gets the first line to display for a long text */
 int zori_line_start(int index) {
-  struct zori_widget * widget = zori_get_widget(index);
-  struct zori_longtext * longtext = zori_widget_to_longtext(widget);
-  if (!longtext) return ZORI_ID_EINVAL;
-  return longtext->line_start;
+  return ZORI_ID_EINVAL;
 }
 
-/** Gets display delay between individual characters  for a long text */
+/** Gets display delay between individual characters for a long text */
 double zori_delay(int index) {
   struct zori_widget * widget = zori_get_widget(index);
   struct zori_longtext * longtext = zori_widget_to_longtext(widget);
   if (!longtext) return ZORI_ID_EINVAL;
-  return longtext->delay;
+  return longtext->settings.delay;
 }
 
-
-/** Sets amount of shown lines for a long text */
+/** Sets amount of shown lines per page for a long text */
 int zori_page_lines_(zori_id index, int lines) {
   struct zori_widget * widget = zori_get_widget(index);
   struct zori_longtext * longtext = zori_widget_to_longtext(widget);
-  if (!longtext) return ZORI_ID_EINVAL;
-  longtext->page_lines = lines;
+  if (!longtext) return ZORI_ID_EINVAL;  
+  zori_longtext_page_lines_(longtext, lines);
   return index;
 }
 
@@ -359,7 +468,7 @@ int zori_page_lines(int index) {
   struct zori_widget * widget = zori_get_widget(index);
   struct zori_longtext * longtext = zori_widget_to_longtext(widget);
   if (!longtext) return ZORI_ID_EINVAL;
-  return longtext->page_lines;
+  return zori_longtext_page_lines(longtext);
 }
 
 /** Sets paused state of long text */
@@ -367,7 +476,7 @@ int zori_paused_(zori_id index, int paused) {
   struct zori_widget * widget = zori_get_widget(index);
   struct zori_longtext * longtext = zori_widget_to_longtext(widget);
   if (!longtext) return ZORI_ID_EINVAL;
-  longtext->paused = paused;
+  longtext->state.paused = paused;
   return index;
 }
 
@@ -376,7 +485,7 @@ int zori_paused(zori_id index) {
   struct zori_widget * widget = zori_get_widget(index);
   struct zori_longtext * longtext = zori_widget_to_longtext(widget);
   if (!longtext) return 0;
-  return longtext->paused;
+  return longtext->state.paused;
 }
 
 /** Gets the current text page for a longtext. */
@@ -424,8 +533,14 @@ int zori_previous_page(int index) {
   return zori_page_(index, page - 1); 
 }
 
+/** Handles an update event and pass it on. */
+int zori_longtext_on_update(union zori_event * event) { 
+  struct zori_widget * widget     = event->any.widget;
+  struct zori_longtext * longtext = zori_widget_to_longtext(widget);
+  zori_longtext_update_longtext(longtext, event->update.dt);
 
-
+  return ZORI_HANDLE_PASS;
+}
 
 /** Handles a mouse axis event and pass it on. */
 int zori_longtext_on_mouse_axes(union zori_event * event) { 
@@ -448,10 +563,27 @@ int zori_longtext_on_mouse_click(union zori_event * event) {
     struct zori_longtext * longtext = zori_widget_to_longtext(widget);
     float x = event->sys.ev->mouse.x;
     float y = event->sys.ev->mouse.y;
+    int   b = event->sys.ev->mouse.button;
     if (zori_xy_inside_widget_p(widget, x, y)) {
+      struct zori_widget * page = zori_widget_get_parent_of_type(widget, ZORI_WIDGET_TYPE_PAGE); 
       widget->result.ready = widget->id;
       widget->result.value.string = longtext->text;
       LOG_NOTE("Longtext %d clicked: %d, result %d.\n", widget->id, widget->result);
+      LOG_NOTE("Longtext visible %d.\n", zori_widget_visible(widget));
+      LOG_NOTE("UI page visible %d.\n", zori_widget_visible(page));
+      LOG_NOTE("Longtext page visible %d.\n", zori_longtext_page(longtext));
+      
+      longtext->state.paused = 0;
+      
+      if (1==b) {
+        if (zori_longtext_at_end(longtext)) { 
+          zori_widget_set_closed_result(&longtext->widget, longtext->state.total);
+        } else {
+          zori_longtext_page_(longtext, zori_longtext_page(longtext) + 1);
+        }
+      } else if (2==b) {
+        zori_longtext_page_(longtext, 0);
+      }     
       return zori_widget_raise_action_event(widget);
     }
     return ZORI_HANDLE_PASS;
@@ -470,6 +602,7 @@ struct zori_handler zori_longtext_handlers[] = {
   { ZORI_SYSTEM_EVENT_MOUSE_BUTTON_DOWN , zori_longtext_on_mouse_click   , NULL },
   { ZORI_SYSTEM_EVENT_MOUSE_AXES        , zori_longtext_on_mouse_axes    , NULL },
   { ZORI_EVENT_DRAW                     , zori_longtext_on_draw          , NULL },
+  { ZORI_EVENT_UPDATE                   , zori_longtext_on_update        , NULL },
   { -1, NULL, NULL }
 };
 
@@ -477,7 +610,23 @@ struct zori_handler zori_longtext_handlers[] = {
 struct zori_longtext * 
 zori_longtext_init(struct zori_longtext * longtext, const char * text) {
   if (longtext) {
+    int lh = 8;
     zori_longtext_set_cstr(longtext, text);
+    zori_longtext_page_(longtext, 0);
+    lh = zori_font_lineheight(longtext->widget.style.text.font);
+    zori_longtext_page_lines_(longtext, lh / longtext->widget.inner.size.y);
+    longtext->settings.delay = ZORI_LONGTEXT_DEFAULT_DELAY;
+    longtext->state.line = 0;
+    longtext->state.page = 0;
+    longtext->state.position = 0;
+    longtext->state.paused = 0;
+    longtext->state.anitime = 0.0;
+    longtext->settings.lines = 2;
+    
+    /* XXX It's a hack that this ends up here... */
+    if (longtext->settings.spacing < 1.0) {
+      longtext->settings.spacing = lh;
+    }
   }
   return longtext;
 }
@@ -494,6 +643,7 @@ struct zori_longtext * zori_longtext_new(zori_id id, zori_id parent_id,
     longtext = NULL;
   }
   zori_widget_hover_(&longtext->widget, 0);
+  zori_widget_live_(&longtext->widget, 1);
   
   return longtext;
 }

+ 11 - 1
src/zori/zori_page.c

@@ -3,12 +3,22 @@
 #include "zori_caption.h"
 #include "zori_page.h"
 
+#include "monolog.h"
+
+/* Magic comment for runcprotoall: @generate_cproto@ */
+
 
 struct zori_page * zori_widget_to_page(struct zori_widget * widget) {
   if (!zori_widget_is_type(widget, ZORI_WIDGET_TYPE_PAGE)) return NULL;
   return ZORI_CONTAINER_OF(widget, struct zori_page, widget);
 }
 
+struct zori_page * zori_id_to_page(zori_id id) {
+  struct zori_widget * widget = zori_get_widget(id);
+  if (!widget) return NULL;
+  return zori_widget_to_page(widget);
+}
+
 int zori_page_on_draw(union zori_event * event) {
   struct zori_widget * widget = event->any.widget;
   struct zori_page   * page   = zori_widget_to_page(widget);
@@ -21,7 +31,7 @@ int zori_page_on_draw(union zori_event * event) {
     al_clear_to_color(style->back.color);
   }
   
-  return ZORI_HANDLE_PASS;
+  return ZORI_HANDLE_IGNORE;
 }
 
 

+ 28 - 5
src/zori/zori_screen.c

@@ -6,6 +6,9 @@
 #include "zori_caption.h"
 #include "zori_page.h"
 #include "zori_screen.h"
+#include "monolog.h"
+
+/* Magic comment for runcprotoall: @generate_cproto@ */
 
 
 struct zori_screen * zori_widget_to_screen(struct zori_widget * widget) {
@@ -28,10 +31,10 @@ int zori_screen_on_mouse_axes(union zori_event * event) {
     screen->cursors.mouse.p.y = event->sys.ev->mouse.y;
     
     if (screen->active_page) {
-      return zori_widget_raise_system_event(&screen->active_page->widget, 
+      zori_widget_raise_system_event(&screen->active_page->widget, 
         event->sys.ev);
     }
-    return ZORI_HANDLE_PASS;
+    return ZORI_HANDLE_DONE;
 }
 
 /** Handles a system event by passing it on to the active page.  */
@@ -39,10 +42,10 @@ int zori_screen_on_sysevent(union zori_event * event) {
     struct zori_screen * screen = zori_widget_to_screen(event->any.widget);
   
     if (screen->active_page) {
-      return zori_widget_raise_system_event(&screen->active_page->widget, 
+      zori_widget_raise_system_event(&screen->active_page->widget, 
         event->sys.ev);
     }
-    return ZORI_HANDLE_PASS;
+    return ZORI_HANDLE_DONE;
 }
  
 
@@ -75,7 +78,7 @@ int zori_screen_on_overdraw(union zori_event * event) {
   return ZORI_HANDLE_PASS;
 }
 
-/* Handlers must beset up for many events on screen to funnel them all into 
+/* Handlers must be set up for many events on screen to funnel them all into 
  * the active page. */
 struct zori_handler zori_screen_handlers[] = {
   { ZORI_SYSTEM_EVENT_KEY_DOWN          , zori_screen_on_sysevent       , NULL }, 
@@ -111,6 +114,7 @@ zori_screen_init(struct zori_screen * screen, zori_display * display) {
   
   screen->display     = display; 
   screen->active_page = NULL; 
+  
   return screen;
 }
 
@@ -155,14 +159,33 @@ zori_id zori_active_page(zori_id screen_id) {
 
 
 zori_id zori_screen_go(zori_id screen_id, zori_id page_id, void * data) { 
+  int index, stop;
   struct zori_screen * screen = zori_widget_to_screen(zori_get_widget(screen_id));
   struct zori_page   * page = zori_widget_to_page(zori_get_widget(page_id));
   
   if ((screen) && (page)) {
+    if (screen->active_page) {
+      /* XXX send event later. */
+    }
+    
+    /* disable all other page widgets. */
+    stop = zori_widget_count_children(&screen->widget);
+    for (index = 0; index < stop; index ++) {
+      struct zori_widget * cpw = zori_widget_get_child(&screen->widget, index);
+      struct zori_page   * cpp = zori_widget_to_page(cpw);
+      if (!cpp) continue;
+      zori_widget_live_(&cpp->widget, 0);
+    }
+    
     screen->active_page = page;
     zori_widget_raise_action_event(&page->widget);
+    zori_widget_live_(&page->widget, 1);
+    LOG_NOTE("Switched to page: %d, %d\n", page_id, 
+      zori_widget_visible(&page->widget));
+ 
     return page->widget.id;
   } else {
+    LOG_ERROR("Could not switch to page %d\n", page_id);
     return ZORI_ID_EINVAL;
   }
 }

+ 19 - 3
src/zori/zori_widget.c

@@ -6,6 +6,8 @@
 #include "monolog.h"
 #include "draw.h"
 
+/* Magic comment for runcprotoall: @generate_cproto@ */
+
 
 bool zori_widget_is_type(struct zori_widget * widget, zori_widget_type type) {
   if(!widget) return false;
@@ -73,8 +75,8 @@ zori_widget_raise_event(struct zori_widget * widget, union zori_event * event) {
       struct zori_widget * child = miao_unsafe_get(&widget->children, index);
       event->any.widget = child;
       sub = zori_widget_raise_event(child, event);
-      if (sub == ZORI_HANDLE_DONE) {
-        result = ZORI_HANDLE_DONE;
+      if (sub == ZORI_HANDLE_ERROR) {
+        result = ZORI_HANDLE_ERROR;
         break;
       }
     }
@@ -123,7 +125,7 @@ int zori_widget_raise_free_event(struct zori_widget * widget) {
 int zori_widget_raise_update_event
 (struct zori_widget * widget, double dt) {
   union zori_event event;
-  event.update.any.type   = ZORI_EVENT_DONE;
+  event.update.any.type   = ZORI_EVENT_UPDATE;
   event.update.any.widget = widget;
   event.update.dt         = dt; 
   return zori_widget_raise_event(widget, &event);
@@ -324,6 +326,20 @@ int zori_widget_visible_(struct zori_widget * widget, int set)  {
   return zori_widget_active(widget);
 }
 
+/** Get active and visible */
+int zori_widget_live(struct zori_widget * widget) {
+  return zori_widget_active(widget) && zori_widget_visible(widget);
+} 
+
+/** Set active and visible */
+int zori_widget_live_(struct zori_widget * widget, int set) {
+  zori_widget_active_(widget, set);
+  zori_widget_visible_(widget, set);
+  return set;
+} 
+
+
+
 
 int zori_widget_hover(struct zori_widget * widget)  {
   return widget && ((widget->flags & ZORI_FLAG_HOVERED) == ZORI_FLAG_HOVERED);