Commit b4a9071a authored by Linus Torvalds's avatar Linus Torvalds

Merge git://git.kernel.org/pub/scm/linux/kernel/git/sam/kbuild

* git://git.kernel.org/pub/scm/linux/kernel/git/sam/kbuild:
  kbuild: trivial documentation fixes
  kconfig: fix saving alternate kconfig file in parent dir
  kbuild: make modpost processing configurable
  kconfig/menuconfig: do not let ncurses clutter screen on exit
  kconfig/lxdialog: clear long menu lines
  kbuild: do not build mconf & lxdialog unless needed
  kconfig/lxdialog: fix make mrproper
  kconfig/lxdialog: support resize
  kconfig/lxdialog: let <ESC><ESC> behave as expected
  kconfig/menuconfig: lxdialog is now built-in
  kconfig/lxdialog: add a new theme bluetitle which is now default
  kconfig/lxdialog: add support for color themes and add blackbg theme
  kconfig/lxdialog: refactor color support
parents 8b2a1fd1 99c8b947
...@@ -43,7 +43,7 @@ are not planned to be included in the kernel tree. ...@@ -43,7 +43,7 @@ are not planned to be included in the kernel tree.
What is covered within this file is mainly information to authors What is covered within this file is mainly information to authors
of modules. The author of an external module should supply of modules. The author of an external module should supply
a makefile that hides most of the complexity, so one only has to type a makefile that hides most of the complexity, so one only has to type
'make' to build the module. A complete example will be present in 'make' to build the module. A complete example will be presented in
chapter 4, "Creating a kbuild file for an external module". chapter 4, "Creating a kbuild file for an external module".
...@@ -61,6 +61,7 @@ when building an external module. ...@@ -61,6 +61,7 @@ when building an external module.
make -C <path-to-kernel> M=`pwd` make -C <path-to-kernel> M=`pwd`
For the running kernel use: For the running kernel use:
make -C /lib/modules/`uname -r`/build M=`pwd` make -C /lib/modules/`uname -r`/build M=`pwd`
For the above command to succeed, the kernel must have been For the above command to succeed, the kernel must have been
...@@ -130,10 +131,10 @@ when building an external module. ...@@ -130,10 +131,10 @@ when building an external module.
To make sure the kernel contains the information required to To make sure the kernel contains the information required to
build external modules the target 'modules_prepare' must be used. build external modules the target 'modules_prepare' must be used.
'module_prepare' exists solely as a simple way to prepare 'modules_prepare' exists solely as a simple way to prepare
a kernel source tree for building external modules. a kernel source tree for building external modules.
Note: modules_prepare will not build Module.symvers even if Note: modules_prepare will not build Module.symvers even if
CONFIG_MODULEVERSIONING is set. Therefore a full kernel build CONFIG_MODVERSIONS is set. Therefore a full kernel build
needs to be executed to make module versioning work. needs to be executed to make module versioning work.
--- 2.5 Building separate files for a module --- 2.5 Building separate files for a module
...@@ -450,7 +451,7 @@ kernel refuses to load the module. ...@@ -450,7 +451,7 @@ kernel refuses to load the module.
Module.symvers contains a list of all exported symbols from a kernel build. Module.symvers contains a list of all exported symbols from a kernel build.
--- 7.1 Symbols fron the kernel (vmlinux + modules) --- 7.1 Symbols from the kernel (vmlinux + modules)
During a kernel build, a file named Module.symvers will be generated. During a kernel build, a file named Module.symvers will be generated.
Module.symvers contains all exported symbols from the kernel and Module.symvers contains all exported symbols from the kernel and
......
...@@ -32,6 +32,10 @@ ...@@ -32,6 +32,10 @@
# Step 4 is solely used to allow module versioning in external modules, # Step 4 is solely used to allow module versioning in external modules,
# where the CRC of each module is retrieved from the Module.symers file. # where the CRC of each module is retrieved from the Module.symers file.
# KBUILD_MODPOST_WARN can be set to avoid error out in case of undefined
# symbols in the final module linking stage
# KBUILD_MODPOST_NOFINAL can be set to skip the final link of modules.
# This is solely usefull to speed up test compiles
PHONY := _modpost PHONY := _modpost
_modpost: __modpost _modpost: __modpost
...@@ -46,7 +50,8 @@ modulesymfile := $(KBUILD_EXTMOD)/Module.symvers ...@@ -46,7 +50,8 @@ modulesymfile := $(KBUILD_EXTMOD)/Module.symvers
__modules := $(sort $(shell grep -h '\.ko' /dev/null $(wildcard $(MODVERDIR)/*.mod))) __modules := $(sort $(shell grep -h '\.ko' /dev/null $(wildcard $(MODVERDIR)/*.mod)))
modules := $(patsubst %.o,%.ko, $(wildcard $(__modules:.ko=.o))) modules := $(patsubst %.o,%.ko, $(wildcard $(__modules:.ko=.o)))
_modpost: $(modules) # Stop after building .o files if NOFINAL is set. Makes compile tests quicker
_modpost: $(if $(KBUILD_MODPOST_NOFINAL), $(modules:.ko:.o),$(modules))
# Step 2), invoke modpost # Step 2), invoke modpost
...@@ -58,7 +63,7 @@ quiet_cmd_modpost = MODPOST $(words $(filter-out vmlinux FORCE, $^)) modules ...@@ -58,7 +63,7 @@ quiet_cmd_modpost = MODPOST $(words $(filter-out vmlinux FORCE, $^)) modules
$(if $(KBUILD_EXTMOD),-i,-o) $(kernelsymfile) \ $(if $(KBUILD_EXTMOD),-i,-o) $(kernelsymfile) \
$(if $(KBUILD_EXTMOD),-I $(modulesymfile)) \ $(if $(KBUILD_EXTMOD),-I $(modulesymfile)) \
$(if $(KBUILD_EXTMOD),-o $(modulesymfile)) \ $(if $(KBUILD_EXTMOD),-o $(modulesymfile)) \
$(if $(KBUILD_EXTMOD),-w) \ $(if $(KBUILD_EXTMOD)$(KBUILD_MODPOST_WARN),-w) \
$(wildcard vmlinux) $(filter-out FORCE,$^) $(wildcard vmlinux) $(filter-out FORCE,$^)
PHONY += __modpost PHONY += __modpost
...@@ -92,7 +97,7 @@ targets += $(modules:.ko=.mod.o) ...@@ -92,7 +97,7 @@ targets += $(modules:.ko=.mod.o)
# Step 6), final link of the modules # Step 6), final link of the modules
quiet_cmd_ld_ko_o = LD [M] $@ quiet_cmd_ld_ko_o = LD [M] $@
cmd_ld_ko_o = $(LD) $(LDFLAGS) $(LDFLAGS_MODULE) -o $@ \ cmd_ld_ko_o = $(LD) $(LDFLAGS) $(LDFLAGS_MODULE) -o $@ \
$(filter-out FORCE,$^) $(filter-out FORCE,$^)
$(modules): %.ko :%.o %.mod.o FORCE $(modules): %.ko :%.o %.mod.o FORCE
......
...@@ -11,7 +11,6 @@ gconfig: $(obj)/gconf ...@@ -11,7 +11,6 @@ gconfig: $(obj)/gconf
$< arch/$(ARCH)/Kconfig $< arch/$(ARCH)/Kconfig
menuconfig: $(obj)/mconf menuconfig: $(obj)/mconf
$(Q)$(MAKE) $(build)=scripts/kconfig/lxdialog
$< arch/$(ARCH)/Kconfig $< arch/$(ARCH)/Kconfig
config: $(obj)/conf config: $(obj)/conf
...@@ -81,6 +80,23 @@ help: ...@@ -81,6 +80,23 @@ help:
@echo ' allyesconfig - New config where all options are accepted with yes' @echo ' allyesconfig - New config where all options are accepted with yes'
@echo ' allnoconfig - New config where all options are answered with no' @echo ' allnoconfig - New config where all options are answered with no'
# lxdialog stuff
check-lxdialog := $(srctree)/$(src)/lxdialog/check-lxdialog.sh
# Use reursively expanded variables so we do not call gcc unless
# we really need to do so. (Do not call gcc as part of make mrproper)
HOST_EXTRACFLAGS = $(shell $(CONFIG_SHELL) $(check-lxdialog) -ccflags)
HOST_LOADLIBES = $(shell $(CONFIG_SHELL) $(check-lxdialog) -ldflags $(HOSTCC))
HOST_EXTRACFLAGS += -DLOCALE
PHONY += $(obj)/dochecklxdialog
$(obj)/dochecklxdialog:
$(Q)$(CONFIG_SHELL) $(check-lxdialog) -check $(HOSTCC) $(HOST_LOADLIBES)
always := dochecklxdialog
# =========================================================================== # ===========================================================================
# Shared Makefile for the various kconfig executables: # Shared Makefile for the various kconfig executables:
# conf: Used for defconfig, oldconfig and related targets # conf: Used for defconfig, oldconfig and related targets
...@@ -92,11 +108,19 @@ help: ...@@ -92,11 +108,19 @@ help:
# Based on GTK which needs to be installed to compile it # Based on GTK which needs to be installed to compile it
# object files used by all kconfig flavours # object files used by all kconfig flavours
hostprogs-y := conf mconf qconf gconf kxgettext lxdialog := lxdialog/checklist.o lxdialog/util.o lxdialog/inputbox.o
lxdialog += lxdialog/textbox.o lxdialog/yesno.o lxdialog/menubox.o
conf-objs := conf.o zconf.tab.o conf-objs := conf.o zconf.tab.o
mconf-objs := mconf.o zconf.tab.o mconf-objs := mconf.o zconf.tab.o $(lxdialog)
kxgettext-objs := kxgettext.o zconf.tab.o kxgettext-objs := kxgettext.o zconf.tab.o
hostprogs-y := conf qconf gconf kxgettext
ifeq ($(MAKECMDGOALS),menuconfig)
hostprogs-y += mconf
endif
ifeq ($(MAKECMDGOALS),xconfig) ifeq ($(MAKECMDGOALS),xconfig)
qconf-target := 1 qconf-target := 1
endif endif
...@@ -116,7 +140,6 @@ endif ...@@ -116,7 +140,6 @@ endif
clean-files := lkc_defs.h qconf.moc .tmp_qtcheck \ clean-files := lkc_defs.h qconf.moc .tmp_qtcheck \
.tmp_gtkcheck zconf.tab.c lex.zconf.c zconf.hash.c .tmp_gtkcheck zconf.tab.c lex.zconf.c zconf.hash.c
subdir- += lxdialog
# Needed for systems without gettext # Needed for systems without gettext
KBUILD_HAVE_NLS := $(shell \ KBUILD_HAVE_NLS := $(shell \
......
...@@ -517,7 +517,7 @@ int conf_write(const char *name) ...@@ -517,7 +517,7 @@ int conf_write(const char *name)
fclose(out); fclose(out);
if (*tmpname) { if (*tmpname) {
strcat(dirname, name ? name : conf_get_configname()); strcat(dirname, basename);
strcat(dirname, ".old"); strcat(dirname, ".old");
rename(newname, dirname); rename(newname, dirname);
if (rename(tmpname, newname)) if (rename(tmpname, newname))
......
# Makefile to build lxdialog package
#
check-lxdialog := $(srctree)/$(src)/check-lxdialog.sh
# Use reursively expanded variables so we do not call gcc unless
# we really need to do so. (Do not call gcc as part of make mrproper)
HOST_EXTRACFLAGS = $(shell $(CONFIG_SHELL) $(check-lxdialog) -ccflags)
HOST_LOADLIBES = $(shell $(CONFIG_SHELL) $(check-lxdialog) -ldflags $(HOSTCC))
HOST_EXTRACFLAGS += -DLOCALE
PHONY += dochecklxdialog
$(obj)/dochecklxdialog:
$(Q)$(CONFIG_SHELL) $(check-lxdialog) -check $(HOSTCC) $(HOST_LOADLIBES)
hostprogs-y := lxdialog
always := $(hostprogs-y) dochecklxdialog
lxdialog-objs := checklist.o menubox.o textbox.o yesno.o inputbox.o \
util.o lxdialog.o msgbox.o
...@@ -28,25 +28,25 @@ static int list_width, check_x, item_x; ...@@ -28,25 +28,25 @@ static int list_width, check_x, item_x;
/* /*
* Print list item * Print list item
*/ */
static void print_item(WINDOW * win, const char *item, int status, int choice, static void print_item(WINDOW * win, int choice, int selected)
int selected)
{ {
int i; int i;
/* Clear 'residue' of last item */ /* Clear 'residue' of last item */
wattrset(win, menubox_attr); wattrset(win, dlg.menubox.atr);
wmove(win, choice, 0); wmove(win, choice, 0);
for (i = 0; i < list_width; i++) for (i = 0; i < list_width; i++)
waddch(win, ' '); waddch(win, ' ');
wmove(win, choice, check_x); wmove(win, choice, check_x);
wattrset(win, selected ? check_selected_attr : check_attr); wattrset(win, selected ? dlg.check_selected.atr
wprintw(win, "(%c)", status ? 'X' : ' '); : dlg.check.atr);
wprintw(win, "(%c)", item_is_tag('X') ? 'X' : ' ');
wattrset(win, selected ? tag_selected_attr : tag_attr);
mvwaddch(win, choice, item_x, item[0]); wattrset(win, selected ? dlg.tag_selected.atr : dlg.tag.atr);
wattrset(win, selected ? item_selected_attr : item_attr); mvwaddch(win, choice, item_x, item_str()[0]);
waddstr(win, (char *)item + 1); wattrset(win, selected ? dlg.item_selected.atr : dlg.item.atr);
waddstr(win, (char *)item_str() + 1);
if (selected) { if (selected) {
wmove(win, choice, check_x + 1); wmove(win, choice, check_x + 1);
wrefresh(win); wrefresh(win);
...@@ -62,11 +62,11 @@ static void print_arrows(WINDOW * win, int choice, int item_no, int scroll, ...@@ -62,11 +62,11 @@ static void print_arrows(WINDOW * win, int choice, int item_no, int scroll,
wmove(win, y, x); wmove(win, y, x);
if (scroll > 0) { if (scroll > 0) {
wattrset(win, uarrow_attr); wattrset(win, dlg.uarrow.atr);
waddch(win, ACS_UARROW); waddch(win, ACS_UARROW);
waddstr(win, "(-)"); waddstr(win, "(-)");
} else { } else {
wattrset(win, menubox_attr); wattrset(win, dlg.menubox.atr);
waddch(win, ACS_HLINE); waddch(win, ACS_HLINE);
waddch(win, ACS_HLINE); waddch(win, ACS_HLINE);
waddch(win, ACS_HLINE); waddch(win, ACS_HLINE);
...@@ -77,11 +77,11 @@ static void print_arrows(WINDOW * win, int choice, int item_no, int scroll, ...@@ -77,11 +77,11 @@ static void print_arrows(WINDOW * win, int choice, int item_no, int scroll,
wmove(win, y, x); wmove(win, y, x);
if ((height < item_no) && (scroll + choice < item_no - 1)) { if ((height < item_no) && (scroll + choice < item_no - 1)) {
wattrset(win, darrow_attr); wattrset(win, dlg.darrow.atr);
waddch(win, ACS_DARROW); waddch(win, ACS_DARROW);
waddstr(win, "(+)"); waddstr(win, "(+)");
} else { } else {
wattrset(win, menubox_border_attr); wattrset(win, dlg.menubox_border.atr);
waddch(win, ACS_HLINE); waddch(win, ACS_HLINE);
waddch(win, ACS_HLINE); waddch(win, ACS_HLINE);
waddch(win, ACS_HLINE); waddch(win, ACS_HLINE);
...@@ -109,32 +109,29 @@ static void print_buttons(WINDOW * dialog, int height, int width, int selected) ...@@ -109,32 +109,29 @@ static void print_buttons(WINDOW * dialog, int height, int width, int selected)
* in the style of radiolist (only one option turned on at a time). * in the style of radiolist (only one option turned on at a time).
*/ */
int dialog_checklist(const char *title, const char *prompt, int height, int dialog_checklist(const char *title, const char *prompt, int height,
int width, int list_height, int item_no, int width, int list_height)
const char *const *items)
{ {
int i, x, y, box_x, box_y; int i, x, y, box_x, box_y;
int key = 0, button = 0, choice = 0, scroll = 0, max_choice, *status; int key = 0, button = 0, choice = 0, scroll = 0, max_choice;
WINDOW *dialog, *list; WINDOW *dialog, *list;
/* Allocate space for storing item on/off status */ /* which item to highlight */
if ((status = malloc(sizeof(int) * item_no)) == NULL) { item_foreach() {
endwin(); if (item_is_tag('X'))
fprintf(stderr, choice = item_n();
"\nCan't allocate memory in dialog_checklist().\n"); if (item_is_selected()) {
exit(-1); choice = item_n();
break;
}
} }
/* Initializes status */ do_resize:
for (i = 0; i < item_no; i++) { if (getmaxy(stdscr) < (height + 6))
status[i] = !strcasecmp(items[i * 3 + 2], "on"); return -ERRDISPLAYTOOSMALL;
if ((!choice && status[i]) if (getmaxx(stdscr) < (width + 6))
|| !strcasecmp(items[i * 3 + 2], "selected")) return -ERRDISPLAYTOOSMALL;
choice = i + 1;
}
if (choice)
choice--;
max_choice = MIN(list_height, item_no); max_choice = MIN(list_height, item_count());
/* center dialog box on screen */ /* center dialog box on screen */
x = (COLS - width) / 2; x = (COLS - width) / 2;
...@@ -145,17 +142,18 @@ int dialog_checklist(const char *title, const char *prompt, int height, ...@@ -145,17 +142,18 @@ int dialog_checklist(const char *title, const char *prompt, int height,
dialog = newwin(height, width, y, x); dialog = newwin(height, width, y, x);
keypad(dialog, TRUE); keypad(dialog, TRUE);
draw_box(dialog, 0, 0, height, width, dialog_attr, border_attr); draw_box(dialog, 0, 0, height, width,
wattrset(dialog, border_attr); dlg.dialog.atr, dlg.border.atr);
wattrset(dialog, dlg.border.atr);
mvwaddch(dialog, height - 3, 0, ACS_LTEE); mvwaddch(dialog, height - 3, 0, ACS_LTEE);
for (i = 0; i < width - 2; i++) for (i = 0; i < width - 2; i++)
waddch(dialog, ACS_HLINE); waddch(dialog, ACS_HLINE);
wattrset(dialog, dialog_attr); wattrset(dialog, dlg.dialog.atr);
waddch(dialog, ACS_RTEE); waddch(dialog, ACS_RTEE);
print_title(dialog, title, width); print_title(dialog, title, width);
wattrset(dialog, dialog_attr); wattrset(dialog, dlg.dialog.atr);
print_autowrap(dialog, prompt, width - 2, 1, 3); print_autowrap(dialog, prompt, width - 2, 1, 3);
list_width = width - 6; list_width = width - 6;
...@@ -170,12 +168,12 @@ int dialog_checklist(const char *title, const char *prompt, int height, ...@@ -170,12 +168,12 @@ int dialog_checklist(const char *title, const char *prompt, int height,
/* draw a box around the list items */ /* draw a box around the list items */
draw_box(dialog, box_y, box_x, list_height + 2, list_width + 2, draw_box(dialog, box_y, box_x, list_height + 2, list_width + 2,
menubox_border_attr, menubox_attr); dlg.menubox_border.atr, dlg.menubox.atr);
/* Find length of longest item in order to center checklist */ /* Find length of longest item in order to center checklist */
check_x = 0; check_x = 0;
for (i = 0; i < item_no; i++) item_foreach()
check_x = MAX(check_x, +strlen(items[i * 3 + 1]) + 4); check_x = MAX(check_x, strlen(item_str()) + 4);
check_x = (list_width - check_x) / 2; check_x = (list_width - check_x) / 2;
item_x = check_x + 4; item_x = check_x + 4;
...@@ -187,14 +185,11 @@ int dialog_checklist(const char *title, const char *prompt, int height, ...@@ -187,14 +185,11 @@ int dialog_checklist(const char *title, const char *prompt, int height,
/* Print the list */ /* Print the list */
for (i = 0; i < max_choice; i++) { for (i = 0; i < max_choice; i++) {
if (i != choice) item_set(scroll + i);
print_item(list, items[(scroll + i) * 3 + 1], print_item(list, i, i == choice);
status[i + scroll], i, 0);
} }
print_item(list, items[(scroll + choice) * 3 + 1],
status[choice + scroll], choice, 1);
print_arrows(dialog, choice, item_no, scroll, print_arrows(dialog, choice, item_count(), scroll,
box_y, box_x + check_x + 5, list_height); box_y, box_x + check_x + 5, list_height);
print_buttons(dialog, height, width, 0); print_buttons(dialog, height, width, 0);
...@@ -203,13 +198,14 @@ int dialog_checklist(const char *title, const char *prompt, int height, ...@@ -203,13 +198,14 @@ int dialog_checklist(const char *title, const char *prompt, int height,
wnoutrefresh(list); wnoutrefresh(list);
doupdate(); doupdate();
while (key != ESC) { while (key != KEY_ESC) {
key = wgetch(dialog); key = wgetch(dialog);
for (i = 0; i < max_choice; i++) for (i = 0; i < max_choice; i++) {
if (toupper(key) == item_set(i + scroll);
toupper(items[(scroll + i) * 3 + 1][0])) if (toupper(key) == toupper(item_str()[0]))
break; break;
}
if (i < max_choice || key == KEY_UP || key == KEY_DOWN || if (i < max_choice || key == KEY_UP || key == KEY_DOWN ||
key == '+' || key == '-') { key == '+' || key == '-') {
...@@ -220,15 +216,16 @@ int dialog_checklist(const char *title, const char *prompt, int height, ...@@ -220,15 +216,16 @@ int dialog_checklist(const char *title, const char *prompt, int height,
/* Scroll list down */ /* Scroll list down */
if (list_height > 1) { if (list_height > 1) {
/* De-highlight current first item */ /* De-highlight current first item */
print_item(list, items[scroll * 3 + 1], item_set(scroll);
status[scroll], 0, FALSE); print_item(list, 0, FALSE);
scrollok(list, TRUE); scrollok(list, TRUE);
wscrl(list, -1); wscrl(list, -1);
scrollok(list, FALSE); scrollok(list, FALSE);
} }
scroll--; scroll--;
print_item(list, items[scroll * 3 + 1], status[scroll], 0, TRUE); item_set(scroll);
print_arrows(dialog, choice, item_no, print_item(list, 0, TRUE);
print_arrows(dialog, choice, item_count(),
scroll, box_y, box_x + check_x + 5, list_height); scroll, box_y, box_x + check_x + 5, list_height);
wnoutrefresh(dialog); wnoutrefresh(dialog);
...@@ -239,23 +236,24 @@ int dialog_checklist(const char *title, const char *prompt, int height, ...@@ -239,23 +236,24 @@ int dialog_checklist(const char *title, const char *prompt, int height,
i = choice - 1; i = choice - 1;
} else if (key == KEY_DOWN || key == '+') { } else if (key == KEY_DOWN || key == '+') {
if (choice == max_choice - 1) { if (choice == max_choice - 1) {
if (scroll + choice >= item_no - 1) if (scroll + choice >= item_count() - 1)
continue; continue;
/* Scroll list up */ /* Scroll list up */
if (list_height > 1) { if (list_height > 1) {
/* De-highlight current last item before scrolling up */ /* De-highlight current last item before scrolling up */
print_item(list, items[(scroll + max_choice - 1) * 3 + 1], item_set(scroll + max_choice - 1);
status[scroll + max_choice - 1], print_item(list,
max_choice - 1, FALSE); max_choice - 1,
FALSE);
scrollok(list, TRUE); scrollok(list, TRUE);
wscrl(list, 1); wscrl(list, 1);
scrollok(list, FALSE); scrollok(list, FALSE);
} }
scroll++; scroll++;
print_item(list, items[(scroll + max_choice - 1) * 3 + 1], item_set(scroll + max_choice - 1);
status[scroll + max_choice - 1], max_choice - 1, TRUE); print_item(list, max_choice - 1, TRUE);
print_arrows(dialog, choice, item_no, print_arrows(dialog, choice, item_count(),
scroll, box_y, box_x + check_x + 5, list_height); scroll, box_y, box_x + check_x + 5, list_height);
wnoutrefresh(dialog); wnoutrefresh(dialog);
...@@ -267,12 +265,12 @@ int dialog_checklist(const char *title, const char *prompt, int height, ...@@ -267,12 +265,12 @@ int dialog_checklist(const char *title, const char *prompt, int height,
} }
if (i != choice) { if (i != choice) {
/* De-highlight current item */ /* De-highlight current item */
print_item(list, items[(scroll + choice) * 3 + 1], item_set(scroll + choice);
status[scroll + choice], choice, FALSE); print_item(list, choice, FALSE);
/* Highlight new item */ /* Highlight new item */
choice = i; choice = i;
print_item(list, items[(scroll + choice) * 3 + 1], item_set(scroll + choice);
status[scroll + choice], choice, TRUE); print_item(list, choice, TRUE);
wnoutrefresh(dialog); wnoutrefresh(dialog);
wrefresh(list); wrefresh(list);
} }
...@@ -282,10 +280,19 @@ int dialog_checklist(const char *title, const char *prompt, int height, ...@@ -282,10 +280,19 @@ int dialog_checklist(const char *title, const char *prompt, int height,
case 'H': case 'H':
case 'h': case 'h':
case '?': case '?':
fprintf(stderr, "%s", items[(scroll + choice) * 3]); button = 1;
/* fall-through */
case 'S':
case 's':
case ' ':
case '\n':
item_foreach()
item_set_selected(0);
item_set(scroll + choice);
item_set_selected(1);
delwin(list);
delwin(dialog); delwin(dialog);
free(status); return button;
return 1;
case TAB: case TAB:
case KEY_LEFT: case KEY_LEFT:
case KEY_RIGHT: case KEY_RIGHT:
...@@ -295,42 +302,24 @@ int dialog_checklist(const char *title, const char *prompt, int height, ...@@ -295,42 +302,24 @@ int dialog_checklist(const char *title, const char *prompt, int height,
print_buttons(dialog, height, width, button); print_buttons(dialog, height, width, button);
wrefresh(dialog); wrefresh(dialog);
break; break;
case 'S':
case 's':
case ' ':
case '\n':
if (!button) {
if (!status[scroll + choice]) {
for (i = 0; i < item_no; i++)
status[i] = 0;
status[scroll + choice] = 1;
for (i = 0; i < max_choice; i++)
print_item(list, items[(scroll + i) * 3 + 1],
status[scroll + i], i, i == choice);
}
wnoutrefresh(dialog);
wrefresh(list);
for (i = 0; i < item_no; i++)
if (status[i])
fprintf(stderr, "%s", items[i * 3]);
} else
fprintf(stderr, "%s", items[(scroll + choice) * 3]);
delwin(dialog);
free(status);
return button;
case 'X': case 'X':
case 'x': case 'x':
key = ESC; key = KEY_ESC;
case ESC: break;
case KEY_ESC:
key = on_key_esc(dialog);
break; break;
case KEY_RESIZE:
delwin(list);
delwin(dialog);
on_key_resize();
goto do_resize;
} }
/* Now, update everything... */ /* Now, update everything... */
doupdate(); doupdate();
} }
delwin(list);
delwin(dialog); delwin(dialog);
free(status); return key; /* ESC pressed */
return -1; /* ESC pressed */
} }
/*
* colors.h -- color attribute definitions
*
* AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
*
* 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.
*/
/*
* Default color definitions
*
* *_FG = foreground
* *_BG = background
* *_HL = highlight?
*/
#define SCREEN_FG COLOR_CYAN
#define SCREEN_BG COLOR_BLUE
#define SCREEN_HL TRUE
#define SHADOW_FG COLOR_BLACK
#define SHADOW_BG COLOR_BLACK
#define SHADOW_HL TRUE
#define DIALOG_FG COLOR_BLACK
#define DIALOG_BG COLOR_WHITE
#define DIALOG_HL FALSE
#define TITLE_FG COLOR_YELLOW
#define TITLE_BG COLOR_WHITE
#define TITLE_HL TRUE
#define BORDER_FG COLOR_WHITE
#define BORDER_BG COLOR_WHITE
#define BORDER_HL TRUE
#define BUTTON_ACTIVE_FG COLOR_WHITE
#define BUTTON_ACTIVE_BG COLOR_BLUE
#define BUTTON_ACTIVE_HL TRUE
#define BUTTON_INACTIVE_FG COLOR_BLACK
#define BUTTON_INACTIVE_BG COLOR_WHITE
#define BUTTON_INACTIVE_HL FALSE
#define BUTTON_KEY_ACTIVE_FG COLOR_WHITE
#define BUTTON_KEY_ACTIVE_BG COLOR_BLUE
#define BUTTON_KEY_ACTIVE_HL TRUE
#define BUTTON_KEY_INACTIVE_FG COLOR_RED
#define BUTTON_KEY_INACTIVE_BG COLOR_WHITE
#define BUTTON_KEY_INACTIVE_HL FALSE
#define BUTTON_LABEL_ACTIVE_FG COLOR_YELLOW
#define BUTTON_LABEL_ACTIVE_BG COLOR_BLUE
#define BUTTON_LABEL_ACTIVE_HL TRUE
#define BUTTON_LABEL_INACTIVE_FG COLOR_BLACK
#define BUTTON_LABEL_INACTIVE_BG COLOR_WHITE
#define BUTTON_LABEL_INACTIVE_HL TRUE
#define INPUTBOX_FG COLOR_BLACK
#define INPUTBOX_BG COLOR_WHITE
#define INPUTBOX_HL FALSE
#define INPUTBOX_BORDER_FG COLOR_BLACK
#define INPUTBOX_BORDER_BG COLOR_WHITE
#define INPUTBOX_BORDER_HL FALSE
#define SEARCHBOX_FG COLOR_BLACK
#define SEARCHBOX_BG COLOR_WHITE
#define SEARCHBOX_HL FALSE
#define SEARCHBOX_TITLE_FG COLOR_YELLOW
#define SEARCHBOX_TITLE_BG COLOR_WHITE
#define SEARCHBOX_TITLE_HL TRUE
#define SEARCHBOX_BORDER_FG COLOR_WHITE
#define SEARCHBOX_BORDER_BG COLOR_WHITE
#define SEARCHBOX_BORDER_HL TRUE
#define POSITION_INDICATOR_FG COLOR_YELLOW
#define POSITION_INDICATOR_BG COLOR_WHITE
#define POSITION_INDICATOR_HL TRUE
#define MENUBOX_FG COLOR_BLACK
#define MENUBOX_BG COLOR_WHITE
#define MENUBOX_HL FALSE
#define MENUBOX_BORDER_FG COLOR_WHITE
#define MENUBOX_BORDER_BG COLOR_WHITE
#define MENUBOX_BORDER_HL TRUE
#define ITEM_FG COLOR_BLACK
#define ITEM_BG COLOR_WHITE
#define ITEM_HL FALSE
#define ITEM_SELECTED_FG COLOR_WHITE
#define ITEM_SELECTED_BG COLOR_BLUE
#define ITEM_SELECTED_HL TRUE
#define TAG_FG COLOR_YELLOW
#define TAG_BG COLOR_WHITE
#define TAG_HL TRUE
#define TAG_SELECTED_FG COLOR_YELLOW
#define TAG_SELECTED_BG COLOR_BLUE
#define TAG_SELECTED_HL TRUE
#define TAG_KEY_FG COLOR_YELLOW
#define TAG_KEY_BG COLOR_WHITE
#define TAG_KEY_HL TRUE
#define TAG_KEY_SELECTED_FG COLOR_YELLOW
#define TAG_KEY_SELECTED_BG COLOR_BLUE
#define TAG_KEY_SELECTED_HL TRUE
#define CHECK_FG COLOR_BLACK
#define CHECK_BG COLOR_WHITE
#define CHECK_HL FALSE
#define CHECK_SELECTED_FG COLOR_WHITE
#define CHECK_SELECTED_BG COLOR_BLUE
#define CHECK_SELECTED_HL TRUE
#define UARROW_FG COLOR_GREEN
#define UARROW_BG COLOR_WHITE
#define UARROW_HL TRUE
#define DARROW_FG COLOR_GREEN
#define DARROW_BG COLOR_WHITE
#define DARROW_HL TRUE
/* End of default color definitions */
#define C_ATTR(x,y) ((x ? A_BOLD : 0) | COLOR_PAIR((y)))
#define COLOR_NAME_LEN 10
#define COLOR_COUNT 8
/*
* Global variables
*/
extern int color_table[][3];
...@@ -48,7 +48,7 @@ ...@@ -48,7 +48,7 @@
#define TR(params) _tracef params #define TR(params) _tracef params
#define ESC 27 #define KEY_ESC 27
#define TAB 9 #define TAB 9
#define MAX_LEN 2048 #define MAX_LEN 2048
#define BUF_SIZE (10*1024) #define BUF_SIZE (10*1024)
...@@ -86,63 +86,111 @@ ...@@ -86,63 +86,111 @@
#define ACS_DARROW 'v' #define ACS_DARROW 'v'
#endif #endif
/* error return codes */
#define ERRDISPLAYTOOSMALL (KEY_MAX + 1)
/* /*
* Attribute names * Color definitions
*/ */
#define screen_attr attributes[0] struct dialog_color {
#define shadow_attr attributes[1] chtype atr; /* Color attribute */
#define dialog_attr attributes[2] int fg; /* foreground */
#define title_attr attributes[3] int bg; /* background */
#define border_attr attributes[4] int hl; /* highlight this item */
#define button_active_attr attributes[5] };
#define button_inactive_attr attributes[6]
#define button_key_active_attr attributes[7] struct dialog_info {
#define button_key_inactive_attr attributes[8] const char *backtitle;
#define button_label_active_attr attributes[9] struct dialog_color screen;
#define button_label_inactive_attr attributes[10] struct dialog_color shadow;
#define inputbox_attr attributes[11] struct dialog_color dialog;
#define inputbox_border_attr attributes[12] struct dialog_color title;
#define searchbox_attr attributes[13] struct dialog_color border;
#define searchbox_title_attr attributes[14] struct dialog_color button_active;
#define searchbox_border_attr attributes[15] struct dialog_color button_inactive;
#define position_indicator_attr attributes[16] struct dialog_color button_key_active;
#define menubox_attr attributes[17] struct dialog_color button_key_inactive;
#define menubox_border_attr attributes[18] struct dialog_color button_label_active;
#define item_attr attributes[19] struct dialog_color button_label_inactive;
#define item_selected_attr attributes[20] struct dialog_color inputbox;
#define tag_attr attributes[21] struct dialog_color inputbox_border;
#define tag_selected_attr attributes[22] struct dialog_color searchbox;
#define tag_key_attr attributes[23] struct dialog_color searchbox_title;
#define tag_key_selected_attr attributes[24] struct dialog_color searchbox_border;
#define check_attr attributes[25] struct dialog_color position_indicator;
#define check_selected_attr attributes[26] struct dialog_color menubox;
#define uarrow_attr attributes[27] struct dialog_color menubox_border;
#define darrow_attr attributes[28] struct dialog_color item;
struct dialog_color item_selected;
/* number of attributes */ struct dialog_color tag;
#define ATTRIBUTE_COUNT 29 struct dialog_color tag_selected;
struct dialog_color tag_key;
struct dialog_color tag_key_selected;
struct dialog_color check;
struct dialog_color check_selected;
struct dialog_color uarrow;
struct dialog_color darrow;
};
/* /*
* Global variables * Global variables
*/ */
extern bool use_colors; extern struct dialog_info dlg;
extern bool use_shadow; extern char dialog_input_result[];
extern chtype attributes[];
extern const char *backtitle;
/* /*
* Function prototypes * Function prototypes
*/ */
extern void create_rc(const char *filename);
extern int parse_rc(void);
void init_dialog(void); /* item list as used by checklist and menubox */
void item_reset(void);
void item_make(const char *fmt, ...);
void item_add_str(const char *fmt, ...);
void item_set_tag(char tag);
void item_set_data(void *p);
void item_set_selected(int val);
int item_activate_selected(void);
void *item_data(void);
char item_tag(void);
/* item list manipulation for lxdialog use */
#define MAXITEMSTR 200
struct dialog_item {
char str[MAXITEMSTR]; /* promtp displayed */
char tag;
void *data; /* pointer to menu item - used by menubox+checklist */
int selected; /* Set to 1 by dialog_*() function if selected. */
};
/* list of lialog_items */
struct dialog_list {
struct dialog_item node;
struct dialog_list *next;
};
extern struct dialog_list *item_cur;
extern struct dialog_list item_nil;
extern struct dialog_list *item_head;
int item_count(void);
void item_set(int n);
int item_n(void);
const char *item_str(void);
int item_is_selected(void);
int item_is_tag(char tag);
#define item_foreach() \
for (item_cur = item_head ? item_head: item_cur; \
item_cur && (item_cur != &item_nil); item_cur = item_cur->next)
/* generic key handlers */
int on_key_esc(WINDOW *win);
int on_key_resize(void);
void init_dialog(const char *backtitle);
void reset_dialog(void);
void end_dialog(void); void end_dialog(void);
void attr_clear(WINDOW * win, int height, int width, chtype attr); void attr_clear(WINDOW * win, int height, int width, chtype attr);
void dialog_clear(void); void dialog_clear(void);
void color_setup(void);
void print_autowrap(WINDOW * win, const char *prompt, int width, int y, int x); void print_autowrap(WINDOW * win, const char *prompt, int width, int y, int x);
void print_button(WINDOW * win, const char *label, int y, int x, int selected); void print_button(WINDOW * win, const char *label, int y, int x, int selected);
void print_title(WINDOW *dialog, const char *title, int width); void print_title(WINDOW *dialog, const char *title, int width);
...@@ -155,12 +203,10 @@ int dialog_yesno(const char *title, const char *prompt, int height, int width); ...@@ -155,12 +203,10 @@ int dialog_yesno(const char *title, const char *prompt, int height, int width);
int dialog_msgbox(const char *title, const char *prompt, int height, int dialog_msgbox(const char *title, const char *prompt, int height,
int width, int pause); int width, int pause);
int dialog_textbox(const char *title, const char *file, int height, int width); int dialog_textbox(const char *title, const char *file, int height, int width);
int dialog_menu(const char *title, const char *prompt, int height, int width, int dialog_menu(const char *title, const char *prompt,
int menu_height, const char *choice, int item_no, const void *selected, int *s_scroll);
const char *const *items);
int dialog_checklist(const char *title, const char *prompt, int height, int dialog_checklist(const char *title, const char *prompt, int height,
int width, int list_height, int item_no, int width, int list_height);
const char *const *items);
extern char dialog_input_result[]; extern char dialog_input_result[];
int dialog_inputbox(const char *title, const char *prompt, int height, int dialog_inputbox(const char *title, const char *prompt, int height,
int width, const char *init); int width, const char *init);
......
...@@ -49,6 +49,17 @@ int dialog_inputbox(const char *title, const char *prompt, int height, int width ...@@ -49,6 +49,17 @@ int dialog_inputbox(const char *title, const char *prompt, int height, int width
char *instr = dialog_input_result; char *instr = dialog_input_result;
WINDOW *dialog; WINDOW *dialog;
if (!init)
instr[0] = '\0';
else
strcpy(instr, init);
do_resize:
if (getmaxy(stdscr) <= (height - 2))
return -ERRDISPLAYTOOSMALL;
if (getmaxx(stdscr) <= (width - 2))
return -ERRDISPLAYTOOSMALL;
/* center dialog box on screen */ /* center dialog box on screen */
x = (COLS - width) / 2; x = (COLS - width) / 2;
y = (LINES - height) / 2; y = (LINES - height) / 2;
...@@ -58,17 +69,18 @@ int dialog_inputbox(const char *title, const char *prompt, int height, int width ...@@ -58,17 +69,18 @@ int dialog_inputbox(const char *title, const char *prompt, int height, int width
dialog = newwin(height, width, y, x); dialog = newwin(height, width, y, x);
keypad(dialog, TRUE); keypad(dialog, TRUE);
draw_box(dialog, 0, 0, height, width, dialog_attr, border_attr); draw_box(dialog, 0, 0, height, width,
wattrset(dialog, border_attr); dlg.dialog.atr, dlg.border.atr);
wattrset(dialog, dlg.border.atr);
mvwaddch(dialog, height - 3, 0, ACS_LTEE); mvwaddch(dialog, height - 3, 0, ACS_LTEE);
for (i = 0; i < width - 2; i++) for (i = 0; i < width - 2; i++)
waddch(dialog, ACS_HLINE); waddch(dialog, ACS_HLINE);
wattrset(dialog, dialog_attr); wattrset(dialog, dlg.dialog.atr);
waddch(dialog, ACS_RTEE); waddch(dialog, ACS_RTEE);
print_title(dialog, title, width); print_title(dialog, title, width);
wattrset(dialog, dialog_attr); wattrset(dialog, dlg.dialog.atr);
print_autowrap(dialog, prompt, width - 2, 1, 3); print_autowrap(dialog, prompt, width - 2, 1, 3);
/* Draw the input field box */ /* Draw the input field box */
...@@ -76,18 +88,14 @@ int dialog_inputbox(const char *title, const char *prompt, int height, int width ...@@ -76,18 +88,14 @@ int dialog_inputbox(const char *title, const char *prompt, int height, int width
getyx(dialog, y, x); getyx(dialog, y, x);
box_y = y + 2; box_y = y + 2;
box_x = (width - box_width) / 2; box_x = (width - box_width) / 2;
draw_box(dialog, y + 1, box_x - 1, 3, box_width + 2, border_attr, dialog_attr); draw_box(dialog, y + 1, box_x - 1, 3, box_width + 2,
dlg.border.atr, dlg.dialog.atr);
print_buttons(dialog, height, width, 0); print_buttons(dialog, height, width, 0);
/* Set up the initial value */ /* Set up the initial value */
wmove(dialog, box_y, box_x); wmove(dialog, box_y, box_x);
wattrset(dialog, inputbox_attr); wattrset(dialog, dlg.inputbox.atr);
if (!init)
instr[0] = '\0';
else
strcpy(instr, init);
input_x = strlen(instr); input_x = strlen(instr);
...@@ -104,7 +112,7 @@ int dialog_inputbox(const char *title, const char *prompt, int height, int width ...@@ -104,7 +112,7 @@ int dialog_inputbox(const char *title, const char *prompt, int height, int width
wrefresh(dialog); wrefresh(dialog);
while (key != ESC) { while (key != KEY_ESC) {
key = wgetch(dialog); key = wgetch(dialog);
if (button == -1) { /* Input box selected */ if (button == -1) { /* Input box selected */
...@@ -120,7 +128,7 @@ int dialog_inputbox(const char *title, const char *prompt, int height, int width ...@@ -120,7 +128,7 @@ int dialog_inputbox(const char *title, const char *prompt, int height, int width
case KEY_BACKSPACE: case KEY_BACKSPACE:
case 127: case 127:
if (input_x || scroll) { if (input_x || scroll) {
wattrset(dialog, inputbox_attr); wattrset(dialog, dlg.inputbox.atr);
if (!input_x) { if (!input_x) {
scroll = scroll < box_width - 1 ? 0 : scroll - (box_width - 1); scroll = scroll < box_width - 1 ? 0 : scroll - (box_width - 1);
wmove(dialog, box_y, box_x); wmove(dialog, box_y, box_x);
...@@ -140,7 +148,7 @@ int dialog_inputbox(const char *title, const char *prompt, int height, int width ...@@ -140,7 +148,7 @@ int dialog_inputbox(const char *title, const char *prompt, int height, int width
default: default:
if (key < 0x100 && isprint(key)) { if (key < 0x100 && isprint(key)) {
if (scroll + input_x < MAX_LEN) { if (scroll + input_x < MAX_LEN) {
wattrset(dialog, inputbox_attr); wattrset(dialog, dlg.inputbox.atr);
instr[scroll + input_x] = key; instr[scroll + input_x] = key;
instr[scroll + input_x + 1] = '\0'; instr[scroll + input_x + 1] = '\0';
if (input_x == box_width - 1) { if (input_x == box_width - 1) {
...@@ -213,12 +221,18 @@ int dialog_inputbox(const char *title, const char *prompt, int height, int width ...@@ -213,12 +221,18 @@ int dialog_inputbox(const char *title, const char *prompt, int height, int width
return (button == -1 ? 0 : button); return (button == -1 ? 0 : button);
case 'X': case 'X':
case 'x': case 'x':
key = ESC; key = KEY_ESC;
case ESC: break;
case KEY_ESC:
key = on_key_esc(dialog);
break; break;
case KEY_RESIZE:
delwin(dialog);
on_key_resize();
goto do_resize;
} }
} }
delwin(dialog); delwin(dialog);
return -1; /* ESC pressed */ return KEY_ESC; /* ESC pressed */
} }
/*
* dialog - Display simple dialog boxes from shell scripts
*
* ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
* MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com)
*
* 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 "dialog.h"
static void Usage(const char *name);
typedef int (jumperFn) (const char *title, int argc, const char *const *argv);
struct Mode {
char *name;
int argmin, argmax, argmod;
jumperFn *jumper;
};
jumperFn j_menu, j_radiolist, j_yesno, j_textbox, j_inputbox;
jumperFn j_msgbox, j_infobox;
static struct Mode modes[] = {
{"--menu", 9, 0, 3, j_menu},
{"--radiolist", 9, 0, 3, j_radiolist},
{"--yesno", 5, 5, 1, j_yesno},
{"--textbox", 5, 5, 1, j_textbox},
{"--inputbox", 5, 6, 1, j_inputbox},
{"--msgbox", 5, 5, 1, j_msgbox},
{"--infobox", 5, 5, 1, j_infobox},
{NULL, 0, 0, 0, NULL}
};
static struct Mode *modePtr;
#ifdef LOCALE
#include <locale.h>
#endif
int main(int argc, const char *const *argv)
{
int offset = 0, opt_clear = 0, end_common_opts = 0, retval;
const char *title = NULL;
#ifdef LOCALE
(void)setlocale(LC_ALL, "");
#endif
#ifdef TRACE
trace(TRACE_CALLS | TRACE_UPDATE);
#endif
if (argc < 2) {
Usage(argv[0]);
exit(-1);
}
while (offset < argc - 1 && !end_common_opts) { /* Common options */
if (!strcmp(argv[offset + 1], "--title")) {
if (argc - offset < 3 || title != NULL) {
Usage(argv[0]);
exit(-1);
} else {
title = argv[offset + 2];
offset += 2;
}
} else if (!strcmp(argv[offset + 1], "--backtitle")) {
if (backtitle != NULL) {
Usage(argv[0]);
exit(-1);
} else {
backtitle = argv[offset + 2];
offset += 2;
}
} else if (!strcmp(argv[offset + 1], "--clear")) {
if (opt_clear) { /* Hey, "--clear" can't appear twice! */
Usage(argv[0]);
exit(-1);
} else if (argc == 2) { /* we only want to clear the screen */
init_dialog();
refresh(); /* init_dialog() will clear the screen for us */
end_dialog();
return 0;
} else {
opt_clear = 1;
offset++;
}
} else /* no more common options */
end_common_opts = 1;
}
if (argc - 1 == offset) { /* no more options */
Usage(argv[0]);
exit(-1);
}
/* use a table to look for the requested mode, to avoid code duplication */
for (modePtr = modes; modePtr->name; modePtr++) /* look for the mode */
if (!strcmp(argv[offset + 1], modePtr->name))
break;
if (!modePtr->name)
Usage(argv[0]);
if (argc - offset < modePtr->argmin)
Usage(argv[0]);
if (modePtr->argmax && argc - offset > modePtr->argmax)
Usage(argv[0]);
init_dialog();
retval = (*(modePtr->jumper)) (title, argc - offset, argv + offset);
if (opt_clear) { /* clear screen before exit */
attr_clear(stdscr, LINES, COLS, screen_attr);
refresh();
}
end_dialog();
exit(retval);
}
/*
* Print program usage
*/
static void Usage(const char *name)
{
fprintf(stderr, "\
\ndialog, by Savio Lam (lam836@cs.cuhk.hk).\
\n patched by Stuart Herbert (S.Herbert@shef.ac.uk)\
\n modified/gutted for use as a Linux kernel config tool by \
\n William Roadcap (roadcapw@cfw.com)\
\n\
\n* Display dialog boxes from shell scripts *\
\n\
\nUsage: %s --clear\
\n %s [--title <title>] [--backtitle <backtitle>] --clear <Box options>\
\n\
\nBox options:\
\n\
\n --menu <text> <height> <width> <menu height> <tag1> <item1>...\
\n --radiolist <text> <height> <width> <list height> <tag1> <item1> <status1>...\
\n --textbox <file> <height> <width>\
\n --inputbox <text> <height> <width> [<init>]\
\n --yesno <text> <height> <width>\
\n", name, name);
exit(-1);
}
/*
* These are the program jumpers
*/
int j_menu(const char *t, int ac, const char *const *av)
{
return dialog_menu(t, av[2], atoi(av[3]), atoi(av[4]),
atoi(av[5]), av[6], (ac - 6) / 2, av + 7);
}
int j_radiolist(const char *t, int ac, const char *const *av)
{
return dialog_checklist(t, av[2], atoi(av[3]), atoi(av[4]),
atoi(av[5]), (ac - 6) / 3, av + 6);
}
int j_textbox(const char *t, int ac, const char *const *av)
{
return dialog_textbox(t, av[2], atoi(av[3]), atoi(av[4]));
}
int j_yesno(const char *t, int ac, const char *const *av)
{
return dialog_yesno(t, av[2], atoi(av[3]), atoi(av[4]));
}
int j_inputbox(const char *t, int ac, const char *const *av)
{
int ret = dialog_inputbox(t, av[2], atoi(av[3]), atoi(av[4]),
ac == 6 ? av[5] : (char *)NULL);
if (ret == 0)
fprintf(stderr, dialog_input_result);
return ret;
}
int j_msgbox(const char *t, int ac, const char *const *av)
{
return dialog_msgbox(t, av[2], atoi(av[3]), atoi(av[4]), 1);
}
int j_infobox(const char *t, int ac, const char *const *av)
{
return dialog_msgbox(t, av[2], atoi(av[3]), atoi(av[4]), 0);
}
...@@ -63,19 +63,19 @@ static int menu_width, item_x; ...@@ -63,19 +63,19 @@ static int menu_width, item_x;
/* /*
* Print menu item * Print menu item
*/ */
static void do_print_item(WINDOW * win, const char *item, int choice, static void do_print_item(WINDOW * win, const char *item, int line_y,
int selected, int hotkey) int selected, int hotkey)
{ {
int j; int j;
char *menu_item = malloc(menu_width + 1); char *menu_item = malloc(menu_width + 1);
strncpy(menu_item, item, menu_width - item_x); strncpy(menu_item, item, menu_width - item_x);
menu_item[menu_width] = 0; menu_item[menu_width - item_x] = '\0';
j = first_alpha(menu_item, "YyNnMmHh"); j = first_alpha(menu_item, "YyNnMmHh");
/* Clear 'residue' of last item */ /* Clear 'residue' of last item */
wattrset(win, menubox_attr); wattrset(win, dlg.menubox.atr);
wmove(win, choice, 0); wmove(win, line_y, 0);
#if OLD_NCURSES #if OLD_NCURSES
{ {
int i; int i;
...@@ -85,23 +85,24 @@ static void do_print_item(WINDOW * win, const char *item, int choice, ...@@ -85,23 +85,24 @@ static void do_print_item(WINDOW * win, const char *item, int choice,
#else #else
wclrtoeol(win); wclrtoeol(win);
#endif #endif
wattrset(win, selected ? item_selected_attr : item_attr); wattrset(win, selected ? dlg.item_selected.atr : dlg.item.atr);
mvwaddstr(win, choice, item_x, menu_item); mvwaddstr(win, line_y, item_x, menu_item);
if (hotkey) { if (hotkey) {
wattrset(win, selected ? tag_key_selected_attr : tag_key_attr); wattrset(win, selected ? dlg.tag_key_selected.atr
mvwaddch(win, choice, item_x + j, menu_item[j]); : dlg.tag_key.atr);
mvwaddch(win, line_y, item_x + j, menu_item[j]);
} }
if (selected) { if (selected) {
wmove(win, choice, item_x + 1); wmove(win, line_y, item_x + 1);
} }
free(menu_item); free(menu_item);
wrefresh(win); wrefresh(win);
} }
#define print_item(index, choice, selected) \ #define print_item(index, choice, selected) \
do {\ do { \
int hotkey = (items[(index) * 2][0] != ':'); \ item_set(index); \
do_print_item(menu, items[(index) * 2 + 1], choice, selected, hotkey); \ do_print_item(menu, item_str(), choice, selected, !item_is_tag(':')); \
} while (0) } while (0)
/* /*
...@@ -117,11 +118,11 @@ static void print_arrows(WINDOW * win, int item_no, int scroll, int y, int x, ...@@ -117,11 +118,11 @@ static void print_arrows(WINDOW * win, int item_no, int scroll, int y, int x,
wmove(win, y, x); wmove(win, y, x);
if (scroll > 0) { if (scroll > 0) {
wattrset(win, uarrow_attr); wattrset(win, dlg.uarrow.atr);
waddch(win, ACS_UARROW); waddch(win, ACS_UARROW);
waddstr(win, "(-)"); waddstr(win, "(-)");
} else { } else {
wattrset(win, menubox_attr); wattrset(win, dlg.menubox.atr);
waddch(win, ACS_HLINE); waddch(win, ACS_HLINE);
waddch(win, ACS_HLINE); waddch(win, ACS_HLINE);
waddch(win, ACS_HLINE); waddch(win, ACS_HLINE);
...@@ -133,11 +134,11 @@ static void print_arrows(WINDOW * win, int item_no, int scroll, int y, int x, ...@@ -133,11 +134,11 @@ static void print_arrows(WINDOW * win, int item_no, int scroll, int y, int x,
wrefresh(win); wrefresh(win);
if ((height < item_no) && (scroll + height < item_no)) { if ((height < item_no) && (scroll + height < item_no)) {
wattrset(win, darrow_attr); wattrset(win, dlg.darrow.atr);
waddch(win, ACS_DARROW); waddch(win, ACS_DARROW);
waddstr(win, "(+)"); waddstr(win, "(+)");
} else { } else {
wattrset(win, menubox_border_attr); wattrset(win, dlg.menubox_border.atr);
waddch(win, ACS_HLINE); waddch(win, ACS_HLINE);
waddch(win, ACS_HLINE); waddch(win, ACS_HLINE);
waddch(win, ACS_HLINE); waddch(win, ACS_HLINE);
...@@ -178,17 +179,26 @@ static void do_scroll(WINDOW *win, int *scroll, int n) ...@@ -178,17 +179,26 @@ static void do_scroll(WINDOW *win, int *scroll, int n)
/* /*
* Display a menu for choosing among a number of options * Display a menu for choosing among a number of options
*/ */
int dialog_menu(const char *title, const char *prompt, int height, int width, int dialog_menu(const char *title, const char *prompt,
int menu_height, const char *current, int item_no, const void *selected, int *s_scroll)
const char *const *items)
{ {
int i, j, x, y, box_x, box_y; int i, j, x, y, box_x, box_y;
int height, width, menu_height;
int key = 0, button = 0, scroll = 0, choice = 0; int key = 0, button = 0, scroll = 0, choice = 0;
int first_item = 0, max_choice; int first_item = 0, max_choice;
WINDOW *dialog, *menu; WINDOW *dialog, *menu;
FILE *f;
max_choice = MIN(menu_height, item_no); do_resize:
height = getmaxy(stdscr);
width = getmaxx(stdscr);
if (height < 15 || width < 65)
return -ERRDISPLAYTOOSMALL;
height -= 4;
width -= 5;
menu_height = height - 10;
max_choice = MIN(menu_height, item_count());
/* center dialog box on screen */ /* center dialog box on screen */
x = (COLS - width) / 2; x = (COLS - width) / 2;
...@@ -199,18 +209,19 @@ int dialog_menu(const char *title, const char *prompt, int height, int width, ...@@ -199,18 +209,19 @@ int dialog_menu(const char *title, const char *prompt, int height, int width,
dialog = newwin(height, width, y, x); dialog = newwin(height, width, y, x);
keypad(dialog, TRUE); keypad(dialog, TRUE);
draw_box(dialog, 0, 0, height, width, dialog_attr, border_attr); draw_box(dialog, 0, 0, height, width,
wattrset(dialog, border_attr); dlg.dialog.atr, dlg.border.atr);
wattrset(dialog, dlg.border.atr);
mvwaddch(dialog, height - 3, 0, ACS_LTEE); mvwaddch(dialog, height - 3, 0, ACS_LTEE);
for (i = 0; i < width - 2; i++) for (i = 0; i < width - 2; i++)
waddch(dialog, ACS_HLINE); waddch(dialog, ACS_HLINE);
wattrset(dialog, dialog_attr); wattrset(dialog, dlg.dialog.atr);
wbkgdset(dialog, dialog_attr & A_COLOR); wbkgdset(dialog, dlg.dialog.atr & A_COLOR);
waddch(dialog, ACS_RTEE); waddch(dialog, ACS_RTEE);
print_title(dialog, title, width); print_title(dialog, title, width);
wattrset(dialog, dialog_attr); wattrset(dialog, dlg.dialog.atr);
print_autowrap(dialog, prompt, width - 2, 1, 3); print_autowrap(dialog, prompt, width - 2, 1, 3);
menu_width = width - 6; menu_width = width - 6;
...@@ -224,33 +235,29 @@ int dialog_menu(const char *title, const char *prompt, int height, int width, ...@@ -224,33 +235,29 @@ int dialog_menu(const char *title, const char *prompt, int height, int width,
/* draw a box around the menu items */ /* draw a box around the menu items */
draw_box(dialog, box_y, box_x, menu_height + 2, menu_width + 2, draw_box(dialog, box_y, box_x, menu_height + 2, menu_width + 2,
menubox_border_attr, menubox_attr); dlg.menubox_border.atr, dlg.menubox.atr);
item_x = (menu_width - 70) / 2; if (menu_width >= 80)
item_x = (menu_width - 70) / 2;
else
item_x = 4;
/* Set choice to default item */ /* Set choice to default item */
for (i = 0; i < item_no; i++) item_foreach()
if (strcmp(current, items[i * 2]) == 0) if (selected && (selected == item_data()))
choice = i; choice = item_n();
/* get the saved scroll info */
/* get the scroll info from the temp file */ scroll = *s_scroll;
if ((f = fopen("lxdialog.scrltmp", "r")) != NULL) { if ((scroll <= choice) && (scroll + max_choice > choice) &&
if ((fscanf(f, "%d\n", &scroll) == 1) && (scroll <= choice) && (scroll >= 0) && (scroll + max_choice <= item_count())) {
(scroll + max_choice > choice) && (scroll >= 0) && first_item = scroll;
(scroll + max_choice <= item_no)) { choice = choice - scroll;
first_item = scroll; } else {
choice = choice - scroll; scroll = 0;
fclose(f);
} else {
scroll = 0;
remove("lxdialog.scrltmp");
fclose(f);
f = NULL;
}
} }
if ((choice >= max_choice) || (f == NULL && choice >= max_choice / 2)) { if ((choice >= max_choice)) {
if (choice >= item_no - max_choice / 2) if (choice >= item_count() - max_choice / 2)
scroll = first_item = item_no - max_choice; scroll = first_item = item_count() - max_choice;
else else
scroll = first_item = choice - max_choice / 2; scroll = first_item = choice - max_choice / 2;
choice = choice - scroll; choice = choice - scroll;
...@@ -263,14 +270,14 @@ int dialog_menu(const char *title, const char *prompt, int height, int width, ...@@ -263,14 +270,14 @@ int dialog_menu(const char *title, const char *prompt, int height, int width,
wnoutrefresh(menu); wnoutrefresh(menu);
print_arrows(dialog, item_no, scroll, print_arrows(dialog, item_count(), scroll,
box_y, box_x + item_x + 1, menu_height); box_y, box_x + item_x + 1, menu_height);
print_buttons(dialog, height, width, 0); print_buttons(dialog, height, width, 0);
wmove(menu, choice, item_x + 1); wmove(menu, choice, item_x + 1);
wrefresh(menu); wrefresh(menu);
while (key != ESC) { while (key != KEY_ESC) {
key = wgetch(menu); key = wgetch(menu);
if (key < 256 && isalpha(key)) if (key < 256 && isalpha(key))
...@@ -280,14 +287,16 @@ int dialog_menu(const char *title, const char *prompt, int height, int width, ...@@ -280,14 +287,16 @@ int dialog_menu(const char *title, const char *prompt, int height, int width,
i = max_choice; i = max_choice;
else { else {
for (i = choice + 1; i < max_choice; i++) { for (i = choice + 1; i < max_choice; i++) {
j = first_alpha(items[(scroll + i) * 2 + 1], "YyNnMmHh"); item_set(scroll + i);
if (key == tolower(items[(scroll + i) * 2 + 1][j])) j = first_alpha(item_str(), "YyNnMmHh");
if (key == tolower(item_str()[j]))
break; break;
} }
if (i == max_choice) if (i == max_choice)
for (i = 0; i < max_choice; i++) { for (i = 0; i < max_choice; i++) {
j = first_alpha(items [(scroll + i) * 2 + 1], "YyNnMmHh"); item_set(scroll + i);
if (key == tolower(items[(scroll + i) * 2 + 1][j])) j = first_alpha(item_str(), "YyNnMmHh");
if (key == tolower(item_str()[j]))
break; break;
} }
} }
...@@ -312,7 +321,7 @@ int dialog_menu(const char *title, const char *prompt, int height, int width, ...@@ -312,7 +321,7 @@ int dialog_menu(const char *title, const char *prompt, int height, int width,
print_item(scroll+choice, choice, FALSE); print_item(scroll+choice, choice, FALSE);
if ((choice > max_choice - 3) && if ((choice > max_choice - 3) &&
(scroll + max_choice < item_no)) { (scroll + max_choice < item_count())) {
/* Scroll menu up */ /* Scroll menu up */
do_scroll(menu, &scroll, 1); do_scroll(menu, &scroll, 1);
...@@ -335,7 +344,7 @@ int dialog_menu(const char *title, const char *prompt, int height, int width, ...@@ -335,7 +344,7 @@ int dialog_menu(const char *title, const char *prompt, int height, int width,
} else if (key == KEY_NPAGE) { } else if (key == KEY_NPAGE) {
for (i = 0; (i < max_choice); i++) { for (i = 0; (i < max_choice); i++) {
if (scroll + max_choice < item_no) { if (scroll + max_choice < item_count()) {
do_scroll(menu, &scroll, 1); do_scroll(menu, &scroll, 1);
print_item(scroll+max_choice-1, print_item(scroll+max_choice-1,
max_choice - 1, FALSE); max_choice - 1, FALSE);
...@@ -349,7 +358,7 @@ int dialog_menu(const char *title, const char *prompt, int height, int width, ...@@ -349,7 +358,7 @@ int dialog_menu(const char *title, const char *prompt, int height, int width,
print_item(scroll + choice, choice, TRUE); print_item(scroll + choice, choice, TRUE);
print_arrows(dialog, item_no, scroll, print_arrows(dialog, item_count(), scroll,
box_y, box_x + item_x + 1, menu_height); box_y, box_x + item_x + 1, menu_height);
wnoutrefresh(dialog); wnoutrefresh(dialog);
...@@ -375,12 +384,11 @@ int dialog_menu(const char *title, const char *prompt, int height, int width, ...@@ -375,12 +384,11 @@ int dialog_menu(const char *title, const char *prompt, int height, int width,
case 'm': case 'm':
case '/': case '/':
/* save scroll info */ /* save scroll info */
if ((f = fopen("lxdialog.scrltmp", "w")) != NULL) { *s_scroll = scroll;
fprintf(f, "%d\n", scroll); delwin(menu);
fclose(f);
}
delwin(dialog); delwin(dialog);
fprintf(stderr, "%s\n", items[(scroll + choice) * 2]); item_set(scroll + choice);
item_set_selected(1);
switch (key) { switch (key) {
case 's': case 's':
return 3; return 3;
...@@ -400,27 +408,27 @@ int dialog_menu(const char *title, const char *prompt, int height, int width, ...@@ -400,27 +408,27 @@ int dialog_menu(const char *title, const char *prompt, int height, int width,
case '?': case '?':
button = 2; button = 2;
case '\n': case '\n':
*s_scroll = scroll;
delwin(menu);
delwin(dialog); delwin(dialog);
if (button == 2) item_set(scroll + choice);
fprintf(stderr, "%s \"%s\"\n", item_set_selected(1);
items[(scroll + choice) * 2],
items[(scroll + choice) * 2 + 1] +
first_alpha(items [(scroll + choice) * 2 + 1], ""));
else
fprintf(stderr, "%s\n",
items[(scroll + choice) * 2]);
remove("lxdialog.scrltmp");
return button; return button;
case 'e': case 'e':
case 'x': case 'x':
key = ESC; key = KEY_ESC;
case ESC: break;
case KEY_ESC:
key = on_key_esc(menu);
break; break;
case KEY_RESIZE:
on_key_resize();
delwin(menu);
delwin(dialog);
goto do_resize;
} }
} }
delwin(menu);
delwin(dialog); delwin(dialog);
remove("lxdialog.scrltmp"); return key; /* ESC pressed */
return -1; /* ESC pressed */
} }
/*
* msgbox.c -- implements the message box and info box
*
* ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
* MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcapw@cfw.com)
*
* 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 "dialog.h"
/*
* Display a message box. Program will pause and display an "OK" button
* if the parameter 'pause' is non-zero.
*/
int dialog_msgbox(const char *title, const char *prompt, int height, int width,
int pause)
{
int i, x, y, key = 0;
WINDOW *dialog;
/* center dialog box on screen */
x = (COLS - width) / 2;
y = (LINES - height) / 2;
draw_shadow(stdscr, y, x, height, width);
dialog = newwin(height, width, y, x);
keypad(dialog, TRUE);
draw_box(dialog, 0, 0, height, width, dialog_attr, border_attr);
print_title(dialog, title, width);
wattrset(dialog, dialog_attr);
print_autowrap(dialog, prompt, width - 2, 1, 2);
if (pause) {
wattrset(dialog, border_attr);
mvwaddch(dialog, height - 3, 0, ACS_LTEE);
for (i = 0; i < width - 2; i++)
waddch(dialog, ACS_HLINE);
wattrset(dialog, dialog_attr);
waddch(dialog, ACS_RTEE);
print_button(dialog, " Ok ", height - 2, width / 2 - 4, TRUE);
wrefresh(dialog);
while (key != ESC && key != '\n' && key != ' ' &&
key != 'O' && key != 'o' && key != 'X' && key != 'x')
key = wgetch(dialog);
} else {
key = '\n';
wrefresh(dialog);
}
delwin(dialog);
return key == ESC ? -1 : 0;
}
...@@ -25,56 +25,62 @@ static void back_lines(int n); ...@@ -25,56 +25,62 @@ static void back_lines(int n);
static void print_page(WINDOW * win, int height, int width); static void print_page(WINDOW * win, int height, int width);
static void print_line(WINDOW * win, int row, int width); static void print_line(WINDOW * win, int row, int width);
static char *get_line(void); static char *get_line(void);
static void print_position(WINDOW * win, int height, int width); static void print_position(WINDOW * win);
static int hscroll;
static int begin_reached, end_reached, page_length;
static const char *buf;
static const char *page;
/*
* refresh window content
*/
static void refresh_text_box(WINDOW *dialog, WINDOW *box, int boxh, int boxw,
int cur_y, int cur_x)
{
print_page(box, boxh, boxw);
print_position(dialog);
wmove(dialog, cur_y, cur_x); /* Restore cursor position */
wrefresh(dialog);
}
static int hscroll, fd, file_size, bytes_read;
static int begin_reached = 1, end_reached, page_length;
static char *buf, *page;
/* /*
* Display text from a file in a dialog box. * Display text from a file in a dialog box.
*/ */
int dialog_textbox(const char *title, const char *file, int height, int width) int dialog_textbox(const char *title, const char *tbuf,
int initial_height, int initial_width)
{ {
int i, x, y, cur_x, cur_y, fpos, key = 0; int i, x, y, cur_x, cur_y, key = 0;
int height, width, boxh, boxw;
int passed_end; int passed_end;
char search_term[MAX_LEN + 1]; WINDOW *dialog, *box;
WINDOW *dialog, *text;
search_term[0] = '\0'; /* no search term entered yet */
/* Open input file for reading */ begin_reached = 1;
if ((fd = open(file, O_RDONLY)) == -1) { end_reached = 0;
endwin(); page_length = 0;
fprintf(stderr, "\nCan't open input file in dialog_textbox().\n"); hscroll = 0;
exit(-1); buf = tbuf;
} page = buf; /* page is pointer to start of page to be displayed */
/* Get file size. Actually, 'file_size' is the real file size - 1,
since it's only the last byte offset from the beginning */ do_resize:
if ((file_size = lseek(fd, 0, SEEK_END)) == -1) { getmaxyx(stdscr, height, width);
endwin(); if (height < 8 || width < 8)
fprintf(stderr, "\nError getting file size in dialog_textbox().\n"); return -ERRDISPLAYTOOSMALL;
exit(-1); if (initial_height != 0)
} height = initial_height;
/* Restore file pointer to beginning of file after getting file size */ else
if (lseek(fd, 0, SEEK_SET) == -1) { if (height > 4)
endwin(); height -= 4;
fprintf(stderr, "\nError moving file pointer in dialog_textbox().\n"); else
exit(-1); height = 0;
} if (initial_width != 0)
/* Allocate space for read buffer */ width = initial_width;
if ((buf = malloc(BUF_SIZE + 1)) == NULL) { else
endwin(); if (width > 5)
fprintf(stderr, "\nCan't allocate memory in dialog_textbox().\n"); width -= 5;
exit(-1); else
} width = 0;
if ((bytes_read = read(fd, buf, BUF_SIZE)) == -1) {
endwin();
fprintf(stderr, "\nError reading file in dialog_textbox().\n");
exit(-1);
}
buf[bytes_read] = '\0'; /* mark end of valid data */
page = buf; /* page is pointer to start of page to be displayed */
/* center dialog box on screen */ /* center dialog box on screen */
x = (COLS - width) / 2; x = (COLS - width) / 2;
...@@ -85,22 +91,25 @@ int dialog_textbox(const char *title, const char *file, int height, int width) ...@@ -85,22 +91,25 @@ int dialog_textbox(const char *title, const char *file, int height, int width)
dialog = newwin(height, width, y, x); dialog = newwin(height, width, y, x);
keypad(dialog, TRUE); keypad(dialog, TRUE);
/* Create window for text region, used for scrolling text */ /* Create window for box region, used for scrolling text */
text = subwin(dialog, height - 4, width - 2, y + 1, x + 1); boxh = height - 4;
wattrset(text, dialog_attr); boxw = width - 2;
wbkgdset(text, dialog_attr & A_COLOR); box = subwin(dialog, boxh, boxw, y + 1, x + 1);
wattrset(box, dlg.dialog.atr);
wbkgdset(box, dlg.dialog.atr & A_COLOR);
keypad(text, TRUE); keypad(box, TRUE);
/* register the new window, along with its borders */ /* register the new window, along with its borders */
draw_box(dialog, 0, 0, height, width, dialog_attr, border_attr); draw_box(dialog, 0, 0, height, width,
dlg.dialog.atr, dlg.border.atr);
wattrset(dialog, border_attr); wattrset(dialog, dlg.border.atr);
mvwaddch(dialog, height - 3, 0, ACS_LTEE); mvwaddch(dialog, height - 3, 0, ACS_LTEE);
for (i = 0; i < width - 2; i++) for (i = 0; i < width - 2; i++)
waddch(dialog, ACS_HLINE); waddch(dialog, ACS_HLINE);
wattrset(dialog, dialog_attr); wattrset(dialog, dlg.dialog.atr);
wbkgdset(dialog, dialog_attr & A_COLOR); wbkgdset(dialog, dlg.dialog.atr & A_COLOR);
waddch(dialog, ACS_RTEE); waddch(dialog, ACS_RTEE);
print_title(dialog, title, width); print_title(dialog, title, width);
...@@ -110,85 +119,37 @@ int dialog_textbox(const char *title, const char *file, int height, int width) ...@@ -110,85 +119,37 @@ int dialog_textbox(const char *title, const char *file, int height, int width)
getyx(dialog, cur_y, cur_x); /* Save cursor position */ getyx(dialog, cur_y, cur_x); /* Save cursor position */
/* Print first page of text */ /* Print first page of text */
attr_clear(text, height - 4, width - 2, dialog_attr); attr_clear(box, boxh, boxw, dlg.dialog.atr);
print_page(text, height - 4, width - 2); refresh_text_box(dialog, box, boxh, boxw, cur_y, cur_x);
print_position(dialog, height, width);
wmove(dialog, cur_y, cur_x); /* Restore cursor position */
wrefresh(dialog);
while ((key != ESC) && (key != '\n')) { while ((key != KEY_ESC) && (key != '\n')) {
key = wgetch(dialog); key = wgetch(dialog);
switch (key) { switch (key) {
case 'E': /* Exit */ case 'E': /* Exit */
case 'e': case 'e':
case 'X': case 'X':
case 'x': case 'x':
delwin(box);
delwin(dialog); delwin(dialog);
free(buf);
close(fd);
return 0; return 0;
case 'g': /* First page */ case 'g': /* First page */
case KEY_HOME: case KEY_HOME:
if (!begin_reached) { if (!begin_reached) {
begin_reached = 1; begin_reached = 1;
/* First page not in buffer? */
if ((fpos = lseek(fd, 0, SEEK_CUR)) == -1) {
endwin();
fprintf(stderr, "\nError moving file pointer in dialog_textbox().\n");
exit(-1);
}
if (fpos > bytes_read) { /* Yes, we have to read it in */
if (lseek(fd, 0, SEEK_SET) == -1) {
endwin();
fprintf(stderr, "\nError moving file pointer in "
"dialog_textbox().\n");
exit(-1);
}
if ((bytes_read =
read(fd, buf, BUF_SIZE)) == -1) {
endwin();
fprintf(stderr, "\nError reading file in dialog_textbox().\n");
exit(-1);
}
buf[bytes_read] = '\0';
}
page = buf; page = buf;
print_page(text, height - 4, width - 2); refresh_text_box(dialog, box, boxh, boxw,
print_position(dialog, height, width); cur_y, cur_x);
wmove(dialog, cur_y, cur_x); /* Restore cursor position */
wrefresh(dialog);
} }
break; break;
case 'G': /* Last page */ case 'G': /* Last page */
case KEY_END: case KEY_END:
end_reached = 1; end_reached = 1;
/* Last page not in buffer? */ /* point to last char in buf */
if ((fpos = lseek(fd, 0, SEEK_CUR)) == -1) { page = buf + strlen(buf);
endwin(); back_lines(boxh);
fprintf(stderr, "\nError moving file pointer in dialog_textbox().\n"); refresh_text_box(dialog, box, boxh, boxw,
exit(-1); cur_y, cur_x);
}
if (fpos < file_size) { /* Yes, we have to read it in */
if (lseek(fd, -BUF_SIZE, SEEK_END) == -1) {
endwin();
fprintf(stderr, "\nError moving file pointer in dialog_textbox().\n");
exit(-1);
}
if ((bytes_read =
read(fd, buf, BUF_SIZE)) == -1) {
endwin();
fprintf(stderr, "\nError reading file in dialog_textbox().\n");
exit(-1);
}
buf[bytes_read] = '\0';
}
page = buf + bytes_read;
back_lines(height - 4);
print_page(text, height - 4, width - 2);
print_position(dialog, height, width);
wmove(dialog, cur_y, cur_x); /* Restore cursor position */
wrefresh(dialog);
break; break;
case 'K': /* Previous line */ case 'K': /* Previous line */
case 'k': case 'k':
...@@ -196,21 +157,23 @@ int dialog_textbox(const char *title, const char *file, int height, int width) ...@@ -196,21 +157,23 @@ int dialog_textbox(const char *title, const char *file, int height, int width)
if (!begin_reached) { if (!begin_reached) {
back_lines(page_length + 1); back_lines(page_length + 1);
/* We don't call print_page() here but use scrolling to ensure /* We don't call print_page() here but use
faster screen update. However, 'end_reached' and * scrolling to ensure faster screen update.
'page_length' should still be updated, and 'page' should * However, 'end_reached' and 'page_length'
point to start of next page. This is done by calling * should still be updated, and 'page' should
get_line() in the following 'for' loop. */ * point to start of next page. This is done
scrollok(text, TRUE); * by calling get_line() in the following
wscrl(text, -1); /* Scroll text region down one line */ * 'for' loop. */
scrollok(text, FALSE); scrollok(box, TRUE);
wscrl(box, -1); /* Scroll box region down one line */
scrollok(box, FALSE);
page_length = 0; page_length = 0;
passed_end = 0; passed_end = 0;
for (i = 0; i < height - 4; i++) { for (i = 0; i < boxh; i++) {
if (!i) { if (!i) {
/* print first line of page */ /* print first line of page */
print_line(text, 0, width - 2); print_line(box, 0, boxw);
wnoutrefresh(text); wnoutrefresh(box);
} else } else
/* Called to update 'end_reached' and 'page' */ /* Called to update 'end_reached' and 'page' */
get_line(); get_line();
...@@ -220,7 +183,7 @@ int dialog_textbox(const char *title, const char *file, int height, int width) ...@@ -220,7 +183,7 @@ int dialog_textbox(const char *title, const char *file, int height, int width)
passed_end = 1; passed_end = 1;
} }
print_position(dialog, height, width); print_position(dialog);
wmove(dialog, cur_y, cur_x); /* Restore cursor position */ wmove(dialog, cur_y, cur_x); /* Restore cursor position */
wrefresh(dialog); wrefresh(dialog);
} }
...@@ -230,23 +193,21 @@ int dialog_textbox(const char *title, const char *file, int height, int width) ...@@ -230,23 +193,21 @@ int dialog_textbox(const char *title, const char *file, int height, int width)
case KEY_PPAGE: case KEY_PPAGE:
if (begin_reached) if (begin_reached)
break; break;
back_lines(page_length + height - 4); back_lines(page_length + boxh);
print_page(text, height - 4, width - 2); refresh_text_box(dialog, box, boxh, boxw,
print_position(dialog, height, width); cur_y, cur_x);
wmove(dialog, cur_y, cur_x);
wrefresh(dialog);
break; break;
case 'J': /* Next line */ case 'J': /* Next line */
case 'j': case 'j':
case KEY_DOWN: case KEY_DOWN:
if (!end_reached) { if (!end_reached) {
begin_reached = 0; begin_reached = 0;
scrollok(text, TRUE); scrollok(box, TRUE);
scroll(text); /* Scroll text region up one line */ scroll(box); /* Scroll box region up one line */
scrollok(text, FALSE); scrollok(box, FALSE);
print_line(text, height - 5, width - 2); print_line(box, boxh - 1, boxw);
wnoutrefresh(text); wnoutrefresh(box);
print_position(dialog, height, width); print_position(dialog);
wmove(dialog, cur_y, cur_x); /* Restore cursor position */ wmove(dialog, cur_y, cur_x); /* Restore cursor position */
wrefresh(dialog); wrefresh(dialog);
} }
...@@ -257,10 +218,8 @@ int dialog_textbox(const char *title, const char *file, int height, int width) ...@@ -257,10 +218,8 @@ int dialog_textbox(const char *title, const char *file, int height, int width)
break; break;
begin_reached = 0; begin_reached = 0;
print_page(text, height - 4, width - 2); refresh_text_box(dialog, box, boxh, boxw,
print_position(dialog, height, width); cur_y, cur_x);
wmove(dialog, cur_y, cur_x);
wrefresh(dialog);
break; break;
case '0': /* Beginning of line */ case '0': /* Beginning of line */
case 'H': /* Scroll left */ case 'H': /* Scroll left */
...@@ -275,9 +234,8 @@ int dialog_textbox(const char *title, const char *file, int height, int width) ...@@ -275,9 +234,8 @@ int dialog_textbox(const char *title, const char *file, int height, int width)
hscroll--; hscroll--;
/* Reprint current page to scroll horizontally */ /* Reprint current page to scroll horizontally */
back_lines(page_length); back_lines(page_length);
print_page(text, height - 4, width - 2); refresh_text_box(dialog, box, boxh, boxw,
wmove(dialog, cur_y, cur_x); cur_y, cur_x);
wrefresh(dialog);
break; break;
case 'L': /* Scroll right */ case 'L': /* Scroll right */
case 'l': case 'l':
...@@ -287,131 +245,56 @@ int dialog_textbox(const char *title, const char *file, int height, int width) ...@@ -287,131 +245,56 @@ int dialog_textbox(const char *title, const char *file, int height, int width)
hscroll++; hscroll++;
/* Reprint current page to scroll horizontally */ /* Reprint current page to scroll horizontally */
back_lines(page_length); back_lines(page_length);
print_page(text, height - 4, width - 2); refresh_text_box(dialog, box, boxh, boxw,
wmove(dialog, cur_y, cur_x); cur_y, cur_x);
wrefresh(dialog);
break; break;
case ESC: case KEY_ESC:
key = on_key_esc(dialog);
break; break;
case KEY_RESIZE:
back_lines(height);
delwin(box);
delwin(dialog);
on_key_resize();
goto do_resize;
} }
} }
delwin(box);
delwin(dialog); delwin(dialog);
free(buf); return key; /* ESC pressed */
close(fd);
return -1; /* ESC pressed */
} }
/* /*
* Go back 'n' lines in text file. Called by dialog_textbox(). * Go back 'n' lines in text. Called by dialog_textbox().
* 'page' will be updated to point to the desired line in 'buf'. * 'page' will be updated to point to the desired line in 'buf'.
*/ */
static void back_lines(int n) static void back_lines(int n)
{ {
int i, fpos; int i;
begin_reached = 0; begin_reached = 0;
/* We have to distinguish between end_reached and !end_reached /* Go back 'n' lines */
since at end of file, the line is not ended by a '\n'. for (i = 0; i < n; i++) {
The code inside 'if' basically does a '--page' to move one if (*page == '\0') {
character backward so as to skip '\n' of the previous line */ if (end_reached) {
if (!end_reached) { end_reached = 0;
/* Either beginning of buffer or beginning of file reached? */ continue;
if (page == buf) {
if ((fpos = lseek(fd, 0, SEEK_CUR)) == -1) {
endwin();
fprintf(stderr, "\nError moving file pointer in "
"back_lines().\n");
exit(-1);
}
if (fpos > bytes_read) { /* Not beginning of file yet */
/* We've reached beginning of buffer, but not beginning of
file yet, so read previous part of file into buffer.
Note that we only move backward for BUF_SIZE/2 bytes,
but not BUF_SIZE bytes to avoid re-reading again in
print_page() later */
/* Really possible to move backward BUF_SIZE/2 bytes? */
if (fpos < BUF_SIZE / 2 + bytes_read) {
/* No, move less then */
if (lseek(fd, 0, SEEK_SET) == -1) {
endwin();
fprintf(stderr, "\nError moving file pointer in "
"back_lines().\n");
exit(-1);
}
page = buf + fpos - bytes_read;
} else { /* Move backward BUF_SIZE/2 bytes */
if (lseek (fd, -(BUF_SIZE / 2 + bytes_read), SEEK_CUR) == -1) {
endwin();
fprintf(stderr, "\nError moving file pointer "
"in back_lines().\n");
exit(-1);
}
page = buf + BUF_SIZE / 2;
}
if ((bytes_read =
read(fd, buf, BUF_SIZE)) == -1) {
endwin();
fprintf(stderr, "\nError reading file in back_lines().\n");
exit(-1);
}
buf[bytes_read] = '\0';
} else { /* Beginning of file reached */
begin_reached = 1;
return;
} }
} }
if (*(--page) != '\n') { /* '--page' here */ if (page == buf) {
/* Something's wrong... */ begin_reached = 1;
endwin(); return;
fprintf(stderr, "\nInternal error in back_lines().\n");
exit(-1);
} }
} page--;
/* Go back 'n' lines */
for (i = 0; i < n; i++)
do { do {
if (page == buf) { if (page == buf) {
if ((fpos = lseek(fd, 0, SEEK_CUR)) == -1) { begin_reached = 1;
endwin(); return;
fprintf(stderr, "\nError moving file pointer in back_lines().\n");
exit(-1);
}
if (fpos > bytes_read) {
/* Really possible to move backward BUF_SIZE/2 bytes? */
if (fpos < BUF_SIZE / 2 + bytes_read) {
/* No, move less then */
if (lseek(fd, 0, SEEK_SET) == -1) {
endwin();
fprintf(stderr, "\nError moving file pointer "
"in back_lines().\n");
exit(-1);
}
page = buf + fpos - bytes_read;
} else { /* Move backward BUF_SIZE/2 bytes */
if (lseek (fd, -(BUF_SIZE / 2 + bytes_read), SEEK_CUR) == -1) {
endwin();
fprintf(stderr, "\nError moving file pointer"
" in back_lines().\n");
exit(-1);
}
page = buf + BUF_SIZE / 2;
}
if ((bytes_read =
read(fd, buf, BUF_SIZE)) == -1) {
endwin();
fprintf(stderr, "\nError reading file in "
"back_lines().\n");
exit(-1);
}
buf[bytes_read] = '\0';
} else { /* Beginning of file reached */
begin_reached = 1;
return;
}
} }
} while (*(--page) != '\n'); page--;
page++; } while (*page != '\n');
page++;
}
} }
/* /*
...@@ -466,33 +349,14 @@ static void print_line(WINDOW * win, int row, int width) ...@@ -466,33 +349,14 @@ static void print_line(WINDOW * win, int row, int width)
*/ */
static char *get_line(void) static char *get_line(void)
{ {
int i = 0, fpos; int i = 0;
static char line[MAX_LEN + 1]; static char line[MAX_LEN + 1];
end_reached = 0; end_reached = 0;
while (*page != '\n') { while (*page != '\n') {
if (*page == '\0') { if (*page == '\0') {
/* Either end of file or end of buffer reached */ if (!end_reached) {
if ((fpos = lseek(fd, 0, SEEK_CUR)) == -1) { end_reached = 1;
endwin();
fprintf(stderr, "\nError moving file pointer in "
"get_line().\n");
exit(-1);
}
if (fpos < file_size) { /* Not end of file yet */
/* We've reached end of buffer, but not end of file yet,
so read next part of file into buffer */
if ((bytes_read =
read(fd, buf, BUF_SIZE)) == -1) {
endwin();
fprintf(stderr, "\nError reading file in get_line().\n");
exit(-1);
}
buf[bytes_read] = '\0';
page = buf;
} else {
if (!end_reached)
end_reached = 1;
break; break;
} }
} else if (i < MAX_LEN) } else if (i < MAX_LEN)
...@@ -515,19 +379,13 @@ static char *get_line(void) ...@@ -515,19 +379,13 @@ static char *get_line(void)
/* /*
* Print current position * Print current position
*/ */
static void print_position(WINDOW * win, int height, int width) static void print_position(WINDOW * win)
{ {
int fpos, percent; int percent;
if ((fpos = lseek(fd, 0, SEEK_CUR)) == -1) { wattrset(win, dlg.position_indicator.atr);
endwin(); wbkgdset(win, dlg.position_indicator.atr & A_COLOR);
fprintf(stderr, "\nError moving file pointer in print_position().\n"); percent = (page - buf) * 100 / strlen(buf);
exit(-1); wmove(win, getmaxy(win) - 3, getmaxx(win) - 9);
}
wattrset(win, position_indicator_attr);
wbkgdset(win, position_indicator_attr & A_COLOR);
percent = !file_size ?
100 : ((fpos - bytes_read + page - buf) * 100) / file_size;
wmove(win, height - 3, width - 9);
wprintw(win, "(%3d%%)", percent); wprintw(win, "(%3d%%)", percent);
} }
...@@ -21,85 +21,217 @@ ...@@ -21,85 +21,217 @@
#include "dialog.h" #include "dialog.h"
/* use colors by default? */ struct dialog_info dlg;
bool use_colors = 1;
const char *backtitle = NULL; static void set_mono_theme(void)
{
dlg.screen.atr = A_NORMAL;
dlg.shadow.atr = A_NORMAL;
dlg.dialog.atr = A_NORMAL;
dlg.title.atr = A_BOLD;
dlg.border.atr = A_NORMAL;
dlg.button_active.atr = A_REVERSE;
dlg.button_inactive.atr = A_DIM;
dlg.button_key_active.atr = A_REVERSE;
dlg.button_key_inactive.atr = A_BOLD;
dlg.button_label_active.atr = A_REVERSE;
dlg.button_label_inactive.atr = A_NORMAL;
dlg.inputbox.atr = A_NORMAL;
dlg.inputbox_border.atr = A_NORMAL;
dlg.searchbox.atr = A_NORMAL;
dlg.searchbox_title.atr = A_BOLD;
dlg.searchbox_border.atr = A_NORMAL;
dlg.position_indicator.atr = A_BOLD;
dlg.menubox.atr = A_NORMAL;
dlg.menubox_border.atr = A_NORMAL;
dlg.item.atr = A_NORMAL;
dlg.item_selected.atr = A_REVERSE;
dlg.tag.atr = A_BOLD;
dlg.tag_selected.atr = A_REVERSE;
dlg.tag_key.atr = A_BOLD;
dlg.tag_key_selected.atr = A_REVERSE;
dlg.check.atr = A_BOLD;
dlg.check_selected.atr = A_REVERSE;
dlg.uarrow.atr = A_BOLD;
dlg.darrow.atr = A_BOLD;
}
#define DLG_COLOR(dialog, f, b, h) \
do { \
dlg.dialog.fg = (f); \
dlg.dialog.bg = (b); \
dlg.dialog.hl = (h); \
} while (0)
static void set_classic_theme(void)
{
DLG_COLOR(screen, COLOR_CYAN, COLOR_BLUE, true);
DLG_COLOR(shadow, COLOR_BLACK, COLOR_BLACK, true);
DLG_COLOR(dialog, COLOR_BLACK, COLOR_WHITE, false);
DLG_COLOR(title, COLOR_YELLOW, COLOR_WHITE, true);
DLG_COLOR(border, COLOR_WHITE, COLOR_WHITE, true);
DLG_COLOR(button_active, COLOR_WHITE, COLOR_BLUE, true);
DLG_COLOR(button_inactive, COLOR_BLACK, COLOR_WHITE, false);
DLG_COLOR(button_key_active, COLOR_WHITE, COLOR_BLUE, true);
DLG_COLOR(button_key_inactive, COLOR_RED, COLOR_WHITE, false);
DLG_COLOR(button_label_active, COLOR_YELLOW, COLOR_BLUE, true);
DLG_COLOR(button_label_inactive, COLOR_BLACK, COLOR_WHITE, true);
DLG_COLOR(inputbox, COLOR_BLACK, COLOR_WHITE, false);
DLG_COLOR(inputbox_border, COLOR_BLACK, COLOR_WHITE, false);
DLG_COLOR(searchbox, COLOR_BLACK, COLOR_WHITE, false);
DLG_COLOR(searchbox_title, COLOR_YELLOW, COLOR_WHITE, true);
DLG_COLOR(searchbox_border, COLOR_WHITE, COLOR_WHITE, true);
DLG_COLOR(position_indicator, COLOR_YELLOW, COLOR_WHITE, true);
DLG_COLOR(menubox, COLOR_BLACK, COLOR_WHITE, false);
DLG_COLOR(menubox_border, COLOR_WHITE, COLOR_WHITE, true);
DLG_COLOR(item, COLOR_BLACK, COLOR_WHITE, false);
DLG_COLOR(item_selected, COLOR_WHITE, COLOR_BLUE, true);
DLG_COLOR(tag, COLOR_YELLOW, COLOR_WHITE, true);
DLG_COLOR(tag_selected, COLOR_YELLOW, COLOR_BLUE, true);
DLG_COLOR(tag_key, COLOR_YELLOW, COLOR_WHITE, true);
DLG_COLOR(tag_key_selected, COLOR_YELLOW, COLOR_BLUE, true);
DLG_COLOR(check, COLOR_BLACK, COLOR_WHITE, false);
DLG_COLOR(check_selected, COLOR_WHITE, COLOR_BLUE, true);
DLG_COLOR(uarrow, COLOR_GREEN, COLOR_WHITE, true);
DLG_COLOR(darrow, COLOR_GREEN, COLOR_WHITE, true);
}
static void set_blackbg_theme(void)
{
DLG_COLOR(screen, COLOR_RED, COLOR_BLACK, true);
DLG_COLOR(shadow, COLOR_BLACK, COLOR_BLACK, false);
DLG_COLOR(dialog, COLOR_WHITE, COLOR_BLACK, false);
DLG_COLOR(title, COLOR_RED, COLOR_BLACK, false);
DLG_COLOR(border, COLOR_BLACK, COLOR_BLACK, true);
DLG_COLOR(button_active, COLOR_YELLOW, COLOR_RED, false);
DLG_COLOR(button_inactive, COLOR_YELLOW, COLOR_BLACK, false);
DLG_COLOR(button_key_active, COLOR_YELLOW, COLOR_RED, true);
DLG_COLOR(button_key_inactive, COLOR_RED, COLOR_BLACK, false);
DLG_COLOR(button_label_active, COLOR_WHITE, COLOR_RED, false);
DLG_COLOR(button_label_inactive, COLOR_BLACK, COLOR_BLACK, true);
DLG_COLOR(inputbox, COLOR_YELLOW, COLOR_BLACK, false);
DLG_COLOR(inputbox_border, COLOR_YELLOW, COLOR_BLACK, false);
DLG_COLOR(searchbox, COLOR_YELLOW, COLOR_BLACK, false);
DLG_COLOR(searchbox_title, COLOR_YELLOW, COLOR_BLACK, true);
DLG_COLOR(searchbox_border, COLOR_BLACK, COLOR_BLACK, true);
DLG_COLOR(position_indicator, COLOR_RED, COLOR_BLACK, false);
DLG_COLOR(menubox, COLOR_YELLOW, COLOR_BLACK, false);
DLG_COLOR(menubox_border, COLOR_BLACK, COLOR_BLACK, true);
DLG_COLOR(item, COLOR_WHITE, COLOR_BLACK, false);
DLG_COLOR(item_selected, COLOR_WHITE, COLOR_RED, false);
DLG_COLOR(tag, COLOR_RED, COLOR_BLACK, false);
DLG_COLOR(tag_selected, COLOR_YELLOW, COLOR_RED, true);
DLG_COLOR(tag_key, COLOR_RED, COLOR_BLACK, false);
DLG_COLOR(tag_key_selected, COLOR_YELLOW, COLOR_RED, true);
DLG_COLOR(check, COLOR_YELLOW, COLOR_BLACK, false);
DLG_COLOR(check_selected, COLOR_YELLOW, COLOR_RED, true);
DLG_COLOR(uarrow, COLOR_RED, COLOR_BLACK, false);
DLG_COLOR(darrow, COLOR_RED, COLOR_BLACK, false);
}
static void set_bluetitle_theme(void)
{
set_classic_theme();
DLG_COLOR(title, COLOR_BLUE, COLOR_WHITE, true);
DLG_COLOR(button_key_active, COLOR_YELLOW, COLOR_BLUE, true);
DLG_COLOR(button_label_active, COLOR_WHITE, COLOR_BLUE, true);
DLG_COLOR(searchbox_title, COLOR_BLUE, COLOR_WHITE, true);
DLG_COLOR(position_indicator, COLOR_BLUE, COLOR_WHITE, true);
DLG_COLOR(tag, COLOR_BLUE, COLOR_WHITE, true);
DLG_COLOR(tag_key, COLOR_BLUE, COLOR_WHITE, true);
}
/* /*
* Attribute values, default is for mono display * Select color theme
*/ */
chtype attributes[] = { static int set_theme(const char *theme)
A_NORMAL, /* screen_attr */ {
A_NORMAL, /* shadow_attr */ int use_color = 1;
A_NORMAL, /* dialog_attr */ if (!theme)
A_BOLD, /* title_attr */ set_bluetitle_theme();
A_NORMAL, /* border_attr */ else if (strcmp(theme, "classic") == 0)
A_REVERSE, /* button_active_attr */ set_classic_theme();
A_DIM, /* button_inactive_attr */ else if (strcmp(theme, "bluetitle") == 0)
A_REVERSE, /* button_key_active_attr */ set_bluetitle_theme();
A_BOLD, /* button_key_inactive_attr */ else if (strcmp(theme, "blackbg") == 0)
A_REVERSE, /* button_label_active_attr */ set_blackbg_theme();
A_NORMAL, /* button_label_inactive_attr */ else if (strcmp(theme, "mono") == 0)
A_NORMAL, /* inputbox_attr */ use_color = 0;
A_NORMAL, /* inputbox_border_attr */
A_NORMAL, /* searchbox_attr */ return use_color;
A_BOLD, /* searchbox_title_attr */ }
A_NORMAL, /* searchbox_border_attr */
A_BOLD, /* position_indicator_attr */ static void init_one_color(struct dialog_color *color)
A_NORMAL, /* menubox_attr */ {
A_NORMAL, /* menubox_border_attr */ static int pair = 0;
A_NORMAL, /* item_attr */
A_REVERSE, /* item_selected_attr */ pair++;
A_BOLD, /* tag_attr */ init_pair(pair, color->fg, color->bg);
A_REVERSE, /* tag_selected_attr */ if (color->hl)
A_BOLD, /* tag_key_attr */ color->atr = A_BOLD | COLOR_PAIR(pair);
A_REVERSE, /* tag_key_selected_attr */ else
A_BOLD, /* check_attr */ color->atr = COLOR_PAIR(pair);
A_REVERSE, /* check_selected_attr */ }
A_BOLD, /* uarrow_attr */
A_BOLD /* darrow_attr */ static void init_dialog_colors(void)
}; {
init_one_color(&dlg.screen);
#include "colors.h" init_one_color(&dlg.shadow);
init_one_color(&dlg.dialog);
init_one_color(&dlg.title);
init_one_color(&dlg.border);
init_one_color(&dlg.button_active);
init_one_color(&dlg.button_inactive);
init_one_color(&dlg.button_key_active);
init_one_color(&dlg.button_key_inactive);
init_one_color(&dlg.button_label_active);
init_one_color(&dlg.button_label_inactive);
init_one_color(&dlg.inputbox);
init_one_color(&dlg.inputbox_border);
init_one_color(&dlg.searchbox);
init_one_color(&dlg.searchbox_title);
init_one_color(&dlg.searchbox_border);
init_one_color(&dlg.position_indicator);
init_one_color(&dlg.menubox);
init_one_color(&dlg.menubox_border);
init_one_color(&dlg.item);
init_one_color(&dlg.item_selected);
init_one_color(&dlg.tag);
init_one_color(&dlg.tag_selected);
init_one_color(&dlg.tag_key);
init_one_color(&dlg.tag_key_selected);
init_one_color(&dlg.check);
init_one_color(&dlg.check_selected);
init_one_color(&dlg.uarrow);
init_one_color(&dlg.darrow);
}
/* /*
* Table of color values * Setup for color display
*/ */
int color_table[][3] = { static void color_setup(const char *theme)
{SCREEN_FG, SCREEN_BG, SCREEN_HL}, {
{SHADOW_FG, SHADOW_BG, SHADOW_HL}, if (set_theme(theme)) {
{DIALOG_FG, DIALOG_BG, DIALOG_HL}, if (has_colors()) { /* Terminal supports color? */
{TITLE_FG, TITLE_BG, TITLE_HL}, start_color();
{BORDER_FG, BORDER_BG, BORDER_HL}, init_dialog_colors();
{BUTTON_ACTIVE_FG, BUTTON_ACTIVE_BG, BUTTON_ACTIVE_HL}, }
{BUTTON_INACTIVE_FG, BUTTON_INACTIVE_BG, BUTTON_INACTIVE_HL}, }
{BUTTON_KEY_ACTIVE_FG, BUTTON_KEY_ACTIVE_BG, BUTTON_KEY_ACTIVE_HL}, else
{BUTTON_KEY_INACTIVE_FG, BUTTON_KEY_INACTIVE_BG, {
BUTTON_KEY_INACTIVE_HL}, set_mono_theme();
{BUTTON_LABEL_ACTIVE_FG, BUTTON_LABEL_ACTIVE_BG, }
BUTTON_LABEL_ACTIVE_HL}, }
{BUTTON_LABEL_INACTIVE_FG, BUTTON_LABEL_INACTIVE_BG,
BUTTON_LABEL_INACTIVE_HL},
{INPUTBOX_FG, INPUTBOX_BG, INPUTBOX_HL},
{INPUTBOX_BORDER_FG, INPUTBOX_BORDER_BG, INPUTBOX_BORDER_HL},
{SEARCHBOX_FG, SEARCHBOX_BG, SEARCHBOX_HL},
{SEARCHBOX_TITLE_FG, SEARCHBOX_TITLE_BG, SEARCHBOX_TITLE_HL},
{SEARCHBOX_BORDER_FG, SEARCHBOX_BORDER_BG, SEARCHBOX_BORDER_HL},
{POSITION_INDICATOR_FG, POSITION_INDICATOR_BG, POSITION_INDICATOR_HL},
{MENUBOX_FG, MENUBOX_BG, MENUBOX_HL},
{MENUBOX_BORDER_FG, MENUBOX_BORDER_BG, MENUBOX_BORDER_HL},
{ITEM_FG, ITEM_BG, ITEM_HL},
{ITEM_SELECTED_FG, ITEM_SELECTED_BG, ITEM_SELECTED_HL},
{TAG_FG, TAG_BG, TAG_HL},
{TAG_SELECTED_FG, TAG_SELECTED_BG, TAG_SELECTED_HL},
{TAG_KEY_FG, TAG_KEY_BG, TAG_KEY_HL},
{TAG_KEY_SELECTED_FG, TAG_KEY_SELECTED_BG, TAG_KEY_SELECTED_HL},
{CHECK_FG, CHECK_BG, CHECK_HL},
{CHECK_SELECTED_FG, CHECK_SELECTED_BG, CHECK_SELECTED_HL},
{UARROW_FG, UARROW_BG, UARROW_HL},
{DARROW_FG, DARROW_BG, DARROW_HL},
}; /* color_table */
/* /*
* Set window to attribute 'attr' * Set window to attribute 'attr'
...@@ -119,13 +251,13 @@ void attr_clear(WINDOW * win, int height, int width, chtype attr) ...@@ -119,13 +251,13 @@ void attr_clear(WINDOW * win, int height, int width, chtype attr)
void dialog_clear(void) void dialog_clear(void)
{ {
attr_clear(stdscr, LINES, COLS, screen_attr); attr_clear(stdscr, LINES, COLS, dlg.screen.atr);
/* Display background title if it exists ... - SLH */ /* Display background title if it exists ... - SLH */
if (backtitle != NULL) { if (dlg.backtitle != NULL) {
int i; int i;
wattrset(stdscr, screen_attr); wattrset(stdscr, dlg.screen.atr);
mvwaddstr(stdscr, 0, 1, (char *)backtitle); mvwaddstr(stdscr, 0, 1, (char *)dlg.backtitle);
wmove(stdscr, 1, 1); wmove(stdscr, 1, 1);
for (i = 1; i < COLS - 1; i++) for (i = 1; i < COLS - 1; i++)
waddch(stdscr, ACS_HLINE); waddch(stdscr, ACS_HLINE);
...@@ -136,39 +268,21 @@ void dialog_clear(void) ...@@ -136,39 +268,21 @@ void dialog_clear(void)
/* /*
* Do some initialization for dialog * Do some initialization for dialog
*/ */
void init_dialog(void) void init_dialog(const char *backtitle)
{
dlg.backtitle = backtitle;
color_setup(getenv("MENUCONFIG_COLOR"));
}
void reset_dialog(void)
{ {
initscr(); /* Init curses */ initscr(); /* Init curses */
keypad(stdscr, TRUE); keypad(stdscr, TRUE);
cbreak(); cbreak();
noecho(); noecho();
if (use_colors) /* Set up colors */
color_setup();
dialog_clear(); dialog_clear();
} }
/*
* Setup for color display
*/
void color_setup(void)
{
int i;
if (has_colors()) { /* Terminal supports color? */
start_color();
/* Initialize color pairs */
for (i = 0; i < ATTRIBUTE_COUNT; i++)
init_pair(i + 1, color_table[i][0], color_table[i][1]);
/* Setup color attributes */
for (i = 0; i < ATTRIBUTE_COUNT; i++)
attributes[i] = C_ATTR(color_table[i][2], i + 1);
}
}
/* /*
* End using dialog functions. * End using dialog functions.
*/ */
...@@ -184,7 +298,7 @@ void print_title(WINDOW *dialog, const char *title, int width) ...@@ -184,7 +298,7 @@ void print_title(WINDOW *dialog, const char *title, int width)
{ {
if (title) { if (title) {
int tlen = MIN(width - 2, strlen(title)); int tlen = MIN(width - 2, strlen(title));
wattrset(dialog, title_attr); wattrset(dialog, dlg.title.atr);
mvwaddch(dialog, 0, (width - tlen) / 2 - 1, ' '); mvwaddch(dialog, 0, (width - tlen) / 2 - 1, ' ');
mvwaddnstr(dialog, 0, (width - tlen)/2, title, tlen); mvwaddnstr(dialog, 0, (width - tlen)/2, title, tlen);
waddch(dialog, ' '); waddch(dialog, ' ');
...@@ -264,21 +378,23 @@ void print_button(WINDOW * win, const char *label, int y, int x, int selected) ...@@ -264,21 +378,23 @@ void print_button(WINDOW * win, const char *label, int y, int x, int selected)
int i, temp; int i, temp;
wmove(win, y, x); wmove(win, y, x);
wattrset(win, selected ? button_active_attr : button_inactive_attr); wattrset(win, selected ? dlg.button_active.atr
: dlg.button_inactive.atr);
waddstr(win, "<"); waddstr(win, "<");
temp = strspn(label, " "); temp = strspn(label, " ");
label += temp; label += temp;
wattrset(win, selected ? button_label_active_attr wattrset(win, selected ? dlg.button_label_active.atr
: button_label_inactive_attr); : dlg.button_label_inactive.atr);
for (i = 0; i < temp; i++) for (i = 0; i < temp; i++)
waddch(win, ' '); waddch(win, ' ');
wattrset(win, selected ? button_key_active_attr wattrset(win, selected ? dlg.button_key_active.atr
: button_key_inactive_attr); : dlg.button_key_inactive.atr);
waddch(win, label[0]); waddch(win, label[0]);
wattrset(win, selected ? button_label_active_attr wattrset(win, selected ? dlg.button_label_active.atr
: button_label_inactive_attr); : dlg.button_label_inactive.atr);
waddstr(win, (char *)label + 1); waddstr(win, (char *)label + 1);
wattrset(win, selected ? button_active_attr : button_inactive_attr); wattrset(win, selected ? dlg.button_active.atr
: dlg.button_inactive.atr);
waddstr(win, ">"); waddstr(win, ">");
wmove(win, y, x + temp + 1); wmove(win, y, x + temp + 1);
} }
...@@ -326,7 +442,7 @@ void draw_shadow(WINDOW * win, int y, int x, int height, int width) ...@@ -326,7 +442,7 @@ void draw_shadow(WINDOW * win, int y, int x, int height, int width)
int i; int i;
if (has_colors()) { /* Whether terminal supports color? */ if (has_colors()) { /* Whether terminal supports color? */
wattrset(win, shadow_attr); wattrset(win, dlg.shadow.atr);
wmove(win, y + height, x + 2); wmove(win, y + height, x + 2);
for (i = 0; i < width; i++) for (i = 0; i < width; i++)
waddch(win, winch(win) & A_CHARTEXT); waddch(win, winch(win) & A_CHARTEXT);
...@@ -360,3 +476,167 @@ int first_alpha(const char *string, const char *exempt) ...@@ -360,3 +476,167 @@ int first_alpha(const char *string, const char *exempt)
return 0; return 0;
} }
/*
* ncurses uses ESC to detect escaped char sequences. This resutl in
* a small timeout before ESC is actually delivered to the application.
* lxdialog suggest <ESC> <ESC> which is correctly translated to two
* times esc. But then we need to ignore the second esc to avoid stepping
* out one menu too much. Filter away all escaped key sequences since
* keypad(FALSE) turn off ncurses support for escape sequences - and thats
* needed to make notimeout() do as expected.
*/
int on_key_esc(WINDOW *win)
{
int key;
int key2;
int key3;
nodelay(win, TRUE);
keypad(win, FALSE);
key = wgetch(win);
key2 = wgetch(win);
do {
key3 = wgetch(win);
} while (key3 != ERR);
nodelay(win, FALSE);
keypad(win, TRUE);
if (key == KEY_ESC && key2 == ERR)
return KEY_ESC;
else if (key != ERR && key != KEY_ESC && key2 == ERR)
ungetch(key);
return -1;
}
/* redraw screen in new size */
int on_key_resize(void)
{
dialog_clear();
return KEY_RESIZE;
}
struct dialog_list *item_cur;
struct dialog_list item_nil;
struct dialog_list *item_head;
void item_reset(void)
{
struct dialog_list *p, *next;
for (p = item_head; p; p = next) {
next = p->next;
free(p);
}
item_head = NULL;
item_cur = &item_nil;
}
void item_make(const char *fmt, ...)
{
va_list ap;
struct dialog_list *p = malloc(sizeof(*p));
if (item_head)
item_cur->next = p;
else
item_head = p;
item_cur = p;
memset(p, 0, sizeof(*p));
va_start(ap, fmt);
vsnprintf(item_cur->node.str, sizeof(item_cur->node.str), fmt, ap);
va_end(ap);
}
void item_add_str(const char *fmt, ...)
{
va_list ap;
size_t avail;
avail = sizeof(item_cur->node.str) - strlen(item_cur->node.str);
va_start(ap, fmt);
vsnprintf(item_cur->node.str + strlen(item_cur->node.str),
avail, fmt, ap);
item_cur->node.str[sizeof(item_cur->node.str) - 1] = '\0';
va_end(ap);
}
void item_set_tag(char tag)
{
item_cur->node.tag = tag;
}
void item_set_data(void *ptr)
{
item_cur->node.data = ptr;
}
void item_set_selected(int val)
{
item_cur->node.selected = val;
}
int item_activate_selected(void)
{
item_foreach()
if (item_is_selected())
return 1;
return 0;
}
void *item_data(void)
{
return item_cur->node.data;
}
char item_tag(void)
{
return item_cur->node.tag;
}
int item_count(void)
{
int n = 0;
struct dialog_list *p;
for (p = item_head; p; p = p->next)
n++;
return n;
}
void item_set(int n)
{
int i = 0;
item_foreach()
if (i++ == n)
return;
}
int item_n(void)
{
int n = 0;
struct dialog_list *p;
for (p = item_head; p; p = p->next) {
if (p == item_cur)
return n;
n++;
}
return 0;
}
const char *item_str(void)
{
return item_cur->node.str;
}
int item_is_selected(void)
{
return (item_cur->node.selected != 0);
}
int item_is_tag(char tag)
{
return (item_cur->node.tag == tag);
}
...@@ -44,6 +44,12 @@ int dialog_yesno(const char *title, const char *prompt, int height, int width) ...@@ -44,6 +44,12 @@ int dialog_yesno(const char *title, const char *prompt, int height, int width)
int i, x, y, key = 0, button = 0; int i, x, y, key = 0, button = 0;
WINDOW *dialog; WINDOW *dialog;
do_resize:
if (getmaxy(stdscr) < (height + 4))
return -ERRDISPLAYTOOSMALL;
if (getmaxx(stdscr) < (width + 4))
return -ERRDISPLAYTOOSMALL;
/* center dialog box on screen */ /* center dialog box on screen */
x = (COLS - width) / 2; x = (COLS - width) / 2;
y = (LINES - height) / 2; y = (LINES - height) / 2;
...@@ -53,22 +59,23 @@ int dialog_yesno(const char *title, const char *prompt, int height, int width) ...@@ -53,22 +59,23 @@ int dialog_yesno(const char *title, const char *prompt, int height, int width)
dialog = newwin(height, width, y, x); dialog = newwin(height, width, y, x);
keypad(dialog, TRUE); keypad(dialog, TRUE);
draw_box(dialog, 0, 0, height, width, dialog_attr, border_attr); draw_box(dialog, 0, 0, height, width,
wattrset(dialog, border_attr); dlg.dialog.atr, dlg.border.atr);
wattrset(dialog, dlg.border.atr);
mvwaddch(dialog, height - 3, 0, ACS_LTEE); mvwaddch(dialog, height - 3, 0, ACS_LTEE);
for (i = 0; i < width - 2; i++) for (i = 0; i < width - 2; i++)
waddch(dialog, ACS_HLINE); waddch(dialog, ACS_HLINE);
wattrset(dialog, dialog_attr); wattrset(dialog, dlg.dialog.atr);
waddch(dialog, ACS_RTEE); waddch(dialog, ACS_RTEE);
print_title(dialog, title, width); print_title(dialog, title, width);
wattrset(dialog, dialog_attr); wattrset(dialog, dlg.dialog.atr);
print_autowrap(dialog, prompt, width - 2, 1, 3); print_autowrap(dialog, prompt, width - 2, 1, 3);
print_buttons(dialog, height, width, 0); print_buttons(dialog, height, width, 0);
while (key != ESC) { while (key != KEY_ESC) {
key = wgetch(dialog); key = wgetch(dialog);
switch (key) { switch (key) {
case 'Y': case 'Y':
...@@ -92,11 +99,16 @@ int dialog_yesno(const char *title, const char *prompt, int height, int width) ...@@ -92,11 +99,16 @@ int dialog_yesno(const char *title, const char *prompt, int height, int width)
case '\n': case '\n':
delwin(dialog); delwin(dialog);
return button; return button;
case ESC: case KEY_ESC:
key = on_key_esc(dialog);
break; break;
case KEY_RESIZE:
delwin(dialog);
on_key_resize();
goto do_resize;
} }
} }
delwin(dialog); delwin(dialog);
return -1; /* ESC pressed */ return key; /* ESC pressed */
} }
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#define LKC_DIRECT_LINK #define LKC_DIRECT_LINK
#include "lkc.h" #include "lkc.h"
#include "lxdialog/dialog.h"
static char menu_backtitle[128]; static char menu_backtitle[128];
static const char mconf_readme[] = N_( static const char mconf_readme[] = N_(
...@@ -159,7 +160,21 @@ static const char mconf_readme[] = N_( ...@@ -159,7 +160,21 @@ static const char mconf_readme[] = N_(
"\n" "\n"
"Note that this mode can eventually be a little more CPU expensive\n" "Note that this mode can eventually be a little more CPU expensive\n"
"(especially with a larger number of unrolled categories) than the\n" "(especially with a larger number of unrolled categories) than the\n"
"default mode.\n"), "default mode.\n"
"\n"
"Different color themes available\n"
"--------------------------------\n"
"It is possible to select different color themes using the variable\n"
"MENUCONFIG_COLOR. To select a theme use:\n"
"\n"
"make MENUCONFIG_COLOR=<theme> menuconfig\n"
"\n"
"Available themes are\n"
" mono => selects colors suitable for monochrome displays\n"
" blackbg => selects a color scheme with black background\n"
" classic => theme with blue background. The classic look\n"
" bluetitle => a LCD friendly version of classic. (default)\n"
"\n"),
menu_instructions[] = N_( menu_instructions[] = N_(
"Arrow keys navigate the menu. " "Arrow keys navigate the menu. "
"<Enter> selects submenus --->. " "<Enter> selects submenus --->. "
...@@ -256,16 +271,12 @@ search_help[] = N_( ...@@ -256,16 +271,12 @@ search_help[] = N_(
" USB$ => find all CONFIG_ symbols ending with USB\n" " USB$ => find all CONFIG_ symbols ending with USB\n"
"\n"); "\n");
static char buf[4096], *bufptr = buf;
static char input_buf[4096];
static char filename[PATH_MAX+1] = ".config"; static char filename[PATH_MAX+1] = ".config";
static char *args[1024], **argptr = args;
static int indent; static int indent;
static struct termios ios_org; static struct termios ios_org;
static int rows = 0, cols = 0; static int rows = 0, cols = 0;
static struct menu *current_menu; static struct menu *current_menu;
static int child_count; static int child_count;
static int do_resize;
static int single_menu_mode; static int single_menu_mode;
static void conf(struct menu *menu); static void conf(struct menu *menu);
...@@ -276,12 +287,6 @@ static void conf_save(void); ...@@ -276,12 +287,6 @@ static void conf_save(void);
static void show_textbox(const char *title, const char *text, int r, int c); static void show_textbox(const char *title, const char *text, int r, int c);
static void show_helptext(const char *title, const char *text); static void show_helptext(const char *title, const char *text);
static void show_help(struct menu *menu); static void show_help(struct menu *menu);
static void show_file(const char *filename, const char *title, int r, int c);
static void cprint_init(void);
static int cprint1(const char *fmt, ...);
static void cprint_done(void);
static int cprint(const char *fmt, ...);
static void init_wsize(void) static void init_wsize(void)
{ {
...@@ -318,54 +323,6 @@ static void init_wsize(void) ...@@ -318,54 +323,6 @@ static void init_wsize(void)
cols -= 5; cols -= 5;
} }
static void cprint_init(void)
{
bufptr = buf;
argptr = args;
memset(args, 0, sizeof(args));
indent = 0;
child_count = 0;
cprint("./scripts/kconfig/lxdialog/lxdialog");
cprint("--backtitle");
cprint(menu_backtitle);
}
static int cprint1(const char *fmt, ...)
{
va_list ap;
int res;
if (!*argptr)
*argptr = bufptr;
va_start(ap, fmt);
res = vsprintf(bufptr, fmt, ap);
va_end(ap);
bufptr += res;
return res;
}
static void cprint_done(void)
{
*bufptr++ = 0;
argptr++;
}
static int cprint(const char *fmt, ...)
{
va_list ap;
int res;
*argptr++ = bufptr;
va_start(ap, fmt);
res = vsprintf(bufptr, fmt, ap);
va_end(ap);
bufptr += res;
*bufptr++ = 0;
return res;
}
static void get_prompt_str(struct gstr *r, struct property *prop) static void get_prompt_str(struct gstr *r, struct property *prop)
{ {
int i, j; int i, j;
...@@ -438,108 +395,17 @@ static struct gstr get_relations_str(struct symbol **sym_arr) ...@@ -438,108 +395,17 @@ static struct gstr get_relations_str(struct symbol **sym_arr)
return res; return res;
} }
pid_t pid;
static void winch_handler(int sig)
{
if (!do_resize) {
kill(pid, SIGINT);
do_resize = 1;
}
}
static int exec_conf(void)
{
int pipefd[2], stat, size;
struct sigaction sa;
sigset_t sset, osset;
sigemptyset(&sset);
sigaddset(&sset, SIGINT);
sigprocmask(SIG_BLOCK, &sset, &osset);
signal(SIGINT, SIG_DFL);
sa.sa_handler = winch_handler;
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_RESTART;
sigaction(SIGWINCH, &sa, NULL);
*argptr++ = NULL;
pipe(pipefd);
pid = fork();
if (pid == 0) {
sigprocmask(SIG_SETMASK, &osset, NULL);
dup2(pipefd[1], 2);
close(pipefd[0]);
close(pipefd[1]);
execv(args[0], args);
_exit(EXIT_FAILURE);
}
close(pipefd[1]);
bufptr = input_buf;
while (1) {
size = input_buf + sizeof(input_buf) - bufptr;
size = read(pipefd[0], bufptr, size);
if (size <= 0) {
if (size < 0) {
if (errno == EINTR || errno == EAGAIN)
continue;
perror("read");
}
break;
}
bufptr += size;
}
*bufptr++ = 0;
close(pipefd[0]);
waitpid(pid, &stat, 0);
if (do_resize) {
init_wsize();
do_resize = 0;
sigprocmask(SIG_SETMASK, &osset, NULL);
return -1;
}
if (WIFSIGNALED(stat)) {
printf("\finterrupted(%d)\n", WTERMSIG(stat));
exit(1);
}
#if 0
printf("\fexit state: %d\nexit data: '%s'\n", WEXITSTATUS(stat), input_buf);
sleep(1);
#endif
sigpending(&sset);
if (sigismember(&sset, SIGINT)) {
printf("\finterrupted\n");
exit(1);
}
sigprocmask(SIG_SETMASK, &osset, NULL);
return WEXITSTATUS(stat);
}
static void search_conf(void) static void search_conf(void)
{ {
struct symbol **sym_arr; struct symbol **sym_arr;
int stat;
struct gstr res; struct gstr res;
int dres;
again: again:
cprint_init(); dialog_clear();
cprint("--title"); dres = dialog_inputbox(_("Search Configuration Parameter"),
cprint(_("Search Configuration Parameter")); _("Enter CONFIG_ (sub)string to search for (omit CONFIG_)"),
cprint("--inputbox"); 10, 75, "");
cprint(_("Enter CONFIG_ (sub)string to search for (omit CONFIG_)")); switch (dres) {
cprint("10");
cprint("75");
cprint("");
stat = exec_conf();
if (stat < 0)
goto again;
switch (stat) {
case 0: case 0:
break; break;
case 1: case 1:
...@@ -549,7 +415,7 @@ static void search_conf(void) ...@@ -549,7 +415,7 @@ static void search_conf(void)
return; return;
} }
sym_arr = sym_re_search(input_buf); sym_arr = sym_re_search(dialog_input_result);
res = get_relations_str(sym_arr); res = get_relations_str(sym_arr);
free(sym_arr); free(sym_arr);
show_textbox(_("Search Results"), str_get(&res), 0, 0); show_textbox(_("Search Results"), str_get(&res), 0, 0);
...@@ -576,24 +442,24 @@ static void build_conf(struct menu *menu) ...@@ -576,24 +442,24 @@ static void build_conf(struct menu *menu)
switch (prop->type) { switch (prop->type) {
case P_MENU: case P_MENU:
child_count++; child_count++;
cprint("m%p", menu);
if (single_menu_mode) { if (single_menu_mode) {
cprint1("%s%*c%s", item_make("%s%*c%s",
menu->data ? "-->" : "++>", menu->data ? "-->" : "++>",
indent + 1, ' ', prompt); indent + 1, ' ', prompt);
} else } else
cprint1(" %*c%s --->", indent + 1, ' ', prompt); item_make(" %*c%s --->", indent + 1, ' ', prompt);
cprint_done(); item_set_tag('m');
item_set_data(menu);
if (single_menu_mode && menu->data) if (single_menu_mode && menu->data)
goto conf_childs; goto conf_childs;
return; return;
default: default:
if (prompt) { if (prompt) {
child_count++; child_count++;
cprint(":%p", menu); item_make("---%*c%s", indent + 1, ' ', prompt);
cprint("---%*c%s", indent + 1, ' ', prompt); item_set_tag(':');
item_set_data(menu);
} }
} }
} else } else
...@@ -614,10 +480,9 @@ static void build_conf(struct menu *menu) ...@@ -614,10 +480,9 @@ static void build_conf(struct menu *menu)
val = sym_get_tristate_value(sym); val = sym_get_tristate_value(sym);
if (sym_is_changable(sym)) { if (sym_is_changable(sym)) {
cprint("t%p", menu);
switch (type) { switch (type) {
case S_BOOLEAN: case S_BOOLEAN:
cprint1("[%c]", val == no ? ' ' : '*'); item_make("[%c]", val == no ? ' ' : '*');
break; break;
case S_TRISTATE: case S_TRISTATE:
switch (val) { switch (val) {
...@@ -625,84 +490,87 @@ static void build_conf(struct menu *menu) ...@@ -625,84 +490,87 @@ static void build_conf(struct menu *menu)
case mod: ch = 'M'; break; case mod: ch = 'M'; break;
default: ch = ' '; break; default: ch = ' '; break;
} }
cprint1("<%c>", ch); item_make("<%c>", ch);
break; break;
} }
item_set_tag('t');
item_set_data(menu);
} else { } else {
cprint("%c%p", def_menu ? 't' : ':', menu); item_make(" ");
cprint1(" "); item_set_tag(def_menu ? 't' : ':');
item_set_data(menu);
} }
cprint1("%*c%s", indent + 1, ' ', menu_get_prompt(menu)); item_add_str("%*c%s", indent + 1, ' ', menu_get_prompt(menu));
if (val == yes) { if (val == yes) {
if (def_menu) { if (def_menu) {
cprint1(" (%s)", menu_get_prompt(def_menu)); item_add_str(" (%s)", menu_get_prompt(def_menu));
cprint1(" --->"); item_add_str(" --->");
cprint_done();
if (def_menu->list) { if (def_menu->list) {
indent += 2; indent += 2;
build_conf(def_menu); build_conf(def_menu);
indent -= 2; indent -= 2;
} }
} else }
cprint_done();
return; return;
} }
cprint_done();
} else { } else {
if (menu == current_menu) { if (menu == current_menu) {
cprint(":%p", menu); item_make("---%*c%s", indent + 1, ' ', menu_get_prompt(menu));
cprint("---%*c%s", indent + 1, ' ', menu_get_prompt(menu)); item_set_tag(':');
item_set_data(menu);
goto conf_childs; goto conf_childs;
} }
child_count++; child_count++;
val = sym_get_tristate_value(sym); val = sym_get_tristate_value(sym);
if (sym_is_choice_value(sym) && val == yes) { if (sym_is_choice_value(sym) && val == yes) {
cprint(":%p", menu); item_make(" ");
cprint1(" "); item_set_tag(':');
item_set_data(menu);
} else { } else {
switch (type) { switch (type) {
case S_BOOLEAN: case S_BOOLEAN:
cprint("t%p", menu);
if (sym_is_changable(sym)) if (sym_is_changable(sym))
cprint1("[%c]", val == no ? ' ' : '*'); item_make("[%c]", val == no ? ' ' : '*');
else else
cprint1("---"); item_make("---");
item_set_tag('t');
item_set_data(menu);
break; break;
case S_TRISTATE: case S_TRISTATE:
cprint("t%p", menu);
switch (val) { switch (val) {
case yes: ch = '*'; break; case yes: ch = '*'; break;
case mod: ch = 'M'; break; case mod: ch = 'M'; break;
default: ch = ' '; break; default: ch = ' '; break;
} }
if (sym_is_changable(sym)) if (sym_is_changable(sym))
cprint1("<%c>", ch); item_make("<%c>", ch);
else else
cprint1("---"); item_make("---");
item_set_tag('t');
item_set_data(menu);
break; break;
default: default:
cprint("s%p", menu); tmp = 2 + strlen(sym_get_string_value(sym)); /* () = 2 */
tmp = cprint1("(%s)", sym_get_string_value(sym)); item_make("(%s)", sym_get_string_value(sym));
tmp = indent - tmp + 4; tmp = indent - tmp + 4;
if (tmp < 0) if (tmp < 0)
tmp = 0; tmp = 0;
cprint1("%*c%s%s", tmp, ' ', menu_get_prompt(menu), item_add_str("%*c%s%s", tmp, ' ', menu_get_prompt(menu),
(sym_has_value(sym) || !sym_is_changable(sym)) ? (sym_has_value(sym) || !sym_is_changable(sym)) ?
"" : " (NEW)"); "" : " (NEW)");
cprint_done(); item_set_tag('s');
item_set_data(menu);
goto conf_childs; goto conf_childs;
} }
} }
cprint1("%*c%s%s", indent + 1, ' ', menu_get_prompt(menu), item_add_str("%*c%s%s", indent + 1, ' ', menu_get_prompt(menu),
(sym_has_value(sym) || !sym_is_changable(sym)) ? (sym_has_value(sym) || !sym_is_changable(sym)) ?
"" : " (NEW)"); "" : " (NEW)");
if (menu->prompt->type == P_MENU) { if (menu->prompt->type == P_MENU) {
cprint1(" --->"); item_add_str(" --->");
cprint_done();
return; return;
} }
cprint_done();
} }
conf_childs: conf_childs:
...@@ -717,59 +585,45 @@ static void conf(struct menu *menu) ...@@ -717,59 +585,45 @@ static void conf(struct menu *menu)
struct menu *submenu; struct menu *submenu;
const char *prompt = menu_get_prompt(menu); const char *prompt = menu_get_prompt(menu);
struct symbol *sym; struct symbol *sym;
char active_entry[40]; struct menu *active_menu = NULL;
int stat, type, i; int res;
int s_scroll = 0;
unlink("lxdialog.scrltmp");
active_entry[0] = 0;
while (1) { while (1) {
cprint_init(); item_reset();
cprint("--title");
cprint("%s", prompt ? prompt : _("Main Menu"));
cprint("--menu");
cprint(_(menu_instructions));
cprint("%d", rows);
cprint("%d", cols);
cprint("%d", rows - 10);
cprint("%s", active_entry);
current_menu = menu; current_menu = menu;
build_conf(menu); build_conf(menu);
if (!child_count) if (!child_count)
break; break;
if (menu == &rootmenu) { if (menu == &rootmenu) {
cprint(":"); item_make("--- ");
cprint("--- "); item_set_tag(':');
cprint("L"); item_make(_(" Load an Alternate Configuration File"));
cprint(_(" Load an Alternate Configuration File")); item_set_tag('L');
cprint("S"); item_make(_(" Save an Alternate Configuration File"));
cprint(_(" Save Configuration to an Alternate File")); item_set_tag('S');
} }
stat = exec_conf(); dialog_clear();
if (stat < 0) res = dialog_menu(prompt ? prompt : _("Main Menu"),
continue; _(menu_instructions),
active_menu, &s_scroll);
if (stat == 1 || stat == 255) if (res == 1 || res == KEY_ESC || res == -ERRDISPLAYTOOSMALL)
break; break;
if (!item_activate_selected())
type = input_buf[0]; continue;
if (!type) if (!item_tag())
continue; continue;
for (i = 0; input_buf[i] && !isspace(input_buf[i]); i++) submenu = item_data();
; active_menu = item_data();
if (i >= sizeof(active_entry)) if (submenu)
i = sizeof(active_entry) - 1;
input_buf[i] = 0;
strcpy(active_entry, input_buf);
sym = NULL;
submenu = NULL;
if (sscanf(input_buf + 1, "%p", &submenu) == 1)
sym = submenu->sym; sym = submenu->sym;
else
sym = NULL;
switch (stat) { switch (res) {
case 0: case 0:
switch (type) { switch (item_tag()) {
case 'm': case 'm':
if (single_menu_mode) if (single_menu_mode)
submenu->data = (void *) (long) !submenu->data; submenu->data = (void *) (long) !submenu->data;
...@@ -800,7 +654,7 @@ static void conf(struct menu *menu) ...@@ -800,7 +654,7 @@ static void conf(struct menu *menu)
show_helptext("README", _(mconf_readme)); show_helptext("README", _(mconf_readme));
break; break;
case 3: case 3:
if (type == 't') { if (item_is_tag('t')) {
if (sym_set_tristate_value(sym, yes)) if (sym_set_tristate_value(sym, yes))
break; break;
if (sym_set_tristate_value(sym, mod)) if (sym_set_tristate_value(sym, mod))
...@@ -808,17 +662,17 @@ static void conf(struct menu *menu) ...@@ -808,17 +662,17 @@ static void conf(struct menu *menu)
} }
break; break;
case 4: case 4:
if (type == 't') if (item_is_tag('t'))
sym_set_tristate_value(sym, no); sym_set_tristate_value(sym, no);
break; break;
case 5: case 5:
if (type == 't') if (item_is_tag('t'))
sym_set_tristate_value(sym, mod); sym_set_tristate_value(sym, mod);
break; break;
case 6: case 6:
if (type == 't') if (item_is_tag('t'))
sym_toggle_tristate_value(sym); sym_toggle_tristate_value(sym);
else if (type == 'm') else if (item_is_tag('m'))
conf(submenu); conf(submenu);
break; break;
case 7: case 7:
...@@ -830,13 +684,8 @@ static void conf(struct menu *menu) ...@@ -830,13 +684,8 @@ static void conf(struct menu *menu)
static void show_textbox(const char *title, const char *text, int r, int c) static void show_textbox(const char *title, const char *text, int r, int c)
{ {
int fd; dialog_clear();
dialog_textbox(title, text, r, c);
fd = creat(".help.tmp", 0777);
write(fd, text, strlen(text));
close(fd);
show_file(".help.tmp", title, r, c);
unlink(".help.tmp");
} }
static void show_helptext(const char *title, const char *text) static void show_helptext(const char *title, const char *text)
...@@ -864,68 +713,52 @@ static void show_help(struct menu *menu) ...@@ -864,68 +713,52 @@ static void show_help(struct menu *menu)
str_free(&help); str_free(&help);
} }
static void show_file(const char *filename, const char *title, int r, int c)
{
do {
cprint_init();
if (title) {
cprint("--title");
cprint("%s", title);
}
cprint("--textbox");
cprint("%s", filename);
cprint("%d", r ? r : rows);
cprint("%d", c ? c : cols);
} while (exec_conf() < 0);
}
static void conf_choice(struct menu *menu) static void conf_choice(struct menu *menu)
{ {
const char *prompt = menu_get_prompt(menu); const char *prompt = menu_get_prompt(menu);
struct menu *child; struct menu *child;
struct symbol *active; struct symbol *active;
int stat;
active = sym_get_choice_value(menu->sym); active = sym_get_choice_value(menu->sym);
while (1) { while (1) {
cprint_init(); int res;
cprint("--title"); int selected;
cprint("%s", prompt ? prompt : _("Main Menu")); item_reset();
cprint("--radiolist");
cprint(_(radiolist_instructions));
cprint("15");
cprint("70");
cprint("6");
current_menu = menu; current_menu = menu;
for (child = menu->list; child; child = child->next) { for (child = menu->list; child; child = child->next) {
if (!menu_is_visible(child)) if (!menu_is_visible(child))
continue; continue;
cprint("%p", child); item_make("%s", menu_get_prompt(child));
cprint("%s", menu_get_prompt(child)); item_set_data(child);
if (child->sym == active)
item_set_selected(1);
if (child->sym == sym_get_choice_value(menu->sym)) if (child->sym == sym_get_choice_value(menu->sym))
cprint("ON"); item_set_tag('X');
else if (child->sym == active)
cprint("SELECTED");
else
cprint("OFF");
} }
dialog_clear();
stat = exec_conf(); res = dialog_checklist(prompt ? prompt : _("Main Menu"),
switch (stat) { _(radiolist_instructions),
15, 70, 6);
selected = item_activate_selected();
switch (res) {
case 0: case 0:
if (sscanf(input_buf, "%p", &child) != 1) if (selected) {
break; child = item_data();
sym_set_tristate_value(child->sym, yes); sym_set_tristate_value(child->sym, yes);
}
return; return;
case 1: case 1:
if (sscanf(input_buf, "%p", &child) == 1) { if (selected) {
child = item_data();
show_help(child); show_help(child);
active = child->sym; active = child->sym;
} else } else
show_help(menu); show_help(menu);
break; break;
case 255: case KEY_ESC:
return;
case -ERRDISPLAYTOOSMALL:
return; return;
} }
} }
...@@ -934,40 +767,38 @@ static void conf_choice(struct menu *menu) ...@@ -934,40 +767,38 @@ static void conf_choice(struct menu *menu)
static void conf_string(struct menu *menu) static void conf_string(struct menu *menu)
{ {
const char *prompt = menu_get_prompt(menu); const char *prompt = menu_get_prompt(menu);
int stat;
while (1) { while (1) {
cprint_init(); int res;
cprint("--title"); char *heading;
cprint("%s", prompt ? prompt : _("Main Menu"));
cprint("--inputbox");
switch (sym_get_type(menu->sym)) { switch (sym_get_type(menu->sym)) {
case S_INT: case S_INT:
cprint(_(inputbox_instructions_int)); heading = _(inputbox_instructions_int);
break; break;
case S_HEX: case S_HEX:
cprint(_(inputbox_instructions_hex)); heading = _(inputbox_instructions_hex);
break; break;
case S_STRING: case S_STRING:
cprint(_(inputbox_instructions_string)); heading = _(inputbox_instructions_string);
break; break;
default: default:
/* panic? */; heading = "Internal mconf error!";
} }
cprint("10"); dialog_clear();
cprint("75"); res = dialog_inputbox(prompt ? prompt : _("Main Menu"),
cprint("%s", sym_get_string_value(menu->sym)); heading, 10, 75,
stat = exec_conf(); sym_get_string_value(menu->sym));
switch (stat) { switch (res) {
case 0: case 0:
if (sym_set_string_value(menu->sym, input_buf)) if (sym_set_string_value(menu->sym, dialog_input_result))
return; return;
show_textbox(NULL, _("You have made an invalid entry."), 5, 43); show_textbox(NULL, _("You have made an invalid entry."), 5, 43);
break; break;
case 1: case 1:
show_help(menu); show_help(menu);
break; break;
case 255: case KEY_ESC:
return; return;
} }
} }
...@@ -975,28 +806,24 @@ static void conf_string(struct menu *menu) ...@@ -975,28 +806,24 @@ static void conf_string(struct menu *menu)
static void conf_load(void) static void conf_load(void)
{ {
int stat;
while (1) { while (1) {
cprint_init(); int res;
cprint("--inputbox"); dialog_clear();
cprint(load_config_text); res = dialog_inputbox(NULL, load_config_text,
cprint("11"); 11, 55, filename);
cprint("55"); switch(res) {
cprint("%s", filename);
stat = exec_conf();
switch(stat) {
case 0: case 0:
if (!input_buf[0]) if (!dialog_input_result[0])
return; return;
if (!conf_read(input_buf)) if (!conf_read(dialog_input_result))
return; return;
show_textbox(NULL, _("File does not exist!"), 5, 38); show_textbox(NULL, _("File does not exist!"), 5, 38);
break; break;
case 1: case 1:
show_helptext(_("Load Alternate Configuration"), load_config_help); show_helptext(_("Load Alternate Configuration"), load_config_help);
break; break;
case 255: case KEY_ESC:
return; return;
} }
} }
...@@ -1004,28 +831,23 @@ static void conf_load(void) ...@@ -1004,28 +831,23 @@ static void conf_load(void)
static void conf_save(void) static void conf_save(void)
{ {
int stat;
while (1) { while (1) {
cprint_init(); int res;
cprint("--inputbox"); dialog_clear();
cprint(save_config_text); res = dialog_inputbox(NULL, save_config_text,
cprint("11"); 11, 55, filename);
cprint("55"); switch(res) {
cprint("%s", filename);
stat = exec_conf();
switch(stat) {
case 0: case 0:
if (!input_buf[0]) if (!dialog_input_result[0])
return; return;
if (!conf_write(input_buf)) if (!conf_write(dialog_input_result))
return; return;
show_textbox(NULL, _("Can't create file! Probably a nonexistent directory."), 5, 60); show_textbox(NULL, _("Can't create file! Probably a nonexistent directory."), 5, 60);
break; break;
case 1: case 1:
show_helptext(_("Save Alternate Configuration"), save_config_help); show_helptext(_("Save Alternate Configuration"), save_config_help);
break; break;
case 255: case KEY_ESC:
return; return;
} }
} }
...@@ -1034,15 +856,13 @@ static void conf_save(void) ...@@ -1034,15 +856,13 @@ static void conf_save(void)
static void conf_cleanup(void) static void conf_cleanup(void)
{ {
tcsetattr(1, TCSAFLUSH, &ios_org); tcsetattr(1, TCSAFLUSH, &ios_org);
unlink(".help.tmp");
unlink("lxdialog.scrltmp");
} }
int main(int ac, char **av) int main(int ac, char **av)
{ {
struct symbol *sym; struct symbol *sym;
char *mode; char *mode;
int stat; int res;
setlocale(LC_ALL, ""); setlocale(LC_ALL, "");
bindtextdomain(PACKAGE, LOCALEDIR); bindtextdomain(PACKAGE, LOCALEDIR);
...@@ -1065,18 +885,19 @@ int main(int ac, char **av) ...@@ -1065,18 +885,19 @@ int main(int ac, char **av)
tcgetattr(1, &ios_org); tcgetattr(1, &ios_org);
atexit(conf_cleanup); atexit(conf_cleanup);
init_wsize(); init_wsize();
conf(&rootmenu); reset_dialog();
init_dialog(menu_backtitle);
do { do {
cprint_init(); conf(&rootmenu);
cprint("--yesno"); dialog_clear();
cprint(_("Do you wish to save your new kernel configuration?")); res = dialog_yesno(NULL,
cprint("5"); _("Do you wish to save your "
cprint("60"); "new kernel configuration?\n"
stat = exec_conf(); "<ESC><ESC> to continue."),
} while (stat < 0); 6, 60);
} while (res == KEY_ESC);
if (stat == 0) { end_dialog();
if (res == 0) {
if (conf_write(NULL)) { if (conf_write(NULL)) {
fprintf(stderr, _("\n\n" fprintf(stderr, _("\n\n"
"Error during writing of the kernel configuration.\n" "Error during writing of the kernel configuration.\n"
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment