diff options
Diffstat (limited to 'scripts/config/lxdialog')
| -rw-r--r-- | scripts/config/lxdialog/.gitignore | 2 | ||||
| -rw-r--r-- | scripts/config/lxdialog/Makefile | 28 | ||||
| -rw-r--r-- | scripts/config/lxdialog/check-lxdialog.sh | 90 | ||||
| -rw-r--r-- | scripts/config/lxdialog/checklist.c | 334 | ||||
| -rw-r--r-- | scripts/config/lxdialog/colors.h | 154 | ||||
| -rw-r--r-- | scripts/config/lxdialog/dialog.h | 177 | ||||
| -rw-r--r-- | scripts/config/lxdialog/inputbox.c | 224 | ||||
| -rw-r--r-- | scripts/config/lxdialog/lxdialog.c | 204 | ||||
| -rw-r--r-- | scripts/config/lxdialog/menubox.c | 425 | ||||
| -rw-r--r-- | scripts/config/lxdialog/msgbox.c | 71 | ||||
| -rw-r--r-- | scripts/config/lxdialog/textbox.c | 533 | ||||
| -rw-r--r-- | scripts/config/lxdialog/util.c | 362 | ||||
| -rw-r--r-- | scripts/config/lxdialog/yesno.c | 102 | 
13 files changed, 2706 insertions, 0 deletions
| diff --git a/scripts/config/lxdialog/.gitignore b/scripts/config/lxdialog/.gitignore new file mode 100644 index 000000000..405824dbd --- /dev/null +++ b/scripts/config/lxdialog/.gitignore @@ -0,0 +1,2 @@ +lxdialog +*.o diff --git a/scripts/config/lxdialog/Makefile b/scripts/config/lxdialog/Makefile new file mode 100644 index 000000000..bdafde0c0 --- /dev/null +++ b/scripts/config/lxdialog/Makefile @@ -0,0 +1,28 @@ +# Makefile to build lxdialog package +# + +all: lxdialog + +# 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) +CFLAGS := $(shell sh check-lxdialog.sh -ccflags) +LIBS := $(shell sh check-lxdialog.sh -ldflags gcc) + +# workaround for OpenBSD, which does not use symlinks to libncurses.so +OS := $(shell uname -s) +ifeq ($(strip $(OS)),OpenBSD) +LIBS := -lncurses +endif +ifeq ($(shell uname -o),Cygwin) +LIBS := -lncurses +endif +always		:= $(hostprogs-y) dochecklxdialog + +%.o: %.c +	$(CC) -c $(CFLAGS) -o $@ $< + +lxdialog: checklist.o menubox.o textbox.o yesno.o inputbox.o util.o lxdialog.o msgbox.o +	$(CC) -o $@ $^ $(LIBS) + +clean: +	rm -f *.o lxdialog diff --git a/scripts/config/lxdialog/check-lxdialog.sh b/scripts/config/lxdialog/check-lxdialog.sh new file mode 100644 index 000000000..9a6c915e5 --- /dev/null +++ b/scripts/config/lxdialog/check-lxdialog.sh @@ -0,0 +1,90 @@ +#!/usr/bin/env bash +# Check ncurses compatibility + +# What library to link +ldflags() +{ +	for ext in so dylib; do +		for dir in "" /usr/local/lib /opt/local/lib; do +			$cc ${dir:+-L$dir} -print-file-name=libncursesw.$ext | grep -q / +			if [ $? -eq 0 ]; then +				echo $dir '-lncursesw' +				exit +			fi +			$cc ${dir:+-L$dir} -print-file-name=libncurses.$ext | grep -q / +			if [ $? -eq 0 ]; then +				echo $dir '-lncurses' +				exit  +			fi +			$cc ${dir:+-L$dir} -print-file-name=libcurses.$ext | grep -q / +			if [ $? -eq 0 ]; then +				echo $dir '-lcurses' +				exit +			fi +		done +	done +	exit 1 +} + +# Where is ncurses.h? +ccflags() +{ +	if [ -f /usr/include/ncurses/ncurses.h ]; then +		echo '-I/usr/include/ncurses -DCURSES_LOC="<ncurses.h>"' +	elif [ -f /usr/include/ncurses/curses.h ]; then +		echo '-I/usr/include/ncurses -DCURSES_LOC="<ncurses/curses.h>"' +	elif [ -f /opt/local/include/ncurses/ncurses.h ]; then +		echo '-I/opt/local/include -I/opt/local/include/ncurses -DCURSES_LOC="<ncurses/ncurses.h>"' +	elif [ -f /usr/include/ncurses.h ]; then +		echo '-DCURSES_LOC="<ncurses.h>"' +	else +		echo '-DCURSES_LOC="<curses.h>"' +	fi +} + +# Temp file, try to clean up after us +tmp=.lxdialog.tmp +trap "rm -f $tmp" 0 1 2 3 15 + +# Check if we can link to ncurses +check() { +	echo "main() {}" | $cc -xc - -o $tmp 2> /dev/null +	if [ $? != 0 ]; then +		echo " *** Unable to find the ncurses libraries."          1>&2 +		echo " *** make menuconfig require the ncurses libraries"  1>&2 +		echo " *** "                                               1>&2 +		echo " *** Install ncurses (ncurses-devel) and try again"  1>&2 +		echo " *** "                                               1>&2 +		exit 1 +	fi +} + +usage() { +	printf "Usage: $0 [-check compiler options|-header|-library]\n" +} + +if [ $# -eq 0 ]; then +	usage +	exit 1 +fi + +cc="" +case "$1" in +	"-check") +		shift +		cc="$@" +		check +		;; +	"-ccflags") +		ccflags +		;; +	"-ldflags") +		shift +		cc="$@" +		ldflags +		;; +	"*") +		usage +		exit 1 +		;; +esac diff --git a/scripts/config/lxdialog/checklist.c b/scripts/config/lxdialog/checklist.c new file mode 100644 index 000000000..db07ae73e --- /dev/null +++ b/scripts/config/lxdialog/checklist.c @@ -0,0 +1,334 @@ +/* + *  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; + +/* + * 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); +	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 + * 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 i, x, y, box_x, box_y; +	int key = 0, button = 0, choice = 0, scroll = 0, max_choice, *status; +	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; +	} +	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); + +	print_title(dialog, title, width); + +	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); +						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); +					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 (!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]) +						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 */ +} diff --git a/scripts/config/lxdialog/colors.h b/scripts/config/lxdialog/colors.h new file mode 100644 index 000000000..b58c8ed41 --- /dev/null +++ b/scripts/config/lxdialog/colors.h @@ -0,0 +1,154 @@ +/* + *  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_BLUE +#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_BLUE +#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_BLUE +#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_BLUE +#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_BLUE +#define TAG_KEY_BG                   COLOR_WHITE +#define TAG_KEY_HL                   TRUE + +#define TAG_KEY_SELECTED_FG          COLOR_YELLOW +#define TAG_KEY_SELECTED_BG          COLOR_BLUE +#define TAG_KEY_SELECTED_HL          TRUE + +#define CHECK_FG                     COLOR_BLACK +#define CHECK_BG                     COLOR_WHITE +#define CHECK_HL                     FALSE + +#define CHECK_SELECTED_FG            COLOR_WHITE +#define CHECK_SELECTED_BG            COLOR_BLUE +#define CHECK_SELECTED_HL            TRUE + +#define UARROW_FG                    COLOR_GREEN +#define UARROW_BG                    COLOR_WHITE +#define UARROW_HL                    TRUE + +#define DARROW_FG                    COLOR_GREEN +#define DARROW_BG                    COLOR_WHITE +#define DARROW_HL                    TRUE + +/* End of default color definitions */ + +#define C_ATTR(x,y)                  ((x ? A_BOLD : 0) | COLOR_PAIR((y))) +#define COLOR_NAME_LEN               10 +#define COLOR_COUNT                  8 + +/* + * Global variables + */ + +extern int color_table[][3]; diff --git a/scripts/config/lxdialog/dialog.h b/scripts/config/lxdialog/dialog.h new file mode 100644 index 000000000..af3cf716e --- /dev/null +++ b/scripts/config/lxdialog/dialog.h @@ -0,0 +1,177 @@ +/* + *  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 print_title(WINDOW *dialog, const char *title, int width); +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); +extern 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) diff --git a/scripts/config/lxdialog/inputbox.c b/scripts/config/lxdialog/inputbox.c new file mode 100644 index 000000000..779503726 --- /dev/null +++ b/scripts/config/lxdialog/inputbox.c @@ -0,0 +1,224 @@ +/* + *  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" + +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; +	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); + +	print_title(dialog, title, width); + +	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 */ +} diff --git a/scripts/config/lxdialog/lxdialog.c b/scripts/config/lxdialog/lxdialog.c new file mode 100644 index 000000000..79f6c5fb5 --- /dev/null +++ b/scripts/config/lxdialog/lxdialog.c @@ -0,0 +1,204 @@ +/* + *  dialog - Display simple dialog boxes from shell scripts + * + *  ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk) + *  MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com) + * + *  This program is free software; you can redistribute it and/or + *  modify it under the terms of the GNU General Public License + *  as published by the Free Software Foundation; either version 2 + *  of the License, or (at your option) any later version. + * + *  This program is distributed in the hope that it will be useful, + *  but WITHOUT ANY WARRANTY; without even the implied warranty of + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *  GNU General Public License for more details. + * + *  You should have received a copy of the GNU General Public License + *  along with this program; if not, write to the Free Software + *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "dialog.h" + +static void Usage(const char *name); + +typedef int (jumperFn) (const char *title, int argc, const char *const *argv); + +struct Mode { +	char *name; +	int argmin, argmax, argmod; +	jumperFn *jumper; +}; + +jumperFn j_menu, j_radiolist, j_yesno, j_textbox, j_inputbox; +jumperFn j_msgbox, j_infobox; + +static struct Mode modes[] = { +	{"--menu", 9, 0, 3, j_menu}, +	{"--radiolist", 9, 0, 3, j_radiolist}, +	{"--yesno", 5, 5, 1, j_yesno}, +	{"--textbox", 5, 5, 1, j_textbox}, +	{"--inputbox", 5, 6, 1, j_inputbox}, +	{"--msgbox", 5, 5, 1, j_msgbox}, +	{"--infobox", 5, 5, 1, j_infobox}, +	{NULL, 0, 0, 0, NULL} +}; + +static struct Mode *modePtr; + +#ifdef LOCALE +#include <locale.h> +#endif + +int main(int argc, const char *const *argv) +{ +	int offset = 0, opt_clear = 0, end_common_opts = 0, retval; +	const char *title = NULL; + +#ifdef LOCALE +	(void)setlocale(LC_ALL, ""); +#endif + +#ifdef TRACE +	trace(TRACE_CALLS | TRACE_UPDATE); +#endif +	if (argc < 2) { +		Usage(argv[0]); +		exit(-1); +	} + +	while (offset < argc - 1 && !end_common_opts) {	/* Common options */ +		if (!strcmp(argv[offset + 1], "--title")) { +			if (argc - offset < 3 || title != NULL) { +				Usage(argv[0]); +				exit(-1); +			} else { +				title = argv[offset + 2]; +				offset += 2; +			} +		} else if (!strcmp(argv[offset + 1], "--backtitle")) { +			if (backtitle != NULL) { +				Usage(argv[0]); +				exit(-1); +			} else { +				backtitle = argv[offset + 2]; +				offset += 2; +			} +		} else if (!strcmp(argv[offset + 1], "--clear")) { +			if (opt_clear) {	/* Hey, "--clear" can't appear twice! */ +				Usage(argv[0]); +				exit(-1); +			} else if (argc == 2) {	/* we only want to clear the screen */ +				init_dialog(); +				refresh();	/* init_dialog() will clear the screen for us */ +				end_dialog(); +				return 0; +			} else { +				opt_clear = 1; +				offset++; +			} +		} else		/* no more common options */ +			end_common_opts = 1; +	} + +	if (argc - 1 == offset) {	/* no more options */ +		Usage(argv[0]); +		exit(-1); +	} +	/* use a table to look for the requested mode, to avoid code duplication */ + +	for (modePtr = modes; modePtr->name; modePtr++)	/* look for the mode */ +		if (!strcmp(argv[offset + 1], modePtr->name)) +			break; + +	if (!modePtr->name) +		Usage(argv[0]); +	if (argc - offset < modePtr->argmin) +		Usage(argv[0]); +	if (modePtr->argmax && argc - offset > modePtr->argmax) +		Usage(argv[0]); + +	init_dialog(); +	retval = (*(modePtr->jumper)) (title, argc - offset, argv + offset); + +	if (opt_clear) {	/* clear screen before exit */ +		attr_clear(stdscr, LINES, COLS, screen_attr); +		refresh(); +	} +	end_dialog(); + +	exit(retval); +} + +/* + * Print program usage + */ +static void Usage(const char *name) +{ +	fprintf(stderr, "\ +\ndialog, by Savio Lam (lam836@cs.cuhk.hk).\ +\n  patched by Stuart Herbert (S.Herbert@shef.ac.uk)\ +\n  modified/gutted for use as a Linux kernel config tool by \ +\n  William Roadcap (roadcapw@cfw.com)\ +\n\ +\n* Display dialog boxes from shell scripts *\ +\n\ +\nUsage: %s --clear\ +\n       %s [--title <title>] [--backtitle <backtitle>] --clear <Box options>\ +\n\ +\nBox options:\ +\n\ +\n  --menu      <text> <height> <width> <menu height> <tag1> <item1>...\ +\n  --radiolist <text> <height> <width> <list height> <tag1> <item1> <status1>...\ +\n  --textbox   <file> <height> <width>\ +\n  --inputbox  <text> <height> <width> [<init>]\ +\n  --yesno     <text> <height> <width>\ +\n", name, name); +	exit(-1); +} + +/* + * These are the program jumpers + */ + +int j_menu(const char *t, int ac, const char *const *av) +{ +	return dialog_menu(t, av[2], atoi(av[3]), atoi(av[4]), +			   atoi(av[5]), av[6], (ac - 6) / 2, av + 7); +} + +int j_radiolist(const char *t, int ac, const char *const *av) +{ +	return dialog_checklist(t, av[2], atoi(av[3]), atoi(av[4]), +				atoi(av[5]), (ac - 6) / 3, av + 6); +} + +int j_textbox(const char *t, int ac, const char *const *av) +{ +	return dialog_textbox(t, av[2], atoi(av[3]), atoi(av[4])); +} + +int j_yesno(const char *t, int ac, const char *const *av) +{ +	return dialog_yesno(t, av[2], atoi(av[3]), atoi(av[4])); +} + +int j_inputbox(const char *t, int ac, const char *const *av) +{ +	int ret = dialog_inputbox(t, av[2], atoi(av[3]), atoi(av[4]), +				  ac == 6 ? av[5] : (char *)NULL); +	if (ret == 0) +		fprintf(stderr, dialog_input_result); +	return ret; +} + +int j_msgbox(const char *t, int ac, const char *const *av) +{ +	return dialog_msgbox(t, av[2], atoi(av[3]), atoi(av[4]), 1); +} + +int j_infobox(const char *t, int ac, const char *const *av) +{ +	return dialog_msgbox(t, av[2], atoi(av[3]), atoi(av[4]), 0); +} diff --git a/scripts/config/lxdialog/menubox.c b/scripts/config/lxdialog/menubox.c new file mode 100644 index 000000000..09512b544 --- /dev/null +++ b/scripts/config/lxdialog/menubox.c @@ -0,0 +1,425 @@ +/* + *  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" + +#define ITEM_IDENT 1   /* Indent of menu entries. Fixed for all menus */ +static int menu_width; + +/* + * Print menu item + */ +static void do_print_item(WINDOW * win, const char *item, int choice, +                          int selected, int hotkey) +{ +	int j; +	char *menu_item = malloc(menu_width + 1); + +	strncpy(menu_item, item, menu_width - ITEM_IDENT); +	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_IDENT, menu_item); +	if (hotkey) { +		wattrset(win, selected ? tag_key_selected_attr : tag_key_attr); +		mvwaddch(win, choice, ITEM_IDENT + j, menu_item[j]); +	} +	if (selected) { +		wmove(win, choice, ITEM_IDENT + 1); +	} +	free(menu_item); +	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); \ +} while (0) + +/* + * 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); +	wrefresh(win); + +	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); +	wrefresh(win); +} + +/* + * 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); +} + +/* scroll up n lines (n may be negative) */ +static void do_scroll(WINDOW *win, int *scroll, int n) +{ +	/* Scroll menu up */ +	scrollok(win, TRUE); +	wscrl(win, n); +	scrollok(win, FALSE); +	*scroll = *scroll + n; +	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; +	int 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); + +	print_title(dialog, title, width); + +	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); + +	/* 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; +		} +	} +	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(first_item + i, i, i == choice); +	} + +	wnoutrefresh(menu); + +	print_arrows(dialog, item_no, scroll, +		     box_y, box_x + ITEM_IDENT + 1, menu_height); + +	print_buttons(dialog, height, width, 0); +	wmove(menu, choice, ITEM_IDENT + 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) { +			/* Remove highligt of current item */ +			print_item(scroll + choice, choice, FALSE); + +			if (key == KEY_UP || key == '-') { +				if (choice < 2 && scroll) { +					/* Scroll menu down */ +					do_scroll(menu, &scroll, -1); + +					print_item(scroll, 0, FALSE); +				} else +					choice = MAX(choice - 1, 0); + +			} else if (key == KEY_DOWN || key == '+') { +				print_item(scroll+choice, choice, FALSE); + +				if ((choice > max_choice - 3) && +				    (scroll + max_choice < item_no)) { +					/* Scroll menu up */ +					do_scroll(menu, &scroll, 1); + +					print_item(scroll+max_choice - 1, +						   max_choice - 1, FALSE); +				} 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) { +						do_scroll(menu, &scroll, -1); +						print_item(scroll, 0, FALSE); +					} else { +						if (choice > 0) +							choice--; +					} +				} + +			} else if (key == KEY_NPAGE) { +				for (i = 0; (i < max_choice); i++) { +					if (scroll + max_choice < item_no) { +						do_scroll(menu, &scroll, 1); +						print_item(scroll+max_choice-1, +							   max_choice - 1, FALSE); +					} else { +						if (choice + 1 < max_choice) +							choice++; +					} +				} +			} else +				choice = i; + +			print_item(scroll + choice, choice, TRUE); + +			print_arrows(dialog, item_no, scroll, +				     box_y, box_x + ITEM_IDENT + 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 */ +} diff --git a/scripts/config/lxdialog/msgbox.c b/scripts/config/lxdialog/msgbox.c new file mode 100644 index 000000000..7323f5471 --- /dev/null +++ b/scripts/config/lxdialog/msgbox.c @@ -0,0 +1,71 @@ +/* + *  msgbox.c -- implements the message box and info box + * + *  ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk) + *  MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcapw@cfw.com) + * + *  This program is free software; you can redistribute it and/or + *  modify it under the terms of the GNU General Public License + *  as published by the Free Software Foundation; either version 2 + *  of the License, or (at your option) any later version. + * + *  This program is distributed in the hope that it will be useful, + *  but WITHOUT ANY WARRANTY; without even the implied warranty of + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *  GNU General Public License for more details. + * + *  You should have received a copy of the GNU General Public License + *  along with this program; if not, write to the Free Software + *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "dialog.h" + +/* + * Display a message box. Program will pause and display an "OK" button + * if the parameter 'pause' is non-zero. + */ +int dialog_msgbox(const char *title, const char *prompt, int height, int width, +                  int pause) +{ +	int i, x, y, key = 0; +	WINDOW *dialog; + +	/* center dialog box on screen */ +	x = (COLS - width) / 2; +	y = (LINES - height) / 2; + +	draw_shadow(stdscr, y, x, height, width); + +	dialog = newwin(height, width, y, x); +	keypad(dialog, TRUE); + +	draw_box(dialog, 0, 0, height, width, dialog_attr, border_attr); + +	print_title(dialog, title, width); + +	wattrset(dialog, dialog_attr); +	print_autowrap(dialog, prompt, width - 2, 1, 2); + +	if (pause) { +		wattrset(dialog, border_attr); +		mvwaddch(dialog, height - 3, 0, ACS_LTEE); +		for (i = 0; i < width - 2; i++) +			waddch(dialog, ACS_HLINE); +		wattrset(dialog, dialog_attr); +		waddch(dialog, ACS_RTEE); + +		print_button(dialog, "  Ok  ", height - 2, width / 2 - 4, TRUE); + +		wrefresh(dialog); +		while (key != ESC && key != '\n' && key != ' ' && +		       key != 'O' && key != 'o' && key != 'X' && key != 'x') +			key = wgetch(dialog); +	} else { +		key = '\n'; +		wrefresh(dialog); +	} + +	delwin(dialog); +	return key == ESC ? -1 : 0; +} diff --git a/scripts/config/lxdialog/textbox.c b/scripts/config/lxdialog/textbox.c new file mode 100644 index 000000000..77848bb8e --- /dev/null +++ b/scripts/config/lxdialog/textbox.c @@ -0,0 +1,533 @@ +/* + *  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); + +	print_title(dialog, title, width); + +	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); +} diff --git a/scripts/config/lxdialog/util.c b/scripts/config/lxdialog/util.c new file mode 100644 index 000000000..f82cebb9f --- /dev/null +++ b/scripts/config/lxdialog/util.c @@ -0,0 +1,362 @@ +/* + *  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; + +/* + * 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 the title of the dialog. Center the title and truncate + * tile if wider than dialog (- 2 chars). + **/ +void print_title(WINDOW *dialog, const char *title, int width) +{ +	if (title) { +		int tlen = MIN(width - 2, strlen(title)); +		wattrset(dialog, title_attr); +		mvwaddch(dialog, 0, (width - tlen) / 2 - 1, ' '); +		mvwaddnstr(dialog, 0, (width - tlen)/2, title, tlen); +		waddch(dialog, ' '); +	} +} + +/* + * 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; +} diff --git a/scripts/config/lxdialog/yesno.c b/scripts/config/lxdialog/yesno.c new file mode 100644 index 000000000..cb2568aae --- /dev/null +++ b/scripts/config/lxdialog/yesno.c @@ -0,0 +1,102 @@ +/* + *  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); + +	print_title(dialog, title, width); + +	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 */ +} | 
