Initial commit from Ventoy@7cbdc5c
This commit is contained in:
@@ -0,0 +1,165 @@
|
||||
/* gfxmenu.c - Graphical menu interface controller. */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2008 Free Software Foundation, Inc.
|
||||
*
|
||||
* GRUB is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GRUB is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <grub/types.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/mm.h>
|
||||
#include <grub/err.h>
|
||||
#include <grub/dl.h>
|
||||
#include <grub/command.h>
|
||||
#include <grub/video.h>
|
||||
#include <grub/gfxterm.h>
|
||||
#include <grub/bitmap.h>
|
||||
#include <grub/bitmap_scale.h>
|
||||
#include <grub/term.h>
|
||||
#include <grub/env.h>
|
||||
#include <grub/normal.h>
|
||||
#include <grub/gfxwidgets.h>
|
||||
#include <grub/menu.h>
|
||||
#include <grub/menu_viewer.h>
|
||||
#include <grub/gfxmenu_model.h>
|
||||
#include <grub/gfxmenu_view.h>
|
||||
#include <grub/time.h>
|
||||
#include <grub/env.h>
|
||||
#include <grub/i18n.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
extern int g_ventoy_menu_refresh;
|
||||
|
||||
static grub_gfxmenu_view_t cached_view;
|
||||
|
||||
static void
|
||||
grub_gfxmenu_viewer_fini (void *data __attribute__ ((unused)))
|
||||
{
|
||||
}
|
||||
|
||||
/* FIXME: Previously 't' changed to text menu is it necessary? */
|
||||
static grub_err_t
|
||||
grub_gfxmenu_try (int entry, grub_menu_t menu, int nested)
|
||||
{
|
||||
int force_refresh = 0;
|
||||
grub_gfxmenu_view_t view = NULL;
|
||||
const char *theme_path;
|
||||
char *full_theme_path = 0;
|
||||
struct grub_menu_viewer *instance;
|
||||
grub_err_t err;
|
||||
struct grub_video_mode_info mode_info;
|
||||
|
||||
theme_path = grub_env_get ("theme");
|
||||
if (! theme_path)
|
||||
return grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("variable `%s' isn't set"),
|
||||
"theme");
|
||||
|
||||
err = grub_video_get_info (&mode_info);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
instance = grub_zalloc (sizeof (*instance));
|
||||
if (!instance)
|
||||
return grub_errno;
|
||||
|
||||
if (theme_path[0] != '/' && theme_path[0] != '(')
|
||||
{
|
||||
const char *prefix;
|
||||
prefix = grub_env_get ("prefix");
|
||||
full_theme_path = grub_xasprintf ("%s/themes/%s",
|
||||
prefix,
|
||||
theme_path);
|
||||
}
|
||||
|
||||
if (g_ventoy_menu_refresh)
|
||||
{
|
||||
g_ventoy_menu_refresh = 0;
|
||||
force_refresh = 1;
|
||||
}
|
||||
|
||||
if (force_refresh ||
|
||||
!cached_view || grub_strcmp (cached_view->theme_path,
|
||||
full_theme_path ? : theme_path) != 0
|
||||
|| cached_view->screen.width != mode_info.width
|
||||
|| cached_view->screen.height != mode_info.height)
|
||||
{
|
||||
grub_gfxmenu_view_destroy (cached_view);
|
||||
/* Create the view. */
|
||||
cached_view = grub_gfxmenu_view_new (full_theme_path ? : theme_path,
|
||||
mode_info.width,
|
||||
mode_info.height);
|
||||
}
|
||||
grub_free (full_theme_path);
|
||||
|
||||
if (! cached_view)
|
||||
{
|
||||
grub_free (instance);
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
view = cached_view;
|
||||
|
||||
view->double_repaint = (mode_info.mode_type
|
||||
& GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED)
|
||||
&& !(mode_info.mode_type & GRUB_VIDEO_MODE_TYPE_UPDATING_SWAP);
|
||||
view->selected = entry;
|
||||
view->menu = menu;
|
||||
view->nested = nested;
|
||||
view->first_timeout = -1;
|
||||
if (menu->size)
|
||||
view->menu_title_offset = grub_zalloc (sizeof (*view->menu_title_offset) * menu->size);
|
||||
|
||||
grub_video_set_viewport (0, 0, mode_info.width, mode_info.height);
|
||||
if (view->double_repaint)
|
||||
{
|
||||
grub_video_swap_buffers ();
|
||||
grub_video_set_viewport (0, 0, mode_info.width, mode_info.height);
|
||||
}
|
||||
|
||||
grub_gfxmenu_view_draw (view);
|
||||
|
||||
instance->data = view;
|
||||
instance->set_chosen_entry = grub_gfxmenu_set_chosen_entry;
|
||||
instance->fini = grub_gfxmenu_viewer_fini;
|
||||
instance->print_timeout = grub_gfxmenu_print_timeout;
|
||||
instance->clear_timeout = grub_gfxmenu_clear_timeout;
|
||||
if (view->menu_title_offset)
|
||||
instance->scroll_chosen_entry = grub_gfxmenu_scroll_chosen_entry;
|
||||
|
||||
grub_menu_register_viewer (instance);
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
GRUB_MOD_INIT (gfxmenu)
|
||||
{
|
||||
struct grub_term_output *term;
|
||||
|
||||
FOR_ACTIVE_TERM_OUTPUTS(term)
|
||||
if (grub_gfxmenu_try_hook && term->fullscreen)
|
||||
{
|
||||
term->fullscreen ();
|
||||
break;
|
||||
}
|
||||
|
||||
grub_gfxmenu_try_hook = grub_gfxmenu_try;
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI (gfxmenu)
|
||||
{
|
||||
grub_gfxmenu_view_destroy (cached_view);
|
||||
grub_gfxmenu_try_hook = NULL;
|
||||
}
|
||||
@@ -0,0 +1,324 @@
|
||||
/* gui_label.c - GUI component to display a line of text. */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2008,2009 Free Software Foundation, Inc.
|
||||
*
|
||||
* GRUB is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GRUB is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <grub/mm.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/gui.h>
|
||||
#include <grub/font.h>
|
||||
#include <grub/gui_string_util.h>
|
||||
#include <grub/i18n.h>
|
||||
#include <grub/color.h>
|
||||
#include <grub/env.h>
|
||||
|
||||
extern int g_ventoy_memdisk_mode;
|
||||
extern int g_ventoy_iso_raw;
|
||||
extern int g_ventoy_grub2_mode;
|
||||
extern int g_ventoy_wimboot_mode;
|
||||
extern int g_ventoy_iso_uefi_drv;
|
||||
extern char g_ventoy_hotkey_tip[256];
|
||||
|
||||
static const char *align_options[] =
|
||||
{
|
||||
"left",
|
||||
"center",
|
||||
"right",
|
||||
0
|
||||
};
|
||||
|
||||
enum align_mode {
|
||||
align_left,
|
||||
align_center,
|
||||
align_right
|
||||
};
|
||||
|
||||
struct grub_gui_label
|
||||
{
|
||||
struct grub_gui_component comp;
|
||||
|
||||
grub_gui_container_t parent;
|
||||
grub_video_rect_t bounds;
|
||||
char *id;
|
||||
int visible;
|
||||
char *text;
|
||||
char *template;
|
||||
grub_font_t font;
|
||||
grub_video_rgba_color_t color;
|
||||
int value;
|
||||
int vtoytip;
|
||||
enum align_mode align;
|
||||
};
|
||||
|
||||
typedef struct grub_gui_label *grub_gui_label_t;
|
||||
|
||||
extern const char * g_ventoy_tip_msg1;
|
||||
extern const char * g_ventoy_tip_msg2;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
static const char *
|
||||
label_get_id (void *vself)
|
||||
{
|
||||
grub_gui_label_t self = vself;
|
||||
return self->id;
|
||||
}
|
||||
|
||||
static int
|
||||
label_is_instance (void *vself __attribute__((unused)), const char *type)
|
||||
{
|
||||
return grub_strcmp (type, "component") == 0;
|
||||
}
|
||||
|
||||
static void
|
||||
label_paint (void *vself, const grub_video_rect_t *region)
|
||||
{
|
||||
const char *text;
|
||||
grub_gui_label_t self = vself;
|
||||
|
||||
if (! self->visible)
|
||||
return;
|
||||
|
||||
if (!grub_video_have_common_points (region, &self->bounds))
|
||||
return;
|
||||
|
||||
if (self->vtoytip == 1) {
|
||||
text = g_ventoy_tip_msg1 ? g_ventoy_tip_msg1 : "";
|
||||
} else if (self->vtoytip == 2) {
|
||||
text = g_ventoy_tip_msg2 ? g_ventoy_tip_msg2 : "";
|
||||
} else {
|
||||
text = self->text;
|
||||
}
|
||||
|
||||
/* Calculate the starting x coordinate. */
|
||||
int left_x;
|
||||
if (self->align == align_left)
|
||||
left_x = 0;
|
||||
else if (self->align == align_center)
|
||||
left_x = (self->bounds.width
|
||||
- grub_font_get_string_width (self->font, text)) / 2;
|
||||
else if (self->align == align_right)
|
||||
left_x = (self->bounds.width
|
||||
- grub_font_get_string_width (self->font, text));
|
||||
else
|
||||
return; /* Invalid alignment. */
|
||||
|
||||
if (left_x < 0 || left_x > (int) self->bounds.width)
|
||||
left_x = 0;
|
||||
|
||||
grub_video_rect_t vpsave;
|
||||
grub_gui_set_viewport (&self->bounds, &vpsave);
|
||||
grub_font_draw_string (text,
|
||||
self->font,
|
||||
grub_video_map_rgba_color (self->color),
|
||||
left_x,
|
||||
grub_font_get_ascent (self->font));
|
||||
grub_gui_restore_viewport (&vpsave);
|
||||
}
|
||||
|
||||
static void
|
||||
label_set_parent (void *vself, grub_gui_container_t parent)
|
||||
{
|
||||
grub_gui_label_t self = vself;
|
||||
self->parent = parent;
|
||||
}
|
||||
|
||||
static grub_gui_container_t
|
||||
label_get_parent (void *vself)
|
||||
{
|
||||
grub_gui_label_t self = vself;
|
||||
return self->parent;
|
||||
}
|
||||
|
||||
static void
|
||||
label_set_bounds (void *vself, const grub_video_rect_t *bounds)
|
||||
{
|
||||
grub_gui_label_t self = vself;
|
||||
self->bounds = *bounds;
|
||||
}
|
||||
|
||||
static void
|
||||
label_get_bounds (void *vself, grub_video_rect_t *bounds)
|
||||
{
|
||||
grub_gui_label_t self = vself;
|
||||
*bounds = self->bounds;
|
||||
}
|
||||
|
||||
static void
|
||||
label_get_minimal_size (void *vself, unsigned *width, unsigned *height)
|
||||
{
|
||||
grub_gui_label_t self = vself;
|
||||
*width = grub_font_get_string_width (self->font, self->text);
|
||||
*height = (grub_font_get_ascent (self->font)
|
||||
+ grub_font_get_descent (self->font));
|
||||
}
|
||||
|
||||
#pragma GCC diagnostic ignored "-Wformat-nonliteral"
|
||||
|
||||
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)
|
||||
{
|
||||
grub_gui_label_t self = vself;
|
||||
if (grub_strcmp (name, "text") == 0)
|
||||
{
|
||||
grub_free (self->text);
|
||||
grub_free (self->template);
|
||||
if (! value)
|
||||
{
|
||||
self->template = NULL;
|
||||
self->text = grub_strdup ("");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (grub_strcmp (value, "@KEYMAP_LONG@") == 0)
|
||||
value = _("Press enter to boot the selected OS, "
|
||||
"`e' to edit the commands before booting "
|
||||
"or `c' for a command-line. ESC to return previous menu.");
|
||||
else if (grub_strcmp (value, "@KEYMAP_MIDDLE@") == 0)
|
||||
value = _("Press enter to boot the selected OS, "
|
||||
"`e' to edit the commands before booting "
|
||||
"or `c' for a command-line.");
|
||||
else if (grub_strcmp (value, "@KEYMAP_SHORT@") == 0)
|
||||
value = _("enter: boot, `e': options, `c': cmd-line");
|
||||
/* FIXME: Add more templates here if needed. */
|
||||
|
||||
else if (grub_strcmp (value, "@VTOY_MEM_DISK@") == 0) {
|
||||
value = g_ventoy_memdisk_mode ? grub_env_get("VTOY_MEM_DISK_STR") : " ";
|
||||
}
|
||||
else if (grub_strcmp (value, "@VTOY_ISO_RAW@") == 0) {
|
||||
value = g_ventoy_iso_raw ? grub_env_get("VTOY_ISO_RAW_STR") : " ";
|
||||
}
|
||||
else if (grub_strcmp (value, "@VTOY_GRUB2_MODE@") == 0) {
|
||||
value = g_ventoy_grub2_mode ? grub_env_get("VTOY_GRUB2_MODE_STR") : " ";
|
||||
}
|
||||
else if (grub_strcmp (value, "@VTOY_WIMBOOT_MODE@") == 0) {
|
||||
value = g_ventoy_wimboot_mode ? grub_env_get("VTOY_WIMBOOT_MODE_STR") : " ";
|
||||
}
|
||||
else if (grub_strcmp (value, "@VTOY_ISO_UEFI_DRV@") == 0) {
|
||||
value = g_ventoy_iso_uefi_drv ? grub_env_get("VTOY_ISO_UEFI_DRV_STR") : " ";
|
||||
}
|
||||
else if (grub_strcmp (value, "@VTOY_HOTKEY_TIP@") == 0) {
|
||||
value = g_ventoy_hotkey_tip;
|
||||
} else if (value[0] == '@' && value[1] == '@' && value[2]) {
|
||||
value = grub_env_get(value + 2);
|
||||
if (!value)
|
||||
value = " ";
|
||||
}
|
||||
|
||||
self->template = grub_strdup (value);
|
||||
self->text = grub_xasprintf (value, self->value);
|
||||
}
|
||||
}
|
||||
else if (grub_strcmp (name, "font") == 0)
|
||||
{
|
||||
self->font = grub_font_get (value);
|
||||
}
|
||||
else if (grub_strcmp (name, "color") == 0)
|
||||
{
|
||||
grub_video_parse_color (value, &self->color);
|
||||
}
|
||||
else if (grub_strcmp (name, "align") == 0)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; align_options[i]; i++)
|
||||
{
|
||||
if (grub_strcmp (align_options[i], value) == 0)
|
||||
{
|
||||
self->align = i; /* Set the alignment mode. */
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (grub_strcmp (name, "visible") == 0)
|
||||
{
|
||||
self->visible = grub_strcmp (value, "false") != 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);
|
||||
if (grub_strcmp(value, "VTOY_MENU_TIP_1") == 0) {
|
||||
self->vtoytip = 1;
|
||||
} else if (grub_strcmp(value, "VTOY_MENU_TIP_2") == 0) {
|
||||
self->vtoytip = 2;
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
#pragma GCC diagnostic error "-Wformat-nonliteral"
|
||||
|
||||
static struct grub_gui_component_ops label_ops =
|
||||
{
|
||||
.destroy = label_destroy,
|
||||
.get_id = label_get_id,
|
||||
.is_instance = label_is_instance,
|
||||
.paint = label_paint,
|
||||
.set_parent = label_set_parent,
|
||||
.get_parent = label_get_parent,
|
||||
.set_bounds = label_set_bounds,
|
||||
.get_bounds = label_get_bounds,
|
||||
.get_minimal_size = label_get_minimal_size,
|
||||
.set_property = label_set_property
|
||||
};
|
||||
|
||||
grub_gui_component_t
|
||||
grub_gui_label_new (void)
|
||||
{
|
||||
grub_gui_label_t label;
|
||||
label = grub_zalloc (sizeof (*label));
|
||||
if (! label)
|
||||
return 0;
|
||||
label->comp.ops = &label_ops;
|
||||
label->visible = 1;
|
||||
label->text = grub_strdup ("");
|
||||
label->font = grub_font_get ("Unknown Regular 16");
|
||||
label->color.red = 0;
|
||||
label->color.green = 0;
|
||||
label->color.blue = 0;
|
||||
label->color.alpha = 255;
|
||||
label->align = align_left;
|
||||
return (grub_gui_component_t) label;
|
||||
}
|
||||
@@ -0,0 +1,961 @@
|
||||
/* gui_list.c - GUI component to display a selectable list of items. */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2008,2009 Free Software Foundation, Inc.
|
||||
*
|
||||
* GRUB is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GRUB is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <grub/mm.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/gui.h>
|
||||
#include <grub/gui_string_util.h>
|
||||
#include <grub/gfxmenu_view.h>
|
||||
#include <grub/gfxwidgets.h>
|
||||
#include <grub/color.h>
|
||||
#include <grub/charset.h>
|
||||
|
||||
enum scrollbar_slice_mode {
|
||||
SCROLLBAR_SLICE_WEST,
|
||||
SCROLLBAR_SLICE_CENTER,
|
||||
SCROLLBAR_SLICE_EAST
|
||||
};
|
||||
|
||||
struct grub_gui_list_impl
|
||||
{
|
||||
struct grub_gui_list list;
|
||||
|
||||
grub_gui_container_t parent;
|
||||
grub_video_rect_t bounds;
|
||||
char *id;
|
||||
int visible;
|
||||
|
||||
int icon_width;
|
||||
int icon_height;
|
||||
int item_height;
|
||||
int item_padding;
|
||||
int item_icon_space;
|
||||
int item_spacing;
|
||||
grub_font_t item_font;
|
||||
int selected_item_font_inherit;
|
||||
grub_font_t selected_item_font;
|
||||
grub_video_rgba_color_t item_color;
|
||||
int selected_item_color_inherit;
|
||||
grub_video_rgba_color_t selected_item_color;
|
||||
|
||||
int draw_scrollbar;
|
||||
int need_to_recreate_scrollbar;
|
||||
char *scrollbar_frame_pattern;
|
||||
char *scrollbar_thumb_pattern;
|
||||
grub_gfxmenu_box_t scrollbar_frame;
|
||||
grub_gfxmenu_box_t scrollbar_thumb;
|
||||
int scrollbar_thumb_overlay;
|
||||
int scrollbar_width;
|
||||
enum scrollbar_slice_mode scrollbar_slice;
|
||||
int scrollbar_left_pad;
|
||||
int scrollbar_right_pad;
|
||||
int scrollbar_top_pad;
|
||||
int scrollbar_bottom_pad;
|
||||
|
||||
int first_shown_index;
|
||||
|
||||
int need_to_recreate_boxes;
|
||||
char *theme_dir;
|
||||
char *menu_box_pattern;
|
||||
char *item_box_pattern;
|
||||
int selected_item_box_pattern_inherit;
|
||||
char *selected_item_box_pattern;
|
||||
grub_gfxmenu_box_t menu_box;
|
||||
grub_gfxmenu_box_t selected_item_box;
|
||||
grub_gfxmenu_box_t item_box;
|
||||
|
||||
grub_gfxmenu_icon_manager_t icon_manager;
|
||||
|
||||
grub_gfxmenu_view_t view;
|
||||
};
|
||||
|
||||
typedef struct grub_gui_list_impl *list_impl_t;
|
||||
|
||||
static void
|
||||
list_destroy (void *vself)
|
||||
{
|
||||
list_impl_t self = vself;
|
||||
|
||||
grub_free (self->theme_dir);
|
||||
grub_free (self->menu_box_pattern);
|
||||
grub_free (self->item_box_pattern);
|
||||
grub_free (self->selected_item_box_pattern);
|
||||
if (self->menu_box)
|
||||
self->menu_box->destroy (self->menu_box);
|
||||
if (self->item_box)
|
||||
self->item_box->destroy (self->item_box);
|
||||
if (self->selected_item_box)
|
||||
self->selected_item_box->destroy (self->selected_item_box);
|
||||
if (self->icon_manager)
|
||||
grub_gfxmenu_icon_manager_destroy (self->icon_manager);
|
||||
if (self->scrollbar_thumb)
|
||||
self->scrollbar_thumb->destroy (self->scrollbar_thumb);
|
||||
if (self->scrollbar_frame)
|
||||
self->scrollbar_frame->destroy (self->scrollbar_frame);
|
||||
grub_free (self->scrollbar_thumb_pattern);
|
||||
grub_free (self->scrollbar_frame_pattern);
|
||||
grub_free (self);
|
||||
}
|
||||
|
||||
static int
|
||||
get_num_shown_items (list_impl_t self)
|
||||
{
|
||||
int boxpad = self->item_padding;
|
||||
int item_vspace = self->item_spacing;
|
||||
int item_height = self->item_height;
|
||||
|
||||
grub_gfxmenu_box_t box = self->menu_box;
|
||||
int box_top_pad = box->get_top_pad (box);
|
||||
int box_bottom_pad = box->get_bottom_pad (box);
|
||||
grub_gfxmenu_box_t itembox = self->item_box;
|
||||
grub_gfxmenu_box_t selbox = self->selected_item_box;
|
||||
int item_top_pad = itembox->get_top_pad (itembox);
|
||||
int item_bottom_pad = itembox->get_bottom_pad (itembox);
|
||||
int sel_top_pad = selbox->get_top_pad (selbox);
|
||||
int sel_bottom_pad = selbox->get_bottom_pad (selbox);
|
||||
int max_top_pad = grub_max (item_top_pad, sel_top_pad);
|
||||
int max_bottom_pad = grub_max (item_bottom_pad, sel_bottom_pad);
|
||||
|
||||
if (item_height + item_vspace <= 0)
|
||||
return 1;
|
||||
|
||||
return (self->bounds.height + item_vspace - 2 * boxpad
|
||||
- max_top_pad - max_bottom_pad
|
||||
- box_top_pad - box_bottom_pad) / (item_height + item_vspace);
|
||||
}
|
||||
|
||||
static int
|
||||
check_boxes (list_impl_t self)
|
||||
{
|
||||
if (self->need_to_recreate_boxes)
|
||||
{
|
||||
grub_gui_recreate_box (&self->menu_box,
|
||||
self->menu_box_pattern,
|
||||
self->theme_dir);
|
||||
|
||||
grub_gui_recreate_box (&self->item_box,
|
||||
self->item_box_pattern,
|
||||
self->theme_dir);
|
||||
|
||||
grub_gui_recreate_box (&self->selected_item_box,
|
||||
self->selected_item_box_pattern,
|
||||
self->theme_dir);
|
||||
|
||||
self->need_to_recreate_boxes = 0;
|
||||
}
|
||||
|
||||
return (self->menu_box != 0 && self->selected_item_box != 0
|
||||
&& self->item_box != 0);
|
||||
}
|
||||
|
||||
static int
|
||||
check_scrollbar (list_impl_t self)
|
||||
{
|
||||
if (self->need_to_recreate_scrollbar)
|
||||
{
|
||||
grub_gui_recreate_box (&self->scrollbar_frame,
|
||||
self->scrollbar_frame_pattern,
|
||||
self->theme_dir);
|
||||
|
||||
grub_gui_recreate_box (&self->scrollbar_thumb,
|
||||
self->scrollbar_thumb_pattern,
|
||||
self->theme_dir);
|
||||
|
||||
self->need_to_recreate_scrollbar = 0;
|
||||
}
|
||||
|
||||
if (self->scrollbar_frame == 0 || self->scrollbar_thumb == 0)
|
||||
return 0;
|
||||
|
||||
/* Sanity checks. */
|
||||
grub_gfxmenu_box_t frame = self->scrollbar_frame;
|
||||
grub_gfxmenu_box_t thumb = self->scrollbar_thumb;
|
||||
grub_gfxmenu_box_t menu = self->menu_box;
|
||||
int min_width = frame->get_left_pad (frame)
|
||||
+ frame->get_right_pad (frame);
|
||||
int min_height = frame->get_top_pad (frame)
|
||||
+ frame->get_bottom_pad (frame)
|
||||
+ self->scrollbar_top_pad + self->scrollbar_bottom_pad
|
||||
+ menu->get_top_pad (menu)
|
||||
+ menu->get_bottom_pad (menu);
|
||||
if (!self->scrollbar_thumb_overlay)
|
||||
{
|
||||
min_width += thumb->get_left_pad (thumb)
|
||||
+ thumb->get_right_pad (thumb);
|
||||
min_height += thumb->get_top_pad (thumb)
|
||||
+ thumb->get_bottom_pad (thumb);
|
||||
}
|
||||
if (min_width <= self->scrollbar_width
|
||||
&& min_height <= (int) self->bounds.height)
|
||||
return 1;
|
||||
|
||||
/* Unprintable dimenstions. */
|
||||
self->draw_scrollbar = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char *
|
||||
list_get_id (void *vself)
|
||||
{
|
||||
list_impl_t self = vself;
|
||||
return self->id;
|
||||
}
|
||||
|
||||
static int
|
||||
list_is_instance (void *vself __attribute__((unused)), const char *type)
|
||||
{
|
||||
return (grub_strcmp (type, "component") == 0
|
||||
|| grub_strcmp (type, "list") == 0);
|
||||
}
|
||||
|
||||
static struct grub_video_bitmap *
|
||||
get_item_icon (list_impl_t self, int item_index)
|
||||
{
|
||||
grub_menu_entry_t entry;
|
||||
entry = grub_menu_get_entry (self->view->menu, item_index);
|
||||
if (! entry)
|
||||
return 0;
|
||||
|
||||
return grub_gfxmenu_icon_manager_get_icon (self->icon_manager, entry);
|
||||
}
|
||||
|
||||
static void
|
||||
make_selected_item_visible (list_impl_t self)
|
||||
{
|
||||
int selected_index = self->view->selected;
|
||||
if (selected_index < 0)
|
||||
return; /* No item is selected. */
|
||||
int num_shown_items = get_num_shown_items (self);
|
||||
int last_shown_index = self->first_shown_index + (num_shown_items - 1);
|
||||
if (selected_index < self->first_shown_index)
|
||||
self->first_shown_index = selected_index;
|
||||
else if (selected_index > last_shown_index)
|
||||
self->first_shown_index = selected_index - (num_shown_items - 1);
|
||||
}
|
||||
|
||||
/* Draw a scrollbar on the menu. */
|
||||
static void
|
||||
draw_scrollbar (list_impl_t self,
|
||||
int value, int extent, int min, int max,
|
||||
int scrollbar_width, int scrollbar_height)
|
||||
{
|
||||
unsigned thumby, thumbheight;
|
||||
|
||||
grub_gfxmenu_box_t frame = self->scrollbar_frame;
|
||||
grub_gfxmenu_box_t thumb = self->scrollbar_thumb;
|
||||
int frame_vertical_pad = (frame->get_top_pad (frame)
|
||||
+ frame->get_bottom_pad (frame));
|
||||
int frame_horizontal_pad = (frame->get_left_pad (frame)
|
||||
+ frame->get_right_pad (frame));
|
||||
unsigned thumb_vertical_pad = (thumb->get_top_pad (thumb)
|
||||
+ thumb->get_bottom_pad (thumb));
|
||||
int thumb_horizontal_pad = (thumb->get_left_pad (thumb)
|
||||
+ thumb->get_right_pad (thumb));
|
||||
int tracktop = frame->get_top_pad (frame);
|
||||
unsigned tracklen;
|
||||
if (scrollbar_height <= frame_vertical_pad)
|
||||
tracklen = 0;
|
||||
else
|
||||
tracklen = scrollbar_height - frame_vertical_pad;
|
||||
frame->set_content_size (frame,
|
||||
scrollbar_width - frame_horizontal_pad,
|
||||
tracklen);
|
||||
if (self->scrollbar_thumb_overlay)
|
||||
{
|
||||
tracklen += thumb_vertical_pad;
|
||||
tracktop -= thumb->get_top_pad (thumb);
|
||||
}
|
||||
if (value <= min || max <= min)
|
||||
thumby = 0;
|
||||
else
|
||||
thumby = ((unsigned) tracklen * (value - min))
|
||||
/ ((unsigned) (max - min));
|
||||
if (max <= min)
|
||||
thumbheight = 1;
|
||||
else
|
||||
thumbheight = ((unsigned) (tracklen * extent)
|
||||
/ ((unsigned) (max - min))) + 1;
|
||||
/* Rare occasion: too many entries or too low height. */
|
||||
if (thumbheight < thumb_vertical_pad)
|
||||
{
|
||||
thumbheight = thumb_vertical_pad;
|
||||
if (value <= min || max <= extent
|
||||
|| tracklen <= thumb_vertical_pad)
|
||||
thumby = 0;
|
||||
else
|
||||
thumby = ((unsigned) ((tracklen - thumb_vertical_pad) * (value - min))
|
||||
/ ((unsigned)(max - extent)));
|
||||
}
|
||||
thumby += tracktop;
|
||||
int thumbx = frame->get_left_pad (frame);
|
||||
int thumbwidth = scrollbar_width - frame_horizontal_pad;
|
||||
if (!self->scrollbar_thumb_overlay)
|
||||
thumbwidth -= thumb_horizontal_pad;
|
||||
else
|
||||
thumbx -= thumb->get_left_pad (thumb);
|
||||
thumb->set_content_size (thumb, thumbwidth,
|
||||
thumbheight - thumb_vertical_pad);
|
||||
frame->draw (frame, 0, 0);
|
||||
thumb->draw (thumb, thumbx, thumby);
|
||||
}
|
||||
|
||||
/* Draw the list of items. */
|
||||
static void
|
||||
draw_menu (list_impl_t self, int num_shown_items)
|
||||
{
|
||||
if (! self->menu_box || ! self->selected_item_box || ! self->item_box)
|
||||
return;
|
||||
|
||||
int boxpad = self->item_padding;
|
||||
int icon_text_space = self->item_icon_space;
|
||||
int item_vspace = self->item_spacing;
|
||||
|
||||
int ascent = grub_font_get_ascent (self->item_font);
|
||||
int descent = grub_font_get_descent (self->item_font);
|
||||
int selected_ascent = grub_font_get_ascent (self->selected_item_font);
|
||||
int selected_descent = grub_font_get_descent (self->selected_item_font);
|
||||
int text_box_height = self->item_height;
|
||||
|
||||
make_selected_item_visible (self);
|
||||
|
||||
grub_gfxmenu_box_t itembox = self->item_box;
|
||||
grub_gfxmenu_box_t selbox = self->selected_item_box;
|
||||
int item_leftpad = itembox->get_left_pad (itembox);
|
||||
int item_rightpad = itembox->get_right_pad (itembox);
|
||||
int item_border_width = item_leftpad + item_rightpad;
|
||||
int item_toppad = itembox->get_top_pad (itembox);
|
||||
int sel_leftpad = selbox->get_left_pad (selbox);
|
||||
int sel_rightpad = selbox->get_right_pad (selbox);
|
||||
int sel_border_width = sel_leftpad + sel_rightpad;
|
||||
int sel_toppad = selbox->get_top_pad (selbox);
|
||||
|
||||
int max_leftpad = grub_max (item_leftpad, sel_leftpad);
|
||||
int max_toppad = grub_max (item_toppad, sel_toppad);
|
||||
int item_top = 0;
|
||||
int menu_index;
|
||||
int visible_index;
|
||||
struct grub_video_rect oviewport;
|
||||
|
||||
grub_video_get_viewport (&oviewport.x, &oviewport.y,
|
||||
&oviewport.width, &oviewport.height);
|
||||
grub_video_set_viewport (oviewport.x + boxpad,
|
||||
oviewport.y + boxpad,
|
||||
oviewport.width - 2 * boxpad,
|
||||
oviewport.height - 2 * boxpad);
|
||||
|
||||
int cwidth = oviewport.width - 2 * boxpad;
|
||||
|
||||
itembox->set_content_size (itembox, cwidth - item_border_width,
|
||||
text_box_height);
|
||||
selbox->set_content_size (selbox, cwidth - sel_border_width,
|
||||
text_box_height);
|
||||
|
||||
int text_left_offset = self->icon_width + icon_text_space;
|
||||
int item_text_top_offset = (text_box_height - (ascent + descent)) / 2 + ascent;
|
||||
int sel_text_top_offset = (text_box_height - (selected_ascent
|
||||
+ selected_descent)) / 2
|
||||
+ selected_ascent;
|
||||
|
||||
grub_video_rect_t svpsave, sviewport;
|
||||
sviewport.x = max_leftpad + text_left_offset;
|
||||
int text_viewport_width = cwidth - sviewport.x;
|
||||
sviewport.height = text_box_height;
|
||||
|
||||
grub_video_color_t item_color;
|
||||
grub_video_color_t sel_color;
|
||||
item_color = grub_video_map_rgba_color (self->item_color);
|
||||
sel_color = grub_video_map_rgba_color (self->selected_item_color);
|
||||
|
||||
int item_box_top_offset = max_toppad - item_toppad;
|
||||
int sel_box_top_offset = max_toppad - sel_toppad;
|
||||
int item_viewport_width = text_viewport_width - item_rightpad;
|
||||
int sel_viewport_width = text_viewport_width - sel_rightpad;
|
||||
int tmp_icon_top_offset = (text_box_height - self->icon_height) / 2;
|
||||
int item_icon_top_offset = item_toppad + tmp_icon_top_offset;
|
||||
int sel_icon_top_offset = sel_toppad + tmp_icon_top_offset;
|
||||
|
||||
for (visible_index = 0, menu_index = self->first_shown_index;
|
||||
visible_index < num_shown_items && menu_index < self->view->menu->size;
|
||||
visible_index++, menu_index++)
|
||||
{
|
||||
int is_selected = (menu_index == self->view->selected);
|
||||
struct grub_video_bitmap *icon;
|
||||
grub_font_t font;
|
||||
grub_video_color_t color;
|
||||
int text_top_offset;
|
||||
int top_pad;
|
||||
int icon_top_offset;
|
||||
int viewport_width;
|
||||
|
||||
if (is_selected)
|
||||
{
|
||||
selbox->draw (selbox, 0, item_top + sel_box_top_offset);
|
||||
font = self->selected_item_font;
|
||||
color = sel_color;
|
||||
text_top_offset = sel_text_top_offset;
|
||||
top_pad = sel_toppad;
|
||||
icon_top_offset = sel_icon_top_offset;
|
||||
viewport_width = sel_viewport_width;
|
||||
}
|
||||
else
|
||||
{
|
||||
itembox->draw (itembox, 0, item_top + item_box_top_offset);
|
||||
font = self->item_font;
|
||||
color = item_color;
|
||||
text_top_offset = item_text_top_offset;
|
||||
top_pad = item_toppad;
|
||||
icon_top_offset = item_icon_top_offset;
|
||||
viewport_width = item_viewport_width;
|
||||
}
|
||||
|
||||
icon = get_item_icon (self, menu_index);
|
||||
if (icon != 0)
|
||||
grub_video_blit_bitmap (icon, GRUB_VIDEO_BLIT_BLEND,
|
||||
max_leftpad,
|
||||
item_top + icon_top_offset,
|
||||
0, 0, self->icon_width, self->icon_height);
|
||||
|
||||
const char *item_title =
|
||||
grub_menu_get_entry (self->view->menu, menu_index)->title;
|
||||
|
||||
|
||||
int off = self->view->menu_title_offset[menu_index];
|
||||
const char *scrolled_title =
|
||||
grub_utf8_offset_code (item_title, grub_strlen (item_title), off);
|
||||
if (scrolled_title)
|
||||
item_title = scrolled_title;
|
||||
|
||||
sviewport.y = item_top + top_pad;
|
||||
sviewport.width = viewport_width;
|
||||
grub_gui_set_viewport (&sviewport, &svpsave);
|
||||
grub_font_draw_string (item_title,
|
||||
font,
|
||||
color,
|
||||
0,
|
||||
text_top_offset);
|
||||
grub_gui_restore_viewport (&svpsave);
|
||||
|
||||
item_top += text_box_height + item_vspace;
|
||||
}
|
||||
grub_video_set_viewport (oviewport.x,
|
||||
oviewport.y,
|
||||
oviewport.width,
|
||||
oviewport.height);
|
||||
}
|
||||
|
||||
static void
|
||||
list_paint (void *vself, const grub_video_rect_t *region)
|
||||
{
|
||||
list_impl_t self = vself;
|
||||
grub_video_rect_t vpsave;
|
||||
|
||||
if (! self->visible)
|
||||
return;
|
||||
if (!grub_video_have_common_points (region, &self->bounds))
|
||||
return;
|
||||
|
||||
check_boxes (self);
|
||||
|
||||
if (! self->menu_box || ! self->selected_item_box || ! self->item_box)
|
||||
return;
|
||||
|
||||
grub_gui_set_viewport (&self->bounds, &vpsave);
|
||||
{
|
||||
grub_gfxmenu_box_t box = self->menu_box;
|
||||
int box_left_pad = box->get_left_pad (box);
|
||||
int box_top_pad = box->get_top_pad (box);
|
||||
int box_right_pad = box->get_right_pad (box);
|
||||
int box_bottom_pad = box->get_bottom_pad (box);
|
||||
grub_video_rect_t vpsave2, content_rect;
|
||||
int num_shown_items = get_num_shown_items (self);
|
||||
int drawing_scrollbar = (self->draw_scrollbar
|
||||
&& (num_shown_items < self->view->menu->size)
|
||||
&& check_scrollbar (self));
|
||||
int scrollbar_width = self->scrollbar_width;
|
||||
|
||||
content_rect.x = box_left_pad;
|
||||
content_rect.y = box_top_pad;
|
||||
content_rect.width = self->bounds.width - box_left_pad - box_right_pad;
|
||||
content_rect.height = self->bounds.height - box_top_pad - box_bottom_pad;
|
||||
|
||||
box->set_content_size (box, content_rect.width, content_rect.height);
|
||||
|
||||
box->draw (box, 0, 0);
|
||||
|
||||
switch (self->scrollbar_slice)
|
||||
{
|
||||
case SCROLLBAR_SLICE_WEST:
|
||||
content_rect.x += self->scrollbar_right_pad;
|
||||
content_rect.width -= self->scrollbar_right_pad;
|
||||
break;
|
||||
case SCROLLBAR_SLICE_CENTER:
|
||||
if (drawing_scrollbar)
|
||||
content_rect.width -= scrollbar_width + self->scrollbar_left_pad
|
||||
+ self->scrollbar_right_pad;
|
||||
break;
|
||||
case SCROLLBAR_SLICE_EAST:
|
||||
content_rect.width -= self->scrollbar_left_pad;
|
||||
break;
|
||||
}
|
||||
|
||||
grub_gui_set_viewport (&content_rect, &vpsave2);
|
||||
draw_menu (self, num_shown_items);
|
||||
grub_gui_restore_viewport (&vpsave2);
|
||||
|
||||
if (drawing_scrollbar)
|
||||
{
|
||||
content_rect.y += self->scrollbar_top_pad;
|
||||
content_rect.height -= self->scrollbar_top_pad
|
||||
+ self->scrollbar_bottom_pad;
|
||||
content_rect.width = scrollbar_width;
|
||||
switch (self->scrollbar_slice)
|
||||
{
|
||||
case SCROLLBAR_SLICE_WEST:
|
||||
if (box_left_pad > scrollbar_width)
|
||||
{
|
||||
content_rect.x = box_left_pad - scrollbar_width;
|
||||
content_rect.width = scrollbar_width;
|
||||
}
|
||||
else
|
||||
{
|
||||
content_rect.x = 0;
|
||||
content_rect.width = box_left_pad;
|
||||
}
|
||||
break;
|
||||
case SCROLLBAR_SLICE_CENTER:
|
||||
content_rect.x = self->bounds.width - box_right_pad
|
||||
- scrollbar_width - self->scrollbar_right_pad;
|
||||
content_rect.width = scrollbar_width;
|
||||
break;
|
||||
case SCROLLBAR_SLICE_EAST:
|
||||
content_rect.x = self->bounds.width - box_right_pad;
|
||||
content_rect.width = box_right_pad;
|
||||
break;
|
||||
}
|
||||
|
||||
grub_gui_set_viewport (&content_rect, &vpsave2);
|
||||
draw_scrollbar (self,
|
||||
self->first_shown_index, num_shown_items,
|
||||
0, self->view->menu->size,
|
||||
scrollbar_width,
|
||||
content_rect.height);
|
||||
grub_gui_restore_viewport (&vpsave2);
|
||||
}
|
||||
}
|
||||
|
||||
grub_gui_restore_viewport (&vpsave);
|
||||
}
|
||||
|
||||
static void
|
||||
list_set_parent (void *vself, grub_gui_container_t parent)
|
||||
{
|
||||
list_impl_t self = vself;
|
||||
self->parent = parent;
|
||||
}
|
||||
|
||||
static grub_gui_container_t
|
||||
list_get_parent (void *vself)
|
||||
{
|
||||
list_impl_t self = vself;
|
||||
return self->parent;
|
||||
}
|
||||
|
||||
static void
|
||||
list_set_bounds (void *vself, const grub_video_rect_t *bounds)
|
||||
{
|
||||
list_impl_t self = vself;
|
||||
self->bounds = *bounds;
|
||||
}
|
||||
|
||||
static void
|
||||
list_get_bounds (void *vself, grub_video_rect_t *bounds)
|
||||
{
|
||||
list_impl_t self = vself;
|
||||
*bounds = self->bounds;
|
||||
}
|
||||
|
||||
static void
|
||||
list_get_minimal_size (void *vself, unsigned *width, unsigned *height)
|
||||
{
|
||||
list_impl_t self = vself;
|
||||
|
||||
if (check_boxes (self))
|
||||
{
|
||||
int boxpad = self->item_padding;
|
||||
int item_vspace = self->item_spacing;
|
||||
int item_height = self->item_height;
|
||||
int num_items = 3;
|
||||
|
||||
grub_gfxmenu_box_t box = self->menu_box;
|
||||
int box_left_pad = box->get_left_pad (box);
|
||||
int box_top_pad = box->get_top_pad (box);
|
||||
int box_right_pad = box->get_right_pad (box);
|
||||
int box_bottom_pad = box->get_bottom_pad (box);
|
||||
unsigned width_s;
|
||||
|
||||
grub_gfxmenu_box_t selbox = self->selected_item_box;
|
||||
int sel_top_pad = selbox->get_top_pad (selbox);
|
||||
int sel_bottom_pad = selbox->get_bottom_pad (selbox);
|
||||
int sel_left_pad = selbox->get_left_pad (selbox);
|
||||
int sel_right_pad = selbox->get_right_pad (selbox);
|
||||
|
||||
grub_gfxmenu_box_t itembox = self->item_box;
|
||||
int item_top_pad = itembox->get_top_pad (itembox);
|
||||
int item_bottom_pad = itembox->get_bottom_pad (itembox);
|
||||
int item_left_pad = itembox->get_left_pad (itembox);
|
||||
int item_right_pad = itembox->get_right_pad (itembox);
|
||||
|
||||
int max_left_pad = grub_max (item_left_pad, sel_left_pad);
|
||||
int max_right_pad = grub_max (item_right_pad, sel_right_pad);
|
||||
int max_top_pad = grub_max (item_top_pad, sel_top_pad);
|
||||
int max_bottom_pad = grub_max (item_bottom_pad, sel_bottom_pad);
|
||||
|
||||
*width = grub_font_get_string_width (self->item_font, "Typical OS");
|
||||
width_s = grub_font_get_string_width (self->selected_item_font,
|
||||
"Typical OS");
|
||||
if (*width < width_s)
|
||||
*width = width_s;
|
||||
|
||||
*width += 2 * boxpad + box_left_pad + box_right_pad
|
||||
+ max_left_pad + max_right_pad
|
||||
+ self->item_icon_space + self->icon_width;
|
||||
|
||||
switch (self->scrollbar_slice)
|
||||
{
|
||||
case SCROLLBAR_SLICE_WEST:
|
||||
*width += self->scrollbar_right_pad;
|
||||
break;
|
||||
case SCROLLBAR_SLICE_CENTER:
|
||||
*width += self->scrollbar_width + self->scrollbar_left_pad
|
||||
+ self->scrollbar_right_pad;
|
||||
break;
|
||||
case SCROLLBAR_SLICE_EAST:
|
||||
*width += self->scrollbar_left_pad;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Set the menu box height to fit the items. */
|
||||
*height = (item_height * num_items
|
||||
+ item_vspace * (num_items - 1)
|
||||
+ 2 * boxpad
|
||||
+ box_top_pad + box_bottom_pad
|
||||
+ max_top_pad + max_bottom_pad);
|
||||
}
|
||||
else
|
||||
{
|
||||
*width = 0;
|
||||
*height = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
list_set_property (void *vself, const char *name, const char *value)
|
||||
{
|
||||
list_impl_t self = vself;
|
||||
if (grub_strcmp (name, "item_font") == 0)
|
||||
{
|
||||
self->item_font = grub_font_get (value);
|
||||
if (self->selected_item_font_inherit)
|
||||
self->selected_item_font = self->item_font;
|
||||
}
|
||||
else if (grub_strcmp (name, "selected_item_font") == 0)
|
||||
{
|
||||
if (! value || grub_strcmp (value, "inherit") == 0)
|
||||
{
|
||||
self->selected_item_font = self->item_font;
|
||||
self->selected_item_font_inherit = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
self->selected_item_font = grub_font_get (value);
|
||||
self->selected_item_font_inherit = 0;
|
||||
}
|
||||
}
|
||||
else if (grub_strcmp (name, "item_color") == 0)
|
||||
{
|
||||
grub_video_rgba_color_t color;
|
||||
if (grub_video_parse_color (value, &color) == GRUB_ERR_NONE)
|
||||
{
|
||||
self->item_color = color;
|
||||
if (self->selected_item_color_inherit)
|
||||
self->selected_item_color = self->item_color;
|
||||
}
|
||||
}
|
||||
else if (grub_strcmp (name, "selected_item_color") == 0)
|
||||
{
|
||||
if (! value || grub_strcmp (value, "inherit") == 0)
|
||||
{
|
||||
self->selected_item_color = self->item_color;
|
||||
self->selected_item_color_inherit = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
grub_video_rgba_color_t color;
|
||||
if (grub_video_parse_color (value, &color)
|
||||
== GRUB_ERR_NONE)
|
||||
{
|
||||
self->selected_item_color = color;
|
||||
self->selected_item_color_inherit = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (grub_strcmp (name, "icon_width") == 0)
|
||||
{
|
||||
self->icon_width = grub_strtol (value, 0, 10);
|
||||
grub_gfxmenu_icon_manager_set_icon_size (self->icon_manager,
|
||||
self->icon_width,
|
||||
self->icon_height);
|
||||
}
|
||||
else if (grub_strcmp (name, "icon_height") == 0)
|
||||
{
|
||||
self->icon_height = grub_strtol (value, 0, 10);
|
||||
grub_gfxmenu_icon_manager_set_icon_size (self->icon_manager,
|
||||
self->icon_width,
|
||||
self->icon_height);
|
||||
}
|
||||
else if (grub_strcmp (name, "item_height") == 0)
|
||||
{
|
||||
self->item_height = grub_strtol (value, 0, 10);
|
||||
}
|
||||
else if (grub_strcmp (name, "item_padding") == 0)
|
||||
{
|
||||
self->item_padding = grub_strtol (value, 0, 10);
|
||||
}
|
||||
else if (grub_strcmp (name, "item_icon_space") == 0)
|
||||
{
|
||||
self->item_icon_space = grub_strtol (value, 0, 10);
|
||||
}
|
||||
else if (grub_strcmp (name, "item_spacing") == 0)
|
||||
{
|
||||
self->item_spacing = grub_strtol (value, 0, 10);
|
||||
}
|
||||
else if (grub_strcmp (name, "visible") == 0)
|
||||
{
|
||||
self->visible = grub_strcmp (value, "false") != 0;
|
||||
}
|
||||
else if (grub_strcmp (name, "menu_pixmap_style") == 0)
|
||||
{
|
||||
self->need_to_recreate_boxes = 1;
|
||||
grub_free (self->menu_box_pattern);
|
||||
self->menu_box_pattern = value ? grub_strdup (value) : 0;
|
||||
}
|
||||
else if (grub_strcmp (name, "item_pixmap_style") == 0)
|
||||
{
|
||||
self->need_to_recreate_boxes = 1;
|
||||
grub_free (self->item_box_pattern);
|
||||
self->item_box_pattern = value ? grub_strdup (value) : 0;
|
||||
if (self->selected_item_box_pattern_inherit)
|
||||
{
|
||||
grub_free (self->selected_item_box_pattern);
|
||||
self->selected_item_box_pattern = value ? grub_strdup (value) : 0;
|
||||
}
|
||||
}
|
||||
else if (grub_strcmp (name, "selected_item_pixmap_style") == 0)
|
||||
{
|
||||
if (!value || grub_strcmp (value, "inherit") == 0)
|
||||
{
|
||||
grub_free (self->selected_item_box_pattern);
|
||||
char *tmp = self->item_box_pattern;
|
||||
self->selected_item_box_pattern = tmp ? grub_strdup (tmp) : 0;
|
||||
self->selected_item_box_pattern_inherit = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
self->need_to_recreate_boxes = 1;
|
||||
grub_free (self->selected_item_box_pattern);
|
||||
self->selected_item_box_pattern = value ? grub_strdup (value) : 0;
|
||||
self->selected_item_box_pattern_inherit = 0;
|
||||
}
|
||||
}
|
||||
else if (grub_strcmp (name, "scrollbar_frame") == 0)
|
||||
{
|
||||
self->need_to_recreate_scrollbar = 1;
|
||||
grub_free (self->scrollbar_frame_pattern);
|
||||
self->scrollbar_frame_pattern = value ? grub_strdup (value) : 0;
|
||||
}
|
||||
else if (grub_strcmp (name, "scrollbar_thumb") == 0)
|
||||
{
|
||||
self->need_to_recreate_scrollbar = 1;
|
||||
grub_free (self->scrollbar_thumb_pattern);
|
||||
self->scrollbar_thumb_pattern = value ? grub_strdup (value) : 0;
|
||||
}
|
||||
else if (grub_strcmp (name, "scrollbar_thumb_overlay") == 0)
|
||||
{
|
||||
self->scrollbar_thumb_overlay = grub_strcmp (value, "true") == 0;
|
||||
}
|
||||
else if (grub_strcmp (name, "scrollbar_width") == 0)
|
||||
{
|
||||
self->scrollbar_width = grub_strtol (value, 0, 10);
|
||||
}
|
||||
else if (grub_strcmp (name, "scrollbar_slice") == 0)
|
||||
{
|
||||
if (grub_strcmp (value, "west") == 0)
|
||||
self->scrollbar_slice = SCROLLBAR_SLICE_WEST;
|
||||
else if (grub_strcmp (value, "center") == 0)
|
||||
self->scrollbar_slice = SCROLLBAR_SLICE_CENTER;
|
||||
else if (grub_strcmp (value, "east") == 0)
|
||||
self->scrollbar_slice = SCROLLBAR_SLICE_EAST;
|
||||
}
|
||||
else if (grub_strcmp (name, "scrollbar_left_pad") == 0)
|
||||
{
|
||||
self->scrollbar_left_pad = grub_strtol (value, 0, 10);
|
||||
}
|
||||
else if (grub_strcmp (name, "scrollbar_right_pad") == 0)
|
||||
{
|
||||
self->scrollbar_right_pad = grub_strtol (value, 0, 10);
|
||||
}
|
||||
else if (grub_strcmp (name, "scrollbar_top_pad") == 0)
|
||||
{
|
||||
self->scrollbar_top_pad = grub_strtol (value, 0, 10);
|
||||
}
|
||||
else if (grub_strcmp (name, "scrollbar_bottom_pad") == 0)
|
||||
{
|
||||
self->scrollbar_bottom_pad = grub_strtol (value, 0, 10);
|
||||
}
|
||||
else if (grub_strcmp (name, "scrollbar") == 0)
|
||||
{
|
||||
self->draw_scrollbar = grub_strcmp (value, "false") != 0;
|
||||
}
|
||||
else if (grub_strcmp (name, "theme_dir") == 0)
|
||||
{
|
||||
self->need_to_recreate_boxes = 1;
|
||||
grub_free (self->theme_dir);
|
||||
self->theme_dir = value ? grub_strdup (value) : 0;
|
||||
}
|
||||
else if (grub_strcmp (name, "id") == 0)
|
||||
{
|
||||
grub_free (self->id);
|
||||
if (value)
|
||||
self->id = grub_strdup (value);
|
||||
else
|
||||
self->id = 0;
|
||||
}
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
/* Set necessary information that the gfxmenu view provides. */
|
||||
static void
|
||||
list_set_view_info (void *vself,
|
||||
grub_gfxmenu_view_t view)
|
||||
{
|
||||
list_impl_t self = vself;
|
||||
grub_gfxmenu_icon_manager_set_theme_path (self->icon_manager,
|
||||
view->theme_path);
|
||||
self->view = view;
|
||||
}
|
||||
|
||||
/* Refresh list variables */
|
||||
static void
|
||||
list_refresh_info (void *vself,
|
||||
grub_gfxmenu_view_t view)
|
||||
{
|
||||
list_impl_t self = vself;
|
||||
if (view->nested)
|
||||
self->first_shown_index = 0;
|
||||
}
|
||||
|
||||
static struct grub_gui_component_ops list_comp_ops =
|
||||
{
|
||||
.destroy = list_destroy,
|
||||
.get_id = list_get_id,
|
||||
.is_instance = list_is_instance,
|
||||
.paint = list_paint,
|
||||
.set_parent = list_set_parent,
|
||||
.get_parent = list_get_parent,
|
||||
.set_bounds = list_set_bounds,
|
||||
.get_bounds = list_get_bounds,
|
||||
.get_minimal_size = list_get_minimal_size,
|
||||
.set_property = list_set_property
|
||||
};
|
||||
|
||||
static struct grub_gui_list_ops list_ops =
|
||||
{
|
||||
.set_view_info = list_set_view_info,
|
||||
.refresh_list = list_refresh_info
|
||||
};
|
||||
|
||||
grub_gui_component_t
|
||||
grub_gui_list_new (void)
|
||||
{
|
||||
list_impl_t self;
|
||||
grub_font_t default_font;
|
||||
grub_video_rgba_color_t default_fg_color;
|
||||
|
||||
self = grub_zalloc (sizeof (*self));
|
||||
if (! self)
|
||||
return 0;
|
||||
|
||||
self->list.ops = &list_ops;
|
||||
self->list.component.ops = &list_comp_ops;
|
||||
|
||||
self->visible = 1;
|
||||
|
||||
default_font = grub_font_get ("Unknown Regular 16");
|
||||
default_fg_color = grub_video_rgba_color_rgb (0, 0, 0);
|
||||
|
||||
self->icon_width = 32;
|
||||
self->icon_height = 32;
|
||||
self->item_height = 42;
|
||||
self->item_padding = 14;
|
||||
self->item_icon_space = 4;
|
||||
self->item_spacing = 16;
|
||||
self->item_font = default_font;
|
||||
self->selected_item_font_inherit = 1; /* Default to using the item_font. */
|
||||
self->selected_item_font = default_font;
|
||||
self->item_color = default_fg_color;
|
||||
self->selected_item_color_inherit = 1; /* Default to using the item_color. */
|
||||
self->selected_item_color = default_fg_color;
|
||||
|
||||
self->draw_scrollbar = 1;
|
||||
self->need_to_recreate_scrollbar = 1;
|
||||
self->scrollbar_frame = 0;
|
||||
self->scrollbar_thumb = 0;
|
||||
self->scrollbar_frame_pattern = 0;
|
||||
self->scrollbar_thumb_pattern = 0;
|
||||
self->scrollbar_thumb_overlay = 0;
|
||||
self->scrollbar_width = 16;
|
||||
self->scrollbar_slice = SCROLLBAR_SLICE_EAST;
|
||||
self->scrollbar_left_pad = 2;
|
||||
self->scrollbar_right_pad = 0;
|
||||
self->scrollbar_top_pad = 0;
|
||||
self->scrollbar_bottom_pad = 0;
|
||||
|
||||
self->first_shown_index = 0;
|
||||
|
||||
self->need_to_recreate_boxes = 0;
|
||||
self->theme_dir = 0;
|
||||
self->menu_box_pattern = 0;
|
||||
self->item_box_pattern = 0;
|
||||
self->selected_item_box_pattern_inherit = 1;/*Default to using the item_box.*/
|
||||
self->selected_item_box_pattern = 0;
|
||||
self->menu_box = grub_gfxmenu_create_box (0, 0);
|
||||
self->item_box = grub_gfxmenu_create_box (0, 0);
|
||||
self->selected_item_box = grub_gfxmenu_create_box (0, 0);
|
||||
|
||||
self->icon_manager = grub_gfxmenu_icon_manager_new ();
|
||||
if (! self->icon_manager)
|
||||
{
|
||||
self->list.component.ops->destroy (self);
|
||||
return 0;
|
||||
}
|
||||
grub_gfxmenu_icon_manager_set_icon_size (self->icon_manager,
|
||||
self->icon_width,
|
||||
self->icon_height);
|
||||
return (grub_gui_component_t) self;
|
||||
}
|
||||
@@ -0,0 +1,893 @@
|
||||
/* theme_loader.c - Theme file loader for gfxmenu. */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2008 Free Software Foundation, Inc.
|
||||
*
|
||||
* GRUB is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GRUB is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <grub/types.h>
|
||||
#include <grub/file.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/mm.h>
|
||||
#include <grub/err.h>
|
||||
#include <grub/dl.h>
|
||||
#include <grub/video.h>
|
||||
#include <grub/gui_string_util.h>
|
||||
#include <grub/bitmap.h>
|
||||
#include <grub/bitmap_scale.h>
|
||||
#include <grub/gfxwidgets.h>
|
||||
#include <grub/gfxmenu_view.h>
|
||||
#include <grub/gui.h>
|
||||
#include <grub/color.h>
|
||||
#include <grub/env.h>
|
||||
|
||||
static grub_err_t
|
||||
parse_proportional_spec (const char *value, signed *abs, grub_fixed_signed_t *prop);
|
||||
|
||||
/* Construct a new box widget using ABSPATTERN to find the pixmap files for
|
||||
it, storing the new box instance at *BOXPTR.
|
||||
PATTERN should be of the form: "(hd0,0)/somewhere/style*.png".
|
||||
The '*' then gets substituted with the various pixmap names that the
|
||||
box uses. */
|
||||
static grub_err_t
|
||||
recreate_box_absolute (grub_gfxmenu_box_t *boxptr, const char *abspattern)
|
||||
{
|
||||
char *prefix;
|
||||
char *suffix;
|
||||
char *star;
|
||||
grub_gfxmenu_box_t box;
|
||||
|
||||
star = grub_strchr (abspattern, '*');
|
||||
if (! star)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT,
|
||||
"missing `*' in box pixmap pattern `%s'", abspattern);
|
||||
|
||||
/* Prefix: Get the part before the '*'. */
|
||||
prefix = grub_malloc (star - abspattern + 1);
|
||||
if (! prefix)
|
||||
return grub_errno;
|
||||
|
||||
grub_memcpy (prefix, abspattern, star - abspattern);
|
||||
prefix[star - abspattern] = '\0';
|
||||
|
||||
/* Suffix: Everything after the '*' is the suffix. */
|
||||
suffix = star + 1;
|
||||
|
||||
box = grub_gfxmenu_create_box (prefix, suffix);
|
||||
grub_free (prefix);
|
||||
if (! box)
|
||||
return grub_errno;
|
||||
|
||||
if (*boxptr)
|
||||
(*boxptr)->destroy (*boxptr);
|
||||
*boxptr = box;
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
|
||||
/* Construct a new box widget using PATTERN to find the pixmap files for it,
|
||||
storing the new widget at *BOXPTR. PATTERN should be of the form:
|
||||
"somewhere/style*.png". The '*' then gets substituted with the various
|
||||
pixmap names that the widget uses.
|
||||
|
||||
Important! The value of *BOXPTR must be initialized! It must either
|
||||
(1) Be 0 (a NULL pointer), or
|
||||
(2) Be a pointer to a valid 'grub_gfxmenu_box_t' instance.
|
||||
In this case, the previous instance is destroyed. */
|
||||
grub_err_t
|
||||
grub_gui_recreate_box (grub_gfxmenu_box_t *boxptr,
|
||||
const char *pattern, const char *theme_dir)
|
||||
{
|
||||
char *abspattern;
|
||||
|
||||
/* Check arguments. */
|
||||
if (! pattern)
|
||||
{
|
||||
/* If no pixmap pattern is given, then just create an empty box. */
|
||||
if (*boxptr)
|
||||
(*boxptr)->destroy (*boxptr);
|
||||
*boxptr = grub_gfxmenu_create_box (0, 0);
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
if (! theme_dir)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT,
|
||||
"styled box missing theme directory");
|
||||
|
||||
/* Resolve to an absolute path. */
|
||||
abspattern = grub_resolve_relative_path (theme_dir, pattern);
|
||||
if (! abspattern)
|
||||
return grub_errno;
|
||||
|
||||
/* Create the box. */
|
||||
recreate_box_absolute (boxptr, abspattern);
|
||||
grub_free (abspattern);
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
theme_get_unsigned_int_from_proportional (const char *value,
|
||||
unsigned absolute_value,
|
||||
unsigned int *parsed_value)
|
||||
{
|
||||
grub_err_t err;
|
||||
grub_fixed_signed_t frac;
|
||||
signed pixels;
|
||||
err = parse_proportional_spec (value, &pixels, &frac);
|
||||
if (err != GRUB_ERR_NONE)
|
||||
return err;
|
||||
int result = grub_fixed_sfs_multiply (absolute_value, frac) + pixels;
|
||||
if (result < 0)
|
||||
result = 0;
|
||||
*parsed_value = result;
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
/* Set the specified property NAME on the view to the given string VALUE.
|
||||
The caller is responsible for the lifetimes of NAME and VALUE. */
|
||||
static grub_err_t
|
||||
theme_set_string (grub_gfxmenu_view_t view,
|
||||
const char *name,
|
||||
const char *value,
|
||||
const char *theme_dir,
|
||||
const char *filename,
|
||||
int line_num,
|
||||
int col_num)
|
||||
{
|
||||
if (! grub_strcmp ("title-font", name))
|
||||
view->title_font = grub_font_get (value);
|
||||
else if (! grub_strcmp ("message-font", name))
|
||||
view->message_font = grub_font_get (value);
|
||||
else if (! grub_strcmp ("terminal-font", name))
|
||||
{
|
||||
grub_free (view->terminal_font_name);
|
||||
view->terminal_font_name = grub_strdup (value);
|
||||
if (! view->terminal_font_name)
|
||||
return grub_errno;
|
||||
}
|
||||
else if (! grub_strcmp ("title-color", name))
|
||||
grub_video_parse_color (value, &view->title_color);
|
||||
else if (! grub_strcmp ("message-color", name))
|
||||
grub_video_parse_color (value, &view->message_color);
|
||||
else if (! grub_strcmp ("message-bg-color", name))
|
||||
grub_video_parse_color (value, &view->message_bg_color);
|
||||
else if (! grub_strcmp("menu-tip-left", name))
|
||||
grub_env_set("VTOY_TIP_LEFT", value);
|
||||
else if (! grub_strcmp("menu-tip-top", name))
|
||||
grub_env_set("VTOY_TIP_TOP", value);
|
||||
else if (! grub_strcmp("menu-tip-color", name))
|
||||
grub_env_set("VTOY_TIP_COLOR", value);
|
||||
else if (! grub_strcmp ("desktop-image", name))
|
||||
{
|
||||
struct grub_video_bitmap *raw_bitmap;
|
||||
char *path;
|
||||
path = grub_resolve_relative_path (theme_dir, value);
|
||||
if (! path)
|
||||
return grub_errno;
|
||||
if (grub_video_bitmap_load (&raw_bitmap, path) != GRUB_ERR_NONE)
|
||||
{
|
||||
grub_free (path);
|
||||
return grub_errno;
|
||||
}
|
||||
grub_free(path);
|
||||
grub_video_bitmap_destroy (view->raw_desktop_image);
|
||||
view->raw_desktop_image = raw_bitmap;
|
||||
}
|
||||
else if (! grub_strcmp ("desktop-image-scale-method", name))
|
||||
{
|
||||
if (! value || ! grub_strcmp ("stretch", value))
|
||||
view->desktop_image_scale_method =
|
||||
GRUB_VIDEO_BITMAP_SELECTION_METHOD_STRETCH;
|
||||
else if (! grub_strcmp ("crop", value))
|
||||
view->desktop_image_scale_method =
|
||||
GRUB_VIDEO_BITMAP_SELECTION_METHOD_CROP;
|
||||
else if (! grub_strcmp ("padding", value))
|
||||
view->desktop_image_scale_method =
|
||||
GRUB_VIDEO_BITMAP_SELECTION_METHOD_PADDING;
|
||||
else if (! grub_strcmp ("fitwidth", value))
|
||||
view->desktop_image_scale_method =
|
||||
GRUB_VIDEO_BITMAP_SELECTION_METHOD_FITWIDTH;
|
||||
else if (! grub_strcmp ("fitheight", value))
|
||||
view->desktop_image_scale_method =
|
||||
GRUB_VIDEO_BITMAP_SELECTION_METHOD_FITHEIGHT;
|
||||
else
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT,
|
||||
"Unsupported scale method: %s",
|
||||
value);
|
||||
}
|
||||
else if (! grub_strcmp ("desktop-image-h-align", name))
|
||||
{
|
||||
if (! grub_strcmp ("left", value))
|
||||
view->desktop_image_h_align = GRUB_VIDEO_BITMAP_H_ALIGN_LEFT;
|
||||
else if (! grub_strcmp ("center", value))
|
||||
view->desktop_image_h_align = GRUB_VIDEO_BITMAP_H_ALIGN_CENTER;
|
||||
else if (! grub_strcmp ("right", value))
|
||||
view->desktop_image_h_align = GRUB_VIDEO_BITMAP_H_ALIGN_RIGHT;
|
||||
else
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT,
|
||||
"Unsupported horizontal align method: %s",
|
||||
value);
|
||||
}
|
||||
else if (! grub_strcmp ("desktop-image-v-align", name))
|
||||
{
|
||||
if (! grub_strcmp ("top", value))
|
||||
view->desktop_image_v_align = GRUB_VIDEO_BITMAP_V_ALIGN_TOP;
|
||||
else if (! grub_strcmp ("center", value))
|
||||
view->desktop_image_v_align = GRUB_VIDEO_BITMAP_V_ALIGN_CENTER;
|
||||
else if (! grub_strcmp ("bottom", value))
|
||||
view->desktop_image_v_align = GRUB_VIDEO_BITMAP_V_ALIGN_BOTTOM;
|
||||
else
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT,
|
||||
"Unsupported vertical align method: %s",
|
||||
value);
|
||||
}
|
||||
else if (! grub_strcmp ("desktop-color", name))
|
||||
grub_video_parse_color (value, &view->desktop_color);
|
||||
else if (! grub_strcmp ("terminal-box", name))
|
||||
{
|
||||
grub_err_t err;
|
||||
err = grub_gui_recreate_box (&view->terminal_box, value, theme_dir);
|
||||
if (err != GRUB_ERR_NONE)
|
||||
return err;
|
||||
}
|
||||
else if (! grub_strcmp ("terminal-border", name))
|
||||
{
|
||||
view->terminal_border = grub_strtoul (value, 0, 10);
|
||||
if (grub_errno)
|
||||
return grub_errno;
|
||||
}
|
||||
else if (! grub_strcmp ("terminal-left", name))
|
||||
{
|
||||
unsigned int tmp;
|
||||
int err = theme_get_unsigned_int_from_proportional (value,
|
||||
view->screen.width,
|
||||
&tmp);
|
||||
if (err != GRUB_ERR_NONE)
|
||||
return err;
|
||||
view->terminal_rect.x = tmp;
|
||||
}
|
||||
else if (! grub_strcmp ("terminal-top", name))
|
||||
{
|
||||
unsigned int tmp;
|
||||
int err = theme_get_unsigned_int_from_proportional (value,
|
||||
view->screen.height,
|
||||
&tmp);
|
||||
if (err != GRUB_ERR_NONE)
|
||||
return err;
|
||||
view->terminal_rect.y = tmp;
|
||||
}
|
||||
else if (! grub_strcmp ("terminal-width", name))
|
||||
{
|
||||
unsigned int tmp;
|
||||
int err = theme_get_unsigned_int_from_proportional (value,
|
||||
view->screen.width,
|
||||
&tmp);
|
||||
if (err != GRUB_ERR_NONE)
|
||||
return err;
|
||||
view->terminal_rect.width = tmp;
|
||||
}
|
||||
else if (! grub_strcmp ("terminal-height", name))
|
||||
{
|
||||
unsigned int tmp;
|
||||
int err = theme_get_unsigned_int_from_proportional (value,
|
||||
view->screen.height,
|
||||
&tmp);
|
||||
if (err != GRUB_ERR_NONE)
|
||||
return err;
|
||||
view->terminal_rect.height = tmp;
|
||||
}
|
||||
else if (! grub_strcmp ("title-text", name))
|
||||
{
|
||||
grub_free (view->title_text);
|
||||
view->title_text = grub_strdup (value);
|
||||
if (! view->title_text)
|
||||
return grub_errno;
|
||||
}
|
||||
else if (! grub_strcmp ("ventoy_left_top_color", name))
|
||||
return grub_errno;
|
||||
else
|
||||
{
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT,
|
||||
"%s:%d:%d unknown property `%s'",
|
||||
filename, line_num, col_num, name);
|
||||
}
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
struct parsebuf
|
||||
{
|
||||
char *buf;
|
||||
int pos;
|
||||
int len;
|
||||
int line_num;
|
||||
int col_num;
|
||||
const char *filename;
|
||||
char *theme_dir;
|
||||
grub_gfxmenu_view_t view;
|
||||
};
|
||||
|
||||
static int
|
||||
has_more (struct parsebuf *p)
|
||||
{
|
||||
return p->pos < p->len;
|
||||
}
|
||||
|
||||
static int
|
||||
read_char (struct parsebuf *p)
|
||||
{
|
||||
if (has_more (p))
|
||||
{
|
||||
char c;
|
||||
c = p->buf[p->pos++];
|
||||
if (c == '\n')
|
||||
{
|
||||
p->line_num++;
|
||||
p->col_num = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
p->col_num++;
|
||||
}
|
||||
return c;
|
||||
}
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int
|
||||
peek_char (struct parsebuf *p)
|
||||
{
|
||||
if (has_more (p))
|
||||
return p->buf[p->pos];
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int
|
||||
is_whitespace (char c)
|
||||
{
|
||||
return (c == ' '
|
||||
|| c == '\t'
|
||||
|| c == '\r'
|
||||
|| c == '\n'
|
||||
|| c == '\f');
|
||||
}
|
||||
|
||||
static void
|
||||
skip_whitespace (struct parsebuf *p)
|
||||
{
|
||||
while (has_more (p) && is_whitespace(peek_char (p)))
|
||||
read_char (p);
|
||||
}
|
||||
|
||||
static void
|
||||
advance_to_next_line (struct parsebuf *p)
|
||||
{
|
||||
int c;
|
||||
|
||||
/* Eat characters up to the newline. */
|
||||
do
|
||||
{
|
||||
c = read_char (p);
|
||||
}
|
||||
while (c != -1 && c != '\n');
|
||||
}
|
||||
|
||||
static int
|
||||
is_identifier_char (int c)
|
||||
{
|
||||
return (c != -1
|
||||
&& (grub_isalpha(c)
|
||||
|| grub_isdigit(c)
|
||||
|| c == '_'
|
||||
|| c == '-'));
|
||||
}
|
||||
|
||||
static char *
|
||||
read_identifier (struct parsebuf *p)
|
||||
{
|
||||
/* Index of the first character of the identifier in p->buf. */
|
||||
int start;
|
||||
/* Next index after the last character of the identifer in p->buf. */
|
||||
int end;
|
||||
|
||||
skip_whitespace (p);
|
||||
|
||||
/* Capture the start of the identifier. */
|
||||
start = p->pos;
|
||||
|
||||
/* Scan for the end. */
|
||||
while (is_identifier_char (peek_char (p)))
|
||||
read_char (p);
|
||||
end = p->pos;
|
||||
|
||||
if (end - start < 1)
|
||||
return 0;
|
||||
|
||||
return grub_new_substring (p->buf, start, end);
|
||||
}
|
||||
|
||||
static char *
|
||||
read_expression (struct parsebuf *p)
|
||||
{
|
||||
int start;
|
||||
int end;
|
||||
|
||||
skip_whitespace (p);
|
||||
if (peek_char (p) == '"')
|
||||
{
|
||||
/* Read as a quoted string.
|
||||
The quotation marks are not included in the expression value. */
|
||||
/* Skip opening quotation mark. */
|
||||
read_char (p);
|
||||
start = p->pos;
|
||||
while (has_more (p) && peek_char (p) != '"')
|
||||
read_char (p);
|
||||
end = p->pos;
|
||||
/* Skip the terminating quotation mark. */
|
||||
read_char (p);
|
||||
}
|
||||
else if (peek_char (p) == '(')
|
||||
{
|
||||
/* Read as a parenthesized string -- for tuples/coordinates. */
|
||||
/* The parentheses are included in the expression value. */
|
||||
int c;
|
||||
|
||||
start = p->pos;
|
||||
do
|
||||
{
|
||||
c = read_char (p);
|
||||
}
|
||||
while (c != -1 && c != ')');
|
||||
end = p->pos;
|
||||
}
|
||||
else if (has_more (p))
|
||||
{
|
||||
/* Read as a single word -- for numeric values or words without
|
||||
whitespace. */
|
||||
start = p->pos;
|
||||
while (has_more (p) && ! is_whitespace (peek_char (p))
|
||||
&& peek_char (p) != '}')
|
||||
read_char (p);
|
||||
end = p->pos;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* The end of the theme file has been reached. */
|
||||
grub_error (GRUB_ERR_IO, "%s:%d:%d expression expected in theme file",
|
||||
p->filename, p->line_num, p->col_num);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return grub_new_substring (p->buf, start, end);
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
parse_proportional_spec (const char *value, signed *abs, grub_fixed_signed_t *prop)
|
||||
{
|
||||
signed num;
|
||||
const 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, (char **) &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);
|
||||
ptr++;
|
||||
}
|
||||
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
|
||||
read_object (struct parsebuf *p, grub_gui_container_t parent)
|
||||
{
|
||||
grub_video_rect_t bounds;
|
||||
|
||||
char *name;
|
||||
name = read_identifier (p);
|
||||
if (! name)
|
||||
goto cleanup;
|
||||
|
||||
grub_gui_component_t component = 0;
|
||||
if (grub_strcmp (name, "label") == 0)
|
||||
{
|
||||
component = grub_gui_label_new ();
|
||||
}
|
||||
else if (grub_strcmp (name, "image") == 0)
|
||||
{
|
||||
component = grub_gui_image_new ();
|
||||
}
|
||||
else if (grub_strcmp (name, "vbox") == 0)
|
||||
{
|
||||
component = (grub_gui_component_t) grub_gui_vbox_new ();
|
||||
}
|
||||
else if (grub_strcmp (name, "hbox") == 0)
|
||||
{
|
||||
component = (grub_gui_component_t) grub_gui_hbox_new ();
|
||||
}
|
||||
else if (grub_strcmp (name, "canvas") == 0)
|
||||
{
|
||||
component = (grub_gui_component_t) grub_gui_canvas_new ();
|
||||
}
|
||||
else if (grub_strcmp (name, "progress_bar") == 0)
|
||||
{
|
||||
component = grub_gui_progress_bar_new ();
|
||||
}
|
||||
else if (grub_strcmp (name, "circular_progress") == 0)
|
||||
{
|
||||
component = grub_gui_circular_progress_new ();
|
||||
}
|
||||
else if (grub_strcmp (name, "boot_menu") == 0)
|
||||
{
|
||||
component = grub_gui_list_new ();
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Unknown type. */
|
||||
grub_error (GRUB_ERR_IO, "%s:%d:%d unknown object type `%s'",
|
||||
p->filename, p->line_num, p->col_num, name);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (! component)
|
||||
goto cleanup;
|
||||
|
||||
/* Inform the component about the theme so it can find its resources. */
|
||||
component->ops->set_property (component, "theme_dir", p->theme_dir);
|
||||
component->ops->set_property (component, "theme_path", p->filename);
|
||||
|
||||
/* Add the component as a child of PARENT. */
|
||||
bounds.x = 0;
|
||||
bounds.y = 0;
|
||||
bounds.width = -1;
|
||||
bounds.height = -1;
|
||||
component->ops->set_bounds (component, &bounds);
|
||||
parent->ops->add (parent, component);
|
||||
|
||||
skip_whitespace (p);
|
||||
if (read_char (p) != '{')
|
||||
{
|
||||
grub_error (GRUB_ERR_IO,
|
||||
"%s:%d:%d expected `{' after object type name `%s'",
|
||||
p->filename, p->line_num, p->col_num, name);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
while (has_more (p))
|
||||
{
|
||||
skip_whitespace (p);
|
||||
|
||||
/* Check whether the end has been encountered. */
|
||||
if (peek_char (p) == '}')
|
||||
{
|
||||
/* Skip the closing brace. */
|
||||
read_char (p);
|
||||
break;
|
||||
}
|
||||
|
||||
if (peek_char (p) == '#')
|
||||
{
|
||||
/* Skip comments. */
|
||||
advance_to_next_line (p);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (peek_char (p) == '+')
|
||||
{
|
||||
/* Skip the '+'. */
|
||||
read_char (p);
|
||||
|
||||
/* Check whether this component is a container. */
|
||||
if (component->ops->is_instance (component, "container"))
|
||||
{
|
||||
/* Read the sub-object recursively and add it as a child. */
|
||||
if (read_object (p, (grub_gui_container_t) component) != 0)
|
||||
goto cleanup;
|
||||
/* After reading the sub-object, resume parsing, expecting
|
||||
another property assignment or sub-object definition. */
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
grub_error (GRUB_ERR_IO,
|
||||
"%s:%d:%d attempted to add object to non-container",
|
||||
p->filename, p->line_num, p->col_num);
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
char *property;
|
||||
property = read_identifier (p);
|
||||
if (! property)
|
||||
{
|
||||
grub_error (GRUB_ERR_IO, "%s:%d:%d identifier expected in theme file",
|
||||
p->filename, p->line_num, p->col_num);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
skip_whitespace (p);
|
||||
if (read_char (p) != '=')
|
||||
{
|
||||
grub_error (GRUB_ERR_IO,
|
||||
"%s:%d:%d expected `=' after property name `%s'",
|
||||
p->filename, p->line_num, p->col_num, property);
|
||||
grub_free (property);
|
||||
goto cleanup;
|
||||
}
|
||||
skip_whitespace (p);
|
||||
|
||||
char *value;
|
||||
value = read_expression (p);
|
||||
if (! value)
|
||||
{
|
||||
grub_free (property);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* Handle the property value. */
|
||||
if (grub_strcmp (property, "left") == 0)
|
||||
parse_proportional_spec (value, &component->x, &component->xfrac);
|
||||
else if (grub_strcmp (property, "top") == 0)
|
||||
parse_proportional_spec (value, &component->y, &component->yfrac);
|
||||
else if (grub_strcmp (property, "width") == 0)
|
||||
parse_proportional_spec (value, &component->w, &component->wfrac);
|
||||
else if (grub_strcmp (property, "height") == 0)
|
||||
parse_proportional_spec (value, &component->h, &component->hfrac);
|
||||
else
|
||||
/* General property handling. */
|
||||
component->ops->set_property (component, property, value);
|
||||
|
||||
grub_free (value);
|
||||
grub_free (property);
|
||||
if (grub_errno != GRUB_ERR_NONE)
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
cleanup:
|
||||
grub_free (name);
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
read_property (struct parsebuf *p)
|
||||
{
|
||||
char *name;
|
||||
|
||||
/* Read the property name. */
|
||||
name = read_identifier (p);
|
||||
if (! name)
|
||||
{
|
||||
advance_to_next_line (p);
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
/* Skip whitespace before separator. */
|
||||
skip_whitespace (p);
|
||||
|
||||
/* Read separator. */
|
||||
if (read_char (p) != ':')
|
||||
{
|
||||
grub_error (GRUB_ERR_IO,
|
||||
"%s:%d:%d missing separator after property name `%s'",
|
||||
p->filename, p->line_num, p->col_num, name);
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Skip whitespace after separator. */
|
||||
skip_whitespace (p);
|
||||
|
||||
/* Get the value based on its type. */
|
||||
if (peek_char (p) == '"')
|
||||
{
|
||||
/* String value (e.g., '"My string"'). */
|
||||
char *value = read_expression (p);
|
||||
if (! value)
|
||||
{
|
||||
grub_error (GRUB_ERR_IO, "%s:%d:%d missing property value",
|
||||
p->filename, p->line_num, p->col_num);
|
||||
goto done;
|
||||
}
|
||||
/* If theme_set_string results in an error, grub_errno will be returned
|
||||
below. */
|
||||
theme_set_string (p->view, name, value, p->theme_dir,
|
||||
p->filename, p->line_num, p->col_num);
|
||||
grub_free (value);
|
||||
}
|
||||
else
|
||||
{
|
||||
grub_error (GRUB_ERR_IO,
|
||||
"%s:%d:%d property value invalid; "
|
||||
"enclose literal values in quotes (\")",
|
||||
p->filename, p->line_num, p->col_num);
|
||||
|
||||
grub_printf("File: %s\nLine:%d Column:%d\n"
|
||||
"property value invalid; enclose literal values in quotes (\")\n\n",
|
||||
p->filename, p->line_num, p->col_num);
|
||||
|
||||
goto done;
|
||||
}
|
||||
|
||||
done:
|
||||
grub_free (name);
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
extern int g_menu_update_mode;
|
||||
|
||||
/* Set properties on the view based on settings from the specified
|
||||
theme file. */
|
||||
grub_err_t
|
||||
grub_gfxmenu_view_load_theme (grub_gfxmenu_view_t view, const char *theme_path)
|
||||
{
|
||||
int flag = 0;
|
||||
grub_file_t file;
|
||||
struct parsebuf p;
|
||||
|
||||
p.view = view;
|
||||
p.theme_dir = grub_get_dirname (theme_path);
|
||||
|
||||
file = grub_file_open (theme_path, GRUB_FILE_TYPE_THEME);
|
||||
if (! file)
|
||||
{
|
||||
grub_free (p.theme_dir);
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
p.len = grub_file_size (file);
|
||||
p.buf = grub_malloc (p.len + 8192);
|
||||
p.pos = 0;
|
||||
p.line_num = 1;
|
||||
p.col_num = 1;
|
||||
p.filename = theme_path;
|
||||
if (! p.buf)
|
||||
{
|
||||
grub_file_close (file);
|
||||
grub_free (p.theme_dir);
|
||||
return grub_errno;
|
||||
}
|
||||
if (grub_file_read (file, p.buf, p.len) != p.len)
|
||||
{
|
||||
grub_free (p.buf);
|
||||
grub_file_close (file);
|
||||
grub_free (p.theme_dir);
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
{
|
||||
const char *checkret = grub_env_get("VTOY_CHKDEV_RESULT_STRING");
|
||||
if (checkret == NULL || checkret[0] != '0')
|
||||
{
|
||||
p.len += grub_snprintf(p.buf + p.len, 4096, "\n+ hbox{\n left = 1%%\n top = 90%%\n"
|
||||
" + label {text = \"[Unofficial Ventoy]\" color = \"red\" align = \"left\"}\n"
|
||||
"}\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (view->canvas)
|
||||
view->canvas->component.ops->destroy (view->canvas);
|
||||
|
||||
view->canvas = grub_gui_canvas_new ();
|
||||
if (!view->canvas)
|
||||
goto fail;
|
||||
((grub_gui_component_t) view->canvas)
|
||||
->ops->set_bounds ((grub_gui_component_t) view->canvas,
|
||||
&view->screen);
|
||||
|
||||
parse:
|
||||
while (has_more (&p))
|
||||
{
|
||||
/* Skip comments (lines beginning with #). */
|
||||
if (peek_char (&p) == '#')
|
||||
{
|
||||
advance_to_next_line (&p);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Find the first non-whitespace character. */
|
||||
skip_whitespace (&p);
|
||||
|
||||
/* Handle the content. */
|
||||
if (peek_char (&p) == '+')
|
||||
{
|
||||
/* Skip the '+'. */
|
||||
read_char (&p);
|
||||
read_object (&p, view->canvas);
|
||||
}
|
||||
else
|
||||
{
|
||||
read_property (&p);
|
||||
}
|
||||
|
||||
if (grub_errno != GRUB_ERR_NONE)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
||||
if (flag == 0)
|
||||
{
|
||||
const char *tip = grub_env_get("VTOY_MENU_TIP_ENABLE");
|
||||
if (tip && tip[0] == '1')
|
||||
{
|
||||
char tmpmsg[512];
|
||||
|
||||
grub_memset(tmpmsg, 'w', 500);
|
||||
tmpmsg[500] = 0;
|
||||
|
||||
g_menu_update_mode = 1;
|
||||
p.len += grub_snprintf(p.buf + p.len, 4096,
|
||||
"\n+ vbox{\n left = %s\n top = %s\n"
|
||||
"+ label { id=\"VTOY_MENU_TIP_1\" text = \"%s\" color = \"%s\" align = \"%s\"}\n"
|
||||
"+ label { id=\"VTOY_MENU_TIP_2\" text = \"%s\" color = \"%s\" align = \"%s\"}\n"
|
||||
"}\n",
|
||||
grub_env_get("VTOY_TIP_LEFT"),
|
||||
grub_env_get("VTOY_TIP_TOP"),
|
||||
tmpmsg,
|
||||
grub_env_get("VTOY_TIP_COLOR"),
|
||||
grub_env_get("VTOY_TIP_ALIGN"),
|
||||
tmpmsg,
|
||||
grub_env_get("VTOY_TIP_COLOR"),
|
||||
grub_env_get("VTOY_TIP_ALIGN")
|
||||
);
|
||||
|
||||
flag = 1;
|
||||
goto parse;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Set the new theme path. */
|
||||
grub_free (view->theme_path);
|
||||
view->theme_path = grub_strdup (theme_path);
|
||||
goto cleanup;
|
||||
|
||||
fail:
|
||||
if (view->canvas)
|
||||
{
|
||||
view->canvas->component.ops->destroy (view->canvas);
|
||||
view->canvas = 0;
|
||||
}
|
||||
|
||||
cleanup:
|
||||
grub_free (p.buf);
|
||||
grub_file_close (file);
|
||||
grub_free (p.theme_dir);
|
||||
return grub_errno;
|
||||
}
|
||||
@@ -0,0 +1,694 @@
|
||||
/* view.c - Graphical menu interface MVC view. */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2008 Free Software Foundation, Inc.
|
||||
*
|
||||
* GRUB is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GRUB is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <grub/types.h>
|
||||
#include <grub/file.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/mm.h>
|
||||
#include <grub/err.h>
|
||||
#include <grub/dl.h>
|
||||
#include <grub/normal.h>
|
||||
#include <grub/video.h>
|
||||
#include <grub/gfxterm.h>
|
||||
#include <grub/bitmap.h>
|
||||
#include <grub/bitmap_scale.h>
|
||||
#include <grub/term.h>
|
||||
#include <grub/gfxwidgets.h>
|
||||
#include <grub/time.h>
|
||||
#include <grub/menu.h>
|
||||
#include <grub/menu_viewer.h>
|
||||
#include <grub/gfxmenu_view.h>
|
||||
#include <grub/gui_string_util.h>
|
||||
#include <grub/icon_manager.h>
|
||||
#include <grub/i18n.h>
|
||||
#include <grub/charset.h>
|
||||
|
||||
static void
|
||||
init_terminal (grub_gfxmenu_view_t view);
|
||||
static void
|
||||
init_background (grub_gfxmenu_view_t view);
|
||||
static grub_gfxmenu_view_t term_view;
|
||||
|
||||
/* Create a new view object, loading the theme specified by THEME_PATH and
|
||||
associating MODEL with the view. */
|
||||
grub_gfxmenu_view_t
|
||||
grub_gfxmenu_view_new (const char *theme_path,
|
||||
int width, int height)
|
||||
{
|
||||
grub_gfxmenu_view_t view;
|
||||
grub_font_t default_font;
|
||||
grub_video_rgba_color_t default_fg_color;
|
||||
grub_video_rgba_color_t default_bg_color;
|
||||
|
||||
view = grub_malloc (sizeof (*view));
|
||||
if (! view)
|
||||
return 0;
|
||||
|
||||
while (grub_gfxmenu_timeout_notifications)
|
||||
{
|
||||
struct grub_gfxmenu_timeout_notify *p;
|
||||
p = grub_gfxmenu_timeout_notifications;
|
||||
grub_gfxmenu_timeout_notifications = grub_gfxmenu_timeout_notifications->next;
|
||||
grub_free (p);
|
||||
}
|
||||
|
||||
view->screen.x = 0;
|
||||
view->screen.y = 0;
|
||||
view->screen.width = width;
|
||||
view->screen.height = height;
|
||||
|
||||
view->need_to_check_sanity = 1;
|
||||
view->terminal_border = 3;
|
||||
view->terminal_rect.width = view->screen.width * 7 / 10;
|
||||
view->terminal_rect.height = view->screen.height * 7 / 10;
|
||||
view->terminal_rect.x = view->screen.x + (view->screen.width
|
||||
- view->terminal_rect.width) / 2;
|
||||
view->terminal_rect.y = view->screen.y + (view->screen.height
|
||||
- view->terminal_rect.height) / 2;
|
||||
|
||||
default_font = grub_font_get ("Unknown Regular 16");
|
||||
default_fg_color = grub_video_rgba_color_rgb (0, 0, 0);
|
||||
default_bg_color = grub_video_rgba_color_rgb (255, 255, 255);
|
||||
|
||||
view->canvas = 0;
|
||||
|
||||
view->title_font = default_font;
|
||||
view->message_font = default_font;
|
||||
view->terminal_font_name = grub_strdup ("Fixed 10");
|
||||
view->title_color = default_fg_color;
|
||||
view->message_color = default_bg_color;
|
||||
view->message_bg_color = default_fg_color;
|
||||
view->raw_desktop_image = 0;
|
||||
view->scaled_desktop_image = 0;
|
||||
view->desktop_image_scale_method = GRUB_VIDEO_BITMAP_SELECTION_METHOD_STRETCH;
|
||||
view->desktop_image_h_align = GRUB_VIDEO_BITMAP_H_ALIGN_CENTER;
|
||||
view->desktop_image_v_align = GRUB_VIDEO_BITMAP_V_ALIGN_CENTER;
|
||||
view->desktop_color = default_bg_color;
|
||||
view->terminal_box = grub_gfxmenu_create_box (0, 0);
|
||||
view->title_text = grub_strdup (_("GRUB Boot Menu"));
|
||||
view->progress_message_text = 0;
|
||||
view->theme_path = 0;
|
||||
|
||||
/* Set the timeout bar's frame. */
|
||||
view->progress_message_frame.width = view->screen.width * 4 / 5;
|
||||
view->progress_message_frame.height = 50;
|
||||
view->progress_message_frame.x = view->screen.x
|
||||
+ (view->screen.width - view->progress_message_frame.width) / 2;
|
||||
view->progress_message_frame.y = view->screen.y
|
||||
+ view->screen.height - 90 - 20 - view->progress_message_frame.height;
|
||||
|
||||
if (grub_gfxmenu_view_load_theme (view, theme_path) != 0)
|
||||
{
|
||||
grub_gfxmenu_view_destroy (view);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
/* Destroy the view object. All used memory is freed. */
|
||||
void
|
||||
grub_gfxmenu_view_destroy (grub_gfxmenu_view_t view)
|
||||
{
|
||||
if (!view)
|
||||
return;
|
||||
while (grub_gfxmenu_timeout_notifications)
|
||||
{
|
||||
struct grub_gfxmenu_timeout_notify *p;
|
||||
p = grub_gfxmenu_timeout_notifications;
|
||||
grub_gfxmenu_timeout_notifications = grub_gfxmenu_timeout_notifications->next;
|
||||
grub_free (p);
|
||||
}
|
||||
grub_video_bitmap_destroy (view->raw_desktop_image);
|
||||
grub_video_bitmap_destroy (view->scaled_desktop_image);
|
||||
if (view->terminal_box)
|
||||
view->terminal_box->destroy (view->terminal_box);
|
||||
grub_free (view->terminal_font_name);
|
||||
grub_free (view->title_text);
|
||||
grub_free (view->progress_message_text);
|
||||
grub_free (view->theme_path);
|
||||
if (view->menu_title_offset)
|
||||
grub_free (view->menu_title_offset);
|
||||
if (view->canvas)
|
||||
view->canvas->component.ops->destroy (view->canvas);
|
||||
grub_free (view);
|
||||
}
|
||||
|
||||
static void
|
||||
redraw_background (grub_gfxmenu_view_t view,
|
||||
const grub_video_rect_t *bounds)
|
||||
{
|
||||
if (view->scaled_desktop_image)
|
||||
{
|
||||
struct grub_video_bitmap *img = view->scaled_desktop_image;
|
||||
grub_video_blit_bitmap (img, GRUB_VIDEO_BLIT_REPLACE,
|
||||
bounds->x, bounds->y,
|
||||
bounds->x - view->screen.x,
|
||||
bounds->y - view->screen.y,
|
||||
bounds->width, bounds->height);
|
||||
}
|
||||
else
|
||||
{
|
||||
grub_video_fill_rect (grub_video_map_rgba_color (view->desktop_color),
|
||||
bounds->x, bounds->y,
|
||||
bounds->width, bounds->height);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
draw_title (grub_gfxmenu_view_t view)
|
||||
{
|
||||
if (! view->title_text)
|
||||
return;
|
||||
|
||||
/* Center the title. */
|
||||
int title_width = grub_font_get_string_width (view->title_font,
|
||||
view->title_text);
|
||||
int x = (view->screen.width - title_width) / 2;
|
||||
int y = 40 + grub_font_get_ascent (view->title_font);
|
||||
grub_font_draw_string (view->title_text,
|
||||
view->title_font,
|
||||
grub_video_map_rgba_color (view->title_color),
|
||||
x, y);
|
||||
}
|
||||
|
||||
struct progress_value_data
|
||||
{
|
||||
int visible;
|
||||
int start;
|
||||
int end;
|
||||
int value;
|
||||
};
|
||||
|
||||
struct grub_gfxmenu_timeout_notify *grub_gfxmenu_timeout_notifications;
|
||||
|
||||
static void
|
||||
update_timeouts (int visible, int start, int value, int 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_video_set_area_status (GRUB_VIDEO_AREA_ENABLED);
|
||||
grub_gfxmenu_view_redraw (view, &bounds);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
grub_gfxmenu_print_timeout (int timeout, void *data)
|
||||
{
|
||||
struct grub_gfxmenu_view *view = data;
|
||||
|
||||
if (view->first_timeout == -1)
|
||||
view->first_timeout = timeout;
|
||||
|
||||
update_timeouts (1, -view->first_timeout, -timeout, 0);
|
||||
redraw_timeouts (view);
|
||||
grub_video_swap_buffers ();
|
||||
if (view->double_repaint)
|
||||
redraw_timeouts (view);
|
||||
}
|
||||
|
||||
void
|
||||
grub_gfxmenu_clear_timeout (void *data)
|
||||
{
|
||||
struct grub_gfxmenu_view *view = data;
|
||||
|
||||
update_timeouts (0, 1, 0, 0);
|
||||
redraw_timeouts (view);
|
||||
grub_video_swap_buffers ();
|
||||
if (view->double_repaint)
|
||||
redraw_timeouts (view);
|
||||
}
|
||||
|
||||
static void
|
||||
update_menu_visit (grub_gui_component_t component,
|
||||
void *userdata)
|
||||
{
|
||||
grub_gfxmenu_view_t view;
|
||||
view = userdata;
|
||||
if (component->ops->is_instance (component, "list"))
|
||||
{
|
||||
grub_gui_list_t list = (grub_gui_list_t) component;
|
||||
list->ops->set_view_info (list, view);
|
||||
}
|
||||
}
|
||||
|
||||
/* Update any boot menu components with the current menu model and
|
||||
theme path. */
|
||||
static void
|
||||
update_menu_components (grub_gfxmenu_view_t view)
|
||||
{
|
||||
grub_gui_iterate_recursively ((grub_gui_component_t) view->canvas,
|
||||
update_menu_visit, view);
|
||||
}
|
||||
|
||||
static void
|
||||
refresh_menu_visit (grub_gui_component_t component,
|
||||
void *userdata)
|
||||
{
|
||||
grub_gfxmenu_view_t view;
|
||||
view = userdata;
|
||||
if (component->ops->is_instance (component, "list"))
|
||||
{
|
||||
grub_gui_list_t list = (grub_gui_list_t) component;
|
||||
list->ops->refresh_list (list, view);
|
||||
}
|
||||
}
|
||||
|
||||
/* Refresh list information (useful for submenus) */
|
||||
static void
|
||||
refresh_menu_components (grub_gfxmenu_view_t view)
|
||||
{
|
||||
grub_gui_iterate_recursively ((grub_gui_component_t) view->canvas,
|
||||
refresh_menu_visit, view);
|
||||
}
|
||||
|
||||
static void
|
||||
draw_message (grub_gfxmenu_view_t view)
|
||||
{
|
||||
char *text = view->progress_message_text;
|
||||
grub_video_rect_t f = view->progress_message_frame;
|
||||
if (! text)
|
||||
return;
|
||||
|
||||
grub_font_t font = view->message_font;
|
||||
grub_video_color_t color = grub_video_map_rgba_color (view->message_color);
|
||||
|
||||
/* Border. */
|
||||
grub_video_fill_rect (color,
|
||||
f.x-1, f.y-1, f.width+2, f.height+2);
|
||||
/* Fill. */
|
||||
grub_video_fill_rect (grub_video_map_rgba_color (view->message_bg_color),
|
||||
f.x, f.y, f.width, f.height);
|
||||
|
||||
/* Center the text. */
|
||||
int text_width = grub_font_get_string_width (font, text);
|
||||
int x = f.x + (f.width - text_width) / 2;
|
||||
int y = (f.y + (f.height - grub_font_get_descent (font)) / 2
|
||||
+ grub_font_get_ascent (font) / 2);
|
||||
grub_font_draw_string (text, font, color, x, y);
|
||||
}
|
||||
|
||||
void
|
||||
grub_gfxmenu_view_redraw (grub_gfxmenu_view_t view,
|
||||
const grub_video_rect_t *region)
|
||||
{
|
||||
if (grub_video_have_common_points (&view->terminal_rect, region))
|
||||
grub_gfxterm_schedule_repaint ();
|
||||
|
||||
grub_video_set_active_render_target (GRUB_VIDEO_RENDER_TARGET_DISPLAY);
|
||||
grub_video_area_status_t area_status;
|
||||
grub_video_get_area_status (&area_status);
|
||||
if (area_status == GRUB_VIDEO_AREA_ENABLED)
|
||||
grub_video_set_region (region->x, region->y,
|
||||
region->width, region->height);
|
||||
|
||||
redraw_background (view, region);
|
||||
if (view->canvas)
|
||||
view->canvas->component.ops->paint (view->canvas, region);
|
||||
draw_title (view);
|
||||
if (grub_video_have_common_points (&view->progress_message_frame, region))
|
||||
draw_message (view);
|
||||
|
||||
if (area_status == GRUB_VIDEO_AREA_ENABLED)
|
||||
grub_video_set_area_status (GRUB_VIDEO_AREA_ENABLED);
|
||||
}
|
||||
|
||||
void
|
||||
grub_gfxmenu_view_draw (grub_gfxmenu_view_t view)
|
||||
{
|
||||
init_terminal (view);
|
||||
|
||||
init_background (view);
|
||||
|
||||
/* Clear the screen; there may be garbage left over in video memory. */
|
||||
grub_video_fill_rect (grub_video_map_rgb (0, 0, 0),
|
||||
view->screen.x, view->screen.y,
|
||||
view->screen.width, view->screen.height);
|
||||
grub_video_swap_buffers ();
|
||||
if (view->double_repaint)
|
||||
grub_video_fill_rect (grub_video_map_rgb (0, 0, 0),
|
||||
view->screen.x, view->screen.y,
|
||||
view->screen.width, view->screen.height);
|
||||
|
||||
refresh_menu_components (view);
|
||||
update_menu_components (view);
|
||||
|
||||
grub_video_set_area_status (GRUB_VIDEO_AREA_DISABLED);
|
||||
grub_gfxmenu_view_redraw (view, &view->screen);
|
||||
grub_video_swap_buffers ();
|
||||
if (view->double_repaint)
|
||||
{
|
||||
grub_video_set_area_status (GRUB_VIDEO_AREA_DISABLED);
|
||||
grub_gfxmenu_view_redraw (view, &view->screen);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
redraw_menu_visit (grub_gui_component_t component,
|
||||
void *userdata)
|
||||
{
|
||||
grub_gfxmenu_view_t view;
|
||||
view = userdata;
|
||||
if (component->ops->is_instance (component, "list"))
|
||||
{
|
||||
grub_video_rect_t bounds;
|
||||
|
||||
component->ops->get_bounds (component, &bounds);
|
||||
grub_video_set_area_status (GRUB_VIDEO_AREA_ENABLED);
|
||||
grub_gfxmenu_view_redraw (view, &bounds);
|
||||
}
|
||||
}
|
||||
|
||||
extern int g_menu_update_mode;
|
||||
|
||||
static void grub_gfxmenu_update_all(grub_gfxmenu_view_t view)
|
||||
{
|
||||
grub_video_set_area_status(GRUB_VIDEO_AREA_DISABLED);
|
||||
grub_gfxmenu_view_redraw(view, &view->screen);
|
||||
}
|
||||
|
||||
void
|
||||
grub_gfxmenu_redraw_menu (grub_gfxmenu_view_t view)
|
||||
{
|
||||
update_menu_components (view);
|
||||
|
||||
if (g_menu_update_mode)
|
||||
grub_gfxmenu_update_all(view);
|
||||
else
|
||||
grub_gui_iterate_recursively ((grub_gui_component_t) view->canvas,
|
||||
redraw_menu_visit, view);
|
||||
|
||||
grub_video_swap_buffers ();
|
||||
if (view->double_repaint)
|
||||
{
|
||||
if (g_menu_update_mode)
|
||||
grub_gfxmenu_update_all(view);
|
||||
else
|
||||
grub_gui_iterate_recursively ((grub_gui_component_t) view->canvas,
|
||||
redraw_menu_visit, view);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
grub_gfxmenu_set_chosen_entry (int entry, void *data)
|
||||
{
|
||||
grub_gfxmenu_view_t view = data;
|
||||
|
||||
view->selected = entry;
|
||||
grub_gfxmenu_redraw_menu (view);
|
||||
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
grub_gfxmenu_scroll_chosen_entry (void *data, int diren)
|
||||
{
|
||||
grub_gfxmenu_view_t view = data;
|
||||
const char *item_title;
|
||||
int off;
|
||||
int max;
|
||||
|
||||
if (!view->menu->size)
|
||||
return;
|
||||
|
||||
item_title = grub_menu_get_entry (view->menu, view->selected)->title;
|
||||
off = view->menu_title_offset[view->selected] + diren;
|
||||
max = grub_utf8_get_num_code (item_title, grub_strlen(item_title));
|
||||
|
||||
if (diren == 1000000)
|
||||
off = (max >= 20) ? (max - 20) : 0;
|
||||
else if (off < 0)
|
||||
off = 0;
|
||||
else if (off > max)
|
||||
off = max;
|
||||
|
||||
view->menu_title_offset[view->selected] = off;
|
||||
grub_gfxmenu_redraw_menu (view);
|
||||
}
|
||||
|
||||
static void
|
||||
grub_gfxmenu_draw_terminal_box (void)
|
||||
{
|
||||
grub_gfxmenu_box_t term_box;
|
||||
|
||||
term_box = term_view->terminal_box;
|
||||
if (!term_box)
|
||||
return;
|
||||
|
||||
grub_video_set_area_status (GRUB_VIDEO_AREA_DISABLED);
|
||||
|
||||
term_box->set_content_size (term_box, term_view->terminal_rect.width,
|
||||
term_view->terminal_rect.height);
|
||||
|
||||
term_box->draw (term_box,
|
||||
term_view->terminal_rect.x - term_box->get_left_pad (term_box),
|
||||
term_view->terminal_rect.y - term_box->get_top_pad (term_box));
|
||||
}
|
||||
|
||||
static void
|
||||
get_min_terminal (grub_font_t terminal_font,
|
||||
unsigned int border_width,
|
||||
unsigned int *min_terminal_width,
|
||||
unsigned int *min_terminal_height)
|
||||
{
|
||||
struct grub_font_glyph *glyph;
|
||||
glyph = grub_font_get_glyph (terminal_font, 'M');
|
||||
*min_terminal_width = (glyph? glyph->device_width : 8) * 80
|
||||
+ 2 * border_width;
|
||||
*min_terminal_height = grub_font_get_max_char_height (terminal_font) * 24
|
||||
+ 2 * border_width;
|
||||
}
|
||||
|
||||
static void
|
||||
terminal_sanity_check (grub_gfxmenu_view_t view)
|
||||
{
|
||||
if (!view->need_to_check_sanity)
|
||||
return;
|
||||
|
||||
/* terminal_font was checked before in the init_terminal function. */
|
||||
grub_font_t terminal_font = grub_font_get (view->terminal_font_name);
|
||||
|
||||
/* Non-negative numbers below. */
|
||||
int scr_x = view->screen.x;
|
||||
int scr_y = view->screen.y;
|
||||
int scr_width = view->screen.width;
|
||||
int scr_height = view->screen.height;
|
||||
int term_x = view->terminal_rect.x;
|
||||
int term_y = view->terminal_rect.y;
|
||||
int term_width = view->terminal_rect.width;
|
||||
int term_height = view->terminal_rect.height;
|
||||
|
||||
/* Check that border_width isn't too big. */
|
||||
unsigned int border_width = view->terminal_border;
|
||||
unsigned int min_terminal_width;
|
||||
unsigned int min_terminal_height;
|
||||
get_min_terminal (terminal_font, border_width,
|
||||
&min_terminal_width, &min_terminal_height);
|
||||
if (border_width > 3 && ((int) min_terminal_width >= scr_width
|
||||
|| (int) min_terminal_height >= scr_height))
|
||||
{
|
||||
border_width = 3;
|
||||
get_min_terminal (terminal_font, border_width,
|
||||
&min_terminal_width, &min_terminal_height);
|
||||
}
|
||||
|
||||
/* Sanity checks. */
|
||||
if (term_width > scr_width)
|
||||
term_width = scr_width;
|
||||
if (term_height > scr_height)
|
||||
term_height = scr_height;
|
||||
|
||||
if (scr_width <= (int) min_terminal_width
|
||||
|| scr_height <= (int) min_terminal_height)
|
||||
{
|
||||
/* The screen resulution is too low. Use all space, except a small border
|
||||
to show the user, that it is a window. Then center the window. */
|
||||
term_width = scr_width - 6 * border_width;
|
||||
term_height = scr_height - 6 * border_width;
|
||||
term_x = scr_x + (scr_width - term_width) / 2;
|
||||
term_y = scr_y + (scr_height - term_height) / 2;
|
||||
}
|
||||
else if (term_width < (int) min_terminal_width
|
||||
|| term_height < (int) min_terminal_height)
|
||||
{
|
||||
/* The screen resolution is big enough. Make sure, that terminal screen
|
||||
dimensions aren't less than minimal values. Then center the window. */
|
||||
term_width = (int) min_terminal_width;
|
||||
term_height = (int) min_terminal_height;
|
||||
term_x = scr_x + (scr_width - term_width) / 2;
|
||||
term_y = scr_y + (scr_height - term_height) / 2;
|
||||
}
|
||||
|
||||
/* At this point w and h are satisfying. */
|
||||
if (term_x + term_width > scr_width)
|
||||
term_x = scr_width - term_width;
|
||||
if (term_y + term_height > scr_height)
|
||||
term_y = scr_height - term_height;
|
||||
|
||||
/* Write down corrected data. */
|
||||
view->terminal_rect.x = (unsigned int) term_x;
|
||||
view->terminal_rect.y = (unsigned int) term_y;
|
||||
view->terminal_rect.width = (unsigned int) term_width;
|
||||
view->terminal_rect.height = (unsigned int) term_height;
|
||||
view->terminal_border = border_width;
|
||||
|
||||
view->need_to_check_sanity = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
init_terminal (grub_gfxmenu_view_t view)
|
||||
{
|
||||
grub_font_t terminal_font;
|
||||
|
||||
terminal_font = grub_font_get (view->terminal_font_name);
|
||||
if (!terminal_font)
|
||||
{
|
||||
grub_error (GRUB_ERR_BAD_FONT, "no font loaded");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Check that terminal window size and position are sane. */
|
||||
terminal_sanity_check (view);
|
||||
|
||||
term_view = view;
|
||||
|
||||
/* Note: currently there is no API for changing the gfxterm font
|
||||
on the fly, so whatever font the initially loaded theme specifies
|
||||
will be permanent. */
|
||||
grub_gfxterm_set_window (GRUB_VIDEO_RENDER_TARGET_DISPLAY,
|
||||
view->terminal_rect.x,
|
||||
view->terminal_rect.y,
|
||||
view->terminal_rect.width,
|
||||
view->terminal_rect.height,
|
||||
view->double_repaint,
|
||||
terminal_font,
|
||||
view->terminal_border);
|
||||
grub_gfxterm_decorator_hook = grub_gfxmenu_draw_terminal_box;
|
||||
}
|
||||
|
||||
static void
|
||||
init_background (grub_gfxmenu_view_t view)
|
||||
{
|
||||
if (view->scaled_desktop_image || (!view->raw_desktop_image))
|
||||
return;
|
||||
|
||||
struct grub_video_bitmap *scaled_bitmap;
|
||||
if (view->desktop_image_scale_method ==
|
||||
GRUB_VIDEO_BITMAP_SELECTION_METHOD_STRETCH)
|
||||
grub_video_bitmap_create_scaled (&scaled_bitmap,
|
||||
view->screen.width,
|
||||
view->screen.height,
|
||||
view->raw_desktop_image,
|
||||
GRUB_VIDEO_BITMAP_SCALE_METHOD_BEST);
|
||||
else
|
||||
grub_video_bitmap_scale_proportional (&scaled_bitmap,
|
||||
view->screen.width,
|
||||
view->screen.height,
|
||||
view->raw_desktop_image,
|
||||
GRUB_VIDEO_BITMAP_SCALE_METHOD_BEST,
|
||||
view->desktop_image_scale_method,
|
||||
view->desktop_image_v_align,
|
||||
view->desktop_image_h_align);
|
||||
if (! scaled_bitmap)
|
||||
return;
|
||||
view->scaled_desktop_image = scaled_bitmap;
|
||||
|
||||
}
|
||||
|
||||
/* FIXME: previously notifications were displayed in special case.
|
||||
Is it necessary?
|
||||
*/
|
||||
#if 0
|
||||
/* Sets MESSAGE as the progress message for the view.
|
||||
MESSAGE can be 0, in which case no message is displayed. */
|
||||
static void
|
||||
set_progress_message (grub_gfxmenu_view_t view, const char *message)
|
||||
{
|
||||
grub_free (view->progress_message_text);
|
||||
if (message)
|
||||
view->progress_message_text = grub_strdup (message);
|
||||
else
|
||||
view->progress_message_text = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
notify_booting (grub_menu_entry_t entry, void *userdata)
|
||||
{
|
||||
grub_gfxmenu_view_t view = (grub_gfxmenu_view_t) userdata;
|
||||
|
||||
char *s = grub_malloc (100 + grub_strlen (entry->title));
|
||||
if (!s)
|
||||
return;
|
||||
|
||||
grub_sprintf (s, "Booting '%s'", entry->title);
|
||||
set_progress_message (view, s);
|
||||
grub_free (s);
|
||||
grub_gfxmenu_view_redraw (view, &view->progress_message_frame);
|
||||
grub_video_swap_buffers ();
|
||||
if (view->double_repaint)
|
||||
grub_gfxmenu_view_redraw (view, &view->progress_message_frame);
|
||||
}
|
||||
|
||||
static void
|
||||
notify_fallback (grub_menu_entry_t entry, void *userdata)
|
||||
{
|
||||
grub_gfxmenu_view_t view = (grub_gfxmenu_view_t) userdata;
|
||||
|
||||
char *s = grub_malloc (100 + grub_strlen (entry->title));
|
||||
if (!s)
|
||||
return;
|
||||
|
||||
grub_sprintf (s, "Falling back to '%s'", entry->title);
|
||||
set_progress_message (view, s);
|
||||
grub_free (s);
|
||||
grub_gfxmenu_view_redraw (view, &view->progress_message_frame);
|
||||
grub_video_swap_buffers ();
|
||||
if (view->double_repaint)
|
||||
grub_gfxmenu_view_redraw (view, &view->progress_message_frame);
|
||||
}
|
||||
|
||||
static void
|
||||
notify_execution_failure (void *userdata __attribute__ ((unused)))
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
static struct grub_menu_execute_callback execute_callback =
|
||||
{
|
||||
.notify_booting = notify_booting,
|
||||
.notify_fallback = notify_fallback,
|
||||
.notify_failure = notify_execution_failure
|
||||
};
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user