Updated PCI IDs to latest snapshot.
[tangerine.git] / arch / common / boot / grub2 / normal / menu_entry.c
bloba9c17886f31e8df7614f0c899d51d7f0538b9f76
1 /*
2 * GRUB -- GRand Unified Bootloader
3 * Copyright (C) 2005,2006,2007,2008 Free Software Foundation, Inc.
5 * GRUB 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 3 of the License, or
8 * (at your option) any later version.
10 * GRUB 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 GRUB. If not, see <http://www.gnu.org/licenses/>.
19 #include <grub/normal.h>
20 #include <grub/term.h>
21 #include <grub/misc.h>
22 #include <grub/mm.h>
23 #include <grub/loader.h>
24 #include <grub/script.h>
26 enum update_mode
28 NO_LINE,
29 SINGLE_LINE,
30 ALL_LINES
33 struct line
35 /* The line buffer. */
36 char *buf;
37 /* The length of the line. */
38 int len;
39 /* The maximum length of the line. */
40 int max_len;
43 struct screen
45 /* The array of lines. */
46 struct line *lines;
47 /* The number of lines. */
48 int num_lines;
49 /* The current column. */
50 int column;
51 /* The real column. */
52 int real_column;
53 /* The current line. */
54 int line;
55 /* The X coordinate. */
56 int x;
57 /* The Y coordinate. */
58 int y;
59 /* The kill buffer. */
60 char *killed_text;
61 /* The flag of a completion window. */
62 int completion_shown;
65 /* Used for storing completion items temporarily. */
66 static struct line completion_buffer;
68 /* Initialize a line. */
69 static int
70 init_line (struct line *linep)
72 linep->len = 0;
73 linep->max_len = 80; /* XXX */
74 linep->buf = grub_malloc (linep->max_len);
75 if (! linep->buf)
76 return 0;
78 return 1;
81 /* Allocate extra space if necessary. */
82 static int
83 ensure_space (struct line *linep, int extra)
85 if (linep->max_len < linep->len + extra)
87 linep->max_len = linep->len + extra + 80; /* XXX */
88 linep->buf = grub_realloc (linep->buf, linep->max_len + 1);
89 if (! linep->buf)
90 return 0;
93 return 1;
96 /* Return the number of lines occupied by this line on the screen. */
97 static int
98 get_logical_num_lines (struct line *linep)
100 return (linep->len / GRUB_TERM_ENTRY_WIDTH) + 1;
103 /* Print a line. */
104 static void
105 print_line (struct line *linep, int offset, int start, int y)
107 int i;
108 char *p;
110 grub_gotoxy (GRUB_TERM_LEFT_BORDER_X + GRUB_TERM_MARGIN + start + 1,
111 y + GRUB_TERM_FIRST_ENTRY_Y);
113 for (p = linep->buf + offset + start, i = start;
114 i < GRUB_TERM_ENTRY_WIDTH && offset + i < linep->len;
115 p++, i++)
116 grub_putchar (*p);
118 for (; i < GRUB_TERM_ENTRY_WIDTH; i++)
119 grub_putchar (' ');
121 if (linep->len >= offset + GRUB_TERM_ENTRY_WIDTH)
122 grub_putchar ('\\');
123 else
124 grub_putchar (' ');
127 /* Print an empty line. */
128 static void
129 print_empty_line (int y)
131 int i;
133 grub_gotoxy (GRUB_TERM_LEFT_BORDER_X + GRUB_TERM_MARGIN + 1,
134 y + GRUB_TERM_FIRST_ENTRY_Y);
136 for (i = 0; i < GRUB_TERM_ENTRY_WIDTH + 1; i++)
137 grub_putchar (' ');
140 /* Print an up arrow. */
141 static void
142 print_up (int flag)
144 grub_gotoxy (GRUB_TERM_LEFT_BORDER_X + GRUB_TERM_BORDER_WIDTH,
145 GRUB_TERM_FIRST_ENTRY_Y);
147 if (flag)
148 grub_putcode (GRUB_TERM_DISP_UP);
149 else
150 grub_putchar (' ');
153 /* Print a down arrow. */
154 static void
155 print_down (int flag)
157 grub_gotoxy (GRUB_TERM_LEFT_BORDER_X + GRUB_TERM_BORDER_WIDTH,
158 GRUB_TERM_TOP_BORDER_Y + GRUB_TERM_NUM_ENTRIES);
160 if (flag)
161 grub_putcode (GRUB_TERM_DISP_DOWN);
162 else
163 grub_putchar (' ');
166 /* Draw the lines of the screen SCREEN. */
167 static void
168 update_screen (struct screen *screen, int region_start, int region_column,
169 int up, int down, enum update_mode mode)
171 int up_flag = 0;
172 int down_flag = 0;
173 int y;
174 int i;
175 struct line *linep;
177 /* Check if scrolling is necessary. */
178 if (screen->y < 0 || screen->y >= GRUB_TERM_NUM_ENTRIES)
180 if (screen->y < 0)
181 screen->y = 0;
182 else
183 screen->y = GRUB_TERM_NUM_ENTRIES - 1;
185 region_start = 0;
186 region_column = 0;
187 up = 1;
188 down = 1;
189 mode = ALL_LINES;
192 if (mode != NO_LINE)
194 /* Draw lines. This code is tricky, because this must calculate logical
195 positions. */
196 y = screen->y - screen->column / GRUB_TERM_ENTRY_WIDTH;
197 i = screen->line;
198 linep = screen->lines + i;
199 while (y > 0)
201 i--;
202 linep--;
203 y -= get_logical_num_lines (linep);
206 if (y < 0 || i > 0)
207 up_flag = 1;
211 int column;
213 for (column = 0;
214 column <= linep->len && y < GRUB_TERM_NUM_ENTRIES;
215 column += GRUB_TERM_ENTRY_WIDTH, y++)
217 if (y < 0)
218 continue;
220 if (i == region_start)
222 if (region_column >= column
223 && region_column < column + GRUB_TERM_ENTRY_WIDTH)
224 print_line (linep, column, region_column - column, y);
225 else if (region_column < column)
226 print_line (linep, column, 0, y);
228 else if (i > region_start && mode == ALL_LINES)
229 print_line (linep, column, 0, y);
232 if (y == GRUB_TERM_NUM_ENTRIES)
234 if (column <= linep->len || i + 1 < screen->num_lines)
235 down_flag = 1;
238 linep++;
239 i++;
241 if (mode == ALL_LINES && i == screen->num_lines)
242 for (; y < GRUB_TERM_NUM_ENTRIES; y++)
243 print_empty_line (y);
246 while (y < GRUB_TERM_NUM_ENTRIES);
248 /* Draw up and down arrows. */
249 if (up)
250 print_up (up_flag);
251 if (down)
252 print_down (down_flag);
255 /* Place the cursor. */
256 grub_gotoxy (GRUB_TERM_LEFT_BORDER_X + GRUB_TERM_MARGIN + 1 + screen->x,
257 GRUB_TERM_FIRST_ENTRY_Y + screen->y);
259 grub_refresh ();
262 /* Insert the string S into the screen SCREEN. This updates the cursor
263 position and redraw the screen. Return zero if fails. */
264 static int
265 insert_string (struct screen *screen, char *s, int update)
267 int region_start = screen->num_lines;
268 int region_column = 0;
269 int down = 0;
270 enum update_mode mode = NO_LINE;
272 while (*s)
274 if (*s == '\n')
276 /* LF is special because it creates a new line. */
277 struct line *current_linep;
278 struct line *next_linep;
279 int size;
281 /* Make a new line. */
282 screen->num_lines++;
283 screen->lines = grub_realloc (screen->lines,
284 screen->num_lines
285 * sizeof (struct line));
286 if (! screen->lines)
287 return 0;
289 /* Scroll down. */
290 grub_memmove (screen->lines + screen->line + 2,
291 screen->lines + screen->line + 1,
292 ((screen->num_lines - screen->line - 2)
293 * sizeof (struct line)));
295 if (! init_line (screen->lines + screen->line + 1))
296 return 0;
298 /* Fold the line. */
299 current_linep = screen->lines + screen->line;
300 next_linep = current_linep + 1;
301 size = current_linep->len - screen->column;
303 if (! ensure_space (next_linep, size))
304 return 0;
306 grub_memmove (next_linep->buf,
307 current_linep->buf + screen->column,
308 size);
309 current_linep->len = screen->column;
310 next_linep->len = size;
312 /* Update a dirty region. */
313 if (region_start > screen->line)
315 region_start = screen->line;
316 region_column = screen->column;
319 mode = ALL_LINES;
320 down = 1; /* XXX not optimal. */
322 /* Move the cursor. */
323 screen->column = screen->real_column = 0;
324 screen->line++;
325 screen->x = 0;
326 screen->y++;
328 s++;
330 else
332 /* All but LF. */
333 char *p;
334 struct line *current_linep;
335 int size;
336 int orig_num, new_num;
338 /* Find a string delimited by LF. */
339 p = grub_strchr (s, '\n');
340 if (! p)
341 p = s + grub_strlen (s);
343 /* Insert the string. */
344 current_linep = screen->lines + screen->line;
345 size = p - s;
346 if (! ensure_space (current_linep, size))
347 return 0;
349 grub_memmove (current_linep->buf + screen->column + size,
350 current_linep->buf + screen->column,
351 current_linep->len - screen->column);
352 grub_memmove (current_linep->buf + screen->column,
354 size);
355 orig_num = get_logical_num_lines (current_linep);
356 current_linep->len += size;
357 new_num = get_logical_num_lines (current_linep);
359 /* Update the dirty region. */
360 if (region_start > screen->line)
362 region_start = screen->line;
363 region_column = screen->column;
366 if (orig_num != new_num)
368 mode = ALL_LINES;
369 down = 1; /* XXX not optimal. */
371 else if (mode != ALL_LINES)
372 mode = SINGLE_LINE;
374 /* Move the cursor. */
375 screen->column += size;
376 screen->real_column = screen->column;
377 screen->x += size;
378 screen->y += screen->x / GRUB_TERM_ENTRY_WIDTH;
379 screen->x %= GRUB_TERM_ENTRY_WIDTH;
381 s = p;
385 if (update)
386 update_screen (screen, region_start, region_column, 0, down, mode);
388 return 1;
391 /* Release the resource allocated for SCREEN. */
392 static void
393 destroy_screen (struct screen *screen)
395 int i;
397 if (screen->lines)
398 for (i = 0; i < screen->num_lines; i++)
400 struct line *linep = screen->lines + i;
402 if (linep)
403 grub_free (linep->buf);
406 grub_free (screen->killed_text);
407 grub_free (screen->lines);
408 grub_free (screen);
411 /* Make a new screen. */
412 static struct screen *
413 make_screen (grub_menu_entry_t entry)
415 struct screen *screen;
417 /* Initialize the screen. */
418 screen = grub_malloc (sizeof (*screen));
419 if (! screen)
420 return 0;
422 screen->num_lines = 1;
423 screen->column = 0;
424 screen->real_column = 0;
425 screen->line = 0;
426 screen->x = 0;
427 screen->y = 0;
428 screen->killed_text = 0;
429 screen->completion_shown = 0;
430 screen->lines = grub_malloc (sizeof (struct line));
431 if (! screen->lines)
432 goto fail;
434 /* Initialize the first line which must be always present. */
435 if (! init_line (screen->lines))
436 goto fail;
438 insert_string (screen, (char *) entry->sourcecode, 0);
440 /* Reset the cursor position. */
441 screen->column = 0;
442 screen->real_column = 0;
443 screen->line = 0;
444 screen->x = 0;
445 screen->y = 0;
447 return screen;
449 fail:
450 destroy_screen (screen);
451 return 0;
454 static int
455 forward_char (struct screen *screen, int update)
457 struct line *linep;
459 linep = screen->lines + screen->line;
460 if (screen->column < linep->len)
462 screen->column++;
463 screen->x++;
464 if (screen->x == GRUB_TERM_ENTRY_WIDTH)
466 screen->x = 0;
467 screen->y++;
470 else if (screen->num_lines > screen->line + 1)
472 screen->column = 0;
473 screen->line++;
474 screen->x = 0;
475 screen->y++;
478 screen->real_column = screen->column;
480 if (update)
481 update_screen (screen, screen->num_lines, 0, 0, 0, NO_LINE);
482 return 1;
485 static int
486 backward_char (struct screen *screen, int update)
488 if (screen->column > 0)
490 screen->column--;
491 screen->x--;
492 if (screen->x == -1)
494 screen->x = GRUB_TERM_ENTRY_WIDTH - 1;
495 screen->y--;
498 else if (screen->line > 0)
500 struct line *linep;
502 screen->line--;
503 linep = screen->lines + screen->line;
504 screen->column = linep->len;
505 screen->x = screen->column % GRUB_TERM_ENTRY_WIDTH;
506 screen->y--;
509 screen->real_column = screen->column;
511 if (update)
512 update_screen (screen, screen->num_lines, 0, 0, 0, NO_LINE);
514 return 1;
517 static int
518 previous_line (struct screen *screen, int update)
520 if (screen->line > 0)
522 struct line *linep;
523 int dy;
525 /* How many physical lines from the current position
526 to the first physical line? */
527 dy = screen->column / GRUB_TERM_ENTRY_WIDTH;
529 screen->line--;
531 linep = screen->lines + screen->line;
532 if (linep->len < screen->real_column)
533 screen->column = linep->len;
534 else
535 screen->column = screen->real_column;
537 /* How many physical lines from the current position
538 to the last physical line? */
539 dy += (linep->len / GRUB_TERM_ENTRY_WIDTH
540 - screen->column / GRUB_TERM_ENTRY_WIDTH);
542 screen->y -= dy + 1;
543 screen->x = screen->column % GRUB_TERM_ENTRY_WIDTH;
545 else
547 screen->y -= screen->column / GRUB_TERM_ENTRY_WIDTH;
548 screen->column = 0;
549 screen->x = 0;
552 if (update)
553 update_screen (screen, screen->num_lines, 0, 0, 0, NO_LINE);
555 return 1;
558 static int
559 next_line (struct screen *screen, int update)
561 if (screen->line < screen->num_lines - 1)
563 struct line *linep;
564 int dy;
566 /* How many physical lines from the current position
567 to the last physical line? */
568 linep = screen->lines + screen->line;
569 dy = (linep->len / GRUB_TERM_ENTRY_WIDTH
570 - screen->column / GRUB_TERM_ENTRY_WIDTH);
572 screen->line++;
574 linep++;
575 if (linep->len < screen->real_column)
576 screen->column = linep->len;
577 else
578 screen->column = screen->real_column;
580 /* How many physical lines from the current position
581 to the first physical line? */
582 dy += screen->column / GRUB_TERM_ENTRY_WIDTH;
584 screen->y += dy + 1;
585 screen->x = screen->column % GRUB_TERM_ENTRY_WIDTH;
587 else
589 struct line *linep;
591 linep = screen->lines + screen->line;
592 screen->y += (linep->len / GRUB_TERM_ENTRY_WIDTH
593 - screen->column / GRUB_TERM_ENTRY_WIDTH);
594 screen->column = linep->len;
595 screen->x = screen->column % GRUB_TERM_ENTRY_WIDTH;
598 if (update)
599 update_screen (screen, screen->num_lines, 0, 0, 0, NO_LINE);
601 return 1;
604 static int
605 beginning_of_line (struct screen *screen, int update)
607 screen->y -= screen->column / GRUB_TERM_ENTRY_WIDTH;
608 screen->column = screen->real_column = 0;
609 screen->x = 0;
611 if (update)
612 update_screen (screen, screen->num_lines, 0, 0, 0, NO_LINE);
614 return 1;
617 static int
618 end_of_line (struct screen *screen, int update)
620 struct line *linep;
622 linep = screen->lines + screen->line;
623 screen->y += (linep->len / GRUB_TERM_ENTRY_WIDTH
624 - screen->column / GRUB_TERM_ENTRY_WIDTH);
625 screen->column = screen->real_column = linep->len;
626 screen->x = screen->column % GRUB_TERM_ENTRY_WIDTH;
628 if (update)
629 update_screen (screen, screen->num_lines, 0, 0, 0, NO_LINE);
631 return 1;
634 static int
635 delete_char (struct screen *screen, int update)
637 struct line *linep;
638 enum update_mode mode = NO_LINE;
639 int start = screen->num_lines;
640 int column = 0;
641 int down = 0;
643 linep = screen->lines + screen->line;
644 if (linep->len > screen->column)
646 int orig_num, new_num;
648 orig_num = get_logical_num_lines (linep);
650 grub_memmove (linep->buf + screen->column,
651 linep->buf + screen->column + 1,
652 linep->len - screen->column - 1);
653 linep->len--;
655 new_num = get_logical_num_lines (linep);
657 if (orig_num != new_num)
658 mode = ALL_LINES;
659 else
660 mode = SINGLE_LINE;
662 start = screen->line;
663 column = screen->column;
665 else if (screen->num_lines > screen->line + 1)
667 struct line *next_linep;
669 next_linep = linep + 1;
670 if (! ensure_space (linep, next_linep->len))
671 return 0;
673 grub_memmove (linep->buf + linep->len, next_linep->buf, next_linep->len);
674 linep->len += next_linep->len;
676 grub_free (next_linep->buf);
677 grub_memmove (next_linep,
678 next_linep + 1,
679 (screen->num_lines - screen->line - 2)
680 * sizeof (struct line));
681 screen->num_lines--;
683 mode = ALL_LINES;
684 start = screen->line;
685 column = screen->column;
686 down = 1;
689 screen->real_column = screen->column;
691 if (update)
692 update_screen (screen, start, column, 0, down, mode);
694 return 1;
697 static int
698 backward_delete_char (struct screen *screen, int update)
700 int saved_column;
701 int saved_line;
703 saved_column = screen->column;
704 saved_line = screen->line;
706 if (! backward_char (screen, 0))
707 return 0;
709 if (saved_column != screen->column || saved_line != screen->line)
710 if (! delete_char (screen, update))
711 return 0;
713 return 1;
716 static int
717 kill_line (struct screen *screen, int continuous, int update)
719 struct line *linep;
720 char *p;
721 int size;
722 int offset;
724 p = screen->killed_text;
725 if (! continuous && p)
726 p[0] = '\0';
728 linep = screen->lines + screen->line;
729 size = linep->len - screen->column;
731 if (p)
732 offset = grub_strlen (p);
733 else
734 offset = 0;
736 if (size > 0)
738 enum update_mode mode = SINGLE_LINE;
739 int down = 0;
740 int orig_num, new_num;
742 p = grub_realloc (p, offset + size + 1);
743 if (! p)
744 return 0;
746 grub_memmove (p + offset, linep->buf + screen->column, size);
747 p[offset + size - 1] = '\0';
749 screen->killed_text = p;
751 orig_num = get_logical_num_lines (linep);
752 linep->len = screen->column;
753 new_num = get_logical_num_lines (linep);
755 if (orig_num != new_num)
757 mode = ALL_LINES;
758 down = 1;
761 if (update)
762 update_screen (screen, screen->line, screen->column, 0, down, mode);
764 else if (screen->line + 1 < screen->num_lines)
766 p = grub_realloc (p, offset + 1 + 1);
767 if (! p)
768 return 0;
770 p[offset] = '\n';
771 p[offset + 1] = '\0';
773 screen->killed_text = p;
775 return delete_char (screen, update);
778 return 1;
781 static int
782 yank (struct screen *screen, int update)
784 if (screen->killed_text)
785 return insert_string (screen, screen->killed_text, update);
787 return 1;
790 static int
791 open_line (struct screen *screen, int update)
793 int saved_y = screen->y;
795 if (! insert_string (screen, "\n", 0))
796 return 0;
798 if (! backward_char (screen, 0))
799 return 0;
801 screen->y = saved_y;
803 if (update)
804 update_screen (screen, screen->line, screen->column, 0, 1, ALL_LINES);
806 return 1;
809 /* A completion hook to print items. */
810 static void
811 store_completion (const char *item, grub_completion_type_t type, int count)
813 char *p;
815 if (count == 0)
817 /* If this is the first time, print a label. */
818 const char *what;
820 switch (type)
822 case GRUB_COMPLETION_TYPE_COMMAND:
823 what = "commands";
824 break;
825 case GRUB_COMPLETION_TYPE_DEVICE:
826 what = "devices";
827 break;
828 case GRUB_COMPLETION_TYPE_FILE:
829 what = "files";
830 break;
831 case GRUB_COMPLETION_TYPE_PARTITION:
832 what = "partitions";
833 break;
834 case GRUB_COMPLETION_TYPE_ARGUMENT:
835 what = "arguments";
836 break;
837 default:
838 what = "things";
839 break;
842 grub_gotoxy (0, GRUB_TERM_HEIGHT - 3);
843 grub_printf (" Possible %s are:\n ", what);
846 /* Make sure that the completion buffer has enough room. */
847 if (completion_buffer.max_len < (completion_buffer.len
848 + (int) grub_strlen (item) + 1 + 1))
850 grub_size_t new_len;
852 new_len = completion_buffer.len + grub_strlen (item) + 80;
853 p = grub_realloc (completion_buffer.buf, new_len);
854 if (! p)
856 /* Possibly not fatal. */
857 grub_errno = GRUB_ERR_NONE;
858 return;
860 p[completion_buffer.len] = 0;
861 completion_buffer.buf = p;
862 completion_buffer.max_len = new_len;
865 p = completion_buffer.buf + completion_buffer.len;
866 if (completion_buffer.len != 0)
868 *p++ = ' ';
869 completion_buffer.len++;
871 grub_strcpy (p, item);
872 completion_buffer.len += grub_strlen (item);
875 static int
876 complete (struct screen *screen, int continuous, int update)
878 grub_uint16_t pos;
879 char saved_char;
880 struct line *linep;
881 int restore;
882 char *insert;
883 static int count = -1;
885 if (continuous)
886 count++;
887 else
888 count = 0;
890 pos = grub_getxy ();
891 grub_gotoxy (0, GRUB_TERM_HEIGHT - 3);
893 completion_buffer.buf = 0;
894 completion_buffer.len = 0;
895 completion_buffer.max_len = 0;
897 linep = screen->lines + screen->line;
898 saved_char = linep->buf[screen->column];
899 linep->buf[screen->column] = '\0';
901 insert = grub_normal_do_completion (linep->buf, &restore, store_completion);
903 linep->buf[screen->column] = saved_char;
905 if (restore)
907 char *p = completion_buffer.buf;
909 screen->completion_shown = 1;
911 if (p)
913 int num_sections = ((completion_buffer.len + GRUB_TERM_WIDTH - 8 - 1)
914 / (GRUB_TERM_WIDTH - 8));
915 char *endp;
917 p += (count % num_sections) * (GRUB_TERM_WIDTH - 8);
918 endp = p + (GRUB_TERM_WIDTH - 8);
920 if (p != completion_buffer.buf)
921 grub_putcode (GRUB_TERM_DISP_LEFT);
922 else
923 grub_putchar (' ');
925 while (*p && p < endp)
926 grub_putchar (*p++);
928 if (*p)
929 grub_putcode (GRUB_TERM_DISP_RIGHT);
933 grub_gotoxy (pos >> 8, pos & 0xFF);
935 if (insert)
937 insert_string (screen, insert, update);
938 count = -1;
939 grub_free (insert);
941 else if (update)
942 grub_refresh ();
944 grub_free (completion_buffer.buf);
945 return 1;
948 /* Clear displayed completions. */
949 static void
950 clear_completions (void)
952 grub_uint16_t pos;
953 int i, j;
955 pos = grub_getxy ();
956 grub_gotoxy (0, GRUB_TERM_HEIGHT - 3);
958 for (i = 0; i < 2; i++)
960 for (j = 0; j < GRUB_TERM_WIDTH - 1; j++)
961 grub_putchar (' ');
962 grub_putchar ('\n');
965 grub_gotoxy (pos >> 8, pos & 0xFF);
966 grub_refresh ();
969 /* Execute the command list in the screen SCREEN. */
970 static int
971 run (struct screen *screen)
973 struct grub_script *parsed_script = 0;
974 int currline = 0;
975 char *nextline;
977 auto grub_err_t editor_getline (char **line);
978 grub_err_t editor_getline (char **line)
980 struct line *linep = screen->lines + currline;
981 char *p;
983 if (currline > screen->num_lines)
985 *line = 0;
986 return 0;
989 /* Trim down space characters. */
990 for (p = linep->buf + linep->len - 1;
991 p >= linep->buf && grub_isspace (*p);
992 p--)
994 *++p = '\0';
996 linep->len = p - linep->buf;
997 for (p = linep->buf; grub_isspace (*p); p++)
999 *line = grub_strdup (p);
1000 currline++;
1001 return 0;
1004 grub_cls ();
1005 grub_printf (" Booting a command list\n\n");
1008 /* Execute the script, line for line. */
1009 while (currline < screen->num_lines)
1011 editor_getline (&nextline);
1012 parsed_script = grub_script_parse (nextline, editor_getline);
1013 if (parsed_script)
1015 /* Execute the command(s). */
1016 grub_script_execute (parsed_script);
1018 /* The parsed script was executed, throw it away. */
1019 grub_script_free (parsed_script);
1021 else
1022 break;
1025 if (grub_errno == GRUB_ERR_NONE && grub_loader_is_loaded ())
1026 /* Implicit execution of boot, only if something is loaded. */
1027 grub_command_execute ("boot", 0);
1029 if (grub_errno != GRUB_ERR_NONE)
1031 grub_print_error ();
1032 grub_errno = GRUB_ERR_NONE;
1033 grub_wait_after_message ();
1036 return 1;
1039 /* Edit a menu entry with an Emacs-like interface. */
1040 void
1041 grub_menu_entry_run (grub_menu_entry_t entry)
1043 struct screen *screen;
1044 int prev_c;
1046 screen = make_screen (entry);
1047 if (! screen)
1048 return;
1050 refresh:
1051 /* Draw the screen. */
1052 grub_menu_init_page (0, 1);
1053 update_screen (screen, 0, 0, 1, 1, ALL_LINES);
1054 grub_setcursor (1);
1055 prev_c = '\0';
1057 while (1)
1059 int c = GRUB_TERM_ASCII_CHAR (grub_getkey ());
1061 if (screen->completion_shown)
1063 clear_completions ();
1064 screen->completion_shown = 0;
1067 switch (c)
1069 case 16: /* C-p */
1070 if (! previous_line (screen, 1))
1071 goto fail;
1072 break;
1074 case 14: /* C-n */
1075 if (! next_line (screen, 1))
1076 goto fail;
1077 break;
1079 case 6: /* C-f */
1080 if (! forward_char (screen, 1))
1081 goto fail;
1082 break;
1084 case 2: /* C-b */
1085 if (! backward_char (screen, 1))
1086 goto fail;
1087 break;
1089 case 1: /* C-a */
1090 if (! beginning_of_line (screen, 1))
1091 goto fail;
1092 break;
1094 case 5: /* C-e */
1095 if (! end_of_line (screen, 1))
1096 goto fail;
1097 break;
1099 case '\t': /* C-i */
1100 if (! complete (screen, prev_c == c, 1))
1101 goto fail;
1102 break;
1104 case 4: /* C-d */
1105 if (! delete_char (screen, 1))
1106 goto fail;
1107 break;
1109 case 8: /* C-h */
1110 if (! backward_delete_char (screen, 1))
1111 goto fail;
1112 break;
1114 case 11: /* C-k */
1115 if (! kill_line (screen, prev_c == c, 1))
1116 goto fail;
1117 break;
1119 case 21: /* C-u */
1120 /* FIXME: What behavior is good for this key? */
1121 break;
1123 case 25: /* C-y */
1124 if (! yank (screen, 1))
1125 goto fail;
1126 break;
1128 case 12: /* C-l */
1129 /* FIXME: centering. */
1130 goto refresh;
1132 case 15: /* C-o */
1133 if (! open_line (screen, 1))
1134 goto fail;
1135 break;
1137 case '\n':
1138 case '\r':
1139 if (! insert_string (screen, "\n", 1))
1140 goto fail;
1141 break;
1143 case '\e':
1144 destroy_screen (screen);
1145 return;
1147 case 3: /* C-c */
1148 grub_cmdline_run (1);
1149 goto refresh;
1151 case 24: /* C-x */
1152 if (! run (screen))
1153 goto fail;
1154 goto refresh;
1156 case 18: /* C-r */
1157 case 19: /* C-s */
1158 case 20: /* C-t */
1159 /* FIXME */
1160 break;
1162 default:
1163 if (grub_isprint (c))
1165 char buf[2];
1167 buf[0] = c;
1168 buf[1] = '\0';
1169 if (! insert_string (screen, buf, 1))
1170 goto fail;
1172 break;
1175 prev_c = c;
1178 fail:
1179 destroy_screen (screen);
1181 grub_cls ();
1182 grub_print_error ();
1183 grub_errno = GRUB_ERR_NONE;
1184 grub_printf ("\nPress any key to continue...");
1185 (void) grub_getkey ();