]> git.ipfire.org Git - thirdparty/grub.git/commitdiff
Fix gfxmenu crash.
authorVladimir 'phcoder' Serbinenko <phcoder@gmail.com>
Thu, 13 May 2010 01:56:14 +0000 (03:56 +0200)
committerVladimir 'phcoder' Serbinenko <phcoder@gmail.com>
Thu, 13 May 2010 01:56:14 +0000 (03:56 +0200)
Reported by: Thorsten Grützmacher.

* gfxmenu/gui_circular_progress.c (circprog_destroy): Unregister
timeout hook.
(circprog_set_property): Register and unregister timeout hook.
* gfxmenu/gui_label.c (grub_gui_label): New fields template and value.
(label_destroy): Free template. and unregister hook.
(label_set_state): New function.
(label_set_property): Handle templates and hooks.
* gfxmenu/gui_progress_bar.c (progress_bar_destroy): Unregister
timeout hook.
(progress_bar_set_property): Register and unregister timeout hook.
* gfxmenu/view.c (TIMEOUT_COMPONENT_ID): Move from here ...
* include/grub/gui.h (GRUB_GFXMENU_TIMEOUT_COMPONENT_ID): ...to here
* gfxmenu/view.c (grub_gfxmenu_timeout_notifications): New variable.
(update_timeout_visit): Removed.
(update_timeouts): New function.
(redraw_timeouts): Likewise.
(grub_gfxmenu_print_timeout): Use update_timeouts and redraw_timeouts.
(grub_gfxmenu_clear_timeout): Likewise.
* include/grub/gui.h (grub_gfxmenu_set_state_t): New type.
(grub_gfxmenu_timeout_notify): Likewise.
(grub_gfxmenu_timeout_notifications): New external variable.
(grub_gfxmenu_timeout_register): New function.
(grub_gfxmenu_timeout_unregister): Likewise.

ChangeLog
gfxmenu/gui_circular_progress.c
gfxmenu/gui_label.c
gfxmenu/gui_progress_bar.c
gfxmenu/view.c
include/grub/gui.h

index a388738cb6bb46767d8555c483179af63d5ce93c..78eebc11b3bef11d8884e2a9e65a982c5429ef2d 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,32 @@
+2010-05-13  Vladimir Serbinenko  <phcoder@gmail.com>
+
+       Fix gfxmenu crash.
+       Reported by: Thorsten Grützmacher.
+
+       * gfxmenu/gui_circular_progress.c (circprog_destroy): Unregister
+       timeout hook.
+       (circprog_set_property): Register and unregister timeout hook.
+       * gfxmenu/gui_label.c (grub_gui_label): New fields template and value.
+       (label_destroy): Free template. and unregister hook.
+       (label_set_state): New function.
+       (label_set_property): Handle templates and hooks.
+       * gfxmenu/gui_progress_bar.c (progress_bar_destroy): Unregister
+       timeout hook.
+       (progress_bar_set_property): Register and unregister timeout hook.
+       * gfxmenu/view.c (TIMEOUT_COMPONENT_ID): Move from here ...
+       * include/grub/gui.h (GRUB_GFXMENU_TIMEOUT_COMPONENT_ID): ...to here
+       * gfxmenu/view.c (grub_gfxmenu_timeout_notifications): New variable.
+       (update_timeout_visit): Removed.
+       (update_timeouts): New function.
+       (redraw_timeouts): Likewise.
+       (grub_gfxmenu_print_timeout): Use update_timeouts and redraw_timeouts.
+       (grub_gfxmenu_clear_timeout): Likewise.
+       * include/grub/gui.h (grub_gfxmenu_set_state_t): New type.
+       (grub_gfxmenu_timeout_notify): Likewise.
+       (grub_gfxmenu_timeout_notifications): New external variable.
+       (grub_gfxmenu_timeout_register): New function.
+       (grub_gfxmenu_timeout_unregister): Likewise.
+
 2010-05-09  Vladimir Serbinenko  <phcoder@gmail.com>
 
        Transform (broken) vga terminal into (working) vga video driver.
index 9a859ee2e9ca90ad4643b7e8eba18302cb2b411f..098ae1c928a659be1d93c73f379be5fe8de09699 100644 (file)
@@ -54,6 +54,7 @@ static void
 circprog_destroy (void *vself)
 {
   circular_progress_t self = vself;
+  grub_gfxmenu_timeout_unregister ((grub_gui_component_t) self);
   grub_free (self);
 }
 
