]> git.ipfire.org Git - thirdparty/grub.git/commitdiff
2005-02-19 Yoshinori K. Okuji <okuji@enbug.org>
authorokuji <okuji@localhost>
Sat, 19 Feb 2005 20:56:07 +0000 (20:56 +0000)
committerokuji <okuji@localhost>
Sat, 19 Feb 2005 20:56:07 +0000 (20:56 +0000)
  This implements an Emacs-like menu entry editor.

  * normal/menu_entry.c: New file.

  * util/console.c (grub_ncurses_putchar): Translate some Unicode
  characters to ASCII.
  (saved_char): New variable.
  (grub_ncurses_checkkey): Rewritten completely.
  (grub_ncurses_getkey): Likewise.
  (grub_ncurses_init): Call raw instead of cbreak.

  * normal/menu.c (print_entry): Do not put a space.
  (init_page): Renamed to ...
  (grub_menu_init_page): ... this. All callers changed.
  (edit_menu_entry): Removed.
  (run_menu): Call grub_menu_entry_run instead of edit_menu_entry.

  * normal/cmdline.c (grub_cmdline_run): Call grub_setcursor.

  * kern/misc.c (grub_vprintf): Call grub_refresh.

  * normal/menu.c (DISP_LEFT): Renamed to ...
  * include/grub/term.h (GRUB_TERM_DISP_LEFT): ... this.
  * normal/menu.c (DISP_UP): Renamed to ...
  * include/grub/term.h (GRUB_TERM_DISP_UP): ... this.
  * normal/menu.c (DISP_RIGHT): Renamed to ...
  * include/grub/term.h (GRUB_TERM_DISP_RIGHT): ... this.
  * normal/menu.c (DISP_DOWN): Renamed to ...
  * include/grub/term.h (GRUB_TERM_DISP_DOWN): ... this.
  * normal/menu.c (DISP_HLINE): Renamed to ...
  * include/grub/term.h (GRUB_TERM_DISP_HLINE): ... this.
  * normal/menu.c (DISP_VLINE): Renamed to ...
  * include/grub/term.h (GRUB_TERM_DISP_VLINE): ... this.
  * normal/menu.c (DISP_UL): Renamed to ...
  * include/grub/term.h (GRUB_TERM_DISP_UL): ... this.
  * normal/menu.c (DISP_UR): Renamed to ...
  * include/grub/term.h (GRUB_TERM_DISP_UR): ... this.
  * normal/menu.c (DISP_LL): Renamed to ...
  * include/grub/term.h (GRUB_TERM_DISP_LL): ... this.
  * normal/menu.c (DISP_LR): Renamed to ...
  * include/grub/term.h (GRUB_TERM_DISP_LR): ... this.
  * normal/menu.c (TERM_WIDTH): Renamed to ...
  * include/grub/term.h (GRUB_TERM_WIDTH): ... this.
  * normal/menu.c (TERM_HEIGHT): Renamed to ...
  * include/grub/term.h (GRUB_TERM_HEIGHT): ... this.
  * normal/menu.c (TERM_INFO_HEIGHT): Renamed to ...
  * include/grub/term.h (GRUB_TERM_INFO_HEIGHT): ... this.
  * normal/menu.c (TERM_MARGIN): Renamed to ...
  * include/grub/term.h (GRUB_TERM_MARGIN): ... this.
  * normal/menu.c (TERM_SCROLL_WIDTH): Renamed to ...
  * include/grub/term.h (GRUB_TERM_SCROLL_WIDTH): ... this.
  * normal/menu.c (TERM_TOP_BORDER_Y): Renamed to ...
  * include/grub/term.h (GRUB_TERM_TOP_BORDER_Y): ... this.
  * normal/menu.c (TERM_LEFT_BORDER_X): Renamed to ...
  * include/grub/term.h (GRUB_TERM_LEFT_BORDER_X): ... this.
  * normal/menu.c (TERM_BORDER_WIDTH): Renamed to ...
  * include/grub/term.h (GRUB_TERM_BORDER_WIDTH): ... this.
  * normal/menu.c (TERM_MESSAGE_HEIGHT): Renamed to ...
  * include/grub/term.h (GRUB_TERM_MESSAGE_HEIGHT): ... this.
  * normal/menu.c (TERM_BORDER_HEIGHT): Renamed to ...
  * include/grub/term.h (GRUB_TERM_BORDER_HEIGHT): ... this.
  * normal/menu.c (TERM_NUM_ENTRIES): Renamed to ...
  * include/grub/term.h (GRUB_TERM_NUM_ENTRIES): ... this.
  * normal/menu.c (TERM_FIRST_ENTRY_Y): Renamed to ...
  * include/grub/term.h (GRUB_TERM_FIRST_ENTRY_Y): ... this.
  * normal/menu.c (TERM_ENTRY_WIDTH): Renamed to ...
  * include/grub/term.h (GRUB_TERM_ENTRY_WIDTH): ... this.
  * normal/menu.c (TERM_CURSOR_X): Renamed to ...
  * include/grub/term.h (GRUB_TERM_CURSOR_X): ... this.
  All callers changed.

  * include/grub/normal.h: New prototype.

  * conf/i386-pc.rmk (grub_emu_SOURCES): Added
  normal/menu_entry.c.
  (normal_mod_SOURCES): Likewise.
  * conf/powerpc-ieee1275.rmk (grub_emu_SOURCES): Likewise.
  (normal_mod_SOURCES): Likewise.

2005-02-15  Yoshinori K. Okuji  <okuji@enbug.org>

  * include/grub/normal.h (grub_halt_init): New prototype.
  (grub_halt_fini): Likewise.
  (grub_reboot_init): Likewise.
  (grub_reboot_fini): Likewise.

  * util/grub-emu.c: Include signal.h.
  (main_env): New global variable.
  (grub_machine_init): Ignore SIGINT. Otherwise grub-emu cannot
  catch C-c.
  (grub_machine_fini): New function.
  (main): Call grub_halt_init and grub_reboot_init before
  grub_main, and grub_reboot_fini and grub_halt_fini after it.
  Call setjmp with MAIN_ENV to go back afterwards.
  Call grub_machine_fini right before return.

  * include/grub/util/misc.h: Include setjmp.h.
  (main_env): New prototype.

  * include/grub/kernel.h (grub_machine_fini): New prototype.
  * include/grub/i386/pc/biosdisk.h (grub_biosdisk_fini): Likewise.
  * include/grub/i386/pc/console.h (grub_console_fini): Likewise.

  * disk/i386/pc/biosdisk.c (grub_biosdisk_fini): New function.
  * kern/i386/pc/init.c (grub_machine_fini): Likewise.
  * term/i386/pc/console.c (grub_console_fini): Likewise.

  * util/i386/pc/misc.c: New file.

  * conf/i386-pc.rmk (grub_emu_SOURCES): Added
  util/i386/pc/misc.c, commands/i386/pc/halt.c and
  commands/i386/pc/reboot.c.

ChangeLog
conf/i386-pc.mk
conf/i386-pc.rmk
conf/powerpc-ieee1275.rmk
include/grub/normal.h
include/grub/term.h
kern/misc.c
normal/cmdline.c
normal/menu.c
normal/menu_entry.c [new file with mode: 0644]
util/console.c

index ecf35f4826601bfcca8eeaf8ea5a5e88134e7d68..a8d9133a2b61ac98b6f065e62f1da6a8434a5329 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,84 @@
+2005-02-19  Yoshinori K. Okuji  <okuji@enbug.org>
+
+       This implements an Emacs-like menu entry editor.
+       
+       * normal/menu_entry.c: New file.
+       
+       * util/console.c (grub_ncurses_putchar): Translate some Unicode
+       characters to ASCII.
+       (saved_char): New variable.
+       (grub_ncurses_checkkey): Rewritten completely.
+       (grub_ncurses_getkey): Likewise.
+       (grub_ncurses_init): Call raw instead of cbreak.
+
+       * normal/menu.c (print_entry): Do not put a space.
+       (init_page): Renamed to ...
+       (grub_menu_init_page): ... this. All callers changed.
+       (edit_menu_entry): Removed.
+       (run_menu): Call grub_menu_entry_run instead of edit_menu_entry.
+
+       * normal/cmdline.c (grub_cmdline_run): Call grub_setcursor.
+
+       * kern/misc.c (grub_vprintf): Call grub_refresh.
+
+       * normal/menu.c (DISP_LEFT): Renamed to ...
+       * include/grub/term.h (GRUB_TERM_DISP_LEFT): ... this.
+       * normal/menu.c (DISP_UP): Renamed to ...
+       * include/grub/term.h (GRUB_TERM_DISP_UP): ... this.
+       * normal/menu.c (DISP_RIGHT): Renamed to ...
+       * include/grub/term.h (GRUB_TERM_DISP_RIGHT): ... this.
+       * normal/menu.c (DISP_DOWN): Renamed to ...
+       * include/grub/term.h (GRUB_TERM_DISP_DOWN): ... this.
+       * normal/menu.c (DISP_HLINE): Renamed to ...
+       * include/grub/term.h (GRUB_TERM_DISP_HLINE): ... this.
+       * normal/menu.c (DISP_VLINE): Renamed to ...
+       * include/grub/term.h (GRUB_TERM_DISP_VLINE): ... this.
+       * normal/menu.c (DISP_UL): Renamed to ...
+       * include/grub/term.h (GRUB_TERM_DISP_UL): ... this.
+       * normal/menu.c (DISP_UR): Renamed to ...
+       * include/grub/term.h (GRUB_TERM_DISP_UR): ... this.
+       * normal/menu.c (DISP_LL): Renamed to ...
+       * include/grub/term.h (GRUB_TERM_DISP_LL): ... this.
+       * normal/menu.c (DISP_LR): Renamed to ...
+       * include/grub/term.h (GRUB_TERM_DISP_LR): ... this.
+       * normal/menu.c (TERM_WIDTH): Renamed to ...
+       * include/grub/term.h (GRUB_TERM_WIDTH): ... this.
+       * normal/menu.c (TERM_HEIGHT): Renamed to ...
+       * include/grub/term.h (GRUB_TERM_HEIGHT): ... this.
+       * normal/menu.c (TERM_INFO_HEIGHT): Renamed to ...
+       * include/grub/term.h (GRUB_TERM_INFO_HEIGHT): ... this.
+       * normal/menu.c (TERM_MARGIN): Renamed to ...
+       * include/grub/term.h (GRUB_TERM_MARGIN): ... this.
+       * normal/menu.c (TERM_SCROLL_WIDTH): Renamed to ...
+       * include/grub/term.h (GRUB_TERM_SCROLL_WIDTH): ... this.
+       * normal/menu.c (TERM_TOP_BORDER_Y): Renamed to ...
+       * include/grub/term.h (GRUB_TERM_TOP_BORDER_Y): ... this.
+       * normal/menu.c (TERM_LEFT_BORDER_X): Renamed to ...
+       * include/grub/term.h (GRUB_TERM_LEFT_BORDER_X): ... this.
+       * normal/menu.c (TERM_BORDER_WIDTH): Renamed to ...
+       * include/grub/term.h (GRUB_TERM_BORDER_WIDTH): ... this.
+       * normal/menu.c (TERM_MESSAGE_HEIGHT): Renamed to ...
+       * include/grub/term.h (GRUB_TERM_MESSAGE_HEIGHT): ... this.
+       * normal/menu.c (TERM_BORDER_HEIGHT): Renamed to ...
+       * include/grub/term.h (GRUB_TERM_BORDER_HEIGHT): ... this.
+       * normal/menu.c (TERM_NUM_ENTRIES): Renamed to ...
+       * include/grub/term.h (GRUB_TERM_NUM_ENTRIES): ... this.
+       * normal/menu.c (TERM_FIRST_ENTRY_Y): Renamed to ...
+       * include/grub/term.h (GRUB_TERM_FIRST_ENTRY_Y): ... this.
+       * normal/menu.c (TERM_ENTRY_WIDTH): Renamed to ...
+       * include/grub/term.h (GRUB_TERM_ENTRY_WIDTH): ... this.
+       * normal/menu.c (TERM_CURSOR_X): Renamed to ...
+       * include/grub/term.h (GRUB_TERM_CURSOR_X): ... this.
+       All callers changed.
+
+       * include/grub/normal.h: New prototype.
+
+       * conf/i386-pc.rmk (grub_emu_SOURCES): Added
+       normal/menu_entry.c.
+       (normal_mod_SOURCES): Likewise.
+       * conf/powerpc-ieee1275.rmk (grub_emu_SOURCES): Likewise.
+       (normal_mod_SOURCES): Likewise.
+
 2005-02-15  Yoshinori K. Okuji  <okuji@enbug.org>
 
        * include/grub/normal.h (grub_halt_init): New prototype.
index a99cac8bfadeeb7980249392c35fb11c07067234..5b26d4e94dd395b6f9b05e6521a0e0314fd10e3c 100644 (file)
@@ -507,15 +507,15 @@ grub_emu_SOURCES = commands/boot.c commands/cat.c commands/cmp.c  \
        kern/file.c kern/fs.c kern/loader.c kern/main.c kern/misc.c     \
        kern/partition.c kern/rescue.c kern/term.c                      \
        normal/arg.c normal/cmdline.c normal/command.c normal/main.c    \
-       normal/menu.c                                                   \
+       normal/menu.c normal/menu_entry.c                               \
        partmap/amiga.c partmap/apple.c partmap/pc.c                    \
        util/console.c util/grub-emu.c util/misc.c                      \
        util/i386/pc/biosdisk.c util/i386/pc/getroot.c                  \
        util/i386/pc/misc.c
-CLEANFILES += grub-emu grub_emu-commands_boot.o grub_emu-commands_cat.o grub_emu-commands_cmp.o grub_emu-commands_help.o grub_emu-commands_terminal.o grub_emu-commands_ls.o grub_emu-commands_i386_pc_halt.o grub_emu-commands_i386_pc_reboot.o grub_emu-disk_loopback.o grub_emu-fs_ext2.o grub_emu-fs_fat.o grub_emu-fs_fshelp.o grub_emu-fs_hfs.o grub_emu-fs_iso9660.o grub_emu-fs_jfs.o grub_emu-fs_minix.o grub_emu-fs_ufs.o grub_emu-kern_device.o grub_emu-kern_disk.o grub_emu-kern_dl.o grub_emu-kern_env.o grub_emu-kern_err.o grub_emu-kern_file.o grub_emu-kern_fs.o grub_emu-kern_loader.o grub_emu-kern_main.o grub_emu-kern_misc.o grub_emu-kern_partition.o grub_emu-kern_rescue.o grub_emu-kern_term.o grub_emu-normal_arg.o grub_emu-normal_cmdline.o grub_emu-normal_command.o grub_emu-normal_main.o grub_emu-normal_menu.o grub_emu-partmap_amiga.o grub_emu-partmap_apple.o grub_emu-partmap_pc.o grub_emu-util_console.o grub_emu-util_grub_emu.o grub_emu-util_misc.o grub_emu-util_i386_pc_biosdisk.o grub_emu-util_i386_pc_getroot.o grub_emu-util_i386_pc_misc.o
-MOSTLYCLEANFILES += grub_emu-commands_boot.d grub_emu-commands_cat.d grub_emu-commands_cmp.d grub_emu-commands_help.d grub_emu-commands_terminal.d grub_emu-commands_ls.d grub_emu-commands_i386_pc_halt.d grub_emu-commands_i386_pc_reboot.d grub_emu-disk_loopback.d grub_emu-fs_ext2.d grub_emu-fs_fat.d grub_emu-fs_fshelp.d grub_emu-fs_hfs.d grub_emu-fs_iso9660.d grub_emu-fs_jfs.d grub_emu-fs_minix.d grub_emu-fs_ufs.d grub_emu-kern_device.d grub_emu-kern_disk.d grub_emu-kern_dl.d grub_emu-kern_env.d grub_emu-kern_err.d grub_emu-kern_file.d grub_emu-kern_fs.d grub_emu-kern_loader.d grub_emu-kern_main.d grub_emu-kern_misc.d grub_emu-kern_partition.d grub_emu-kern_rescue.d grub_emu-kern_term.d grub_emu-normal_arg.d grub_emu-normal_cmdline.d grub_emu-normal_command.d grub_emu-normal_main.d grub_emu-normal_menu.d grub_emu-partmap_amiga.d grub_emu-partmap_apple.d grub_emu-partmap_pc.d grub_emu-util_console.d grub_emu-util_grub_emu.d grub_emu-util_misc.d grub_emu-util_i386_pc_biosdisk.d grub_emu-util_i386_pc_getroot.d grub_emu-util_i386_pc_misc.d
+CLEANFILES += grub-emu grub_emu-commands_boot.o grub_emu-commands_cat.o grub_emu-commands_cmp.o grub_emu-commands_help.o grub_emu-commands_terminal.o grub_emu-commands_ls.o grub_emu-commands_i386_pc_halt.o grub_emu-commands_i386_pc_reboot.o grub_emu-disk_loopback.o grub_emu-fs_ext2.o grub_emu-fs_fat.o grub_emu-fs_fshelp.o grub_emu-fs_hfs.o grub_emu-fs_iso9660.o grub_emu-fs_jfs.o grub_emu-fs_minix.o grub_emu-fs_ufs.o grub_emu-kern_device.o grub_emu-kern_disk.o grub_emu-kern_dl.o grub_emu-kern_env.o grub_emu-kern_err.o grub_emu-kern_file.o grub_emu-kern_fs.o grub_emu-kern_loader.o grub_emu-kern_main.o grub_emu-kern_misc.o grub_emu-kern_partition.o grub_emu-kern_rescue.o grub_emu-kern_term.o grub_emu-normal_arg.o grub_emu-normal_cmdline.o grub_emu-normal_command.o grub_emu-normal_main.o grub_emu-normal_menu.o grub_emu-normal_menu_entry.o grub_emu-partmap_amiga.o grub_emu-partmap_apple.o grub_emu-partmap_pc.o grub_emu-util_console.o grub_emu-util_grub_emu.o grub_emu-util_misc.o grub_emu-util_i386_pc_biosdisk.o grub_emu-util_i386_pc_getroot.o grub_emu-util_i386_pc_misc.o
+MOSTLYCLEANFILES += grub_emu-commands_boot.d grub_emu-commands_cat.d grub_emu-commands_cmp.d grub_emu-commands_help.d grub_emu-commands_terminal.d grub_emu-commands_ls.d grub_emu-commands_i386_pc_halt.d grub_emu-commands_i386_pc_reboot.d grub_emu-disk_loopback.d grub_emu-fs_ext2.d grub_emu-fs_fat.d grub_emu-fs_fshelp.d grub_emu-fs_hfs.d grub_emu-fs_iso9660.d grub_emu-fs_jfs.d grub_emu-fs_minix.d grub_emu-fs_ufs.d grub_emu-kern_device.d grub_emu-kern_disk.d grub_emu-kern_dl.d grub_emu-kern_env.d grub_emu-kern_err.d grub_emu-kern_file.d grub_emu-kern_fs.d grub_emu-kern_loader.d grub_emu-kern_main.d grub_emu-kern_misc.d grub_emu-kern_partition.d grub_emu-kern_rescue.d grub_emu-kern_term.d grub_emu-normal_arg.d grub_emu-normal_cmdline.d grub_emu-normal_command.d grub_emu-normal_main.d grub_emu-normal_menu.d grub_emu-normal_menu_entry.d grub_emu-partmap_amiga.d grub_emu-partmap_apple.d grub_emu-partmap_pc.d grub_emu-util_console.d grub_emu-util_grub_emu.d grub_emu-util_misc.d grub_emu-util_i386_pc_biosdisk.d grub_emu-util_i386_pc_getroot.d grub_emu-util_i386_pc_misc.d
 
