kconfig/lxdialog/checklist.c
author "Yann E. MORIN" <yann.morin.1998@anciens.enib.fr>
Sun Jan 17 23:06:02 2010 +0100 (2010-01-17)
changeset 1740 c57458bb354d
parent 1 eeea35fbf182
child 2448 a103abae1560
permissions -rw-r--r--
configure: do not require hg when configuring in an hg clone

When configuring in an hg clone, we need hg to compute the version string.
It can happen that users do not have Mercurial (eg. if they got a snapshot
rather that they did a full clone). In this case, we can still run, of
course, so simply fill the version string with a sufficiently explicit
value, that does not require hg. The date is a good candidate.
yann@1
     1
/*
yann@1
     2
 *  checklist.c -- implements the checklist box
yann@1
     3
 *
yann@1
     4
 *  ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
yann@1
     5
 *     Stuart Herbert - S.Herbert@sheffield.ac.uk: radiolist extension
yann@1
     6
 *     Alessandro Rubini - rubini@ipvvis.unipv.it: merged the two
yann@1
     7
 *  MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com)
yann@1
     8
 *
yann@1
     9
 *  This program is free software; you can redistribute it and/or
yann@1
    10
 *  modify it under the terms of the GNU General Public License
yann@1
    11
 *  as published by the Free Software Foundation; either version 2
yann@1
    12
 *  of the License, or (at your option) any later version.
yann@1
    13
 *
yann@1
    14
 *  This program is distributed in the hope that it will be useful,
yann@1
    15
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
yann@1
    16
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
yann@1
    17
 *  GNU General Public License for more details.
yann@1
    18
 *
yann@1
    19
 *  You should have received a copy of the GNU General Public License
yann@1
    20
 *  along with this program; if not, write to the Free Software
yann@1
    21
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
yann@1
    22
 */
yann@1
    23
yann@1
    24
#include "dialog.h"
yann@1
    25
yann@1
    26
static int list_width, check_x, item_x;
yann@1
    27
yann@1
    28
/*
yann@1
    29
 * Print list item
yann@1
    30
 */
yann@1
    31
static void print_item(WINDOW * win, int choice, int selected)
yann@1
    32
{
yann@1
    33
	int i;
yann@1
    34
yann@1
    35
	/* Clear 'residue' of last item */
yann@1
    36
	wattrset(win, dlg.menubox.atr);
yann@1
    37
	wmove(win, choice, 0);
yann@1
    38
	for (i = 0; i < list_width; i++)
yann@1
    39
		waddch(win, ' ');
yann@1
    40
yann@1
    41
	wmove(win, choice, check_x);
yann@1
    42
	wattrset(win, selected ? dlg.check_selected.atr
yann@1
    43
		 : dlg.check.atr);
yann@1
    44
	wprintw(win, "(%c)", item_is_tag('X') ? 'X' : ' ');
yann@1
    45
yann@1
    46
	wattrset(win, selected ? dlg.tag_selected.atr : dlg.tag.atr);
yann@1
    47
	mvwaddch(win, choice, item_x, item_str()[0]);
yann@1
    48
	wattrset(win, selected ? dlg.item_selected.atr : dlg.item.atr);
yann@1
    49
	waddstr(win, (char *)item_str() + 1);
yann@1
    50
	if (selected) {
yann@1
    51
		wmove(win, choice, check_x + 1);
yann@1
    52
		wrefresh(win);
yann@1
    53
	}
yann@1
    54
}
yann@1
    55
yann@1
    56
/*
yann@1
    57
 * Print the scroll indicators.
yann@1
    58
 */
yann@1
    59
static void print_arrows(WINDOW * win, int choice, int item_no, int scroll,
yann@1
    60
	     int y, int x, int height)
