Big endian: Part1
[grub2/phcoder.git] / normal / menu_entry.c
blob86e581e8098531e9f18b444720c419e764178960
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/command.h>
25 #include <grub/parser.h>
27 enum update_mode
29 NO_LINE,
30 SINGLE_LINE,
31 ALL_LINES
34 struct line
36 /* The line buffer. */
37 char *buf;
38 /* The length of the line. */
39 int len;
40 /* The maximum length of the line. */
41 int max_len;
44 struct screen
46 /* The array of lines. */
47 struct line *lines;
48 /* The number of lines. */
49 int num_lines;
50 /* The current column. */
51 int column;
52 /* The real column. */
53 int real_column;
54 /* The current line. */
55 int line;
56 /* The X coordinate. */
57 int x;
58 /* The Y coordinate. */
59 int y;
60 /* The kill buffer. */
61 char *killed_text;
62 /* The flag of a completion window. */
63 int completion_shown;
66 /* Used for storing completion items temporarily. */
67 static struct line completion_buffer;
69 /* Initialize a line. */
70 static int
71 init_line (struct line *linep)
73 linep->len = 0;
74 linep->max_len = 80; /* XXX */
75 linep->buf = grub_malloc (linep->max_len);
76 if (! linep->buf)
77 return 0;
79 return 1;
82 /* Allocate extra space if necessary. */
83 static int
84 ensure_space (struct line *linep, int extra)
86 if (linep->max_len < linep->len + extra)
88 linep->max_len = linep->len + extra + 80; /* XXX */
89 linep->buf = grub_realloc (linep->buf, linep->max_len + 1);
90 if (! linep->buf)
91 return 0;
94 return 1;
97 /* Return the number of lines occupied by this line on the screen. */
98 static int
99 get_logical_num_lines (struct line *linep)
101 return (linep->len / GRUB_TERM_ENTRY_WIDTH) + 1;
104 /* Print a line. */
105 static void
106 print_line (struct line *linep, int offset, int start, int y)
108 int i;
109 char *p;
111 grub_gotoxy (GRUB_TERM_LEFT_BORDER_X + GRUB_TERM_MARGIN + start + 1,
112 y + GRUB_TERM_FIRST_ENTRY_Y);
114 for (p = linep->buf + offset + start, i = start;
115 i < GRUB_TERM_ENTRY_WIDTH && offset + i < linep->len;
116 p++, i++)
117 grub_putchar (*p);
119 for (; i < GRUB_TERM_ENTRY_WIDTH; i++)
120 grub_putchar (' ');
122 if (linep->len >= offset + GRUB_TERM_ENTRY_WIDTH)
123 grub_putchar ('\\');
124 else
125 grub_putchar (' ');
128 /* Print an empty line. */
129 static void
130 print_empty_line (int y)
132 int i;
134 grub_gotoxy (GRUB_TERM_LEFT_BORDER_X + GRUB_TERM_MARGIN + 1,
135 y + GRUB_TERM_FIRST_ENTRY_Y);
137 for (i = 0; i < GRUB_TERM_ENTRY_WIDTH + 1; i++)
138 grub_putchar (' ');
141 /* Print an up arrow. */
142 static void
143 print_up (int flag)
145 grub_gotoxy (GRUB_TERM_LEFT_BORDER_X + GRUB_TERM_BORDER_WIDTH,
146 GRUB_TERM_FIRST_ENTRY_Y);
148 if (flag)
149 grub_putcode (GRUB_TERM_DISP_UP);
150 else
151 grub_putchar (' ');
154 /* Print a down arrow. */
155 static void
156 print_down (int flag)
158 grub_gotoxy (GRUB_TERM_LEFT_BORDER_X + GRUB_TERM_BORDER_WIDTH,
159 GRUB_TERM_TOP_BORDER_Y + GRUB_TERM_NUM_ENTRIES);
161 if (flag)
162 grub_putcode (GRUB_TERM_DISP_DOWN);
163 else
164 grub_putchar (' ');
167 /* Draw the lines of the screen SCREEN. */
168 static void
169 update_screen (struct screen *screen, int region_start, int region_column,
170 int up, int down, enum update_mode mode)
172 int up_flag = 0;
173 int down_flag = 0;
174 int y;
175 int i;
176 struct line *linep;
178 /* Check if scrolling is necessary. */
179 if (screen->y < 0 || screen->y >= GRUB_TERM_NUM_ENTRIES)
181 if (screen->y < 0)
182 screen->y = 0;
183 else
184 screen->y = GRUB_TERM_NUM_ENTRIES - 1;
186 region_start = 0;
187 region_column = 0;
188 up = 1;
189 down = 1;
190 mode = ALL_LINES;
193 if (mode != NO_LINE)
195 /* Draw lines. This code is tricky, because this must calculate logical
196 positions. */
197 y = screen->y - screen->column / GRUB_TERM_ENTRY_WIDTH;
198 i = screen->line;
199 linep = screen->lines + i;
200 while (y > 0)
202 i--;
203 linep--;
204 y -= get_logical_num_lines (linep);
207 if (y < 0 || i > 0)
208 up_flag = 1;
212 int column;
214 for (column = 0;
215 column <= linep->len && y < GRUB_TERM_NUM_ENTRIES;
216 column += GRUB_TERM_ENTRY_WIDTH, y++)
218 if (y < 0)
219 continue;
221 if (i == region_start)
223 if (region_column >= column
224 && region_column < column + GRUB_TERM_ENTRY_WIDTH)
225 print_line (linep, column, region_column - column, y);
226 else if (region_column < column)
227 print_line (linep, column, 0, y);
229 else if (i > region_start && mode == ALL_LINES)
230 print_line (linep, column, 0, y);
233 if (y == GRUB_TERM_NUM_ENTRIES)
235 if (column <= linep->len || i + 1 < screen->num_lines)
236 down_flag = 1;
239 linep++;
240 i++;
242 if (mode == ALL_LINES && i == screen->num_lines)
243 for (; y < GRUB_TERM_NUM_ENTRIES; y++)
244 print_empty_line (y);
247 while (y < GRUB_TERM_NUM_ENTRIES);
249 /* Draw up and down arrows. */
250 if (up)
251 print_up (up_flag);
252 if (down)
253 print_down (down_flag);
256 /* Place the cursor. */
257 grub_gotoxy (GRUB_TERM_LEFT_BORDER_X + GRUB_TERM_MARGIN + 1 + screen->x,
258 GRUB_TERM_FIRST_ENTRY_Y + screen->y);
260 grub_refresh ();
263 /* Insert the string S into the screen SCREEN. This updates the cursor
264 position and redraw the screen. Return zero if fails. */
265 static int
266 insert_string (struct screen *screen, char *s, int update)
268 int region_start = screen->num_lines;
269 int region_column = 0;
270 int down = 0;
271 enum update_mode mode = NO_LINE;
273 while (*s)
275 if (*s == '\n')
277 /* LF is special because it creates a new line. */
278 struct line *current_linep;
279 struct line *next_linep;
280 int size;
282 /* Make a new line. */
283 screen->num_lines++;
284 screen->lines = grub_realloc (screen->lines,
285 screen->num_lines
286 * sizeof (struct line));
287 if (! screen->lines)
288 return 0;
290 /* Scroll down. */
291 grub_memmove (screen->lines + screen->line + 2,
292 screen->lines + screen->line + 1,
293 ((screen->num_lines - screen->line - 2)
294 * sizeof (struct line)));
296 if (! init_line (screen->lines + screen->line + 1))
297 return 0;
299 /* Fold the line. */
300 current_linep = screen->lines + screen->line;
301 next_linep = current_linep + 1;
302 size = current_linep->len - screen->column;
304 if (! ensure_space (next_linep, size))
305 return 0;
307 grub_memmove (next_linep->buf,
308 current_linep->buf + screen->column,
309 size);
310 current_linep->len = screen->column;
311 next_linep->len = size;
313 /* Update a dirty region. */
314 if (region_start > screen->line)
316 region_start = screen->line;
317 region_column = screen->column;
320 mode = ALL_LINES;
321 down = 1; /* XXX not optimal. */
323 /* Move the cursor. */
324 screen->column = screen->real_column = 0;
325 screen->line++;
326 screen->x = 0;
327 screen->y++;
329 s++;
331 else
333 /* All but LF. */
334 char *p;
335 struct line *current_linep;
336 int size;
337 int orig_num, new_num;
339 /* Find a string delimited by LF. */
340 p = grub_strchr (s, '\n');
341 if (! p)
342 p = s + grub_strlen (s);
344 /* Insert the string. */
345 current_linep = screen->lines + screen->line;
346 size = p - s;
347 if (! ensure_space (current_linep, size))
348 return 0;
350 grub_memmove (current_linep->buf + screen->column + size,
351 current_linep->buf + screen->column,
352 current_linep->len - screen->column);
353 grub_memmove (current_linep->buf + screen->column,
355 size);
356 orig_num = get_logical_num_lines (current_linep);
357 current_linep->len += size;
358 new_num = get_logical_num_lines (current_linep);
360 /* Update the dirty region. */
361 if (region_start > screen->line)
363 region_start = screen->line;
364 region_column = screen->column;
367 if (orig_num != new_num)
369 mode = ALL_LINES;
370 down = 1; /* XXX not optimal. */
372 else if (mode != ALL_LINES)
373 mode = SINGLE_LINE;
375 /* Move the cursor. */
376 screen->column += size;
377 screen->real_column = screen->column;
378 screen->x += size;
379 screen->y += screen->x / GRUB_TERM_ENTRY_WIDTH;
380 screen->x %= GRUB_TERM_ENTRY_WIDTH;
382 s = p;
386 if (update)
387 update_screen (screen, region_start, region_column, 0, down, mode);
389 return 1;
392 /* Release the resource allocated for SCREEN. */
393 static void
394 destroy_screen (struct screen *screen)
396 int i;
398 if (screen->lines)
399 for (i = 0; i < screen->num_lines; i++)
401 struct line *linep = screen->lines + i;
403 if (linep)
404 grub_free (linep->buf);
407 grub_free (screen->killed_text);
408 grub_free (screen->lines);
409 grub_free (screen);
412 /* Make a new screen. */
413 static struct screen *
414 make_screen (grub_menu_entry_t entry)
416 struct screen *screen;
418 /* Initialize the screen. */
419 screen = grub_malloc (sizeof (*screen));
420 if (! screen)
421 return 0;
423 screen->num_lines = 1;
424 screen->column = 0;
425 screen->real_column = 0;
426 screen->line = 0;
427 screen->x = 0;
428 screen->y = 0;
429 screen->killed_text = 0;
430 screen->completion_shown = 0;
431 screen->lines = grub_malloc (sizeof (struct line));
432 if (! screen->lines)
433 goto fail;
435 /* Initialize the first line which must be always present. */
436 if (! init_line (screen->lines))
437 goto fail;
439 insert_string (screen, (char *) entry->sourcecode, 0);
441 /* Reset the cursor position. */
442 screen->column = 0;
443 screen->real_column = 0;
444 screen->line = 0;
445 screen->x = 0;
446 screen->y = 0;
448 return screen;
450 fail:
451 destroy_screen (screen);
452 return 0;
455 static int
456 forward_char (struct screen *screen, int update)
458 struct line *linep;
460 linep = screen->lines + screen->line;
461 if (screen->column < linep->len)
463 screen->column++;
464 screen->x++;
465 if (screen->x == GRUB_TERM_ENTRY_WIDTH)
467 screen->x = 0;
468 screen->y++;
471 else if (screen->num_lines > screen->line + 1)
473 screen->column = 0;
474 screen->line++;
475 screen->x = 0;
476 screen->y++;
479 screen->real_column = screen->column;
481 if (update)
482 update_screen (screen, screen->num_lines, 0, 0, 0, NO_LINE);
483 return 1;
486 static int
487 backward_char (struct screen *screen, int update)
489 if (screen->column > 0)
491 screen->column--;
492 screen->x--;
493 if (screen->x == -1)
495 screen->x = GRUB_TERM_ENTRY_WIDTH - 1;
496 screen->y--;
499 else if (screen->line > 0)
501 struct line *linep;
503 screen->line--;
504 linep = screen->lines + screen->line;
505 screen->column = linep->len;
506 screen->x = screen->column % GRUB_TERM_ENTRY_WIDTH;
507 screen->y--;
510 screen->real_column = screen->column;
512 if (update)
513 update_screen (screen, screen->num_lines, 0, 0, 0, NO_LINE);
515 return 1;
518 static int
519 previous_line (struct screen *screen, int update)
521 if (screen->line > 0)
523 struct line *linep;
524 int dy;
526 /* How many physical lines from the current position
527 to the first physical line? */
528 dy = screen->column / GRUB_TERM_ENTRY_WIDTH;
530 screen->line--;
532 linep = screen->lines + screen->line;
533 if (linep->len < screen->real_column)
534 screen->column = linep->len;
535 else
536 screen->column = screen->real_column;
538 /* How many physical lines from the current position
539 to the last physical line? */
540 dy += (linep->len / GRUB_TERM_ENTRY_WIDTH
541 - screen->column / GRUB_TERM_ENTRY_WIDTH);
543 screen->y -= dy + 1;
544 screen->x = screen->column % GRUB_TERM_ENTRY_WIDTH;
546 else
548 screen->y -= screen->column / GRUB_TERM_ENTRY_WIDTH;
549 screen->column = 0;
550 screen->x = 0;
553 if (update)
554 update_screen (screen, screen->num_lines, 0, 0, 0, NO_LINE);
556 return 1;
559 static int
560 next_line (struct screen *screen, int update)
562 if (screen->line < screen->num_lines - 1)
564 struct line *linep;
565 int dy;
567 /* How many physical lines from the current position
568 to the last physical line? */
569 linep = screen->lines + screen->line;
570 dy = (linep->len / GRUB_TERM_ENTRY_WIDTH
571 - screen->column / GRUB_TERM_ENTRY_WIDTH);
573 screen->line++;
575 linep++;
576 if (linep->len < screen->real_column)
577 screen->column = linep->len;
578 else
579 screen->column = screen->real_column;
581 /* How many physical lines from the current position
582 to the first physical line? */
583 dy += screen->column / GRUB_TERM_ENTRY_WIDTH;
585 screen->y += dy + 1;
586 screen->x = screen->column % GRUB_TERM_ENTRY_WIDTH;
588 else
590 struct line *linep;
592 linep = screen->lines + screen->line;
593 screen->y += (linep->len / GRUB_TERM_ENTRY_WIDTH
594 - screen->column / GRUB_TERM_ENTRY_WIDTH);
595 screen->column = linep->len;
596 screen->x = screen->column % GRUB_TERM_ENTRY_WIDTH;
599 if (update)
600 update_screen (screen, screen->num_lines, 0, 0, 0, NO_LINE);
602 return 1;
605 static int
606 beginning_of_line (struct screen *screen, int update)
608 screen->y -= screen->column / GRUB_TERM_ENTRY_WIDTH;
609 screen->column = screen->real_column = 0;
610 screen->x = 0;
612 if (update)
613 update_screen (screen, screen->num_lines, 0, 0, 0, NO_LINE);
615 return 1;
618 static int
619 end_of_line (struct screen *screen, int update)
621 struct line *linep;
623 linep = screen->lines + screen->line;
624 screen->y += (linep->len / GRUB_TERM_ENTRY_WIDTH
625 - screen->column / GRUB_TERM_ENTRY_WIDTH);
626 screen->column = screen->real_column = linep->len;
627 screen->x = screen->column % GRUB_TERM_ENTRY_WIDTH;
629 if (update)
630 update_screen (screen, screen->num_lines, 0, 0, 0, NO_LINE);
632 return 1;
635 static int
636 delete_char (struct screen *screen, int update)
638 struct line *linep;
639 enum update_mode mode = NO_LINE;
640 int start = screen->num_lines;
641 int column = 0;
642 int down = 0;
644 linep = screen->lines + screen->line;
645 if (linep->len > screen->column)
647 int orig_num, new_num;
649 orig_num = get_logical_num_lines (linep);
651 grub_memmove (linep->buf + screen->column,
652 linep->buf + screen->column + 1,
653 linep->len - screen->column - 1);
654 linep->len--;
656 new_num = get_logical_num_lines (linep);
658 if (orig_num != new_num)
659 mode = ALL_LINES;
660 else
661 mode = SINGLE_LINE;
663 start = screen->line;
664 column = screen->column;
666 else if (screen->num_lines > screen->line + 1)
668 struct line *next_linep;
670 next_linep = linep + 1;
671 if (! ensure_space (linep, next_linep->len))
672 return 0;
674 grub_memmove (linep->buf + linep->len, next_linep->buf, next_linep->len);
675 linep->len += next_linep->len;
677 grub_free (next_linep->buf);
678 grub_memmove (next_linep,
679 next_linep + 1,
680 (screen->num_lines - screen->line - 2)
681 * sizeof (struct line));
682 screen->num_lines--;
684 mode = ALL_LINES;
685 start = screen->line;
686 column = screen->column;
687 down = 1;
690 screen->real_column = screen->column;
692 if (update)
693 update_screen (screen, start, column, 0, down, mode);
695 return 1;
698 static int
699 backward_delete_char (struct screen *screen, int update)
701 int saved_column;
702 int saved_line;
704 saved_column = screen->column;
705 saved_line = screen->line;
707 if (! backward_char (screen, 0))
708 return 0;
710 if (saved_column != screen->column || saved_line != screen->line)
711 if (! delete_char (screen, update))
712 return 0;
714 return 1;
717 static int
718 kill_line (struct screen *screen, int continuous, int update)
720 struct line *linep;
721 char *p;
722 int size;
723 int offset;
725 p = screen->killed_text;
726 if (! continuous && p)
727 p[0] = '\0';
729 linep = screen->lines + screen->line;
730 size = linep->len - screen->column;
732 if (p)
733 offset = grub_strlen (p);
734 else
735 offset = 0;
737 if (size > 0)
739 enum update_mode mode = SINGLE_LINE;
740 int down = 0;
741 int orig_num, new_num;
743 p = grub_realloc (p, offset + size + 1);
744 if (! p)
745 return 0;
747 grub_memmove (p + offset, linep->buf + screen->column, size);
748 p[offset + size - 1] = '\0';
750 screen->killed_text = p;
752 orig_num = get_logical_num_lines (linep);
753 linep->len = screen->column;
754 new_num = get_logical_num_lines (linep);
756 if (orig_num != new_num)
758 mode = ALL_LINES;
759 down = 1;
762 if (update)
763 update_screen (screen, screen->line, screen->column, 0, down, mode);
765 else if (screen->line + 1 < screen->num_lines)
767 p = grub_realloc (p, offset + 1 + 1);
768 if (! p)
769 return 0;
771 p[offset] = '\n';
772 p[offset + 1] = '\0';
774 screen->killed_text = p;
776 return delete_char (screen, update);
779 return 1;
782 static int
783 yank (struct screen *screen, int update)
785 if (screen->killed_text)
786 return insert_string (screen, screen->killed_text, update);
788 return 1;
791 static int
792 open_line (struct screen *screen, int update)
794 int saved_y = screen->y;
796 if (! insert_string (screen, "\n", 0))
797 return 0;
799 if (! backward_char (screen, 0))
800 return 0;
802 screen->y = saved_y;
804 if (update)
805 update_screen (screen, screen->line, screen->column, 0, 1, ALL_LINES);
807 return 1;
810 /* A completion hook to print items. */
811 static void
812 store_completion (const char *item, grub_completion_type_t type, int count)
814 char *p;
816 if (count == 0)
818 /* If this is the first time, print a label. */
819 const char *what;
821 switch (type)
823 case GRUB_COMPLETION_TYPE_COMMAND:
824 what = "commands";
825 break;
826 case GRUB_COMPLETION_TYPE_DEVICE:
827 what = "devices";
828 break;
829 case GRUB_COMPLETION_TYPE_FILE:
830 what = "files";
831 break;
832 case GRUB_COMPLETION_TYPE_PARTITION:
833 what = "partitions";
834 break;
835 case GRUB_COMPLETION_TYPE_ARGUMENT:
836 what = "arguments";
837 break;
838 default:
839 what = "things";
840 break;
843 grub_gotoxy (0, GRUB_TERM_HEIGHT - 3);
844 grub_printf (" Possible %s are:\n ", what);
847 /* Make sure that the completion buffer has enough room. */
848 if (completion_buffer.max_len < (completion_buffer.len
849 + (int) grub_strlen (item) + 1 + 1))
851 grub_size_t new_len;
853 new_len = completion_buffer.len + grub_strlen (item) + 80;
854 p = grub_realloc (completion_buffer.buf, new_len);
855 if (! p)
857 /* Possibly not fatal. */
858 grub_errno = GRUB_ERR_NONE;
859 return;
861 p[completion_buffer.len] = 0;
862 completion_buffer.buf = p;
863 completion_buffer.max_len = new_len;
866 p = completion_buffer.buf + completion_buffer.len;
867 if (completion_buffer.len != 0)
869 *p++ = ' ';
870 completion_buffer.len++;
872 grub_strcpy (p, item);
873 completion_buffer.len += grub_strlen (item);
876 static int
877 complete (struct screen *screen, int continuous, int update)
879 grub_uint16_t pos;
880 char saved_char;
881 struct line *linep;
882 int restore;
883 char *insert;
884 static int count = -1;
886 if (continuous)
887 count++;
888 else
889 count = 0;
891 pos = grub_getxy ();
892 grub_gotoxy (0, GRUB_TERM_HEIGHT - 3);
894 completion_buffer.buf = 0;
895 completion_buffer.len = 0;
896 completion_buffer.max_len = 0;
898 linep = screen->lines + screen->line;
899 saved_char = linep->buf[screen->column];
900 linep->buf[screen->column] = '\0';
902 insert = grub_normal_do_completion (linep->buf, &restore, store_completion);
904 linep->buf[screen->column] = saved_char;
906 if (restore)
908 char *p = completion_buffer.buf;
910 screen->completion_shown = 1;
912 if (p)
914 int num_sections = ((completion_buffer.len + GRUB_TERM_WIDTH - 8 - 1)
915 / (GRUB_TERM_WIDTH - 8));
916 char *endp;
918 p += (count % num_sections) * (GRUB_TERM_WIDTH - 8);
919 endp = p + (GRUB_TERM_WIDTH - 8);
921 if (p != completion_buffer.buf)
922 grub_putcode (GRUB_TERM_DISP_LEFT);
923 else
924 grub_putchar (' ');
926 while (*p && p < endp)
927 grub_putchar (*p++);
929 if (*p)
930 grub_putcode (GRUB_TERM_DISP_RIGHT);
934 grub_gotoxy (pos >> 8, pos & 0xFF);
936 if (insert)
938 insert_string (screen, insert, update);
939 count = -1;
940 grub_free (insert);
942 else if (update)
943 grub_refresh ();
945 grub_free (completion_buffer.buf);
946 return 1;
949 /* Clear displayed completions. */
950 static void
951 clear_completions (void)
953 grub_uint16_t pos;
954 int i, j;
956 pos = grub_getxy ();
957 grub_gotoxy (0, GRUB_TERM_HEIGHT - 3);
959 for (i = 0; i < 2; i++)
961 for (j = 0; j < GRUB_TERM_WIDTH - 1; j++)
962 grub_putchar (' ');
963 grub_putchar ('\n');
966 grub_gotoxy (pos >> 8, pos & 0xFF);
967 grub_refresh ();
970 /* Execute the command list in the screen SCREEN. */
971 static int
972 run (struct screen *screen)
974 int currline = 0;
975 char *nextline;
977 auto grub_err_t editor_getline (char **line, int cont);
978 grub_err_t editor_getline (char **line, int cont __attribute__ ((unused)))
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, 0);
1012 if (grub_parser_get_current ()->parse_line (nextline, editor_getline))
1013 break;
1016 if (grub_errno == GRUB_ERR_NONE && grub_loader_is_loaded ())
1017 /* Implicit execution of boot, only if something is loaded. */
1018 grub_command_execute ("boot", 0, 0);
1020 if (grub_errno != GRUB_ERR_NONE)
1022 grub_print_error ();
1023 grub_errno = GRUB_ERR_NONE;
1024 grub_wait_after_message ();
1027 return 1;
1030 /* Edit a menu entry with an Emacs-like interface. */
1031 void
1032 grub_menu_entry_run (grub_menu_entry_t entry)
1034 struct screen *screen;
1035 int prev_c;
1037 screen = make_screen (entry);
1038 if (! screen)
1039 return;
1041 refresh:
1042 /* Draw the screen. */
1043 grub_menu_init_page (0, 1);
1044 update_screen (screen, 0, 0, 1, 1, ALL_LINES);
1045 grub_setcursor (1);
1046 prev_c = '\0';
1048 while (1)
1050 int c = GRUB_TERM_ASCII_CHAR (grub_getkey ());
1052 if (screen->completion_shown)
1054 clear_completions ();
1055 screen->completion_shown = 0;
1058 switch (c)
1060 case 16: /* C-p */
1061 if (! previous_line (screen, 1))
1062 goto fail;
1063 break;
1065 case 14: /* C-n */
1066 if (! next_line (screen, 1))
1067 goto fail;
1068 break;
1070 case 6: /* C-f */
1071 if (! forward_char (screen, 1))
1072 goto fail;
1073 break;
1075 case 2: /* C-b */
1076 if (! backward_char (screen, 1))
1077 goto fail;
1078 break;
1080 case 1: /* C-a */
1081 if (! beginning_of_line (screen, 1))
1082 goto fail;
1083 break;
1085 case 5: /* C-e */
1086 if (! end_of_line (screen, 1))
1087 goto fail;
1088 break;
1090 case '\t': /* C-i */
1091 if (! complete (screen, prev_c == c, 1))
1092 goto fail;
1093 break;
1095 case 4: /* C-d */
1096 if (! delete_char (screen, 1))
1097 goto fail;
1098 break;
1100 case 8: /* C-h */
1101 if (! backward_delete_char (screen, 1))
1102 goto fail;
1103 break;
1105 case 11: /* C-k */
1106 if (! kill_line (screen, prev_c == c, 1))
1107 goto fail;
1108 break;
1110 case 21: /* C-u */
1111 /* FIXME: What behavior is good for this key? */
1112 break;
1114 case 25: /* C-y */
1115 if (! yank (screen, 1))
1116 goto fail;
1117 break;
1119 case 12: /* C-l */
1120 /* FIXME: centering. */
1121 goto refresh;
1123 case 15: /* C-o */
1124 if (! open_line (screen, 1))
1125 goto fail;
1126 break;
1128 case '\n':
1129 case '\r':
1130 if (! insert_string (screen, "\n", 1))
1131 goto fail;
1132 break;
1134 case '\e':
1135 destroy_screen (screen);
1136 return;
1138 case 3: /* C-c */
1139 grub_cmdline_run (1);
1140 goto refresh;
1142 case 24: /* C-x */
1143 if (! run (screen))
1144 goto fail;
1145 goto refresh;
1147 case 18: /* C-r */
1148 case 19: /* C-s */
1149 case 20: /* C-t */
1150 /* FIXME */
1151 break;
1153 default:
1154 if (grub_isprint (c))
1156 char buf[2];
1158 buf[0] = c;
1159 buf[1] = '\0';
1160 if (! insert_string (screen, buf, 1))
1161 goto fail;
1163 break;
1166 prev_c = c;
1169 fail:
1170 destroy_screen (screen);
1172 grub_cls ();
1173 grub_print_error ();
1174 grub_errno = GRUB_ERR_NONE;
1175 grub_printf ("\nPress any key to continue...");
1176 (void) grub_getkey ();