-grub-emu: grub_emu-commands_boot.o grub_emu-commands_cat.o grub_emu-commands_cmp.o grub_emu-commands_help.o grub_emu-commands_terminal.o grub_emu-commands_ls.o grub_emu-commands_i386_pc_halt.o grub_emu-commands_i386_pc_reboot.o grub_emu-disk_loopback.o grub_emu-fs_ext2.o grub_emu-fs_fat.o grub_emu-fs_fshelp.o grub_emu-fs_hfs.o grub_emu-fs_iso9660.o grub_emu-fs_jfs.o grub_emu-fs_minix.o grub_emu-fs_ufs.o grub_emu-kern_device.o grub_emu-kern_disk.o grub_emu-kern_dl.o grub_emu-kern_env.o grub_emu-kern_err.o grub_emu-kern_file.o grub_emu-kern_fs.o grub_emu-kern_loader.o grub_emu-kern_main.o grub_emu-kern_misc.o grub_emu-kern_partition.o grub_emu-kern_rescue.o grub_emu-kern_term.o grub_emu-normal_arg.o grub_emu-normal_cmdline.o grub_emu-normal_command.o grub_emu-normal_main.o grub_emu-normal_menu.o grub_emu-partmap_amiga.o grub_emu-partmap_apple.o grub_emu-partmap_pc.o grub_emu-util_console.o grub_emu-util_grub_emu.o grub_emu-util_misc.o grub_emu-util_i386_pc_biosdisk.o grub_emu-util_i386_pc_getroot.o grub_emu-util_i386_pc_misc.o
+grub-emu: grub_emu-commands_boot.o grub_emu-commands_cat.o grub_emu-commands_cmp.o grub_emu-commands_help.o grub_emu-commands_terminal.o grub_emu-commands_ls.o grub_emu-commands_i386_pc_halt.o grub_emu-commands_i386_pc_reboot.o grub_emu-disk_loopback.o grub_emu-fs_ext2.o grub_emu-fs_fat.o grub_emu-fs_fshelp.o grub_emu-fs_hfs.o grub_emu-fs_iso9660.o grub_emu-fs_jfs.o grub_emu-fs_minix.o grub_emu-fs_ufs.o grub_emu-kern_device.o grub_emu-kern_disk.o grub_emu-kern_dl.o grub_emu-kern_env.o grub_emu-kern_err.o grub_emu-kern_file.o grub_emu-kern_fs.o grub_emu-kern_loader.o grub_emu-kern_main.o grub_emu-kern_misc.o grub_emu-kern_partition.o grub_emu-kern_rescue.o grub_emu-kern_term.o grub_emu-normal_arg.o grub_emu-normal_cmdline.o grub_emu-normal_command.o grub_emu-normal_main.o grub_emu-normal_menu.o grub_emu-normal_menu_entry.o grub_emu-partmap_amiga.o grub_emu-partmap_apple.o grub_emu-partmap_pc.o grub_emu-util_console.o grub_emu-util_grub_emu.o grub_emu-util_misc.o grub_emu-util_i386_pc_biosdisk.o grub_emu-util_i386_pc_getroot.o grub_emu-util_i386_pc_misc.o
        $(BUILD_CC) -o $@ $^ $(BUILD_LDFLAGS) $(grub_emu_LDFLAGS)
 
 grub_emu-commands_boot.o: commands/boot.c
@@ -798,6 +798,14 @@ grub_emu-normal_menu.d: normal/menu.c
 
 -include grub_emu-normal_menu.d
 
