2 * GRUB -- GRand Unified Bootloader
3 * Copyright (C) 2005,2006,2007,2008,2009 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>
23 #include <grub/loader.h>
24 #include <grub/command.h>
25 #include <grub/parser.h>
26 #include <grub/auth.h>
27 #include <grub/i18n.h>
38 /* The line buffer. */
40 /* The length of the line. */
42 /* The maximum length of the line. */
46 struct per_term_screen
48 struct grub_term_output
*term
;
49 /* The X coordinate. */
51 /* The Y coordinate. */
57 /* The array of lines. */
59 /* The number of lines. */
61 /* The current column. */
63 /* The real column. */
65 /* The current line. */
67 /* The kill buffer. */
69 /* The flag of a completion window. */
72 struct per_term_screen
*terms
;
76 /* Used for storing completion items temporarily. */
77 static struct line completion_buffer
;
78 static int completion_type
;
80 /* Initialize a line. */
82 init_line (struct line
*linep
)
85 linep
->max_len
= 80; /* XXX */
86 linep
->buf
= grub_malloc (linep
->max_len
);
93 /* Allocate extra space if necessary. */
95 ensure_space (struct line
*linep
, int extra
)
97 if (linep
->max_len
< linep
->len
+ extra
)
99 linep
->max_len
= linep
->len
+ extra
+ 80; /* XXX */
100 linep
->buf
= grub_realloc (linep
->buf
, linep
->max_len
+ 1);
108 /* Return the number of lines occupied by this line on the screen. */
110 get_logical_num_lines (struct line
*linep
, struct per_term_screen
*term_screen
)
112 return (linep
->len
/ grub_term_entry_width (term_screen
->term
)) + 1;
117 print_line (struct line
*linep
, int offset
, int start
, int y
,
118 struct per_term_screen
*term_screen
)
120 grub_term_gotoxy (term_screen
->term
,
121 GRUB_TERM_LEFT_BORDER_X
+ GRUB_TERM_MARGIN
+ start
+ 1,
122 y
+ GRUB_TERM_FIRST_ENTRY_Y
);
124 if (linep
->len
>= offset
+ grub_term_entry_width (term_screen
->term
))
127 p
= linep
->buf
+ offset
+ grub_term_entry_width (term_screen
->term
);
130 grub_puts_terminal (linep
->buf
+ offset
+ start
, term_screen
->term
);
132 grub_putcode ('\\', term_screen
->term
);
139 p
= linep
->buf
+ linep
->len
;
142 grub_puts_terminal (linep
->buf
+ offset
+ start
, term_screen
->term
);
146 i
<= grub_term_entry_width (term_screen
->term
) - linep
->len
+ offset
;
148 grub_putcode (' ', term_screen
->term
);
152 /* Print an empty line. */
154 print_empty_line (int y
, struct per_term_screen
*term_screen
)
158 grub_term_gotoxy (term_screen
->term
,
159 GRUB_TERM_LEFT_BORDER_X
+ GRUB_TERM_MARGIN
+ 1,
160 y
+ GRUB_TERM_FIRST_ENTRY_Y
);
162 for (i
= 0; i
< grub_term_entry_width (term_screen
->term
) + 1; i
++)
163 grub_putcode (' ', term_screen
->term
);
166 /* Print an up arrow. */
168 print_up (int flag
, struct per_term_screen
*term_screen
)
170 grub_term_gotoxy (term_screen
->term
, GRUB_TERM_LEFT_BORDER_X
171 + grub_term_entry_width (term_screen
->term
),
172 GRUB_TERM_FIRST_ENTRY_Y
);
175 grub_putcode (GRUB_TERM_DISP_UP
, term_screen
->term
);
177 grub_putcode (' ', term_screen
->term
);
180 /* Print a down arrow. */
182 print_down (int flag
, struct per_term_screen
*term_screen
)
184 grub_term_gotoxy (term_screen
->term
, GRUB_TERM_LEFT_BORDER_X
185 + grub_term_border_width (term_screen
->term
),
186 GRUB_TERM_TOP_BORDER_Y
187 + grub_term_num_entries (term_screen
->term
));
190 grub_putcode (GRUB_TERM_DISP_DOWN
, term_screen
->term
);
192 grub_putcode (' ', term_screen
->term
);
195 /* Draw the lines of the screen SCREEN. */
197 update_screen (struct screen
*screen
, struct per_term_screen
*term_screen
,
198 int region_start
, int region_column
,
199 int up
, int down
, enum update_mode mode
)
207 /* Check if scrolling is necessary. */
208 if (term_screen
->y
< 0 || term_screen
->y
209 >= grub_term_num_entries (term_screen
->term
))
211 if (term_screen
->y
< 0)
214 term_screen
->y
= grub_term_num_entries (term_screen
->term
) - 1;
225 /* Draw lines. This code is tricky, because this must calculate logical
227 y
= term_screen
->y
- screen
->column
228 / grub_term_entry_width (term_screen
->term
);
230 linep
= screen
->lines
+ i
;
235 y
-= get_logical_num_lines (linep
, term_screen
);
247 && y
< grub_term_num_entries (term_screen
->term
);
248 column
+= grub_term_entry_width (term_screen
->term
), y
++)
253 if (i
== region_start
)
255 if (region_column
>= column
258 + grub_term_entry_width (term_screen
->term
)))
259 print_line (linep
, column
, region_column
- column
, y
,
261 else if (region_column
< column
)
262 print_line (linep
, column
, 0, y
, term_screen
);
264 else if (i
> region_start
&& mode
== ALL_LINES
)
265 print_line (linep
, column
, 0, y
, term_screen
);
268 if (y
== grub_term_num_entries (term_screen
->term
))
270 if (column
<= linep
->len
|| i
+ 1 < screen
->num_lines
)
277 if (mode
== ALL_LINES
&& i
== screen
->num_lines
)
278 for (; y
< grub_term_num_entries (term_screen
->term
); y
++)
279 print_empty_line (y
, term_screen
);
282 while (y
< grub_term_num_entries (term_screen
->term
));
284 /* Draw up and down arrows. */
286 print_up (up_flag
, term_screen
);
288 print_down (down_flag
, term_screen
);
291 /* Place the cursor. */
292 grub_term_gotoxy (term_screen
->term
,
293 GRUB_TERM_LEFT_BORDER_X
+ GRUB_TERM_MARGIN
+ 1
295 GRUB_TERM_FIRST_ENTRY_Y
+ term_screen
->y
);
297 grub_term_refresh (term_screen
->term
);
301 update_screen_all (struct screen
*screen
,
302 int region_start
, int region_column
,
303 int up
, int down
, enum update_mode mode
)
306 for (i
= 0; i
< screen
->nterms
; i
++)
307 update_screen (screen
, &screen
->terms
[i
], region_start
, region_column
,
312 insert_string (struct screen
*screen
, char *s
, int update
)
314 int region_start
= screen
->num_lines
;
315 int region_column
= 0;
316 int down
[screen
->nterms
];
317 enum update_mode mode
[screen
->nterms
];
320 for (i
= 0; i
< screen
->nterms
; i
++)
330 /* LF is special because it creates a new line. */
331 struct line
*current_linep
;
332 struct line
*next_linep
;
335 /* Make a new line. */
337 screen
->lines
= grub_realloc (screen
->lines
,
339 * sizeof (struct line
));
344 grub_memmove (screen
->lines
+ screen
->line
+ 2,
345 screen
->lines
+ screen
->line
+ 1,
346 ((screen
->num_lines
- screen
->line
- 2)
347 * sizeof (struct line
)));
349 if (! init_line (screen
->lines
+ screen
->line
+ 1))
353 current_linep
= screen
->lines
+ screen
->line
;
354 next_linep
= current_linep
+ 1;
355 size
= current_linep
->len
- screen
->column
;
357 if (! ensure_space (next_linep
, size
))
360 grub_memmove (next_linep
->buf
,
361 current_linep
->buf
+ screen
->column
,
363 current_linep
->len
= screen
->column
;
364 next_linep
->len
= size
;
366 /* Update a dirty region. */
367 if (region_start
> screen
->line
)
369 region_start
= screen
->line
;
370 region_column
= screen
->column
;
373 for (i
= 0; i
< screen
->nterms
; i
++)
376 down
[i
] = 1; /* XXX not optimal. */
379 /* Move the cursor. */
380 screen
->column
= screen
->real_column
= 0;
382 for (i
= 0; i
< screen
->nterms
; i
++)
384 screen
->terms
[i
].x
= 0;
385 screen
->terms
[i
].y
++;
393 struct line
*current_linep
;
395 int orig_num
[screen
->nterms
], new_num
[screen
->nterms
];
397 /* Find a string delimited by LF. */
398 p
= grub_strchr (s
, '\n');
400 p
= s
+ grub_strlen (s
);
402 /* Insert the string. */
403 current_linep
= screen
->lines
+ screen
->line
;
405 if (! ensure_space (current_linep
, size
))
408 grub_memmove (current_linep
->buf
+ screen
->column
+ size
,
409 current_linep
->buf
+ screen
->column
,
410 current_linep
->len
- screen
->column
);
411 grub_memmove (current_linep
->buf
+ screen
->column
,
414 for (i
= 0; i
< screen
->nterms
; i
++)
415 orig_num
[i
] = get_logical_num_lines (current_linep
,
417 current_linep
->len
+= size
;
418 for (i
= 0; i
< screen
->nterms
; i
++)
419 new_num
[i
] = get_logical_num_lines (current_linep
,
422 /* Update the dirty region. */
423 if (region_start
> screen
->line
)
425 region_start
= screen
->line
;
426 region_column
= screen
->column
;
429 for (i
= 0; i
< screen
->nterms
; i
++)
430 if (orig_num
[i
] != new_num
[i
])
433 down
[i
] = 1; /* XXX not optimal. */
435 else if (mode
[i
] != ALL_LINES
)
436 mode
[i
] = SINGLE_LINE
;
438 /* Move the cursor. */
439 screen
->column
+= size
;
440 screen
->real_column
= screen
->column
;
441 for (i
= 0; i
< screen
->nterms
; i
++)
443 screen
->terms
[i
].x
+= size
;
444 screen
->terms
[i
].y
+= screen
->terms
[i
].x
445 / grub_term_entry_width (screen
->terms
[i
].term
);
447 %= grub_term_entry_width (screen
->terms
[i
].term
);
454 for (i
= 0; i
< screen
->nterms
; i
++)
455 update_screen (screen
, &screen
->terms
[i
],
456 region_start
, region_column
, 0, down
[i
], mode
[i
]);
461 /* Release the resource allocated for SCREEN. */
463 destroy_screen (struct screen
*screen
)
468 for (i
= 0; i
< screen
->num_lines
; i
++)
470 struct line
*linep
= screen
->lines
+ i
;
473 grub_free (linep
->buf
);
476 grub_free (screen
->killed_text
);
477 grub_free (screen
->lines
);
478 grub_free (screen
->terms
);
482 /* Make a new screen. */
483 static struct screen
*
484 make_screen (grub_menu_entry_t entry
)
486 struct screen
*screen
;
489 /* Initialize the screen. */
490 screen
= grub_zalloc (sizeof (*screen
));
494 screen
->num_lines
= 1;
495 screen
->lines
= grub_malloc (sizeof (struct line
));
499 /* Initialize the first line which must be always present. */
500 if (! init_line (screen
->lines
))
503 insert_string (screen
, (char *) entry
->sourcecode
, 0);
505 /* Reset the cursor position. */
507 screen
->real_column
= 0;
509 for (i
= 0; i
< screen
->nterms
; i
++)
511 screen
->terms
[i
].x
= 0;
512 screen
->terms
[i
].y
= 0;
518 destroy_screen (screen
);
523 forward_char (struct screen
*screen
, int update
)
528 linep
= screen
->lines
+ screen
->line
;
529 if (screen
->column
< linep
->len
)
532 for (i
= 0; i
< screen
->nterms
; i
++)
534 screen
->terms
[i
].x
++;
535 if (screen
->terms
[i
].x
536 == grub_term_entry_width (screen
->terms
[i
].term
))
538 screen
->terms
[i
].x
= 0;
539 screen
->terms
[i
].y
++;
543 else if (screen
->num_lines
> screen
->line
+ 1)
547 for (i
= 0; i
< screen
->nterms
; i
++)
549 screen
->terms
[i
].x
= 0;
550 screen
->terms
[i
].y
++;
554 screen
->real_column
= screen
->column
;
557 update_screen_all (screen
, screen
->num_lines
, 0, 0, 0, NO_LINE
);
562 backward_char (struct screen
*screen
, int update
)
566 if (screen
->column
> 0)
569 for (i
= 0; i
< screen
->nterms
; i
++)
571 screen
->terms
[i
].x
--;
572 if (screen
->terms
[i
].x
== -1)
575 = grub_term_entry_width (screen
->terms
[i
].term
) - 1;
576 screen
->terms
[i
].y
--;
580 else if (screen
->line
> 0)
585 linep
= screen
->lines
+ screen
->line
;
586 screen
->column
= linep
->len
;
587 for (i
= 0; i
< screen
->nterms
; i
++)
589 screen
->terms
[i
].x
= screen
->column
590 % grub_term_entry_width (screen
->terms
[i
].term
);
591 screen
->terms
[i
].y
--;
595 screen
->real_column
= screen
->column
;
598 update_screen_all (screen
, screen
->num_lines
, 0, 0, 0, NO_LINE
);
604 previous_line (struct screen
*screen
, int update
)
608 if (screen
->line
> 0)
613 /* How many physical lines from the current position
614 to the first physical line? */
615 col
= screen
->column
;
619 linep
= screen
->lines
+ screen
->line
;
620 if (linep
->len
< screen
->real_column
)
621 screen
->column
= linep
->len
;
623 screen
->column
= screen
->real_column
;
625 for (i
= 0; i
< screen
->nterms
; i
++)
628 dy
= col
/ grub_term_entry_width (screen
->terms
[i
].term
);
630 /* How many physical lines from the current position
631 to the last physical line? */
632 dy
+= (linep
->len
/ grub_term_entry_width (screen
->terms
[i
].term
)
634 / grub_term_entry_width (screen
->terms
[i
].term
));
636 screen
->terms
[i
].y
-= dy
+ 1;
638 = screen
->column
% grub_term_entry_width (screen
->terms
[i
].term
);
643 for (i
= 0; i
< screen
->nterms
; i
++)
646 -= screen
->column
/ grub_term_entry_width (screen
->terms
[i
].term
);
647 screen
->terms
[i
].x
= 0;
653 update_screen_all (screen
, screen
->num_lines
, 0, 0, 0, NO_LINE
);
659 next_line (struct screen
*screen
, int update
)
663 if (screen
->line
< screen
->num_lines
- 1)
668 /* How many physical lines from the current position
669 to the last physical line? */
670 linep
= screen
->lines
+ screen
->line
;
677 if (linep
->len
< screen
->real_column
)
678 screen
->column
= linep
->len
;
680 screen
->column
= screen
->real_column
;
682 for (i
= 0; i
< screen
->nterms
; i
++)
685 dy
= l1
/ grub_term_entry_width (screen
->terms
[i
].term
)
686 - c1
/ grub_term_entry_width (screen
->terms
[i
].term
);
687 /* How many physical lines from the current position
688 to the first physical line? */
689 dy
+= screen
->column
/ grub_term_entry_width (screen
->terms
[i
].term
);
690 screen
->terms
[i
].y
+= dy
+ 1;
691 screen
->terms
[i
].x
= screen
->column
692 % grub_term_entry_width (screen
->terms
[i
].term
);
700 linep
= screen
->lines
+ screen
->line
;
703 screen
->column
= linep
->len
;
704 for (i
= 0; i
< screen
->nterms
; i
++)
707 += (l
/ grub_term_entry_width (screen
->terms
[i
].term
)
708 - s
/ grub_term_entry_width (screen
->terms
[i
].term
));
710 = screen
->column
% grub_term_entry_width (screen
->terms
[i
].term
);
715 update_screen_all (screen
, screen
->num_lines
, 0, 0, 0, NO_LINE
);
721 beginning_of_line (struct screen
*screen
, int update
)
726 col
= screen
->column
;
727 screen
->column
= screen
->real_column
= 0;
728 for (i
= 0; i
< screen
->nterms
; i
++)
730 screen
->terms
[i
].x
= 0;
731 screen
->terms
[i
].y
-= col
/ grub_term_entry_width (screen
->terms
[i
].term
);
735 update_screen_all (screen
, screen
->num_lines
, 0, 0, 0, NO_LINE
);
741 end_of_line (struct screen
*screen
, int update
)
747 linep
= screen
->lines
+ screen
->line
;
748 col
= screen
->column
;
749 screen
->column
= screen
->real_column
= linep
->len
;
750 for (i
= 0; i
< screen
->nterms
; i
++)
753 += (linep
->len
/ grub_term_entry_width (screen
->terms
->term
)
754 - col
/ grub_term_entry_width (screen
->terms
->term
));
756 = screen
->column
% grub_term_entry_width (screen
->terms
->term
);
760 update_screen_all (screen
, screen
->num_lines
, 0, 0, 0, NO_LINE
);
766 delete_char (struct screen
*screen
, int update
)
769 int start
= screen
->num_lines
;
772 linep
= screen
->lines
+ screen
->line
;
773 if (linep
->len
> screen
->column
)
775 int orig_num
[screen
->nterms
], new_num
;
778 for (i
= 0; i
< screen
->nterms
; i
++)
779 orig_num
[i
] = get_logical_num_lines (linep
, &screen
->terms
[i
]);
781 grub_memmove (linep
->buf
+ screen
->column
,
782 linep
->buf
+ screen
->column
+ 1,
783 linep
->len
- screen
->column
- 1);
786 start
= screen
->line
;
787 column
= screen
->column
;
789 screen
->real_column
= screen
->column
;
793 for (i
= 0; i
< screen
->nterms
; i
++)
795 new_num
= get_logical_num_lines (linep
, &screen
->terms
[i
]);
796 if (orig_num
[i
] != new_num
)
797 update_screen (screen
, &screen
->terms
[i
],
798 start
, column
, 0, 0, ALL_LINES
);
800 update_screen (screen
, &screen
->terms
[i
],
801 start
, column
, 0, 0, SINGLE_LINE
);
805 else if (screen
->num_lines
> screen
->line
+ 1)
807 struct line
*next_linep
;
809 next_linep
= linep
+ 1;
810 if (! ensure_space (linep
, next_linep
->len
))
813 grub_memmove (linep
->buf
+ linep
->len
, next_linep
->buf
, next_linep
->len
);
814 linep
->len
+= next_linep
->len
;
816 grub_free (next_linep
->buf
);
817 grub_memmove (next_linep
,
819 (screen
->num_lines
- screen
->line
- 2)
820 * sizeof (struct line
));
823 start
= screen
->line
;
824 column
= screen
->column
;
826 screen
->real_column
= screen
->column
;
828 update_screen_all (screen
, start
, column
, 0, 1, ALL_LINES
);
835 backward_delete_char (struct screen
*screen
, int update
)
840 saved_column
= screen
->column
;
841 saved_line
= screen
->line
;
843 if (! backward_char (screen
, 0))
846 if (saved_column
!= screen
->column
|| saved_line
!= screen
->line
)
847 if (! delete_char (screen
, update
))
854 kill_line (struct screen
*screen
, int continuous
, int update
)
861 p
= screen
->killed_text
;
862 if (! continuous
&& p
)
865 linep
= screen
->lines
+ screen
->line
;
866 size
= linep
->len
- screen
->column
;
869 offset
= grub_strlen (p
);
875 int orig_num
[screen
->nterms
], new_num
;
878 p
= grub_realloc (p
, offset
+ size
+ 1);
882 grub_memmove (p
+ offset
, linep
->buf
+ screen
->column
, size
);
883 p
[offset
+ size
- 1] = '\0';
885 screen
->killed_text
= p
;
887 for (i
= 0; i
< screen
->nterms
; i
++)
888 orig_num
[i
] = get_logical_num_lines (linep
, &screen
->terms
[i
]);
889 linep
->len
= screen
->column
;
893 new_num
= get_logical_num_lines (linep
, &screen
->terms
[i
]);
894 for (i
= 0; i
< screen
->nterms
; i
++)
896 if (orig_num
[i
] != new_num
)
897 update_screen (screen
, &screen
->terms
[i
],
898 screen
->line
, screen
->column
, 0, 1, ALL_LINES
);
900 update_screen (screen
, &screen
->terms
[i
],
901 screen
->line
, screen
->column
, 0, 0, SINGLE_LINE
);
905 else if (screen
->line
+ 1 < screen
->num_lines
)
907 p
= grub_realloc (p
, offset
+ 1 + 1);
912 p
[offset
+ 1] = '\0';
914 screen
->killed_text
= p
;
916 return delete_char (screen
, update
);
923 yank (struct screen
*screen
, int update
)
925 if (screen
->killed_text
)
926 return insert_string (screen
, screen
->killed_text
, update
);
932 open_line (struct screen
*screen
, int update
)
934 int saved_y
[screen
->nterms
];
937 for (i
= 0; i
< screen
->nterms
; i
++)
938 saved_y
[i
] = screen
->terms
[i
].y
;
940 if (! insert_string (screen
, "\n", 0))
943 if (! backward_char (screen
, 0))
946 for (i
= 0; i
< screen
->nterms
; i
++)
947 screen
->terms
[i
].y
= saved_y
[i
];
950 update_screen_all (screen
, screen
->line
, screen
->column
, 0, 1, ALL_LINES
);
955 /* A completion hook to print items. */
957 store_completion (const char *item
, grub_completion_type_t type
,
958 int count
__attribute__ ((unused
)))
962 completion_type
= type
;
964 /* Make sure that the completion buffer has enough room. */
965 if (completion_buffer
.max_len
< (completion_buffer
.len
966 + (int) grub_strlen (item
) + 1 + 1))
970 new_len
= completion_buffer
.len
+ grub_strlen (item
) + 80;
971 p
= grub_realloc (completion_buffer
.buf
, new_len
);
974 /* Possibly not fatal. */
975 grub_errno
= GRUB_ERR_NONE
;
978 p
[completion_buffer
.len
] = 0;
979 completion_buffer
.buf
= p
;
980 completion_buffer
.max_len
= new_len
;
983 p
= completion_buffer
.buf
+ completion_buffer
.len
;
984 if (completion_buffer
.len
!= 0)
987 completion_buffer
.len
++;
989 grub_strcpy (p
, item
);
990 completion_buffer
.len
+= grub_strlen (item
);
994 complete (struct screen
*screen
, int continuous
, int update
)
1000 static int count
= -1;
1002 grub_uint32_t
*ucs4
;
1004 grub_ssize_t ucs4len
;
1011 completion_buffer
.buf
= 0;
1012 completion_buffer
.len
= 0;
1013 completion_buffer
.max_len
= 0;
1015 linep
= screen
->lines
+ screen
->line
;
1016 saved_char
= linep
->buf
[screen
->column
];
1017 linep
->buf
[screen
->column
] = '\0';
1019 insert
= grub_normal_do_completion (linep
->buf
, &restore
, store_completion
);
1021 linep
->buf
[screen
->column
] = saved_char
;
1023 buflen
= grub_strlen (completion_buffer
.buf
);
1024 ucs4
= grub_malloc (sizeof (grub_uint32_t
) * (buflen
+ 1));
1028 grub_print_error ();
1029 grub_errno
= GRUB_ERR_NONE
;
1033 ucs4len
= grub_utf8_to_ucs4 (ucs4
, buflen
,
1034 (grub_uint8_t
*) completion_buffer
.buf
,
1039 for (i
= 0; i
< screen
->nterms
; i
++)
1041 int num_sections
= ((completion_buffer
.len
1042 + grub_term_width (screen
->terms
[i
].term
) - 8 - 1)
1043 / (grub_term_width (screen
->terms
[i
].term
) - 8));
1044 grub_uint32_t
*endp
;
1046 grub_uint32_t
*p
= ucs4
;
1048 pos
= grub_term_getxy (screen
->terms
[i
].term
);
1049 grub_term_gotoxy (screen
->terms
[i
].term
, 0,
1050 grub_term_height (screen
->terms
[i
].term
) - 3);
1052 screen
->completion_shown
= 1;
1054 grub_term_gotoxy (screen
->terms
[i
].term
, 0,
1055 grub_term_height (screen
->terms
[i
].term
) - 3);
1056 grub_puts_terminal (" ", screen
->terms
[i
].term
);
1057 switch (completion_type
)
1059 case GRUB_COMPLETION_TYPE_COMMAND
:
1060 grub_puts_terminal (_("Possible commands are:"),
1061 screen
->terms
[i
].term
);
1063 case GRUB_COMPLETION_TYPE_DEVICE
:
1064 grub_puts_terminal (_("Possible devices are:"),
1065 screen
->terms
[i
].term
);
1067 case GRUB_COMPLETION_TYPE_FILE
:
1068 grub_puts_terminal (_("Possible files are:"),
1069 screen
->terms
[i
].term
);
1071 case GRUB_COMPLETION_TYPE_PARTITION
:
1072 grub_puts_terminal (_("Possible partitions are:"),
1073 screen
->terms
[i
].term
);
1075 case GRUB_COMPLETION_TYPE_ARGUMENT
:
1076 grub_puts_terminal (_("Possible arguments are:"),
1077 screen
->terms
[i
].term
);
1080 grub_puts_terminal (_("Possible things are:"),
1081 screen
->terms
[i
].term
);
1085 grub_puts_terminal ("\n ", screen
->terms
[i
].term
);
1087 p
+= (count
% num_sections
)
1088 * (grub_term_width (screen
->terms
[i
].term
) - 8);
1089 endp
= p
+ (grub_term_width (screen
->terms
[i
].term
) - 8);
1092 grub_putcode (GRUB_TERM_DISP_LEFT
, screen
->terms
[i
].term
);
1094 grub_putcode (' ', screen
->terms
[i
].term
);
1096 while (*p
&& p
< endp
)
1097 grub_putcode (*p
++, screen
->terms
[i
].term
);
1100 grub_putcode (GRUB_TERM_DISP_RIGHT
, screen
->terms
[i
].term
);
1101 grub_term_gotoxy (screen
->terms
[i
].term
, pos
>> 8, pos
& 0xFF);
1106 insert_string (screen
, insert
, update
);
1113 grub_free (completion_buffer
.buf
);
1117 /* Clear displayed completions. */
1119 clear_completions (struct per_term_screen
*term_screen
)
1124 pos
= grub_term_getxy (term_screen
->term
);
1125 grub_term_gotoxy (term_screen
->term
, 0,
1126 grub_term_height (term_screen
->term
) - 3);
1128 for (i
= 0; i
< 2; i
++)
1130 for (j
= 0; j
< grub_term_width (term_screen
->term
) - 1; j
++)
1131 grub_putcode (' ', term_screen
->term
);
1132 grub_putcode ('\n', term_screen
->term
);
1135 grub_term_gotoxy (term_screen
->term
, pos
>> 8, pos
& 0xFF);
1136 grub_term_refresh (term_screen
->term
);
1140 clear_completions_all (struct screen
*screen
)
1144 for (i
= 0; i
< screen
->nterms
; i
++)
1145 clear_completions (&screen
->terms
[i
]);
1148 /* Execute the command list in the screen SCREEN. */
1150 run (struct screen
*screen
)
1155 auto grub_err_t
editor_getline (char **line
, int cont
);
1156 grub_err_t
editor_getline (char **line
, int cont
__attribute__ ((unused
)))
1158 struct line
*linep
= screen
->lines
+ currline
;
1161 if (currline
> screen
->num_lines
)
1167 /* Trim down space characters. */
1168 for (p
= linep
->buf
+ linep
->len
- 1;
1169 p
>= linep
->buf
&& grub_isspace (*p
);
1174 linep
->len
= p
- linep
->buf
;
1175 for (p
= linep
->buf
; grub_isspace (*p
); p
++)
1177 *line
= grub_strdup (p
);
1184 grub_printf_ (N_("Booting a command list"));
1185 grub_printf ("\n\n");
1188 /* Execute the script, line for line. */
1189 while (currline
< screen
->num_lines
)
1191 editor_getline (&nextline
, 0);
1192 if (grub_parser_get_current ()->parse_line (nextline
, editor_getline
))
1196 if (grub_errno
== GRUB_ERR_NONE
&& grub_loader_is_loaded ())
1197 /* Implicit execution of boot, only if something is loaded. */
1198 grub_command_execute ("boot", 0, 0);
1200 if (grub_errno
!= GRUB_ERR_NONE
)
1202 grub_print_error ();
1203 grub_errno
= GRUB_ERR_NONE
;
1204 grub_wait_after_message ();
1210 /* Edit a menu entry with an Emacs-like interface. */
1212 grub_menu_entry_run (grub_menu_entry_t entry
)
1214 struct screen
*screen
;
1216 grub_err_t err
= GRUB_ERR_NONE
;
1218 grub_term_output_t term
;
1220 err
= grub_auth_check_authentication (NULL
);
1224 grub_print_error ();
1225 grub_errno
= GRUB_ERR_NONE
;
1229 screen
= make_screen (entry
);
1233 screen
->terms
= NULL
;
1236 grub_free (screen
->terms
);
1238 FOR_ACTIVE_TERM_OUTPUTS(term
)
1240 screen
->terms
= grub_malloc (screen
->nterms
* sizeof (screen
->terms
[0]));
1243 grub_print_error ();
1244 grub_errno
= GRUB_ERR_NONE
;
1248 FOR_ACTIVE_TERM_OUTPUTS(term
)
1250 screen
->terms
[i
].term
= term
;
1251 screen
->terms
[i
].x
= 0;
1252 screen
->terms
[i
].y
= 0;
1255 /* Draw the screen. */
1256 for (i
= 0; i
< screen
->nterms
; i
++)
1257 grub_menu_init_page (0, 1, screen
->terms
[i
].term
);
1258 update_screen_all (screen
, 0, 0, 1, 1, ALL_LINES
);
1259 for (i
= 0; i
< screen
->nterms
; i
++)
1260 grub_term_setcursor (screen
->terms
[i
].term
, 1);
1265 int c
= GRUB_TERM_ASCII_CHAR (grub_getkey ());
1267 if (screen
->completion_shown
)
1269 clear_completions_all (screen
);
1270 screen
->completion_shown
= 0;
1273 if (grub_normal_exit_level
)
1275 destroy_screen (screen
);
1282 if (! previous_line (screen
, 1))
1287 if (! next_line (screen
, 1))
1292 if (! forward_char (screen
, 1))
1297 if (! backward_char (screen
, 1))
1302 if (! beginning_of_line (screen
, 1))
1307 if (! end_of_line (screen
, 1))
1311 case '\t': /* C-i */
1312 if (! complete (screen
, prev_c
== c
, 1))
1317 if (! delete_char (screen
, 1))
1322 if (! backward_delete_char (screen
, 1))
1327 if (! kill_line (screen
, prev_c
== c
, 1))
1332 /* FIXME: What behavior is good for this key? */
1336 if (! yank (screen
, 1))
1341 /* FIXME: centering. */
1345 if (! open_line (screen
, 1))
1351 if (! insert_string (screen
, "\n", 1))
1356 destroy_screen (screen
);
1360 grub_cmdline_run (1);
1375 if (grub_isprint (c
))
1381 if (! insert_string (screen
, buf
, 1))
1391 destroy_screen (screen
);
1394 grub_print_error ();
1395 grub_errno
= GRUB_ERR_NONE
;
1396 grub_putchar ('\n');
1397 grub_printf_ (N_("Press any key to continue..."));
1398 (void) grub_getkey ();