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.
+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.
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
-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 $@ $<
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
$(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 $@ $^
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 $@ $<
-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 $@ $<
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 \
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)
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
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)
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);
/*
* 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
/* 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. */
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
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\
#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)
{
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
{
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.");
? 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);
}
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)
{
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. */
refresh:
grub_setcursor (0);
- init_page (nested, 0);
+ grub_menu_init_page (nested, 0);
print_entries (menu, first, offset);
grub_refresh ();
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 ();
}
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)
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)
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
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:
--- /dev/null
+/*
+ * 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 ();
+}
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);
}
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)
{
grub_ncurses_init (void)
{
initscr ();
- cbreak ();
+ raw ();
noecho ();
scrollok (stdscr, TRUE);