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.


imported SEABIOS source tree
[palacios.git] / bios / seabios / tools / kconfig / nconf.gui.c
1 /*
2  * Copyright (C) 2008 Nir Tzachar <nir.tzachar@gmail.com?
3  * Released under the terms of the GNU GPL v2.0.
4  *
5  * Derived from menuconfig.
6  *
7  */
8 #include "nconf.h"
9
10 /* a list of all the different widgets we use */
11 attributes_t attributes[ATTR_MAX+1] = {0};
12
13 /* available colors:
14    COLOR_BLACK   0
15    COLOR_RED     1
16    COLOR_GREEN   2
17    COLOR_YELLOW  3
18    COLOR_BLUE    4
19    COLOR_MAGENTA 5
20    COLOR_CYAN    6
21    COLOR_WHITE   7
22    */
23 static void set_normal_colors(void)
24 {
25         init_pair(NORMAL, -1, -1);
26         init_pair(MAIN_HEADING, COLOR_MAGENTA, -1);
27
28         /* FORE is for the selected item */
29         init_pair(MAIN_MENU_FORE, -1, -1);
30         /* BACK for all the rest */
31         init_pair(MAIN_MENU_BACK, -1, -1);
32         init_pair(MAIN_MENU_GREY, -1, -1);
33         init_pair(MAIN_MENU_HEADING, COLOR_GREEN, -1);
34         init_pair(MAIN_MENU_BOX, COLOR_YELLOW, -1);
35
36         init_pair(SCROLLWIN_TEXT, -1, -1);
37         init_pair(SCROLLWIN_HEADING, COLOR_GREEN, -1);
38         init_pair(SCROLLWIN_BOX, COLOR_YELLOW, -1);
39
40         init_pair(DIALOG_TEXT, -1, -1);
41         init_pair(DIALOG_BOX, COLOR_YELLOW, -1);
42         init_pair(DIALOG_MENU_BACK, COLOR_YELLOW, -1);
43         init_pair(DIALOG_MENU_FORE, COLOR_RED, -1);
44
45         init_pair(INPUT_BOX, COLOR_YELLOW, -1);
46         init_pair(INPUT_HEADING, COLOR_GREEN, -1);
47         init_pair(INPUT_TEXT, -1, -1);
48         init_pair(INPUT_FIELD, -1, -1);
49
50         init_pair(FUNCTION_HIGHLIGHT, -1, -1);
51         init_pair(FUNCTION_TEXT, COLOR_BLUE, -1);
52 }
53
54 /* available attributes:
55    A_NORMAL        Normal display (no highlight)
56    A_STANDOUT      Best highlighting mode of the terminal.
57    A_UNDERLINE     Underlining
58    A_REVERSE       Reverse video
59    A_BLINK         Blinking
60    A_DIM           Half bright
61    A_BOLD          Extra bright or bold
62    A_PROTECT       Protected mode
63    A_INVIS         Invisible or blank mode
64    A_ALTCHARSET    Alternate character set
65    A_CHARTEXT      Bit-mask to extract a character
66    COLOR_PAIR(n)   Color-pair number n
67    */
68 static void normal_color_theme(void)
69 {
70         /* automatically add color... */
71 #define mkattr(name, attr) do { \
72 attributes[name] = attr | COLOR_PAIR(name); } while (0)
73         mkattr(NORMAL, NORMAL);
74         mkattr(MAIN_HEADING, A_BOLD | A_UNDERLINE);
75
76         mkattr(MAIN_MENU_FORE, A_REVERSE);
77         mkattr(MAIN_MENU_BACK, A_NORMAL);
78         mkattr(MAIN_MENU_GREY, A_NORMAL);
79         mkattr(MAIN_MENU_HEADING, A_BOLD);
80         mkattr(MAIN_MENU_BOX, A_NORMAL);
81
82         mkattr(SCROLLWIN_TEXT, A_NORMAL);
83         mkattr(SCROLLWIN_HEADING, A_BOLD);
84         mkattr(SCROLLWIN_BOX, A_BOLD);
85
86         mkattr(DIALOG_TEXT, A_BOLD);
87         mkattr(DIALOG_BOX, A_BOLD);
88         mkattr(DIALOG_MENU_FORE, A_STANDOUT);
89         mkattr(DIALOG_MENU_BACK, A_NORMAL);
90
91         mkattr(INPUT_BOX, A_NORMAL);
92         mkattr(INPUT_HEADING, A_BOLD);
93         mkattr(INPUT_TEXT, A_NORMAL);
94         mkattr(INPUT_FIELD, A_UNDERLINE);
95
96         mkattr(FUNCTION_HIGHLIGHT, A_BOLD);
97         mkattr(FUNCTION_TEXT, A_REVERSE);
98 }
99
100 static void no_colors_theme(void)
101 {
102         /* automatically add highlight, no color */
103 #define mkattrn(name, attr) { attributes[name] = attr; }
104
105         mkattrn(NORMAL, NORMAL);
106         mkattrn(MAIN_HEADING, A_BOLD | A_UNDERLINE);
107
108         mkattrn(MAIN_MENU_FORE, A_STANDOUT);
109         mkattrn(MAIN_MENU_BACK, A_NORMAL);
110         mkattrn(MAIN_MENU_GREY, A_NORMAL);
111         mkattrn(MAIN_MENU_HEADING, A_BOLD);
112         mkattrn(MAIN_MENU_BOX, A_NORMAL);
113
114         mkattrn(SCROLLWIN_TEXT, A_NORMAL);
115         mkattrn(SCROLLWIN_HEADING, A_BOLD);
116         mkattrn(SCROLLWIN_BOX, A_BOLD);
117
118         mkattrn(DIALOG_TEXT, A_NORMAL);
119         mkattrn(DIALOG_BOX, A_BOLD);
120         mkattrn(DIALOG_MENU_FORE, A_STANDOUT);
121         mkattrn(DIALOG_MENU_BACK, A_NORMAL);
122
123         mkattrn(INPUT_BOX, A_BOLD);
124         mkattrn(INPUT_HEADING, A_BOLD);
125         mkattrn(INPUT_TEXT, A_NORMAL);
126         mkattrn(INPUT_FIELD, A_UNDERLINE);
127
128         mkattrn(FUNCTION_HIGHLIGHT, A_BOLD);
129         mkattrn(FUNCTION_TEXT, A_REVERSE);
130 }
131
132 void set_colors()
133 {
134         start_color();
135         use_default_colors();
136         set_normal_colors();
137         if (has_colors()) {
138                 normal_color_theme();
139         } else {
140                 /* give defaults */
141                 no_colors_theme();
142         }
143 }
144
145
146 /* this changes the windows attributes !!! */
147 void print_in_middle(WINDOW *win,
148                 int starty,
149                 int startx,
150                 int width,
151                 const char *string,
152                 chtype color)
153 {      int length, x, y;
154         float temp;
155
156
157         if (win == NULL)
158                 win = stdscr;
159         getyx(win, y, x);
160         if (startx != 0)
161                 x = startx;
162         if (starty != 0)
163                 y = starty;
164         if (width == 0)
165                 width = 80;
166
167         length = strlen(string);
168         temp = (width - length) / 2;
169         x = startx + (int)temp;
170         (void) wattrset(win, color);
171         mvwprintw(win, y, x, "%s", string);
172         refresh();
173 }
174
175 int get_line_no(const char *text)
176 {
177         int i;
178         int total = 1;
179
180         if (!text)
181                 return 0;
182
183         for (i = 0; text[i] != '\0'; i++)
184                 if (text[i] == '\n')
185                         total++;
186         return total;
187 }
188
189 const char *get_line(const char *text, int line_no)
190 {
191         int i;
192         int lines = 0;
193
194         if (!text)
195                 return 0;
196
197         for (i = 0; text[i] != '\0' && lines < line_no; i++)
198                 if (text[i] == '\n')
199                         lines++;
200         return text+i;
201 }
202
203 int get_line_length(const char *line)
204 {
205         int res = 0;
206         while (*line != '\0' && *line != '\n') {
207                 line++;
208                 res++;
209         }
210         return res;
211 }
212
213 /* print all lines to the window. */
214 void fill_window(WINDOW *win, const char *text)
215 {
216         int x, y;
217         int total_lines = get_line_no(text);
218         int i;
219
220         getmaxyx(win, y, x);
221         /* do not go over end of line */
222         total_lines = min(total_lines, y);
223         for (i = 0; i < total_lines; i++) {
224                 char tmp[x+10];
225                 const char *line = get_line(text, i);
226                 int len = get_line_length(line);
227                 strncpy(tmp, line, min(len, x));
228                 tmp[len] = '\0';
229                 mvwprintw(win, i, 0, "%s", tmp);
230         }
231 }
232
233 /* get the message, and buttons.
234  * each button must be a char*
235  * return the selected button
236  *
237  * this dialog is used for 2 different things:
238  * 1) show a text box, no buttons.
239  * 2) show a dialog, with horizontal buttons
240  */
241 int btn_dialog(WINDOW *main_window, const char *msg, int btn_num, ...)
242 {
243         va_list ap;
244         char *btn;
245         int btns_width = 0;
246         int msg_lines = 0;
247         int msg_width = 0;
248         int total_width;
249         int win_rows = 0;
250         WINDOW *win;
251         WINDOW *msg_win;
252         WINDOW *menu_win;
253         MENU *menu;
254         ITEM *btns[btn_num+1];
255         int i, x, y;
256         int res = -1;
257
258
259         va_start(ap, btn_num);
260         for (i = 0; i < btn_num; i++) {
261                 btn = va_arg(ap, char *);
262                 btns[i] = new_item(btn, "");
263                 btns_width += strlen(btn)+1;
264         }
265         va_end(ap);
266         btns[btn_num] = NULL;
267
268         /* find the widest line of msg: */
269         msg_lines = get_line_no(msg);
270         for (i = 0; i < msg_lines; i++) {
271                 const char *line = get_line(msg, i);
272                 int len = get_line_length(line);
273                 if (msg_width < len)
274                         msg_width = len;
275         }
276
277         total_width = max(msg_width, btns_width);
278         /* place dialog in middle of screen */
279         y = (LINES-(msg_lines+4))/2;
280         x = (COLS-(total_width+4))/2;
281
282
283         /* create the windows */
284         if (btn_num > 0)
285                 win_rows = msg_lines+4;
286         else
287                 win_rows = msg_lines+2;
288
289         win = newwin(win_rows, total_width+4, y, x);
290         keypad(win, TRUE);
291         menu_win = derwin(win, 1, btns_width, win_rows-2,
292                         1+(total_width+2-btns_width)/2);
293         menu = new_menu(btns);
294         msg_win = derwin(win, win_rows-2, msg_width, 1,
295                         1+(total_width+2-msg_width)/2);
296
297         set_menu_fore(menu, attributes[DIALOG_MENU_FORE]);
298         set_menu_back(menu, attributes[DIALOG_MENU_BACK]);
299
300         (void) wattrset(win, attributes[DIALOG_BOX]);
301         box(win, 0, 0);
302
303         /* print message */
304         (void) wattrset(msg_win, attributes[DIALOG_TEXT]);
305         fill_window(msg_win, msg);
306
307         set_menu_win(menu, win);
308         set_menu_sub(menu, menu_win);
309         set_menu_format(menu, 1, btn_num);
310         menu_opts_off(menu, O_SHOWDESC);
311         menu_opts_off(menu, O_SHOWMATCH);
312         menu_opts_on(menu, O_ONEVALUE);
313         menu_opts_on(menu, O_NONCYCLIC);
314         set_menu_mark(menu, "");
315         post_menu(menu);
316
317
318         touchwin(win);
319         refresh_all_windows(main_window);
320         while ((res = wgetch(win))) {
321                 switch (res) {
322                 case KEY_LEFT:
323                         menu_driver(menu, REQ_LEFT_ITEM);
324                         break;
325                 case KEY_RIGHT:
326                         menu_driver(menu, REQ_RIGHT_ITEM);
327                         break;
328                 case 10: /* ENTER */
329                 case 27: /* ESCAPE */
330                 case ' ':
331                 case KEY_F(F_BACK):
332                 case KEY_F(F_EXIT):
333                         break;
334                 }
335                 touchwin(win);
336                 refresh_all_windows(main_window);
337
338                 if (res == 10 || res == ' ') {
339                         res = item_index(current_item(menu));
340                         break;
341                 } else if (res == 27 || res == KEY_F(F_BACK) ||
342                                 res == KEY_F(F_EXIT)) {
343                         res = KEY_EXIT;
344                         break;
345                 }
346         }
347
348         unpost_menu(menu);
349         free_menu(menu);
350         for (i = 0; i < btn_num; i++)
351                 free_item(btns[i]);
352
353         delwin(win);
354         return res;
355 }
356
357 int dialog_inputbox(WINDOW *main_window,
358                 const char *title, const char *prompt,
359                 const char *init, char *result, int result_len)
360 {
361         int prompt_lines = 0;
362         int prompt_width = 0;
363         WINDOW *win;
364         WINDOW *prompt_win;
365         WINDOW *form_win;
366         PANEL *panel;
367         int i, x, y;
368         int res = -1;
369         int cursor_position = strlen(init);
370
371
372         /* find the widest line of msg: */
373         prompt_lines = get_line_no(prompt);
374         for (i = 0; i < prompt_lines; i++) {
375                 const char *line = get_line(prompt, i);
376                 int len = get_line_length(line);
377                 prompt_width = max(prompt_width, len);
378         }
379
380         if (title)
381                 prompt_width = max(prompt_width, strlen(title));
382
383         /* place dialog in middle of screen */
384         y = (LINES-(prompt_lines+4))/2;
385         x = (COLS-(prompt_width+4))/2;
386
387         strncpy(result, init, result_len);
388
389         /* create the windows */
390         win = newwin(prompt_lines+6, prompt_width+7, y, x);
391         prompt_win = derwin(win, prompt_lines+1, prompt_width, 2, 2);
392         form_win = derwin(win, 1, prompt_width, prompt_lines+3, 2);
393         keypad(form_win, TRUE);
394
395         (void) wattrset(form_win, attributes[INPUT_FIELD]);
396
397         (void) wattrset(win, attributes[INPUT_BOX]);
398         box(win, 0, 0);
399         (void) wattrset(win, attributes[INPUT_HEADING]);
400         if (title)
401                 mvwprintw(win, 0, 3, "%s", title);
402
403         /* print message */
404         (void) wattrset(prompt_win, attributes[INPUT_TEXT]);
405         fill_window(prompt_win, prompt);
406
407         mvwprintw(form_win, 0, 0, "%*s", prompt_width, " ");
408         mvwprintw(form_win, 0, 0, "%s", result);
409
410         /* create panels */
411         panel = new_panel(win);
412
413         /* show the cursor */
414         curs_set(1);
415
416         touchwin(win);
417         refresh_all_windows(main_window);
418         while ((res = wgetch(form_win))) {
419                 int len = strlen(result);
420                 switch (res) {
421                 case 10: /* ENTER */
422                 case 27: /* ESCAPE */
423                 case KEY_F(F_HELP):
424                 case KEY_F(F_EXIT):
425                 case KEY_F(F_BACK):
426                         break;
427                 case 127:
428                 case KEY_BACKSPACE:
429                         if (cursor_position > 0) {
430                                 memmove(&result[cursor_position-1],
431                                                 &result[cursor_position],
432                                                 len-cursor_position+1);
433                                 cursor_position--;
434                         }
435                         break;
436                 case KEY_DC:
437                         if (cursor_position >= 0 && cursor_position < len) {
438                                 memmove(&result[cursor_position],
439                                                 &result[cursor_position+1],
440                                                 len-cursor_position+1);
441                         }
442                         break;
443                 case KEY_UP:
444                 case KEY_RIGHT:
445                         if (cursor_position < len &&
446                             cursor_position < min(result_len, prompt_width))
447                                 cursor_position++;
448                         break;
449                 case KEY_DOWN:
450                 case KEY_LEFT:
451                         if (cursor_position > 0)
452                                 cursor_position--;
453                         break;
454                 default:
455                         if ((isgraph(res) || isspace(res)) &&
456                                         len-2 < result_len) {
457                                 /* insert the char at the proper position */
458                                 memmove(&result[cursor_position+1],
459                                                 &result[cursor_position],
460                                                 len+1);
461                                 result[cursor_position] = res;
462                                 cursor_position++;
463                         } else {
464                                 mvprintw(0, 0, "unknow key: %d\n", res);
465                         }
466                         break;
467                 }
468                 wmove(form_win, 0, 0);
469                 wclrtoeol(form_win);
470                 mvwprintw(form_win, 0, 0, "%*s", prompt_width, " ");
471                 mvwprintw(form_win, 0, 0, "%s", result);
472                 wmove(form_win, 0, cursor_position);
473                 touchwin(win);
474                 refresh_all_windows(main_window);
475
476                 if (res == 10) {
477                         res = 0;
478                         break;
479                 } else if (res == 27 || res == KEY_F(F_BACK) ||
480                                 res == KEY_F(F_EXIT)) {
481                         res = KEY_EXIT;
482                         break;
483                 } else if (res == KEY_F(F_HELP)) {
484                         res = 1;
485                         break;
486                 }
487         }
488
489         /* hide the cursor */
490         curs_set(0);
491         del_panel(panel);
492         delwin(prompt_win);
493         delwin(form_win);
494         delwin(win);
495         return res;
496 }
497
498 /* refresh all windows in the correct order */
499 void refresh_all_windows(WINDOW *main_window)
500 {
501         update_panels();
502         touchwin(main_window);
503         refresh();
504 }
505
506 /* layman's scrollable window... */
507 void show_scroll_win(WINDOW *main_window,
508                 const char *title,
509                 const char *text)
510 {
511         int res;
512         int total_lines = get_line_no(text);
513         int x, y;
514         int start_x = 0, start_y = 0;
515         int text_lines = 0, text_cols = 0;
516         int total_cols = 0;
517         int win_cols = 0;
518         int win_lines = 0;
519         int i = 0;
520         WINDOW *win;
521         WINDOW *pad;
522         PANEL *panel;
523
524         /* find the widest line of msg: */
525         total_lines = get_line_no(text);
526         for (i = 0; i < total_lines; i++) {
527                 const char *line = get_line(text, i);
528                 int len = get_line_length(line);
529                 total_cols = max(total_cols, len+2);
530         }
531
532         /* create the pad */
533         pad = newpad(total_lines+10, total_cols+10);
534         (void) wattrset(pad, attributes[SCROLLWIN_TEXT]);
535         fill_window(pad, text);
536
537         win_lines = min(total_lines+4, LINES-2);
538         win_cols = min(total_cols+2, COLS-2);
539         text_lines = max(win_lines-4, 0);
540         text_cols = max(win_cols-2, 0);
541
542         /* place window in middle of screen */
543         y = (LINES-win_lines)/2;
544         x = (COLS-win_cols)/2;
545
546         win = newwin(win_lines, win_cols, y, x);
547         keypad(win, TRUE);
548         /* show the help in the help window, and show the help panel */
549         (void) wattrset(win, attributes[SCROLLWIN_BOX]);
550         box(win, 0, 0);
551         (void) wattrset(win, attributes[SCROLLWIN_HEADING]);
552         mvwprintw(win, 0, 3, " %s ", title);
553         panel = new_panel(win);
554
555         /* handle scrolling */
556         do {
557
558                 copywin(pad, win, start_y, start_x, 2, 2, text_lines,
559                                 text_cols, 0);
560                 print_in_middle(win,
561                                 text_lines+2,
562                                 0,
563                                 text_cols,
564                                 "<OK>",
565                                 attributes[DIALOG_MENU_FORE]);
566                 wrefresh(win);
567
568                 res = wgetch(win);
569                 switch (res) {
570                 case KEY_NPAGE:
571                 case ' ':
572                         start_y += text_lines-2;
573                         break;
574                 case KEY_PPAGE:
575                         start_y -= text_lines+2;
576                         break;
577                 case KEY_HOME:
578                         start_y = 0;
579                         break;
580                 case KEY_END:
581                         start_y = total_lines-text_lines;
582                         break;
583                 case KEY_DOWN:
584                 case 'j':
585                         start_y++;
586                         break;
587                 case KEY_UP:
588                 case 'k':
589                         start_y--;
590                         break;
591                 case KEY_LEFT:
592                 case 'h':
593                         start_x--;
594                         break;
595                 case KEY_RIGHT:
596                 case 'l':
597                         start_x++;
598                         break;
599                 }
600                 if (res == 10 || res == 27 || res == 'q'
601                     || res == KEY_F(F_BACK) || res == KEY_F(F_EXIT)) {
602                         break;
603                 }
604                 if (start_y < 0)
605                         start_y = 0;
606                 if (start_y >= total_lines-text_lines)
607                         start_y = total_lines-text_lines;
608                 if (start_x < 0)
609                         start_x = 0;
610                 if (start_x >= total_cols-text_cols)
611                         start_x = total_cols-text_cols;
612         } while (res);
613
614         del_panel(panel);
615         delwin(win);
616         refresh_all_windows(main_window);
617 }