Browse Source

Copy vendor/linux/2.6.11/scripts/lxdialog to
trunk/uClibc/extra/config/lxdialog.

Peter Kjellerstedt 19 years ago
parent
commit
5178925d7b

+ 4 - 0
extra/config/lxdialog/BIG.FAT.WARNING

@@ -0,0 +1,4 @@
+This is NOT the official version of dialog.  This version has been
+significantly modified from the original.  It is for use by the Linux
+kernel configuration script.  Please do not bother Savio Lam with 
+questions about this program.

+ 42 - 0
extra/config/lxdialog/Makefile

@@ -0,0 +1,42 @@
+HOST_EXTRACFLAGS := -DLOCALE 
+ifeq ($(shell uname),SunOS)
+HOST_LOADLIBES   := -lcurses
+else
+HOST_LOADLIBES   := -lncurses
+endif
+
+ifeq (/usr/include/ncurses/ncurses.h, $(wildcard /usr/include/ncurses/ncurses.h))
+        HOST_EXTRACFLAGS += -I/usr/include/ncurses -DCURSES_LOC="<ncurses.h>"
+else
+ifeq (/usr/include/ncurses/curses.h, $(wildcard /usr/include/ncurses/curses.h))
+        HOST_EXTRACFLAGS += -I/usr/include/ncurses -DCURSES_LOC="<ncurses/curses.h>"
+else
+ifeq (/usr/include/ncurses.h, $(wildcard /usr/include/ncurses.h))
+        HOST_EXTRACFLAGS += -DCURSES_LOC="<ncurses.h>"
+else
+	HOST_EXTRACFLAGS += -DCURSES_LOC="<curses.h>"
+endif
+endif
+endif
+
+hostprogs-y	:= lxdialog
+always		:= ncurses $(hostprogs-y)
+
+lxdialog-objs := checklist.o menubox.o textbox.o yesno.o inputbox.o \
+		 util.o lxdialog.o msgbox.o
+
+.PHONY: $(obj)/ncurses
+$(obj)/ncurses:
+	@echo "main() {}" > lxtemp.c
+	@if $(HOSTCC) lxtemp.c  $(HOST_LOADLIBES); then \
+		rm -f lxtemp.c a.out; \
+	else \
+		rm -f lxtemp.c; \
+		echo -e "\007" ;\
+		echo ">> Unable to find the Ncurses libraries." ;\
+		echo ">>" ;\
+		echo ">> You must install ncurses-devel in order" ;\
+		echo ">> to use 'make menuconfig'" ;\
+		echo ;\
+		exit 1 ;\
+	fi

+ 373 - 0
extra/config/lxdialog/checklist.c

