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.
This commit is contained in:
Vladimir 'phcoder' Serbinenko 2010-05-13 03:56:14 +02:00
parent c6e5caab1d
commit cced9145fc
6 changed files with 155 additions and 73 deletions

View file

@ -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> 2010-05-09 Vladimir Serbinenko <phcoder@gmail.com>
Transform (broken) vga terminal into (working) vga video driver. Transform (broken) vga terminal into (working) vga video driver.

View file

@ -54,6 +54,7 @@ static void
circprog_destroy (void *vself) circprog_destroy (void *vself)
{ {
circular_progress_t self = vself; circular_progress_t self = vself;
grub_gfxmenu_timeout_unregister ((grub_gui_component_t) self);
grub_free (self); grub_free (self);
} }
@ -211,6 +212,17 @@ circprog_get_bounds (void *vself, grub_video_rect_t *bounds)
*bounds = self->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 static grub_err_t
circprog_set_property (void *vself, const char *name, const char *value) 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) else if (grub_strcmp (name, "id") == 0)
{ {
grub_gfxmenu_timeout_unregister ((grub_gui_component_t) self);
grub_free (self->id); grub_free (self->id);
if (value) if (value)
self->id = grub_strdup (value); self->id = grub_strdup (value);
else else
self->id = 0; 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; 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 = static struct grub_gui_component_ops circprog_ops =
{ {
.destroy = circprog_destroy, .destroy = circprog_destroy,

View file

@ -46,8 +46,10 @@ struct grub_gui_label
char *id; char *id;
int visible; int visible;
char *text; char *text;
char *template;
grub_font_t font; grub_font_t font;
grub_gui_color_t color; grub_gui_color_t color;
int value;
enum align_mode align; enum align_mode align;
}; };
@ -57,7 +59,9 @@ static void
label_destroy (void *vself) label_destroy (void *vself)
{ {
grub_gui_label_t self = vself; grub_gui_label_t self = vself;
grub_gfxmenu_timeout_unregister ((grub_gui_component_t) self);
grub_free (self->text); grub_free (self->text);
grub_free (self->template);
grub_free (self); grub_free (self);
} }
@ -146,6 +150,17 @@ label_get_minimal_size (void *vself, unsigned *width, unsigned *height)
+ grub_font_get_descent (self->font)); + 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 static grub_err_t
label_set_property (void *vself, const char *name, const char *value) 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) if (grub_strcmp (name, "text") == 0)
{ {
grub_free (self->text); grub_free (self->text);
grub_free (self->template);
if (! value) 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, "font") == 0)
{ {
@ -183,11 +206,16 @@ label_set_property (void *vself, const char *name, const char *value)
} }
else if (grub_strcmp (name, "id") == 0) else if (grub_strcmp (name, "id") == 0)
{ {
grub_gfxmenu_timeout_unregister ((grub_gui_component_t) self);
grub_free (self->id); grub_free (self->id);
if (value) if (value)
self->id = grub_strdup (value); self->id = grub_strdup (value);
else else
self->id = 0; 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; return GRUB_ERR_NONE;
} }

View file

@ -60,6 +60,7 @@ static void
progress_bar_destroy (void *vself) progress_bar_destroy (void *vself)
{ {
grub_gui_progress_bar_t self = vself; grub_gui_progress_bar_t self = vself;
grub_gfxmenu_timeout_unregister ((grub_gui_component_t) self);
grub_free (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) else if (grub_strcmp (name, "id") == 0)
{ {
grub_gfxmenu_timeout_unregister ((grub_gui_component_t) self);
grub_free (self->id); grub_free (self->id);
if (value) if (value)
self->id = grub_strdup (value); self->id = grub_strdup (value);
else else
self->id = 0; 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; return grub_errno;
} }
@ -368,6 +374,7 @@ grub_gui_progress_bar_new (void)
self = grub_zalloc (sizeof (*self)); self = grub_zalloc (sizeof (*self));
if (! self) if (! self)
return 0; return 0;
self->progress.ops = &progress_bar_pb_ops; self->progress.ops = &progress_bar_pb_ops;
self->progress.component.ops = &progress_bar_ops; self->progress.component.ops = &progress_bar_ops;
self->visible = 1; self->visible = 1;

View file

@ -37,10 +37,6 @@
#include <grub/gui_string_util.h> #include <grub/gui_string_util.h>
#include <grub/icon_manager.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 static void
init_terminal (grub_gfxmenu_view_t view); init_terminal (grub_gfxmenu_view_t view);
static grub_video_rect_t term_rect; static grub_video_rect_t term_rect;
@ -166,16 +162,28 @@ struct progress_value_data
int value; int value;
}; };
static void struct grub_gfxmenu_timeout_notify *grub_gfxmenu_timeout_notifications;
update_timeout_visit (grub_gui_component_t component,
void *userdata)
{
struct progress_value_data *pv;
pv = (struct progress_value_data *) userdata;
((struct grub_gui_progress *) component)->ops static void
->set_state ((struct grub_gui_progress *) component, update_timeouts (int visible, int start, int value, int end)
pv->visible, pv->start, pv->value, pv->end); {
struct grub_gfxmenu_timeout_notify *cur;
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 void
@ -183,67 +191,26 @@ grub_gfxmenu_print_timeout (int timeout, void *data)
{ {
struct grub_gfxmenu_view *view = 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) if (view->first_timeout == -1)
view->first_timeout = timeout; view->first_timeout = timeout;
pv.visible = 1; update_timeouts (1, -(view->first_timeout + 1), -timeout, 0);
pv.start = -(view->first_timeout + 1); redraw_timeouts (view);
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);
grub_video_swap_buffers (); grub_video_swap_buffers ();
if (view->double_repaint) if (view->double_repaint)
grub_gui_find_by_id ((grub_gui_component_t) view->canvas, redraw_timeouts (view);
TIMEOUT_COMPONENT_ID, redraw_timeout_visit, &pv);
} }
void void
grub_gfxmenu_clear_timeout (void *data) grub_gfxmenu_clear_timeout (void *data)
{ {
struct progress_value_data pv;
struct grub_gfxmenu_view *view = data; struct grub_gfxmenu_view *view = data;
auto void redraw_timeout_visit (grub_gui_component_t component, update_timeouts (0, 1, 0, 0);
void *userdata __attribute__ ((unused))); redraw_timeouts (view);
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);
grub_video_swap_buffers (); grub_video_swap_buffers ();
if (view->double_repaint) if (view->double_repaint)
grub_gui_find_by_id ((grub_gui_component_t) view->canvas, redraw_timeouts (view);
TIMEOUT_COMPONENT_ID, redraw_timeout_visit, &pv);
} }
static void static void

View file

@ -22,10 +22,15 @@
#include <grub/video.h> #include <grub/video.h>
#include <grub/bitmap.h> #include <grub/bitmap.h>
#include <grub/gfxmenu_view.h> #include <grub/gfxmenu_view.h>
#include <grub/mm.h>
#ifndef GRUB_GUI_H #ifndef GRUB_GUI_H
#define GRUB_GUI_H 1 #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 /* A representation of a color. Unlike grub_video_color_t, this
representation is independent of any video mode specifics. */ representation is independent of any video mode specifics. */
typedef struct grub_gui_color 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); 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; typedef signed grub_fixed_signed_t;
#define GRUB_FIXED_1 0x10000 #define GRUB_FIXED_1 0x10000