21 |
#include <grub/term.h> |
#include <grub/term.h> |
22 |
#include <grub/misc.h> |
#include <grub/misc.h> |
23 |
#include <grub/loader.h> |
#include <grub/loader.h> |
24 |
|
#include <grub/mm.h> |
25 |
#include <grub/machine/time.h> |
#include <grub/machine/time.h> |
26 |
|
|
27 |
/* FIXME: These below are all runaround. */ |
/* FIXME: These below are all runaround. */ |
37 |
#define DISP_LL 0x2517 |
#define DISP_LL 0x2517 |
38 |
#define DISP_LR 0x251B |
#define DISP_LR 0x251B |
39 |
|
|
40 |
|
/* FIXME: These should be dynamically obtained from a terminal. */ |
41 |
|
#define TERM_WIDTH (80 - 1) |
42 |
|
#define TERM_HEIGHT 25 |
43 |
|
|
44 |
|
/* The number of lines of "GRUB version..." at the top. */ |
45 |
|
#define TERM_INFO_HEIGHT 1 |
46 |
|
|
47 |
|
/* The number of columns/lines between messages/borders/etc. */ |
48 |
|
#define TERM_MARGIN 1 |
49 |
|
|
50 |
|
/* The number of columns of scroll information. */ |
51 |
|
#define TERM_SCROLL_WIDTH 1 |
52 |
|
|
53 |
|
/* The Y position of the top border. */ |
54 |
|
#define TERM_TOP_BORDER_Y (TERM_MARGIN + TERM_HEIGHT + TERM_MARGIN) |
55 |
|
|
56 |
|
/* The X position of the left border. */ |
57 |
|
#define TERM_LEFT_BORDER_X TERM_MARGIN |
58 |
|
|
59 |
|
/* The width of the border. */ |
60 |
|
#define TERM_BORDER_WIDTH (TERM_WIDTH \ |
61 |
|
- TERM_MARGIN * 3 \ |
62 |
|
- TERM_SCROLL_WIDTH) |
63 |
|
|
64 |
|
/* The number of lines of messages at the bottom. */ |
65 |
|
#define TERM_MESSAGE_HEIGHT 8 |
66 |
|
|
67 |
|
/* The height of the border. */ |
68 |
|
#define TERM_BORDER_HEIGHT (TERM_HEIGHT \ |
69 |
|
- TERM_TOP_BORDER_Y \ |
70 |
|
- TERM_MESSAGE_HEIGHT) |
71 |
|
|
72 |
|
/* The number of entries shown at a time. */ |
73 |
|
#define TERM_NUM_ENTRIES (TERM_BORDER_HEIGHT - 2) |
74 |
|
|
75 |
|
/* The Y position of the first entry. */ |
76 |
|
#define TERM_FIRST_ENTRY_Y (TERM_TOP_BORDER_Y + 1) |
77 |
|
|
78 |
|
/* The max column number of an entry. The last "-1" is for a |
79 |
|
continuation marker. */ |
80 |
|
#define TERM_ENTRY_WIDTH (TERM_BORDER_WIDTH - 2 - TERM_MARGIN * 2 - 1) |
81 |
|
|
82 |
|
/* The standard X position of the cursor. */ |
83 |
|
#define TERM_CURSOR_X (TERM_LEFT_BORDER_X \ |
84 |
|
+ TERM_BORDER_WIDTH \ |
85 |
|
- TERM_MARGIN \ |
86 |
|
- 1) |
87 |
|
|
88 |
static void |
static void |
89 |
draw_border (void) |
draw_border (void) |
90 |
{ |
{ |
92 |
|
|
93 |
grub_setcolorstate (GRUB_TERM_COLOR_NORMAL); |
grub_setcolorstate (GRUB_TERM_COLOR_NORMAL); |
94 |
|
|
95 |
grub_gotoxy (1, 3); |
grub_gotoxy (TERM_MARGIN, TERM_TOP_BORDER_Y); |
96 |
grub_putcode (DISP_UL); |
grub_putcode (DISP_UL); |
97 |
for (i = 0; i < 73; i++) |
for (i = 0; i < TERM_BORDER_WIDTH - 2; i++) |
98 |
grub_putcode (DISP_HLINE); |
grub_putcode (DISP_HLINE); |
99 |
grub_putcode (DISP_UR); |
grub_putcode (DISP_UR); |
100 |
|
|
101 |
i = 1; |
i = 1; |
102 |
while (1) |
while (1) |
103 |
{ |
{ |
104 |
grub_gotoxy (1, 3 + i); |
grub_gotoxy (TERM_MARGIN, TERM_TOP_BORDER_Y + i); |
105 |
|
|
106 |
if (i > 12) |
if (i > (unsigned) TERM_NUM_ENTRIES) |
107 |
break; |
break; |
108 |
|
|
109 |
grub_putcode (DISP_VLINE); |
grub_putcode (DISP_VLINE); |
110 |
grub_gotoxy (75, 3 + i); |
grub_gotoxy (TERM_MARGIN + TERM_BORDER_WIDTH - 1, TERM_TOP_BORDER_Y + i); |
111 |
grub_putcode (DISP_VLINE); |
grub_putcode (DISP_VLINE); |
112 |
|
|
113 |
i++; |
i++; |
114 |
} |
} |
115 |
|
|
116 |
grub_putcode (DISP_LL); |
grub_putcode (DISP_LL); |
117 |
for (i = 0; i < 73; i++) |
for (i = 0; i < TERM_BORDER_WIDTH - 2; i++) |
118 |
grub_putcode (DISP_HLINE); |
grub_putcode (DISP_HLINE); |
119 |
grub_putcode (DISP_LR); |
grub_putcode (DISP_LR); |
120 |
|
|
122 |
} |
} |
123 |
|
|
124 |
static void |
static void |
125 |
print_message (int nested) |
print_message (int nested, int edit) |
126 |
{ |
{ |
127 |
grub_printf ("\n\ |
if (edit) |
128 |
|
{ |
129 |
|
grub_printf ("\n\ |
130 |
|
Minimum Emacs-like screen editing is supported. TAB lists\n\ |
131 |
|
available completions. Press C-x (\'x\' with Ctrl) to boot,\n\ |
132 |
|
C-c (\'c\' with Ctrl) for a command-line or ESC to return menu."); |
133 |
|
} |
134 |
|
else |
135 |
|
{ |
136 |
|
grub_printf ("\n\ |
137 |
Use the %C and %C keys to select which entry is highlighted.\n", |
Use the %C and %C keys to select which entry is highlighted.\n", |
138 |
(grub_uint32_t) DISP_UP, (grub_uint32_t) DISP_DOWN); |
(grub_uint32_t) DISP_UP, (grub_uint32_t) DISP_DOWN); |
139 |
grub_printf ("\ |
grub_printf ("\ |
140 |
Press enter to boot the selected OS, \'e\' to edit the\n\ |
Press enter to boot the selected OS, \'e\' to edit the\n\ |
141 |
commands before booting, or \'c\' for a command-line."); |
commands before booting or \'c\' for a command-line."); |
142 |
if (nested) |
if (nested) |
143 |
grub_printf ("\n\ |
grub_printf ("\n\ |
144 |
ESC to return previous menu."); |
ESC to return previous menu."); |
145 |
|
} |
146 |
|
|
147 |
} |
} |
148 |
|
|
149 |
static grub_menu_entry_t |
static grub_menu_entry_t |
169 |
? GRUB_TERM_COLOR_HIGHLIGHT |
? GRUB_TERM_COLOR_HIGHLIGHT |
170 |
: GRUB_TERM_COLOR_NORMAL); |
: GRUB_TERM_COLOR_NORMAL); |
171 |
|
|
172 |
grub_gotoxy (2, y); |
grub_gotoxy (TERM_LEFT_BORDER_X + TERM_MARGIN, y); |
173 |
grub_putchar (' '); |
grub_putchar (' '); |
174 |
for (x = 3; x < 75; x++) |
for (x = TERM_LEFT_BORDER_X + TERM_MARGIN + 1; |
175 |
|
x < TERM_LEFT_BORDER_X + TERM_BORDER_WIDTH - 1; |
176 |
|
x++) |
177 |
{ |
{ |
178 |
if (*title && x <= 72) |
if (*title && x <= TERM_LEFT_BORDER_X + TERM_ENTRY_WIDTH + 1) |
179 |
{ |
{ |
180 |
if (x == 72) |
if (x == TERM_LEFT_BORDER_X + TERM_ENTRY_WIDTH + 1) |
181 |
grub_putcode (DISP_RIGHT); |
grub_putcode (DISP_RIGHT); |
182 |
else |
else |
183 |
grub_putchar (*title++); |
grub_putchar (*title++); |
185 |
else |
else |
186 |
grub_putchar (' '); |
grub_putchar (' '); |
187 |
} |
} |
188 |
grub_gotoxy (74, y); |
grub_gotoxy (TERM_CURSOR_X, y); |
189 |
|
|
190 |
grub_setcolorstate (GRUB_TERM_COLOR_STANDARD); |
grub_setcolorstate (GRUB_TERM_COLOR_STANDARD); |
191 |
} |
} |
196 |
grub_menu_entry_t e; |
grub_menu_entry_t e; |
197 |
int i; |
int i; |
198 |
|
|
199 |
grub_gotoxy (77, 4); |
grub_gotoxy (TERM_LEFT_BORDER_X + TERM_BORDER_WIDTH + TERM_MARGIN, |
200 |
|
TERM_FIRST_ENTRY_Y); |
201 |
|
|
202 |
if (first) |
if (first) |
203 |
grub_putcode (DISP_UP); |
grub_putcode (DISP_UP); |
206 |
|
|
207 |
e = get_entry (menu, first); |
e = get_entry (menu, first); |
208 |
|
|
209 |
for (i = 0; i < 12; i++) |
for (i = 0; i < TERM_NUM_ENTRIES; i++) |
210 |
{ |
{ |
211 |
print_entry (4 + i, offset == i, e); |
print_entry (TERM_FIRST_ENTRY_Y + i, offset == i, e); |
212 |
if (e) |
if (e) |
213 |
e = e->next; |
e = e->next; |
214 |
} |
} |
215 |
|
|
216 |
grub_gotoxy (77, 4 + 12); |
grub_gotoxy (TERM_LEFT_BORDER_X + TERM_BORDER_WIDTH + TERM_MARGIN, |
217 |
|
TERM_TOP_BORDER_Y + TERM_NUM_ENTRIES); |
218 |
|
|
219 |
if (e) |
if (e) |
220 |
grub_putcode (DISP_DOWN); |
grub_putcode (DISP_DOWN); |
221 |
else |
else |
222 |
grub_putchar (' '); |
grub_putchar (' '); |
223 |
|
|
224 |
grub_gotoxy (74, 4 + offset); |
grub_gotoxy (TERM_CURSOR_X, TERM_FIRST_ENTRY_Y + offset); |
225 |
} |
} |
226 |
|
|
227 |
static void |
static void |
228 |
init_page (int nested) |
init_page (int nested, int edit) |
229 |
{ |
{ |
230 |
grub_normal_init_page (); |
grub_normal_init_page (); |
231 |
draw_border (); |
draw_border (); |
232 |
print_message (nested); |
print_message (nested, edit); |
233 |
|
} |
234 |
|
|
235 |
|
/* Edit a menu entry with an Emacs-like interface. */ |
236 |
|
static void |
237 |
|
edit_menu_entry (grub_menu_entry_t entry) |
238 |
|
{ |
239 |
|
/* Not yet implemented. */ |
240 |
} |
} |
241 |
|
|
242 |
static int |
static int |
245 |
int first, offset; |
int first, offset; |
246 |
unsigned long saved_time; |
unsigned long saved_time; |
247 |
|
|
|
grub_setcursor (0); |
|
|
|
|
248 |
first = 0; |
first = 0; |
249 |
offset = menu->default_entry; |
offset = menu->default_entry; |
250 |
if (offset > 11) |
if (offset > TERM_NUM_ENTRIES - 1) |
251 |
{ |
{ |
252 |
first = offset - 11; |
first = offset - (TERM_NUM_ENTRIES - 1); |
253 |
offset = 11; |
offset = TERM_NUM_ENTRIES - 1; |
254 |
} |
} |
255 |
|
|
256 |
init_page (nested); |
/* Initialize the time. */ |
257 |
|
saved_time = grub_get_rtc (); |
258 |
|
|
259 |
|
refresh: |
260 |
|
grub_setcursor (0); |
261 |
|
init_page (nested, 0); |
262 |
print_entries (menu, first, offset); |
print_entries (menu, first, offset); |
263 |
grub_refresh (); |
grub_refresh (); |
264 |
|
|
|
/* Initialize the time. */ |
|
|
saved_time = grub_get_rtc (); |
|
|
|
|
265 |
while (1) |
while (1) |
266 |
{ |
{ |
267 |
int c; |
int c; |
277 |
saved_time = current_time; |
saved_time = current_time; |
278 |
} |
} |
279 |
|
|
280 |
grub_gotoxy (3, 22); |
grub_gotoxy (0, TERM_HEIGHT - 3); |
281 |
grub_printf ("The highlighted entry will be booted automatically in %d seconds. ", |
/* NOTE: Do not remove the trailing space characters. |
282 |
|
They are required to clear the line. */ |
283 |
|
grub_printf ("\ |
284 |
|
The highlighted entry will be booted automatically in %d seconds. ", |
285 |
menu->timeout); |
menu->timeout); |
286 |
grub_gotoxy (74, 4 + offset); |
grub_gotoxy (TERM_CURSOR_X, TERM_FIRST_ENTRY_Y + offset); |
287 |
grub_refresh (); |
grub_refresh (); |
288 |
} |
} |
289 |
|
|
296 |
|
|
297 |
if (menu->timeout >= 0) |
if (menu->timeout >= 0) |
298 |
{ |
{ |
299 |
grub_gotoxy (3, 22); |
grub_gotoxy (0, TERM_HEIGHT - 3); |
300 |
grub_printf (" "); |
grub_printf ("\ |
301 |
|
"); |
302 |
menu->timeout = -1; |
menu->timeout = -1; |
303 |
menu->fallback_entry = -1; |
menu->fallback_entry = -1; |
304 |
grub_gotoxy (74, 4 + offset); |
grub_gotoxy (TERM_CURSOR_X, TERM_FIRST_ENTRY_Y + offset); |
305 |
} |
} |
306 |
|
|
307 |
switch (c) |
switch (c) |
310 |
case '^': |
case '^': |
311 |
if (offset > 0) |
if (offset > 0) |
312 |
{ |
{ |
313 |
print_entry (4 + offset, 0, |
print_entry (TERM_FIRST_ENTRY_Y + offset, 0, |
314 |
get_entry (menu, first + offset)); |
get_entry (menu, first + offset)); |
315 |
offset--; |
offset--; |
316 |
print_entry (4 + offset, 1, |
print_entry (TERM_FIRST_ENTRY_Y + offset, 1, |
317 |
get_entry (menu, first + offset)); |
get_entry (menu, first + offset)); |
318 |
} |
} |
319 |
else if (first > 0) |
else if (first > 0) |
327 |
case 'v': |
case 'v': |
328 |
if (menu->size > first + offset + 1) |
if (menu->size > first + offset + 1) |
329 |
{ |
{ |
330 |
if (offset < 11) |
if (offset < TERM_NUM_ENTRIES - 1) |
331 |
{ |
{ |
332 |
print_entry (4 + offset, 0, |
print_entry (TERM_FIRST_ENTRY_Y + offset, 0, |
333 |
get_entry (menu, first + offset)); |
get_entry (menu, first + offset)); |
334 |
offset++; |
offset++; |
335 |
print_entry (4 + offset, 1, |
print_entry (TERM_FIRST_ENTRY_Y + offset, 1, |
336 |
get_entry (menu, first + offset)); |
get_entry (menu, first + offset)); |
337 |
} |
} |
338 |
else |
else |
360 |
case 'c': |
case 'c': |
361 |
grub_setcursor (1); |
grub_setcursor (1); |
362 |
grub_cmdline_run (1); |
grub_cmdline_run (1); |
363 |
grub_setcursor (0); |
goto refresh; |
364 |
init_page (nested); |
|
365 |
print_entries (menu, first, offset); |
case 'e': |
366 |
break; |
edit_menu_entry (get_entry (menu, first + offset)); |
367 |
|
goto refresh; |
368 |
|
|
369 |
default: |
default: |
370 |
break; |
break; |
387 |
for (cl = entry->command_list; cl != 0; cl = cl->next) |
for (cl = entry->command_list; cl != 0; cl = cl->next) |
388 |
{ |
{ |
389 |
grub_command_t c; |
grub_command_t c; |
390 |
|
|
391 |
|
if (cl->command[0] == '\0') |
392 |
|
/* Ignore an empty command line. */ |
393 |
|
continue; |
394 |
|
|
395 |
c = grub_command_find (cl->command); |
c = grub_command_find (cl->command); |
396 |
if (! c) |
if (! c) |