Chameleon

Chameleon Svn Source Tree

Root/tags/2.0/i386/config/menubox.c

Source at commit 1808 created 12 years 3 months ago.
By blackosx, Revise layout of package installer 'Welcome' file so it looks cleaner. Change the copyright notice to begin from 2009 as seen in the Chameleon 2.0 r431 installer. Should this date be set earlier?
1/*
2 * menubox.c -- implements the menu box
3 *
4 * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
5 * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcapw@cfw.com)
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22/*
23 * Changes by Clifford Wolf (god@clifford.at)
24 *
25 * [ 1998-06-13 ]
26 *
27 * *) A bugfix for the Page-Down problem
28 *
29 * *) Formerly when I used Page Down and Page Up, the cursor would be set
30 * to the first position in the menu box. Now lxdialog is a bit
31 * smarter and works more like other menu systems (just have a look at
32 * it).
33 *
34 * *) Formerly if I selected something my scrolling would be broken because
35 * lxdialog is re-invoked by the Menuconfig shell script, can't
36 * remember the last scrolling position, and just sets it so that the
37 * cursor is at the bottom of the box. Now it writes the temporary file
38 * lxdialog.scrltmp which contains this information. The file is
39 * deleted by lxdialog if the user leaves a submenu or enters a new
40 * one, but it would be nice if Menuconfig could make another "rm -f"
41 * just to be sure. Just try it out - you will recognise a difference!
42 *
43 * [ 1998-06-14 ]
44 *
45 * *) Now lxdialog is crash-safe against broken "lxdialog.scrltmp" files
46 * and menus change their size on the fly.
47 *
48 * *) If for some reason the last scrolling position is not saved by
49 * lxdialog, it sets the scrolling so that the selected item is in the
50 * middle of the menu box, not at the bottom.
51 *
52 * 02 January 1999, Michael Elizabeth Chastain (mec@shout.net)
53 * Reset 'scroll' to 0 if the value from lxdialog.scrltmp is bogus.
54 * This fixes a bug in Menuconfig where using ' ' to descend into menus
55 * would leave mis-synchronized lxdialog.scrltmp files lying around,
56 * fscanf would read in 'scroll', and eventually that value would get used.
57 */
58
59#include "dialog.h"
60
61static int menu_width, item_x;
62
63/*
64 * Print menu item
65 */
66static void do_print_item(WINDOW * win, const char *item, int line_y,
67 int selected, int hotkey)
68{
69int j;
70char *menu_item = malloc(menu_width + 1);
71
72strncpy(menu_item, item, menu_width - item_x);
73menu_item[menu_width - item_x] = '\0';
74j = first_alpha(menu_item, "YyNnMmHh");
75
76/* Clear 'residue' of last item */
77wattrset(win, dlg.menubox.atr);
78wmove(win, line_y, 0);
79#if OLD_NCURSES
80{
81int i;
82for (i = 0; i < menu_width; i++)
83waddch(win, ' ');
84}
85#else
86wclrtoeol(win);
87#endif
88wattrset(win, selected ? dlg.item_selected.atr : dlg.item.atr);
89mvwaddstr(win, line_y, item_x, menu_item);
90if (hotkey) {
91wattrset(win, selected ? dlg.tag_key_selected.atr
92 : dlg.tag_key.atr);
93mvwaddch(win, line_y, item_x + j, menu_item[j]);
94}
95if (selected) {
96wmove(win, line_y, item_x + 1);
97}
98free(menu_item);
99wrefresh(win);
100}
101
102#define print_item(index, choice, selected)\
103do {\
104item_set(index);\
105do_print_item(menu, item_str(), choice, selected, !item_is_tag(':')); \
106} while (0)
107
108/*
109 * Print the scroll indicators.
110 */
111static void print_arrows(WINDOW * win, int item_no, int scroll, int y, int x,
112 int height)
113{
114int cur_y, cur_x;
115
116getyx(win, cur_y, cur_x);
117
118wmove(win, y, x);
119
120if (scroll > 0) {
121wattrset(win, dlg.uarrow.atr);
122waddch(win, ACS_UARROW);
123waddstr(win, "(-)");
124} else {
125wattrset(win, dlg.menubox.atr);
126waddch(win, ACS_HLINE);
127waddch(win, ACS_HLINE);
128waddch(win, ACS_HLINE);
129waddch(win, ACS_HLINE);
130}
131
132y = y + height + 1;
133wmove(win, y, x);
134wrefresh(win);
135
136if ((height < item_no) && (scroll + height < item_no)) {
137wattrset(win, dlg.darrow.atr);
138waddch(win, ACS_DARROW);
139waddstr(win, "(+)");
140} else {
141wattrset(win, dlg.menubox_border.atr);
142waddch(win, ACS_HLINE);
143waddch(win, ACS_HLINE);
144waddch(win, ACS_HLINE);
145waddch(win, ACS_HLINE);
146}
147
148wmove(win, cur_y, cur_x);
149wrefresh(win);
150}
151
152/*
153 * Display the termination buttons.
154 */
155static void print_buttons(WINDOW * win, int height, int width, int selected)
156{
157int x = width / 2 - 16;
158int y = height - 2;
159
160print_button(win, gettext("Select"), y, x, selected == 0);
161print_button(win, gettext(" Exit "), y, x + 12, selected == 1);
162print_button(win, gettext(" Help "), y, x + 24, selected == 2);
163
164wmove(win, y, x + 1 + 12 * selected);
165wrefresh(win);
166}
167
168/* scroll up n lines (n may be negative) */
169static void do_scroll(WINDOW *win, int *scroll, int n)
170{
171/* Scroll menu up */
172scrollok(win, TRUE);
173wscrl(win, n);
174scrollok(win, FALSE);
175*scroll = *scroll + n;
176wrefresh(win);
177}
178
179/*
180 * Display a menu for choosing among a number of options
181 */
182int dialog_menu(const char *title, const char *prompt,
183 const void *selected, int *s_scroll)
184{
185int i, j, x, y, box_x, box_y;
186int height, width, menu_height;
187int key = 0, button = 0, scroll = 0, choice = 0;
188int first_item = 0, max_choice;
189WINDOW *dialog, *menu;
190
191do_resize:
192height = getmaxy(stdscr);
193width = getmaxx(stdscr);
194if (height < 15 || width < 65)
195return -ERRDISPLAYTOOSMALL;
196
197height -= 4;
198width -= 5;
199menu_height = height - 10;
200
201max_choice = MIN(menu_height, item_count());
202
203/* center dialog box on screen */
204x = (COLS - width) / 2;
205y = (LINES - height) / 2;
206
207draw_shadow(stdscr, y, x, height, width);
208
209dialog = newwin(height, width, y, x);
210keypad(dialog, TRUE);
211
212draw_box(dialog, 0, 0, height, width,
213 dlg.dialog.atr, dlg.border.atr);
214wattrset(dialog, dlg.border.atr);
215mvwaddch(dialog, height - 3, 0, ACS_LTEE);
216for (i = 0; i < width - 2; i++)
217waddch(dialog, ACS_HLINE);
218wattrset(dialog, dlg.dialog.atr);
219wbkgdset(dialog, dlg.dialog.atr & A_COLOR);
220waddch(dialog, ACS_RTEE);
221
222print_title(dialog, title, width);
223
224wattrset(dialog, dlg.dialog.atr);
225print_autowrap(dialog, prompt, width - 2, 1, 3);
226
227menu_width = width - 6;
228box_y = height - menu_height - 5;
229box_x = (width - menu_width) / 2 - 1;
230
231/* create new window for the menu */
232menu = subwin(dialog, menu_height, menu_width,
233 y + box_y + 1, x + box_x + 1);
234keypad(menu, TRUE);
235
236/* draw a box around the menu items */
237draw_box(dialog, box_y, box_x, menu_height + 2, menu_width + 2,
238 dlg.menubox_border.atr, dlg.menubox.atr);
239
240if (menu_width >= 80)
241item_x = (menu_width - 70) / 2;
242else
243item_x = 4;
244
245/* Set choice to default item */
246item_foreach()
247if (selected && (selected == item_data()))
248choice = item_n();
249/* get the saved scroll info */
250scroll = *s_scroll;
251if ((scroll <= choice) && (scroll + max_choice > choice) &&
252 (scroll >= 0) && (scroll + max_choice <= item_count())) {
253first_item = scroll;
254choice = choice - scroll;
255} else {
256scroll = 0;
257}
258if ((choice >= max_choice)) {
259if (choice >= item_count() - max_choice / 2)
260scroll = first_item = item_count() - max_choice;
261else
262scroll = first_item = choice - max_choice / 2;
263choice = choice - scroll;
264}
265
266/* Print the menu */
267for (i = 0; i < max_choice; i++) {
268print_item(first_item + i, i, i == choice);
269}
270
271wnoutrefresh(menu);
272
273print_arrows(dialog, item_count(), scroll,
274 box_y, box_x + item_x + 1, menu_height);
275
276print_buttons(dialog, height, width, 0);
277wmove(menu, choice, item_x + 1);
278wrefresh(menu);
279
280while (key != KEY_ESC) {
281key = wgetch(menu);
282
283if (key < 256 && isalpha(key))
284key = tolower(key);
285
286if (strchr("ynmh", key))
287i = max_choice;
288else {
289for (i = choice + 1; i < max_choice; i++) {
290item_set(scroll + i);
291j = first_alpha(item_str(), "YyNnMmHh");
292if (key == tolower(item_str()[j]))
293break;
294}
295if (i == max_choice)
296for (i = 0; i < max_choice; i++) {
297item_set(scroll + i);
298j = first_alpha(item_str(), "YyNnMmHh");
299if (key == tolower(item_str()[j]))
300break;
301}
302}
303
304if (i < max_choice ||
305 key == KEY_UP || key == KEY_DOWN ||
306 key == '-' || key == '+' ||
307 key == KEY_PPAGE || key == KEY_NPAGE) {
308/* Remove highligt of current item */
309print_item(scroll + choice, choice, FALSE);
310
311if (key == KEY_UP || key == '-') {
312if (choice < 2 && scroll) {
313/* Scroll menu down */
314do_scroll(menu, &scroll, -1);
315
316print_item(scroll, 0, FALSE);
317} else
318choice = MAX(choice - 1, 0);
319
320} else if (key == KEY_DOWN || key == '+') {
321print_item(scroll+choice, choice, FALSE);
322
323if ((choice > max_choice - 3) &&
324 (scroll + max_choice < item_count())) {
325/* Scroll menu up */
326do_scroll(menu, &scroll, 1);
327
328print_item(scroll+max_choice - 1,
329 max_choice - 1, FALSE);
330} else
331choice = MIN(choice + 1, max_choice - 1);
332
333} else if (key == KEY_PPAGE) {
334scrollok(menu, TRUE);
335for (i = 0; (i < max_choice); i++) {
336if (scroll > 0) {
337do_scroll(menu, &scroll, -1);
338print_item(scroll, 0, FALSE);
339} else {
340if (choice > 0)
341choice--;
342}
343}
344
345} else if (key == KEY_NPAGE) {
346for (i = 0; (i < max_choice); i++) {
347if (scroll + max_choice < item_count()) {
348do_scroll(menu, &scroll, 1);
349print_item(scroll+max_choice-1,
350 max_choice - 1, FALSE);
351} else {
352if (choice + 1 < max_choice)
353choice++;
354}
355}
356} else
357choice = i;
358
359print_item(scroll + choice, choice, TRUE);
360
361print_arrows(dialog, item_count(), scroll,
362 box_y, box_x + item_x + 1, menu_height);
363
364wnoutrefresh(dialog);
365wrefresh(menu);
366
367continue;/* wait for another key press */
368}
369
370switch (key) {
371case KEY_LEFT:
372case TAB:
373case KEY_RIGHT:
374button = ((key == KEY_LEFT ? --button : ++button) < 0)
375 ? 2 : (button > 2 ? 0 : button);
376
377print_buttons(dialog, height, width, button);
378wrefresh(menu);
379break;
380case ' ':
381case 's':
382case 'y':
383case 'n':
384case 'm':
385case '/':
386case 'h':
387case '?':
388case 'z':
389case '\n':
390/* save scroll info */
391*s_scroll = scroll;
392delwin(menu);
393delwin(dialog);
394item_set(scroll + choice);
395item_set_selected(1);
396switch (key) {
397case 'h':
398case '?':
399return 2;
400case 's':
401case 'y':
402return 3;
403case 'n':
404return 4;
405case 'm':
406return 5;
407case ' ':
408return 6;
409case '/':
410return 7;
411case 'z':
412return 8;
413case '\n':
414return button;
415}
416return 0;
417case 'e':
418case 'x':
419key = KEY_ESC;
420break;
421case KEY_ESC:
422key = on_key_esc(menu);
423break;
424case KEY_RESIZE:
425on_key_resize();
426delwin(menu);
427delwin(dialog);
428goto do_resize;
429}
430}
431delwin(menu);
432delwin(dialog);
433return key;/* ESC pressed */
434}
435

Archive Download this file

Revision: 1808