# Bazaar merge directive format 2 (Bazaar 0.90) # revision_id: colin@gibibit.com-20080705175913-xmp2j688zzymz798 # target_branch: ../../repo/cdbmain # testament_sha1: f20a1f4db0c7558275043ca686fb96b6b43d1947 # timestamp: 2008-07-05 11:47:43 -0700 # source_branch: http://grub.gibibit.com/bzr/cdbmain # base_revision_id: colin@gibibit.com-20080704214036-04igfy0boo1z9489 # # Begin patch === modified file 'conf/common.rmk' --- conf/common.rmk 2008-07-03 14:12:08 +0000 +++ conf/common.rmk 2008-07-05 17:04:34 +0000 @@ -287,6 +287,7 @@ cmp.mod cat.mod help.mod font.mod search.mod \ loopback.mod fs_uuid.mod configfile.mod echo.mod \ terminfo.mod test.mod blocklist.mod hexdump.mod \ + protomenu.mod \ read.mod sleep.mod loadenv.mod # For hello.mod. @@ -374,6 +375,11 @@ hexdump_mod_CFLAGS = $(COMMON_CFLAGS) hexdump_mod_LDFLAGS = $(COMMON_LDFLAGS) +# For protomenu.mod. +protomenu_mod_SOURCES = protomenu/protomenu.c +protomenu_mod_CFLAGS = $(COMMON_CFLAGS) +protomenu_mod_LDFLAGS = $(COMMON_LDFLAGS) + # For read.mod. read_mod_SOURCES = commands/read.c read_mod_CFLAGS = $(COMMON_CFLAGS) === added directory 'protomenu' === added file 'protomenu/protomenu.c' --- protomenu/protomenu.c 1970-01-01 00:00:00 +0000 +++ protomenu/protomenu.c 2008-07-05 17:59:13 +0000 @@ -0,0 +1,277 @@ +/* protomenu.c - Prototype graphical menu: command implementation. */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2003,2007 Free Software Foundation, Inc. + * Copyright (C) 2003 NIIBE Yutaka + * + * 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 . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* A 2D rectangle type. + * This could be worth integrating into the video API if it proves useful.*/ +struct grub_video_rect +{ + /* These are signed because if there are unsigned it causes Bad Things + * to happen when arithmetic and comparisions involving signed types is + * done. Important signed types include offsets from absolute locations. */ + int x; + int y; + int width; + int height; +}; +typedef struct grub_video_rect grub_video_rect_t; + +typedef struct menu_item +{ + const char *name; + struct grub_video_bitmap *icon; + /* TODO add a command to execute. */ +} +menu_item_t; + +static const int icon_width = 48; +static const int icon_height = 48; +static grub_video_rect_t screen; +static grub_font_t title_font; +static grub_font_t item_font; +static grub_font_t status_font; +static grub_video_color_t title_color; +static grub_video_color_t item_color; +static grub_video_color_t status_color; +static grub_video_color_t status_bg_color; +static struct grub_video_bitmap *background_image; +static const char title_text[] = "GRUB 2 Boot Menu"; +static menu_item_t items[3]; +static int selected_item_index; + +static void +style_init (void) +{ + if (!(title_font = grub_font_get ("Helvetica Bold 24")) + || !(item_font = grub_font_get ("Helvetica Bold 14")) + || !(status_font = grub_font_get ("Helvetica 10"))) + return; + + title_color = grub_video_map_rgb (0, 0, 0); + item_color = grub_video_map_rgb (0, 0, 0); + status_color = grub_video_map_rgb (255, 255, 255); + status_bg_color = grub_video_map_rgba (0, 0, 0, 112); + + struct grub_video_bitmap *img; + grub_video_bitmap_load (&img, "/boot/images/bg-protomenu1.tga"); + if (grub_errno != GRUB_ERR_NONE) + return; + + grub_video_bitmap_create_scaled (&background_image, screen.width, + screen.height, img, + GRUB_VIDEO_BITMAP_SCALE_METHOD_BEST); + if (grub_errno != GRUB_ERR_NONE) + return; + grub_video_bitmap_destroy (img); + + + items[0].name = "Ubuntu 8.10"; + grub_video_bitmap_load (&img, "/boot/images/icon-ubuntu.tga"); + if (grub_errno == GRUB_ERR_NONE) + { + grub_video_bitmap_create_scaled (&items[0].icon, icon_width, + icon_height, img, + GRUB_VIDEO_BITMAP_SCALE_METHOD_BEST); + if (grub_errno != GRUB_ERR_NONE) + return; + grub_video_bitmap_destroy (img); + } + + items[1].name = "Gentoo Linux"; + grub_video_bitmap_load (&img, "/boot/images/icon-gentoo.tga"); + if (grub_errno == GRUB_ERR_NONE) + { + grub_video_bitmap_create_scaled (&items[1].icon, icon_width, + icon_height, img, + GRUB_VIDEO_BITMAP_SCALE_METHOD_BEST); + if (grub_errno != GRUB_ERR_NONE) + return; + grub_video_bitmap_destroy (img); + } + + items[2].name = "Windows Vista"; + grub_video_bitmap_load (&img, "/boot/images/icon-vista.tga"); + if (grub_errno == GRUB_ERR_NONE) + { + grub_video_bitmap_create_scaled (&items[2].icon, icon_width, + icon_height, img, + GRUB_VIDEO_BITMAP_SCALE_METHOD_BEST); + if (grub_errno != GRUB_ERR_NONE) + return; + grub_video_bitmap_destroy (img); + } +} + +static void +draw_background (void) +{ + grub_video_blit_bitmap (background_image, GRUB_VIDEO_BLIT_REPLACE, + 0, 0, 0, 0, + grub_video_bitmap_get_width (background_image), + grub_video_bitmap_get_height (background_image)); +} + +static void +draw_menu (void) +{ + /* TODO make this use pixmaps and draw a cool menu */ + + grub_video_rect_t r; + r.width = screen.width * 2 / 3; + r.height = screen.height * 1 / 2; + r.x = (screen.width - r.width) / 2; + r.y = (screen.height - r.height) / 2; + + grub_video_color_t bg = grub_video_map_rgb (255, 255, 255); + grub_video_fill_rect (bg, r.x, r.y, r.width, r.height); + + int boxpad = 6; + int icon_text_space = 4; + int item_pad = 3; + int item_vspace = 2; + + int ascent = grub_font_get_ascent (item_font); + int descent = grub_font_get_descent (item_font); + int item_top = r.y + boxpad; + int item_left = r.x + boxpad; + int item_height = 54; + unsigned i; + for (i = 0; i < sizeof (items) / sizeof (*items); i++) + { + if ((int) i == selected_item_index) + { + /* TODO use pixmap-stylized box to highlight selected item */ + grub_video_fill_rect (grub_video_map_rgb (128, 128, 255), + item_left, item_top, + r.width - 2 * boxpad, item_height); + } + + if (items[i].icon) + grub_video_blit_bitmap (items[i].icon, GRUB_VIDEO_BLIT_BLEND, + item_left, + item_top + (item_height - icon_height) / 2, + 0, 0, icon_width, icon_height); + + grub_video_draw_string (items[i].name, item_font, item_color, + item_left + icon_width + icon_text_space, + (item_top + (item_height - (ascent + descent)) + / 2 + ascent)); + + item_top += item_height + item_vspace; + } +} + +static void +draw_title (void) +{ + /* Center the title. */ + int title_width = grub_font_get_string_width (title_font, title_text); + int x = (screen.width - title_width) / 2; + int y = 40 + grub_font_get_ascent (title_font); + grub_video_draw_string (title_text, title_font, title_color, x, y); +} + +static void +draw_status (void) +{ + int descent = grub_font_get_descent (status_font); + int ascent = grub_font_get_ascent (status_font); + int vpad = 5; + int textheight = descent + ascent; + int h = 2 * vpad + textheight; + + grub_video_fill_rect (status_bg_color, 0, screen.height - h, + screen.width, screen.height - 1); + + int texty = screen.height - vpad - descent; + grub_video_draw_string ("Select an item with the arrow keys and " + "press Enter to boot.", + status_font, status_color, 30, texty); +} + +static grub_err_t +grub_cmd_protomenu (struct grub_arg_list *state __attribute__ ((unused)), + int argc __attribute__ ((unused)), + char **args __attribute__ ((unused))) +{ + if (grub_video_setup (1024, 768, GRUB_VIDEO_MODE_TYPE_RGB) != GRUB_ERR_NONE) + return grub_errno; + + grub_video_get_viewport ((unsigned *) &screen.x, + (unsigned *) &screen.y, + (unsigned *) &screen.width, + (unsigned *) &screen.height); + + style_init (); + selected_item_index = 0; + + int done = 0; + while (!done) + { + draw_background (); + draw_menu (); + draw_title (); + draw_status (); + + int c = GRUB_TERM_ASCII_CHAR (grub_getkey ()); + if (c == 'j') + { + selected_item_index++; + if (selected_item_index >= (int) (sizeof (items) / sizeof (*items))) + selected_item_index = 0; + } + else if (c == 'k') + { + selected_item_index--; + if (selected_item_index < 0) + selected_item_index = (sizeof (items) / sizeof (*items)) - 1; + } + else if (c == GRUB_TERM_ESC) + { + done = 1; + } + } + + grub_video_restore (); + return 0; +} + +GRUB_MOD_INIT (protomenu) +{ + (void) mod; /* To stop warning. */ + grub_register_command ("protomenu", + grub_cmd_protomenu, GRUB_COMMAND_FLAG_BOTH, + "protomenu", "Show graphical menu prototype", 0); +} + +GRUB_MOD_FINI (protomenu) +{ + grub_unregister_command ("protomenu"); +} # Begin bundle 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 hIa+S+AA