yann@1
    61
{
yann@1
    62
	wmove(win, y, x);
yann@1
    63
yann@1
    64
	if (scroll > 0) {
yann@1
    65
		wattrset(win, dlg.uarrow.atr);
yann@1
    66
		waddch(win, ACS_UARROW);
yann@1
    67
		waddstr(win, "(-)");
yann@1
    68
	} else {
yann@1
    69
		wattrset(win, dlg.menubox.atr);
yann@1
    70
		waddch(win, ACS_HLINE);
yann@1
    71
		waddch(win, ACS_HLINE);
yann@1
    72
		waddch(win, ACS_HLINE);
yann@1
    73
		waddch(win, ACS_HLINE);
yann@1
    74
	}
yann@1
    75
yann@1
    76
	y = y + height + 1;
yann@1
    77
	wmove(win, y, x);
yann@1
    78
yann@1
    79
	if ((height < item_no) && (scroll + choice < item_no - 1)) {
yann@1
    80
		wattrset(win, dlg.darrow.atr);
yann@1
    81
		waddch(win, ACS_DARROW);
yann@1
    82
		waddstr(win, "(+)");
yann@1
    83
	} else {
yann@1
    84
		wattrset(win, dlg.menubox_border.atr);
yann@1
    85
		waddch(win, ACS_HLINE);
yann@1
    86
		waddch(win, ACS_HLINE);
yann@1
    87
		waddch(win, ACS_HLINE);
yann@1
    88
		waddch(win, ACS_HLINE);
yann@1
    89
	}
yann@1
    90
}
yann@1
    91
yann@1
    92
/*
yann@1
    93
 *  Display the termination buttons
yann@1
    94
 */
yann@1
    95
static void print_buttons(WINDOW * dialog, int height, int width, int selected)
yann@1
    96
{
yann@1
    97
	int x = width / 2 - 11;
yann@1
    98
	int y = height - 2;
yann@1
    99
yann@943
   100
	print_button(dialog, gettext("Select"), y, x, selected == 0);
yann@943
   101
	print_button(dialog, gettext(" Help "), y, x + 14, selected == 1);
yann@1
   102
yann@1
   103
	wmove(dialog, y, x + 1 + 14 * selected);
yann@1
   104
	wrefresh(dialog);
yann@1
   105
}
yann@1
   106
yann@1
   107
/*
yann@1
   108
 * Display a dialog box with a list of options that can be turned on or off
yann@1
   109
 * in the style of radiolist (only one option turned on at a time).
yann@1
   110
 */
yann@1
   111
int dialog_checklist(const char *title, const char *prompt, int height,
yann@1
   112
		     int width, int list_height)