@@ -211,6 +212,17 @@ circprog_get_bounds (void *vself, grub_video_rect_t *bounds)
   *bounds = self->bounds;
 }
 
+static void
+circprog_set_state (void *vself, int visible, int start,
+                   int current, int end)
+{
+  circular_progress_t self = vself;  
+  self->visible = visible;
+  self->start = start;
+  self->value = current;
+  self->end = end;
+}
+
 static grub_err_t
 circprog_set_property (void *vself, const char *name, const char *value)
 {
@@ -247,26 +259,20 @@ circprog_set_property (void *vself, const char *name, const char *value)
     }
   else if (grub_strcmp (name, "id") == 0)
     {
+      grub_gfxmenu_timeout_unregister ((grub_gui_component_t) self);
       grub_free (self->id);
       if (value)
         self->id = grub_strdup (value);
       else
         self->id = 0;
+      if (self->id && grub_strcmp (self->id, GRUB_GFXMENU_TIMEOUT_COMPONENT_ID)
+         == 0)
+       grub_gfxmenu_timeout_register ((grub_gui_component_t) self,
+                                      circprog_set_state);
     }
   return grub_errno;
 }
 
-static void
-circprog_set_state (void *vself, int visible, int start,
-                   int current, int end)
-{
-  circular_progress_t self = vself;  
-  self->visible = visible;
-  self->start = start;
-  self->value = current;
-  self->end = end;
-}
-
 static struct grub_gui_component_ops circprog_ops =
 {
   .destroy = circprog_destroy,
index a9dd575ac9506ac3b6d837e2783064e8cbdad582..15a352f84c25379fb51123b2893a14a30cc74c82 100644 (file)
@@ -46,8 +46,10 @@ struct grub_gui_label
   char *id;
   int visible;
   char *text;
+  char *template;
   grub_font_t font;
   grub_gui_color_t color;
+  int value;
   enum align_mode align;
 };
 
@@ -57,7 +59,9 @@ static void
 label_destroy (void *vself)
 {
   grub_gui_label_t self = vself;
+  grub_gfxmenu_timeout_unregister ((grub_gui_component_t) self);
   grub_free (self->text);
+  grub_free (self->template);
   grub_free (self);
 }
 
@@ -146,6 +150,17 @@ label_get_minimal_size (void *vself, unsigned *width, unsigned *height)
              + grub_font_get_descent (self->font));
 }
 
+static void
+label_set_state (void *vself, int visible, int start __attribute__ ((unused)),
+                int current, int end __attribute__ ((unused)))
+{
+  grub_gui_label_t self = vself;  
+  self->value = -current;
+  self->visible = visible;
+  grub_free (self->text);
+  self->text = grub_xasprintf (self->template ? : "%d", self->value);
+}
+
 static grub_err_t
 label_set_property (void *vself, const char *name, const char *value)
 {
@@ -153,9 +168,17 @@ label_set_property (void *vself, const char *name, const char *value)
   if (grub_strcmp (name, "text") == 0)
     {
       grub_free (self->text);
+      grub_free (self->template);
       if (! value)
-        value = "";
-      self->text = grub_strdup (value);
+       {
+         self->template = NULL;
+         self->text = grub_strdup ("");
+       }
+      else
+       {
+         self->template = grub_strdup (value);
+         self->text = grub_xasprintf (value, self->value);
+       }
     }
   else if (grub_strcmp (name, "font") == 0)
     {
@@ -183,11 +206,16 @@ label_set_property (void *vself, const char *name, const char *value)
     }
   else if (grub_strcmp (name, "id") == 0)
     {
+      grub_gfxmenu_timeout_unregister ((grub_gui_component_t) self);
       grub_free (self->id);
       if (value)
         self->id = grub_strdup (value);
       else
         self->id = 0;
+      if (self->id && grub_strcmp (self->id, GRUB_GFXMENU_TIMEOUT_COMPONENT_ID)
+         == 0)
+       grub_gfxmenu_timeout_register ((grub_gui_component_t) self,
+                                      label_set_state);
     }
   return GRUB_ERR_NONE;
 }
