kconfig/lxdialog/checklist.c
author "Yann E. MORIN" <yann.morin.1998@anciens.enib.fr>
Tue Aug 23 21:11:26 2011 +0200 (2011-08-23)
changeset 2891 f176fee535a0
parent 943 1cca90ce0481
permissions -rw-r--r--
cc/gcc: add 'cflags' paramater to the core backend

As the core backend is used to generate the bare-metal compiler,
we need to pass it the host CFLAGS.

Signed-off-by: "Yann E. MORIN" <yann.morin.1998@anciens.enib.fr>
     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 }