+grub_emu-normal_menu_entry.o: normal/menu_entry.c
+       $(BUILD_CC) -Inormal -I$(srcdir)/normal $(BUILD_CPPFLAGS) $(BUILD_CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -c -o $@ $<
+
+grub_emu-normal_menu_entry.d: normal/menu_entry.c
+       set -e;           $(BUILD_CC) -Inormal -I$(srcdir)/normal $(BUILD_CPPFLAGS) $(BUILD_CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -M $<        | sed 's,menu_entry\.o[ :]*,grub_emu-normal_menu_entry.o $@ : ,g' > $@;         [ -s $@ ] || rm -f $@
+
+-include grub_emu-normal_menu_entry.d
+
 grub_emu-partmap_amiga.o: partmap/amiga.c
        $(BUILD_CC) -Ipartmap -I$(srcdir)/partmap $(BUILD_CPPFLAGS) $(BUILD_CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -c -o $@ $<
 
@@ -1330,10 +1338,11 @@ linux_mod-loader_i386_pc_linux_normal.d: loader/i386/pc/linux_normal.c
 linux_mod_CFLAGS = $(COMMON_CFLAGS)
 
 # For normal.mod.
-normal_mod_SOURCES = normal/cmdline.c normal/command.c normal/main.c \
-       normal/menu.c normal/arg.c normal/i386/setjmp.S
-CLEANFILES += normal.mod mod-normal.o mod-normal.c pre-normal.o normal_mod-normal_cmdline.o normal_mod-normal_command.o normal_mod-normal_main.o normal_mod-normal_menu.o normal_mod-normal_arg.o normal_mod-normal_i386_setjmp.o def-normal.lst und-normal.lst
-MOSTLYCLEANFILES += normal_mod-normal_cmdline.d normal_mod-normal_command.d normal_mod-normal_main.d normal_mod-normal_menu.d normal_mod-normal_arg.d normal_mod-normal_i386_setjmp.d
+normal_mod_SOURCES = normal/arg.c normal/cmdline.c normal/command.c    \
+       normal/main.c normal/menu.c normal/menu_entry.c                 \
+       normal/i386/setjmp.S
+CLEANFILES += normal.mod mod-normal.o mod-normal.c pre-normal.o normal_mod-normal_arg.o normal_mod-normal_cmdline.o normal_mod-normal_command.o normal_mod-normal_main.o normal_mod-normal_menu.o normal_mod-normal_menu_entry.o normal_mod-normal_i386_setjmp.o def-normal.lst und-normal.lst
+MOSTLYCLEANFILES += normal_mod-normal_arg.d normal_mod-normal_cmdline.d normal_mod-normal_command.d normal_mod-normal_main.d normal_mod-normal_menu.d normal_mod-normal_menu_entry.d normal_mod-normal_i386_setjmp.d
 DEFSYMFILES += def-normal.lst
 UNDSYMFILES += und-normal.lst
 
@@ -1342,7 +1351,7 @@ normal.mod: pre-normal.o mod-normal.o
        $(LD) -r -d -o $@ $^
        $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -R .note -R .comment $@
 
-pre-normal.o: normal_mod-normal_cmdline.o normal_mod-normal_command.o normal_mod-normal_main.o normal_mod-normal_menu.o normal_mod-normal_arg.o normal_mod-normal_i386_setjmp.o
+pre-normal.o: normal_mod-normal_arg.o normal_mod-normal_cmdline.o normal_mod-normal_command.o normal_mod-normal_main.o normal_mod-normal_menu.o normal_mod-normal_menu_entry.o normal_mod-normal_i386_setjmp.o
        -rm -f $@
        $(LD) -r -d -o $@ $^
 
@@ -1359,6 +1368,14 @@ und-normal.lst: pre-normal.o
        echo 'normal' > $@
        $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
 
+normal_mod-normal_arg.o: normal/arg.c
+       $(CC) -Inormal -I$(srcdir)/normal $(CPPFLAGS) $(CFLAGS) $(normal_mod_CFLAGS) -c -o $@ $<
+
+normal_mod-normal_arg.d: normal/arg.c
+       set -e;           $(CC) -Inormal -I$(srcdir)/normal $(CPPFLAGS) $(CFLAGS) $(normal_mod_CFLAGS) -M $<      | sed 's,arg\.o[ :]*,normal_mod-normal_arg.o $@ : ,g' > $@;     [ -s $@ ] || rm -f $@
+
+-include normal_mod-normal_arg.d
+
 normal_mod-normal_cmdline.o: normal/cmdline.c
        $(CC) -Inormal -I$(srcdir)/normal $(CPPFLAGS) $(CFLAGS) $(normal_mod_CFLAGS) -c -o $@ $<
 
@@ -1391,13 +1408,13 @@ normal_mod-normal_menu.d: normal/menu.c
 
 -include normal_mod-normal_menu.d
 
-normal_mod-normal_arg.o: normal/arg.c
+normal_mod-normal_menu_entry.o: normal/menu_entry.c
        $(CC) -Inormal -I$(srcdir)/normal $(CPPFLAGS) $(CFLAGS) $(normal_mod_CFLAGS) -c -o $@ $<
 
-normal_mod-normal_arg.d: normal/arg.c
-       set -e;           $(CC) -Inormal -I$(srcdir)/normal $(CPPFLAGS) $(CFLAGS) $(normal_mod_CFLAGS) -M $<      | sed 's,arg\.o[ :]*,normal_mod-normal_arg.o $@ : ,g' > $@;     [ -s $@ ] || rm -f $@
+normal_mod-normal_menu_entry.d: normal/menu_entry.c
+       set -e;           $(CC) -Inormal -I$(srcdir)/normal $(CPPFLAGS) $(CFLAGS) $(normal_mod_CFLAGS) -M $<      | sed 's,menu_entry\.o[ :]*,normal_mod-normal_menu_entry.o $@ : ,g' > $@;       [ -s $@ ] || rm -f $@
 
--include normal_mod-normal_arg.d
+-include normal_mod-normal_menu_entry.d
 
 normal_mod-normal_i386_setjmp.o: normal/i386/setjmp.S
        $(CC) -Inormal/i386 -I$(srcdir)/normal/i386 $(CPPFLAGS) $(ASFLAGS) $(normal_mod_ASFLAGS) -c -o $@ $<
index d5728e2510a5da88b6c6b9cb704fcccf97d0cd48..d649c359e04a68fd8498a79a8789936e40516df4 100644 (file)
@@ -75,7 +75,7 @@ grub_emu_SOURCES = commands/boot.c commands/cat.c commands/cmp.c      \
        kern/file.c kern/fs.c kern/loader.c kern/main.c kern/misc.c     \
        kern/partition.c kern/rescue.c kern/term.c                      \
        normal/arg.c normal/cmdline.c normal/command.c normal/main.c    \
-       normal/menu.c                                                   \
+       normal/menu.c normal/menu_entry.c                               \
        partmap/amiga.c partmap/apple.c partmap/pc.c                    \
        util/console.c util/grub-emu.c util/misc.c                      \
        util/i386/pc/biosdisk.c util/i386/pc/getroot.c                  \
@@ -141,8 +141,9 @@ linux_mod_SOURCES = loader/i386/pc/linux_normal.c
 linux_mod_CFLAGS = $(COMMON_CFLAGS)
 
 # For normal.mod.
-normal_mod_SOURCES = normal/cmdline.c normal/command.c normal/main.c \
-       normal/menu.c normal/arg.c normal/i386/setjmp.S
+normal_mod_SOURCES = normal/arg.c normal/cmdline.c normal/command.c    \
+       normal/main.c normal/menu.c normal/menu_entry.c                 \
+       normal/i386/setjmp.S
 normal_mod_CFLAGS = $(COMMON_CFLAGS)
 normal_mod_ASFLAGS = $(COMMON_ASFLAGS)
 
index a06a58f6656587a49fb8e339f6dfa739c8c1dcf9..25a0388626282494523404a4db0dbbf1f863896d 100644 (file)
@@ -39,7 +39,7 @@ grub_emu_SOURCES = kern/main.c kern/device.c                          \
        util/i386/pc/biosdisk.c fs/fat.c fs/ext2.c fs/ufs.c fs/minix.c fs/hfs.c \
        fs/jfs.c fs/iso9660.c \
        normal/cmdline.c normal/command.c normal/main.c normal/menu.c   \
-       normal/arg.c kern/partition.c   \
+       normal/menu_entry.c normal/arg.c kern/partition.c       \
        util/console.c util/grub-emu.c util/misc.c util/i386/pc/getroot.c \
        kern/env.c disk/loopback.c commands/ls.c commands/help.c        \
        commands/terminal.c commands/boot.c commands/cmp.c commands/cat.c
@@ -108,8 +108,9 @@ linux_mod_SOURCES = loader/powerpc/ieee1275/linux_normal.c
 linux_mod_CFLAGS = $(COMMON_CFLAGS)
 
 # For normal.mod.
-normal_mod_SOURCES = normal/cmdline.c normal/command.c normal/main.c \
-       normal/menu.c normal/arg.c normal/powerpc/setjmp.S
+normal_mod_SOURCES = normal/arg.c normal/cmdline.c normal/command.c    \
+       normal/main.c normal/menu.c normal/menu_entry.c                 \
+       normal/powerpc/setjmp.S
 normal_mod_CFLAGS = $(COMMON_CFLAGS)
 normal_mod_ASFLAGS = $(COMMON_ASFLAGS)
 
index 3ab367fe268078f338fdf574964b0f8d7b7326d4..f89b6c7cbff1fd76f3b81f102efeaf4eacdc2a79 100644 (file)
@@ -140,6 +140,7 @@ int grub_iterate_commands (int (*iterate) (grub_command_t));
 int grub_command_execute (char *cmdline);
 void grub_command_init (void);
 void grub_normal_init_page (void);
+void grub_menu_init_page (int nested, int edit);
 int grub_arg_parse (grub_command_t parser, int argc, char **argv,
                    struct grub_arg_list *usr, char ***args, int *argnum);
 void grub_arg_show_help (grub_command_t cmd);
index 594648542cc3fe8fdf28f67f0bb61fe1c7d731ae..8612272a1ea6160bf812b6ffcf5e8a630ae21e73 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  GRUB  --  GRand Unified Bootloader
- *  Copyright (C) 2002,2003  Free Software Foundation, Inc.
+ *  Copyright (C) 2002,2003,2005  Free Software Foundation, Inc.
  *
  *  GRUB is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -55,6 +55,73 @@ grub_term_color_state;
 /* Set when the terminal needs to be initialized.  */
 #define GRUB_TERM_NEED_INIT    (1 << 16)
 
+
+/* Unicode characters for fancy graphics.  */
+#define GRUB_TERM_DISP_LEFT    0x2190
+#define GRUB_TERM_DISP_UP      0x2191
+#define GRUB_TERM_DISP_RIGHT   0x2192
+#define GRUB_TERM_DISP_DOWN    0x2193
+#define GRUB_TERM_DISP_HLINE   0x2501
+#define GRUB_TERM_DISP_VLINE   0x2503
+#define GRUB_TERM_DISP_UL      0x250F
+#define GRUB_TERM_DISP_UR      0x2513
+#define GRUB_TERM_DISP_LL      0x2517
+#define GRUB_TERM_DISP_LR      0x251B
+
+
+/* Menu-related geometrical constants.  */
+
+/* FIXME: These should be dynamically obtained from a terminal.  */
+#define GRUB_TERM_WIDTH                80
+#define GRUB_TERM_HEIGHT       25
+
+/* The number of lines of "GRUB version..." at the top.  */
+#define GRUB_TERM_INFO_HEIGHT  1
+
+/* The number of columns/lines between messages/borders/etc.  */
+#define GRUB_TERM_MARGIN       1
+
+/* The number of columns of scroll information.  */
+#define GRUB_TERM_SCROLL_WIDTH 1
+
+/* The Y position of the top border.  */
+#define GRUB_TERM_TOP_BORDER_Y (GRUB_TERM_MARGIN + GRUB_TERM_INFO_HEIGHT \
+                                 + GRUB_TERM_MARGIN)
+
+/* The X position of the left border.  */
+#define GRUB_TERM_LEFT_BORDER_X        GRUB_TERM_MARGIN
+
+/* The width of the border.  */
+#define GRUB_TERM_BORDER_WIDTH (GRUB_TERM_WIDTH \
+                                 - GRUB_TERM_MARGIN * 3 \
+                                - GRUB_TERM_SCROLL_WIDTH)
+
+/* The number of lines of messages at the bottom.  */
+#define GRUB_TERM_MESSAGE_HEIGHT       8
+
+/* The height of the border.  */
+#define GRUB_TERM_BORDER_HEIGHT        (GRUB_TERM_HEIGHT \
+                                 - GRUB_TERM_TOP_BORDER_Y \
+                                 - GRUB_TERM_MESSAGE_HEIGHT)
+
+/* The number of entries shown at a time.  */
+#define GRUB_TERM_NUM_ENTRIES  (GRUB_TERM_BORDER_HEIGHT - 2)
+
+/* The Y position of the first entry.  */
+#define GRUB_TERM_FIRST_ENTRY_Y        (GRUB_TERM_TOP_BORDER_Y + 1)
+
+/* The max column number of an entry. The last "-1" is for a
+   continuation marker.  */
+#define GRUB_TERM_ENTRY_WIDTH  (GRUB_TERM_BORDER_WIDTH - 2 \
+                                 - GRUB_TERM_MARGIN * 2 - 1)
+
+/* The standard X position of the cursor.  */
+#define GRUB_TERM_CURSOR_X     (GRUB_TERM_LEFT_BORDER_X \
+                                 + GRUB_TERM_BORDER_WIDTH \
+                                 - GRUB_TERM_MARGIN \
+                                 - 1)
+
+
 struct grub_term
 {
   /* The terminal name.  */
index 1352a6fe5a3bb418b2c7095efa935e82dbac6caf..da809ff5c99ea9428fdcc1496bd29583813a49d8 100644 (file)
@@ -131,7 +131,11 @@ grub_printf (const char *fmt, ...)
 int
 grub_vprintf (const char *fmt, va_list args)
 {
-  return grub_vsprintf (0, fmt, args);
+  int ret;
+
+  ret = grub_vsprintf (0, fmt, args);
+  grub_refresh ();
+  return ret;
 }
 
 int
index 694d33133900d9b6048d5f8aaeee8642422c0cb3..d235803f46dbd91f38319f1afbf4967e2c5c9b69 100644 (file)
@@ -431,6 +431,7 @@ void
 grub_cmdline_run (int nested)
 {
   grub_normal_init_page ();
+  grub_setcursor (1);
   
   grub_printf ("\
  [ Minimal BASH-like line editing is supported. For the first word, TAB\n\
index 1debeb27a13ca49af9cce28450602378952b8817..e8d77070a555720cec2ddf5bc484a610dfb11df2 100644 (file)
 #include <grub/mm.h>
 #include <grub/machine/time.h>
 
-/* FIXME: These below are all runaround.  */
-
-#define DISP_LEFT      0x2190
-#define DISP_UP                0x2191
-#define DISP_RIGHT     0x2192
-#define DISP_DOWN      0x2193
-#define DISP_HLINE     0x2501
-#define DISP_VLINE     0x2503
-#define DISP_UL                0x250F
-#define DISP_UR                0x2513
-#define DISP_LL                0x2517
-#define DISP_LR                0x251B
-
-/* FIXME: These should be dynamically obtained from a terminal.  */
-#define TERM_WIDTH     80
-#define TERM_HEIGHT    25
-
-/* The number of lines of "GRUB version..." at the top.  */
-#define TERM_INFO_HEIGHT       1
-
-/* The number of columns/lines between messages/borders/etc.  */
-#define TERM_MARGIN    1
-
-/* The number of columns of scroll information.  */
-#define TERM_SCROLL_WIDTH      1
-
-/* The Y position of the top border.  */
-#define TERM_TOP_BORDER_Y      (TERM_MARGIN + TERM_INFO_HEIGHT + TERM_MARGIN)
-
-/* The X position of the left border.  */
-#define TERM_LEFT_BORDER_X     TERM_MARGIN
-
-/* The width of the border.  */
-#define TERM_BORDER_WIDTH      (TERM_WIDTH \
-                                 - TERM_MARGIN * 3 \
-                                - TERM_SCROLL_WIDTH)
-
-/* The number of lines of messages at the bottom.  */
-#define TERM_MESSAGE_HEIGHT    8
-
-/* The height of the border.  */
-#define TERM_BORDER_HEIGHT     (TERM_HEIGHT \
-                                 - TERM_TOP_BORDER_Y \
-                                 - TERM_MESSAGE_HEIGHT)
-
-/* The number of entries shown at a time.  */
-#define TERM_NUM_ENTRIES       (TERM_BORDER_HEIGHT - 2)
-
-/* The Y position of the first entry.  */
-#define TERM_FIRST_ENTRY_Y     (TERM_TOP_BORDER_Y + 1)
-
-/* The max column number of an entry. The last "-1" is for a
-   continuation marker.  */
-#define TERM_ENTRY_WIDTH       (TERM_BORDER_WIDTH - 2 - TERM_MARGIN * 2 - 1)
-
-/* The standard X position of the cursor.  */
-#define TERM_CURSOR_X          (TERM_LEFT_BORDER_X \
-                                 + TERM_BORDER_WIDTH \
-                                 - TERM_MARGIN \
-                                 - 1)
-
 static void
 draw_border (void)
 {
@@ -92,29 +31,29 @@ draw_border (void)
   
   grub_setcolorstate (GRUB_TERM_COLOR_NORMAL);
   
-  grub_gotoxy (TERM_MARGIN, TERM_TOP_BORDER_Y);
-  grub_putcode (DISP_UL);
-  for (i = 0; i < TERM_BORDER_WIDTH - 2; i++)
-    grub_putcode (DISP_HLINE);
-  grub_putcode (DISP_UR);
+  grub_gotoxy (GRUB_TERM_MARGIN, GRUB_TERM_TOP_BORDER_Y);
+  grub_putcode (GRUB_TERM_DISP_UL);
+  for (i = 0; i < GRUB_TERM_BORDER_WIDTH - 2; i++)
+    grub_putcode (GRUB_TERM_DISP_HLINE);
+  grub_putcode (GRUB_TERM_DISP_UR);
 
-  for (i = 0; i < (unsigned) TERM_NUM_ENTRIES; i++)
+  for (i = 0; i < (unsigned) GRUB_TERM_NUM_ENTRIES; i++)
     {
-      grub_gotoxy (TERM_MARGIN, TERM_TOP_BORDER_Y + i + 1);
-      grub_putcode (DISP_VLINE);
-      grub_gotoxy (TERM_MARGIN + TERM_BORDER_WIDTH - 1, TERM_TOP_BORDER_Y + i + 1);
-      grub_putcode (DISP_VLINE);
+      grub_gotoxy (GRUB_TERM_MARGIN, GRUB_TERM_TOP_BORDER_Y + i + 1);
+      grub_putcode (GRUB_TERM_DISP_VLINE);
+      grub_gotoxy (GRUB_TERM_MARGIN + GRUB_TERM_BORDER_WIDTH - 1, GRUB_TERM_TOP_BORDER_Y + i + 1);
+      grub_putcode (GRUB_TERM_DISP_VLINE);
     }
 
-  grub_gotoxy (TERM_MARGIN, TERM_TOP_BORDER_Y + TERM_NUM_ENTRIES + 1);
-  grub_putcode (DISP_LL);
-  for (i = 0; i < TERM_BORDER_WIDTH - 2; i++)
-    grub_putcode (DISP_HLINE);
-  grub_putcode (DISP_LR);
+  grub_gotoxy (GRUB_TERM_MARGIN, GRUB_TERM_TOP_BORDER_Y + GRUB_TERM_NUM_ENTRIES + 1);
+  grub_putcode (GRUB_TERM_DISP_LL);
+  for (i = 0; i < GRUB_TERM_BORDER_WIDTH - 2; i++)
+    grub_putcode (GRUB_TERM_DISP_HLINE);
+  grub_putcode (GRUB_TERM_DISP_LR);
 
   grub_setcolorstate (GRUB_TERM_COLOR_STANDARD);
 
-  grub_gotoxy (TERM_MARGIN, TERM_TOP_BORDER_Y + TERM_NUM_ENTRIES + TERM_MARGIN + 1);
+  grub_gotoxy (GRUB_TERM_MARGIN, GRUB_TERM_TOP_BORDER_Y + GRUB_TERM_NUM_ENTRIES + GRUB_TERM_MARGIN + 1);
 }
 
 static void