index d786aae31a77d5048c9240e5e9f7315a2634f045..e1b31794fb7810b02c2adb04f825c3db1bcaeacb 100644 (file)
@@ -60,6 +60,7 @@ static void
 progress_bar_destroy (void *vself)
 {
   grub_gui_progress_bar_t self = vself;
+  grub_gfxmenu_timeout_unregister ((grub_gui_component_t) self);
   grub_free (self);
 }
 
@@ -333,11 +334,16 @@ progress_bar_set_property (void *vself, const char *name, const char *value)
     }
   else if (grub_strcmp (name, "id") == 0)
     {
+      grub_gfxmenu_timeout_unregister ((grub_gui_component_t) self);
       grub_free (self->id);
       if (value)
         self->id = grub_strdup (value);
       else
         self->id = 0;
+      /*      if (self->id && grub_strcmp (self->id, GRUB_GFXMENU_TIMEOUT_COMPONENT_ID)
+             == 0)*/
+       grub_gfxmenu_timeout_register ((grub_gui_component_t) self,
+                                      progress_bar_set_state);
     }
   return grub_errno;
 }
@@ -368,6 +374,7 @@ grub_gui_progress_bar_new (void)
   self = grub_zalloc (sizeof (*self));
   if (! self)
     return 0;
+
   self->progress.ops = &progress_bar_pb_ops;
   self->progress.component.ops = &progress_bar_ops;
   self->visible = 1;
index bf637a96d9839d3efc65e10f6266cb12434346b2..9a5671cdd3245d04b0508d51ec189b461bd0c885 100644 (file)
 #include <grub/gui_string_util.h>
 #include <grub/icon_manager.h>
 
-/* The component ID identifying GUI components to be updated as the timeout
-   status changes.  */
-#define TIMEOUT_COMPONENT_ID "__timeout__"
-
 static void
 init_terminal (grub_gfxmenu_view_t view);
 static grub_video_rect_t term_rect;
@@ -166,16 +162,28 @@ struct progress_value_data
   int value;
 };
 
+struct grub_gfxmenu_timeout_notify *grub_gfxmenu_timeout_notifications;
+
 static void
-update_timeout_visit (grub_gui_component_t component,
-                      void *userdata)
+update_timeouts (int visible, int start, int value, int end)
 {
-  struct progress_value_data *pv;
-  pv = (struct progress_value_data *) userdata;
+  struct grub_gfxmenu_timeout_notify *cur;
 
-  ((struct grub_gui_progress *) component)->ops
-    ->set_state ((struct grub_gui_progress *) component,
-                pv->visible, pv->start, pv->value, pv->end);
+  for (cur = grub_gfxmenu_timeout_notifications; cur; cur = cur->next)
+    cur->set_state (cur->self, visible, start, value, end);
+}
+
+static void
+redraw_timeouts (struct grub_gfxmenu_view *view)
+{
+  struct grub_gfxmenu_timeout_notify *cur;
+
+  for (cur = grub_gfxmenu_timeout_notifications; cur; cur = cur->next)
+    {
+      grub_video_rect_t bounds;
+      cur->self->ops->get_bounds (cur->self, &bounds);
+      grub_gfxmenu_view_redraw (view, &bounds);
+    }
 }
 
 void 
