[PATCH 4/13] kconfig/menuconfig: lxdialog is now built-in

sam
2006-10-01T10:53:20Z

lxdialog was previously called as an external program causing screen
to flicker when used. With this patch lxdialog is now built-in.
It is loosly based om previous work by: Petr Baudis <pasky@ucw.cz>

Following is a list of changes:
o Moved build of dialog routings to kconfig Makefile
o menubox + checklist uses a new item list to hold all menu items
o in util.c implmented helper function to deal with item list
o menubox now uses parameters to save scroll state (avoids temp file)
o textbox now get text to be displayed as parameter and not a file
o make sure to properly delete subwin's before main windows
o killed unused files: lxdialog.c msgbox.c
o modified return value for ESC to match direct calling
o in a few places the code has been adjusted to 80 char wide
o in textbox a small refactoring was made to make code remotely readable
o in mconf removed all unused stuff (functions/variables)

Following is a list of know short comings:
a) pressing ESC twice will be interpreted as two ESC presses
b) resize does not work. menuconfig needs to be restarted to be adjusted

Signed-off-by: Sam Ravnborg <sam@ravnborg.org>
---
scripts/kconfig/Makefile | 23 +-
scripts/kconfig/lxdialog/Makefile | 21 -
scripts/kconfig/lxdialog/checklist.c | 136 ++++------
scripts/kconfig/lxdialog/dialog.h | 52 +++-
scripts/kconfig/lxdialog/inputbox.c | 2
scripts/kconfig/lxdialog/lxdialog.c | 204 --------------
scripts/kconfig/lxdialog/menubox.c | 95 +++----
scripts/kconfig/lxdialog/msgbox.c | 72 -----
scripts/kconfig/lxdialog/textbox.c | 298 +++++----------------
scripts/kconfig/lxdialog/util.c | 134 +++++++++
scripts/kconfig/lxdialog/yesno.c | 2
scripts/kconfig/mconf.c | 482 ++++++++++------------------------
12 files changed, 502 insertions(+), 1019 deletions(-)

diff --git a/scripts/kconfig/Makefile b/scripts/kconfig/Makefile
index a90d3cc..b2928f0 100644
--- a/scripts/kconfig/Makefile
+++ b/scripts/kconfig/Makefile
@@ -11,7 +11,6 @@ gconfig: $(obj)/gconf
$< arch/$(ARCH)/Kconfig

menuconfig: $(obj)/mconf
- $(Q)$(MAKE) $(build)=scripts/kconfig/lxdialog
$< arch/$(ARCH)/Kconfig

config: $(obj)/conf
@@ -81,6 +80,23 @@ help:
@echo ' allyesconfig - New config where all options are accepted with yes'
@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:
# conf: Used for defconfig, oldconfig and related targets
@@ -92,9 +108,12 @@ # gconf: Used for the gconfig target
# Based on GTK which needs to be installed to compile it
# object files used by all kconfig flavours

+lxdialog := lxdialog/checklist.o lxdialog/util.o lxdialog/inputbox.o
+lxdialog += lxdialog/textbox.o lxdialog/yesno.o lxdialog/menubox.o
+
hostprogs-y := conf mconf qconf gconf kxgettext
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