@@ -131,7 +70,7 @@ print_message (int nested, int edit)
     {
       grub_printf ("\n\
       Use the %C and %C keys to select which entry is highlighted.\n",
-                  (grub_uint32_t) DISP_UP, (grub_uint32_t) DISP_DOWN);
+                  (grub_uint32_t) GRUB_TERM_DISP_UP, (grub_uint32_t) GRUB_TERM_DISP_DOWN);
       grub_printf ("\
       Press enter to boot the selected OS, \'e\' to edit the\n\
       commands before booting or \'c\' for a command-line.");
@@ -165,23 +104,23 @@ print_entry (int y, int highlight, grub_menu_entry_t entry)
                      ? GRUB_TERM_COLOR_HIGHLIGHT
                      : GRUB_TERM_COLOR_NORMAL);
 
-  grub_gotoxy (TERM_LEFT_BORDER_X + TERM_MARGIN, y);
-  grub_putchar (' ');
-  for (x = TERM_LEFT_BORDER_X + TERM_MARGIN + 1;
-       x < TERM_LEFT_BORDER_X + TERM_BORDER_WIDTH - TERM_MARGIN;
+  grub_gotoxy (GRUB_TERM_LEFT_BORDER_X + GRUB_TERM_MARGIN, y);
+
+  for (x = GRUB_TERM_LEFT_BORDER_X + GRUB_TERM_MARGIN + 1;
+       x < GRUB_TERM_LEFT_BORDER_X + GRUB_TERM_BORDER_WIDTH - GRUB_TERM_MARGIN;
        x++)
     {
-      if (*title && x <= TERM_LEFT_BORDER_X + TERM_BORDER_WIDTH - TERM_MARGIN - 1)
+      if (*title && x <= GRUB_TERM_LEFT_BORDER_X + GRUB_TERM_BORDER_WIDTH - GRUB_TERM_MARGIN - 1)
        {
-         if (x == TERM_LEFT_BORDER_X + TERM_BORDER_WIDTH - TERM_MARGIN - 1)
-           grub_putcode (DISP_RIGHT);
+         if (x == GRUB_TERM_LEFT_BORDER_X + GRUB_TERM_BORDER_WIDTH - GRUB_TERM_MARGIN - 1)
+           grub_putcode (GRUB_TERM_DISP_RIGHT);
          else
            grub_putchar (*title++);
        }
       else
        grub_putchar (' ');
     }
-  grub_gotoxy (TERM_CURSOR_X, y);
+  grub_gotoxy (GRUB_TERM_CURSOR_X, y);
 
   grub_setcolorstate (GRUB_TERM_COLOR_STANDARD);
 }
@@ -192,49 +131,45 @@ print_entries (grub_menu_t menu, int first, int offset)
   grub_menu_entry_t e;
   int i;
   
-  grub_gotoxy (TERM_LEFT_BORDER_X + TERM_BORDER_WIDTH,
-              TERM_FIRST_ENTRY_Y);
+  grub_gotoxy (GRUB_TERM_LEFT_BORDER_X + GRUB_TERM_BORDER_WIDTH,
+              GRUB_TERM_FIRST_ENTRY_Y);
 
   if (first)
-    grub_putcode (DISP_UP);
+    grub_putcode (GRUB_TERM_DISP_UP);
   else
     grub_putchar (' ');
 
   e = get_entry (menu, first);
 
-  for (i = 0; i < TERM_NUM_ENTRIES; i++)
+  for (i = 0; i < GRUB_TERM_NUM_ENTRIES; i++)
     {
-      print_entry (TERM_FIRST_ENTRY_Y + i, offset == i, e);
+      print_entry (GRUB_TERM_FIRST_ENTRY_Y + i, offset == i, e);
       if (e)
        e = e->next;
     }
 
-  grub_gotoxy (TERM_LEFT_BORDER_X + TERM_BORDER_WIDTH,
-              TERM_TOP_BORDER_Y + TERM_NUM_ENTRIES);
+  grub_gotoxy (GRUB_TERM_LEFT_BORDER_X + GRUB_TERM_BORDER_WIDTH,
+              GRUB_TERM_TOP_BORDER_Y + GRUB_TERM_NUM_ENTRIES);
 
   if (e)
-    grub_putcode (DISP_DOWN);
+    grub_putcode (GRUB_TERM_DISP_DOWN);
   else
     grub_putchar (' ');
 
-  grub_gotoxy (TERM_CURSOR_X, TERM_FIRST_ENTRY_Y + offset);
+  grub_gotoxy (GRUB_TERM_CURSOR_X, GRUB_TERM_FIRST_ENTRY_Y + offset);
 }
 
-static void
-init_page (int nested, int edit)
+/* Initialize the screen.  If NESTED is non-zero, assume that this menu
+   is run from another menu or a command-line. If EDIT is non-zero, show
+   a message for the menu entry editor.  */
+void
+grub_menu_init_page (int nested, int edit)
 {
   grub_normal_init_page ();
   draw_border ();
   print_message (nested, edit);
 }
 
-/* Edit a menu entry with an Emacs-like interface.  */
-static void
-edit_menu_entry (grub_menu_entry_t entry)
-{
-  /* Not yet implemented.  */
-}
-
 static int
 run_menu (grub_menu_t menu, int nested)
 {
@@ -243,10 +178,10 @@ run_menu (grub_menu_t menu, int nested)
   
   first = 0;
   offset = menu->default_entry;
-  if (offset > TERM_NUM_ENTRIES - 1)
+  if (offset > GRUB_TERM_NUM_ENTRIES - 1)
     {
-      first = offset - (TERM_NUM_ENTRIES - 1);
-      offset = TERM_NUM_ENTRIES - 1;
+      first = offset - (GRUB_TERM_NUM_ENTRIES - 1);
+      offset = GRUB_TERM_NUM_ENTRIES - 1;
     }
 
   /* Initialize the time.  */
@@ -254,7 +189,7 @@ run_menu (grub_menu_t menu, int nested)
 
  refresh:
   grub_setcursor (0);
-  init_page (nested, 0);
+  grub_menu_init_page (nested, 0);
   print_entries (menu, first, offset);
   grub_refresh ();
 
@@ -273,13 +208,13 @@ run_menu (grub_menu_t menu, int nested)
              saved_time = current_time;
            }
          
-         grub_gotoxy (0, TERM_HEIGHT - 3);
+         grub_gotoxy (0, GRUB_TERM_HEIGHT - 3);
          /* NOTE: Do not remove the trailing space characters.
             They are required to clear the line.  */
          grub_printf ("\
    The highlighted entry will be booted automatically in %d seconds.    ",
                       menu->timeout);
-         grub_gotoxy (TERM_CURSOR_X, TERM_FIRST_ENTRY_Y + offset);
+         grub_gotoxy (GRUB_TERM_CURSOR_X, GRUB_TERM_FIRST_ENTRY_Y + offset);
          grub_refresh ();
        }
 
@@ -292,12 +227,12 @@ run_menu (grub_menu_t menu, int nested)
          
          if (menu->timeout >= 0)
            {
-             grub_gotoxy (0, TERM_HEIGHT - 3);
+             grub_gotoxy (0, GRUB_TERM_HEIGHT - 3);
               grub_printf ("\
                                                                         ");
               menu->timeout = -1;
               menu->fallback_entry = -1;
-             grub_gotoxy (TERM_CURSOR_X, TERM_FIRST_ENTRY_Y + offset);
+             grub_gotoxy (GRUB_TERM_CURSOR_X, GRUB_TERM_FIRST_ENTRY_Y + offset);
            }
          
          switch (c)
