2
* GRUB -- GRand Unified Bootloader
3
* Copyright (C) 2003,2004,2005 Free Software Foundation, Inc.
5
* This program is free software; you can redistribute it and/or modify
6
* it under the terms of the GNU General Public License as published by
7
* the Free Software Foundation; either version 2 of the License, or
8
* (at your option) any later version.
10
* This program is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
* GNU General Public License for more details.
15
* You should have received a copy of the GNU General Public License
16
* along with this program; if not, write to the Free Software
17
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20
#include <grub/normal.h>
21
#include <grub/term.h>
22
#include <grub/misc.h>
23
#include <grub/loader.h>
25
#include <grub/machine/time.h>
32
grub_setcolorstate (GRUB_TERM_COLOR_NORMAL);
34
grub_gotoxy (GRUB_TERM_MARGIN, GRUB_TERM_TOP_BORDER_Y);
35
grub_putcode (GRUB_TERM_DISP_UL);
36
for (i = 0; i < (unsigned) GRUB_TERM_BORDER_WIDTH - 2; i++)
37
grub_putcode (GRUB_TERM_DISP_HLINE);
38
grub_putcode (GRUB_TERM_DISP_UR);
40
for (i = 0; i < (unsigned) GRUB_TERM_NUM_ENTRIES; i++)
42
grub_gotoxy (GRUB_TERM_MARGIN, GRUB_TERM_TOP_BORDER_Y + i + 1);
43
grub_putcode (GRUB_TERM_DISP_VLINE);
44
grub_gotoxy (GRUB_TERM_MARGIN + GRUB_TERM_BORDER_WIDTH - 1,
45
GRUB_TERM_TOP_BORDER_Y + i + 1);
46
grub_putcode (GRUB_TERM_DISP_VLINE);
49
grub_gotoxy (GRUB_TERM_MARGIN,
50
GRUB_TERM_TOP_BORDER_Y + GRUB_TERM_NUM_ENTRIES + 1);
51
grub_putcode (GRUB_TERM_DISP_LL);
52
for (i = 0; i < (unsigned) GRUB_TERM_BORDER_WIDTH - 2; i++)
53
grub_putcode (GRUB_TERM_DISP_HLINE);
54
grub_putcode (GRUB_TERM_DISP_LR);
56
grub_setcolorstate (GRUB_TERM_COLOR_STANDARD);
58
grub_gotoxy (GRUB_TERM_MARGIN,
59
(GRUB_TERM_TOP_BORDER_Y + GRUB_TERM_NUM_ENTRIES
60
+ GRUB_TERM_MARGIN + 1));
64
print_message (int nested, int edit)
69
Minimum Emacs-like screen editing is supported. TAB lists\n\
70
available completions. Press C-x (\'x\' with Ctrl) to boot,\n\
71
C-c (\'c\' with Ctrl) for a command-line or ESC to return menu.");
76
Use the %C and %C keys to select which entry is highlighted.\n",
77
(grub_uint32_t) GRUB_TERM_DISP_UP, (grub_uint32_t) GRUB_TERM_DISP_DOWN);
79
Press enter to boot the selected OS, \'e\' to edit the\n\
80
commands before booting or \'c\' for a command-line.");
83
ESC to return previous menu.");
88
static grub_menu_entry_t
89
get_entry (grub_menu_t menu, int no)
93
for (e = menu->entry_list; e && no > 0; e = e->next, no--)
100
print_entry (int y, int highlight, grub_menu_entry_t entry)
105
grub_uint32_t *unicode_title;
108
title = entry ? entry->title : "";
109
unicode_title = grub_malloc (grub_strlen (title) * sizeof (*unicode_title));
111
/* XXX How to show this error? */
114
len = grub_utf8_to_ucs4 (unicode_title, title, grub_strlen (title));
117
/* It is an invalid sequence. */
118
grub_free (unicode_title);
122
grub_setcolorstate (highlight
123
? GRUB_TERM_COLOR_HIGHLIGHT
124
: GRUB_TERM_COLOR_NORMAL);
126
grub_gotoxy (GRUB_TERM_LEFT_BORDER_X + GRUB_TERM_MARGIN, y);
128
for (x = GRUB_TERM_LEFT_BORDER_X + GRUB_TERM_MARGIN + 1, i = 0;
129
x < GRUB_TERM_LEFT_BORDER_X + GRUB_TERM_BORDER_WIDTH - GRUB_TERM_MARGIN;
133
&& x <= (GRUB_TERM_LEFT_BORDER_X + GRUB_TERM_BORDER_WIDTH
134
- GRUB_TERM_MARGIN - 1))
138
width = grub_getcharwidth (unicode_title[i]);
140
if (x + width > (GRUB_TERM_LEFT_BORDER_X + GRUB_TERM_BORDER_WIDTH
141
- GRUB_TERM_MARGIN - 1))
142
grub_putcode (GRUB_TERM_DISP_RIGHT);
144
grub_putcode (unicode_title[i]);
154
grub_gotoxy (GRUB_TERM_CURSOR_X, y);
156
grub_setcolorstate (GRUB_TERM_COLOR_STANDARD);
157
grub_free (unicode_title);
161
print_entries (grub_menu_t menu, int first, int offset)
166
grub_gotoxy (GRUB_TERM_LEFT_BORDER_X + GRUB_TERM_BORDER_WIDTH,
167
GRUB_TERM_FIRST_ENTRY_Y);
170
grub_putcode (GRUB_TERM_DISP_UP);
174
e = get_entry (menu, first);
176
for (i = 0; i < GRUB_TERM_NUM_ENTRIES; i++)
178
print_entry (GRUB_TERM_FIRST_ENTRY_Y + i, offset == i, e);
183
grub_gotoxy (GRUB_TERM_LEFT_BORDER_X + GRUB_TERM_BORDER_WIDTH,
184
GRUB_TERM_TOP_BORDER_Y + GRUB_TERM_NUM_ENTRIES);
187
grub_putcode (GRUB_TERM_DISP_DOWN);
191
grub_gotoxy (GRUB_TERM_CURSOR_X, GRUB_TERM_FIRST_ENTRY_Y + offset);
194
/* Initialize the screen. If NESTED is non-zero, assume that this menu
195
is run from another menu or a command-line. If EDIT is non-zero, show
196
a message for the menu entry editor. */
198
grub_menu_init_page (int nested, int edit)
200
grub_normal_init_page ();
202
print_message (nested, edit);
206
run_menu (grub_menu_t menu, int nested)
209
unsigned long saved_time;
212
offset = menu->default_entry;
213
if (offset > GRUB_TERM_NUM_ENTRIES - 1)
215
first = offset - (GRUB_TERM_NUM_ENTRIES - 1);
216
offset = GRUB_TERM_NUM_ENTRIES - 1;
219
/* Initialize the time. */
220
saved_time = grub_get_rtc ();
224
grub_menu_init_page (nested, 0);
225
print_entries (menu, first, offset);
232
if (menu->timeout > 0)
234
unsigned long current_time;
236
current_time = grub_get_rtc ();
237
if (current_time - saved_time >= GRUB_TICKS_PER_SECOND)
240
saved_time = current_time;
243
grub_gotoxy (0, GRUB_TERM_HEIGHT - 3);
244
/* NOTE: Do not remove the trailing space characters.
245
They are required to clear the line. */
247
The highlighted entry will be booted automatically in %d seconds. ",
249
grub_gotoxy (GRUB_TERM_CURSOR_X, GRUB_TERM_FIRST_ENTRY_Y + offset);
253
if (menu->timeout == 0)
256
return menu->default_entry;
259
if (grub_checkkey () >= 0 || menu->timeout < 0)
261
c = GRUB_TERM_ASCII_CHAR (grub_getkey ());
263
if (menu->timeout >= 0)
265
grub_gotoxy (0, GRUB_TERM_HEIGHT - 3);
269
menu->fallback_entry = -1;
270
grub_gotoxy (GRUB_TERM_CURSOR_X, GRUB_TERM_FIRST_ENTRY_Y + offset);
279
print_entry (GRUB_TERM_FIRST_ENTRY_Y + offset, 0,
280
get_entry (menu, first + offset));
282
print_entry (GRUB_TERM_FIRST_ENTRY_Y + offset, 1,
283
get_entry (menu, first + offset));
288
print_entries (menu, first, offset);
294
if (menu->size > first + offset + 1)
296
if (offset < GRUB_TERM_NUM_ENTRIES - 1)
298
print_entry (GRUB_TERM_FIRST_ENTRY_Y + offset, 0,
299
get_entry (menu, first + offset));
301
print_entry (GRUB_TERM_FIRST_ENTRY_Y + offset, 1,
302
get_entry (menu, first + offset));
307
print_entries (menu, first, offset);
316
return first + offset;
327
grub_cmdline_run (1);
331
grub_menu_entry_run (get_entry (menu, first + offset));
342
/* Never reach here. */
346
/* Run a menu entry. */
348
run_menu_entry (grub_menu_entry_t entry)
350
grub_command_list_t cl;
352
for (cl = entry->command_list; cl != 0; cl = cl->next)
354
if (cl->command[0] == '\0')
355
/* Ignore an empty command line. */
358
if (grub_command_execute (cl->command, 0) != 0)
362
if (grub_errno == GRUB_ERR_NONE && grub_loader_is_loaded ())
363
/* Implicit execution of boot, only if something is loaded. */
364
grub_command_execute ("boot", 0);
368
grub_menu_run (grub_menu_t menu, int nested)
375
boot_entry = run_menu (menu, nested);
382
e = get_entry (menu, boot_entry);
383
grub_printf (" Booting \'%s\'\n\n", e->title);
387
/* Deal with a fallback entry. */
388
/* FIXME: Multiple fallback entries like GRUB Legacy. */
389
if (menu->fallback_entry >= 0)
392
grub_errno = GRUB_ERR_NONE;
394
e = get_entry (menu, menu->fallback_entry);
395
menu->fallback_entry = -1;
396
grub_printf ("\n Falling back to \'%s\'\n\n", e->title);
400
if (grub_errno != GRUB_ERR_NONE)
403
grub_errno = GRUB_ERR_NONE;
405
/* Wait until the user pushes any key so that the user
406
can see what happened. */
407
grub_printf ("\nPress any key to continue...");
408
(void) grub_getkey ();