~darkmuggle-deactivatedaccount/ubuntu/quantal/grub2/fix-872244

« back to all changes in this revision

Viewing changes to normal/menu_entry.c

  • Committer: Bazaar Package Importer
  • Author(s): Colin Watson, Colin Watson, Evan Broder, Mario Limonciello
  • Date: 2010-11-24 13:59:55 UTC
  • mfrom: (1.17.6 upstream) (17.6.15 experimental)
  • Revision ID: james.westby@ubuntu.com-20101124135955-r6ii5sepayr7jt53
Tags: 1.99~20101124-1ubuntu1
[ Colin Watson ]
* Resynchronise with Debian experimental.  Remaining changes:
  - Adjust for default Ubuntu boot options ("quiet splash").
  - Default to hiding the menu; holding down Shift at boot will show it.
  - Set a monochromatic theme for Ubuntu.
  - Apply Ubuntu GRUB Legacy changes to legacy update-grub script: title,
    recovery mode, quiet option, tweak how memtest86+ is displayed, and
    use UUIDs where appropriate.
  - Fix backslash-escaping in merge_debconf_into_conf.
  - Remove "GNU/Linux" from default distributor string.
  - Add crashkernel= options if kdump and makedumpfile are available.
  - If other operating systems are installed, then automatically unhide
    the menu.  Otherwise, if GRUB_HIDDEN_TIMEOUT is 0, then use keystatus
    if available to check whether Shift is pressed.  If it is, show the
    menu, otherwise boot immediately.  If keystatus is not available, then
    fall back to a short delay interruptible with Escape.
  - Allow Shift to interrupt 'sleep --interruptible'.
  - Don't display introductory message about line editing unless we're
    actually offering a shell prompt.  Don't clear the screen just before
    booting if we never drew the menu in the first place.
  - Remove some verbose messages printed before reading the configuration
    file.
  - Suppress progress messages as the kernel and initrd load for
    non-recovery kernel menu entries.
  - Change prepare_grub_to_access_device to handle filesystems
    loop-mounted on file images.
  - Ignore devices loop-mounted from files in 10_linux.
  - Show the boot menu if the previous boot failed, that is if it failed
    to get to the end of one of the normal runlevels.
  - Don't generate /boot/grub/device.map during grub-install or
    grub-mkconfig by default.
  - Adjust upgrade version checks for Ubuntu.
  - Don't display "GRUB loading" unless Shift is held down.
  - Adjust versions of grub-doc and grub-legacy-doc conflicts to tolerate
    our backport of the grub-doc split.
  - Fix LVM/RAID probing in the absence of /boot/grub/device.map.
  - Look for .mo files in /usr/share/locale-langpack as well, in
    preference.
  - Make sure GRUB_TIMEOUT isn't quoted unnecessarily.
  - Probe all devices in 'grub-probe --target=drive' if
    /boot/grub/device.map is missing.
  - Build-depend on qemu-kvm rather than qemu-system for grub-pc tests.
  - Use qemu rather than qemu-system-i386.
  - Program vesafb on BIOS systems rather than efifb.
  - Add a grub-rescue-efi-amd64 package containing a rescue CD-ROM image
    for EFI-AMD64.
  - On Wubi, don't ask for an install device, but just update wubildr
    using the diverted grub-install.
  - When embedding the core image in a post-MBR gap, check for and avoid
    sectors matching any of a list of known signatures.
  - Disable video_bochs and video_cirrus on PC BIOS systems, as probing
    PCI space seems to break on some systems.
* Downgrade "ACPI shutdown failed" error to a debug message, since it can
  cause spurious test failures.

[ Evan Broder ]
* Enable lua from grub-extras.
* Incorporate the bitop library into lua.
* Add enum_pci function to grub module in lua.
* Switch back to gfxpayload=keep by default, unless the video hardware
  is known to not support it.

[ Mario Limonciello ]
* Built part_msdos and vfat into bootx64.efi (LP: #677758)

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