kconfig/lxdialog/checklist.c
author "Benoît Thébaudeau" <benoit.thebaudeau@advansee.com>
Mon Apr 16 15:25:36 2012 +0200 (2012-04-16)
changeset 2941 13e40098fffc
parent 943 1cca90ce0481
permissions -rw-r--r--
cc/gcc: update Linaro GCC revisions to 2012.04

Update Linaro GCC with the latest available revisions.

The 4.7 revision is also released, but the infrastructure is not yet ready for
it in CT-NG.

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