struct component_node *cur;
unsigned w = 0, mwfrac = 0, h = 0, x = 0;
- grub_fixed_unsigned_t wfrac = 0;
+ grub_fixed_signed_t wfrac = 0;
int bogus_frac = 0;
for (cur = self->chead.next; cur != &self->ctail; cur = cur->next)
if (c->ops->get_minimal_size)
c->ops->get_minimal_size (c, &mw, &mh);
- if (!c->ishfrac && c->h > h)
+ if (c->h > (signed) h)
h = c->h;
if (mh > h)
h = mh;
- if (!c->iswfrac)
- w += mw > c->w ? mw : c->w;
- if (c->iswfrac)
- {
- wfrac += c->wfrac;
- mwfrac += mw;
- }
+ wfrac += c->wfrac;
+ w += c->w;
+ if (mw - c->w > 0)
+ mwfrac += mw - c->w;
}
if (wfrac > GRUB_FIXED_1 || (w > 0 && wfrac == GRUB_FIXED_1))
bogus_frac = 1;
if (min_width)
{
if (wfrac < GRUB_FIXED_1)
- *min_width = grub_fixed_ufu_divide (w, GRUB_FIXED_1 - wfrac);
+ *min_width = grub_fixed_sfs_divide (w, GRUB_FIXED_1 - wfrac);
else
*min_width = w;
if (*min_width < w + mwfrac)
r.x = x;
r.y = 0;
- r.width = 32;
r.height = h;
if (c->ops->get_minimal_size)
c->ops->get_minimal_size (c, &mw, &mh);
- if (!c->iswfrac)
- r.width = c->w;
- if (c->iswfrac && !bogus_frac)
- r.width = grub_fixed_ufu_multiply (self->bounds.width, c->wfrac);
+ r.width = c->w;
+ if (!bogus_frac)
+ r.width += grub_fixed_sfs_multiply (self->bounds.width, c->wfrac);
if (r.width < mw)
r.width = mw;
struct component_node *cur;
unsigned h = 0, mhfrac = 0, w = 0, y = 0;
- grub_fixed_unsigned_t hfrac = 0;
+ grub_fixed_signed_t hfrac = 0;
int bogus_frac = 0;
for (cur = self->chead.next; cur != &self->ctail; cur = cur->next)
if (c->ops->get_minimal_size)
c->ops->get_minimal_size (c, &mw, &mh);
- if (!c->iswfrac && c->w > w)
+ if (c->w > (signed) w)
w = c->w;
if (mw > w)
w = mw;
- if (!c->ishfrac)
- h += mh > c->h ? mh : c->h;
- if (c->ishfrac)
- {
- hfrac += c->hfrac;
- mhfrac += mh;
- }
+ hfrac += c->hfrac;
+ h += c->h;
+ if (mh - c->h > 0)
+ mhfrac += mh - c->h;
}
if (hfrac > GRUB_FIXED_1 || (h > 0 && hfrac == GRUB_FIXED_1))
bogus_frac = 1;
if (min_height)
{
if (hfrac < GRUB_FIXED_1)
- *min_height = grub_fixed_ufu_divide (h, GRUB_FIXED_1 - hfrac);
+ *min_height = grub_fixed_sfs_divide (h, GRUB_FIXED_1 - hfrac);
else
*min_height = h;
if (*min_height < h + mhfrac)
r.x = 0;
r.y = y;
r.width = w;
- r.height = 32;
if (c->ops->get_minimal_size)
c->ops->get_minimal_size (c, &mw, &mh);
- if (!c->ishfrac)
- r.height = c->h;
- if (c->ishfrac)
- r.height = grub_fixed_ufu_multiply (self->bounds.height, c->hfrac);
+ r.height = c->h;
+ if (!bogus_frac)
+ r.height += grub_fixed_sfs_multiply (self->bounds.height, c->hfrac);
if (r.height < mh)
r.height = mh;
{
grub_video_rect_t r;
grub_gui_component_t comp;
+ signed x, y, w, h;
comp = cur->component;
- r.x = 0;
- r.y = 0;
- r.width = 32;
- r.height = 32;
-
- if (!comp->iswfrac && comp->w)
- r.width = comp->w;
-
- if (!comp->ishfrac && comp->h)
- r.height = comp->h;
-
- if (!comp->isxfrac && comp->x)
- r.x = comp->x;
-
- if (!comp->isyfrac && comp->y)
- r.y = comp->y;
-
- if (comp->ishfrac && comp->hfrac)
- r.height = grub_fixed_ufu_multiply (self->bounds.height, comp->hfrac);
-
- if (comp->iswfrac && comp->wfrac)
- r.width = grub_fixed_ufu_multiply (self->bounds.width, comp->wfrac);
-
- if (comp->isxfrac && comp->xfrac)
- r.x = grub_fixed_ufu_multiply (self->bounds.width, comp->xfrac);
-
- if (comp->isyfrac && comp->yfrac)
- r.y = grub_fixed_ufu_multiply (self->bounds.height, comp->yfrac);
+ w = grub_fixed_sfs_multiply (self->bounds.width, comp->wfrac) + comp->w;
+ h = grub_fixed_sfs_multiply (self->bounds.height, comp->hfrac) + comp->h;
+ x = grub_fixed_sfs_multiply (self->bounds.width, comp->xfrac) + comp->x;
+ y = grub_fixed_sfs_multiply (self->bounds.height, comp->yfrac) + comp->y;
if (comp->ops->get_minimal_size)
{
unsigned mw;
unsigned mh;
comp->ops->get_minimal_size (comp, &mw, &mh);
- if (r.width < mw)
- r.width = mw;
- if (r.height < mh)
- r.height = mh;
+ if (w < (signed) mw)
+ w = mw;
+ if (h < (signed) mh)
+ h = mh;
}
+ /* Sanity checks. */
+ if (w <= 0)
+ w = 32;
+ if (h <= 0)
+ h = 32;
+
+ if (x >= (signed) self->bounds.width)
+ x = self->bounds.width - 32;
+ if (y >= (signed) self->bounds.height)
+ y = self->bounds.height - 32;
+
+ if (x < 0)
+ x = 0;
+ if (y < 0)
+ y = 0;
+
+ if (x + w >= (signed) self->bounds.width)
+ w = self->bounds.width - x;
+ if (y + h >= (signed) self->bounds.height)
+ h = self->bounds.height - y;
+
+ r.x = x;
+ r.y = y;
+ r.width = w;
+ r.height = h;
comp->ops->set_bounds (comp, &r);
/* Paint the child. */
return grub_new_substring (p->buf, start, end);
}
+static grub_err_t
+parse_proportional_spec (char *value, signed *abs, grub_fixed_signed_t *prop)
+{
+ signed num;
+ char *ptr;
+ int sig = 0;
+ *abs = 0;
+ *prop = 0;
+ ptr = value;
+ while (*ptr)
+ {
+ sig = 0;
+
+ while (*ptr == '-' || *ptr == '+')
+ {
+ if (*ptr == '-')
+ sig = !sig;
+ ptr++;
+ }
+
+ num = grub_strtoul (ptr, &ptr, 0);
+ if (grub_errno)
+ return grub_errno;
+ if (sig)
+ num = -num;
+ if (*ptr == '%')
+ *prop += grub_fixed_fsf_divide (grub_signed_to_fixed (num), 100);
+ else
+ *abs += num;
+ }
+ return GRUB_ERR_NONE;
+}
+
+
/* Read a GUI object specification from the theme file.
Any components created will be added to the GUI container PARENT. */
static grub_err_t
/* Handle the property value. */
if (grub_strcmp (property, "left") == 0)
- {
- unsigned num;
- char *ptr;
- num = grub_strtoul (value, &ptr, 0);
- if (*ptr == '%')
- {
- component->isxfrac = 1;
- component->xfrac
- = grub_fixed_fuf_divide (grub_unsigned_to_fixed (num), 100);
- }
- else
- {
- component->isxfrac = 0;
- component->x = num;
- }
- }
+ parse_proportional_spec (value, &component->x, &component->xfrac);
else if (grub_strcmp (property, "top") == 0)
- {
- unsigned num;
- char *ptr;
- num = grub_strtoul (value, &ptr, 0);
- if (*ptr == '%')
- {
- component->isyfrac = 1;
- component->yfrac
- = grub_fixed_fuf_divide (grub_unsigned_to_fixed (num), 100);
- }
- else
- {
- component->isyfrac = 0;
- component->y = num;
- }
- }
+ parse_proportional_spec (value, &component->y, &component->yfrac);
else if (grub_strcmp (property, "width") == 0)
- {
- unsigned num;
- char *ptr;
- num = grub_strtoul (value, &ptr, 0);
- if (*ptr == '%')
- {
- component->iswfrac = 1;
- component->wfrac
- = grub_fixed_fuf_divide (grub_unsigned_to_fixed (num), 100);
- }
- else
- {
- component->iswfrac = 0;
- component->w = num;
- }
- }
+ parse_proportional_spec (value, &component->w, &component->wfrac);
else if (grub_strcmp (property, "height") == 0)
- {
- unsigned num;
- char *ptr;
- num = grub_strtoul (value, &ptr, 0);
- if (*ptr == '%')
- {
- component->ishfrac = 1;
- component->hfrac
- = grub_fixed_fuf_divide (grub_unsigned_to_fixed (num), 100);
- }
- else
- {
- component->ishfrac = 0;
- component->h = num;
- }
- }
+ parse_proportional_spec (value, &component->h, &component->hfrac);
else
- {
- /* General property handling. */
- component->ops->set_property (component, property, value);
- }
+ /* General property handling. */
+ component->ops->set_property (component, property, value);
grub_free (value);
grub_free (property);
grub_gfxmenu_model_t menu);
};
-typedef grub_uint32_t grub_fixed_unsigned_t;
+typedef signed grub_fixed_signed_t;
#define GRUB_FIXED_1 0x10000
-static inline unsigned
-grub_fixed_ufu_divide (grub_uint32_t a, grub_fixed_unsigned_t b)
+static inline signed
+grub_fixed_sfs_divide (signed a, grub_fixed_signed_t b)
{
- return (a << 16) / b;
+ return (a * GRUB_FIXED_1) / b;
}
-static inline grub_fixed_unsigned_t
-grub_fixed_fuf_divide (grub_fixed_unsigned_t a, grub_uint32_t b)
+static inline grub_fixed_signed_t
+grub_fixed_fsf_divide (grub_fixed_signed_t a, signed b)
{
return a / b;
}
-static inline unsigned
-grub_fixed_ufu_multiply (grub_uint32_t a, grub_fixed_unsigned_t b)
+static inline signed
+grub_fixed_sfs_multiply (signed a, grub_fixed_signed_t b)
{
- return (a * b) >> 16;
+ return (a * b) / GRUB_FIXED_1;
}
-static inline unsigned
-grub_fixed_to_unsigned (grub_fixed_unsigned_t in)
+static inline signed
+grub_fixed_to_signed (grub_fixed_signed_t in)
{
- return in >> 16;
+ return in / GRUB_FIXED_1;
}
-static inline grub_fixed_unsigned_t
-grub_unsigned_to_fixed (unsigned in)
+static inline grub_fixed_signed_t
+grub_signed_to_fixed (signed in)
{
- return in << 16;
+ return in * GRUB_FIXED_1;
}
struct grub_gui_component
{
struct grub_gui_component_ops *ops;
- int isxfrac:1;
- int isyfrac:1;
- int iswfrac:1;
- int ishfrac:1;
- union {
- unsigned x;
- grub_fixed_unsigned_t xfrac;
- };
- union {
- unsigned y;
- grub_fixed_unsigned_t yfrac;
- };
- union {
- unsigned w;
- grub_fixed_unsigned_t wfrac;
- };
- union {
- unsigned h;
- grub_fixed_unsigned_t hfrac;
- };
+ signed x;
+ grub_fixed_signed_t xfrac;
+ signed y;
+ grub_fixed_signed_t yfrac;
+ signed w;
+ grub_fixed_signed_t wfrac;
+ signed h;
+ grub_fixed_signed_t hfrac;
};
struct grub_gui_container