yann@1
   113
{
yann@1
   114
	int i, x, y, box_x, box_y;
yann@1
   115
	int key = 0, button = 0, choice = 0, scroll = 0, max_choice;
yann@1
   116
	WINDOW *dialog, *list;
yann@1
   117
yann@1
   118
	/* which item to highlight */
yann@1
   119
	item_foreach() {
yann@1
   120
		if (item_is_tag('X'))
yann@1
   121
			choice = item_n();
yann@1
   122
		if (item_is_selected()) {
yann@1
   123
			choice = item_n();
yann@1
   124
			break;
yann@1
   125
		}
yann@1
   126
	}
yann@1
   127
yann@1
   128
do_resize:
yann@1
   129
	if (getmaxy(stdscr) < (height + 6))
yann@1
   130
		return -ERRDISPLAYTOOSMALL;
yann@1
   131
	if (getmaxx(stdscr) < (width + 6))
yann@1
   132
		return -ERRDISPLAYTOOSMALL;
yann@1
   133
yann@1
   134
	max_choice = MIN(list_height, item_count());
yann@1
   135
yann@1
   136
	/* center dialog box on screen */
yann@1
   137
	x = (COLS - width) / 2;
yann@1
   138
	y = (LINES - height) / 2;
yann@1
   139
yann@1
   140
	draw_shadow(stdscr, y, x, height, width);
yann@1
   141
yann@1
   142
	dialog = newwin(height, width, y, x);
yann@1
   143
	keypad(dialog, TRUE);
yann@1
   144
yann@1
   145
	draw_box(dialog, 0, 0, height, width,
yann@1
   146
		 dlg.dialog.atr, dlg.border.atr);
yann@1
   147
	wattrset(dialog, dlg.border.atr);
yann@1
   148
	mvwaddch(dialog, height - 3, 0, ACS_LTEE);
yann@1
   149
	for (i = 0; i < width - 2; i++)
yann@1
   150
		waddch(dialog, ACS_HLINE);
yann@1
   151
	wattrset(dialog, dlg.dialog.atr);
yann@1
   152
	waddch(dialog, ACS_RTEE);
yann@1
   153
yann@1
   154
	print_title(dialog, title, width);
yann@1
   155
yann@1
   156
	wattrset(dialog, dlg.dialog.atr);
yann@1
   157
	print_autowrap(dialog, prompt, width - 2, 1, 3);
yann@1
   158
yann@1
   159
	list_width = width - 6;
yann@1
   160
	box_y = height - list_height - 5;
yann@1
   161
	box_x = (width - list_width) / 2 - 1;
yann@1
   162
yann@1
   163
	/* create new window for the list */
yann@1
   164
	list = subwin(dialog, list_height, list_width, y + box_y + 1,
yann@1
   165
	              x + box_x + 1);
yann@1
   166
yann@1
   167
	keypad(list, TRUE);
yann@1
   168
yann@1
   169
	/* draw a box around the list items */
yann@1
   170
	draw_box(dialog, box_y, box_x, list_height + 2, list_width + 2,
yann@1
   171
	         dlg.menubox_border.atr, dlg.menubox.atr);
yann@1
   172
yann@1
   173
	/* Find length of longest item in order to center checklist */
yann@1
   174
	check_x = 0;
yann@1
   175
	item_foreach()
yann@1
   176
		check_x = MAX(check_x, strlen(item_str()) + 4);
yann@1
   177
yann@1
   178
	check_x = (list_width - check_x) / 2;
yann@1
   179
	item_x = check_x + 4;
yann@1
   180
yann@1
   181
	if (choice >= list_height) {
yann@1
   182
		scroll = choice - list_height + 1;
yann@1
   183
		choice -= scroll;
yann@1
   184
	}
yann@1
   185
yann@1
   186
	/* Print the list */
yann@1
   187
	for (i = 0; i < max_choice; i++) {
yann@1
   188
		item_set(scroll + i);
yann@1
   189
		print_item(list, i, i == choice);
yann@1
   190
	}
yann@1
   191
yann@1
   192
	print_arrows(dialog, choice, item_count(), scroll,
yann@1
   193
		     box_y, box_x + check_x + 5, list_height);
yann@1
   194
yann@1
   195
	print_buttons(dialog, height, width, 0);
yann@1
   196
yann@1
   197
	wnoutrefresh(dialog);
yann@1
   198
	wnoutrefresh(list);
yann@1
   199
	doupdate();
yann@1
   200
yann@1
   201
	while (key != KEY_ESC) {
yann@1
   202
		key = wgetch(dialog);
yann@1
   203
yann@1
   204
		for (i = 0; i < max_choice; i++) {
yann@1
   205
			item_set(i + scroll);
yann@1
   206
			if (toupper(key) == toupper(item_str()[0]))
yann@1
   207
				break;
yann@1
   208
		}
yann@1
   209
yann@1
   210
		if (i < max_choice || key == KEY_UP || key == KEY_DOWN ||
yann@1
   211
		    key == '+' || key == '-') {
yann@1
   212
			if (key == KEY_UP || key == '-') {
yann@1
   213
				if (!choice) {
yann@1
   214
					if (!scroll)
yann@1
   215
						continue;
yann@1
   216
					/* Scroll list down */
yann@1
   217
					if (list_height > 1) {
yann@1
   218
						/* De-highlight current first item */
yann@1
   219
						item_set(scroll);
yann@1
   220
						print_item(list, 0, FALSE);
yann@1
   221
						scrollok(list, TRUE);
yann@1
   222
						wscrl(list, -1);
yann@1
   223
						scrollok(list, FALSE);
yann@1
   224
					}
yann@1
   225
					scroll--;
yann@1
   226
					item_set(scroll);
yann@1
   227
					print_item(list, 0, TRUE);
yann@1
   228
					print_arrows(dialog, choice, item_count(),
yann@1
   229
						     scroll, box_y, box_x + check_x + 5, list_height);
yann@1
   230
yann@1
   231
					wnoutrefresh(dialog);
yann@1
   232
					wrefresh(list);
yann@1
   233
yann@1
   234
					continue;	/* wait for another key press */
yann@1
   235
				} else
yann@1
   236
					i = choice - 1;
yann@1
   237
			} else if (key == KEY_DOWN || key == '+') {
yann@1
   238
				if (choice == max_choice - 1) {
yann@1
   239
					if (scroll + choice >= item_count() - 1)
yann@1
   240
						continue;
yann@1
   241
					/* Scroll list up */
yann@1
   242
					if (list_height > 1) {
yann@1
   243
						/* De-highlight current last item before scrolling up */
yann@1
   244
						item_set(scroll + max_choice - 1);
yann@1
   245
						print_item(list,
yann@1
   246
							    max_choice - 1,
yann@1
   247
							    FALSE);
yann@1
   248
						scrollok(list, TRUE);
yann@1
   249
						wscrl(list, 1);
yann@1
   250
						scrollok(list, FALSE);
yann@1
   251
					}
yann@1
   252
					scroll++;
yann@1
   253
					item_set(scroll + max_choice - 1);
yann@1
   254
					print_item(list, max_choice - 1, TRUE);
yann@1
   255
yann@1
   256
					print_arrows(dialog, choice, item_count(),
yann@1
   257
						     scroll, box_y, box_x + check_x + 5, list_height);
yann@1
   258
yann@1
   259
					wnoutrefresh(dialog);
yann@1
   260
					wrefresh(list);
yann@1
   261
yann@1
   262
					continue;	/* wait for another key press */
yann@1
   263
				} else
yann@1
   264
					i = choice + 1;
yann@1
   265
			}
yann@1
   266
			if (i != choice) {
yann@1
   267
				/* De-highlight current item */
yann@1
   268
				item_set(scroll + choice);
yann@1
   269
				print_item(list, choice, FALSE);
yann@1
   270
				/* Highlight new item */
yann@1
   271
				choice = i;
yann@1
   272
				item_set(scroll + choice);
yann@1
   273
				print_item(list, choice, TRUE);
yann@1
   274
				wnoutrefresh(dialog);
yann@1
   275
				wrefresh(list);
yann@1
   276
			}
yann@1
   277
			continue;	/* wait for another key press */
yann@1
   278
		}
yann@1
   279
		switch (key) {
yann@1
   280
		case 'H':
yann@1
   281
		case 'h':
yann@1
   282
		case '?':
yann@1
   283
			button = 1;
yann@1
   284
			/* fall-through */
yann@1
   285
		case 'S':
yann@1
   286
		case 's':
yann@1
   287
		case ' ':
yann@1
   288
		case '\n':
yann@1
   289
			item_foreach()
yann@1
   290
				item_set_selected(0);
yann@1
   291
			item_set(scroll + choice);
yann@1
   292
			item_set_selected(1);
yann@1
   293
			delwin(list);
yann@1
   294
			delwin(dialog);
yann@1
   295
			return button;
yann@1
   296
		case TAB:
yann@1
   297
		case KEY_LEFT:
yann@1
   298
		case KEY_RIGHT:
yann@1
   299
			button = ((key == KEY_LEFT ? --button : ++button) < 0)
yann@1
   300
			    ? 1 : (button > 1 ? 0 : button);
yann@1
   301
yann@1
   302
			print_buttons(dialog, height, width, button);
yann@1
   303
			wrefresh(dialog);
yann@1
   304
			break;
yann@1
   305
		case 'X':
yann@1
   306
		case 'x':
yann@1
   307
			key = KEY_ESC;
yann@1
   308
			break;
yann@1
   309
		case KEY_ESC:
yann@1
   310
			key = on_key_esc(dialog);
yann@1
   311
			break;
yann@1
   312
		case KEY_RESIZE:
yann@1
   313
			delwin(list);
yann@1
   314
			delwin(dialog);
yann@1
   315
			on_key_resize();
yann@1
   316
			goto do_resize;
yann@1
   317
		}
yann@1
   318
yann@1
   319
		/* Now, update everything... */
yann@1
   320
		doupdate();
yann@1
   321
	}
yann@1
   322
	delwin(list);
yann@1
   323
	delwin(dialog);
yann@1
   324
	return key;		/* ESC pressed */
yann@1
   325
}