ifeq ($(MAKECMDGOALS),xconfig)
diff --git a/scripts/kconfig/lxdialog/Makefile b/scripts/kconfig/lxdialog/Makefile
deleted file mode 100644
index a8b0263..0000000
--- a/scripts/kconfig/lxdialog/Makefile
+++ /dev/null
@@ -1,21 +0,0 @@
-# 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
diff --git a/scripts/kconfig/lxdialog/checklist.c b/scripts/kconfig/lxdialog/checklist.c
index b90e888..2825110 100644
--- a/scripts/kconfig/lxdialog/checklist.c
+++ b/scripts/kconfig/lxdialog/checklist.c
@@ -28,8 +28,7 @@ static int list_width, check_x, item_x;
/*
* Print list item
*/
-static void print_item(WINDOW * win, const char *item, int status, int choice,
- int selected)
+static void print_item(WINDOW * win, int choice, int selected)
{
int i;

@@ -42,12 +41,12 @@ static void print_item(WINDOW * win, con
wmove(win, choice, check_x);
wattrset(win, selected ? dlg.check_selected.atr
: dlg.check.atr);
- wprintw(win, "(%c)", status ? 'X' : ' ');
+ wprintw(win, "(%c)", item_is_tag('X') ? 'X' : ' ');

wattrset(win, selected ? dlg.tag_selected.atr : dlg.tag.atr);
- mvwaddch(win, choice, item_x, item[0]);
+ mvwaddch(win, choice, item_x, item_str()[0]);
wattrset(win, selected ? dlg.item_selected.atr : dlg.item.atr);
- waddstr(win, (char *)item + 1);
+ waddstr(win, (char *)item_str() + 1);
if (selected) {
wmove(win, choice, check_x + 1);
wrefresh(win);
@@ -110,32 +109,23 @@ static void print_buttons(WINDOW * dialo
* 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 width, int list_height, int item_no,
- const char *const *items)
+ int width, int list_height)
{
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;

- /* Allocate space for storing item on/off status */
- if ((status = malloc(sizeof(int) * item_no)) == NULL) {
- endwin();
- fprintf(stderr,
- "\nCan't allocate memory in dialog_checklist().\n");
- exit(-1);
- }
-
- /* Initializes status */
- for (i = 0; i < item_no; i++) {
- status[i] = !strcasecmp(items[i * 3 + 2], "on");
- if ((!choice && status[i])
- || !strcasecmp(items[i * 3 + 2], "selected"))
- choice = i + 1;
+ /* which item to highlight */
+ item_foreach() {
+ if (item_is_tag('X'))
+ choice = item_n();
+ if (item_is_selected()) {
+ choice = item_n();
+ break;
+ }
}
- if (choice)
- choice--;

- max_choice = MIN(list_height, item_no);
+ max_choice = MIN(list_height, item_count());

/* center dialog box on screen */
x = (COLS - width) / 2;
@@ -176,8 +166,8 @@ int dialog_checklist(const char *title,

/* Find length of longest item in order to center checklist */
check_x = 0;
- for (i = 0; i < item_no; i++)
- check_x = MAX(check_x, +strlen(items[i * 3 + 1]) + 4);
+ item_foreach()
+ check_x = MAX(check_x, strlen(item_str()) + 4);

check_x = (list_width - check_x) / 2;
item_x = check_x + 4;
@@ -189,14 +179,11 @@ int dialog_checklist(const char *title,

/* Print the list */
for (i = 0; i < max_choice; i++) {
- if (i != choice)
- print_item(list, items[(scroll + i) * 3 + 1],
- status[i + scroll], i, 0);
+ item_set(scroll + i);
+ print_item(list, i, i == choice);
}
- 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);

print_buttons(dialog, height, width, 0);
@@ -208,10 +195,11 @@ int dialog_checklist(const char *title,
while (key != ESC) {
key = wgetch(dialog);

- for (i = 0; i < max_choice; i++)
- if (toupper(key) ==
- toupper(items[(scroll + i) * 3 + 1][0]))
+ for (i = 0; i < max_choice; i++) {
+ item_set(i + scroll);
+ if (toupper(key) == toupper(item_str()[0]))
break;
+ }

if (i < max_choice || key == KEY_UP || key == KEY_DOWN ||
key == '+' || key == '-') {
@@ -222,15 +210,16 @@ int dialog_checklist(const char *title,
/* Scroll list down */
if (list_height > 1) {
/* De-highlight current first item */
- print_item(list, items[scroll * 3 + 1],
- status[scroll], 0, FALSE);
+ item_set(scroll);
+ print_item(list, 0, FALSE);
scrollok(list, TRUE);
wscrl(list, -1);
scrollok(list, FALSE);
}
scroll--;
- print_item(list, items[scroll * 3 + 1], status[scroll], 0, TRUE);
- print_arrows(dialog, choice, item_no,
+ item_set(scroll);
+ print_item(list, 0, TRUE);
+ print_arrows(dialog, choice, item_count(),
scroll, box_y, box_x + check_x + 5, list_height);

wnoutrefresh(dialog);
@@ -241,23 +230,24 @@ int dialog_checklist(const char *title,
i = choice - 1;
} else if (key == KEY_DOWN || key == '+') {
if (choice == max_choice - 1) {
- if (scroll + choice >= item_no - 1)
+ if (scroll + choice >= item_count() - 1)
continue;
/* Scroll list up */
if (list_height > 1) {
/* De-highlight current last item before scrolling up */
- print_item(list, items[(scroll + max_choice - 1) * 3 + 1],
- status[scroll + max_choice - 1],
- max_choice - 1, FALSE);
+ item_set(scroll + max_choice - 1);
+ print_item(list,
+ max_choice - 1,
+ FALSE);
scrollok(list, TRUE);
wscrl(list, 1);
scrollok(list, FALSE);
}
scroll++;
- print_item(list, items[(scroll + max_choice - 1) * 3 + 1],
- status[scroll + max_choice - 1], max_choice - 1, TRUE);
+ item_set(scroll + max_choice - 1);
+ 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);

wnoutrefresh(dialog);
@@ -269,12 +259,12 @@ int dialog_checklist(const char *title,
}
if (i != choice) {
/* De-highlight current item */
- print_item(list, items[(scroll + choice) * 3 + 1],
- status[scroll + choice], choice, FALSE);
+ item_set(scroll + choice);
+ print_item(list, choice, FALSE);
/* Highlight new item */
choice = i;
- print_item(list, items[(scroll + choice) * 3 + 1],
- status[scroll + choice], choice, TRUE);
+ item_set(scroll + choice);
+ print_item(list, choice, TRUE);
wnoutrefresh(dialog);
wrefresh(list);
}
@@ -284,10 +274,19 @@ int dialog_checklist(const char *title,
case 'H':
case 'h':
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);
- free(status);
- return 1;
+ return button;
case TAB:
case KEY_LEFT:
case KEY_RIGHT:
@@ -297,30 +296,6 @@ int dialog_checklist(const char *title,
print_buttons(dialog, height, width, button);
wrefresh(dialog);
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':
key = ESC;
@@ -331,8 +306,7 @@ int dialog_checklist(const char *title,
/* Now, update everything... */
doupdate();
}
-
+ delwin(list);
delwin(dialog);
- free(status);
- return -1; /* ESC pressed */
+ return 255; /* ESC pressed */
}
diff --git a/scripts/kconfig/lxdialog/dialog.h b/scripts/kconfig/lxdialog/dialog.h
index 2f4c19d..065ded0 100644
--- a/scripts/kconfig/lxdialog/dialog.h
+++ b/scripts/kconfig/lxdialog/dialog.h
@@ -133,11 +133,55 @@ struct dialog_info {
* Global variables
*/
extern struct dialog_info dlg;
+extern char dialog_input_result[];

/*
* Function prototypes
*/
-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)
+
+
+void init_dialog(const char *backtitle);
+void reset_dialog(void);
void end_dialog(void);
void attr_clear(WINDOW * win, int height, int width, chtype attr);
void dialog_clear(void);
@@ -154,11 +198,9 @@ int dialog_msgbox(const char *title, con
int width, int pause);
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 menu_height, const char *choice, int item_no,
- const char *const *items);
+ int menu_height, const void *selected, int *s_scroll);
int dialog_checklist(const char *title, const char *prompt, int height,
- int width, int list_height, int item_no,
- const char *const *items);
+ int width, int list_height);
extern char dialog_input_result[];
int dialog_inputbox(const char *title, const char *prompt, int height,
int width, const char *init);
diff --git a/scripts/kconfig/lxdialog/inputbox.c b/scripts/kconfig/lxdialog/inputbox.c
index f75b51f..9c53098 100644
--- a/scripts/kconfig/lxdialog/inputbox.c
+++ b/scripts/kconfig/lxdialog/inputbox.c
@@ -222,5 +222,5 @@ int dialog_inputbox(const char *title, c
}

delwin(dialog);
- return -1; /* ESC pressed */
+ return 255; /* ESC pressed */
}
diff --git a/scripts/kconfig/lxdialog/lxdialog.c b/scripts/kconfig/lxdialog/lxdialog.c
deleted file mode 100644
index c264e02..0000000
--- a/scripts/kconfig/lxdialog/lxdialog.c
+++ /dev/null
@@ -1,204 +0,0 @@
-/*
- * 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 (dlg.backtitle != NULL) {
- Usage(argv[0]);
- exit(-1);
- } else {
- dlg.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, dlg.screen.atr);
- 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 ] [--backtitle <backtitle>] --clear <Box options>\
-\n\
-\nBox options:\
-\n\
-\n --menu <text> <height> <width> <tag1> <item1>...\
-\n --radiolist <text> <height> <width> <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);
-}
diff --git a/scripts/kconfig/lxdialog/menubox.c b/scripts/kconfig/lxdialog/menubox.c
index ff991db..f39ae29 100644
--- a/scripts/kconfig/lxdialog/menubox.c
+++ b/scripts/kconfig/lxdialog/menubox.c
@@ -99,10 +99,10 @@ #endif
wrefresh(win);
}

-#define print_item(index, choice, selected) \
-do {\
- int hotkey = (items[(index) * 2][0] != ':'); \
- do_print_item(menu, items[(index) * 2 + 1], choice, selected, hotkey); \
+#define print_item(index, choice, selected) \
+do { \
+ item_set(index); \
+ do_print_item(menu, item_str(), choice, selected, !item_is_tag(':')); \
} while (0)

/*
@@ -180,16 +180,14 @@ static void do_scroll(WINDOW *win, int *
* Display a menu for choosing among a number of options
*/
int dialog_menu(const char *title, const char *prompt, int height, int width,
- int menu_height, const char *current, int item_no,
- const char *const *items)
+ int menu_height, const void *selected, int *s_scroll)
{
int i, j, x, y, box_x, box_y;
int key = 0, button = 0, scroll = 0, choice = 0;
int first_item = 0, max_choice;
WINDOW *dialog, *menu;
- FILE *f;

- max_choice = MIN(menu_height, item_no);
+ max_choice = MIN(menu_height, item_count());

/* center dialog box on screen */
x = (COLS - width) / 2;
@@ -231,28 +229,21 @@ int dialog_menu(const char *title, const
item_x = (menu_width - 70) / 2;

/* Set choice to default item */
- for (i = 0; i < item_no; i++)
- if (strcmp(current, items[i * 2]) == 0)
- choice = i;
-
- /* get the scroll info from the temp file */
- if ((f = fopen("lxdialog.scrltmp", "r")) != NULL) {
- if ((fscanf(f, "%d\n", &scroll) == 1) && (scroll <= choice) &&
- (scroll + max_choice > choice) && (scroll >= 0) &&
- (scroll + max_choice <= item_no)) {
- first_item = scroll;
- choice = choice - scroll;
- fclose(f);
- } else {
- scroll = 0;
- remove("lxdialog.scrltmp");
- fclose(f);
- f = NULL;
- }
+ item_foreach()
+ if (selected && (selected == item_data()))
+ choice = item_n();
+ /* get the saved scroll info */
+ scroll = *s_scroll;
+ if ((scroll <= choice) && (scroll + max_choice > choice) &&
+ (scroll >= 0) && (scroll + max_choice <= item_count())) {
+ first_item = scroll;
+ choice = choice - scroll;
+ } else {
+ scroll = 0;
}
- if ((choice >= max_choice) || (f == NULL && choice >= max_choice / 2)) {
- if (choice >= item_no - max_choice / 2)
- scroll = first_item = item_no - max_choice;
+ if ((choice >= max_choice)) {
+ if (choice >= item_count() - max_choice / 2)
+ scroll = first_item = item_count() - max_choice;
else
scroll = first_item = choice - max_choice / 2;
choice = choice - scroll;
@@ -265,7 +256,7 @@ int dialog_menu(const char *title, const

wnoutrefresh(menu);

- print_arrows(dialog, item_no, scroll,
+ print_arrows(dialog, item_count(), scroll,
box_y, box_x + item_x + 1, menu_height);

print_buttons(dialog, height, width, 0);
@@ -282,14 +273,16 @@ int dialog_menu(const char *title, const
i = max_choice;
else {
for (i = choice + 1; i < max_choice; i++) {
- j = first_alpha(items[(scroll + i) * 2 + 1], "YyNnMmHh");
- if (key == tolower(items[(scroll + i) * 2 + 1][j]))
+ item_set(scroll + i);
+ j = first_alpha(item_str(), "YyNnMmHh");
+ if (key == tolower(item_str()[j]))
break;
}
if (i == max_choice)
for (i = 0; i < max_choice; i++) {
- j = first_alpha(items [(scroll + i) * 2 + 1], "YyNnMmHh");
- if (key == tolower(items[(scroll + i) * 2 + 1][j]))
+ item_set(scroll + i);
+ j = first_alpha(item_str(), "YyNnMmHh");
+ if (key == tolower(item_str()[j]))
break;
}
}
@@ -314,7 +307,7 @@ int dialog_menu(const char *title, const
print_item(scroll+choice, choice, FALSE);

if ((choice > max_choice - 3) &&
- (scroll + max_choice < item_no)) {
+ (scroll + max_choice < item_count())) {
/* Scroll menu up */
do_scroll(menu, &scroll, 1);

@@ -337,7 +330,7 @@ int dialog_menu(const char *title, const

} else if (key == KEY_NPAGE) {
for (i = 0; (i < max_choice); i++) {
- if (scroll + max_choice < item_no) {
+ if (scroll + max_choice < item_count()) {
do_scroll(menu, &scroll, 1);
print_item(scroll+max_choice-1,
max_choice - 1, FALSE);
@@ -351,7 +344,7 @@ int dialog_menu(const char *title, const

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);

wnoutrefresh(dialog);
@@ -377,12 +370,11 @@ int dialog_menu(const char *title, const
case 'm':
case '/':
/* save scroll info */
- if ((f = fopen("lxdialog.scrltmp", "w")) != NULL) {
- fprintf(f, "%d\n", scroll);
- fclose(f);
- }
+ *s_scroll = scroll;
+ delwin(menu);
delwin(dialog);
- fprintf(stderr, "%s\n", items[(scroll + choice) * 2]);
+ item_set(scroll + choice);
+ item_set_selected(1);
switch (key) {
case 's':
return 3;
@@ -402,17 +394,11 @@ int dialog_menu(const char *title, const
case '?':
button = 2;
case '\n':
+ *s_scroll = scroll;
+ delwin(menu);
delwin(dialog);
- if (button == 2)
- fprintf(stderr, "%s \"%s\"\n",
- 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");
+ item_set(scroll + choice);
+ item_set_selected(1);
return button;
case 'e':
case 'x':
@@ -421,8 +407,7 @@ int dialog_menu(const char *title, const
break;
}
}
-
+ delwin(menu);
delwin(dialog);
- remove("lxdialog.scrltmp");
- return -1; /* ESC pressed */
+ return 255; /* ESC pressed */
}
diff --git a/scripts/kconfig/lxdialog/msgbox.c b/scripts/kconfig/lxdialog/msgbox.c
deleted file mode 100644
index 236759f..0000000
--- a/scripts/kconfig/lxdialog/msgbox.c
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * 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,
- dlg.dialog.atr, dlg.border.atr);
-
- print_title(dialog, title, width);
-
- wattrset(dialog, dlg.dialog.atr);
- print_autowrap(dialog, prompt, width - 2, 1, 2);
-
- if (pause) {
- wattrset(dialog, dlg.border.atr);
- mvwaddch(dialog, height - 3, 0, ACS_LTEE);
- for (i = 0; i < width - 2; i++)
- waddch(dialog, ACS_HLINE);
- wattrset(dialog, dlg.dialog.atr);
- 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;
-}
diff --git a/scripts/kconfig/lxdialog/textbox.c b/scripts/kconfig/lxdialog/textbox.c
index 336793b..86b0770 100644
--- a/scripts/kconfig/lxdialog/textbox.c
+++ b/scripts/kconfig/lxdialog/textbox.c
@@ -27,54 +27,27 @@ static void print_line(WINDOW * win, int
static char *get_line(void);
static void print_position(WINDOW * win, int height, int width);

-static int hscroll, fd, file_size, bytes_read;
-static int begin_reached = 1, end_reached, page_length;
-static char *buf, *page;
+static int hscroll;
+static int begin_reached, end_reached, page_length;
+static const char *buf;
+static const char *page;

/*
* 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 height, int width)
{
- int i, x, y, cur_x, cur_y, fpos, key = 0;
+ int i, x, y, cur_x, cur_y, key = 0;
+ int texth, textw;
int passed_end;
- char search_term[MAX_LEN + 1];
WINDOW *dialog, *text;

- search_term[0] = '\0'; /* no search term entered yet */
-
- /* Open input file for reading */
- if ((fd = open(file, O_RDONLY)) == -1) {
- endwin();
- fprintf(stderr, "\nCan't open input file in dialog_textbox().\n");
- exit(-1);
- }
- /* Get file size. Actually, 'file_size' is the real file size - 1,
- since it's only the last byte offset from the beginning */
- if ((file_size = lseek(fd, 0, SEEK_END)) == -1) {
- endwin();
- fprintf(stderr, "\nError getting file size in dialog_textbox().\n");
- exit(-1);
- }
- /* Restore file pointer to beginning of file after getting file size */
- if (lseek(fd, 0, SEEK_SET) == -1) {
- endwin();
- fprintf(stderr, "\nError moving file pointer in dialog_textbox().\n");
- exit(-1);
- }
- /* Allocate space for read buffer */
- if ((buf = malloc(BUF_SIZE + 1)) == NULL) {
- endwin();
- fprintf(stderr, "\nCan't allocate memory 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'; /* mark end of valid data */
- page = buf; /* page is pointer to start of page to be displayed */
+ begin_reached = 1;
+ end_reached = 0;
+ page_length = 0;
+ hscroll = 0;
+ buf = tbuf;
+ page = buf; /* page is pointer to start of page to be displayed */

/* center dialog box on screen */
x = (COLS - width) / 2;
@@ -86,7 +59,9 @@ int dialog_textbox(const char *title, co
keypad(dialog, TRUE);

/* Create window for text region, used for scrolling text */
- text = subwin(dialog, height - 4, width - 2, y + 1, x + 1);
+ texth = height - 4;
+ textw = width - 2;
+ text = subwin(dialog, texth, textw, y + 1, x + 1);
wattrset(text, dlg.dialog.atr);
wbkgdset(text, dlg.dialog.atr & A_COLOR);

@@ -111,8 +86,8 @@ int dialog_textbox(const char *title, co
getyx(dialog, cur_y, cur_x); /* Save cursor position */

/* Print first page of text */
- attr_clear(text, height - 4, width - 2, dlg.dialog.atr);
- print_page(text, height - 4, width - 2);
+ attr_clear(text, texth, textw, dlg.dialog.atr);
+ print_page(text, texth, textw);
print_position(dialog, height, width);
wmove(dialog, cur_y, cur_x); /* Restore cursor position */
wrefresh(dialog);
@@ -124,37 +99,15 @@ int dialog_textbox(const char *title, co
case 'e':
case 'X':
case 'x':
+ delwin(text);
delwin(dialog);
- free(buf);
- close(fd);
return 0;
case 'g': /* First page */
case KEY_HOME:
if (!begin_reached) {
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;
- print_page(text, height - 4, width - 2);
+ print_page(text, texth, textw);
print_position(dialog, height, width);
wmove(dialog, cur_y, cur_x); /* Restore cursor position */
wrefresh(dialog);
@@ -164,29 +117,10 @@ int dialog_textbox(const char *title, co
case KEY_END:

end_reached = 1;
- /* Last 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 < 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);
+ /* point to last char in buf */
+ page = buf + strlen(buf);
+ back_lines(texth);
+ print_page(text, texth, textw);
print_position(dialog, height, width);
wmove(dialog, cur_y, cur_x); /* Restore cursor position */
wrefresh(dialog);
@@ -197,20 +131,22 @@ int dialog_textbox(const char *title, co
if (!begin_reached) {
back_lines(page_length + 1);

- /* We don't call print_page() here but use scrolling to ensure
- faster screen update. However, 'end_reached' and
- 'page_length' should still be updated, and 'page' should
- point to start of next page. This is done by calling
- get_line() in the following 'for' loop. */
+ /* We don't call print_page() here but use
+ * scrolling to ensure faster screen update.
+ * However, 'end_reached' and 'page_length'
+ * should still be updated, and 'page' should
+ * point to start of next page. This is done
+ * by calling get_line() in the following
+ * 'for' loop. */
scrollok(text, TRUE);
wscrl(text, -1); /* Scroll text region down one line */
scrollok(text, FALSE);
page_length = 0;
passed_end = 0;
- for (i = 0; i < height - 4; i++) {
+ for (i = 0; i < texth; i++) {
if (!i) {
/* print first line of page */
- print_line(text, 0, width - 2);
+ print_line(text, 0, textw);
wnoutrefresh(text);
} else
/* Called to update 'end_reached' and 'page' */
@@ -231,8 +167,8 @@ int dialog_textbox(const char *title, co
case KEY_PPAGE:
if (begin_reached)
break;
- back_lines(page_length + height - 4);
- print_page(text, height - 4, width - 2);
+ back_lines(page_length + texth);
+ print_page(text, texth, textw);
print_position(dialog, height, width);
wmove(dialog, cur_y, cur_x);
wrefresh(dialog);
@@ -245,7 +181,7 @@ int dialog_textbox(const char *title, co
scrollok(text, TRUE);
scroll(text); /* Scroll text region up one line */
scrollok(text, FALSE);
- print_line(text, height - 5, width - 2);
+ print_line(text, texth - 1, textw);
wnoutrefresh(text);
print_position(dialog, height, width);
wmove(dialog, cur_y, cur_x); /* Restore cursor position */
@@ -258,7 +194,7 @@ int dialog_textbox(const char *title, co
break;

begin_reached = 0;
- print_page(text, height - 4, width - 2);
+ print_page(text, texth, textw);
print_position(dialog, height, width);
wmove(dialog, cur_y, cur_x);
wrefresh(dialog);
@@ -276,7 +212,7 @@ int dialog_textbox(const char *title, co
hscroll--;
/* Reprint current page to scroll horizontally */
back_lines(page_length);
- print_page(text, height - 4, width - 2);
+ print_page(text, texth, textw);
wmove(dialog, cur_y, cur_x);
wrefresh(dialog);
break;
@@ -288,7 +224,7 @@ int dialog_textbox(const char *title, co
hscroll++;
/* Reprint current page to scroll horizontally */
back_lines(page_length);
- print_page(text, height - 4, width - 2);
+ print_page(text, texth, textw);
wmove(dialog, cur_y, cur_x);
wrefresh(dialog);
break;
@@ -296,123 +232,42 @@ int dialog_textbox(const char *title, co
break;
}
}
-
+ delwin(text);
delwin(dialog);
- free(buf);
- close(fd);
- return -1; /* ESC pressed */
+ return 255; /* 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'.
*/
static void back_lines(int n)
{
- int i, fpos;
+ int i;

begin_reached = 0;
- /* We have to distinguish between end_reached and !end_reached
- since at end of file, the line is not ended by a '\n'.
- The code inside 'if' basically does a '--page' to move one
- character backward so as to skip '\n' of the previous line */
- if (!end_reached) {
- /* Either beginning of buffer or beginning of file reached? */
- 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;
+ /* Go back 'n' lines */
+ for (i = 0; i < n; i++) {
+ if (*page == '\0') {
+ if (end_reached) {
+ end_reached = 0;
+ continue;
}
}
- if (*(--page) != '\n') { /* '--page' here */
- /* Something's wrong... */
- endwin();
- fprintf(stderr, "\nInternal error in back_lines().\n");
- exit(-1);
+ if (page == buf) {
+ begin_reached = 1;
+ return;
}
- }
- /* Go back 'n' lines */
- for (i = 0; i < n; i++)
+ page--;
do {
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) {
- /* 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;
- }
+ begin_reached = 1;
+ return;
}
- } while (*(--page) != '\n');
- page++;
+ page--;
+ } while (*page != '\n');
+ page++;
+ }
}

/*
@@ -467,33 +322,14 @@ #endif
*/
static char *get_line(void)
{
- int i = 0, fpos;
+ int i = 0;
static char line[MAX_LEN + 1];

end_reached = 0;
while (*page != '\n') {
if (*page == '\0') {
- /* Either end of file or end of buffer reached */
- if ((fpos = lseek(fd, 0, SEEK_CUR)) == -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;
+ if (!end_reached) {
+ end_reached = 1;
break;
}
} else if (i < MAX_LEN)
@@ -518,17 +354,11 @@ static char *get_line(void)
*/
static void print_position(WINDOW * win, int height, int width)
{
- int fpos, percent;
+ int percent;

- if ((fpos = lseek(fd, 0, SEEK_CUR)) == -1) {
- endwin();
- fprintf(stderr, "\nError moving file pointer in print_position().\n");
- exit(-1);
- }
wattrset(win, dlg.position_indicator.atr);
wbkgdset(win, dlg.position_indicator.atr & A_COLOR);
- percent = !file_size ?
- 100 : ((fpos - bytes_read + page - buf) * 100) / file_size;
+ percent = (page - buf) * 100 / strlen(buf);
wmove(win, height - 3, width - 9);
wprintw(win, "(%3d%%)", percent);
}
diff --git a/scripts/kconfig/lxdialog/util.c b/scripts/kconfig/lxdialog/util.c
index e73a36d..0b3118d 100644
--- a/scripts/kconfig/lxdialog/util.c
+++ b/scripts/kconfig/lxdialog/util.c
@@ -268,13 +268,18 @@ void dialog_clear(void)
/*
* 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 */
keypad(stdscr, TRUE);
cbreak();
noecho();
- color_setup(getenv("MENUCONFIG_COLOR"));
dialog_clear();
}

@@ -471,3 +476,128 @@ int first_alpha(const char *string, cons

return 0;
}
+
+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);
+}
diff --git a/scripts/kconfig/lxdialog/yesno.c b/scripts/kconfig/lxdialog/yesno.c
index e938037..9fc2449 100644
--- a/scripts/kconfig/lxdialog/yesno.c
+++ b/scripts/kconfig/lxdialog/yesno.c
@@ -99,5 +99,5 @@ int dialog_yesno(const char *title, cons
}

delwin(dialog);
- return -1; /* ESC pressed */
+ return 255; /* ESC pressed */
}
diff --git a/scripts/kconfig/mconf.c b/scripts/kconfig/mconf.c
index 5992673..b1ad9a0 100644
--- a/scripts/kconfig/mconf.c
+++ b/scripts/kconfig/mconf.c
@@ -24,6 +24,7 @@ #include <locale.h>

#define LKC_DIRECT_LINK
#include "lkc.h"
+#include "lxdialog/dialog.h"

static char menu_backtitle[128];
static const char mconf_readme[] = N_(
@@ -270,16 +271,12 @@ search_help[] = N_(
" USB$ => find all CONFIG_ symbols ending with USB\n"
"\n");

-static char buf[4096], *bufptr = buf;
-static char input_buf[4096];
static char filename[PATH_MAX+1] = ".config";
-static char *args[1024], **argptr = args;
static int indent;
static struct termios ios_org;
static int rows = 0, cols = 0;
static struct menu *current_menu;
static int child_count;
-static int do_resize;
static int single_menu_mode;

static void conf(struct menu *menu);
@@ -290,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_helptext(const char *title, const char *text);
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)
{
@@ -332,54 +323,6 @@ static void init_wsize(void)
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)
{
int i, j;
@@ -452,108 +395,17 @@ static struct gstr get_relations_str(str
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)
{
struct symbol **sym_arr;
- int stat;
struct gstr res;
-
+ int dres;
again:
- cprint_init();
- cprint("--title");
- cprint(_("Search Configuration Parameter"));
- cprint("--inputbox");
- cprint(_("Enter CONFIG_ (sub)string to search for (omit CONFIG_)"));
- cprint("10");
- cprint("75");
- cprint("");
- stat = exec_conf();
- if (stat < 0)
- goto again;
- switch (stat) {
+ reset_dialog();
+ dres = dialog_inputbox(_("Search Configuration Parameter"),
+ _("Enter CONFIG_ (sub)string to search for (omit CONFIG_)"),
+ 10, 75, "");
+ switch (dres) {
case 0:
break;
case 1:
@@ -563,7 +415,7 @@ again:
return;
}

- sym_arr = sym_re_search(input_buf);
+ sym_arr = sym_re_search(dialog_input_result);
res = get_relations_str(sym_arr);
free(sym_arr);
show_textbox(_("Search Results"), str_get(&res), 0, 0);
@@ -590,24 +442,24 @@ static void build_conf(struct menu *menu
switch (prop->type) {
case P_MENU:
child_count++;
- cprint("m%p", menu);
-
if (single_menu_mode) {
- cprint1("%s%*c%s",
- menu->data ? "-->" : "++>",
- indent + 1, ' ', prompt);
+ item_make("%s%*c%s",
+ menu->data ? "-->" : "++>",
+ indent + 1, ' ', prompt);
} 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)
goto conf_childs;
return;
default:
if (prompt) {
child_count++;
- cprint(":%p", menu);
- cprint("---%*c%s", indent + 1, ' ', prompt);
+ item_make("---%*c%s", indent + 1, ' ', prompt);
+ item_set_tag(':');
+ item_set_data(menu);
}
}
} else
@@ -628,10 +480,9 @@ static void build_conf(struct menu *menu

val = sym_get_tristate_value(sym);
if (sym_is_changable(sym)) {
- cprint("t%p", menu);
switch (type) {
case S_BOOLEAN:
- cprint1("[%c]", val == no ? ' ' : '*');
+ item_make("[%c]", val == no ? ' ' : '*');
break;
case S_TRISTATE:
switch (val) {
@@ -639,84 +490,87 @@ static void build_conf(struct menu *menu
case mod: ch = 'M'; break;
default: ch = ' '; break;
}
- cprint1("<%c>", ch);
+ item_make("<%c>", ch);
break;
}
+ item_set_tag('t');
+ item_set_data(menu);
} else {
- cprint("%c%p", def_menu ? 't' : ':', menu);
- cprint1(" ");
+ item_make(" ");
+ 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 (def_menu) {
- cprint1(" (%s)", menu_get_prompt(def_menu));
- cprint1(" --->");
- cprint_done();
+ item_add_str(" (%s)", menu_get_prompt(def_menu));
+ item_add_str(" --->");
if (def_menu->list) {
indent += 2;
build_conf(def_menu);
indent -= 2;
}
- } else
- cprint_done();
+ }
return;
}
- cprint_done();
} else {
if (menu == current_menu) {
- cprint(":%p", menu);
- cprint("---%*c%s", indent + 1, ' ', menu_get_prompt(menu));
+ item_make("---%*c%s", indent + 1, ' ', menu_get_prompt(menu));
+ item_set_tag(':');
+ item_set_data(menu);
goto conf_childs;
}
child_count++;
val = sym_get_tristate_value(sym);
if (sym_is_choice_value(sym) && val == yes) {
- cprint(":%p", menu);
- cprint1(" ");
+ item_make(" ");
+ item_set_tag(':');
+ item_set_data(menu);
} else {
switch (type) {
case S_BOOLEAN:
- cprint("t%p", menu);
if (sym_is_changable(sym))
- cprint1("[%c]", val == no ? ' ' : '*');
+ item_make("[%c]", val == no ? ' ' : '*');
else
- cprint1("---");
+ item_make("---");
+ item_set_tag('t');
+ item_set_data(menu);
break;
case S_TRISTATE:
- cprint("t%p", menu);
switch (val) {
case yes: ch = '*'; break;
case mod: ch = 'M'; break;
default: ch = ' '; break;
}
if (sym_is_changable(sym))
- cprint1("<%c>", ch);
+ item_make("<%c>", ch);
else
- cprint1("---");
+ item_make("---");
+ item_set_tag('t');
+ item_set_data(menu);
break;
default:
- cprint("s%p", menu);
- tmp = cprint1("(%s)", sym_get_string_value(sym));
+ tmp = 2 + strlen(sym_get_string_value(sym)); /* () = 2 */
+ item_make("(%s)", sym_get_string_value(sym));
tmp = indent - tmp + 4;
if (tmp < 0)
tmp = 0;
- cprint1("%*c%s%s", tmp, ' ', menu_get_prompt(menu),
- (sym_has_value(sym) || !sym_is_changable(sym)) ?
- "" : " (NEW)");
- cprint_done();
+ item_add_str("%*c%s%s", tmp, ' ', menu_get_prompt(menu),
+ (sym_has_value(sym) || !sym_is_changable(sym)) ?
+ "" : " (NEW)");
+ item_set_tag('s');
+ item_set_data(menu);
goto conf_childs;
}
}
- cprint1("%*c%s%s", indent + 1, ' ', menu_get_prompt(menu),
- (sym_has_value(sym) || !sym_is_changable(sym)) ?
- "" : " (NEW)");
+ item_add_str("%*c%s%s", indent + 1, ' ', menu_get_prompt(menu),
+ (sym_has_value(sym) || !sym_is_changable(sym)) ?
+ "" : " (NEW)");
if (menu->prompt->type == P_MENU) {
- cprint1(" --->");
- cprint_done();
+ item_add_str(" --->");
return;
}
- cprint_done();
}

conf_childs:
@@ -731,59 +585,43 @@ static void conf(struct menu *menu)
struct menu *submenu;
const char *prompt = menu_get_prompt(menu);
struct symbol *sym;
- char active_entry[40];
- int stat, type, i;
+ struct menu *active_menu = NULL;
+ int res;
+ int s_scroll = 0;

- unlink("lxdialog.scrltmp");
- active_entry[0] = 0;
while (1) {
- cprint_init();
- 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);
+ item_reset();
current_menu = menu;
build_conf(menu);
if (!child_count)
break;
if (menu == &rootmenu) {
- cprint(":");
- cprint("--- ");
- cprint("L");
- cprint(_(" Load an Alternate Configuration File"));
- cprint("S");
- cprint(_(" Save Configuration to an Alternate File"));
+ item_make("--- ");
+ item_set_tag(':');
+ item_make(_(" Load an Alternate Configuration File"));
+ item_set_tag('L');
+ item_make(_(" Save an Alternate Configuration File"));
+ item_set_tag('S');
}
- stat = exec_conf();
- if (stat < 0)
- continue;
-
- if (stat == 1 || stat == 255)
+ reset_dialog();
+ res = dialog_menu(prompt ? prompt : _("Main Menu"),
+ _(menu_instructions),
+ rows, cols, rows - 10,
+ active_menu, &s_scroll);
+ if (res == 1 || res == 255)
break;
-
- type = input_buf[0];
- if (!type)
+ if (!item_activate_selected())
+ continue;
+ if (!item_tag())
continue;

- for (i = 0; input_buf[i] && !isspace(input_buf[i]); i++)
- ;
- if (i >= sizeof(active_entry))
- 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;
+ submenu = item_data();
+ active_menu = item_data();
+ sym = submenu->sym;

- switch (stat) {
+ switch (res) {
case 0:
- switch (type) {
+ switch (item_tag()) {
case 'm':
if (single_menu_mode)
submenu->data = (void *) (long) !submenu->data;
@@ -814,7 +652,7 @@ static void conf(struct menu *menu)
show_helptext("README", _(mconf_readme));
break;
case 3:
- if (type == 't') {
+ if (item_is_tag('t')) {
if (sym_set_tristate_value(sym, yes))
break;
if (sym_set_tristate_value(sym, mod))
@@ -822,17 +660,17 @@ static void conf(struct menu *menu)
}
break;
case 4:
- if (type == 't')
+ if (item_is_tag('t'))
sym_set_tristate_value(sym, no);
break;
case 5:
- if (type == 't')
+ if (item_is_tag('t'))
sym_set_tristate_value(sym, mod);
break;
case 6:
- if (type == 't')
+ if (item_is_tag('t'))
sym_toggle_tristate_value(sym);
- else if (type == 'm')
+ else if (item_is_tag('m'))
conf(submenu);
break;
case 7:
@@ -844,13 +682,8 @@ static void conf(struct menu *menu)

static void show_textbox(const char *title, const char *text, int r, int c)
{
- int fd;
-
- fd = creat(".help.tmp", 0777);
- write(fd, text, strlen(text));
- close(fd);
- show_file(".help.tmp", title, r, c);
- unlink(".help.tmp");
+ reset_dialog();
+ dialog_textbox(title, text, r ? r : rows, c ? c : cols);
}

static void show_helptext(const char *title, const char *text)
@@ -878,62 +711,44 @@ static void show_help(struct menu *menu)
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)
{
const char *prompt = menu_get_prompt(menu);
struct menu *child;
struct symbol *active;
- int stat;

active = sym_get_choice_value(menu->sym);
while (1) {
- cprint_init();
- cprint("--title");
- cprint("%s", prompt ? prompt : _("Main Menu"));
- cprint("--radiolist");
- cprint(_(radiolist_instructions));
- cprint("15");
- cprint("70");
- cprint("6");
+ int res;
+ int selected;
+ item_reset();

current_menu = menu;
for (child = menu->list; child; child = child->next) {
if (!menu_is_visible(child))
continue;
- cprint("%p", child);
- cprint("%s", menu_get_prompt(child));
+ item_make("%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))
- cprint("ON");
- else if (child->sym == active)
- cprint("SELECTED");
- else
- cprint("OFF");
+ item_set_tag('X');
}
-
- stat = exec_conf();
- switch (stat) {
+ reset_dialog();
+ res = dialog_checklist(prompt ? prompt : _("Main Menu"),
+ _(radiolist_instructions),
+ 15, 70, 6);
+ selected = item_activate_selected();
+ switch (res) {
case 0:
- if (sscanf(input_buf, "%p", &child) != 1)
- break;
- sym_set_tristate_value(child->sym, yes);
+ if (selected) {
+ child = item_data();
+ sym_set_tristate_value(child->sym, yes);
+ }
return;
case 1:
- if (sscanf(input_buf, "%p", &child) == 1) {
+ if (selected) {
+ child = item_data();
show_help(child);
active = child->sym;
} else
@@ -948,33 +763,31 @@ static void conf_choice(struct menu *men
static void conf_string(struct menu *menu)
{
const char *prompt = menu_get_prompt(menu);
- int stat;

while (1) {
- cprint_init();
- cprint("--title");
- cprint("%s", prompt ? prompt : _("Main Menu"));
- cprint("--inputbox");
+ int res;
+ char *heading;
+
switch (sym_get_type(menu->sym)) {
case S_INT:
- cprint(_(inputbox_instructions_int));
+ heading = _(inputbox_instructions_int);
break;
case S_HEX:
- cprint(_(inputbox_instructions_hex));
+ heading = _(inputbox_instructions_hex);
break;
case S_STRING:
- cprint(_(inputbox_instructions_string));
+ heading = _(inputbox_instructions_string);
break;
default:
- /* panic? */;
+ heading = "Internal mconf error!";
}
- cprint("10");
- cprint("75");
- cprint("%s", sym_get_string_value(menu->sym));
- stat = exec_conf();
- switch (stat) {
+ reset_dialog();
+ res = dialog_inputbox(prompt ? prompt : _("Main Menu"),
+ heading, 10, 75,
+ sym_get_string_value(menu->sym));
+ switch (res) {
case 0:
- if (sym_set_string_value(menu->sym, input_buf))
+ if (sym_set_string_value(menu->sym, dialog_input_result))
return;
show_textbox(NULL, _("You have made an invalid entry."), 5, 43);
break;
@@ -989,21 +802,17 @@ static void conf_string(struct menu *men

static void conf_load(void)
{
- int stat;

while (1) {
- cprint_init();
- cprint("--inputbox");
- cprint(load_config_text);
- cprint("11");
- cprint("55");
- cprint("%s", filename);
- stat = exec_conf();
- switch(stat) {
+ int res;
+ reset_dialog();
+ res = dialog_inputbox(NULL, load_config_text,
+ 11, 55, filename);
+ switch(res) {
case 0:
- if (!input_buf[0])
+ if (!dialog_input_result[0])
return;
- if (!conf_read(input_buf))
+ if (!conf_read(dialog_input_result))
return;
show_textbox(NULL, _("File does not exist!"), 5, 38);
break;
@@ -1018,21 +827,16 @@ static void conf_load(void)

static void conf_save(void)
{
- int stat;
-
while (1) {
- cprint_init();
- cprint("--inputbox");
- cprint(save_config_text);
- cprint("11");
- cprint("55");
- cprint("%s", filename);
- stat = exec_conf();
- switch(stat) {
+ int res;
+ reset_dialog();
+ res = dialog_inputbox(NULL, save_config_text,
+ 11, 55, filename);
+ switch(res) {
case 0:
- if (!input_buf[0])
+ if (!dialog_input_result[0])
return;
- if (!conf_write(input_buf))
+ if (!conf_write(dialog_input_result))
return;
show_textbox(NULL, _("Can't create file! Probably a nonexistent directory."), 5, 60);
break;
@@ -1048,15 +852,13 @@ static void conf_save(void)
static void conf_cleanup(void)
{
tcsetattr(1, TCSAFLUSH, &ios_org);
- unlink(".help.tmp");
- unlink("lxdialog.scrltmp");
}

int main(int ac, char **av)
{
struct symbol *sym;
char *mode;
- int stat;
+ int res;

setlocale(LC_ALL, "");
bindtextdomain(PACKAGE, LOCALEDIR);
@@ -1079,18 +881,16 @@ int main(int ac, char **av)
tcgetattr(1, &ios_org);
atexit(conf_cleanup);
init_wsize();
+ reset_dialog();
+ init_dialog(menu_backtitle);
conf(&rootmenu);
-
- do {
- cprint_init();
- cprint("--yesno");
- cprint(_("Do you wish to save your new kernel configuration?"));
- cprint("5");
- cprint("60");
- stat = exec_conf();
- } while (stat < 0);
-
- if (stat == 0) {
+ reset_dialog();
+ res = dialog_yesno(NULL,
+ _("Do you wish to save your "
+ "new kernel configuration?"),
+ 5, 60);
+ end_dialog();
+ if (res == 0) {
if (conf_write(NULL)) {
fprintf(stderr, _("\n\n"
"Error during writing of the kernel configuration.\n"
--
1.4.1