@@ -306,10 +241,10 @@ run_menu (grub_menu_t menu, int nested)
            case '^':
              if (offset > 0)
                {
-                 print_entry (TERM_FIRST_ENTRY_Y + offset, 0,
+                 print_entry (GRUB_TERM_FIRST_ENTRY_Y + offset, 0,
                               get_entry (menu, first + offset));
                  offset--;
-                 print_entry (TERM_FIRST_ENTRY_Y + offset, 1,
+                 print_entry (GRUB_TERM_FIRST_ENTRY_Y + offset, 1,
                               get_entry (menu, first + offset));
                }
              else if (first > 0)
@@ -323,12 +258,12 @@ run_menu (grub_menu_t menu, int nested)
            case 'v':
              if (menu->size > first + offset + 1)
                {
-                 if (offset < TERM_NUM_ENTRIES - 1)
+                 if (offset < GRUB_TERM_NUM_ENTRIES - 1)
                    {
-                     print_entry (TERM_FIRST_ENTRY_Y + offset, 0,
+                     print_entry (GRUB_TERM_FIRST_ENTRY_Y + offset, 0,
                                   get_entry (menu, first + offset));
                      offset++;
-                     print_entry (TERM_FIRST_ENTRY_Y + offset, 1,
+                     print_entry (GRUB_TERM_FIRST_ENTRY_Y + offset, 1,
                                   get_entry (menu, first + offset));
                    }
                  else
@@ -354,12 +289,11 @@ run_menu (grub_menu_t menu, int nested)
              break;
              
            case 'c':
-             grub_setcursor (1);
              grub_cmdline_run (1);
              goto refresh;
 
            case 'e':
-             edit_menu_entry (get_entry (menu, first + offset));
+             grub_menu_entry_run (get_entry (menu, first + offset));
              goto refresh;
              
            default:
diff --git a/normal/menu_entry.c b/normal/menu_entry.c
new file mode 100644 (file)
index 0000000..5b11ed9
--- /dev/null
@@ -0,0 +1,1016 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2005  Free Software Foundation, Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <grub/normal.h>
+#include <grub/term.h>
+#include <grub/misc.h>
+#include <grub/mm.h>
+#include <grub/loader.h>
+
+enum update_mode
+  {
+    NO_LINE,
+    SINGLE_LINE,
+    ALL_LINES
+  };
+
+struct line
+{
+  /* The line buffer.  */
+  char *buf;
+  /* The length of the line.  */
+  int len;
+  /* The maximum length of the line.  */
+  int max_len;
+};
+
+struct screen
+{
+  /* The array of lines.  */
+  struct line *lines;
+  /* The number of lines.  */
+  int num_lines;
+  /* The current column.  */
+  int column;
+  /* The real column.  */
+  int real_column;
+  /* The current line.  */
+  int line;
+  /* The X coordinate.  */
+  int x;
+  /* The Y coordinate.  */
+  int y;
+  /* The kill buffer.  */
+  char *killed_text;
+};
+
+/* Initialize a line.  */
+static int
+init_line (struct line *linep)
+{
+  linep->len = 0;
+  linep->max_len = 80; /* XXX */
+  linep->buf = grub_malloc (linep->max_len);
+  if (! linep->buf)
+    return 0;
+
+  return 1;
+}
+
+/* Allocate extra space if necessary.  */
+static int
+ensure_space (struct line *linep, int extra)
+{
+  if (linep->max_len < linep->len + extra)
+    {
+      linep->max_len = linep->len + extra + 80; /* XXX */
+      linep->buf = grub_realloc (linep->buf, linep->max_len + 1);
+      if (! linep->buf)
+       return 0;
+    }
+
+  return 1;
+}
+
+/* Return the number of lines occupied by this line on the screen.  */
+static int
+get_logical_num_lines (struct line *linep)
+{
+  return (linep->len / GRUB_TERM_ENTRY_WIDTH) + 1;
+}
+
+/* Print a line.  */
+static void
+print_line (struct line *linep, int offset, int start, int y)
+{
+  int i;
+  char *p;
+  
+  grub_gotoxy (GRUB_TERM_LEFT_BORDER_X + GRUB_TERM_MARGIN + start + 1,
+              y + GRUB_TERM_FIRST_ENTRY_Y);
+
+  for (p = linep->buf + offset + start, i = start;
+       i < GRUB_TERM_ENTRY_WIDTH && offset + i < linep->len;
+       p++, i++)
+    grub_putchar (*p);
+
+  for (; i < GRUB_TERM_ENTRY_WIDTH; i++)
+    grub_putchar (' ');
+
+  if (linep->len >= offset + GRUB_TERM_ENTRY_WIDTH)
+    grub_putchar ('\\');
+  else
+    grub_putchar (' ');
+}
+
+/* Print an empty line.  */
+static void
+print_empty_line (int y)
+{
+  int i;
+  
+  grub_gotoxy (GRUB_TERM_LEFT_BORDER_X + GRUB_TERM_MARGIN + 1,
+              y + GRUB_TERM_FIRST_ENTRY_Y);
+
+  for (i = 0; i < GRUB_TERM_ENTRY_WIDTH + 1; i++)
+    grub_putchar (' ');
+}
+
+/* Print an up arrow.  */
+static void
+print_up (int flag)
+{
+  grub_gotoxy (GRUB_TERM_LEFT_BORDER_X + GRUB_TERM_BORDER_WIDTH,
+              GRUB_TERM_FIRST_ENTRY_Y);
+  
+  if (flag)
+    grub_putcode (GRUB_TERM_DISP_UP);
+  else
+    grub_putchar (' ');
+}
+         
+/* Print a down arrow.  */
+static void
+print_down (int flag)
+{
+  grub_gotoxy (GRUB_TERM_LEFT_BORDER_X + GRUB_TERM_BORDER_WIDTH,
+              GRUB_TERM_TOP_BORDER_Y + GRUB_TERM_NUM_ENTRIES);
+  
+  if (flag)
+    grub_putcode (GRUB_TERM_DISP_DOWN);
+  else
+    grub_putchar (' ');
+}
+         
+/* Draw the lines of the screen SCREEN.  */
+static void
+update_screen (struct screen *screen, int region_start, int region_column,
+              int up, int down, enum update_mode mode)
+{
+  int up_flag = 0;
+  int down_flag = 0;
+  int y;
+  int i;
+  struct line *linep;
+  
+  /* Check if scrolling is necessary.  */
+  if (screen->y < 0 || screen->y >= GRUB_TERM_NUM_ENTRIES)
+    {
+      if (screen->y < 0)
+       screen->y = 0;
+      else
+       screen->y = GRUB_TERM_NUM_ENTRIES - 1;
+      
+      region_start = 0;
+      region_column = 0;
+      up = 1;
+      down = 1;
+      mode = ALL_LINES;
+    }
+
+  if (mode != NO_LINE)
+    {
+      /* Draw lines. This code is tricky, because this must calculate logical
+        positions.  */
+      y = screen->y - screen->column / GRUB_TERM_ENTRY_WIDTH;
+      i = screen->line;
+      linep = screen->lines + i;
+      while (y > 0)
+       {
+          i--;
+          linep--;
+          y -= get_logical_num_lines (linep);
+       }
+      
+      if (y < 0 || i > 0)
+       up_flag = 1;
+      
+      do
+       {
+         int column;
+         
+         for (column = 0;
+              column <= linep->len && y < GRUB_TERM_NUM_ENTRIES;
+              column += GRUB_TERM_ENTRY_WIDTH, y++)
+           {
+             if (y < 0)
+               continue;
+             
+             if (i == region_start)
+               {
+                 if (region_column >= column
+                     && region_column < column + GRUB_TERM_ENTRY_WIDTH)
+                   print_line (linep, column, region_column - column, y);
+                 else if (region_column < column)
+                   print_line (linep, column, 0, y);
+               }
+             else if (i > region_start && mode == ALL_LINES)
+               print_line (linep, column, 0, y);
+           }
+         
+         if (y == GRUB_TERM_NUM_ENTRIES)
+           {
+             if (column <= linep->len || i + 1 < screen->num_lines)
+               down_flag = 1;
+           }
+         
+         linep++;
+         i++;
+
+         if (mode == ALL_LINES && i == screen->num_lines)
+           for (; y < GRUB_TERM_NUM_ENTRIES; y++)
+             print_empty_line (y);
+                 
+       }
+      while (y < GRUB_TERM_NUM_ENTRIES);
+      
+      /* Draw up and down arrows.  */
+      if (up)
+       print_up (up_flag);
+      if (down)
+       print_down (down_flag);
+    }
+  
+  /* Place the cursor.  */
+  grub_gotoxy (GRUB_TERM_LEFT_BORDER_X + GRUB_TERM_MARGIN + 1 + screen->x,
+              GRUB_TERM_FIRST_ENTRY_Y + screen->y);
+  
+  grub_refresh ();
+}
+
+/* Insert the string S into the screen SCREEN. This updates the cursor
+   position and redraw the screen. Return zero if fails.  */
+static int
+insert_string (struct screen *screen, char *s, int update)
+{
+  int region_start = screen->num_lines;
+  int region_column = 0;
+  int down = 0;
+  enum update_mode mode = NO_LINE;
+
+  while (*s)
+    {
+      if (*s == '\n')
+       {
+         /* LF is special because it creates a new line.  */
+         struct line *current_linep;
+         struct line *next_linep;
+         int size;
+         
+         /* Make a new line.  */
+         screen->num_lines++;
+         screen->lines = grub_realloc (screen->lines,
+                                       screen->num_lines
+                                       * sizeof (struct line));
+         if (! screen->lines)
+           return 0;
+
+         /* Scroll down. */
+         grub_memmove (screen->lines + screen->line + 2,
+                       screen->lines + screen->line + 1,
+                       ((screen->num_lines - screen->line - 2)
+                        * sizeof (struct line)));
+
+         if (! init_line (screen->lines + screen->line + 1))
+           return 0;
+         
+         /* Fold the line.  */
+         current_linep = screen->lines + screen->line;
+         next_linep = current_linep + 1;
+         size = current_linep->len - screen->column;
+             
+         if (! ensure_space (next_linep, size))
+           return 0;
+         
+         grub_memmove (next_linep->buf,
+                       current_linep->buf + screen->column,
+                       size);
+         current_linep->len = screen->column;
+         next_linep->len = size;
+
+         /* Update a dirty region.  */
+         if (region_start > screen->line)
+           {
+             region_start = screen->line;
+             region_column = screen->column;
+           }
+
+         mode = ALL_LINES;
+         down = 1; /* XXX not optimal.  */
+         
+         /* Move the cursor.  */
+         screen->column = screen->real_column = 0;
+         screen->line++;
+         screen->x = 0;
+         screen->y++;
+
+         s++;
+       }
+      else
+       {
+         /* All but LF.  */
+         char *p;
+         struct line *current_linep;
+         int size;
+         int orig_num, new_num;
+
+         /* Find a string delimitted by LF.  */
+         p = grub_strchr (s, '\n');
+         if (! p)
+           p = s + grub_strlen (s);
+
+         /* Insert the string.  */
+         current_linep = screen->lines + screen->line;
+         size = p - s;
+         if (! ensure_space (current_linep, size))
+           return 0;
+
+         grub_memmove (current_linep->buf + screen->column + size,
+                       current_linep->buf + screen->column,
+                       current_linep->len - screen->column);
+         grub_memmove (current_linep->buf + screen->column,
+                       s,
+                       size);
+         orig_num = get_logical_num_lines (current_linep);
+         current_linep->len += size;
+         new_num = get_logical_num_lines (current_linep);
+
+         /* Update the dirty region.  */
+         if (region_start > screen->line)
+           {
+             region_start = screen->line;
+             region_column = screen->column;
+           }
+         
+         if (orig_num != new_num)
+           {
+             mode = ALL_LINES;
+             down = 1; /* XXX not optimal.  */
+           }
+         else if (mode != ALL_LINES)
+           mode = SINGLE_LINE;
+
+         /* Move the cursor.  */
+         screen->column += size;
+         screen->real_column = screen->column;
+         screen->x += size;
+         screen->y += screen->x / GRUB_TERM_ENTRY_WIDTH;
+         screen->x %= GRUB_TERM_ENTRY_WIDTH;
+         
+         s = p;
+       }
+    }
+
+  if (update)
+    update_screen (screen, region_start, region_column, 0, down, mode);
+  
+  return 1;
+}
+
+/* Release the resource allocated for SCREEN.  */
+static void
+destroy_screen (struct screen *screen)
+{
+  int i;
+
+  if (screen->lines)
+    for (i = 0; i < screen->num_lines; i++)
+      {
+       struct line *linep = screen->lines + i;
+       
+       if (linep)
+         grub_free (linep->buf);
+      }
+
+  grub_free (screen->killed_text);
+  grub_free (screen->lines);
+  grub_free (screen);
+}
+
+/* Make a new screen.  */
+static struct screen *
+make_screen (grub_menu_entry_t entry)
+{
+  struct screen *screen;
+  grub_command_list_t cl;
+
+  /* Initialize the screen.  */
+  screen = grub_malloc (sizeof (*screen));
+  if (! screen)
+    return 0;
+
+  screen->num_lines = 1;
+  screen->column = 0;
+  screen->real_column = 0;
+  screen->line = 0;
+  screen->x = 0;
+  screen->y = 0;
+  screen->killed_text = 0;
+  screen->lines = grub_malloc (sizeof (struct line));
+  if (! screen->lines)
+    goto fail;
+
+  /* Initialize the first line which must be always present.  */
+  if (! init_line (screen->lines))
+    goto fail;
+  
+  /* Input the entry.  */
+  for (cl = entry->command_list; cl; cl = cl->next)
+    {
+      if (! insert_string (screen, cl->command, 0))
+       goto fail;
+      
+      if (! insert_string (screen, "\n", 0))
+       goto fail;
+    }
+
+  /* Reset the cursor position.  */
+  screen->column = 0;
+  screen->real_column = 0;
+  screen->line = 0;
+  screen->x = 0;
+  screen->y = 0;
+
+  return screen;
+
+ fail:
+  destroy_screen (screen);
+  return 0;
+}
+
+static int
+forward_char (struct screen *screen, int update)
+{
+  struct line *linep;
+  
+  linep = screen->lines + screen->line;
+  if (screen->column < linep->len)
+    {
+      screen->column++;
+      screen->x++;
+      if (screen->x == GRUB_TERM_ENTRY_WIDTH)
+       {
+         screen->x = 0;
+         screen->y++;
+       }
+    }
+  else if (screen->num_lines > screen->line + 1)
+    {
+      screen->column = 0;
+      screen->line++;
+      screen->x = 0;
+      screen->y++;
+    }
+
+  screen->real_column = screen->column;
+
+  if (update)
+    update_screen (screen, screen->num_lines, 0, 0, 0, NO_LINE);
+  return 1;
+}
+
+static int
+backward_char (struct screen *screen, int update)
+{
+  if (screen->column > 0)
+    {
+      screen->column--;
+      screen->x--;
+      if (screen->x == -1)
+       {
+         screen->x = GRUB_TERM_ENTRY_WIDTH - 1;
+         screen->y--;
+       }
+    }
+  else if (screen->line > 0)
+    {
+      struct line *linep;
+      
+      screen->line--;
+      linep = screen->lines + screen->line;
+      screen->column = linep->len;
+      screen->x = screen->column % GRUB_TERM_ENTRY_WIDTH;
+      screen->y--;
+    }
+
+  screen->real_column = screen->column;
+
+  if (update)
+    update_screen (screen, screen->num_lines, 0, 0, 0, NO_LINE);
+  
+  return 1;
+}
+
+static int
+previous_line (struct screen *screen, int update)
+{
+  if (screen->line > 0)
+    {
+      struct line *linep;
+      int dy;
+      
+      /* How many physical lines from the current position
+        to the first physical line?  */
+      dy = screen->column / GRUB_TERM_ENTRY_WIDTH;
+      
+      screen->line--;
+      
+      linep = screen->lines + screen->line;
+      if (linep->len < screen->real_column)
+       screen->column = linep->len;
+      else
+       screen->column = screen->real_column;
+      
+      /* How many physical lines from the current position
+        to the last physical line?  */
+      dy += (linep->len / GRUB_TERM_ENTRY_WIDTH
+            - screen->column / GRUB_TERM_ENTRY_WIDTH);
+      
+      screen->y -= dy + 1;
+      screen->x = screen->column % GRUB_TERM_ENTRY_WIDTH;
+    }
+  else
+    {
+      screen->y -= screen->column / GRUB_TERM_ENTRY_WIDTH;
+      screen->column = 0;
+      screen->x = 0;
+    }
+
+  if (update)
+    update_screen (screen, screen->num_lines, 0, 0, 0, NO_LINE);
+  
+  return 1;
+}
+
+static int
+next_line (struct screen *screen, int update)
+{
+  if (screen->line < screen->num_lines - 1)
+    {
+      struct line *linep;
+      int dy;
+      
+      /* How many physical lines from the current position
+        to the last physical line?  */
+      linep = screen->lines + screen->line;
+      dy = (linep->len / GRUB_TERM_ENTRY_WIDTH
+           - screen->column / GRUB_TERM_ENTRY_WIDTH);
+      
+      screen->line++;
+      
+      linep++;
+      if (linep->len < screen->real_column)
+       screen->column = linep->len;
+      else
+       screen->column = screen->real_column;
+      
+      /* How many physical lines from the current position
+        to the first physical line?  */
+      dy += screen->column / GRUB_TERM_ENTRY_WIDTH;
+      
+      screen->y += dy + 1;
+      screen->x = screen->column % GRUB_TERM_ENTRY_WIDTH;
+    }
+  else
+    {
+      struct line *linep;
+
+      linep = screen->lines + screen->line;
+      screen->y += (linep->len / GRUB_TERM_ENTRY_WIDTH
+                   - screen->column / GRUB_TERM_ENTRY_WIDTH);
+      screen->column = linep->len;
+      screen->x = screen->column % GRUB_TERM_ENTRY_WIDTH;
+    }
+
+  if (update)
+    update_screen (screen, screen->num_lines, 0, 0, 0, NO_LINE);
+  
+  return 1;
+}
+
+static int
+beginning_of_line (struct screen *screen, int update)
+{
+  screen->y -= screen->column / GRUB_TERM_ENTRY_WIDTH;
+  screen->column = screen->real_column = 0;
+  screen->x = 0;
+
+  if (update)
+    update_screen (screen, screen->num_lines, 0, 0, 0, NO_LINE);
+  
+  return 1;
+}
+
+static int
+end_of_line (struct screen *screen, int update)
+{
+  struct line *linep;
+  
+  linep = screen->lines + screen->line;
+  screen->y += (linep->len / GRUB_TERM_ENTRY_WIDTH
+               - screen->column / GRUB_TERM_ENTRY_WIDTH);
+  screen->column = screen->real_column = linep->len;
+  screen->x = screen->column % GRUB_TERM_ENTRY_WIDTH;
+
+  if (update)
+    update_screen (screen, screen->num_lines, 0, 0, 0, NO_LINE);
+  
+  return 1;
+}
+
+static int
+delete_char (struct screen *screen, int update)
+{
+  struct line *linep;
+  enum update_mode mode = NO_LINE;
+  int start = screen->num_lines;
+  int column = 0;
+  int down = 0;
+  
+  linep = screen->lines + screen->line;
+  if (linep->len > screen->column)
+    {
+      int orig_num, new_num;
+
+      orig_num = get_logical_num_lines (linep);
+      
+      grub_memmove (linep->buf + screen->column,
+                   linep->buf + screen->column + 1,
+                   linep->len - screen->column - 1);
+      linep->len--;
+
+      new_num = get_logical_num_lines (linep);
+
+      if (orig_num != new_num)
+       mode = ALL_LINES;
+      else
+       mode = SINGLE_LINE;
+
+      start = screen->line;
+      column = screen->column;
+    }
+  else if (screen->num_lines > screen->line + 1)
+    {
+      struct line *next_linep;
+
+      next_linep = linep + 1;
+      if (! ensure_space (linep, next_linep->len))
+       return 0;
+
+      grub_memmove (linep->buf + linep->len, next_linep->buf, next_linep->len);
+      linep->len += next_linep->len;
+
+      grub_free (next_linep->buf);
+      grub_memmove (next_linep,
+                   next_linep + 1,
+                   (screen->num_lines - screen->line - 2)
+                   * sizeof (struct line));
+      screen->num_lines--;
+      
+      mode = ALL_LINES;
+      start = screen->line;
+      column = screen->column;
+      down = 1;
+    }
+
+  screen->real_column = screen->column;
+
+  if (update)
+    update_screen (screen, start, column, 0, down, mode);
+
+  return 1;
+}
+
+static int
+backward_delete_char (struct screen *screen, int update)
+{
+  int saved_column;
+  int saved_line;
+
+  saved_column = screen->column;
+  saved_line = screen->line;
+  
+  if (! backward_char (screen, 0))
+    return 0;
+
+  if (saved_column != screen->column || saved_line != screen->line)
+    if (! delete_char (screen, update))
+      return 0;
+
+  return 1;
+}
+
+static int
+kill_line (struct screen *screen, int continuous, int update)
+{
+  struct line *linep;
+  char *p;
+  int size;
+  int offset;
+  
+  p = screen->killed_text;
+  if (! continuous && p)
+    p[0] = '\0';
+  
+  linep = screen->lines + screen->line;
+  size = linep->len - screen->column;
+  
+  if (p)
+    offset = grub_strlen (p);
+  else
+    offset = 0;
+      
+  if (size > 0)
+    {
+      enum update_mode mode = SINGLE_LINE;
+      int down = 0;
+      int orig_num, new_num;
+      
+      p = grub_realloc (p, offset + size + 1);
+      if (! p)
+       return 0;
+
+      grub_memmove (p + offset, linep->buf + screen->column, size);
+      p[offset + size - 1] = '\0';
+
+      screen->killed_text = p;
+      
+      orig_num = get_logical_num_lines (linep);
+      linep->len = screen->column;
+      new_num = get_logical_num_lines (linep);
+
+      if (orig_num != new_num)
+       {
+         mode = ALL_LINES;
+         down = 1;
+       }
+
+      if (update)
+       update_screen (screen, screen->line, screen->column, 0, down, mode);
+    }
+  else if (screen->line + 1 < screen->num_lines)
+    {
+      p = grub_realloc (p, offset + 1 + 1);
+      if (! p)
+       return 0;
+
+      p[offset] = '\n';
+      p[offset + 1] = '\0';
+
+      screen->killed_text = p;
+      
+      return delete_char (screen, update);
+    }
+    
+  return 1;
+}
+
+static int
+yank (struct screen *screen, int update)
+{
+  if (screen->killed_text)
+    return insert_string (screen, screen->killed_text, update);
+
+  return 1;
+}
+
+static int
+open_line (struct screen *screen, int update)
+{
+  int saved_y = screen->y;
+  
+  if (! insert_string (screen, "\n", 0))
+    return 0;
+
+  if (! backward_char (screen, 0))
+    return 0;
+
+  screen->y = saved_y;
+
+  if (update)
+    update_screen (screen, screen->line, screen->column, 0, 1, ALL_LINES);
+
+  return 1;
+}
+
+/* Execute the command list in the screen SCREEN.  */
+static int
+run (struct screen *screen)
+{
+  int i;
+  
+  grub_cls ();
+  grub_printf ("  Booting a command list\n\n");
+  
+  for (i = 0; i < screen->num_lines; i++)
+    {
+      struct line *linep = screen->lines + i;
+      char *p;
+      grub_command_t c;
+      
+      /* Trim down space characters.  */
+      for (p = linep->buf + linep->len - 1;
+          p >= linep->buf && grub_isspace (*p);
+          p--)
+       ;
+      *++p = '\0';
+      linep->len = p - linep->buf;
+      
+      for (p = linep->buf; grub_isspace (*p); p++)
+       ;
+      
+      if (*p == '\0')
+       /* Ignore an empty command line.  */
+       continue;
+
+      c = grub_command_find (p);
+      if (! c)
+       break;
+      
+      if (! (c->flags & GRUB_COMMAND_FLAG_CMDLINE))
+       {
+         grub_error (GRUB_ERR_INVALID_COMMAND, "invalid command `%s'", p);
+         break;
+       }
+      
+      if (! (c->flags & GRUB_COMMAND_FLAG_NO_ECHO))
+       grub_printf ("%s\n", p);
+      
+      if (grub_command_execute (p) != 0)
+       break;
+    }
+  
+  if (grub_errno == GRUB_ERR_NONE && grub_loader_is_loaded ())
+    /* Implicit execution of boot, only if something is loaded.  */
+    grub_command_execute ("boot");
+
+  if (grub_errno != GRUB_ERR_NONE)
+    {
+      grub_print_error ();
+      grub_errno = GRUB_ERR_NONE;
+      /* Wait until the user pushes any key so that the user
+        can see what happened.  */
+      grub_printf ("\nPress any key to continue...");
+      (void) grub_getkey ();
+    }
+  
+  return 1;
+}
+
+/* Edit a menu entry with an Emacs-like interface.  */
+void
+grub_menu_entry_run (grub_menu_entry_t entry)
+{
+  struct screen *screen;
+  int prev_c;
+  
+  screen = make_screen (entry);
+  if (! screen)
+    return;
+
+ refresh:
+  /* Draw the screen.  */
+  grub_menu_init_page (0, 1);
+  update_screen (screen, 0, 0, 1, 1, ALL_LINES);
+  grub_setcursor (1);
+  prev_c = '\0';
+  
+  while (1)
+    {
+      int c = GRUB_TERM_ASCII_CHAR (grub_getkey ());
+      
+      switch (c)
+       {
+       case 16: /* C-p */
+         if (! previous_line (screen, 1))
+           goto fail;
+         break;
+
+       case 14: /* C-n */
+         if (! next_line (screen, 1))
+           goto fail;
+         break;
+
+       case 6: /* C-f */
+         if (! forward_char (screen, 1))
+           goto fail;
+         break;
+         
+       case 2: /* C-b */
+         if (! backward_char (screen, 1))
+           goto fail;
+         break;
+
+       case 1: /* C-a */
+         if (! beginning_of_line (screen, 1))
+           goto fail;
+         break;
+
+       case 5: /* C-e */
+         if (! end_of_line (screen, 1))
+           goto fail;
+         break;
+         
+       case '\t': /* C-i */
+         /* FIXME: Completion */
+         break;
+         
+       case 4: /* C-d */
+         if (! delete_char (screen, 1))
+           goto fail;
+         break;
+
+       case 8: /* C-h */
+         if (! backward_delete_char (screen, 1))
+           goto fail;
+         break;
+         
+       case 11: /* C-k */
+         if (! kill_line (screen, prev_c == c, 1))
+           goto fail;
+         break;
+         
+       case 21: /* C-u */
+         /* FIXME: What behavior is good for this key?  */
+         break;
+         
+       case 25: /* C-y */
+         if (! yank (screen, 1))
+           goto fail;
+         break;
+
+       case 12: /* C-l */
+         /* FIXME: centering.  */
+         goto refresh;
+         
+       case 15: /* C-o */
+         if (! open_line (screen, 1))
+           goto fail;
+         break;
+
+       case '\n':
+       case '\r':
+         if (! insert_string (screen, "\n", 1))
+           goto fail;
+         break;
+
+       case '\e':
+         destroy_screen (screen);
+         return;
+         
+       case 3: /* C-c */
+         grub_cmdline_run (1);
+         goto refresh;
+         
+       case 24: /* C-x */
+         if (! run (screen))
+           goto fail;
+         goto refresh;
+
+       case 18: /* C-r */
+       case 19: /* C-s */
+       case 20: /* C-t */
+         /* FIXME */
+         break;
+         
+       default:
+         if (grub_isprint (c))
+           {
+             char buf[2];
+
+             buf[0] = c;
+             buf[1] = '\0';
+             if (! insert_string (screen, buf, 1))
+               goto fail;
+           }
+         break;
+       }
+
+      prev_c = c;
+    }
+
+ fail:
+  destroy_screen (screen);
+  
+  grub_cls ();
+  grub_print_error ();
+  grub_errno = GRUB_ERR_NONE;
+  grub_printf ("\nPress any key to continue...");
+  (void) grub_getkey ();
+}
index 5740590808a0d240dce33e29b9896718b14bfccf..3f00b73356a4ee478a4f993d73607c18d66236d6 100644 (file)
@@ -28,6 +28,44 @@ static int grub_console_attr = A_NORMAL;
 static void
 grub_ncurses_putchar (grub_uint32_t c)
 {
+  /* Better than nothing.  */
+  switch (c)
+    {
+    case GRUB_TERM_DISP_LEFT:
+      c = '<';
+      break;
+
+    case GRUB_TERM_DISP_UP:
+      c = '^';
+      break;
+
+    case GRUB_TERM_DISP_RIGHT:
+      c = '>';
+      break;
+
+    case GRUB_TERM_DISP_DOWN:
+      c = 'v';
+      break;
+
+    case GRUB_TERM_DISP_HLINE:
+      c = '-';
+      break;
+
+    case GRUB_TERM_DISP_VLINE:
+      c = '|';
+      break;
+
+    case GRUB_TERM_DISP_UL:
+    case GRUB_TERM_DISP_UR:
+    case GRUB_TERM_DISP_LL:
+    case GRUB_TERM_DISP_LR:
+      c = '+';
+      break;
+
+    default:
+      break;
+    }
+  
   addch (c | grub_console_attr);
 }
 
@@ -57,16 +95,46 @@ grub_ncurses_setcolor (grub_uint8_t normal_color, grub_uint8_t highlight_color)
   color_set (normal_color << 8 | highlight_color, 0);
 }
 
+static int saved_char = ERR;
+
 static int
 grub_ncurses_checkkey (void)
 {
-  return 1;
+  int c;
+  
+  /* Check for SAVED_CHAR. This should not be true, because this
+     means checkkey is called twice continuously.  */
+  if (saved_char != ERR)
+    return 1;
+  
+  wtimeout (stdscr, 100);
+  c = getch ();
+  /* If C is not ERR, then put it back in the input queue.  */
+  if (c != ERR)
+    {
+      saved_char = c;
+      return 1;
+    }
+
+  return 0;
 }
 
 static int
 grub_ncurses_getkey (void)
 {
-  int c = getch ();
+  int c;
+  
+  /* If checkkey has already got a character, then return it.  */
+  if (saved_char != ERR)
+    {
+      c = saved_char;
+      saved_char = ERR;
+    }
+  else
+    {
+      wtimeout (stdscr, -1);
+      c = getch ();
+    }
 
   switch (c)
     {
@@ -161,7 +229,7 @@ static grub_err_t
 grub_ncurses_init (void)
 {
   initscr ();
-  cbreak (); 
+  raw ();
   noecho ();
   scrollok (stdscr, TRUE);