/* Show the menu and handle menu entry selection. Returns the menu entry index that should be executed or -1 if no entry should be executed (e.g., Esc pressed to exit a sub-menu or switching menu viewers). If the return value is not -1, then *AUTO_BOOT is nonzero iff the menu entry to be executed is a result of an automatic default selection because of the timeout. */ static int run_menu (grub_menu_t menu, int nested, int *auto_boot) { grub_uint64_t saved_time; int default_entry, current_entry; int timeout; default_entry = get_entry_number (menu, "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) { *auto_boot = 1; return default_entry; } current_entry = default_entry; /* Initialize the time. */ saved_time = grub_get_time_ms (); refresh: menu_init (current_entry, menu, nested); timeout = grub_menu_get_timeout (); if (timeout > 0) menu_print_timeout (timeout); else clear_timeout (); while (1) { int c; timeout = grub_menu_get_timeout (); if (grub_normal_exit_level) return -1; 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; menu_print_timeout (timeout); } } if (timeout == 0) { grub_env_unset ("timeout"); *auto_boot = 1; menu_fini (); return default_entry; } c = grub_getkey_noblock (); if (c != GRUB_TERM_NO_KEY) { if (timeout >= 0) { grub_env_unset ("timeout"); grub_env_unset ("fallback"); clear_timeout (); } switch (c) { case GRUB_TERM_KEY_HOME: case GRUB_TERM_CTRL | 'a': current_entry = 0; menu_set_chosen_entry (current_entry); break; case GRUB_TERM_KEY_END: case GRUB_TERM_CTRL | 'e': current_entry = menu->size - 1; menu_set_chosen_entry (current_entry); break; case GRUB_TERM_KEY_UP: case GRUB_TERM_CTRL | 'p': case '^': if (current_entry > 0) current_entry--; menu_set_chosen_entry (current_entry); break; case GRUB_TERM_CTRL | 'n': case GRUB_TERM_KEY_DOWN: case 'v': if (current_entry < menu->size - 1) current_entry++; menu_set_chosen_entry (current_entry); break; case GRUB_TERM_CTRL | 'g': case GRUB_TERM_KEY_PPAGE: if (current_entry < GRUB_MENU_PAGE_SIZE) current_entry = 0; else current_entry -= GRUB_MENU_PAGE_SIZE; menu_set_chosen_entry (current_entry); break; case GRUB_TERM_CTRL | 'c': case GRUB_TERM_KEY_NPAGE: if (current_entry + GRUB_MENU_PAGE_SIZE < menu->size) current_entry += GRUB_MENU_PAGE_SIZE; else current_entry = menu->size - 1; menu_set_chosen_entry (current_entry); break; case '\n': case '\r': case GRUB_TERM_KEY_RIGHT: case GRUB_TERM_CTRL | 'f': menu_fini (); *auto_boot = 0; return current_entry; case '\e': if (nested) { menu_fini (); return -1; } break; case 'c': menu_fini (); grub_cmdline_run (1); goto refresh; case 'e': menu_fini (); { grub_menu_entry_t e = grub_menu_get_entry (menu, current_entry); if (e) grub_menu_entry_run (e); } goto refresh; default: { grub_menu_entry_t entry; int i; for (i = 0, entry = menu->entry_list; i < menu->size; i++, entry = entry->next) if (entry->hotkey == c) { menu_fini (); *auto_boot = 0; return i; } } break; } } } /* Never reach here. */ }
/* Show the menu and handle menu entry selection. Returns the menu entry index that should be executed or -1 if no entry should be executed (e.g., Esc pressed to exit a sub-menu or switching menu viewers). If the return value is not -1, then *AUTO_BOOT is nonzero iff the menu entry to be executed is a result of an automatic default selection because of the timeout. */ static int run_menu (grub_menu_t menu, int nested, int *auto_boot) { grub_uint64_t saved_time; int default_entry, current_entry; int timeout; default_entry = get_entry_number (menu, "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) { *auto_boot = 1; return default_entry; } current_entry = default_entry; /* Initialize the time. */ saved_time = grub_get_time_ms (); refresh: menu_init (current_entry, menu, nested); timeout = grub_menu_get_timeout (); if (timeout > 0) menu_print_timeout (timeout); else clear_timeout (); while (1) { int c; timeout = grub_menu_get_timeout (); if (grub_normal_exit_level) return -1; 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; menu_print_timeout (timeout); } } if (timeout == 0) { grub_env_unset ("timeout"); *auto_boot = 1; menu_fini (); return default_entry; } if (grub_checkkey () >= 0 || timeout < 0) { c = GRUB_TERM_ASCII_CHAR (grub_getkey ()); if (timeout >= 0) { grub_env_unset ("timeout"); grub_env_unset ("fallback"); clear_timeout (); } switch (c) { case GRUB_TERM_HOME: current_entry = 0; menu_set_chosen_entry (current_entry); break; case GRUB_TERM_END: current_entry = menu->size - 1; menu_set_chosen_entry (current_entry); break; case GRUB_TERM_UP: case '^': if (current_entry > 0) current_entry--; menu_set_chosen_entry (current_entry); break; case GRUB_TERM_DOWN: case 'v': if (current_entry < menu->size - 1) current_entry++; menu_set_chosen_entry (current_entry); break; case GRUB_TERM_PPAGE: if (current_entry < GRUB_MENU_PAGE_SIZE) current_entry = 0; else current_entry -= GRUB_MENU_PAGE_SIZE; menu_set_chosen_entry (current_entry); break; case GRUB_TERM_NPAGE: if (current_entry + GRUB_MENU_PAGE_SIZE < menu->size) current_entry += GRUB_MENU_PAGE_SIZE; else current_entry = menu->size - 1; menu_set_chosen_entry (current_entry); break; case '\n': case '\r': case 6: menu_fini (); *auto_boot = 0; return current_entry; case '\e': if (nested) { menu_fini (); return -1; } break; case 'c': menu_fini (); grub_cmdline_run (1); goto refresh; case 'e': menu_fini (); { grub_menu_entry_t e = grub_menu_get_entry (menu, current_entry); if (e) grub_menu_entry_run (e); } goto refresh; default: break; } } }