@@ -0,0 +1,373 @@
+/*
+ *  checklist.c -- implements the checklist box
+ *
+ *  ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
+ *     Stuart Herbert - S.Herbert@sheffield.ac.uk: radiolist extension
+ *     Alessandro Rubini - rubini@ipvvis.unipv.it: merged the two
+ *  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 int list_width, check_x, item_x, checkflag;
+
+/*
+ * Print list item
+ */
+static void
+print_item (WINDOW * win, const char *item, int status,
+	    int choice, int selected)
+{
+    int i;
+
+    /* Clear 'residue' of last item */
+    wattrset (win, menubox_attr);
+    wmove (win, choice, 0);
+    for (i = 0; i < list_width; i++)
+	waddch (win, ' ');
+
+    wmove (win, choice, check_x);
+    wattrset (win, selected ? check_selected_attr : check_attr);
+    if (checkflag == FLAG_CHECK)
+	wprintw (win, "[%c]", status ? 'X' : ' ');
+    else
+	wprintw (win, "(%c)", status ? 'X' : ' ');
+
+    wattrset (win, selected ? tag_selected_attr : tag_attr);
+    mvwaddch(win, choice, item_x, item[0]);
+    wattrset (win, selected ? item_selected_attr : item_attr);
+    waddstr (win, (char *)item+1);
+    if (selected) {
+    	wmove (win, choice, check_x+1);
+    	wrefresh (win);
+    }
+}
+
+/*
+ * Print the scroll indicators.
+ */
+static void
+print_arrows (WINDOW * win, int choice, int item_no, int scroll,
+		int y, int x, int height)
+{
+    wmove(win, y, x);
+
+    if (scroll > 0) {
+	wattrset (win, uarrow_attr);
+	waddch (win, ACS_UARROW);
+	waddstr (win, "(-)");
+    }
+    else {
+	wattrset (win, menubox_attr);
+	waddch (win, ACS_HLINE);
+	waddch (win, ACS_HLINE);
+	waddch (win, ACS_HLINE);
+	waddch (win, ACS_HLINE);
+    }
+
+   y = y + height + 1;
+   wmove(win, y, x);
+
+   if ((height < item_no) && (scroll + choice < item_no - 1)) {
+	wattrset (win, darrow_attr);
+	waddch (win, ACS_DARROW);
+	waddstr (win, "(+)");
+    }
+    else {
+	wattrset (win, menubox_border_attr);
+	waddch (win, ACS_HLINE);
+	waddch (win, ACS_HLINE);
+	waddch (win, ACS_HLINE);
+	waddch (win, ACS_HLINE);
+   }
+}
+
+/*
+ *  Display the termination buttons
+ */
+static void
+print_buttons( WINDOW *dialog, int height, int width, int selected)
+{
+    int x = width / 2 - 11;
+    int y = height - 2;
+
+    print_button (dialog, "Select", y, x, selected == 0);
+    print_button (dialog, " Help ", y, x + 14, selected == 1);
+
+    wmove(dialog, y, x+1 + 14*selected);
+    wrefresh (dialog);
+}
+
+/*
+ * Display a dialog box with a list of options that can be turned on or off
+ * The `flag' parameter is used to select between radiolist and checklist.
+ */
+int
+dialog_checklist (const char *title, const char *prompt, int height, int width,
+	int list_height, int item_no, const char * const * items, int flag)
+	
+{
+    int i, x, y, box_x, box_y;
+    int key = 0, button = 0, choice = 0, scroll = 0, max_choice, *status;
+    WINDOW *dialog, *list;
+
+    checkflag = flag;
+
+    /* 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;
+    }
+    if (choice)
+	    choice--;
+
+    max_choice = MIN (list_height, item_no);
+
+    /* 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);
+    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);
+
+    if (title != NULL && strlen(title) >= width-2 ) {
+	/* truncate long title -- mec */
+	char * title2 = malloc(width-2+1);
+	memcpy( title2, title, width-2 );
+	title2[width-2] = '\0';
+	title = title2;
+    }
+
+    if (title != NULL) {
+	wattrset (dialog, title_attr);
+	mvwaddch (dialog, 0, (width - strlen(title))/2 - 1, ' ');
+	waddstr (dialog, (char *)title);
+	waddch (dialog, ' ');
+    }
+
+    wattrset (dialog, dialog_attr);
+    print_autowrap (dialog, prompt, width - 2, 1, 3);
+
+    list_width = width - 6;
+    box_y = height - list_height - 5;
+    box_x = (width - list_width) / 2 - 1;
+
+    /* create new window for the list */
+    list = subwin (dialog, list_height, list_width, y+box_y+1, x+box_x+1);
+
+    keypad (list, TRUE);
+
+    /* draw a box around the list items */
+    draw_box (dialog, box_y, box_x, list_height + 2, list_width + 2,
+	      menubox_border_attr, menubox_attr);
+
+    /* 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);
+
+    check_x = (list_width - check_x) / 2;
+    item_x = check_x + 4;
+
+    if (choice >= list_height) {
+	scroll = choice - list_height + 1;
+	choice -= scroll;
+    }
+
+    /* Print the list */
+    for (i = 0; i < max_choice; i++) {
+	print_item (list, items[(scroll+i) * 3 + 1],
+		    status[i+scroll], i, i == choice);
+    }
+
+    print_arrows(dialog, choice, item_no, scroll,
+			box_y, box_x + check_x + 5, list_height);
+
+    print_buttons(dialog, height, width, 0);
+
+    wnoutrefresh (list);
+    wnoutrefresh (dialog);
+    doupdate ();
+
+    while (key != ESC) {
+	key = wgetch (dialog);
+
+    	for (i = 0; i < max_choice; i++)
+            if (toupper(key) == toupper(items[(scroll+i)*3+1][0]))
+                break;
+
+
+	if ( i < max_choice || key == KEY_UP || key == KEY_DOWN || 
+	    key == '+' || key == '-' ) {
+	    if (key == KEY_UP || key == '-') {
+		if (!choice) {
+		    if (!scroll)
+			continue;
+		    /* Scroll list down */
+		    if (list_height > 1) {
+			/* De-highlight current first item */
+			print_item (list, items[scroll * 3 + 1],
+					status[scroll], 0, FALSE);
+			scrollok (list, TRUE);
+			wscrl (list, -1);
+			scrollok (list, FALSE);
+		    }
+		    scroll--;
+		    print_item (list, items[scroll * 3 + 1],
+				status[scroll], 0, TRUE);
+		    wnoutrefresh (list);
+
+    		    print_arrows(dialog, choice, item_no, scroll,
+				box_y, box_x + check_x + 5, list_height);
+
+		    wrefresh (dialog);
+
+		    continue;	/* wait for another key press */
+		} else
+		    i = choice - 1;
+	    } else if (key == KEY_DOWN || key == '+') {
+		if (choice == max_choice - 1) {
+		    if (scroll + choice >= item_no - 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);
+			scrollok (list, TRUE);
+			scroll (list);
+			scrollok (list, FALSE);
+		    }
+		    scroll++;
+		    print_item (list, items[(scroll + max_choice - 1) * 3 + 1],
+				status[scroll + max_choice - 1],
+				max_choice - 1, TRUE);
+		    wnoutrefresh (list);
+
+    		    print_arrows(dialog, choice, item_no, scroll,
+				box_y, box_x + check_x + 5, list_height);
+
+		    wrefresh (dialog);
+
+		    continue;	/* wait for another key press */
+		} else
+		    i = choice + 1;
+	    }
+	    if (i != choice) {
+		/* De-highlight current item */
+		print_item (list, items[(scroll + choice) * 3 + 1],
+			    status[scroll + choice], choice, FALSE);
+		/* Highlight new item */
+		choice = i;
+		print_item (list, items[(scroll + choice) * 3 + 1],
+			    status[scroll + choice], choice, TRUE);
+		wnoutrefresh (list);
+		wrefresh (dialog);
+	    }
+	    continue;		/* wait for another key press */
+	}
+	switch (key) {
+	case 'H':
+	case 'h':
+	case '?':
+	    fprintf (stderr, "%s", items[(scroll + choice) * 3]);
+	    delwin (dialog);
+	    free (status);
+	    return 1;
+	case TAB:
+	case KEY_LEFT:
+	case KEY_RIGHT:
+	    button = ((key == KEY_LEFT ? --button : ++button) < 0)
+			? 1 : (button > 1 ? 0 : button);
+
+	    print_buttons(dialog, height, width, button);
+	    wrefresh (dialog);
+	    break;
+	case 'S':
+	case 's':
+	case ' ':
+	case '\n':
+	    if (!button) {
+		if (flag == FLAG_CHECK) {
+		    status[scroll + choice] = !status[scroll + choice];
+		    wmove (list, choice, check_x);
+		    wattrset (list, check_selected_attr);
+		    wprintw (list, "[%c]", status[scroll + choice] ? 'X' : ' ');
+		} else {
+		    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 (list);
+		wrefresh (dialog);
+            
+		for (i = 0; i < item_no; i++) {
+		    if (status[i]) {
+			if (flag == FLAG_CHECK) {
+			    fprintf (stderr, "\"%s\" ", items[i * 3]);
+			} else {
+			    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;
+	case ESC:
+	    break;
+	}
+
+	/* Now, update everything... */
+	doupdate ();
+    }
+    
+
+    delwin (dialog);
+    free (status);
+    return -1;			/* ESC pressed */
+}

+ 161 - 0
extra/config/lxdialog/colors.h

@@ -0,0 +1,161 @@
+/*
+ *  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
+ */
+
+typedef struct {
+    char name[COLOR_NAME_LEN];
+    int value;
+} color_names_st;
+
+extern color_names_st color_names[];
+extern int color_table[][3];

+ 187 - 0
extra/config/lxdialog/dialog.h

@@ -0,0 +1,187 @@
+
+/*
+ *  dialog.h -- common declarations for all dialog modules
+ *
+ *  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.
+ */
+
+#include <sys/types.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef __sun__
+#define CURS_MACROS
+#endif
+#include CURSES_LOC
+
+/*
+ * Colors in ncurses 1.9.9e do not work properly since foreground and
+ * background colors are OR'd rather than separately masked.  This version
+ * of dialog was hacked to work with ncurses 1.9.9e, making it incompatible
+ * with standard curses.  The simplest fix (to make this work with standard
+ * curses) uses the wbkgdset() function, not used in the original hack.
+ * Turn it off if we're building with 1.9.9e, since it just confuses things.
+ */
+#if defined(NCURSES_VERSION) && defined(_NEED_WRAP) && !defined(GCC_PRINTFLIKE)
+#define OLD_NCURSES 1
+#undef  wbkgdset
+#define wbkgdset(w,p) /*nothing*/
+#else
+#define OLD_NCURSES 0
+#endif
+
+#define TR(params) _tracef params
+
+#define ESC 27
+#define TAB 9
+#define MAX_LEN 2048
+#define BUF_SIZE (10*1024)
+#define MIN(x,y) (x < y ? x : y)
+#define MAX(x,y) (x > y ? x : y)
+
+
+#ifndef ACS_ULCORNER
+#define ACS_ULCORNER '+'
+#endif
+#ifndef ACS_LLCORNER
+#define ACS_LLCORNER '+'
+#endif
+#ifndef ACS_URCORNER
+#define ACS_URCORNER '+'
+#endif
+#ifndef ACS_LRCORNER
+#define ACS_LRCORNER '+'
+#endif
+#ifndef ACS_HLINE
+#define ACS_HLINE '-'
+#endif
+#ifndef ACS_VLINE
+#define ACS_VLINE '|'
+#endif
+#ifndef ACS_LTEE
+#define ACS_LTEE '+'
+#endif
+#ifndef ACS_RTEE
+#define ACS_RTEE '+'
+#endif
+#ifndef ACS_UARROW
+#define ACS_UARROW '^'
+#endif
+#ifndef ACS_DARROW
+#define ACS_DARROW 'v'
+#endif
+
+/* 
+ * Attribute names
+ */
+#define screen_attr                   attributes[0]
+#define shadow_attr                   attributes[1]
+#define dialog_attr                   attributes[2]
+#define title_attr                    attributes[3]
+#define border_attr                   attributes[4]
+#define button_active_attr            attributes[5]
+#define button_inactive_attr          attributes[6]
+#define button_key_active_attr        attributes[7]
+#define button_key_inactive_attr      attributes[8]
+#define button_label_active_attr      attributes[9]
+#define button_label_inactive_attr    attributes[10]
+#define inputbox_attr                 attributes[11]
+#define inputbox_border_attr          attributes[12]
+#define searchbox_attr                attributes[13]
+#define searchbox_title_attr          attributes[14]
+#define searchbox_border_attr         attributes[15]
+#define position_indicator_attr       attributes[16]
+#define menubox_attr                  attributes[17]
+#define menubox_border_attr           attributes[18]
+#define item_attr                     attributes[19]
+#define item_selected_attr            attributes[20]
+#define tag_attr                      attributes[21]
+#define tag_selected_attr             attributes[22]
+#define tag_key_attr                  attributes[23]
+#define tag_key_selected_attr         attributes[24]
+#define check_attr                    attributes[25]
+#define check_selected_attr           attributes[26]
+#define uarrow_attr                   attributes[27]
+#define darrow_attr                   attributes[28]
+
+/* number of attributes */
+#define ATTRIBUTE_COUNT               29
+
+/*
+ * Global variables
+ */
+extern bool use_colors;
+extern bool use_shadow;
+
+extern chtype attributes[];
+
+extern const char *backtitle;
+
+/*
+ * Function prototypes
+ */
+extern void create_rc (const char *filename);
+extern int parse_rc (void);
+
+
+void init_dialog (void);
+void end_dialog (void);
+void attr_clear (WINDOW * win, int height, int width, chtype attr);
+void dialog_clear (void);
+void color_setup (void);
+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 draw_box (WINDOW * win, int y, int x, int height, int width, chtype box,
+		chtype border);
+void draw_shadow (WINDOW * win, int y, int x, int height, int width);
+
+int first_alpha (const char *string, const char *exempt);
+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 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 dialog_checklist (const char *title, const char *prompt, int height,
+		int width, int list_height, int item_no,
+		const char * const * items, int flag);
+extern unsigned char dialog_input_result[];
+int dialog_inputbox (const char *title, const char *prompt, int height,
+		int width, const char *init);
+
+/*
+ * This is the base for fictitious keys, which activate
+ * the buttons.
+ *
+ * Mouse-generated keys are the following:
+ *   -- the first 32 are used as numbers, in addition to '0'-'9'
+ *   -- the lowercase are used to signal mouse-enter events (M_EVENT + 'o')
+ *   -- uppercase chars are used to invoke the button (M_EVENT + 'O')
+ */
+#define M_EVENT (KEY_MAX+1)
+
+
+/*
+ * The `flag' parameter in checklist is used to select between
+ * radiolist and checklist
+ */
+#define FLAG_CHECK 1
+#define FLAG_RADIO 0

+ 240 - 0
extra/config/lxdialog/inputbox.c

@@ -0,0 +1,240 @@
+/*
+ *  inputbox.c -- implements the input box
+ *
+ *  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"
+
+unsigned char dialog_input_result[MAX_LEN + 1];
+
+/*
+ *  Print the termination buttons
+ */
+static void
+print_buttons(WINDOW *dialog, int height, int width, int selected)
+{
+    int x = width / 2 - 11;
+    int y = height - 2;
+
+    print_button (dialog, "  Ok  ", y, x, selected==0);
+    print_button (dialog, " Help ", y, x + 14, selected==1);
+
+    wmove(dialog, y, x+1+14*selected);
+    wrefresh(dialog);
+}
+
+/*
+ * Display a dialog box for inputing a string
+ */
+int
+dialog_inputbox (const char *title, const char *prompt, int height, int width,
+		 const char *init)
+{
+    int i, x, y, box_y, box_x, box_width;
+    int input_x = 0, scroll = 0, key = 0, button = -1;
+    unsigned char *instr = dialog_input_result;
+    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);
+    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);
+
+    if (title != NULL && strlen(title) >= width-2 ) {
+	/* truncate long title -- mec */
+	char * title2 = malloc(width-2+1);
+	memcpy( title2, title, width-2 );
+	title2[width-2] = '\0';
+	title = title2;
+    }
+
+    if (title != NULL) {
+	wattrset (dialog, title_attr);
+	mvwaddch (dialog, 0, (width - strlen(title))/2 - 1, ' ');
+	waddstr (dialog, (char *)title);
+	waddch (dialog, ' ');
+    }
+
+    wattrset (dialog, dialog_attr);
+    print_autowrap (dialog, prompt, width - 2, 1, 3);
+
+    /* Draw the input field box */
+    box_width = width - 6;
+    getyx (dialog, y, x);
+    box_y = y + 2;
+    box_x = (width - box_width) / 2;
+    draw_box (dialog, y + 1, box_x - 1, 3, box_width + 2,
+	      border_attr, dialog_attr);
+
+    print_buttons(dialog, height, width, 0);
+
+    /* Set up the initial value */
+    wmove (dialog, box_y, box_x);
+    wattrset (dialog, inputbox_attr);
+
+    if (!init)
+	instr[0] = '\0';
+    else
+	strcpy (instr, init);
+
+    input_x = strlen (instr);
+
+    if (input_x >= box_width) {
+	scroll = input_x - box_width + 1;
+	input_x = box_width - 1;
+	for (i = 0; i < box_width - 1; i++)
+	    waddch (dialog, instr[scroll + i]);
+    } else
+	waddstr (dialog, instr);
+
+    wmove (dialog, box_y, box_x + input_x);
+
+    wrefresh (dialog);
+
+    while (key != ESC) {
+	key = wgetch (dialog);
+
+	if (button == -1) {	/* Input box selected */
+	    switch (key) {
+	    case TAB:
+	    case KEY_UP:
+	    case KEY_DOWN:
+		break;
+	    case KEY_LEFT:
+		continue;
+	    case KEY_RIGHT:
+		continue;
+	    case KEY_BACKSPACE:
+	    case 127:
+		if (input_x || scroll) {
+		    wattrset (dialog, inputbox_attr);
+		    if (!input_x) {
+			scroll = scroll < box_width - 1 ?
+			    0 : scroll - (box_width - 1);
+			wmove (dialog, box_y, box_x);
+			for (i = 0; i < box_width; i++)
+			    waddch (dialog, instr[scroll + input_x + i] ?
+				    instr[scroll + input_x + i] : ' ');
+			input_x = strlen (instr) - scroll;
+		    } else
+			input_x--;
+		    instr[scroll + input_x] = '\0';
+		    mvwaddch (dialog, box_y, input_x + box_x, ' ');
+		    wmove (dialog, box_y, input_x + box_x);
+		    wrefresh (dialog);
+		}
+		continue;
+	    default:
+		if (key < 0x100 && isprint (key)) {
+		    if (scroll + input_x < MAX_LEN) {
+			wattrset (dialog, inputbox_attr);
+			instr[scroll + input_x] = key;
+			instr[scroll + input_x + 1] = '\0';
+			if (input_x == box_width - 1) {
+			    scroll++;
+			    wmove (dialog, box_y, box_x);
+			    for (i = 0; i < box_width - 1; i++)
+				waddch (dialog, instr[scroll + i]);
+			} else {
+			    wmove (dialog, box_y, input_x++ + box_x);
+			    waddch (dialog, key);
+			}
+			wrefresh (dialog);
+		    } else
+			flash ();	/* Alarm user about overflow */
+		    continue;
+		}
+	    }
+	}
+	switch (key) {
+	case 'O':
+	case 'o':
+	    delwin (dialog);
+	    return 0;
+	case 'H':
+	case 'h':
+	    delwin (dialog);
+	    return 1;
+	case KEY_UP:
+	case KEY_LEFT:
+	    switch (button) {
+	    case -1:
+		button = 1;	/* Indicates "Cancel" button is selected */
+		print_buttons(dialog, height, width, 1);
+		break;
+	    case 0:
+		button = -1;	/* Indicates input box is selected */
+		print_buttons(dialog, height, width, 0);
+		wmove (dialog, box_y, box_x + input_x);
+		wrefresh (dialog);
+		break;
+	    case 1:
+		button = 0;	/* Indicates "OK" button is selected */
+		print_buttons(dialog, height, width, 0);
+		break;
+	    }
+	    break;
+	case TAB:
+	case KEY_DOWN:
+	case KEY_RIGHT:
+	    switch (button) {
+	    case -1:
+		button = 0;	/* Indicates "OK" button is selected */
+		print_buttons(dialog, height, width, 0);
+		break;
+	    case 0:
+		button = 1;	/* Indicates "Cancel" button is selected */
+		print_buttons(dialog, height, width, 1);
+		break;
+	    case 1:
+		button = -1;	/* Indicates input box is selected */
+		print_buttons(dialog, height, width, 0);
+		wmove (dialog, box_y, box_x + input_x);
+		wrefresh (dialog);
+		break;
+	    }
+	    break;
+	case ' ':
+	case '\n':
+	    delwin (dialog);
+	    return (button == -1 ? 0 : button);
+	case 'X':
+	case 'x':
+	    key = ESC;
+	case ESC:
+	    break;
+	}
+    }
+
+    delwin (dialog);
+    return -1;			/* ESC pressed */
+}

+ 226 - 0
extra/config/lxdialog/lxdialog.c

@@ -0,0 +1,226 @@
+/*
+ *  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_checklist, j_radiolist, j_yesno, j_textbox, j_inputbox;
+jumperFn j_msgbox, j_infobox;
+
+static struct Mode modes[] =
+{
+    {"--menu", 9, 0, 3, j_menu},
+    {"--checklist", 9, 0, 3, j_checklist},
+    {"--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, clear_screen = 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 (clear_screen) {	/* 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 {
+		clear_screen = 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 (clear_screen) {		/* 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  --checklist <text> <height> <width> <list height> <tag1> <item1> <status1>...\
+\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_checklist (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, FLAG_CHECK);
+}
+
+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, FLAG_RADIO);
+}
+
+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);
+}
+

+ 445 - 0
extra/config/lxdialog/menubox.c

@@ -0,0 +1,445 @@
+/*
+ *  menubox.c -- implements the menu 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.
+ */
+
+/*
+ *  Changes by Clifford Wolf (god@clifford.at)
+ *
+ *  [ 1998-06-13 ]
+ *
+ *    *)  A bugfix for the Page-Down problem
+ *
+ *    *)  Formerly when I used Page Down and Page Up, the cursor would be set 
+ *        to the first position in the menu box.  Now lxdialog is a bit
+ *        smarter and works more like other menu systems (just have a look at
+ *        it).
+ *
+ *    *)  Formerly if I selected something my scrolling would be broken because
+ *        lxdialog is re-invoked by the Menuconfig shell script, can't
+ *        remember the last scrolling position, and just sets it so that the
+ *        cursor is at the bottom of the box.  Now it writes the temporary file
+ *        lxdialog.scrltmp which contains this information. The file is
+ *        deleted by lxdialog if the user leaves a submenu or enters a new
+ *        one, but it would be nice if Menuconfig could make another "rm -f"
+ *        just to be sure.  Just try it out - you will recognise a difference!
+ *
+ *  [ 1998-06-14 ]
+ *
+ *    *)  Now lxdialog is crash-safe against broken "lxdialog.scrltmp" files
+ *        and menus change their size on the fly.
+ *
+ *    *)  If for some reason the last scrolling position is not saved by
+ *        lxdialog, it sets the scrolling so that the selected item is in the
+ *        middle of the menu box, not at the bottom.
+ *
+ * 02 January 1999, Michael Elizabeth Chastain (mec@shout.net)
+ * Reset 'scroll' to 0 if the value from lxdialog.scrltmp is bogus.
+ * This fixes a bug in Menuconfig where using ' ' to descend into menus
+ * would leave mis-synchronized lxdialog.scrltmp files lying around,
+ * fscanf would read in 'scroll', and eventually that value would get used.
+ */
+
+#include "dialog.h"
+
+static int menu_width, item_x;
+
+/*
+ * Print menu item
+ */
+static void
+print_item (WINDOW * win, const char *item, int choice, int selected, int hotkey)
+{
+    int j;
+    char menu_item[menu_width+1];
+
+    strncpy(menu_item, item, menu_width);
+    menu_item[menu_width] = 0;
+    j = first_alpha(menu_item, "YyNnMmHh");
+
+    /* Clear 'residue' of last item */
+    wattrset (win, menubox_attr);
+    wmove (win, choice, 0);
+#if OLD_NCURSES
+    {
+        int i;
+        for (i = 0; i < menu_width; i++)
+	    waddch (win, ' ');
+    }
+#else
+    wclrtoeol(win);
+#endif
+    wattrset (win, selected ? item_selected_attr : item_attr);
+    mvwaddstr (win, choice, item_x, menu_item);
+    if (hotkey) {
+    	wattrset (win, selected ? tag_key_selected_attr : tag_key_attr);
+    	mvwaddch(win, choice, item_x+j, menu_item[j]);
+    }
+    if (selected) {
+	wmove (win, choice, item_x+1);
+	wrefresh (win);
+    }
+}
+
+/*
+ * Print the scroll indicators.
+ */
+static void
+print_arrows (WINDOW * win, int item_no, int scroll,
+		int y, int x, int height)
+{
+    int cur_y, cur_x;
+
+    getyx(win, cur_y, cur_x);
+
+    wmove(win, y, x);
+
+    if (scroll > 0) {
+	wattrset (win, uarrow_attr);
+	waddch (win, ACS_UARROW);
+	waddstr (win, "(-)");
+    }
+    else {
+	wattrset (win, menubox_attr);
+	waddch (win, ACS_HLINE);
+	waddch (win, ACS_HLINE);
+	waddch (win, ACS_HLINE);
+	waddch (win, ACS_HLINE);
+    }
+
+   y = y + height + 1;
+   wmove(win, y, x);
+
+   if ((height < item_no) && (scroll + height < item_no)) {
+	wattrset (win, darrow_attr);
+	waddch (win, ACS_DARROW);
+	waddstr (win, "(+)");
+    }
+    else {
+	wattrset (win, menubox_border_attr);
+	waddch (win, ACS_HLINE);
+	waddch (win, ACS_HLINE);
+	waddch (win, ACS_HLINE);
+	waddch (win, ACS_HLINE);
+   }
+
+   wmove(win, cur_y, cur_x);
+}
+
+/*
+ * Display the termination buttons.
+ */
+static void
+print_buttons (WINDOW *win, int height, int width, int selected)
+{
+    int x = width / 2 - 16;
+    int y = height - 2;
+
+    print_button (win, "Select", y, x, selected == 0);
+    print_button (win, " Exit ", y, x + 12, selected == 1);
+    print_button (win, " Help ", y, x + 24, selected == 2);
+
+    wmove(win, y, x+1+12*selected);
+    wrefresh (win);
+}
+
+/*
+ * 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 i, j, x, y, box_x, box_y;
+    int key = 0, button = 0, scroll = 0, choice = 0, first_item = 0, max_choice;
+    WINDOW *dialog, *menu;
+    FILE *f;
+
+    max_choice = MIN (menu_height, item_no);
+
+    /* 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);
+    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);
+    wbkgdset (dialog, dialog_attr & A_COLOR);
+    waddch (dialog, ACS_RTEE);
+
+    if (title != NULL && strlen(title) >= width-2 ) {
+	/* truncate long title -- mec */
+	char * title2 = malloc(width-2+1);
+	memcpy( title2, title, width-2 );
+	title2[width-2] = '\0';
+	title = title2;
+    }
+
+    if (title != NULL) {
+	wattrset (dialog, title_attr);
+	mvwaddch (dialog, 0, (width - strlen(title))/2 - 1, ' ');
+	waddstr (dialog, (char *)title);
+	waddch (dialog, ' ');
+    }
+
+    wattrset (dialog, dialog_attr);
+    print_autowrap (dialog, prompt, width - 2, 1, 3);
+
+    menu_width = width - 6;
+    box_y = height - menu_height - 5;
+    box_x = (width - menu_width) / 2 - 1;
+
+    /* create new window for the menu */
+    menu = subwin (dialog, menu_height, menu_width,
+		y + box_y + 1, x + box_x + 1);
+    keypad (menu, TRUE);
+
+    /* draw a box around the menu items */
+    draw_box (dialog, box_y, box_x, menu_height + 2, menu_width + 2,
+	      menubox_border_attr, menubox_attr);
+
+    /*
+     * Find length of longest item in order to center menu.
+     * Set 'choice' to default item. 
+     */
+    item_x = 0;
+    for (i = 0; i < item_no; i++) {
+	item_x = MAX (item_x, MIN(menu_width, strlen (items[i * 2 + 1]) + 2));
+	if (strcmp(current, items[i*2]) == 0) choice = i;
+    }
+
+    item_x = (menu_width - item_x) / 2;
+
+    /* 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;
+	}
+    }
+    if ( (choice >= max_choice) || (f==NULL && choice >= max_choice/2) ) {
+	if (choice >= item_no-max_choice/2)
+	    scroll = first_item = item_no-max_choice;
+	else
+	    scroll = first_item = choice - max_choice/2;
+	choice = choice - scroll;
+    }
+
+    /* Print the menu */
+    for (i=0; i < max_choice; i++) {
+	print_item (menu, items[(first_item + i) * 2 + 1], i, i == choice,
+                    (items[(first_item + i)*2][0] != ':'));
+    }
+
+    wnoutrefresh (menu);
+
+    print_arrows(dialog, item_no, scroll,
+		 box_y, box_x+item_x+1, menu_height);
+
+    print_buttons (dialog, height, width, 0);
+    wmove (menu, choice, item_x+1);
+    wrefresh (menu);
+
+    while (key != ESC) {
+	key = wgetch(menu);
+
+	if (key < 256 && isalpha(key)) key = tolower(key);
+
+	if (strchr("ynmh", key))
+		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]))
+                	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]))
+                		break;
+		}
+	}
+
+	if (i < max_choice || 
+            key == KEY_UP || key == KEY_DOWN ||
+            key == '-' || key == '+' ||
+            key == KEY_PPAGE || key == KEY_NPAGE) {
+
+            print_item (menu, items[(scroll+choice)*2+1], choice, FALSE,
+                       (items[(scroll+choice)*2][0] != ':'));
+
+	    if (key == KEY_UP || key == '-') {
+                if (choice < 2 && scroll) {
+	            /* Scroll menu down */
+                    scrollok (menu, TRUE);
+                    wscrl (menu, -1);
+                    scrollok (menu, FALSE);
+
+                    scroll--;
+
+                    print_item (menu, items[scroll * 2 + 1], 0, FALSE,
+                               (items[scroll*2][0] != ':'));
+		} else
+		    choice = MAX(choice - 1, 0);
+
+	    } else if (key == KEY_DOWN || key == '+')  {
+
+		print_item (menu, items[(scroll+choice)*2+1], choice, FALSE,
+                                (items[(scroll+choice)*2][0] != ':'));
+
+                if ((choice > max_choice-3) &&
+                    (scroll + max_choice < item_no)
+                   ) {
+		    /* Scroll menu up */
+		    scrollok (menu, TRUE);
+                    scroll (menu);
+                    scrollok (menu, FALSE);
+
+                    scroll++;
+
+                    print_item (menu, items[(scroll+max_choice-1)*2+1],
+                               max_choice-1, FALSE,
+                               (items[(scroll+max_choice-1)*2][0] != ':'));
+                } else
+                    choice = MIN(choice+1, max_choice-1);
+
+	    } else if (key == KEY_PPAGE) {
+	        scrollok (menu, TRUE);
+                for (i=0; (i < max_choice); i++) {
+                    if (scroll > 0) {
+                	wscrl (menu, -1);
+                	scroll--;
+                	print_item (menu, items[scroll * 2 + 1], 0, FALSE,
+                	(items[scroll*2][0] != ':'));
+                    } else {
+                        if (choice > 0)
+                            choice--;
+                    }
+                }
+                scrollok (menu, FALSE);
+
+            } else if (key == KEY_NPAGE) {
+                for (i=0; (i < max_choice); i++) {
+                    if (scroll+max_choice < item_no) {
+			scrollok (menu, TRUE);
+			scroll(menu);
+			scrollok (menu, FALSE);
+                	scroll++;
+                	print_item (menu, items[(scroll+max_choice-1)*2+1],
+			            max_choice-1, FALSE,
+			            (items[(scroll+max_choice-1)*2][0] != ':'));
+		    } else {
+			if (choice+1 < max_choice)
+			    choice++;
+		    }
+                }
+
+            } else
+                choice = i;
+
+            print_item (menu, items[(scroll+choice)*2+1], choice, TRUE,
+                       (items[(scroll+choice)*2][0] != ':'));
+
+            print_arrows(dialog, item_no, scroll,
+                         box_y, box_x+item_x+1, menu_height);
+
+            wnoutrefresh (dialog);
+            wrefresh (menu);
+
+	    continue;		/* wait for another key press */
+        }
+
+	switch (key) {
+	case KEY_LEFT:
+	case TAB:
+	case KEY_RIGHT:
+	    button = ((key == KEY_LEFT ? --button : ++button) < 0)
+			? 2 : (button > 2 ? 0 : button);
+
+	    print_buttons(dialog, height, width, button);
+	    wrefresh (menu);
+	    break;
+	case ' ':
+	case 's':
+	case 'y':
+	case 'n':
+	case 'm':
+	case '/':
+	    /* save scroll info */
+	    if ( (f=fopen("lxdialog.scrltmp","w")) != NULL ) {
+		fprintf(f,"%d\n",scroll);
+		fclose(f);
+	    }
+	    delwin (dialog);
+            fprintf(stderr, "%s\n", items[(scroll + choice) * 2]);
+            switch (key) {
+            case 's': return 3;
+            case 'y': return 3;
+            case 'n': return 4;
+            case 'm': return 5;
+            case ' ': return 6;
+            case '/': return 7;
+            }
+	    return 0;
+	case 'h':
+	case '?':
+	    button = 2;
+	case '\n':
+	    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");
+	    return button;
+	case 'e':
+	case 'x':
+	    key = ESC;
+	case ESC:
+	    break;
+	}
+    }
+
+    delwin (dialog);
+    remove("lxdialog.scrltmp");
+    return -1;			/* ESC pressed */
+}

