* Re: [PATCH] 1/5 Multiple fallback entries
2009-01-31 21:08 ` Vesa Jääskeläinen
@ 2009-02-05 17:40 ` Colin D Bennett
2009-02-13 20:08 ` Colin D Bennett
0 siblings, 1 reply; 4+ messages in thread
From: Colin D Bennett @ 2009-02-05 17:40 UTC (permalink / raw)
To: The development of GRUB 2
[-- Attachment #1.1: Type: text/plain, Size: 2324 bytes --]
Here is an updated patch based on Vesa's feedback. I will commit it in
a few days if no one has any objections.
This patch is against GRUB trunk revision 1973.
On Sat, 31 Jan 2009
23:08:23 +0200 Vesa Jääskeläinen <chaac@nic.fi> wrote:
> What do you think if all text menu related would be moved to own file,
> like menu_text.c or so ? I think it will cleanup code nicely...
Agreed. It has been done.
> Usually pointer to userdata is last argument in list. Please use same
> term for it as in grub_menu_execute_with_fallback (you are free to pick
> new name if you see that it fits better).
The ‘userdata’ argument has been moved to the end of the argument list.
> > +/* Get the first entry number from the variable NAME, which is a
> > + space-separated list of nonnegative integers. The entry number which
> > + is returned is stripped from the value of NAME. If no entry number can
> > + be found, returns -1. */
>
> We use term environment variable...
Fixed.
> > +
> > +/* Callbacks for grub_menu_execute_with_fallback() for the text menu. */
> > +
>
> If you move these to new file, please replace this comment with new
> comments for every function.
Done.
> > +static void
> > +notify_booting (void *userdata __attribute__((unused)),
> > + grub_menu_entry_t entry)
> > +{
> > + grub_printf (" Booting \'%s\'\n\n", entry->title);
> > +}
> > +
> > +static void
> > +notify_fallback (void *userdata __attribute__((unused)),
> > + grub_menu_entry_t entry)
> > +{
> > + grub_printf ("\n Falling back to \'%s\'\n\n", entry->title);
> > + grub_millisleep (2000);
>
> I think this delay should be generic part of the implementation and not
> specific to text menu. Or alternatively it needs to be documented that
> fallback callback function is supposed to wait for 2 secs...
I just added a comment documenting the fact that the implementation of
the callback should delay at least 2 sec before returning so that the
user can see the message. I didn't just put the delay in the generic
code because I thought the graphical menu, for instance, might want to
do something during the delay like doing animation or something, or
providing an OK button to dismiss the message before the delay has
elapsed.
Regards,
Colin
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1.2: 01_multiple-fallback.patch --]
[-- Type: text/x-patch, Size: 43139 bytes --]
=== modified file 'ChangeLog'
--- ChangeLog 2009-02-04 10:52:25 +0000
+++ ChangeLog 2009-02-05 17:23:08 +0000
@@ -1,3 +1,66 @@
+2009-02-05 Colin D Bennett <colin@gibibit.com>
+
+ Support multiple fallback entries, and provide an API to support
+ executing default+fallback menu entries. Renamed the `terminal' menu
+ viewer to `text'.
+
+ * include/grub/normal.h (grub_normal_text_menu_viewer): New global
+ variable declaration.
+ (grub_menu_execute_callback): New structure declaration.
+ (grub_menu_execute_callback_t): New typedef.
+ (grub_menu_execute_with_fallback): New function declaration.
+ (grub_menu_get_timeout): Likewise.
+ (grub_menu_set_timeout): Likewise.
+
+ * normal/main.c (GRUB_MOD_INIT(normal)): Refer to new variable name.
+
+ * normal/menu.c (grub_wait_after_message): Moved to
+ `normal/menu_text.c'.
+ (draw_border): Likewise.
+ (print_message): Likewise.
+ (print_entry): Likewise.
+ (print_entries): Likewise.
+ (grub_menu_init_page): Likewise.
+ (get_entry_number): Likewise.
+ (print_timeout): Likewise.
+ (run_menu): Likewise.
+ (grub_menu_execute_entry): Likewise.
+ (show_text_menu): Likewise.
+ (get_and_remove_first_entry_number): New function.
+ (grub_menu_execute_with_fallback): Likewise.
+ (get_entry): Renamed to ...
+ (grub_menu_get_entry): .. this and made it global.
+ (get_timeout): Renamed to ...
+ (grub_menu_get_timeout): ... this and made it global.
+ (set_timeout): Renamed to ...
+ (grub_menu_set_timeout): ... this and made it global.
+ (grub_normal_terminal_menu_viewer): Renamed to ...
+ (grub_normal_text_menu_viewer): ... this.
+
+ * normal/menu_text.c: New file. Extracted text-menu-specific code
+ from normal/menu.c.
+
+ * conf/i386-coreboot.rmk (grub_emu_SOURCES): Add `normal/menu_text.c'.
+ (normal_mod_SOURCES): Likewise.
+
+ * conf/i386-efi.rmk (grub_emu_SOURCES): Likewise.
+ (normal_mod_SOURCES): Likewise.
+
+ * conf/i386-ieee1275.rmk (grub_emu_SOURCES): Likewise.
+ (normal_mod_SOURCES): Likewise.
+
+ * conf/i386-pc.rmk, (grub_emu_SOURCES): Likewise.
+ (normal_mod_SOURCES): Likewise.
+
+ * conf/powerpc-ieee1275.rmk (grub_emu_SOURCES): Likewise.
+ (normal_mod_SOURCES): Likewise.
+
+ * conf/sparc64-ieee1275.rmk (grub_emu_SOURCES): Likewise.
+ (normal_mod_SOURCES): Likewise.
+
+ * conf/x86_64-efi.rmk (grub_emu_SOURCES): Likewise.
+ (normal_mod_SOURCES): Likewise.
+
2009-02-04 Felix Zielcke <fzielcke@z-51.de>
util/getroot.c (grub_util_get_grub_dev): Add support for /dev/mdNpN and
=== modified file 'conf/i386-coreboot.rmk'
--- conf/i386-coreboot.rmk 2009-02-03 13:22:26 +0000
+++ conf/i386-coreboot.rmk 2009-02-05 17:22:49 +0000
@@ -75,7 +75,7 @@
kern/loader.c kern/main.c kern/misc.c kern/parser.c \
grub_script.tab.c kern/partition.c kern/rescue.c kern/term.c \
normal/arg.c normal/cmdline.c normal/command.c normal/function.c\
- normal/completion.c normal/main.c \
+ normal/completion.c normal/main.c normal/menu_text.c \
normal/menu.c normal/menu_entry.c normal/menu_viewer.c \
normal/misc.c normal/script.c \
normal/color.c \
@@ -123,6 +123,7 @@
normal_mod_SOURCES = normal/arg.c normal/cmdline.c normal/command.c \
normal/completion.c normal/execute.c \
normal/function.c normal/lexer.c normal/main.c normal/menu.c \
+ normal/menu_text.c \
normal/color.c \
normal/menu_viewer.c normal/menu_entry.c \
normal/misc.c grub_script.tab.c \
=== modified file 'conf/i386-efi.rmk'
--- conf/i386-efi.rmk 2009-02-03 13:22:26 +0000
+++ conf/i386-efi.rmk 2009-02-05 17:22:49 +0000
@@ -54,6 +54,7 @@
normal/arg.c normal/cmdline.c normal/command.c normal/function.c\
normal/completion.c normal/context.c normal/main.c \
normal/menu.c normal/menu_entry.c normal/menu_viewer.c \
+ normal/menu_text.c \
normal/misc.c normal/script.c \
normal/color.c \
partmap/amiga.c partmap/apple.c partmap/pc.c partmap/sun.c \
@@ -120,6 +121,7 @@
normal_mod_SOURCES = normal/arg.c normal/cmdline.c normal/command.c \
normal/completion.c normal/execute.c \
normal/function.c normal/lexer.c normal/main.c normal/menu.c \
+ normal/menu_text.c \
normal/color.c \
normal/menu_viewer.c normal/menu_entry.c \
normal/misc.c grub_script.tab.c \
=== modified file 'conf/i386-ieee1275.rmk'
--- conf/i386-ieee1275.rmk 2009-02-03 13:22:26 +0000
+++ conf/i386-ieee1275.rmk 2009-02-05 17:22:49 +0000
@@ -74,7 +74,7 @@
kern/loader.c kern/main.c kern/misc.c kern/parser.c \
grub_script.tab.c kern/partition.c kern/rescue.c kern/term.c \
normal/arg.c normal/cmdline.c normal/command.c normal/function.c\
- normal/completion.c normal/main.c \
+ normal/completion.c normal/main.c normal/menu_text.c \
normal/menu.c normal/menu_entry.c normal/menu_viewer.c \
normal/misc.c normal/script.c \
normal/color.c \
@@ -113,6 +113,7 @@
normal_mod_SOURCES = normal/arg.c normal/cmdline.c normal/command.c \
normal/completion.c normal/execute.c \
normal/function.c normal/lexer.c normal/main.c normal/menu.c \
+ normal/menu_text.c \
normal/color.c \
normal/menu_viewer.c normal/menu_entry.c \
normal/misc.c grub_script.tab.c \
=== modified file 'conf/i386-pc.rmk'
--- conf/i386-pc.rmk 2009-02-03 13:22:26 +0000
+++ conf/i386-pc.rmk 2009-02-05 17:22:49 +0000
@@ -130,6 +130,7 @@
normal/arg.c normal/cmdline.c normal/command.c normal/function.c\
normal/completion.c normal/main.c normal/color.c \
normal/menu.c normal/menu_entry.c normal/menu_viewer.c \
+ normal/menu_text.c \
normal/misc.c normal/script.c \
partmap/amiga.c partmap/apple.c partmap/pc.c partmap/sun.c \
partmap/acorn.c partmap/gpt.c \
@@ -203,6 +204,7 @@
normal_mod_SOURCES = normal/arg.c normal/cmdline.c normal/command.c \
normal/completion.c normal/execute.c \
normal/function.c normal/lexer.c normal/main.c normal/menu.c \
+ normal/menu_text.c \
normal/color.c \
normal/menu_viewer.c normal/menu_entry.c \
normal/misc.c grub_script.tab.c \
=== modified file 'conf/powerpc-ieee1275.rmk'
--- conf/powerpc-ieee1275.rmk 2009-02-03 13:22:26 +0000
+++ conf/powerpc-ieee1275.rmk 2009-02-05 17:22:49 +0000
@@ -58,6 +58,7 @@
normal/arg.c normal/cmdline.c normal/command.c \
normal/completion.c normal/execute.c \
normal/function.c normal/lexer.c normal/main.c normal/menu.c \
+ normal/menu_text.c \
normal/menu_entry.c normal/menu_viewer.c normal/misc.c \
normal/script.c \
normal/color.c \
@@ -133,6 +134,7 @@
normal_mod_SOURCES = normal/arg.c normal/cmdline.c normal/command.c \
normal/completion.c normal/execute.c \
normal/function.c normal/lexer.c normal/main.c normal/menu.c \
+ normal/menu_text.c \
normal/color.c \
normal/menu_viewer.c normal/menu_entry.c \
normal/misc.c grub_script.tab.c \
=== modified file 'conf/sparc64-ieee1275.rmk'
--- conf/sparc64-ieee1275.rmk 2009-02-03 13:34:52 +0000
+++ conf/sparc64-ieee1275.rmk 2009-02-05 17:22:49 +0000
@@ -59,6 +59,7 @@
# normal/completion.c normal/context.c normal/execute.c \
# normal/function.c normal/lexer.c \
# normal/main.c normal/menu.c normal/menu_entry.c \
+# normal/menu_text.c \
# normal/menu_viewer.c normal/misc.c \
# partmap/amiga.c partmap/apple.c partmap/pc.c partmap/sun.c \
# partmap/acorn.c \
@@ -166,6 +167,7 @@
normal_mod_SOURCES = normal/arg.c normal/cmdline.c normal/command.c \
normal/completion.c normal/execute.c \
normal/function.c normal/lexer.c normal/main.c normal/menu.c \
+ normal/menu_text.c \
normal/color.c \
normal/menu_viewer.c normal/menu_entry.c \
normal/misc.c grub_script.tab.c \
=== modified file 'conf/x86_64-efi.rmk'
--- conf/x86_64-efi.rmk 2009-02-03 13:22:26 +0000
+++ conf/x86_64-efi.rmk 2009-02-05 17:22:49 +0000
@@ -56,6 +56,7 @@
normal/arg.c normal/cmdline.c normal/command.c normal/function.c\
normal/completion.c normal/context.c normal/main.c \
normal/menu.c normal/menu_entry.c normal/menu_viewer.c \
+ normal/menu_text.c \
normal/misc.c normal/script.c \
normal/color.c \
partmap/amiga.c partmap/apple.c partmap/pc.c partmap/sun.c \
@@ -122,6 +123,7 @@
normal_mod_SOURCES = normal/arg.c normal/cmdline.c normal/command.c \
normal/completion.c normal/execute.c \
normal/function.c normal/lexer.c normal/main.c normal/menu.c \
+ normal/menu_text.c \
normal/color.c \
normal/menu_viewer.c normal/menu_entry.c \
normal/misc.c grub_script.tab.c \
=== modified file 'include/grub/normal.h'
--- include/grub/normal.h 2009-01-31 09:15:43 +0000
+++ include/grub/normal.h 2009-02-05 17:22:49 +0000
@@ -79,7 +79,7 @@
/* The name of a module. Used for auto-loading. */
char *module_name;
-
+
/* The next element. */
struct grub_command *next;
};
@@ -96,12 +96,38 @@
/* To exit from the normal mode. */
extern grub_jmp_buf grub_exit_env;
-extern struct grub_menu_viewer grub_normal_terminal_menu_viewer;
+extern struct grub_menu_viewer grub_normal_text_menu_viewer;
+
+/* Callback structure menu viewers can use to provide user feedback when
+ default entries are executed, possibly including fallback entries. */
+typedef struct grub_menu_execute_callback
+{
+ /* Called immediately before ENTRY is booted. */
+ void (*notify_booting) (grub_menu_entry_t entry, void *userdata);
+
+ /* Called when executing one entry has failed, and another entry, ENTRY, will
+ be executed as a fallback. The implementation of this function should
+ delay for a period of at least 2 seconds before returning in order to
+ allow the user time to read the information before it can be lost by
+ executing ENTRY. */
+ void (*notify_fallback) (grub_menu_entry_t entry, void *userdata);
+
+ /* Called when an entry has failed to execute and there is no remaining
+ fallback entry to attempt. */
+ void (*notify_failure) (void *userdata);
+}
+*grub_menu_execute_callback_t;
void grub_enter_normal_mode (const char *config);
void grub_normal_execute (const char *config, int nested);
+void grub_menu_execute_with_fallback (grub_menu_t menu,
+ grub_menu_entry_t entry,
+ grub_menu_execute_callback_t callback,
+ void *callback_data);
void grub_menu_entry_run (grub_menu_entry_t entry);
void grub_menu_execute_entry(grub_menu_entry_t entry);
+int grub_menu_get_timeout (void);
+void grub_menu_set_timeout (int timeout);
void grub_cmdline_run (int nested);
int grub_cmdline_get (const char *prompt, char cmdline[], unsigned max_len,
int echo_char, int readline);
=== modified file 'normal/main.c'
--- normal/main.c 2009-01-31 09:15:43 +0000
+++ normal/main.c 2009-02-05 17:22:49 +0000
@@ -620,7 +620,7 @@
if (mod)
grub_dl_ref (mod);
- grub_menu_viewer_register (&grub_normal_terminal_menu_viewer);
+ grub_menu_viewer_register (&grub_normal_text_menu_viewer);
grub_set_history (GRUB_DEFAULT_HISTORY_SIZE);
=== modified file 'normal/menu.c'
--- normal/menu.c 2009-01-31 09:15:43 +0000
+++ normal/menu.c 2009-02-05 17:22:49 +0000
@@ -1,3 +1,4 @@
+/* menu.c - General supporting functionality for menus. */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2003,2004,2005,2006,2007,2008,2009 Free Software Foundation, Inc.
@@ -17,7 +18,6 @@
*/
#include <grub/normal.h>
-#include <grub/term.h>
#include <grub/misc.h>
#include <grub/loader.h>
#include <grub/mm.h>
@@ -26,83 +26,9 @@
#include <grub/script.h>
#include <grub/menu_viewer.h>
-static grub_uint8_t grub_color_menu_normal;
-static grub_uint8_t grub_color_menu_highlight;
-
-/* Wait until the user pushes any key so that the user
- can see what happened. */
-void
-grub_wait_after_message (void)
-{
- grub_printf ("\nPress any key to continue...");
- (void) grub_getkey ();
-}
-
-static void
-draw_border (void)
-{
- unsigned i;
-
- grub_setcolorstate (GRUB_TERM_COLOR_NORMAL);
-
- grub_gotoxy (GRUB_TERM_MARGIN, GRUB_TERM_TOP_BORDER_Y);
- grub_putcode (GRUB_TERM_DISP_UL);
- for (i = 0; i < (unsigned) GRUB_TERM_BORDER_WIDTH - 2; i++)
- grub_putcode (GRUB_TERM_DISP_HLINE);
- grub_putcode (GRUB_TERM_DISP_UR);
-
- for (i = 0; i < (unsigned) GRUB_TERM_NUM_ENTRIES; i++)
- {
- grub_gotoxy (GRUB_TERM_MARGIN, GRUB_TERM_TOP_BORDER_Y + i + 1);
- grub_putcode (GRUB_TERM_DISP_VLINE);
- grub_gotoxy (GRUB_TERM_MARGIN + GRUB_TERM_BORDER_WIDTH - 1,
- GRUB_TERM_TOP_BORDER_Y + i + 1);
- grub_putcode (GRUB_TERM_DISP_VLINE);
- }
-
- grub_gotoxy (GRUB_TERM_MARGIN,
- GRUB_TERM_TOP_BORDER_Y + GRUB_TERM_NUM_ENTRIES + 1);
- grub_putcode (GRUB_TERM_DISP_LL);
- for (i = 0; i < (unsigned) GRUB_TERM_BORDER_WIDTH - 2; i++)
- grub_putcode (GRUB_TERM_DISP_HLINE);
- grub_putcode (GRUB_TERM_DISP_LR);
-
- grub_setcolorstate (GRUB_TERM_COLOR_NORMAL);
-
- grub_gotoxy (GRUB_TERM_MARGIN,
- (GRUB_TERM_TOP_BORDER_Y + GRUB_TERM_NUM_ENTRIES
- + GRUB_TERM_MARGIN + 1));
-}
-
-static void
-print_message (int nested, int edit)
-{
- grub_setcolorstate (GRUB_TERM_COLOR_NORMAL);
-
- if (edit)
- {
- grub_printf ("\n\
- Minimum Emacs-like screen editing is supported. TAB lists\n\
- completions. Press Ctrl-x to boot, Ctrl-c for a command-line\n\
- or ESC to return menu.");
- }
- else
- {
- grub_printf ("\n\
- Use the %C and %C keys to select which entry is highlighted.\n",
- (grub_uint32_t) GRUB_TERM_DISP_UP, (grub_uint32_t) GRUB_TERM_DISP_DOWN);
- grub_printf ("\
- Press enter to boot the selected OS, \'e\' to edit the\n\
- commands before booting or \'c\' for a command-line.");
- if (nested)
- grub_printf ("\n\
- ESC to return previous menu.");
- }
-
-}
-
-static grub_menu_entry_t
-get_entry (grub_menu_t menu, int no)
+/* Get a menu entry by its index in the entry list. */
+grub_menu_entry_t
+grub_menu_get_entry (grub_menu_t menu, int no)
{
grub_menu_entry_t e;
@@ -112,140 +38,10 @@
return e;
}
-static void
-print_entry (int y, int highlight, grub_menu_entry_t entry)
-{
- int x;
- const char *title;
- grub_size_t title_len;
- grub_ssize_t len;
- grub_uint32_t *unicode_title;
- grub_ssize_t i;
- grub_uint8_t old_color_normal, old_color_highlight;
-
- title = entry ? entry->title : "";
- title_len = grub_strlen (title);
- unicode_title = grub_malloc (title_len * sizeof (*unicode_title));
- if (! unicode_title)
- /* XXX How to show this error? */
- return;
-
- len = grub_utf8_to_ucs4 (unicode_title, title_len,
- (grub_uint8_t *) title, -1, 0);
- if (len < 0)
- {
- /* It is an invalid sequence. */
- grub_free (unicode_title);
- return;
- }
-
- grub_getcolor (&old_color_normal, &old_color_highlight);
- grub_setcolor (grub_color_menu_normal, grub_color_menu_highlight);
- grub_setcolorstate (highlight
- ? GRUB_TERM_COLOR_HIGHLIGHT
- : GRUB_TERM_COLOR_NORMAL);
-
- grub_gotoxy (GRUB_TERM_LEFT_BORDER_X + GRUB_TERM_MARGIN, y);
-
- for (x = GRUB_TERM_LEFT_BORDER_X + GRUB_TERM_MARGIN + 1, i = 0;
- x < GRUB_TERM_LEFT_BORDER_X + GRUB_TERM_BORDER_WIDTH - GRUB_TERM_MARGIN;
- i++)
- {
- if (i < len
- && x <= (GRUB_TERM_LEFT_BORDER_X + GRUB_TERM_BORDER_WIDTH
- - GRUB_TERM_MARGIN - 1))
- {
- grub_ssize_t width;
-
- width = grub_getcharwidth (unicode_title[i]);
-
- if (x + width > (GRUB_TERM_LEFT_BORDER_X + GRUB_TERM_BORDER_WIDTH
- - GRUB_TERM_MARGIN - 1))
- grub_putcode (GRUB_TERM_DISP_RIGHT);
- else
- grub_putcode (unicode_title[i]);
-
- x += width;
- }
- else
- {
- grub_putchar (' ');
- x++;
- }
- }
- grub_setcolorstate (GRUB_TERM_COLOR_NORMAL);
- grub_putchar (' ');
-
- grub_gotoxy (GRUB_TERM_CURSOR_X, y);
-
- grub_setcolor (old_color_normal, old_color_highlight);
- grub_setcolorstate (GRUB_TERM_COLOR_NORMAL);
- grub_free (unicode_title);
-}
-
-static void
-print_entries (grub_menu_t menu, int first, int offset)
-{
- grub_menu_entry_t e;
- int i;
-
- grub_gotoxy (GRUB_TERM_LEFT_BORDER_X + GRUB_TERM_BORDER_WIDTH,
- GRUB_TERM_FIRST_ENTRY_Y);
-
- if (first)
- grub_putcode (GRUB_TERM_DISP_UP);
- else
- grub_putchar (' ');
-
- e = get_entry (menu, first);
-
- for (i = 0; i < GRUB_TERM_NUM_ENTRIES; i++)
- {
- print_entry (GRUB_TERM_FIRST_ENTRY_Y + i, offset == i, e);
- if (e)
- e = e->next;
- }
-
- grub_gotoxy (GRUB_TERM_LEFT_BORDER_X + GRUB_TERM_BORDER_WIDTH,
- GRUB_TERM_TOP_BORDER_Y + GRUB_TERM_NUM_ENTRIES);
-
- if (e)
- grub_putcode (GRUB_TERM_DISP_DOWN);
- else
- grub_putchar (' ');
-
- grub_gotoxy (GRUB_TERM_CURSOR_X, GRUB_TERM_FIRST_ENTRY_Y + offset);
-}
-
-/* Initialize the screen. If NESTED is non-zero, assume that this menu
- is run from another menu or a command-line. If EDIT is non-zero, show
- a message for the menu entry editor. */
-void
-grub_menu_init_page (int nested, int edit)
-{
- grub_uint8_t old_color_normal, old_color_highlight;
-
- grub_getcolor (&old_color_normal, &old_color_highlight);
-
- /* By default, use the same colors for the menu. */
- grub_color_menu_normal = old_color_normal;
- grub_color_menu_highlight = old_color_highlight;
-
- /* Then give user a chance to replace them. */
- grub_parse_color_name_pair (&grub_color_menu_normal, grub_env_get ("menu_color_normal"));
- grub_parse_color_name_pair (&grub_color_menu_highlight, grub_env_get ("menu_color_highlight"));
-
- grub_normal_init_page ();
- grub_setcolor (grub_color_menu_normal, grub_color_menu_highlight);
- draw_border ();
- grub_setcolor (old_color_normal, old_color_highlight);
- print_message (nested, edit);
-}
-
/* Return the current timeout. If the variable "timeout" is not set or
invalid, return -1. */
-static int
-get_timeout (void)
+int
+grub_menu_get_timeout (void)
{
char *val;
int timeout;
@@ -272,8 +68,8 @@
}
/* Set current timeout in the variable "timeout". */
-static void
-set_timeout (int timeout)
+void
+grub_menu_set_timeout (int timeout)
{
/* Ignore TIMEOUT if it is zero, because it will be unset really soon. */
if (timeout > 0)
@@ -285,11 +81,15 @@
}
}
-/* Get the entry number from the variable NAME. */
+/* Get the first entry number from the value of the environment variable NAME,
+ which is a space-separated list of nonnegative integers. The entry number
+ which is returned is stripped from the value of NAME. If no entry number
+ can be found, -1 is returned. */
static int
-get_entry_number (const char *name)
+get_and_remove_first_entry_number (const char *name)
{
char *val;
+ char *tail;
int entry;
val = grub_env_get (name);
@@ -298,10 +98,18 @@
grub_error_push ();
- entry = (int) grub_strtoul (val, 0, 0);
+ entry = (int) grub_strtoul (val, &tail, 0);
- if (grub_errno != GRUB_ERR_NONE)
- {
+ if (grub_errno == GRUB_ERR_NONE)
+ {
+ /* Skip whitespace to find the next digit. */
+ while (*tail && grub_isspace (*tail))
+ tail++;
+ grub_env_set (name, tail);
+ }
+ else
+ {
+ grub_env_unset (name);
grub_errno = GRUB_ERR_NONE;
entry = -1;
}
@@ -311,245 +119,6 @@
return entry;
}
-static void
-print_timeout (int timeout, int offset, int second_stage)
-{
- /* NOTE: Do not remove the trailing space characters.
- They are required to clear the line. */
- char *msg = " The highlighted entry will be booted automatically in %ds. ";
- char *msg_end = grub_strchr (msg, '%');
-
- grub_gotoxy (second_stage ? (msg_end - msg) : 0, GRUB_TERM_HEIGHT - 3);
- grub_printf (second_stage ? msg_end : msg, timeout);
- grub_gotoxy (GRUB_TERM_CURSOR_X, GRUB_TERM_FIRST_ENTRY_Y + offset);
- grub_refresh ();
-};
-
-static int
-run_menu (grub_menu_t menu, int nested)
-{
- int first, offset;
- grub_uint64_t saved_time;
- int default_entry;
- int timeout;
-
- first = 0;
-
- default_entry = get_entry_number ("default");
-
- /* If DEFAULT_ENTRY is not within the menu entries, fall back to
- the first entry. */
- if (default_entry < 0 || default_entry >= menu->size)
- default_entry = 0;
-
- /* If timeout is 0, drawing is pointless (and ugly). */
- if (get_timeout () == 0)
- return default_entry;
-
- offset = default_entry;
- if (offset > GRUB_TERM_NUM_ENTRIES - 1)
- {
- first = offset - (GRUB_TERM_NUM_ENTRIES - 1);
- offset = GRUB_TERM_NUM_ENTRIES - 1;
- }
-
- /* Initialize the time. */
- saved_time = grub_get_time_ms ();
-
- refresh:
- grub_setcursor (0);
- grub_menu_init_page (nested, 0);
- print_entries (menu, first, offset);
- grub_refresh ();
-
- timeout = get_timeout ();
-
- if (timeout > 0)
- print_timeout (timeout, offset, 0);
-
- while (1)
- {
- int c;
- timeout = get_timeout ();
-
- if (timeout > 0)
- {
- grub_uint64_t current_time;
-
- current_time = grub_get_time_ms ();
- if (current_time - saved_time >= 1000)
- {
- timeout--;
- set_timeout (timeout);
- saved_time = current_time;
- print_timeout (timeout, offset, 1);
- }
- }
-
- if (timeout == 0)
- {
- grub_env_unset ("timeout");
- return default_entry;
- }
-
- if (grub_checkkey () >= 0 || timeout < 0)
- {
- c = GRUB_TERM_ASCII_CHAR (grub_getkey ());
-
- if (timeout >= 0)
- {
- grub_gotoxy (0, GRUB_TERM_HEIGHT - 3);
- grub_printf ("\
- ");
- grub_env_unset ("timeout");
- grub_env_unset ("fallback");
- grub_gotoxy (GRUB_TERM_CURSOR_X, GRUB_TERM_FIRST_ENTRY_Y + offset);
- }
-
- switch (c)
- {
- case GRUB_TERM_HOME:
- first = 0;
- offset = 0;
- print_entries (menu, first, offset);
- break;
-
- case GRUB_TERM_END:
- offset = menu->size - 1;
- if (offset > GRUB_TERM_NUM_ENTRIES - 1)
- {
- first = offset - (GRUB_TERM_NUM_ENTRIES - 1);
- offset = GRUB_TERM_NUM_ENTRIES - 1;
- }
- print_entries (menu, first, offset);
- break;
-
- case GRUB_TERM_UP:
- case '^':
- if (offset > 0)
- {
- print_entry (GRUB_TERM_FIRST_ENTRY_Y + offset, 0,
- get_entry (menu, first + offset));
- offset--;
- print_entry (GRUB_TERM_FIRST_ENTRY_Y + offset, 1,
- get_entry (menu, first + offset));
- }
- else if (first > 0)
- {
- first--;
- print_entries (menu, first, offset);
- }
- break;
-
- case GRUB_TERM_DOWN:
- case 'v':
- if (menu->size > first + offset + 1)
- {
- if (offset < GRUB_TERM_NUM_ENTRIES - 1)
- {
- print_entry (GRUB_TERM_FIRST_ENTRY_Y + offset, 0,
- get_entry (menu, first + offset));
- offset++;
- print_entry (GRUB_TERM_FIRST_ENTRY_Y + offset, 1,
- get_entry (menu, first + offset));
- }
- else
- {
- first++;
- print_entries (menu, first, offset);
- }
- }
- break;
-
- case GRUB_TERM_PPAGE:
- if (first == 0)
- {
- offset = 0;
- }
- else
- {
- first -= GRUB_TERM_NUM_ENTRIES;
-
- if (first < 0)
- {
- offset += first;
- first = 0;
- }
- }
- print_entries (menu, first, offset);
- break;
-
- case GRUB_TERM_NPAGE:
- if (offset == 0)
- {
- offset += GRUB_TERM_NUM_ENTRIES - 1;
- if (first + offset >= menu->size)
- {
- offset = menu->size - first - 1;
- }
- }
- else
- {
- first += GRUB_TERM_NUM_ENTRIES;
-
- if (first + offset >= menu->size)
- {
- first -= GRUB_TERM_NUM_ENTRIES;
- offset += GRUB_TERM_NUM_ENTRIES;
-
- if (offset > menu->size - 1 ||
- offset > GRUB_TERM_NUM_ENTRIES - 1)
- {
- offset = menu->size - first - 1;
- }
- if (offset > GRUB_TERM_NUM_ENTRIES)
- {
- first += offset - GRUB_TERM_NUM_ENTRIES + 1;
- offset = GRUB_TERM_NUM_ENTRIES - 1;
- }
- }
- }
- print_entries (menu, first, offset);
- break;
-
- case '\n':
- case '\r':
- case 6:
- grub_setcursor (1);
- return first + offset;
-
- case '\e':
- if (nested)
- {
- grub_setcursor (1);
- return -1;
- }
- break;
-
- case 'c':
- grub_cmdline_run (1);
- goto refresh;
-
- case 'e':
- {
- grub_menu_entry_t e = get_entry (menu, first + offset);
- if (e)
- grub_menu_entry_run (e);
- }
- goto refresh;
-
- default:
- break;
- }
-
- grub_refresh ();
- }
- }
-
- /* Never reach here. */
- return -1;
-}
-
/* Run a menu entry. */
void
grub_menu_execute_entry(grub_menu_entry_t entry)
@@ -561,58 +130,34 @@
grub_command_execute ("boot", 0);
}
-static grub_err_t
-show_text_menu (grub_menu_t menu, int nested)
+/* Execute ENTRY from the menu MENU, falling back to entries specified
+ in the environment variable "fallback" if it fails. CALLBACK is a
+ pointer to a struct of function pointers which are used to allow the
+ caller provide feedback to the user. */
+void
+grub_menu_execute_with_fallback (grub_menu_t menu,
+ grub_menu_entry_t entry,
+ grub_menu_execute_callback_t callback,
+ void *callback_data)
{
- while (1)
+ int fallback_entry;
+
+ callback->notify_booting (entry, callback_data);
+
+ grub_menu_execute_entry (entry);
+
+ /* Deal with fallback entries. */
+ while ((fallback_entry = get_and_remove_first_entry_number ("fallback"))
+ >= 0)
{
- int boot_entry;
- grub_menu_entry_t e;
- int fallback_entry;
-
- boot_entry = run_menu (menu, nested);
- if (boot_entry < 0)
- break;
-
- e = get_entry (menu, boot_entry);
- if (! e)
- continue; /* Menu is empty. */
-
- grub_cls ();
- grub_setcursor (1);
-
- grub_printf (" Booting \'%s\'\n\n", e->title);
-
- grub_menu_execute_entry (e);
-
- /* Deal with a fallback entry. */
- /* FIXME: Multiple fallback entries like GRUB Legacy. */
- fallback_entry = get_entry_number ("fallback");
- if (fallback_entry >= 0)
- {
- grub_print_error ();
- grub_errno = GRUB_ERR_NONE;
-
- e = get_entry (menu, fallback_entry);
- grub_env_unset ("fallback");
- grub_printf ("\n Falling back to \'%s\'\n\n", e->title);
- grub_menu_execute_entry (e);
- }
-
- if (grub_errno != GRUB_ERR_NONE)
- {
- grub_print_error ();
- grub_errno = GRUB_ERR_NONE;
-
- grub_wait_after_message ();
- }
+ grub_print_error ();
+ grub_errno = GRUB_ERR_NONE;
+
+ entry = grub_menu_get_entry (menu, fallback_entry);
+ callback->notify_fallback (entry, callback_data);
+ grub_menu_execute_entry (entry);
}
- return GRUB_ERR_NONE;
+ if (grub_errno != GRUB_ERR_NONE)
+ callback->notify_failure (callback_data);
}
-
-struct grub_menu_viewer grub_normal_terminal_menu_viewer =
-{
- .name = "terminal",
- .show_menu = show_text_menu
-};
=== added file 'normal/menu_text.c'
--- normal/menu_text.c 1970-01-01 00:00:00 +0000
+++ normal/menu_text.c 2009-02-05 17:22:49 +0000
@@ -0,0 +1,570 @@
+/* menu_text.c - Basic text menu implementation. */
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2003,2004,2005,2006,2007,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/normal.h>
+#include <grub/term.h>
+#include <grub/misc.h>
+#include <grub/loader.h>
+#include <grub/mm.h>
+#include <grub/time.h>
+#include <grub/env.h>
+#include <grub/script.h>
+#include <grub/menu_viewer.h>
+
+static grub_uint8_t grub_color_menu_normal;
+static grub_uint8_t grub_color_menu_highlight;
+
+/* Wait until the user pushes any key so that the user
+ can see what happened. */
+void
+grub_wait_after_message (void)
+{
+ grub_printf ("\nPress any key to continue...");
+ (void) grub_getkey ();
+}
+
+static void
+draw_border (void)
+{
+ unsigned i;
+
+ grub_setcolorstate (GRUB_TERM_COLOR_NORMAL);
+
+ grub_gotoxy (GRUB_TERM_MARGIN, GRUB_TERM_TOP_BORDER_Y);
+ grub_putcode (GRUB_TERM_DISP_UL);
+ for (i = 0; i < (unsigned) GRUB_TERM_BORDER_WIDTH - 2; i++)
+ grub_putcode (GRUB_TERM_DISP_HLINE);
+ grub_putcode (GRUB_TERM_DISP_UR);
+
+ for (i = 0; i < (unsigned) GRUB_TERM_NUM_ENTRIES; i++)
+ {
+ grub_gotoxy (GRUB_TERM_MARGIN, GRUB_TERM_TOP_BORDER_Y + i + 1);
+ grub_putcode (GRUB_TERM_DISP_VLINE);
+ grub_gotoxy (GRUB_TERM_MARGIN + GRUB_TERM_BORDER_WIDTH - 1,
+ GRUB_TERM_TOP_BORDER_Y + i + 1);
+ grub_putcode (GRUB_TERM_DISP_VLINE);
+ }
+
+ grub_gotoxy (GRUB_TERM_MARGIN,
+ GRUB_TERM_TOP_BORDER_Y + GRUB_TERM_NUM_ENTRIES + 1);
+ grub_putcode (GRUB_TERM_DISP_LL);
+ for (i = 0; i < (unsigned) GRUB_TERM_BORDER_WIDTH - 2; i++)
+ grub_putcode (GRUB_TERM_DISP_HLINE);
+ grub_putcode (GRUB_TERM_DISP_LR);
+
+ grub_setcolorstate (GRUB_TERM_COLOR_NORMAL);
+
+ grub_gotoxy (GRUB_TERM_MARGIN,
+ (GRUB_TERM_TOP_BORDER_Y + GRUB_TERM_NUM_ENTRIES
+ + GRUB_TERM_MARGIN + 1));
+}
+
+static void
+print_message (int nested, int edit)
+{
+ grub_setcolorstate (GRUB_TERM_COLOR_NORMAL);
+
+ if (edit)
+ {
+ grub_printf ("\n\
+ Minimum Emacs-like screen editing is supported. TAB lists\n\
+ completions. Press Ctrl-x to boot, Ctrl-c for a command-line\n\
+ or ESC to return menu.");
+ }
+ else
+ {
+ grub_printf ("\n\
+ Use the %C and %C keys to select which entry is highlighted.\n",
+ (grub_uint32_t) GRUB_TERM_DISP_UP, (grub_uint32_t) GRUB_TERM_DISP_DOWN);
+ grub_printf ("\
+ Press enter to boot the selected OS, \'e\' to edit the\n\
+ commands before booting or \'c\' for a command-line.");
+ if (nested)
+ grub_printf ("\n\
+ ESC to return previous menu.");
+ }
+}
+
+static void
+print_entry (int y, int highlight, grub_menu_entry_t entry)
+{
+ int x;
+ const char *title;
+ grub_size_t title_len;
+ grub_ssize_t len;
+ grub_uint32_t *unicode_title;
+ grub_ssize_t i;
+ grub_uint8_t old_color_normal, old_color_highlight;
+
+ title = entry ? entry->title : "";
+ title_len = grub_strlen (title);
+ unicode_title = grub_malloc (title_len * sizeof (*unicode_title));
+ if (! unicode_title)
+ /* XXX How to show this error? */
+ return;
+
+ len = grub_utf8_to_ucs4 (unicode_title, title_len,
+ (grub_uint8_t *) title, -1, 0);
+ if (len < 0)
+ {
+ /* It is an invalid sequence. */
+ grub_free (unicode_title);
+ return;
+ }
+
+ grub_getcolor (&old_color_normal, &old_color_highlight);
+ grub_setcolor (grub_color_menu_normal, grub_color_menu_highlight);
+ grub_setcolorstate (highlight
+ ? GRUB_TERM_COLOR_HIGHLIGHT
+ : GRUB_TERM_COLOR_NORMAL);
+
+ grub_gotoxy (GRUB_TERM_LEFT_BORDER_X + GRUB_TERM_MARGIN, y);
+
+ for (x = GRUB_TERM_LEFT_BORDER_X + GRUB_TERM_MARGIN + 1, i = 0;
+ x < GRUB_TERM_LEFT_BORDER_X + GRUB_TERM_BORDER_WIDTH - GRUB_TERM_MARGIN;
+ i++)
+ {
+ if (i < len
+ && x <= (GRUB_TERM_LEFT_BORDER_X + GRUB_TERM_BORDER_WIDTH
+ - GRUB_TERM_MARGIN - 1))
+ {
+ grub_ssize_t width;
+
+ width = grub_getcharwidth (unicode_title[i]);
+
+ if (x + width > (GRUB_TERM_LEFT_BORDER_X + GRUB_TERM_BORDER_WIDTH
+ - GRUB_TERM_MARGIN - 1))
+ grub_putcode (GRUB_TERM_DISP_RIGHT);
+ else
+ grub_putcode (unicode_title[i]);
+
+ x += width;
+ }
+ else
+ {
+ grub_putchar (' ');
+ x++;
+ }
+ }
+ grub_setcolorstate (GRUB_TERM_COLOR_NORMAL);
+ grub_putchar (' ');
+
+ grub_gotoxy (GRUB_TERM_CURSOR_X, y);
+
+ grub_setcolor (old_color_normal, old_color_highlight);
+ grub_setcolorstate (GRUB_TERM_COLOR_NORMAL);
+ grub_free (unicode_title);
+}
+
+static void
+print_entries (grub_menu_t menu, int first, int offset)
+{
+ grub_menu_entry_t e;
+ int i;
+
+ grub_gotoxy (GRUB_TERM_LEFT_BORDER_X + GRUB_TERM_BORDER_WIDTH,
+ GRUB_TERM_FIRST_ENTRY_Y);
+
+ if (first)
+ grub_putcode (GRUB_TERM_DISP_UP);
+ else
+ grub_putchar (' ');
+
+ e = grub_menu_get_entry (menu, first);
+
+ for (i = 0; i < GRUB_TERM_NUM_ENTRIES; i++)
+ {
+ print_entry (GRUB_TERM_FIRST_ENTRY_Y + i, offset == i, e);
+ if (e)
+ e = e->next;
+ }
+
+ grub_gotoxy (GRUB_TERM_LEFT_BORDER_X + GRUB_TERM_BORDER_WIDTH,
+ GRUB_TERM_TOP_BORDER_Y + GRUB_TERM_NUM_ENTRIES);
+
+ if (e)
+ grub_putcode (GRUB_TERM_DISP_DOWN);
+ else
+ grub_putchar (' ');
+
+ grub_gotoxy (GRUB_TERM_CURSOR_X, GRUB_TERM_FIRST_ENTRY_Y + offset);
+}
+
+/* Initialize the screen. If NESTED is non-zero, assume that this menu
+ is run from another menu or a command-line. If EDIT is non-zero, show
+ a message for the menu entry editor. */
+void
+grub_menu_init_page (int nested, int edit)
+{
+ grub_uint8_t old_color_normal, old_color_highlight;
+
+ grub_getcolor (&old_color_normal, &old_color_highlight);
+
+ /* By default, use the same colors for the menu. */
+ grub_color_menu_normal = old_color_normal;
+ grub_color_menu_highlight = old_color_highlight;
+
+ /* Then give user a chance to replace them. */
+ grub_parse_color_name_pair (&grub_color_menu_normal, grub_env_get ("menu_color_normal"));
+ grub_parse_color_name_pair (&grub_color_menu_highlight, grub_env_get ("menu_color_highlight"));
+
+ grub_normal_init_page ();
+ grub_setcolor (grub_color_menu_normal, grub_color_menu_highlight);
+ draw_border ();
+ grub_setcolor (old_color_normal, old_color_highlight);
+ print_message (nested, edit);
+}
+
+/* Get the entry number from the variable NAME. */
+static int
+get_entry_number (const char *name)
+{
+ char *val;
+ int entry;
+
+ val = grub_env_get (name);
+ if (! val)
+ return -1;
+
+ grub_error_push ();
+
+ entry = (int) grub_strtoul (val, 0, 0);
+
+ if (grub_errno != GRUB_ERR_NONE)
+ {
+ grub_errno = GRUB_ERR_NONE;
+ entry = -1;
+ }
+
+ grub_error_pop ();
+
+ return entry;
+}
+
+static void
+print_timeout (int timeout, int offset, int second_stage)
+{
+ /* NOTE: Do not remove the trailing space characters.
+ They are required to clear the line. */
+ char *msg = " The highlighted entry will be booted automatically in %ds. ";
+ char *msg_end = grub_strchr (msg, '%');
+
+ grub_gotoxy (second_stage ? (msg_end - msg) : 0, GRUB_TERM_HEIGHT - 3);
+ grub_printf (second_stage ? msg_end : msg, timeout);
+ grub_gotoxy (GRUB_TERM_CURSOR_X, GRUB_TERM_FIRST_ENTRY_Y + offset);
+ grub_refresh ();
+};
+
+static int
+run_menu (grub_menu_t menu, int nested)
+{
+ int first, offset;
+ grub_uint64_t saved_time;
+ int default_entry;
+ int timeout;
+
+ first = 0;
+
+ default_entry = get_entry_number ("default");
+
+ /* If DEFAULT_ENTRY is not within the menu entries, fall back to
+ the first entry. */
+ if (default_entry < 0 || default_entry >= menu->size)
+ default_entry = 0;
+
+ /* If timeout is 0, drawing is pointless (and ugly). */
+ if (grub_menu_get_timeout () == 0)
+ return default_entry;
+
+ offset = default_entry;
+ if (offset > GRUB_TERM_NUM_ENTRIES - 1)
+ {
+ first = offset - (GRUB_TERM_NUM_ENTRIES - 1);
+ offset = GRUB_TERM_NUM_ENTRIES - 1;
+ }
+
+ /* Initialize the time. */
+ saved_time = grub_get_time_ms ();
+
+ refresh:
+ grub_setcursor (0);
+ grub_menu_init_page (nested, 0);
+ print_entries (menu, first, offset);
+ grub_refresh ();
+
+ timeout = grub_menu_get_timeout ();
+
+ if (timeout > 0)
+ print_timeout (timeout, offset, 0);
+
+ while (1)
+ {
+ int c;
+ timeout = grub_menu_get_timeout ();
+
+ if (timeout > 0)
+ {
+ grub_uint64_t current_time;
+
+ current_time = grub_get_time_ms ();
+ if (current_time - saved_time >= 1000)
+ {
+ timeout--;
+ grub_menu_set_timeout (timeout);
+ saved_time = current_time;
+ print_timeout (timeout, offset, 1);
+ }
+ }
+
+ if (timeout == 0)
+ {
+ grub_env_unset ("timeout");
+ return default_entry;
+ }
+
+ if (grub_checkkey () >= 0 || timeout < 0)
+ {
+ c = GRUB_TERM_ASCII_CHAR (grub_getkey ());
+
+ if (timeout >= 0)
+ {
+ grub_gotoxy (0, GRUB_TERM_HEIGHT - 3);
+ grub_printf ("\
+ ");
+ grub_env_unset ("timeout");
+ grub_env_unset ("fallback");
+ grub_gotoxy (GRUB_TERM_CURSOR_X, GRUB_TERM_FIRST_ENTRY_Y + offset);
+ }
+
+ switch (c)
+ {
+ case GRUB_TERM_HOME:
+ first = 0;
+ offset = 0;
+ print_entries (menu, first, offset);
+ break;
+
+ case GRUB_TERM_END:
+ offset = menu->size - 1;
+ if (offset > GRUB_TERM_NUM_ENTRIES - 1)
+ {
+ first = offset - (GRUB_TERM_NUM_ENTRIES - 1);
+ offset = GRUB_TERM_NUM_ENTRIES - 1;
+ }
+ print_entries (menu, first, offset);
+ break;
+
+ case GRUB_TERM_UP:
+ case '^':
+ if (offset > 0)
+ {
+ print_entry (GRUB_TERM_FIRST_ENTRY_Y + offset, 0,
+ grub_menu_get_entry (menu, first + offset));
+ offset--;
+ print_entry (GRUB_TERM_FIRST_ENTRY_Y + offset, 1,
+ grub_menu_get_entry (menu, first + offset));
+ }
+ else if (first > 0)
+ {
+ first--;
+ print_entries (menu, first, offset);
+ }
+ break;
+
+ case GRUB_TERM_DOWN:
+ case 'v':
+ if (menu->size > first + offset + 1)
+ {
+ if (offset < GRUB_TERM_NUM_ENTRIES - 1)
+ {
+ print_entry (GRUB_TERM_FIRST_ENTRY_Y + offset, 0,
+ grub_menu_get_entry (menu, first + offset));
+ offset++;
+ print_entry (GRUB_TERM_FIRST_ENTRY_Y + offset, 1,
+ grub_menu_get_entry (menu, first + offset));
+ }
+ else
+ {
+ first++;
+ print_entries (menu, first, offset);
+ }
+ }
+ break;
+
+ case GRUB_TERM_PPAGE:
+ if (first == 0)
+ {
+ offset = 0;
+ }
+ else
+ {
+ first -= GRUB_TERM_NUM_ENTRIES;
+
+ if (first < 0)
+ {
+ offset += first;
+ first = 0;
+ }
+ }
+ print_entries (menu, first, offset);
+ break;
+
+ case GRUB_TERM_NPAGE:
+ if (offset == 0)
+ {
+ offset += GRUB_TERM_NUM_ENTRIES - 1;
+ if (first + offset >= menu->size)
+ {
+ offset = menu->size - first - 1;
+ }
+ }
+ else
+ {
+ first += GRUB_TERM_NUM_ENTRIES;
+
+ if (first + offset >= menu->size)
+ {
+ first -= GRUB_TERM_NUM_ENTRIES;
+ offset += GRUB_TERM_NUM_ENTRIES;
+
+ if (offset > menu->size - 1 ||
+ offset > GRUB_TERM_NUM_ENTRIES - 1)
+ {
+ offset = menu->size - first - 1;
+ }
+ if (offset > GRUB_TERM_NUM_ENTRIES)
+ {
+ first += offset - GRUB_TERM_NUM_ENTRIES + 1;
+ offset = GRUB_TERM_NUM_ENTRIES - 1;
+ }
+ }
+ }
+ print_entries (menu, first, offset);
+ break;
+
+ case '\n':
+ case '\r':
+ case 6:
+ grub_setcursor (1);
+ return first + offset;
+
+ case '\e':
+ if (nested)
+ {
+ grub_setcursor (1);
+ return -1;
+ }
+ break;
+
+ case 'c':
+ grub_cmdline_run (1);
+ goto refresh;
+
+ case 'e':
+ {
+ grub_menu_entry_t e = grub_menu_get_entry (menu, first + offset);
+ if (e)
+ grub_menu_entry_run (e);
+ }
+ goto refresh;
+
+ default:
+ break;
+ }
+
+ grub_refresh ();
+ }
+ }
+
+ /* Never reach here. */
+ return -1;
+}
+
+/* Callback invoked immediately before a menu entry is executed. */
+static void
+notify_booting (grub_menu_entry_t entry,
+ void *userdata __attribute__((unused)))
+{
+ grub_printf (" Booting \'%s\'\n\n", entry->title);
+}
+
+/* Callback invoked when a default menu entry executed because of a timeout
+ has failed and an attempt will be made to execute the next fallback
+ entry, ENTRY. */
+static void
+notify_fallback (grub_menu_entry_t entry,
+ void *userdata __attribute__((unused)))
+{
+ grub_printf ("\n Falling back to \'%s\'\n\n", entry->title);
+ grub_millisleep (2000);
+}
+
+/* Callback invoked when a menu entry has failed and there is no remaining
+ fallback entry to attempt. */
+static void
+notify_execution_failure (void *userdata __attribute__((unused)))
+{
+ if (grub_errno != GRUB_ERR_NONE)
+ {
+ grub_print_error ();
+ grub_errno = GRUB_ERR_NONE;
+
+ grub_wait_after_message ();
+ }
+}
+
+/* Callbacks used by the text menu to provide user feedback when menu entries
+ are executed. */
+static struct grub_menu_execute_callback execution_callback =
+{
+ .notify_booting = notify_booting,
+ .notify_fallback = notify_fallback,
+ .notify_failure = notify_execution_failure
+};
+
+static grub_err_t
+show_text_menu (grub_menu_t menu, int nested)
+{
+ while (1)
+ {
+ int boot_entry;
+ grub_menu_entry_t e;
+
+ boot_entry = run_menu (menu, nested);
+ if (boot_entry < 0)
+ break;
+
+ e = grub_menu_get_entry (menu, boot_entry);
+ if (! e)
+ continue; /* Menu is empty. */
+
+ grub_cls ();
+ grub_setcursor (1);
+
+ grub_menu_execute_with_fallback (menu, e, &execution_callback, 0);
+ }
+
+ return GRUB_ERR_NONE;
+}
+
+struct grub_menu_viewer grub_normal_text_menu_viewer =
+{
+ .name = "text",
+ .show_menu = show_text_menu
+};
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 197 bytes --]
^ permalink raw reply [flat|nested] 4+ messages in thread