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-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.
circprog_destroy (void *vself)
{
circular_progress_t self = vself;
+ grub_gfxmenu_timeout_unregister ((grub_gui_component_t) self);
grub_free (self);
}
*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)
{
}
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,
char *id;
int visible;
char *text;
+ char *template;
grub_font_t font;
grub_gui_color_t color;
+ int value;
enum align_mode align;
};
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);
}
+ 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)
{
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)
{
}
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;
}
progress_bar_destroy (void *vself)
{
grub_gui_progress_bar_t self = vself;
+ grub_gfxmenu_timeout_unregister ((grub_gui_component_t) self);
grub_free (self);
}
}
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;
}
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;
#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;
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
{
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
#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
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