+ 85 - 0
extra/config/lxdialog/msgbox.c

@@ -0,0 +1,85 @@
+/*
+ *  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);
+
+    if (title != NULL && strlen(title) >= width-2 ) {
+	/* truncate long title -- mec */
+	char * title2 = malloc(width-2+1);
+	memcpy( title2, title, width-2 );
+	title2[width-2] = '\0';
+	title = title2;
+    }
+
+    if (title != NULL) {
+	wattrset (dialog, title_attr);
+	mvwaddch (dialog, 0, (width - strlen(title))/2 - 1, ' ');
+	waddstr (dialog, (char *)title);
+	waddch (dialog, ' ');
+    }
+    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;
+}

+ 556 - 0
extra/config/lxdialog/textbox.c

@@ -0,0 +1,556 @@
+/*
+ *  textbox.c -- implements the text box
+ *
+ *  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 back_lines (int n);
+static void print_page (WINDOW * win, int height, int width);
+static void print_line (WINDOW * win, int row, int width);
+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;
+
+/*
+ * Display text from a file in a dialog box.
+ */
+int
+dialog_textbox (const char *title, const char *file, int height, int width)
+{
+    int i, x, y, cur_x, cur_y, fpos, key = 0;
+    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 */
+
+    /* 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);
+
+    /* Create window for text region, used for scrolling text */
+    text = subwin (dialog, height - 4, width - 2, y + 1, x + 1);
+    wattrset (text, dialog_attr);
+    wbkgdset (text, dialog_attr & A_COLOR);
+
+    keypad (text, TRUE);
+
+    /* register the new window, along with its borders */
+    draw_box (dialog, 0, 0, height, width, dialog_attr, border_attr);
+
+    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);
+    wbkgdset (dialog, dialog_attr & A_COLOR);
+    waddch (dialog, ACS_RTEE);
+
+    if (title != NULL && strlen(title) >= width-2 ) {
+	/* truncate long title -- mec */
+	char * title2 = malloc(width-2+1);
+	memcpy( title2, title, width-2 );
+	title2[width-2] = '\0';
+	title = title2;
+    }
+
+    if (title != NULL) {
+	wattrset (dialog, title_attr);
+	mvwaddch (dialog, 0, (width - strlen(title))/2 - 1, ' ');
+	waddstr (dialog, (char *)title);
+	waddch (dialog, ' ');
+    }
+    print_button (dialog, " Exit ", height - 2, width / 2 - 4, TRUE);
+    wnoutrefresh (dialog);
+    getyx (dialog, cur_y, cur_x);	/* Save cursor position */
+
+    /* Print first page of text */
+    attr_clear (text, height - 4, width - 2, dialog_attr);
+    print_page (text, height - 4, width - 2);
+    print_position (dialog, height, width);
+    wmove (dialog, cur_y, cur_x);	/* Restore cursor position */
+    wrefresh (dialog);
+
+    while ((key != ESC) && (key != '\n')) {
+	key = wgetch (dialog);
+	switch (key) {
+	case 'E':		/* Exit */
+	case 'e':
+	case 'X':
+	case 'x':
+	    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_position (dialog, height, width);
+		wmove (dialog, cur_y, cur_x);	/* Restore cursor position */
+		wrefresh (dialog);
+	    }
+	    break;
+	case 'G':		/* Last page */
+	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);
+	    print_position (dialog, height, width);
+	    wmove (dialog, cur_y, cur_x);	/* Restore cursor position */
+	    wrefresh (dialog);
+	    break;
+	case 'K':		/* Previous line */
+	case 'k':
+	case KEY_UP:
+	    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. */
+		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++) {
+		    if (!i) {
+			/* print first line of page */
+			print_line (text, 0, width - 2);
+			wnoutrefresh (text);
+		    } else
+			/* Called to update 'end_reached' and 'page' */
+			get_line ();
+		    if (!passed_end)
+			page_length++;
+		    if (end_reached && !passed_end)
+			passed_end = 1;
+		}
+
+		print_position (dialog, height, width);
+		wmove (dialog, cur_y, cur_x);	/* Restore cursor position */
+		wrefresh (dialog);
+	    }
+	    break;
+	case 'B':		/* Previous page */
+	case 'b':
+	case KEY_PPAGE:
+	    if (begin_reached)
+		break;
+	    back_lines (page_length + height - 4);
+	    print_page (text, height - 4, width - 2);
+	    print_position (dialog, height, width);
+	    wmove (dialog, cur_y, cur_x);
+	    wrefresh (dialog);
+	    break;
+	case 'J':		/* Next line */
+	case 'j':
+	case KEY_DOWN:
+	    if (!end_reached) {
+		begin_reached = 0;
+		scrollok (text, TRUE);
+		scroll (text);	/* Scroll text region up one line */
+		scrollok (text, FALSE);
+		print_line (text, height - 5, width - 2);
+		wnoutrefresh (text);
+		print_position (dialog, height, width);
+		wmove (dialog, cur_y, cur_x);	/* Restore cursor position */
+		wrefresh (dialog);
+	    }
+	    break;
+	case KEY_NPAGE:		/* Next page */
+	case ' ':
+	    if (end_reached)
+		break;
+
+	    begin_reached = 0;
+	    print_page (text, height - 4, width - 2);
+	    print_position (dialog, height, width);
+	    wmove (dialog, cur_y, cur_x);
+	    wrefresh (dialog);
+	    break;
+	case '0':		/* Beginning of line */
+	case 'H':		/* Scroll left */
+	case 'h':
+	case KEY_LEFT:
+	    if (hscroll <= 0)
+		break;
+
+	    if (key == '0')
+		hscroll = 0;
+	    else
+		hscroll--;
+	    /* Reprint current page to scroll horizontally */
+	    back_lines (page_length);
+	    print_page (text, height - 4, width - 2);
+	    wmove (dialog, cur_y, cur_x);
+	    wrefresh (dialog);
+	    break;
+	case 'L':		/* Scroll right */
+	case 'l':
+	case KEY_RIGHT:
+	    if (hscroll >= MAX_LEN)
+		break;
+	    hscroll++;
+	    /* Reprint current page to scroll horizontally */
+	    back_lines (page_length);
+	    print_page (text, height - 4, width - 2);
+	    wmove (dialog, cur_y, cur_x);
+	    wrefresh (dialog);
+	    break;
+	case ESC:
+	    break;
+	}
+    }
+
+    delwin (dialog);
+    free (buf);
+    close (fd);
+    return -1;			/* ESC pressed */
+}
+
+/*
+ * Go back 'n' lines in text file. 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;
+
+    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;
+	    }
+	}
+	if (*(--page) != '\n') {	/* '--page' here */
+	    /* Something's wrong... */
+	    endwin ();
+	    fprintf (stderr, "\nInternal error in back_lines().\n");
+	    exit (-1);
+	}
+    }
+    /* Go back 'n' lines */
+    for (i = 0; i < n; i++)
+	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;
+		}
+	    }
+	} while (*(--page) != '\n');
+    page++;
+}
+
+/*
+ * Print a new page of text. Called by dialog_textbox().
+ */
+static void
+print_page (WINDOW * win, int height, int width)
+{
+    int i, passed_end = 0;
+
+    page_length = 0;
+    for (i = 0; i < height; i++) {
+	print_line (win, i, width);
+	if (!passed_end)
+	    page_length++;
+	if (end_reached && !passed_end)
+	    passed_end = 1;
+    }
+    wnoutrefresh (win);
+}
+
+/*
+ * Print a new line of text. Called by dialog_textbox() and print_page().
+ */
+static void
+print_line (WINDOW * win, int row, int width)
+{
+    int y, x;
+    char *line;
+
+    line = get_line ();
+    line += MIN (strlen (line), hscroll);	/* Scroll horizontally */
+    wmove (win, row, 0);	/* move cursor to correct line */
+    waddch (win, ' ');
+    waddnstr (win, line, MIN (strlen (line), width - 2));
+
+    getyx (win, y, x);
+    /* Clear 'residue' of previous line */
+#if OLD_NCURSES
+    {
+        int i;
+        for (i = 0; i < width - x; i++)
+	    waddch (win, ' ');
+    }
+#else
+    wclrtoeol(win);
+#endif
+}
+
+/*
+ * Return current line of text. Called by dialog_textbox() and print_line().
+ * 'page' should point to start of current line before calling, and will be
+ * updated to point to start of next line.
+ */
+static char *
+get_line (void)
+{
+    int i = 0, fpos;
+    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;
+		break;
+	    }
+	} else if (i < MAX_LEN)
+	    line[i++] = *(page++);
+	else {
+	    /* Truncate lines longer than MAX_LEN characters */
+	    if (i == MAX_LEN)
+		line[i++] = '\0';
+	    page++;
+	}
+    }
+    if (i <= MAX_LEN)
+	line[i] = '\0';
+    if (!end_reached)
+	page++;			/* move pass '\n' */
+
+    return line;
+}
+
+/*
+ * Print current position
+ */
+static void
+print_position (WINDOW * win, int height, int width)
+{
+    int fpos, percent;
+
+    if ((fpos = lseek (fd, 0, SEEK_CUR)) == -1) {
+	endwin ();
+	fprintf (stderr, "\nError moving file pointer in print_position().\n");
+	exit (-1);
+    }
+    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);
+}

