~hamo/ubuntu/precise/grub2/grub2.hi_res

« back to all changes in this revision

Viewing changes to grub-core/normal/menu_entry.c

  • Committer: Bazaar Package Importer
  • Author(s): Colin Watson, Colin Watson, Robert Millan, Updated translations
  • Date: 2010-11-22 12:24:56 UTC
  • mfrom: (1.26.4 upstream) (17.3.36 sid)
  • mto: (17.3.43 sid)
  • mto: This revision was merged to the branch mainline in revision 89.
  • Revision ID: james.westby@ubuntu.com-20101122122456-y82z3sfb7k4zfdcc
Tags: 1.99~20101122-1
[ Colin Watson ]
* New Bazaar snapshot.  Too many changes to list in full, but some of the
  more user-visible ones are as follows:
  - GRUB script:
    + Function parameters, "break", "continue", "shift", "setparams",
      "return", and "!".
    + "export" command supports multiple variable names.
    + Multi-line quoted strings support.
    + Wildcard expansion.
  - sendkey support.
  - USB hotunplugging and USB serial support.
  - Rename CD-ROM to cd on BIOS.
  - Add new --boot-directory option to grub-install, grub-reboot, and
    grub-set-default; the old --root-directory option is still accepted
    but was often confusing.
  - Basic btrfs detection/UUID support (but no file reading yet).
  - bash-completion for utilities.
  - If a device is listed in device.map, always assume that it is
    BIOS-visible rather than using extra layers such as LVM or RAID.
  - Add grub-mknetdir script (closes: #550658).
  - Remove deprecated "root" command.
  - Handle RAID devices containing virtio components.
  - GRUB Legacy configuration file support (via grub-menulst2cfg).
  - Keyboard layout support (via grub-mklayout and grub-kbdcomp).
  - Check generated grub.cfg for syntax errors before saving.
  - Pause execution for at most ten seconds if any errors are displayed,
    so that the user has a chance to see them.
  - Support submenus.
  - Write embedding zone using Reed-Solomon, so that it's robust against
    being partially overwritten (closes: #550702, #591416, #593347).
  - GRUB_DISABLE_LINUX_RECOVERY and GRUB_DISABLE_NETBSD_RECOVERY merged
    into a single GRUB_DISABLE_RECOVERY variable.
  - Fix loader memory allocation failure (closes: #551627).
  - Don't call savedefault on recovery entries (closes: #589325).
  - Support triple-indirect blocks on ext2 (closes: #543924).
  - Recognise DDF1 fake RAID (closes: #603354).

[ Robert Millan ]
* Use dpkg architecture wildcards.

[ Updated translations ]
* Slovenian (Vanja Cvelbar).  Closes: #604003
* Dzongkha (dawa pemo via Tenzin Dendup).  Closes: #604102

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *  GRUB  --  GRand Unified Bootloader
 
3
 *  Copyright (C) 2005,2006,2007,2008,2009  Free Software Foundation, Inc.
 
4
 *
 
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.
 
9
 *
 
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.
 
14
 *
 
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/>.
 
17
 */
 
18
 
 
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>
 
26
#include <grub/script_sh.h>
 
27
#include <grub/auth.h>
 
28
#include <grub/i18n.h>
 
29
#include <grub/charset.h>
 
30
 
 
31
enum update_mode
 
32
  {
 
33
    NO_LINE,
 
34
    SINGLE_LINE,
 
35
    ALL_LINES
 
36
  };
 
37
 
 
38
struct line
 
39
{
 
40
  /* The line buffer.  */
 
41
  char *buf;
 
42
  /* The length of the line.  */
 
43
  int len;
 
44
  /* The maximum length of the line.  */
 
45
  int max_len;
 
46
};
 
47
 
 
48
struct per_term_screen
 
49
{
 
50
  struct grub_term_output *term;
 
51
  /* The X coordinate.  */
 
52
  int x;
 
53
  /* The Y coordinate.  */
 
54
  int y;
 
55
};
 
56
 
 
57
struct screen
 
58
{
 
59
  /* The array of lines.  */
 
60
  struct line *lines;
 
61
  /* The number of lines.  */
 
62
  int num_lines;
 
63
  /* The current column.  */
 
64
  int column;
 
65
  /* The real column.  */
 
66
  int real_column;
 
67
  /* The current line.  */
 
68
  int line;
 
69
  /* The kill buffer.  */
 
70
  char *killed_text;
 
71
  /* The flag of a completion window.  */
 
72
  int completion_shown;
 
73
 
 
74
  int submenu;
 
75
 
 
76
  struct per_term_screen *terms;
 
77
  unsigned nterms;
 
78
};
 
79
 
 
80
/* Used for storing completion items temporarily.  */
 
81
static struct line completion_buffer;
 
82
static int completion_type;
 
83
 
 
84
/* Initialize a line.  */
 
85
static int
 
86
init_line (struct line *linep)
 
87
{
 
88
  linep->len = 0;
 
89
  linep->max_len = 80; /* XXX */
 
90
  linep->buf = grub_malloc (linep->max_len);
 
91
  if (! linep->buf)
 
92
    return 0;
 
93
 
 
94
  return 1;
 
95
}
 
96
 
 
97
/* Allocate extra space if necessary.  */
 
98
static int
 
99
ensure_space (struct line *linep, int extra)
 
100
{
 
101
  if (linep->max_len < linep->len + extra)
 
102
    {
 
103
      linep->max_len = linep->len + extra + 80; /* XXX */
 
104
      linep->buf = grub_realloc (linep->buf, linep->max_len + 1);
 
105
      if (! linep->buf)
 
106
        return 0;
 
107
    }
 
108
 
 
109
  return 1;
 
110
}
 
111
 
 
112
/* Return the number of lines occupied by this line on the screen.  */
 
113
static int
 
114
get_logical_num_lines (struct line *linep, struct per_term_screen *term_screen)
 
115
{
 
116
  return (linep->len / grub_term_entry_width (term_screen->term)) + 1;
 
117
}
 
118
 
 
119
/* Print a line.  */
 
120
static void
 
121
print_line (struct line *linep, int offset, int start, int y,
 
122
            struct per_term_screen *term_screen)
 
123
{
 
124
  grub_term_gotoxy (term_screen->term, 
 
125
                    GRUB_TERM_LEFT_BORDER_X + GRUB_TERM_MARGIN + start + 1,
 
126
                    y + GRUB_TERM_FIRST_ENTRY_Y);
 
127
 
 
128
  if (linep->len >= offset + grub_term_entry_width (term_screen->term))
 
129
    {
 
130
      char *p, c;
 
131
      p = linep->buf + offset + grub_term_entry_width (term_screen->term);
 
132
      c = *p;
 
133
      *p = 0;
 
134
      grub_puts_terminal (linep->buf + offset + start, term_screen->term);
 
135
      *p = c;
 
136
      grub_putcode ('\\', term_screen->term);
 
137
    }
 
138
  else
 
139
    {
 
140
      int i;
 
141
      char *p, c;
 
142
 
 
143
      p = linep->buf + linep->len;
 
144
      c = *p;
 
145
      *p = 0;
 
146
      grub_puts_terminal (linep->buf + offset + start, term_screen->term);
 
147
      *p = c;
 
148
 
 
149
      for (i = 0;
 
150
           i <= grub_term_entry_width (term_screen->term) - linep->len + offset;
 
151
           i++)
 
152
        grub_putcode (' ', term_screen->term);
 
153
    }
 
154
}
 
155
 
 
156
/* Print an empty line.  */
 
157
static void
 
158
print_empty_line (int y, struct per_term_screen *term_screen)
 
159
{
 
160
  int i;
 
161
 
 
162
  grub_term_gotoxy (term_screen->term,
 
163
                    GRUB_TERM_LEFT_BORDER_X + GRUB_TERM_MARGIN + 1,
 
164
                    y + GRUB_TERM_FIRST_ENTRY_Y);
 
165
 
 
166
  for (i = 0; i < grub_term_entry_width (term_screen->term) + 1; i++)
 
167
    grub_putcode (' ', term_screen->term);
 
168
}
 
169
 
 
170
/* Print an up arrow.  */
 
171
static void
 
172
print_up (int flag, struct per_term_screen *term_screen)
 
173
{
 
174
  grub_term_gotoxy (term_screen->term, GRUB_TERM_LEFT_BORDER_X 
 
175
                    + grub_term_border_width (term_screen->term),
 
176
                    GRUB_TERM_FIRST_ENTRY_Y);
 
177
 
 
178
  if (flag)
 
179
    grub_putcode (GRUB_UNICODE_UPARROW, term_screen->term);
 
180
  else
 
181
    grub_putcode (' ', term_screen->term);
 
182
}
 
183
 
 
184
/* Print a down arrow.  */
 
185
static void
 
186
print_down (int flag, struct per_term_screen *term_screen)
 
187
{
 
188
  grub_term_gotoxy (term_screen->term, GRUB_TERM_LEFT_BORDER_X
 
189
                    + grub_term_border_width (term_screen->term),
 
190
                    GRUB_TERM_TOP_BORDER_Y 
 
191
                    + grub_term_num_entries (term_screen->term));
 
192
 
 
193
  if (flag)
 
194
    grub_putcode (GRUB_UNICODE_DOWNARROW, term_screen->term);
 
195
  else
 
196
    grub_putcode (' ', term_screen->term);
 
197
}
 
198
 
 
199
/* Draw the lines of the screen SCREEN.  */
 
200
static void
 
201
update_screen (struct screen *screen, struct per_term_screen *term_screen,
 
202
               int region_start, int region_column,
 
203
               int up, int down, enum update_mode mode)
 
204
{
 
205
  int up_flag = 0;
 
206
  int down_flag = 0;
 
207
  int y;
 
208
  int i;
 
209
  struct line *linep;
 
210
 
 
211
  /* Check if scrolling is necessary.  */
 
212
  if (term_screen->y < 0 || term_screen->y
 
213
      >= grub_term_num_entries (term_screen->term))
 
214
    {
 
215
      if (term_screen->y < 0)
 
216
        term_screen->y = 0;
 
217
      else
 
218
        term_screen->y = grub_term_num_entries (term_screen->term) - 1;
 
219
 
 
220
      region_start = 0;
 
221
      region_column = 0;
 
222
      up = 1;
 
223
      down = 1;
 
224
      mode = ALL_LINES;
 
225
    }
 
226
 
 
227
  if (mode != NO_LINE)
 
228
    {
 
229
      /* Draw lines. This code is tricky, because this must calculate logical
 
230
         positions.  */
 
231
      y = term_screen->y - screen->column
 
232
        / grub_term_entry_width (term_screen->term);
 
233
      i = screen->line;
 
234
      linep = screen->lines + i;
 
235
      while (y > 0)
 
236
        {
 
237
           i--;
 
238
           linep--;
 
239
           y -= get_logical_num_lines (linep, term_screen);
 
240
        }
 
241
 
 
242
      if (y < 0 || i > 0)
 
243
        up_flag = 1;
 
244
 
 
245
      do
 
246
        {
 
247
          int column;
 
248
 
 
249
          if (linep >= screen->lines + screen->num_lines)
 
250
            break;
 
251
 
 
252
          for (column = 0;
 
253
               column <= linep->len
 
254
                 && y < grub_term_num_entries (term_screen->term);
 
255
               column += grub_term_entry_width (term_screen->term), y++)
 
256
            {
 
257
              if (y < 0)
 
258
                continue;
 
259
 
 
260
              if (i == region_start)
 
261
                {
 
262
                  if (region_column >= column
 
263
                      && region_column
 
264
                      < (column
 
265
                         + grub_term_entry_width (term_screen->term)))
 
266
                    print_line (linep, column, region_column - column, y,
 
267
                                term_screen);
 
268
                  else if (region_column < column)
 
269
                    print_line (linep, column, 0, y, term_screen);
 
270
                }
 
271
              else if (i > region_start && mode == ALL_LINES)
 
272
                print_line (linep, column, 0, y, term_screen);
 
273
            }
 
274
 
 
275
          if (y == grub_term_num_entries (term_screen->term))
 
276
            {
 
277
              if (column <= linep->len || i + 1 < screen->num_lines)
 
278
                down_flag = 1;
 
279
            }
 
280
 
 
281
          linep++;
 
282
          i++;
 
283
 
 
284
          if (mode == ALL_LINES && i == screen->num_lines)
 
285
            for (; y < grub_term_num_entries (term_screen->term); y++)
 
286
              print_empty_line (y, term_screen);
 
287
 
 
288
        }
 
289
      while (y < grub_term_num_entries (term_screen->term));
 
290
 
 
291
      /* Draw up and down arrows.  */
 
292
      if (up)
 
293
        print_up (up_flag, term_screen);
 
294
      if (down)
 
295
        print_down (down_flag, term_screen);
 
296
    }
 
297
 
 
298
  /* Place the cursor.  */
 
299
  grub_term_gotoxy (term_screen->term, 
 
300
                    GRUB_TERM_LEFT_BORDER_X + GRUB_TERM_MARGIN + 1
 
301
                    + term_screen->x,
 
302
                    GRUB_TERM_FIRST_ENTRY_Y + term_screen->y);
 
303
 
 
304
  grub_term_refresh (term_screen->term);
 
305
}
 
306
 
 
307
static void
 
308
update_screen_all (struct screen *screen,
 
309
                   int region_start, int region_column,
 
310
                   int up, int down, enum update_mode mode)
 
311
{
 
312
  unsigned i;
 
313
  for (i = 0; i < screen->nterms; i++)
 
314
    update_screen (screen, &screen->terms[i], region_start, region_column,
 
315
                   up, down, mode);
 
316
}
 
317
 
 
318
static int
 
319
insert_string (struct screen *screen, char *s, int update)
 
320
{
 
321
  int region_start = screen->num_lines;
 
322
  int region_column = 0;
 
323
  int down[screen->nterms];
 
324
  enum update_mode mode[screen->nterms];
 
325
  unsigned i;
 
326
 
 
327
  for (i = 0; i < screen->nterms; i++)
 
328
    {
 
329
      down[i] = 0;
 
330
      mode[i] = NO_LINE;
 
331
    }
 
332
 
 
333
  while (*s)
 
334
    {
 
335
      if (*s == '\n')
 
336
        {
 
337
          /* LF is special because it creates a new line.  */
 
338
          struct line *current_linep;
 
339
          struct line *next_linep;
 
340
          int size;
 
341
 
 
342
          /* Make a new line.  */
 
343
          screen->num_lines++;
 
344
          screen->lines = grub_realloc (screen->lines,
 
345
                                        screen->num_lines
 
346
                                        * sizeof (screen->lines[0]));
 
347
          if (! screen->lines)
 
348
            return 0;
 
349
 
 
350
          /* Scroll down. */
 
351
          grub_memmove (screen->lines + screen->line + 2,
 
352
                        screen->lines + screen->line + 1,
 
353
                        ((screen->num_lines - screen->line - 2)
 
354
                         * sizeof (struct line)));
 
355
 
 
356
          if (! init_line (screen->lines + screen->line + 1))
 
357
            return 0;
 
358
 
 
359
          /* Fold the line.  */
 
360
          current_linep = screen->lines + screen->line;
 
361
          next_linep = current_linep + 1;
 
362
          size = current_linep->len - screen->column;
 
363
 
 
364
          if (! ensure_space (next_linep, size))
 
365
            return 0;
 
366
 
 
367
          grub_memmove (next_linep->buf,
 
368
                        current_linep->buf + screen->column,
 
369
                        size);
 
370
          current_linep->len = screen->column;
 
371
          next_linep->len = size;
 
372
 
 
373
          /* Update a dirty region.  */
 
374
          if (region_start > screen->line)
 
375
            {
 
376
              region_start = screen->line;
 
377
              region_column = screen->column;
 
378
            }
 
379
 
 
380
          for (i = 0; i < screen->nterms; i++)
 
381
            {
 
382
              mode[i] = ALL_LINES;
 
383
              down[i] = 1; /* XXX not optimal.  */
 
384
            }
 
385
 
 
386
          /* Move the cursor.  */
 
387
          screen->column = screen->real_column = 0;
 
388
          screen->line++;
 
389
          for (i = 0; i < screen->nterms; i++)
 
390
            {
 
391
              screen->terms[i].x = 0;
 
392
              screen->terms[i].y++;
 
393
            }
 
394
          s++;
 
395
        }
 
396
      else
 
397
        {
 
398
          /* All but LF.  */
 
399
          char *p;
 
400
          struct line *current_linep;
 
401
          int size;
 
402
          int orig_num[screen->nterms], new_num[screen->nterms];
 
403
 
 
404
          /* Find a string delimited by LF.  */
 
405
          p = grub_strchr (s, '\n');
 
406
          if (! p)
 
407
            p = s + grub_strlen (s);
 
408
 
 
409
          /* Insert the string.  */
 
410
          current_linep = screen->lines + screen->line;
 
411
          size = p - s;
 
412
          if (! ensure_space (current_linep, size))
 
413
            return 0;
 
414
 
 
415
          grub_memmove (current_linep->buf + screen->column + size,
 
416
                        current_linep->buf + screen->column,
 
417
                        current_linep->len - screen->column);
 
418
          grub_memmove (current_linep->buf + screen->column,
 
419
                        s,
 
420
                        size);
 
421
          for (i = 0; i < screen->nterms; i++)
 
422
            orig_num[i] = get_logical_num_lines (current_linep,
 
423
                                                 &screen->terms[i]);
 
424
          current_linep->len += size;
 
425
          for (i = 0; i < screen->nterms; i++)
 
426
            new_num[i] = get_logical_num_lines (current_linep,
 
427
                                                &screen->terms[i]);
 
428
 
 
429
          /* Update the dirty region.  */
 
430
          if (region_start > screen->line)
 
431
            {
 
432
              region_start = screen->line;
 
433
              region_column = screen->column;
 
434
            }
 
435
 
 
436
          for (i = 0; i < screen->nterms; i++)
 
437
            if (orig_num[i] != new_num[i])
 
438
              {
 
439
                mode[i] = ALL_LINES;
 
440
                down[i] = 1; /* XXX not optimal.  */
 
441
              }
 
442
            else if (mode[i] != ALL_LINES)
 
443
              mode[i] = SINGLE_LINE;
 
444
 
 
445
          /* Move the cursor.  */
 
446
          screen->column += size;
 
447
          screen->real_column = screen->column;
 
448
          for (i = 0; i < screen->nterms; i++)
 
449
            {
 
450
              screen->terms[i].x += size;
 
451
              screen->terms[i].y += screen->terms[i].x
 
452
                / grub_term_entry_width (screen->terms[i].term);
 
453
              screen->terms[i].x
 
454
                %= grub_term_entry_width (screen->terms[i].term);
 
455
            }
 
456
          s = p;
 
457
        }
 
458
    }
 
459
 
 
460
  if (update)
 
461
    for (i = 0; i < screen->nterms; i++)
 
462
      update_screen (screen, &screen->terms[i],
 
463
                     region_start, region_column, 0, down[i], mode[i]);
 
464
 
 
465
  return 1;
 
466
}
 
467
 
 
468
/* Release the resource allocated for SCREEN.  */
 
469
static void
 
470
destroy_screen (struct screen *screen)
 
471
{
 
472
  int i;
 
473
 
 
474
  if (screen->lines)
 
475
    for (i = 0; i < screen->num_lines; i++)
 
476
      {
 
477
        struct line *linep = screen->lines + i;
 
478
 
 
479
        if (linep)
 
480
          grub_free (linep->buf);
 
481
      }
 
482
 
 
483
  grub_free (screen->killed_text);
 
484
  grub_free (screen->lines);
 
485
  grub_free (screen->terms);
 
486
  grub_free (screen);
 
487
}
 
488
 
 
489
/* Make a new screen.  */
 
490
static struct screen *
 
491
make_screen (grub_menu_entry_t entry)
 
492
{
 
493
  struct screen *screen;
 
494
  unsigned i;
 
495
 
 
496
  /* Initialize the screen.  */
 
497
  screen = grub_zalloc (sizeof (*screen));
 
498
  if (! screen)
 
499
    return 0;
 
500
 
 
501
  screen->submenu = entry->submenu;
 
502
 
 
503
  screen->num_lines = 1;
 
504
  screen->lines = grub_malloc (sizeof (struct line));
 
505
  if (! screen->lines)
 
506
    goto fail;
 
507
 
 
508
  /* Initialize the first line which must be always present.  */
 
509
  if (! init_line (screen->lines))
 
510
    goto fail;
 
511
 
 
512
  insert_string (screen, (char *) entry->sourcecode, 0);
 
513
 
 
514
  /* Reset the cursor position.  */
 
515
  screen->column = 0;
 
516
  screen->real_column = 0;
 
517
  screen->line = 0;
 
518
  for (i = 0; i < screen->nterms; i++)
 
519
    {
 
520
      screen->terms[i].x = 0;
 
521
      screen->terms[i].y = 0;
 
522
    }
 
523
 
 
524
  return screen;
 
525
 
 
526
 fail:
 
527
  destroy_screen (screen);
 
528
  return 0;
 
529
}
 
530
 
 
531
static int
 
532
forward_char (struct screen *screen, int update)
 
533
{
 
534
  struct line *linep;
 
535
  unsigned i;
 
536
 
 
537
  linep = screen->lines + screen->line;
 
538
  if (screen->column < linep->len)
 
539
    {
 
540
      screen->column++;
 
541
      for (i = 0; i < screen->nterms; i++)
 
542
        {
 
543
          screen->terms[i].x++;
 
544
          if (screen->terms[i].x
 
545
              == grub_term_entry_width (screen->terms[i].term))
 
546
            {
 
547
              screen->terms[i].x = 0;
 
548
              screen->terms[i].y++;
 
549
            }
 
550
        }
 
551
    }
 
552
  else if (screen->num_lines > screen->line + 1)
 
553
    {
 
554
      screen->column = 0;
 
555
      screen->line++;
 
556
      for (i = 0; i < screen->nterms; i++)
 
557
        {
 
558
          screen->terms[i].x = 0;
 
559
          screen->terms[i].y++;
 
560
        }
 
561
    }
 
562
 
 
563
  screen->real_column = screen->column;
 
564
 
 
565
  if (update)
 
566
    update_screen_all (screen, screen->num_lines, 0, 0, 0, NO_LINE);
 
567
  return 1;
 
568
}
 
569
 
 
570
static int
 
571
backward_char (struct screen *screen, int update)
 
572
{
 
573
  unsigned i;
 
574
 
 
575
  if (screen->column > 0)
 
576
    {
 
577
      screen->column--;
 
578
      for (i = 0; i < screen->nterms; i++)
 
579
        {
 
580
          screen->terms[i].x--;
 
581
          if (screen->terms[i].x == -1)
 
582
            {
 
583
              screen->terms[i].x
 
584
                = grub_term_entry_width (screen->terms[i].term) - 1;
 
585
              screen->terms[i].y--;
 
586
            }
 
587
        }
 
588
    }
 
589
  else if (screen->line > 0)
 
590
    {
 
591
      struct line *linep;
 
592
 
 
593
      screen->line--;
 
594
      linep = screen->lines + screen->line;
 
595
      screen->column = linep->len;
 
596
      for (i = 0; i < screen->nterms; i++)
 
597
        {
 
598
          screen->terms[i].x = screen->column
 
599
            % grub_term_entry_width (screen->terms[i].term);
 
600
          screen->terms[i].y--;
 
601
        }
 
602
    }
 
603
 
 
604
  screen->real_column = screen->column;
 
605
 
 
606
  if (update)
 
607
    update_screen_all (screen, screen->num_lines, 0, 0, 0, NO_LINE);
 
608
 
 
609
  return 1;
 
610
}
 
611
 
 
612
static int
 
613
previous_line (struct screen *screen, int update)
 
614
{
 
615
  unsigned i;
 
616
 
 
617
  if (screen->line > 0)
 
618
    {
 
619
      struct line *linep;
 
620
      int col;
 
621
 
 
622
      /* How many physical lines from the current position
 
623
         to the first physical line?  */
 
624
      col = screen->column;
 
625
 
 
626
      screen->line--;
 
627
 
 
628
      linep = screen->lines + screen->line;
 
629
      if (linep->len < screen->real_column)
 
630
        screen->column = linep->len;
 
631
      else
 
632
        screen->column = screen->real_column;
 
633
 
 
634
      for (i = 0; i < screen->nterms; i++)
 
635
        {
 
636
          int dy;
 
637
          dy = col / grub_term_entry_width (screen->terms[i].term);
 
638
 
 
639
          /* How many physical lines from the current position
 
640
             to the last physical line?  */
 
641
          dy += (linep->len / grub_term_entry_width (screen->terms[i].term)
 
642
                 - screen->column
 
643
                 / grub_term_entry_width (screen->terms[i].term));
 
644
        
 
645
          screen->terms[i].y -= dy + 1;
 
646
          screen->terms[i].x
 
647
            = screen->column % grub_term_entry_width (screen->terms[i].term);
 
648
      }
 
649
    }
 
650
  else
 
651
    {
 
652
      for (i = 0; i < screen->nterms; i++)
 
653
        {
 
654
          screen->terms[i].y
 
655
            -= screen->column / grub_term_entry_width (screen->terms[i].term);
 
656
          screen->terms[i].x = 0;
 
657
        }
 
658
      screen->column = 0;
 
659
    }
 
660
 
 
661
  if (update)
 
662
    update_screen_all (screen, screen->num_lines, 0, 0, 0, NO_LINE);
 
663
 
 
664
  return 1;
 
665
}
 
666
 
 
667
static int
 
668
next_line (struct screen *screen, int update)
 
669
{
 
670
  unsigned i;
 
671
 
 
672
  if (screen->line < screen->num_lines - 1)
 
673
    {
 
674
      struct line *linep;
 
675
      int l1, c1;
 
676
 
 
677
      /* How many physical lines from the current position
 
678
         to the last physical line?  */
 
679
      linep = screen->lines + screen->line;
 
680
      l1 = linep->len;
 
681
      c1 = screen->column;
 
682
 
 
683
      screen->line++;
 
684
 
 
685
      linep++;
 
686
      if (linep->len < screen->real_column)
 
687
        screen->column = linep->len;
 
688
      else
 
689
        screen->column = screen->real_column;
 
690
 
 
691
      for (i = 0; i < screen->nterms; i++)
 
692
        {
 
693
          int dy;
 
694
          dy = l1 / grub_term_entry_width (screen->terms[i].term)
 
695
            - c1 / grub_term_entry_width (screen->terms[i].term);
 
696
          /* How many physical lines from the current position
 
697
             to the first physical line?  */
 
698
          dy += screen->column / grub_term_entry_width (screen->terms[i].term);
 
699
          screen->terms[i].y += dy + 1;
 
700
          screen->terms[i].x = screen->column
 
701
            % grub_term_entry_width (screen->terms[i].term);
 
702
        }
 
703
    }
 
704
  else
 
705
    {
 
706
      struct line *linep;
 
707
      int l, s;
 
708
      
 
709
      linep = screen->lines + screen->line;
 
710
      l = linep->len;
 
711
      s = screen->column;
 
712
      screen->column = linep->len;
 
713
      for (i = 0; i < screen->nterms; i++)
 
714
        {
 
715
          screen->terms[i].y 
 
716
            += (l / grub_term_entry_width (screen->terms[i].term)
 
717
                -  s / grub_term_entry_width (screen->terms[i].term));
 
718
          screen->terms[i].x
 
719
            = screen->column % grub_term_entry_width (screen->terms[i].term);
 
720
        }
 
721
    }
 
722
 
 
723
  if (update)
 
724
    update_screen_all (screen, screen->num_lines, 0, 0, 0, NO_LINE);
 
725
 
 
726
  return 1;
 
727
}
 
728
 
 
729
static int
 
730
beginning_of_line (struct screen *screen, int update)
 
731
{
 
732
  unsigned i;
 
733
  int col;
 
734
  
 
735
  col = screen->column;
 
736
  screen->column = screen->real_column = 0;
 
737
  for (i = 0; i < screen->nterms; i++)
 
738
    {
 
739
      screen->terms[i].x = 0;
 
740
      screen->terms[i].y -= col / grub_term_entry_width (screen->terms[i].term);
 
741
    }
 
742
 
 
743
  if (update)
 
744
    update_screen_all (screen, screen->num_lines, 0, 0, 0, NO_LINE);
 
745
 
 
746
  return 1;
 
747
}
 
748
 
 
749
static int
 
750
end_of_line (struct screen *screen, int update)
 
751
{
 
752
  struct line *linep;
 
753
  unsigned i;
 
754
  int col;
 
755
 
 
756
  linep = screen->lines + screen->line;
 
757
  col = screen->column;
 
758
  screen->column = screen->real_column = linep->len;
 
759
  for (i = 0; i < screen->nterms; i++)
 
760
    {
 
761
      screen->terms[i].y 
 
762
        += (linep->len / grub_term_entry_width (screen->terms->term)
 
763
            - col / grub_term_entry_width (screen->terms->term));
 
764
      screen->terms[i].x
 
765
        = screen->column % grub_term_entry_width (screen->terms->term);
 
766
    }
 
767
 
 
768
  if (update)
 
769
    update_screen_all (screen, screen->num_lines, 0, 0, 0, NO_LINE);
 
770
 
 
771
  return 1;
 
772
}
 
773
 
 
774
static int
 
775
delete_char (struct screen *screen, int update)
 
776
{
 
777
  struct line *linep;
 
778
  int start = screen->num_lines;
 
779
  int column = 0;
 
780
 
 
781
  linep = screen->lines + screen->line;
 
782
  if (linep->len > screen->column)
 
783
    {
 
784
      int orig_num[screen->nterms], new_num;
 
785
      unsigned i;
 
786
 
 
787
      for (i = 0; i < screen->nterms; i++)
 
788
        orig_num[i] = get_logical_num_lines (linep, &screen->terms[i]);
 
789
 
 
790
      grub_memmove (linep->buf + screen->column,
 
791
                    linep->buf + screen->column + 1,
 
792
                    linep->len - screen->column - 1);
 
793
      linep->len--;
 
794
 
 
795
      start = screen->line;
 
796
      column = screen->column;
 
797
 
 
798
      screen->real_column = screen->column;
 
799
 
 
800
      if (update)
 
801
        {
 
802
          for (i = 0; i < screen->nterms; i++)
 
803
            {
 
804
              new_num = get_logical_num_lines (linep, &screen->terms[i]);
 
805
              if (orig_num[i] != new_num)
 
806
                update_screen (screen, &screen->terms[i],
 
807
                               start, column, 0, 0, ALL_LINES);
 
808
              else
 
809
                update_screen (screen, &screen->terms[i],
 
810
                               start, column, 0, 0, SINGLE_LINE);
 
811
            }
 
812
        }
 
813
    }
 
814
  else if (screen->num_lines > screen->line + 1)
 
815
    {
 
816
      struct line *next_linep;
 
817
 
 
818
      next_linep = linep + 1;
 
819
      if (! ensure_space (linep, next_linep->len))
 
820
        return 0;
 
821
 
 
822
      grub_memmove (linep->buf + linep->len, next_linep->buf, next_linep->len);
 
823
      linep->len += next_linep->len;
 
824
 
 
825
      grub_free (next_linep->buf);
 
826
      grub_memmove (next_linep,
 
827
                    next_linep + 1,
 
828
                    (screen->num_lines - screen->line - 2)
 
829
                    * sizeof (struct line));
 
830
      screen->num_lines--;
 
831
 
 
832
      start = screen->line;
 
833
      column = screen->column;
 
834
 
 
835
      screen->real_column = screen->column;
 
836
      if (update)
 
837
        update_screen_all (screen, start, column, 0, 1, ALL_LINES);
 
838
    }
 
839
 
 
840
  return 1;
 
841
}
 
842
 
 
843
static int
 
844
backward_delete_char (struct screen *screen, int update)
 
845
{
 
846
  int saved_column;
 
847
  int saved_line;
 
848
 
 
849
  saved_column = screen->column;
 
850
  saved_line = screen->line;
 
851
 
 
852
  if (! backward_char (screen, 0))
 
853
    return 0;
 
854
 
 
855
  if (saved_column != screen->column || saved_line != screen->line)
 
856
    if (! delete_char (screen, update))
 
857
      return 0;
 
858
 
 
859
  return 1;
 
860
}
 
861
 
 
862
static int
 
863
kill_line (struct screen *screen, int continuous, int update)
 
864
{
 
865
  struct line *linep;
 
866
  char *p;
 
867
  int size;
 
868
  int offset;
 
869
 
 
870
  p = screen->killed_text;
 
871
  if (! continuous && p)
 
872
    p[0] = '\0';
 
873
 
 
874
  linep = screen->lines + screen->line;
 
875
  size = linep->len - screen->column;
 
876
 
 
877
  if (p)
 
878
    offset = grub_strlen (p);
 
879
  else
 
880
    offset = 0;
 
881
 
 
882
  if (size > 0)
 
883
    {
 
884
      int orig_num[screen->nterms], new_num;
 
885
      unsigned i;
 
886
 
 
887
      p = grub_realloc (p, offset + size + 1);
 
888
      if (! p)
 
889
        return 0;
 
890
 
 
891
      grub_memmove (p + offset, linep->buf + screen->column, size);
 
892
      p[offset + size - 1] = '\0';
 
893
 
 
894
      screen->killed_text = p;
 
895
 
 
896
      for (i = 0; i < screen->nterms; i++)
 
897
        orig_num[i] = get_logical_num_lines (linep, &screen->terms[i]);
 
898
      linep->len = screen->column;
 
899
 
 
900
      if (update)
 
901
        {
 
902
          new_num = get_logical_num_lines (linep, &screen->terms[i]);
 
903
          for (i = 0; i < screen->nterms; i++)
 
904
            {
 
905
              if (orig_num[i] != new_num)
 
906
                update_screen (screen, &screen->terms[i],
 
907
                               screen->line, screen->column, 0, 1, ALL_LINES);
 
908
              else
 
909
                update_screen (screen, &screen->terms[i],
 
910
                               screen->line, screen->column, 0, 0, SINGLE_LINE);
 
911
            }
 
912
        }
 
913
    }
 
914
  else if (screen->line + 1 < screen->num_lines)
 
915
    {
 
916
      p = grub_realloc (p, offset + 1 + 1);
 
917
      if (! p)
 
918
        return 0;
 
919
 
 
920
      p[offset] = '\n';
 
921
      p[offset + 1] = '\0';
 
922
 
 
923
      screen->killed_text = p;
 
924
 
 
925
      return delete_char (screen, update);
 
926
    }
 
927
 
 
928
  return 1;
 
929
}
 
930
 
 
931
static int
 
932
yank (struct screen *screen, int update)
 
933
{
 
934
  if (screen->killed_text)
 
935
    return insert_string (screen, screen->killed_text, update);
 
936
 
 
937
  return 1;
 
938
}
 
939
 
 
940
static int
 
941
open_line (struct screen *screen, int update)
 
942
{
 
943
  int saved_y[screen->nterms];
 
944
  unsigned i;
 
945
 
 
946
  for (i = 0; i < screen->nterms; i++)
 
947
    saved_y[i] = screen->terms[i].y;
 
948
 
 
949
  if (! insert_string (screen, "\n", 0))
 
950
    return 0;
 
951
 
 
952
  if (! backward_char (screen, 0))
 
953
    return 0;
 
954
 
 
955
  for (i = 0; i < screen->nterms; i++)
 
956
    screen->terms[i].y = saved_y[i];
 
957
 
 
958
  if (update)
 
959
    update_screen_all (screen, screen->line, screen->column, 0, 1, ALL_LINES);
 
960
 
 
961
  return 1;
 
962
}
 
963
 
 
964
/* A completion hook to print items.  */
 
965
static void
 
966
store_completion (const char *item, grub_completion_type_t type,
 
967
                  int count __attribute__ ((unused)))
 
968
{
 
969
  char *p;
 
970
 
 
971
  completion_type = type;
 
972
 
 
973
  /* Make sure that the completion buffer has enough room.  */
 
974
  if (completion_buffer.max_len < (completion_buffer.len
 
975
                                   + (int) grub_strlen (item) + 1 + 1))
 
976
    {
 
977
      grub_size_t new_len;
 
978
 
 
979
      new_len = completion_buffer.len + grub_strlen (item) + 80;
 
980
      p = grub_realloc (completion_buffer.buf, new_len);
 
981
      if (! p)
 
982
        {
 
983
          /* Possibly not fatal.  */
 
984
          grub_errno = GRUB_ERR_NONE;
 
985
          return;
 
986
        }
 
987
      p[completion_buffer.len] = 0;
 
988
      completion_buffer.buf = p;
 
989
      completion_buffer.max_len = new_len;
 
990
    }
 
991
 
 
992
  p = completion_buffer.buf + completion_buffer.len;
 
993
  if (completion_buffer.len != 0)
 
994
    {
 
995
      *p++ = ' ';
 
996
      completion_buffer.len++;
 
997
    }
 
998
  grub_strcpy (p, item);
 
999
  completion_buffer.len += grub_strlen (item);
 
1000
}
 
1001
 
 
1002
static int
 
1003
complete (struct screen *screen, int continuous, int update)
 
1004
{
 
1005
  char saved_char;
 
1006
  struct line *linep;
 
1007
  int restore;
 
1008
  char *insert;
 
1009
  static int count = -1;
 
1010
  unsigned i;
 
1011
  grub_uint32_t *ucs4;
 
1012
  grub_size_t buflen;
 
1013
  grub_ssize_t ucs4len;
 
1014
 
 
1015
  if (continuous)
 
1016
    count++;
 
1017
  else
 
1018
    count = 0;
 
1019
 
 
1020
  completion_buffer.buf = 0;
 
1021
  completion_buffer.len = 0;
 
1022
  completion_buffer.max_len = 0;
 
1023
 
 
1024
  linep = screen->lines + screen->line;
 
1025
  saved_char = linep->buf[screen->column];
 
1026
  linep->buf[screen->column] = '\0';
 
1027
 
 
1028
  insert = grub_normal_do_completion (linep->buf, &restore, store_completion);
 
1029
 
 
1030
  linep->buf[screen->column] = saved_char;
 
1031
  
 
1032
  if (completion_buffer.buf)
 
1033
    {
 
1034
      buflen = grub_strlen (completion_buffer.buf);
 
1035
      ucs4 = grub_malloc (sizeof (grub_uint32_t) * (buflen + 1));
 
1036
      
 
1037
      if (!ucs4)
 
1038
        {
 
1039
          grub_print_error ();
 
1040
          grub_errno = GRUB_ERR_NONE;
 
1041
          return 1;
 
1042
        }
 
1043
 
 
1044
      ucs4len = grub_utf8_to_ucs4 (ucs4, buflen,
 
1045
                                   (grub_uint8_t *) completion_buffer.buf,
 
1046
                                   buflen, 0);
 
1047
      ucs4[ucs4len] = 0;
 
1048
 
 
1049
      if (restore)
 
1050
        for (i = 0; i < screen->nterms; i++)
 
1051
          {
 
1052
            int num_sections = ((completion_buffer.len
 
1053
                                 + grub_term_width (screen->terms[i].term) 
 
1054
                                 - 8 - 1)
 
1055
                                / (grub_term_width (screen->terms[i].term)
 
1056
                                   - 8));
 
1057
            grub_uint32_t *endp;
 
1058
            grub_uint16_t pos;
 
1059
            grub_uint32_t *p = ucs4;
 
1060
 
 
1061
            pos = grub_term_getxy (screen->terms[i].term);
 
1062
            grub_term_gotoxy (screen->terms[i].term, 0,
 
1063
                              grub_term_height (screen->terms[i].term) - 3);
 
1064
 
 
1065
            screen->completion_shown = 1;
 
1066
 
 
1067
            grub_term_gotoxy (screen->terms[i].term, 0,
 
1068
                              grub_term_height (screen->terms[i].term) - 3);
 
1069
            grub_puts_terminal ("   ", screen->terms[i].term);
 
1070
            switch (completion_type)
 
1071
              {
 
1072
              case GRUB_COMPLETION_TYPE_COMMAND:
 
1073
                grub_puts_terminal (_("Possible commands are:"),
 
1074
                                    screen->terms[i].term);
 
1075
                break;
 
1076
              case GRUB_COMPLETION_TYPE_DEVICE:
 
1077
                grub_puts_terminal (_("Possible devices are:"),
 
1078
                                    screen->terms[i].term);
 
1079
                break;
 
1080
              case GRUB_COMPLETION_TYPE_FILE:
 
1081
                grub_puts_terminal (_("Possible files are:"),
 
1082
                                    screen->terms[i].term);
 
1083
                break;
 
1084
              case GRUB_COMPLETION_TYPE_PARTITION:
 
1085
                grub_puts_terminal (_("Possible partitions are:"),
 
1086
                                    screen->terms[i].term);
 
1087
                break;
 
1088
              case GRUB_COMPLETION_TYPE_ARGUMENT:
 
1089
                grub_puts_terminal (_("Possible arguments are:"),
 
1090
                                    screen->terms[i].term);
 
1091
                break;
 
1092
              default:
 
1093
                grub_puts_terminal (_("Possible things are:"),
 
1094
                                    screen->terms[i].term);
 
1095
                break;
 
1096
              }
 
1097
 
 
1098
            grub_puts_terminal ("\n    ", screen->terms[i].term);
 
1099
 
 
1100
            p += (count % num_sections)
 
1101
              * (grub_term_width (screen->terms[i].term) - 8);
 
1102
            endp = p + (grub_term_width (screen->terms[i].term) - 8);
 
1103
 
 
1104
            if (p != ucs4)
 
1105
              grub_putcode (GRUB_UNICODE_LEFTARROW, screen->terms[i].term);
 
1106
            else
 
1107
              grub_putcode (' ', screen->terms[i].term);
 
1108
 
 
1109
            grub_print_ucs4 (p, ucs4 + ucs4len < endp ? ucs4 + ucs4len : endp,
 
1110
                             0, 0, screen->terms[i].term);
 
1111
 
 
1112
            if (ucs4 + ucs4len > endp)
 
1113
              grub_putcode (GRUB_UNICODE_RIGHTARROW, screen->terms[i].term);
 
1114
            grub_term_gotoxy (screen->terms[i].term, pos >> 8, pos & 0xFF);
 
1115
          }
 
1116
    }
 
1117
 
 
1118
  if (insert)
 
1119
    {
 
1120
      insert_string (screen, insert, update);
 
1121
      count = -1;
 
1122
      grub_free (insert);
 
1123
    }
 
1124
  else if (update)
 
1125
    grub_refresh ();
 
1126
 
 
1127
  grub_free (completion_buffer.buf);
 
1128
  return 1;
 
1129
}
 
1130
 
 
1131
/* Clear displayed completions.  */
 
1132
static void
 
1133
clear_completions (struct per_term_screen *term_screen)
 
1134
{
 
1135
  grub_uint16_t pos;
 
1136
  unsigned i, j;
 
1137
 
 
1138
  pos = grub_term_getxy (term_screen->term);
 
1139
  grub_term_gotoxy (term_screen->term, 0,
 
1140
                    grub_term_height (term_screen->term) - 3);
 
1141
 
 
1142
  for (i = 0; i < 2; i++)
 
1143
    {
 
1144
      for (j = 0; j < grub_term_width (term_screen->term) - 1; j++)
 
1145
        grub_putcode (' ', term_screen->term);
 
1146
      grub_putcode ('\n', term_screen->term);
 
1147
    }
 
1148
 
 
1149
  grub_term_gotoxy (term_screen->term, pos >> 8, pos & 0xFF);
 
1150
  grub_term_refresh (term_screen->term);
 
1151
}
 
1152
 
 
1153
static void
 
1154
clear_completions_all (struct screen *screen)
 
1155
{
 
1156
  unsigned i;
 
1157
 
 
1158
  for (i = 0; i < screen->nterms; i++)
 
1159
    clear_completions (&screen->terms[i]);
 
1160
}
 
1161
 
 
1162
/* Execute the command list in the screen SCREEN.  */
 
1163
static int
 
1164
run (struct screen *screen)
 
1165
{
 
1166
  int currline = 0;
 
1167
  char *nextline;
 
1168
  int errs_before;
 
1169
  grub_menu_t menu;
 
1170
 
 
1171
  auto grub_err_t editor_getline (char **line, int cont);
 
1172
  grub_err_t editor_getline (char **line, int cont __attribute__ ((unused)))
 
1173
    {
 
1174
      struct line *linep = screen->lines + currline;
 
1175
      char *p;
 
1176
 
 
1177
      if (currline > screen->num_lines)
 
1178
        {
 
1179
          *line = 0;
 
1180
          return 0;
 
1181
        }
 
1182
 
 
1183
      /* Trim down space characters.  */
 
1184
      for (p = linep->buf + linep->len - 1;
 
1185
           p >= linep->buf && grub_isspace (*p);
 
1186
           p--)
 
1187
        ;
 
1188
      *++p = '\0';
 
1189
 
 
1190
      linep->len = p - linep->buf;
 
1191
      for (p = linep->buf; grub_isspace (*p); p++)
 
1192
        ;
 
1193
      *line = grub_strdup (p);
 
1194
      currline++;
 
1195
      return 0;
 
1196
    }
 
1197
 
 
1198
  grub_cls ();
 
1199
  grub_printf ("  ");
 
1200
  grub_printf_ (N_("Booting a command list"));
 
1201
  grub_printf ("\n\n");
 
1202
 
 
1203
  errs_before = grub_err_printed_errors;
 
1204
 
 
1205
  if (screen->submenu)
 
1206
    {
 
1207
      grub_env_context_open ();
 
1208
      menu = grub_zalloc (sizeof (*menu));
 
1209
      if (! menu)
 
1210
        return 0;
 
1211
      grub_env_set_menu (menu);
 
1212
    }
 
1213
 
 
1214
  /* Execute the script, line for line.  */
 
1215
  while (currline < screen->num_lines)
 
1216
    {
 
1217
      editor_getline (&nextline, 0);
 
1218
      if (grub_normal_parse_line (nextline, editor_getline))
 
1219
        break;
 
1220
    }
 
1221
 
 
1222
  if (errs_before != grub_err_printed_errors)
 
1223
    grub_wait_after_message ();
 
1224
 
 
1225
  if (grub_errno == GRUB_ERR_NONE && grub_loader_is_loaded ())
 
1226
    /* Implicit execution of boot, only if something is loaded.  */
 
1227
    grub_command_execute ("boot", 0, 0);
 
1228
 
 
1229
  if (screen->submenu)
 
1230
    {
 
1231
      if (menu && menu->size)
 
1232
        {
 
1233
          grub_show_menu (menu, 1);
 
1234
          grub_normal_free_menu (menu);
 
1235
        }
 
1236
      grub_env_context_close ();
 
1237
    }
 
1238
 
 
1239
  if (grub_errno != GRUB_ERR_NONE)
 
1240
    {
 
1241
      grub_print_error ();
 
1242
      grub_errno = GRUB_ERR_NONE;
 
1243
      grub_wait_after_message ();
 
1244
    }
 
1245
 
 
1246
  return 1;
 
1247
}
 
1248
 
 
1249
/* Edit a menu entry with an Emacs-like interface.  */
 
1250
void
 
1251
grub_menu_entry_run (grub_menu_entry_t entry)
 
1252
{
 
1253
  struct screen *screen;
 
1254
  int prev_c;
 
1255
  grub_err_t err = GRUB_ERR_NONE;
 
1256
  unsigned i;
 
1257
  grub_term_output_t term;
 
1258
 
 
1259
  err = grub_auth_check_authentication (NULL);
 
1260
 
 
1261
  if (err)
 
1262
    {
 
1263
      grub_print_error ();
 
1264
      grub_errno = GRUB_ERR_NONE;
 
1265
      return;
 
1266
    }
 
1267
 
 
1268
  screen = make_screen (entry);
 
1269
  if (! screen)
 
1270
    return;
 
1271
 
 
1272
  screen->terms = NULL;
 
1273
 
 
1274
 refresh:
 
1275
  grub_free (screen->terms);
 
1276
  screen->nterms = 0;
 
1277
  FOR_ACTIVE_TERM_OUTPUTS(term)
 
1278
    screen->nterms++;
 
1279
  screen->terms = grub_malloc (screen->nterms * sizeof (screen->terms[0]));
 
1280
  if (!screen->terms)
 
1281
    {
 
1282
      grub_print_error ();
 
1283
      grub_errno = GRUB_ERR_NONE;
 
1284
      return;
 
1285
    }
 
1286
  i = 0;
 
1287
  FOR_ACTIVE_TERM_OUTPUTS(term)
 
1288
  {
 
1289
    screen->terms[i].term = term;
 
1290
    screen->terms[i].x = 0;
 
1291
    screen->terms[i].y = 0;
 
1292
    i++;
 
1293
  }
 
1294
  /* Draw the screen.  */
 
1295
  for (i = 0; i < screen->nterms; i++)
 
1296
    grub_menu_init_page (0, 1, screen->terms[i].term);
 
1297
  update_screen_all (screen, 0, 0, 1, 1, ALL_LINES);
 
1298
  for (i = 0; i < screen->nterms; i++)
 
1299
    grub_term_setcursor (screen->terms[i].term, 1);
 
1300
  prev_c = '\0';
 
1301
 
 
1302
  while (1)
 
1303
    {
 
1304
      int c = grub_getkey ();
 
1305
 
 
1306
      if (screen->completion_shown)
 
1307
        {
 
1308
          clear_completions_all (screen);
 
1309
          screen->completion_shown = 0;
 
1310
        }
 
1311
 
 
1312
      if (grub_normal_exit_level)
 
1313
        {
 
1314
          destroy_screen (screen);
 
1315
          return;
 
1316
        }
 
1317
 
 
1318
      switch (c)
 
1319
        {
 
1320
        case GRUB_TERM_KEY_UP:
 
1321
        case GRUB_TERM_CTRL | 'p':
 
1322
          if (! previous_line (screen, 1))
 
1323
            goto fail;
 
1324
          break;
 
1325
 
 
1326
        case GRUB_TERM_CTRL | 'n':
 
1327
        case GRUB_TERM_KEY_DOWN:
 
1328
          if (! next_line (screen, 1))
 
1329
            goto fail;
 
1330
          break;
 
1331
 
 
1332
        case GRUB_TERM_CTRL | 'f':
 
1333
        case GRUB_TERM_KEY_RIGHT:
 
1334
          if (! forward_char (screen, 1))
 
1335
            goto fail;
 
1336
          break;
 
1337
 
 
1338
        case GRUB_TERM_CTRL | 'b':
 
1339
        case GRUB_TERM_KEY_LEFT:
 
1340
          if (! backward_char (screen, 1))
 
1341
            goto fail;
 
1342
          break;
 
1343
 
 
1344
        case GRUB_TERM_CTRL | 'a':
 
1345
        case GRUB_TERM_KEY_HOME:
 
1346
          if (! beginning_of_line (screen, 1))
 
1347
            goto fail;
 
1348
          break;
 
1349
 
 
1350
        case GRUB_TERM_CTRL | 'e':
 
1351
        case GRUB_TERM_KEY_END:
 
1352
          if (! end_of_line (screen, 1))
 
1353
            goto fail;
 
1354
          break;
 
1355
 
 
1356
        case GRUB_TERM_CTRL | 'i':
 
1357
        case '\t':
 
1358
          if (! complete (screen, prev_c == c, 1))
 
1359
            goto fail;
 
1360
          break;
 
1361
 
 
1362
        case GRUB_TERM_CTRL | 'd':
 
1363
        case GRUB_TERM_KEY_DC:
 
1364
          if (! delete_char (screen, 1))
 
1365
            goto fail;
 
1366
          break;
 
1367
 
 
1368
        case GRUB_TERM_CTRL | 'h':
 
1369
        case '\b':
 
1370
          if (! backward_delete_char (screen, 1))
 
1371
            goto fail;
 
1372
          break;
 
1373
 
 
1374
        case GRUB_TERM_CTRL | 'k':
 
1375
          if (! kill_line (screen, prev_c == c, 1))
 
1376
            goto fail;
 
1377
          break;
 
1378
 
 
1379
        case GRUB_TERM_CTRL | 'u':
 
1380
          /* FIXME: What behavior is good for this key?  */
 
1381
          break;
 
1382
 
 
1383
        case GRUB_TERM_CTRL | 'y':
 
1384
          if (! yank (screen, 1))
 
1385
            goto fail;
 
1386
          break;
 
1387
 
 
1388
        case GRUB_TERM_CTRL | 'l':
 
1389
          /* FIXME: centering.  */
 
1390
          goto refresh;
 
1391
 
 
1392
        case GRUB_TERM_CTRL | 'o':
 
1393
          if (! open_line (screen, 1))
 
1394
            goto fail;
 
1395
          break;
 
1396
 
 
1397
        case '\n':
 
1398
        case '\r':
 
1399
          if (! insert_string (screen, "\n", 1))
 
1400
            goto fail;
 
1401
          break;
 
1402
 
 
1403
        case '\e':
 
1404
          destroy_screen (screen);
 
1405
          return;
 
1406
 
 
1407
        case GRUB_TERM_CTRL | 'c':
 
1408
        case GRUB_TERM_KEY_F2:
 
1409
          grub_cmdline_run (1);
 
1410
          goto refresh;
 
1411
 
 
1412
        case GRUB_TERM_CTRL | 'x':
 
1413
        case GRUB_TERM_KEY_F10:
 
1414
          run (screen);
 
1415
          goto refresh;
 
1416
 
 
1417
        case GRUB_TERM_CTRL | 'r':
 
1418
        case GRUB_TERM_CTRL | 's':
 
1419
        case GRUB_TERM_CTRL | 't':
 
1420
          /* FIXME */
 
1421
          break;
 
1422
 
 
1423
        default:
 
1424
          if (grub_isprint (c))
 
1425
            {
 
1426
              char buf[2];
 
1427
 
 
1428
              buf[0] = c;
 
1429
              buf[1] = '\0';
 
1430
              if (! insert_string (screen, buf, 1))
 
1431
                goto fail;
 
1432
            }
 
1433
          break;
 
1434
        }
 
1435
 
 
1436
      prev_c = c;
 
1437
    }
 
1438
 
 
1439
 fail:
 
1440
  destroy_screen (screen);
 
1441
 
 
1442
  grub_cls ();
 
1443
  grub_print_error ();
 
1444
  grub_errno = GRUB_ERR_NONE;
 
1445
  grub_xputs ("\n");
 
1446
  grub_printf_ (N_("Press any key to continue..."));
 
1447
  (void) grub_getkey ();
 
1448
}