Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


Ported palacios to Kbuild
[palacios.git] / scripts / kconfig / lxdialog / menubox.c
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
61 static int menu_width, item_x;
62
63 /*
64  * Print menu item
65  */
66 static void do_print_item(WINDOW * win, const char *item, int choice,
67                           int selected, int hotkey)
68 {
69         int j;
70         char *menu_item = malloc(menu_width + 1);
71
72         strncpy(menu_item, item, menu_width - item_x);
73         menu_item[menu_width] = 0;
74         j = first_alpha(menu_item, "YyNnMmHh");
75
76         /* Clear 'residue' of last item */
77         wattrset(win, menubox_attr);
78         wmove(win, choice, 0);
79 #if OLD_NCURSES
80         {
81                 int i;
82                 for (i = 0; i < menu_width; i++)
83                         waddch(win, ' ');
84         }
85 #else
86         wclrtoeol(win);
87 #endif
88         wattrset(win, selected ? item_selected_attr : item_attr);
89         mvwaddstr(win, choice, item_x, menu_item);
90         if (hotkey) {
91                 wattrset(win, selected ? tag_key_selected_attr : tag_key_attr);
92                 mvwaddch(win, choice, item_x + j, menu_item[j]);
93         }
94         if (selected) {
95                 wmove(win, choice, item_x + 1);
96         }
97         free(menu_item);
98         wrefresh(win);
99 }
100
101 #define print_item(index, choice, selected) \
102 do {\
103         int hotkey = (items[(index) * 2][0] != ':'); \
104         do_print_item(menu, items[(index) * 2 + 1], choice, selected, hotkey); \
105 } while (0)
106
107 /*
108  * Print the scroll indicators.
109  */
110 static void print_arrows(WINDOW * win, int item_no, int scroll, int y, int x,
111                          int height)
112 {
113         int cur_y, cur_x;
114
115         getyx(win, cur_y, cur_x);
116
117         wmove(win, y, x);
118
119         if (scroll > 0) {
120                 wattrset(win, uarrow_attr);
121                 waddch(win, ACS_UARROW);
122                 waddstr(win, "(-)");
123         } else {
124                 wattrset(win, menubox_attr);
125                 waddch(win, ACS_HLINE);
126                 waddch(win, ACS_HLINE);
127                 waddch(win, ACS_HLINE);
128                 waddch(win, ACS_HLINE);
129         }
130
131         y = y + height + 1;
132         wmove(win, y, x);
133         wrefresh(win);
134
135         if ((height < item_no) && (scroll + height < item_no)) {
136                 wattrset(win, darrow_attr);
137                 waddch(win, ACS_DARROW);
138                 waddstr(win, "(+)");
139         } else {
140                 wattrset(win, menubox_border_attr);
141                 waddch(win, ACS_HLINE);
142                 waddch(win, ACS_HLINE);
143                 waddch(win, ACS_HLINE);
144                 waddch(win, ACS_HLINE);
145         }
146
147         wmove(win, cur_y, cur_x);
148         wrefresh(win);
149 }
150
151 /*
152  * Display the termination buttons.
153  */
154 static void print_buttons(WINDOW * win, int height, int width, int selected)
155 {
156         int x = width / 2 - 16;
157         int y = height - 2;
158
159         print_button(win, "Select", y, x, selected == 0);
160         print_button(win, " Exit ", y, x + 12, selected == 1);
161         print_button(win, " Help ", y, x + 24, selected == 2);
162
163         wmove(win, y, x + 1 + 12 * selected);
164         wrefresh(win);
165 }
166
167 /* scroll up n lines (n may be negative) */
168 static void do_scroll(WINDOW *win, int *scroll, int n)
169 {
170         /* Scroll menu up */
171         scrollok(win, TRUE);
172         wscrl(win, n);
173         scrollok(win, FALSE);
174         *scroll = *scroll + n;
175         wrefresh(win);
176 }
177
178 /*
179  * Display a menu for choosing among a number of options
180  */
181 int dialog_menu(const char *title, const char *prompt, int height, int width,
182                 int menu_height, const char *current, int item_no,
183                 const char *const *items)
184 {
185         int i, j, x, y, box_x, box_y;
186         int key = 0, button = 0, scroll = 0, choice = 0;
187         int first_item =  0, max_choice;
188         WINDOW *dialog, *menu;
189         FILE *f;
190
191         max_choice = MIN(menu_height, item_no);
192
193         /* center dialog box on screen */
194         x = (COLS - width) / 2;
195         y = (LINES - height) / 2;
196
197         draw_shadow(stdscr, y, x, height, width);
198
199         dialog = newwin(height, width, y, x);
200         keypad(dialog, TRUE);
201
202         draw_box(dialog, 0, 0, height, width, dialog_attr, border_attr);
203         wattrset(dialog, border_attr);
204         mvwaddch(dialog, height - 3, 0, ACS_LTEE);
205         for (i = 0; i < width - 2; i++)
206                 waddch(dialog, ACS_HLINE);
207         wattrset(dialog, dialog_attr);
208         wbkgdset(dialog, dialog_attr & A_COLOR);
209         waddch(dialog, ACS_RTEE);
210
211         print_title(dialog, title, width);
212
213         wattrset(dialog, dialog_attr);
214         print_autowrap(dialog, prompt, width - 2, 1, 3);
215
216         menu_width = width - 6;
217         box_y = height - menu_height - 5;
218         box_x = (width - menu_width) / 2 - 1;
219
220         /* create new window for the menu */
221         menu = subwin(dialog, menu_height, menu_width,
222                       y + box_y + 1, x + box_x + 1);
223         keypad(menu, TRUE);
224
225         /* draw a box around the menu items */
226         draw_box(dialog, box_y, box_x, menu_height + 2, menu_width + 2,
227                  menubox_border_attr, menubox_attr);
228
229         item_x = (menu_width - 70) / 2;
230
231         /* Set choice to default item */
232         for (i = 0; i < item_no; i++)
233                 if (strcmp(current, items[i * 2]) == 0)
234                         choice = i;
235
236         /* get the scroll info from the temp file */
237         if ((f = fopen("lxdialog.scrltmp", "r")) != NULL) {
238                 if ((fscanf(f, "%d\n", &scroll) == 1) && (scroll <= choice) &&
239                     (scroll + max_choice > choice) && (scroll >= 0) &&
240                     (scroll + max_choice <= item_no)) {
241                         first_item = scroll;
242                         choice = choice - scroll;
243                         fclose(f);
244                 } else {
245                         scroll = 0;
246                         remove("lxdialog.scrltmp");
247                         fclose(f);
248                         f = NULL;
249                 }
250         }
251         if ((choice >= max_choice) || (f == NULL && choice >= max_choice / 2)) {
252                 if (choice >= item_no - max_choice / 2)
253                         scroll = first_item = item_no - max_choice;
254                 else
255                         scroll = first_item = choice - max_choice / 2;
256                 choice = choice - scroll;
257         }
258
259         /* Print the menu */
260         for (i = 0; i < max_choice; i++) {
261                 print_item(first_item + i, i, i == choice);
262         }
263
264         wnoutrefresh(menu);
265
266         print_arrows(dialog, item_no, scroll,
267                      box_y, box_x + item_x + 1, menu_height);
268
269         print_buttons(dialog, height, width, 0);
270         wmove(menu, choice, item_x + 1);
271         wrefresh(menu);
272
273         while (key != ESC) {
274                 key = wgetch(menu);
275
276                 if (key < 256 && isalpha(key))
277                         key = tolower(key);
278
279                 if (strchr("ynmh", key))
280                         i = max_choice;
281                 else {
282                         for (i = choice + 1; i < max_choice; i++) {
283                                 j = first_alpha(items[(scroll + i) * 2 + 1], "YyNnMmHh");
284                                 if (key == tolower(items[(scroll + i) * 2 + 1][j]))
285                                         break;
286                         }
287                         if (i == max_choice)
288                                 for (i = 0; i < max_choice; i++) {
289                                         j = first_alpha(items [(scroll + i) * 2 + 1], "YyNnMmHh");
290                                         if (key == tolower(items[(scroll + i) * 2 + 1][j]))
291                                                 break;
292                                 }
293                 }
294
295                 if (i < max_choice ||
296                     key == KEY_UP || key == KEY_DOWN ||
297                     key == '-' || key == '+' ||
298                     key == KEY_PPAGE || key == KEY_NPAGE) {
299                         /* Remove highligt of current item */
300                         print_item(scroll + choice, choice, FALSE);
301
302                         if (key == KEY_UP || key == '-') {
303                                 if (choice < 2 && scroll) {
304                                         /* Scroll menu down */
305                                         do_scroll(menu, &scroll, -1);
306
307                                         print_item(scroll, 0, FALSE);
308                                 } else
309                                         choice = MAX(choice - 1, 0);
310
311                         } else if (key == KEY_DOWN || key == '+') {
312                                 print_item(scroll+choice, choice, FALSE);
313
314                                 if ((choice > max_choice - 3) &&
315                                     (scroll + max_choice < item_no)) {
316                                         /* Scroll menu up */
317                                         do_scroll(menu, &scroll, 1);
318
319                                         print_item(scroll+max_choice - 1,
320                                                    max_choice - 1, FALSE);
321                                 } else
322                                         choice = MIN(choice + 1, max_choice - 1);
323
324                         } else if (key == KEY_PPAGE) {
325                                 scrollok(menu, TRUE);
326                                 for (i = 0; (i < max_choice); i++) {
327                                         if (scroll > 0) {
328                                                 do_scroll(menu, &scroll, -1);
329                                                 print_item(scroll, 0, FALSE);
330                                         } else {
331                                                 if (choice > 0)
332                                                         choice--;
333                                         }
334                                 }
335
336                         } else if (key == KEY_NPAGE) {
337                                 for (i = 0; (i < max_choice); i++) {
338                                         if (scroll + max_choice < item_no) {
339                                                 do_scroll(menu, &scroll, 1);
340                                                 print_item(scroll+max_choice-1,
341                                                            max_choice - 1, FALSE);
342                                         } else {
343                                                 if (choice + 1 < max_choice)
344                                                         choice++;
345                                         }
346                                 }
347                         } else
348                                 choice = i;
349
350                         print_item(scroll + choice, choice, TRUE);
351
352                         print_arrows(dialog, item_no, scroll,
353                                      box_y, box_x + item_x + 1, menu_height);
354
355                         wnoutrefresh(dialog);
356                         wrefresh(menu);
357
358                         continue;       /* wait for another key press */
359                 }
360
361                 switch (key) {
362                 case KEY_LEFT:
363                 case TAB:
364                 case KEY_RIGHT:
365                         button = ((key == KEY_LEFT ? --button : ++button) < 0)
366                             ? 2 : (button > 2 ? 0 : button);
367
368                         print_buttons(dialog, height, width, button);
369                         wrefresh(menu);
370                         break;
371                 case ' ':
372                 case 's':
373                 case 'y':
374                 case 'n':
375                 case 'm':
376                 case '/':
377                         /* save scroll info */
378                         if ((f = fopen("lxdialog.scrltmp", "w")) != NULL) {
379                                 fprintf(f, "%d\n", scroll);
380                                 fclose(f);
381                         }
382                         delwin(dialog);
383                         fprintf(stderr, "%s\n", items[(scroll + choice) * 2]);
384                         switch (key) {
385                         case 's':
386                                 return 3;
387                         case 'y':
388                                 return 3;
389                         case 'n':
390                                 return 4;
391                         case 'm':
392                                 return 5;
393                         case ' ':
394                                 return 6;
395                         case '/':
396                                 return 7;
397                         }
398                         return 0;
399                 case 'h':
400                 case '?':
401                         button = 2;
402                 case '\n':
403                         delwin(dialog);
404                         if (button == 2)
405                                 fprintf(stderr, "%s \"%s\"\n",
406                                         items[(scroll + choice) * 2],
407                                         items[(scroll + choice) * 2 + 1] +
408                                         first_alpha(items [(scroll + choice) * 2 + 1], ""));
409                         else
410                                 fprintf(stderr, "%s\n",
411                                         items[(scroll + choice) * 2]);
412
413                         remove("lxdialog.scrltmp");
414                         return button;
415                 case 'e':
416                 case 'x':
417                         key = ESC;
418                 case ESC:
419                         break;
420                 }
421         }
422
423         delwin(dialog);
424         remove("lxdialog.scrltmp");
425         return -1;              /* ESC pressed */
426 }