@@ -183,67 +191,26 @@ grub_gfxmenu_print_timeout (int timeout, void *data)
 {
   struct grub_gfxmenu_view *view = data;
 
-  struct progress_value_data pv;
-
-  auto void redraw_timeout_visit (grub_gui_component_t component,
-                                 void *userdata __attribute__ ((unused)));
-
-  auto void redraw_timeout_visit (grub_gui_component_t component,
-                                 void *userdata __attribute__ ((unused)))
-  {
-    grub_video_rect_t bounds;
-    component->ops->get_bounds (component, &bounds);
-    grub_gfxmenu_view_redraw (view, &bounds);
-  }
-
   if (view->first_timeout == -1)
     view->first_timeout = timeout;
 
-  pv.visible = 1;
-  pv.start = -(view->first_timeout + 1);
-  pv.end = 0;
-  pv.value = -timeout;
-
-  grub_gui_find_by_id ((grub_gui_component_t) view->canvas,
-                       TIMEOUT_COMPONENT_ID, update_timeout_visit, &pv);
-  grub_gui_find_by_id ((grub_gui_component_t) view->canvas,
-                      TIMEOUT_COMPONENT_ID, redraw_timeout_visit, &pv);
+  update_timeouts (1, -(view->first_timeout + 1), -timeout, 0);
+  redraw_timeouts (view);
   grub_video_swap_buffers ();
   if (view->double_repaint)
-    grub_gui_find_by_id ((grub_gui_component_t) view->canvas,
-                        TIMEOUT_COMPONENT_ID, redraw_timeout_visit, &pv);
+    redraw_timeouts (view);
 }
 
 void 
 grub_gfxmenu_clear_timeout (void *data)
 {
-  struct progress_value_data pv;
   struct grub_gfxmenu_view *view = data;
 
-  auto void redraw_timeout_visit (grub_gui_component_t component,
-                                 void *userdata __attribute__ ((unused)));
-
-  auto void redraw_timeout_visit (grub_gui_component_t component,
-                                 void *userdata __attribute__ ((unused)))
-  {
-    grub_video_rect_t bounds;
-    component->ops->get_bounds (component, &bounds);
-    grub_gfxmenu_view_redraw (view, &bounds);
-  }
-
-  pv.visible = 0;
-  pv.start = 1;
-  pv.end = 0;
-  pv.value = 0;
-
-  grub_gui_find_by_id ((grub_gui_component_t) view->canvas,
-                       TIMEOUT_COMPONENT_ID, update_timeout_visit, &pv);
-  grub_gui_find_by_id ((grub_gui_component_t) view->canvas,
-                      TIMEOUT_COMPONENT_ID, redraw_timeout_visit, &pv);
+  update_timeouts (0, 1, 0, 0);
+  redraw_timeouts (view);
   grub_video_swap_buffers ();
   if (view->double_repaint)
-    grub_gui_find_by_id ((grub_gui_component_t) view->canvas,
-                        TIMEOUT_COMPONENT_ID, redraw_timeout_visit, &pv);
+    redraw_timeouts (view);
 }
 
 static void
index 7bd71acd36955e71dbd356618c5a99fe87f330ac..6e4a11cbe85b5746cee0c71f18563d2ebdf53fd3 100644 (file)
 #include <grub/video.h>
 #include <grub/bitmap.h>
 #include <grub/gfxmenu_view.h>
+#include <grub/mm.h>
 
 #ifndef GRUB_GUI_H
 #define GRUB_GUI_H 1
 
+/* The component ID identifying GUI components to be updated as the timeout
+   status changes.  */
+#define GRUB_GFXMENU_TIMEOUT_COMPONENT_ID "__timeout__"
+
 /* A representation of a color.  Unlike grub_video_color_t, this
    representation is independent of any video mode specifics.  */
 typedef struct grub_gui_color
@@ -79,6 +84,46 @@ struct grub_gui_progress_ops
   void (*set_state) (void *self, int visible, int start, int current, int end);
 };
 
+typedef void (*grub_gfxmenu_set_state_t) (void *self, int visible, int start,
+                                         int current, int end);
+
+struct grub_gfxmenu_timeout_notify
+{
+  struct grub_gfxmenu_timeout_notify *next;
+  grub_gfxmenu_set_state_t set_state;
+  grub_gui_component_t self;
+};
+
+extern struct grub_gfxmenu_timeout_notify *grub_gfxmenu_timeout_notifications;
+
+static inline grub_err_t
+grub_gfxmenu_timeout_register (grub_gui_component_t self,
+                              grub_gfxmenu_set_state_t set_state)
+{
+  struct grub_gfxmenu_timeout_notify *ne = grub_malloc (sizeof (*ne));
+  if (!ne)
+    return grub_errno;
+  ne->set_state = set_state;
+  ne->self = self;
+  ne->next = grub_gfxmenu_timeout_notifications;
+  grub_gfxmenu_timeout_notifications = ne;
+  return GRUB_ERR_NONE;
+}
+
+static inline void
+grub_gfxmenu_timeout_unregister (grub_gui_component_t self)
+{
+  struct grub_gfxmenu_timeout_notify **p, *q;
+
+  for (p = &grub_gfxmenu_timeout_notifications, q = *p;
+       q; p = &(q->next), q = q->next)
+    if (q->self == self)
+      {
+       *p = q->next;
+       break;
+      }
+}
+
 typedef signed grub_fixed_signed_t;
 #define GRUB_FIXED_1 0x10000