+ 359 - 0
extra/config/lxdialog/util.c

@@ -0,0 +1,359 @@
+/*
+ *  util.c
+ *
+ *  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"
+
+
+/* use colors by default? */
+bool use_colors = 1;
+
+const char *backtitle = NULL;
+
+const char *dialog_result;
+
+/* 
+ * Attribute values, default is for mono display
+ */
+chtype attributes[] =
+{
+    A_NORMAL,			/* screen_attr */
+    A_NORMAL,			/* shadow_attr */
+    A_NORMAL,			/* dialog_attr */
+    A_BOLD,			/* title_attr */
+    A_NORMAL,			/* border_attr */
+    A_REVERSE,			/* button_active_attr */
+    A_DIM,			/* button_inactive_attr */
+    A_REVERSE,			/* button_key_active_attr */
+    A_BOLD,			/* button_key_inactive_attr */
+    A_REVERSE,			/* button_label_active_attr */
+    A_NORMAL,			/* button_label_inactive_attr */
+    A_NORMAL,			/* inputbox_attr */
+    A_NORMAL,			/* inputbox_border_attr */
+    A_NORMAL,			/* searchbox_attr */
+    A_BOLD,			/* searchbox_title_attr */
+    A_NORMAL,			/* searchbox_border_attr */
+    A_BOLD,			/* position_indicator_attr */
+    A_NORMAL,			/* menubox_attr */
+    A_NORMAL,			/* menubox_border_attr */
+    A_NORMAL,			/* item_attr */
+    A_REVERSE,			/* item_selected_attr */
+    A_BOLD,			/* tag_attr */
+    A_REVERSE,			/* tag_selected_attr */
+    A_BOLD,			/* tag_key_attr */
+    A_REVERSE,			/* tag_key_selected_attr */
+    A_BOLD,			/* check_attr */
+    A_REVERSE,			/* check_selected_attr */
+    A_BOLD,			/* uarrow_attr */
+    A_BOLD			/* darrow_attr */
+};
+
+
+#include "colors.h"
+
+/*
+ * Table of color values
+ */
+int color_table[][3] =
+{
+    {SCREEN_FG, SCREEN_BG, SCREEN_HL},
+    {SHADOW_FG, SHADOW_BG, SHADOW_HL},
+    {DIALOG_FG, DIALOG_BG, DIALOG_HL},
+    {TITLE_FG, TITLE_BG, TITLE_HL},
+    {BORDER_FG, BORDER_BG, BORDER_HL},
+    {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},
+    {BUTTON_KEY_INACTIVE_FG, BUTTON_KEY_INACTIVE_BG, BUTTON_KEY_INACTIVE_HL},
+    {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'
+ */
+void
+attr_clear (WINDOW * win, int height, int width, chtype attr)
+{
+    int i, j;
+
+    wattrset (win, attr);
+    for (i = 0; i < height; i++) {
+	wmove (win, i, 0);
+	for (j = 0; j < width; j++)
+	    waddch (win, ' ');
+    }
+    touchwin (win);
+}
+
+void dialog_clear (void)
+{
+    attr_clear (stdscr, LINES, COLS, screen_attr);
+    /* Display background title if it exists ... - SLH */
+    if (backtitle != NULL) {
+        int i;
+
+        wattrset (stdscr, screen_attr);
+        mvwaddstr (stdscr, 0, 1, (char *)backtitle);
+        wmove (stdscr, 1, 1);
+        for (i = 1; i < COLS - 1; i++)
+            waddch (stdscr, ACS_HLINE);
+    }
+    wnoutrefresh (stdscr);
+}
+
+/*
+ * Do some initialization for dialog
+ */
+void
+init_dialog (void)
+{
+    initscr ();			/* Init curses */
+    keypad (stdscr, TRUE);
+    cbreak ();
+    noecho ();
+
+
+    if (use_colors)	/* Set up colors */
+	color_setup ();
+
+
+    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.
+ */
+void
+end_dialog (void)
+{
+    endwin ();
+}
+
+
+/*
+ * Print a string of text in a window, automatically wrap around to the
+ * next line if the string is too long to fit on one line. Newline
+ * characters '\n' are replaced by spaces.  We start on a new line
+ * if there is no room for at least 4 nonblanks following a double-space.
+ */
+void
+print_autowrap (WINDOW * win, const char *prompt, int width, int y, int x)
+{
+    int newl, cur_x, cur_y;
+    int i, prompt_len, room, wlen;
+    char tempstr[MAX_LEN + 1], *word, *sp, *sp2;
+
+    strcpy (tempstr, prompt);
+
+    prompt_len = strlen(tempstr);
+	
+    /*
+     * Remove newlines
+     */
+    for(i=0; i<prompt_len; i++) {
+	if(tempstr[i] == '\n') tempstr[i] = ' ';
+    }
+
+    if (prompt_len <= width - x * 2) {	/* If prompt is short */
+	wmove (win, y, (width - prompt_len) / 2);
+	waddstr (win, tempstr);
+    } else {
+	cur_x = x;
+	cur_y = y;
+	newl = 1;
+	word = tempstr;
+	while (word && *word) {
+	    sp = index(word, ' ');
+	    if (sp)
+	        *sp++ = 0;
+
+	    /* Wrap to next line if either the word does not fit,
+	       or it is the first word of a new sentence, and it is
+	       short, and the next word does not fit. */
+	    room = width - cur_x;
+	    wlen = strlen(word);
+	    if (wlen > room ||
+	       (newl && wlen < 4 && sp && wlen+1+strlen(sp) > room
+		     && (!(sp2 = index(sp, ' ')) || wlen+1+(sp2-sp) > room))) {
+		cur_y++;
+		cur_x = x;
+	    }
+	    wmove (win, cur_y, cur_x);
+	    waddstr (win, word);
+	    getyx (win, cur_y, cur_x);
+	    cur_x++;
+	    if (sp && *sp == ' ') {
+	        cur_x++;	/* double space */
+		while (*++sp == ' ');
+		newl = 1;
+	    } else
+	        newl = 0;
+	    word = sp;
+	}
+    }
+}
+
+/*
+ * Print a button
+ */
+void
+print_button (WINDOW * win, const char *label, int y, int x, int selected)
+{
+    int i, temp;
+
+    wmove (win, y, x);
+    wattrset (win, selected ? button_active_attr : button_inactive_attr);
+    waddstr (win, "<");
+    temp = strspn (label, " ");
+    label += temp;
+    wattrset (win, selected ? button_label_active_attr
+	      : button_label_inactive_attr);
+    for (i = 0; i < temp; i++)
+	waddch (win, ' ');
+    wattrset (win, selected ? button_key_active_attr
+	      : button_key_inactive_attr);
+    waddch (win, label[0]);
+    wattrset (win, selected ? button_label_active_attr
+	      : button_label_inactive_attr);
+    waddstr (win, (char *)label + 1);
+    wattrset (win, selected ? button_active_attr : button_inactive_attr);
+    waddstr (win, ">");
+    wmove (win, y, x + temp + 1);
+}
+
+/*
+ * Draw a rectangular box with line drawing characters
+ */
+void
+draw_box (WINDOW * win, int y, int x, int height, int width,
+	  chtype box, chtype border)
+{
+    int i, j;
+
+    wattrset (win, 0);
+    for (i = 0; i < height; i++) {
+	wmove (win, y + i, x);
+	for (j = 0; j < width; j++)
+	    if (!i && !j)
+		waddch (win, border | ACS_ULCORNER);
+	    else if (i == height - 1 && !j)
+		waddch (win, border | ACS_LLCORNER);
+	    else if (!i && j == width - 1)
+		waddch (win, box | ACS_URCORNER);
+	    else if (i == height - 1 && j == width - 1)
+		waddch (win, box | ACS_LRCORNER);
+	    else if (!i)
+		waddch (win, border | ACS_HLINE);
+	    else if (i == height - 1)
+		waddch (win, box | ACS_HLINE);
+	    else if (!j)
+		waddch (win, border | ACS_VLINE);
+	    else if (j == width - 1)
+		waddch (win, box | ACS_VLINE);
+	    else
+		waddch (win, box | ' ');
+    }
+}
+
+/*
+ * Draw shadows along the right and bottom edge to give a more 3D look
+ * to the boxes
+ */
+void
+draw_shadow (WINDOW * win, int y, int x, int height, int width)
+{
+    int i;
+
+    if (has_colors ()) {	/* Whether terminal supports color? */
+	wattrset (win, shadow_attr);
+	wmove (win, y + height, x + 2);
+	for (i = 0; i < width; i++)
+	    waddch (win, winch (win) & A_CHARTEXT);
+	for (i = y + 1; i < y + height + 1; i++) {
+	    wmove (win, i, x + width);
+	    waddch (win, winch (win) & A_CHARTEXT);
+	    waddch (win, winch (win) & A_CHARTEXT);
+	}
+	wnoutrefresh (win);
+    }
+}
+
+/*
+ *  Return the position of the first alphabetic character in a string.
+ */
+int
+first_alpha(const char *string, const char *exempt)
+{
+	int i, in_paren=0, c;
+
+	for (i = 0; i < strlen(string); i++) {
+		c = tolower(string[i]);
+
+		if (strchr("<[(", c)) ++in_paren;
+		if (strchr(">])", c) && in_paren > 0) --in_paren;
+
+		if ((! in_paren) && isalpha(c) && 
+		     strchr(exempt, c) == 0)
+			return i;
+	}
+
+	return 0;
+}

+ 118 - 0
extra/config/lxdialog/yesno.c

@@ -0,0 +1,118 @@
+/*
+ *  yesno.c -- implements the yes/no box
+ *
+ *  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"
+
+/*
+ * Display termination buttons
+ */
+static void
+print_buttons(WINDOW *dialog, int height, int width, int selected)
+{
+    int x = width / 2 - 10;
+    int y = height - 2;
+
+    print_button (dialog, " Yes ", y, x, selected == 0);
+    print_button (dialog, "  No  ", y, x + 13, selected == 1);
+
+    wmove(dialog, y, x+1 + 13*selected );
+    wrefresh (dialog);
+}
+
+/*
+ * Display a dialog box with two buttons - Yes and No
+ */
+int
+dialog_yesno (const char *title, const char *prompt, int height, int width)
+{
+    int i, x, y, key = 0, button = 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);
+    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);
+
+    if (title != NULL && strlen(title) >= width-2 ) {
+	/* truncate long title -- mec */
+	char * title2 = malloc(width-2+1);
+	memcpy( title2, title, width-2 );
+	title2[width-2] = '\0';
+	title = title2;
+    }
+
+    if (title != NULL) {
+	wattrset (dialog, title_attr);
+	mvwaddch (dialog, 0, (width - strlen(title))/2 - 1, ' ');
+	waddstr (dialog, (char *)title);
+	waddch (dialog, ' ');
+    }
+
+    wattrset (dialog, dialog_attr);
+    print_autowrap (dialog, prompt, width - 2, 1, 3);
+
+    print_buttons(dialog, height, width, 0);
+
+    while (key != ESC) {
+	key = wgetch (dialog);
+	switch (key) {
+	case 'Y':
+	case 'y':
+	    delwin (dialog);
+	    return 0;
+	case 'N':
+	case 'n':
+	    delwin (dialog);
+	    return 1;
+
+	case TAB:
+	case KEY_LEFT:
+	case KEY_RIGHT:
+	    button = ((key == KEY_LEFT ? --button : ++button) < 0)
+			? 1 : (button > 1 ? 0 : button);
+
+	    print_buttons(dialog, height, width, button);
+	    wrefresh (dialog);
+	    break;
+	case ' ':
+	case '\n':
+	    delwin (dialog);
+	    return button;
+	case ESC:
+	    break;
+	}
+    }
+
+    delwin (dialog);
+    return -1;			/* ESC pressed */
+}