|
|
1.1 root 1: /*
2: * Copyright (C) 2008 Nir Tzachar <[email protected]?
3: * Released under the terms of the GNU GPL v2.0.
4: *
5: * Derived from menuconfig.
6: *
7: */
8: #define _GNU_SOURCE
9: #include <string.h>
10: #define LKC_DIRECT_LINK
11: #include "lkc.h"
12: #include "nconf.h"
13: #include <ctype.h>
14:
15: static const char nconf_readme[] = N_(
16: "Overview\n"
17: "--------\n"
18: "This interface let you select features and parameters for the build.\n"
19: "Features can either be built-in, modularized, or ignored. Parameters\n"
20: "must be entered in as decimal or hexadecimal numbers or text.\n"
21: "\n"
22: "Menu items beginning with following braces represent features that\n"
23: " [ ] can be built in or removed\n"
24: " < > can be built in, modularized or removed\n"
25: " { } can be built in or modularized (selected by other feature)\n"
26: " - - are selected by other feature,\n"
27: " XXX cannot be selected. Use Symbol Info to find out why,\n"
28: "while *, M or whitespace inside braces means to build in, build as\n"
29: "a module or to exclude the feature respectively.\n"
30: "\n"
31: "To change any of these features, highlight it with the cursor\n"
32: "keys and press <Y> to build it in, <M> to make it a module or\n"
33: "<N> to removed it. You may also press the <Space Bar> to cycle\n"
34: "through the available options (ie. Y->N->M->Y).\n"
35: "\n"
36: "Some additional keyboard hints:\n"
37: "\n"
38: "Menus\n"
39: "----------\n"
40: "o Use the Up/Down arrow keys (cursor keys) to highlight the item\n"
41: " you wish to change use <Enter> or <Space>. Goto submenu by \n"
42: " pressing <Enter> of <right-arrow>. Use <Esc> or <left-arrow> to go back.\n"
43: " Submenus are designated by \"--->\".\n"
44: "\n"
45: " Searching: pressing '/' triggers interactive search mode.\n"
46: " nconfig performs a case insensitive search for the string\n"
47: " in the menu prompts (no regex support).\n"
48: " Pressing the up/down keys highlights the previous/next\n"
49: " matching item. Backspace removes one character from the\n"
50: " match string. Pressing either '/' again or ESC exits\n"
51: " search mode. All other keys behave normally.\n"
52: "\n"
53: " You may also use the <PAGE UP> and <PAGE DOWN> keys to scroll\n"
54: " unseen options into view.\n"
55: "\n"
56: "o To exit a menu use the just press <ESC> <F5> <F8> or <left-arrow>.\n"
57: "\n"
58: "o To get help with an item, press <F1>\n"
59: " Shortcut: Press <h> or <?>.\n"
60: "\n"
61: "\n"
62: "Radiolists (Choice lists)\n"
63: "-----------\n"
64: "o Use the cursor keys to select the option you wish to set and press\n"
65: " <S> or the <SPACE BAR>.\n"
66: "\n"
67: " Shortcut: Press the first letter of the option you wish to set then\n"
68: " press <S> or <SPACE BAR>.\n"
69: "\n"
70: "o To see available help for the item, press <F1>\n"
71: " Shortcut: Press <H> or <?>.\n"
72: "\n"
73: "\n"
74: "Data Entry\n"
75: "-----------\n"
76: "o Enter the requested information and press <ENTER>\n"
77: " If you are entering hexadecimal values, it is not necessary to\n"
78: " add the '0x' prefix to the entry.\n"
79: "\n"
80: "o For help, press <F1>.\n"
81: "\n"
82: "\n"
83: "Text Box (Help Window)\n"
84: "--------\n"
85: "o Use the cursor keys to scroll up/down/left/right. The VI editor\n"
86: " keys h,j,k,l function here as do <SPACE BAR> for those\n"
87: " who are familiar with less and lynx.\n"
88: "\n"
89: "o Press <Enter>, <F1>, <F5>, <F7> or <Esc> to exit.\n"
90: "\n"
91: "\n"
92: "Alternate Configuration Files\n"
93: "-----------------------------\n"
94: "nconfig supports the use of alternate configuration files for\n"
95: "those who, for various reasons, find it necessary to switch\n"
96: "between different configurations.\n"
97: "\n"
98: "At the end of the main menu you will find two options. One is\n"
99: "for saving the current configuration to a file of your choosing.\n"
100: "The other option is for loading a previously saved alternate\n"
101: "configuration.\n"
102: "\n"
103: "Even if you don't use alternate configuration files, but you\n"
104: "find during a nconfig session that you have completely messed\n"
105: "up your settings, you may use the \"Load Alternate...\" option to\n"
106: "restore your previously saved settings from \".config\" without\n"
107: "restarting nconfig.\n"
108: "\n"
109: "Other information\n"
110: "-----------------\n"
111: "If you use nconfig in an XTERM window make sure you have your\n"
112: "$TERM variable set to point to a xterm definition which supports color.\n"
113: "Otherwise, nconfig will look rather bad. nconfig will not\n"
114: "display correctly in a RXVT window because rxvt displays only one\n"
115: "intensity of color, bright.\n"
116: "\n"
117: "nconfig will display larger menus on screens or xterms which are\n"
118: "set to display more than the standard 25 row by 80 column geometry.\n"
119: "In order for this to work, the \"stty size\" command must be able to\n"
120: "display the screen's current row and column geometry. I STRONGLY\n"
121: "RECOMMEND that you make sure you do NOT have the shell variables\n"
122: "LINES and COLUMNS exported into your environment. Some distributions\n"
123: "export those variables via /etc/profile. Some ncurses programs can\n"
124: "become confused when those variables (LINES & COLUMNS) don't reflect\n"
125: "the true screen size.\n"
126: "\n"
127: "Optional personality available\n"
128: "------------------------------\n"
129: "If you prefer to have all of the options listed in a single menu, rather\n"
130: "than the default multimenu hierarchy, run the nconfig with NCONFIG_MODE\n"
131: "environment variable set to single_menu. Example:\n"
132: "\n"
133: "make NCONFIG_MODE=single_menu nconfig\n"
134: "\n"
135: "<Enter> will then unroll the appropriate category, or enfold it if it\n"
136: "is already unrolled.\n"
137: "\n"
138: "Note that this mode can eventually be a little more CPU expensive\n"
139: "(especially with a larger number of unrolled categories) than the\n"
140: "default mode.\n"
141: "\n"),
142: menu_no_f_instructions[] = N_(
143: " You do not have function keys support. Please follow the\n"
144: " following instructions:\n"
145: " Arrow keys navigate the menu.\n"
146: " <Enter> or <right-arrow> selects submenus --->.\n"
147: " Capital Letters are hotkeys.\n"
148: " Pressing <Y> includes, <N> excludes, <M> modularizes features.\n"
149: " Pressing SpaceBar toggles between the above options.\n"
150: " Press <Esc> or <left-arrow> to go back one menu,\n"
151: " <?> or <h> for Help, </> for Search.\n"
152: " <1> is interchangeable with <F1>, <2> with <F2>, etc.\n"
153: " Legend: [*] built-in [ ] excluded <M> module < > module capable.\n"
154: " <Esc> always leaves the current window.\n"),
155: menu_instructions[] = N_(
156: " Arrow keys navigate the menu.\n"
157: " <Enter> or <right-arrow> selects submenus --->.\n"
158: " Capital Letters are hotkeys.\n"
159: " Pressing <Y> includes, <N> excludes, <M> modularizes features.\n"
160: " Pressing SpaceBar toggles between the above options\n"
161: " Press <Esc>, <F5> or <left-arrow> to go back one menu,\n"
162: " <?>, <F1> or <h> for Help, </> for Search.\n"
163: " <1> is interchangeable with <F1>, <2> with <F2>, etc.\n"
164: " Legend: [*] built-in [ ] excluded <M> module < > module capable.\n"
165: " <Esc> always leaves the current window\n"),
166: radiolist_instructions[] = N_(
167: " Use the arrow keys to navigate this window or\n"
168: " press the hotkey of the item you wish to select\n"
169: " followed by the <SPACE BAR>.\n"
170: " Press <?>, <F1> or <h> for additional information about this option.\n"),
171: inputbox_instructions_int[] = N_(
172: "Please enter a decimal value.\n"
173: "Fractions will not be accepted.\n"
174: "Press <RETURN> to accept, <ESC> to cancel."),
175: inputbox_instructions_hex[] = N_(
176: "Please enter a hexadecimal value.\n"
177: "Press <RETURN> to accept, <ESC> to cancel."),
178: inputbox_instructions_string[] = N_(
179: "Please enter a string value.\n"
180: "Press <RETURN> to accept, <ESC> to cancel."),
181: setmod_text[] = N_(
182: "This feature depends on another which\n"
183: "has been configured as a module.\n"
184: "As a result, this feature will be built as a module."),
185: nohelp_text[] = N_(
186: "There is no help available for this option.\n"),
187: load_config_text[] = N_(
188: "Enter the name of the configuration file you wish to load.\n"
189: "Accept the name shown to restore the configuration you\n"
190: "last retrieved. Leave blank to abort."),
191: load_config_help[] = N_(
192: "\n"
193: "For various reasons, one may wish to keep several different\n"
194: "configurations available on a single machine.\n"
195: "\n"
196: "If you have saved a previous configuration in a file other than the\n"
197: "default one, entering its name here will allow you to modify that\n"
198: "configuration.\n"
199: "\n"
200: "If you are uncertain, then you have probably never used alternate\n"
201: "configuration files. You should therefor leave this blank to abort.\n"),
202: save_config_text[] = N_(
203: "Enter a filename to which this configuration should be saved\n"
204: "as an alternate. Leave blank to abort."),
205: save_config_help[] = N_(
206: "\n"
207: "For various reasons, one may wish to keep different configurations\n"
208: "available on a single machine.\n"
209: "\n"
210: "Entering a file name here will allow you to later retrieve, modify\n"
211: "and use the current configuration as an alternate to whatever\n"
212: "configuration options you have selected at that time.\n"
213: "\n"
214: "If you are uncertain what all this means then you should probably\n"
215: "leave this blank.\n"),
216: search_help[] = N_(
217: "\n"
218: "Search for symbols and display their relations. Regular expressions\n"
219: "are allowed.\n"
220: "Example: search for \"^FOO\"\n"
221: "Result:\n"
222: "-----------------------------------------------------------------\n"
223: "Symbol: FOO [ = m]\n"
224: "Prompt: Foo bus is used to drive the bar HW\n"
225: "Defined at drivers/pci/Kconfig:47\n"
226: "Depends on: X86_LOCAL_APIC && X86_IO_APIC || IA64\n"
227: "Location:\n"
228: " -> Bus options (PCI, PCMCIA, EISA, MCA, ISA)\n"
229: " -> PCI support (PCI [ = y])\n"
230: " -> PCI access mode (<choice> [ = y])\n"
231: "Selects: LIBCRC32\n"
232: "Selected by: BAR\n"
233: "-----------------------------------------------------------------\n"
234: "o The line 'Prompt:' shows the text used in the menu structure for\n"
235: " this symbol\n"
236: "o The 'Defined at' line tell at what file / line number the symbol\n"
237: " is defined\n"
238: "o The 'Depends on:' line tell what symbols needs to be defined for\n"
239: " this symbol to be visible in the menu (selectable)\n"
240: "o The 'Location:' lines tell where in the menu structure this symbol\n"
241: " is located\n"
242: " A location followed by a [ = y] indicate that this is a selectable\n"
243: " menu item - and current value is displayed inside brackets.\n"
244: "o The 'Selects:' line tell what symbol will be automatically\n"
245: " selected if this symbol is selected (y or m)\n"
246: "o The 'Selected by' line tell what symbol has selected this symbol\n"
247: "\n"
248: "Only relevant lines are shown.\n"
249: "\n\n"
250: "Search examples:\n"
251: "Examples: USB => find all symbols containing USB\n"
252: " ^USB => find all symbols starting with USB\n"
253: " USB$ => find all symbols ending with USB\n"
254: "\n");
255:
256: struct mitem {
257: char str[256];
258: char tag;
259: void *usrptr;
260: int is_visible;
261: };
262:
263: #define MAX_MENU_ITEMS 4096
264: static int show_all_items;
265: static int indent;
266: static struct menu *current_menu;
267: static int child_count;
268: static int single_menu_mode;
269: /* the window in which all information appears */
270: static WINDOW *main_window;
271: /* the largest size of the menu window */
272: static int mwin_max_lines;
273: static int mwin_max_cols;
274: /* the window in which we show option buttons */
275: static MENU *curses_menu;
276: static ITEM *curses_menu_items[MAX_MENU_ITEMS];
277: static struct mitem k_menu_items[MAX_MENU_ITEMS];
278: static int items_num;
279: static int global_exit;
280: /* the currently selected button */
281: const char *current_instructions = menu_instructions;
282:
283: static void conf(struct menu *menu);
284: static void conf_choice(struct menu *menu);
285: static void conf_string(struct menu *menu);
286: static void conf_load(void);
287: static void conf_save(void);
288: static void show_help(struct menu *menu);
289: static int do_exit(void);
290: static void setup_windows(void);
291: static void search_conf(void);
292:
293: typedef void (*function_key_handler_t)(int *key, struct menu *menu);
294: static void handle_f1(int *key, struct menu *current_item);
295: static void handle_f2(int *key, struct menu *current_item);
296: static void handle_f3(int *key, struct menu *current_item);
297: static void handle_f4(int *key, struct menu *current_item);
298: static void handle_f5(int *key, struct menu *current_item);
299: static void handle_f6(int *key, struct menu *current_item);
300: static void handle_f7(int *key, struct menu *current_item);
301: static void handle_f8(int *key, struct menu *current_item);
302: static void handle_f9(int *key, struct menu *current_item);
303:
304: struct function_keys {
305: const char *key_str;
306: const char *func;
307: function_key key;
308: function_key_handler_t handler;
309: };
310:
311: static const int function_keys_num = 9;
312: struct function_keys function_keys[] = {
313: {
314: .key_str = "F1",
315: .func = "Help",
316: .key = F_HELP,
317: .handler = handle_f1,
318: },
319: {
320: .key_str = "F2",
321: .func = "Sym Info",
322: .key = F_SYMBOL,
323: .handler = handle_f2,
324: },
325: {
326: .key_str = "F3",
327: .func = "Insts",
328: .key = F_INSTS,
329: .handler = handle_f3,
330: },
331: {
332: .key_str = "F4",
333: .func = "Config",
334: .key = F_CONF,
335: .handler = handle_f4,
336: },
337: {
338: .key_str = "F5",
339: .func = "Back",
340: .key = F_BACK,
341: .handler = handle_f5,
342: },
343: {
344: .key_str = "F6",
345: .func = "Save",
346: .key = F_SAVE,
347: .handler = handle_f6,
348: },
349: {
350: .key_str = "F7",
351: .func = "Load",
352: .key = F_LOAD,
353: .handler = handle_f7,
354: },
355: {
356: .key_str = "F8",
357: .func = "Sym Search",
358: .key = F_SEARCH,
359: .handler = handle_f8,
360: },
361: {
362: .key_str = "F9",
363: .func = "Exit",
364: .key = F_EXIT,
365: .handler = handle_f9,
366: },
367: };
368:
369: static void print_function_line(void)
370: {
371: int i;
372: int offset = 1;
373: const int skip = 1;
374:
375: for (i = 0; i < function_keys_num; i++) {
376: wattrset(main_window, attributes[FUNCTION_HIGHLIGHT]);
377: mvwprintw(main_window, LINES-3, offset,
378: "%s",
379: function_keys[i].key_str);
380: wattrset(main_window, attributes[FUNCTION_TEXT]);
381: offset += strlen(function_keys[i].key_str);
382: mvwprintw(main_window, LINES-3,
383: offset, "%s",
384: function_keys[i].func);
385: offset += strlen(function_keys[i].func) + skip;
386: }
387: wattrset(main_window, attributes[NORMAL]);
388: }
389:
390: /* help */
391: static void handle_f1(int *key, struct menu *current_item)
392: {
393: show_scroll_win(main_window,
394: _("README"), _(nconf_readme));
395: return;
396: }
397:
398: /* symbole help */
399: static void handle_f2(int *key, struct menu *current_item)
400: {
401: show_help(current_item);
402: return;
403: }
404:
405: /* instructions */
406: static void handle_f3(int *key, struct menu *current_item)
407: {
408: show_scroll_win(main_window,
409: _("Instructions"),
410: _(current_instructions));
411: return;
412: }
413:
414: /* config */
415: static void handle_f4(int *key, struct menu *current_item)
416: {
417: int res = btn_dialog(main_window,
418: _("Show all symbols?"),
419: 2,
420: " <Show All> ",
421: "<Don't show all>");
422: if (res == 0)
423: show_all_items = 1;
424: else if (res == 1)
425: show_all_items = 0;
426:
427: return;
428: }
429:
430: /* back */
431: static void handle_f5(int *key, struct menu *current_item)
432: {
433: *key = KEY_LEFT;
434: return;
435: }
436:
437: /* save */
438: static void handle_f6(int *key, struct menu *current_item)
439: {
440: conf_save();
441: return;
442: }
443:
444: /* load */
445: static void handle_f7(int *key, struct menu *current_item)
446: {
447: conf_load();
448: return;
449: }
450:
451: /* search */
452: static void handle_f8(int *key, struct menu *current_item)
453: {
454: search_conf();
455: return;
456: }
457:
458: /* exit */
459: static void handle_f9(int *key, struct menu *current_item)
460: {
461: do_exit();
462: return;
463: }
464:
465: /* return != 0 to indicate the key was handles */
466: static int process_special_keys(int *key, struct menu *menu)
467: {
468: int i;
469:
470: if (*key == KEY_RESIZE) {
471: setup_windows();
472: return 1;
473: }
474:
475: for (i = 0; i < function_keys_num; i++) {
476: if (*key == KEY_F(function_keys[i].key) ||
477: *key == '0' + function_keys[i].key){
478: function_keys[i].handler(key, menu);
479: return 1;
480: }
481: }
482:
483: return 0;
484: }
485:
486: static void clean_items(void)
487: {
488: int i;
489: for (i = 0; curses_menu_items[i]; i++)
490: free_item(curses_menu_items[i]);
491: bzero(curses_menu_items, sizeof(curses_menu_items));
492: bzero(k_menu_items, sizeof(k_menu_items));
493: items_num = 0;
494: }
495:
496: typedef enum {MATCH_TINKER_PATTERN_UP, MATCH_TINKER_PATTERN_DOWN,
497: FIND_NEXT_MATCH_DOWN, FIND_NEXT_MATCH_UP} match_f;
498:
499: /* return the index of the matched item, or -1 if no such item exists */
500: static int get_mext_match(const char *match_str, match_f flag)
501: {
502: int match_start = item_index(current_item(curses_menu));
503: int index;
504:
505: if (flag == FIND_NEXT_MATCH_DOWN)
506: ++match_start;
507: else if (flag == FIND_NEXT_MATCH_UP)
508: --match_start;
509:
510: index = match_start;
511: index = (index + items_num) % items_num;
512: while (true) {
513: char *str = k_menu_items[index].str;
514: if (strcasestr(str, match_str) != 0)
515: return index;
516: if (flag == FIND_NEXT_MATCH_UP ||
517: flag == MATCH_TINKER_PATTERN_UP)
518: --index;
519: else
520: ++index;
521: index = (index + items_num) % items_num;
522: if (index == match_start)
523: return -1;
524: }
525: }
526:
527: /* Make a new item. */
528: static void item_make(struct menu *menu, char tag, const char *fmt, ...)
529: {
530: va_list ap;
531:
532: if (items_num > MAX_MENU_ITEMS-1)
533: return;
534:
535: bzero(&k_menu_items[items_num], sizeof(k_menu_items[0]));
536: k_menu_items[items_num].tag = tag;
537: k_menu_items[items_num].usrptr = menu;
538: if (menu != NULL)
539: k_menu_items[items_num].is_visible =
540: menu_is_visible(menu);
541: else
542: k_menu_items[items_num].is_visible = 1;
543:
544: va_start(ap, fmt);
545: vsnprintf(k_menu_items[items_num].str,
546: sizeof(k_menu_items[items_num].str),
547: fmt, ap);
548: va_end(ap);
549:
550: if (!k_menu_items[items_num].is_visible)
551: memcpy(k_menu_items[items_num].str, "XXX", 3);
552:
553: curses_menu_items[items_num] = new_item(
554: k_menu_items[items_num].str,
555: k_menu_items[items_num].str);
556: set_item_userptr(curses_menu_items[items_num],
557: &k_menu_items[items_num]);
558: /*
559: if (!k_menu_items[items_num].is_visible)
560: item_opts_off(curses_menu_items[items_num], O_SELECTABLE);
561: */
562:
563: items_num++;
564: curses_menu_items[items_num] = NULL;
565: }
566:
567: /* very hackish. adds a string to the last item added */
568: static void item_add_str(const char *fmt, ...)
569: {
570: va_list ap;
571: int index = items_num-1;
572: char new_str[256];
573: char tmp_str[256];
574:
575: if (index < 0)
576: return;
577:
578: va_start(ap, fmt);
579: vsnprintf(new_str, sizeof(new_str), fmt, ap);
580: va_end(ap);
581: snprintf(tmp_str, sizeof(tmp_str), "%s%s",
582: k_menu_items[index].str, new_str);
583: strncpy(k_menu_items[index].str,
584: tmp_str,
585: sizeof(k_menu_items[index].str));
586:
587: free_item(curses_menu_items[index]);
588: curses_menu_items[index] = new_item(
589: k_menu_items[index].str,
590: k_menu_items[index].str);
591: set_item_userptr(curses_menu_items[index],
592: &k_menu_items[index]);
593: }
594:
595: /* get the tag of the currently selected item */
596: static char item_tag(void)
597: {
598: ITEM *cur;
599: struct mitem *mcur;
600:
601: cur = current_item(curses_menu);
602: if (cur == NULL)
603: return 0;
604: mcur = (struct mitem *) item_userptr(cur);
605: return mcur->tag;
606: }
607:
608: static int curses_item_index(void)
609: {
610: return item_index(current_item(curses_menu));
611: }
612:
613: static void *item_data(void)
614: {
615: ITEM *cur;
616: struct mitem *mcur;
617:
618: cur = current_item(curses_menu);
619: if (!cur)
620: return NULL;
621: mcur = (struct mitem *) item_userptr(cur);
622: return mcur->usrptr;
623:
624: }
625:
626: static int item_is_tag(char tag)
627: {
628: return item_tag() == tag;
629: }
630:
631: static char filename[PATH_MAX+1];
632: static char menu_backtitle[PATH_MAX+128];
633: static const char *set_config_filename(const char *config_filename)
634: {
635: int size;
636:
637: size = snprintf(menu_backtitle, sizeof(menu_backtitle),
638: "%s - %s", config_filename, rootmenu.prompt->text);
639: if (size >= sizeof(menu_backtitle))
640: menu_backtitle[sizeof(menu_backtitle)-1] = '\0';
641:
642: size = snprintf(filename, sizeof(filename), "%s", config_filename);
643: if (size >= sizeof(filename))
644: filename[sizeof(filename)-1] = '\0';
645: return menu_backtitle;
646: }
647:
648: /* return = 0 means we are successful.
649: * -1 means go on doing what you were doing
650: */
651: static int do_exit(void)
652: {
653: int res;
654: if (!conf_get_changed()) {
655: global_exit = 1;
656: return 0;
657: }
658: res = btn_dialog(main_window,
659: _("Do you wish to save your new configuration?\n"
660: "<ESC> to cancel and resume nconfig."),
661: 2,
662: " <save> ",
663: "<don't save>");
664: if (res == KEY_EXIT) {
665: global_exit = 0;
666: return -1;
667: }
668:
669: /* if we got here, the user really wants to exit */
670: switch (res) {
671: case 0:
672: res = conf_write(filename);
673: if (res)
674: btn_dialog(
675: main_window,
676: _("Error during writing of configuration.\n"
677: "Your configuration changes were NOT saved."),
678: 1,
679: "<OK>");
680: break;
681: default:
682: btn_dialog(
683: main_window,
684: _("Your configuration changes were NOT saved."),
685: 1,
686: "<OK>");
687: break;
688: }
689: global_exit = 1;
690: return 0;
691: }
692:
693:
694: static void search_conf(void)
695: {
696: struct symbol **sym_arr;
697: struct gstr res;
698: char dialog_input_result[100];
699: char *dialog_input;
700: int dres;
701: again:
702: dres = dialog_inputbox(main_window,
703: _("Search Configuration Parameter"),
704: _("Enter " CONFIG_ " (sub)string to search for "
705: "(with or without \"" CONFIG_ "\")"),
706: "", dialog_input_result, 99);
707: switch (dres) {
708: case 0:
709: break;
710: case 1:
711: show_scroll_win(main_window,
712: _("Search Configuration"), search_help);
713: goto again;
714: default:
715: return;
716: }
717:
718: /* strip the prefix if necessary */
719: dialog_input = dialog_input_result;
720: if (strncasecmp(dialog_input_result, CONFIG_, strlen(CONFIG_)) == 0)
721: dialog_input += strlen(CONFIG_);
722:
723: sym_arr = sym_re_search(dialog_input);
724: res = get_relations_str(sym_arr);
725: free(sym_arr);
726: show_scroll_win(main_window,
727: _("Search Results"), str_get(&res));
728: str_free(&res);
729: }
730:
731:
732: static void build_conf(struct menu *menu)
733: {
734: struct symbol *sym;
735: struct property *prop;
736: struct menu *child;
737: int type, tmp, doint = 2;
738: tristate val;
739: char ch;
740:
741: if (!menu || (!show_all_items && !menu_is_visible(menu)))
742: return;
743:
744: sym = menu->sym;
745: prop = menu->prompt;
746: if (!sym) {
747: if (prop && menu != current_menu) {
748: const char *prompt = menu_get_prompt(menu);
749: enum prop_type ptype;
750: ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN;
751: switch (ptype) {
752: case P_MENU:
753: child_count++;
754: prompt = _(prompt);
755: if (single_menu_mode) {
756: item_make(menu, 'm',
757: "%s%*c%s",
758: menu->data ? "-->" : "++>",
759: indent + 1, ' ', prompt);
760: } else
761: item_make(menu, 'm',
762: " %*c%s --->",
763: indent + 1,
764: ' ', prompt);
765:
766: if (single_menu_mode && menu->data)
767: goto conf_childs;
768: return;
769: case P_COMMENT:
770: if (prompt) {
771: child_count++;
772: item_make(menu, ':',
773: " %*c*** %s ***",
774: indent + 1, ' ',
775: _(prompt));
776: }
777: break;
778: default:
779: if (prompt) {
780: child_count++;
781: item_make(menu, ':', "---%*c%s",
782: indent + 1, ' ',
783: _(prompt));
784: }
785: }
786: } else
787: doint = 0;
788: goto conf_childs;
789: }
790:
791: type = sym_get_type(sym);
792: if (sym_is_choice(sym)) {
793: struct symbol *def_sym = sym_get_choice_value(sym);
794: struct menu *def_menu = NULL;
795:
796: child_count++;
797: for (child = menu->list; child; child = child->next) {
798: if (menu_is_visible(child) && child->sym == def_sym)
799: def_menu = child;
800: }
801:
802: val = sym_get_tristate_value(sym);
803: if (sym_is_changable(sym)) {
804: switch (type) {
805: case S_BOOLEAN:
806: item_make(menu, 't', "[%c]",
807: val == no ? ' ' : '*');
808: break;
809: case S_TRISTATE:
810: switch (val) {
811: case yes:
812: ch = '*';
813: break;
814: case mod:
815: ch = 'M';
816: break;
817: default:
818: ch = ' ';
819: break;
820: }
821: item_make(menu, 't', "<%c>", ch);
822: break;
823: }
824: } else {
825: item_make(menu, def_menu ? 't' : ':', " ");
826: }
827:
828: item_add_str("%*c%s", indent + 1,
829: ' ', _(menu_get_prompt(menu)));
830: if (val == yes) {
831: if (def_menu) {
832: item_add_str(" (%s)",
833: _(menu_get_prompt(def_menu)));
834: item_add_str(" --->");
835: if (def_menu->list) {
836: indent += 2;
837: build_conf(def_menu);
838: indent -= 2;
839: }
840: }
841: return;
842: }
843: } else {
844: if (menu == current_menu) {
845: item_make(menu, ':',
846: "---%*c%s", indent + 1,
847: ' ', _(menu_get_prompt(menu)));
848: goto conf_childs;
849: }
850: child_count++;
851: val = sym_get_tristate_value(sym);
852: if (sym_is_choice_value(sym) && val == yes) {
853: item_make(menu, ':', " ");
854: } else {
855: switch (type) {
856: case S_BOOLEAN:
857: if (sym_is_changable(sym))
858: item_make(menu, 't', "[%c]",
859: val == no ? ' ' : '*');
860: else
861: item_make(menu, 't', "-%c-",
862: val == no ? ' ' : '*');
863: break;
864: case S_TRISTATE:
865: switch (val) {
866: case yes:
867: ch = '*';
868: break;
869: case mod:
870: ch = 'M';
871: break;
872: default:
873: ch = ' ';
874: break;
875: }
876: if (sym_is_changable(sym)) {
877: if (sym->rev_dep.tri == mod)
878: item_make(menu,
879: 't', "{%c}", ch);
880: else
881: item_make(menu,
882: 't', "<%c>", ch);
883: } else
884: item_make(menu, 't', "-%c-", ch);
885: break;
886: default:
887: tmp = 2 + strlen(sym_get_string_value(sym));
888: item_make(menu, 's', " (%s)",
889: sym_get_string_value(sym));
890: tmp = indent - tmp + 4;
891: if (tmp < 0)
892: tmp = 0;
893: item_add_str("%*c%s%s", tmp, ' ',
894: _(menu_get_prompt(menu)),
895: (sym_has_value(sym) ||
896: !sym_is_changable(sym)) ? "" :
897: _(" (NEW)"));
898: goto conf_childs;
899: }
900: }
901: item_add_str("%*c%s%s", indent + 1, ' ',
902: _(menu_get_prompt(menu)),
903: (sym_has_value(sym) || !sym_is_changable(sym)) ?
904: "" : _(" (NEW)"));
905: if (menu->prompt && menu->prompt->type == P_MENU) {
906: item_add_str(" --->");
907: return;
908: }
909: }
910:
911: conf_childs:
912: indent += doint;
913: for (child = menu->list; child; child = child->next)
914: build_conf(child);
915: indent -= doint;
916: }
917:
918: static void reset_menu(void)
919: {
920: unpost_menu(curses_menu);
921: clean_items();
922: }
923:
924: /* adjust the menu to show this item.
925: * prefer not to scroll the menu if possible*/
926: static void center_item(int selected_index, int *last_top_row)
927: {
928: int toprow;
929:
930: set_top_row(curses_menu, *last_top_row);
931: toprow = top_row(curses_menu);
932: if (selected_index < toprow ||
933: selected_index >= toprow+mwin_max_lines) {
934: toprow = max(selected_index-mwin_max_lines/2, 0);
935: if (toprow >= item_count(curses_menu)-mwin_max_lines)
936: toprow = item_count(curses_menu)-mwin_max_lines;
937: set_top_row(curses_menu, toprow);
938: }
939: set_current_item(curses_menu,
940: curses_menu_items[selected_index]);
941: *last_top_row = toprow;
942: post_menu(curses_menu);
943: refresh_all_windows(main_window);
944: }
945:
946: /* this function assumes reset_menu has been called before */
947: static void show_menu(const char *prompt, const char *instructions,
948: int selected_index, int *last_top_row)
949: {
950: int maxx, maxy;
951: WINDOW *menu_window;
952:
953: current_instructions = instructions;
954:
955: clear();
956: wattrset(main_window, attributes[NORMAL]);
957: print_in_middle(stdscr, 1, 0, COLS,
958: menu_backtitle,
959: attributes[MAIN_HEADING]);
960:
961: wattrset(main_window, attributes[MAIN_MENU_BOX]);
962: box(main_window, 0, 0);
963: wattrset(main_window, attributes[MAIN_MENU_HEADING]);
964: mvwprintw(main_window, 0, 3, " %s ", prompt);
965: wattrset(main_window, attributes[NORMAL]);
966:
967: set_menu_items(curses_menu, curses_menu_items);
968:
969: /* position the menu at the middle of the screen */
970: scale_menu(curses_menu, &maxy, &maxx);
971: maxx = min(maxx, mwin_max_cols-2);
972: maxy = mwin_max_lines;
973: menu_window = derwin(main_window,
974: maxy,
975: maxx,
976: 2,
977: (mwin_max_cols-maxx)/2);
978: keypad(menu_window, TRUE);
979: set_menu_win(curses_menu, menu_window);
980: set_menu_sub(curses_menu, menu_window);
981:
982: /* must reassert this after changing items, otherwise returns to a
983: * default of 16
984: */
985: set_menu_format(curses_menu, maxy, 1);
986: center_item(selected_index, last_top_row);
987: set_menu_format(curses_menu, maxy, 1);
988:
989: print_function_line();
990:
991: /* Post the menu */
992: post_menu(curses_menu);
993: refresh_all_windows(main_window);
994: }
995:
996: static void adj_match_dir(match_f *match_direction)
997: {
998: if (*match_direction == FIND_NEXT_MATCH_DOWN)
999: *match_direction =
1000: MATCH_TINKER_PATTERN_DOWN;
1001: else if (*match_direction == FIND_NEXT_MATCH_UP)
1002: *match_direction =
1003: MATCH_TINKER_PATTERN_UP;
1004: /* else, do no change.. */
1005: }
1006:
1007: struct match_state
1008: {
1009: int in_search;
1010: match_f match_direction;
1011: char pattern[256];
1012: };
1013:
1014: /* Return 0 means I have handled the key. In such a case, ans should hold the
1015: * item to center, or -1 otherwise.
1016: * Else return -1 .
1017: */
1018: static int do_match(int key, struct match_state *state, int *ans)
1019: {
1020: char c = (char) key;
1021: int terminate_search = 0;
1022: *ans = -1;
1023: if (key == '/' || (state->in_search && key == 27)) {
1024: move(0, 0);
1025: refresh();
1026: clrtoeol();
1027: state->in_search = 1-state->in_search;
1028: bzero(state->pattern, sizeof(state->pattern));
1029: state->match_direction = MATCH_TINKER_PATTERN_DOWN;
1030: return 0;
1031: } else if (!state->in_search)
1032: return 1;
1033:
1034: if (isalnum(c) || isgraph(c) || c == ' ') {
1035: state->pattern[strlen(state->pattern)] = c;
1036: state->pattern[strlen(state->pattern)] = '\0';
1037: adj_match_dir(&state->match_direction);
1038: *ans = get_mext_match(state->pattern,
1039: state->match_direction);
1040: } else if (key == KEY_DOWN) {
1041: state->match_direction = FIND_NEXT_MATCH_DOWN;
1042: *ans = get_mext_match(state->pattern,
1043: state->match_direction);
1044: } else if (key == KEY_UP) {
1045: state->match_direction = FIND_NEXT_MATCH_UP;
1046: *ans = get_mext_match(state->pattern,
1047: state->match_direction);
1048: } else if (key == KEY_BACKSPACE || key == 127) {
1049: state->pattern[strlen(state->pattern)-1] = '\0';
1050: adj_match_dir(&state->match_direction);
1051: } else
1052: terminate_search = 1;
1053:
1054: if (terminate_search) {
1055: state->in_search = 0;
1056: bzero(state->pattern, sizeof(state->pattern));
1057: move(0, 0);
1058: refresh();
1059: clrtoeol();
1060: return -1;
1061: }
1062: return 0;
1063: }
1064:
1065: static void conf(struct menu *menu)
1066: {
1067: struct menu *submenu = 0;
1068: const char *prompt = menu_get_prompt(menu);
1069: struct symbol *sym;
1070: struct menu *active_menu = NULL;
1071: int res;
1072: int current_index = 0;
1073: int last_top_row = 0;
1074: struct match_state match_state = {
1075: .in_search = 0,
1076: .match_direction = MATCH_TINKER_PATTERN_DOWN,
1077: .pattern = "",
1078: };
1079:
1080: while (!global_exit) {
1081: reset_menu();
1082: current_menu = menu;
1083: build_conf(menu);
1084: if (!child_count)
1085: break;
1086:
1087: show_menu(prompt ? _(prompt) : _("Main Menu"),
1088: _(menu_instructions),
1089: current_index, &last_top_row);
1090: keypad((menu_win(curses_menu)), TRUE);
1091: while (!global_exit) {
1092: if (match_state.in_search) {
1093: mvprintw(0, 0,
1094: "searching: %s", match_state.pattern);
1095: clrtoeol();
1096: }
1097: refresh_all_windows(main_window);
1098: res = wgetch(menu_win(curses_menu));
1099: if (!res)
1100: break;
1101: if (do_match(res, &match_state, ¤t_index) == 0) {
1102: if (current_index != -1)
1103: center_item(current_index,
1104: &last_top_row);
1105: continue;
1106: }
1107: if (process_special_keys(&res,
1108: (struct menu *) item_data()))
1109: break;
1110: switch (res) {
1111: case KEY_DOWN:
1112: menu_driver(curses_menu, REQ_DOWN_ITEM);
1113: break;
1114: case KEY_UP:
1115: menu_driver(curses_menu, REQ_UP_ITEM);
1116: break;
1117: case KEY_NPAGE:
1118: menu_driver(curses_menu, REQ_SCR_DPAGE);
1119: break;
1120: case KEY_PPAGE:
1121: menu_driver(curses_menu, REQ_SCR_UPAGE);
1122: break;
1123: case KEY_HOME:
1124: menu_driver(curses_menu, REQ_FIRST_ITEM);
1125: break;
1126: case KEY_END:
1127: menu_driver(curses_menu, REQ_LAST_ITEM);
1128: break;
1129: case 'h':
1130: case '?':
1131: show_help((struct menu *) item_data());
1132: break;
1133: }
1134: if (res == 10 || res == 27 ||
1135: res == 32 || res == 'n' || res == 'y' ||
1136: res == KEY_LEFT || res == KEY_RIGHT ||
1137: res == 'm')
1138: break;
1139: refresh_all_windows(main_window);
1140: }
1141:
1142: refresh_all_windows(main_window);
1143: /* if ESC or left*/
1144: if (res == 27 || (menu != &rootmenu && res == KEY_LEFT))
1145: break;
1146:
1147: /* remember location in the menu */
1148: last_top_row = top_row(curses_menu);
1149: current_index = curses_item_index();
1150:
1151: if (!item_tag())
1152: continue;
1153:
1154: submenu = (struct menu *) item_data();
1155: active_menu = (struct menu *)item_data();
1156: if (!submenu || !menu_is_visible(submenu))
1157: continue;
1158: if (submenu)
1159: sym = submenu->sym;
1160: else
1161: sym = NULL;
1162:
1163: switch (res) {
1164: case ' ':
1165: if (item_is_tag('t'))
1166: sym_toggle_tristate_value(sym);
1167: else if (item_is_tag('m'))
1168: conf(submenu);
1169: break;
1170: case KEY_RIGHT:
1171: case 10: /* ENTER WAS PRESSED */
1172: switch (item_tag()) {
1173: case 'm':
1174: if (single_menu_mode)
1175: submenu->data =
1176: (void *) (long) !submenu->data;
1177: else
1178: conf(submenu);
1179: break;
1180: case 't':
1181: if (sym_is_choice(sym) &&
1182: sym_get_tristate_value(sym) == yes)
1183: conf_choice(submenu);
1184: else if (submenu->prompt &&
1185: submenu->prompt->type == P_MENU)
1186: conf(submenu);
1187: else if (res == 10)
1188: sym_toggle_tristate_value(sym);
1189: break;
1190: case 's':
1191: conf_string(submenu);
1192: break;
1193: }
1194: break;
1195: case 'y':
1196: if (item_is_tag('t')) {
1197: if (sym_set_tristate_value(sym, yes))
1198: break;
1199: if (sym_set_tristate_value(sym, mod))
1200: btn_dialog(main_window, setmod_text, 0);
1201: }
1202: break;
1203: case 'n':
1204: if (item_is_tag('t'))
1205: sym_set_tristate_value(sym, no);
1206: break;
1207: case 'm':
1208: if (item_is_tag('t'))
1209: sym_set_tristate_value(sym, mod);
1210: break;
1211: }
1212: }
1213: }
1214:
1215: static void conf_message_callback(const char *fmt, va_list ap)
1216: {
1217: char buf[1024];
1218:
1219: vsnprintf(buf, sizeof(buf), fmt, ap);
1220: btn_dialog(main_window, buf, 1, "<OK>");
1221: }
1222:
1223: static void show_help(struct menu *menu)
1224: {
1225: struct gstr help = str_new();
1226:
1227: if (menu && menu->sym && menu_has_help(menu)) {
1228: if (menu->sym->name) {
1229: str_printf(&help, "%s%s:\n\n", CONFIG_, menu->sym->name);
1230: str_append(&help, _(menu_get_help(menu)));
1231: str_append(&help, "\n");
1232: get_symbol_str(&help, menu->sym);
1233: } else {
1234: str_append(&help, _(menu_get_help(menu)));
1235: }
1236: } else {
1237: str_append(&help, nohelp_text);
1238: }
1239: show_scroll_win(main_window, _(menu_get_prompt(menu)), str_get(&help));
1240: str_free(&help);
1241: }
1242:
1243: static void conf_choice(struct menu *menu)
1244: {
1245: const char *prompt = _(menu_get_prompt(menu));
1246: struct menu *child = 0;
1247: struct symbol *active;
1248: int selected_index = 0;
1249: int last_top_row = 0;
1250: int res, i = 0;
1251: struct match_state match_state = {
1252: .in_search = 0,
1253: .match_direction = MATCH_TINKER_PATTERN_DOWN,
1254: .pattern = "",
1255: };
1256:
1257: active = sym_get_choice_value(menu->sym);
1258: /* this is mostly duplicated from the conf() function. */
1259: while (!global_exit) {
1260: reset_menu();
1261:
1262: for (i = 0, child = menu->list; child; child = child->next) {
1263: if (!show_all_items && !menu_is_visible(child))
1264: continue;
1265:
1266: if (child->sym == sym_get_choice_value(menu->sym))
1267: item_make(child, ':', "<X> %s",
1268: _(menu_get_prompt(child)));
1269: else if (child->sym)
1270: item_make(child, ':', " %s",
1271: _(menu_get_prompt(child)));
1272: else
1273: item_make(child, ':', "*** %s ***",
1274: _(menu_get_prompt(child)));
1275:
1276: if (child->sym == active){
1277: last_top_row = top_row(curses_menu);
1278: selected_index = i;
1279: }
1280: i++;
1281: }
1282: show_menu(prompt ? _(prompt) : _("Choice Menu"),
1283: _(radiolist_instructions),
1284: selected_index,
1285: &last_top_row);
1286: while (!global_exit) {
1287: if (match_state.in_search) {
1288: mvprintw(0, 0, "searching: %s",
1289: match_state.pattern);
1290: clrtoeol();
1291: }
1292: refresh_all_windows(main_window);
1293: res = wgetch(menu_win(curses_menu));
1294: if (!res)
1295: break;
1296: if (do_match(res, &match_state, &selected_index) == 0) {
1297: if (selected_index != -1)
1298: center_item(selected_index,
1299: &last_top_row);
1300: continue;
1301: }
1302: if (process_special_keys(
1303: &res,
1304: (struct menu *) item_data()))
1305: break;
1306: switch (res) {
1307: case KEY_DOWN:
1308: menu_driver(curses_menu, REQ_DOWN_ITEM);
1309: break;
1310: case KEY_UP:
1311: menu_driver(curses_menu, REQ_UP_ITEM);
1312: break;
1313: case KEY_NPAGE:
1314: menu_driver(curses_menu, REQ_SCR_DPAGE);
1315: break;
1316: case KEY_PPAGE:
1317: menu_driver(curses_menu, REQ_SCR_UPAGE);
1318: break;
1319: case KEY_HOME:
1320: menu_driver(curses_menu, REQ_FIRST_ITEM);
1321: break;
1322: case KEY_END:
1323: menu_driver(curses_menu, REQ_LAST_ITEM);
1324: break;
1325: case 'h':
1326: case '?':
1327: show_help((struct menu *) item_data());
1328: break;
1329: }
1330: if (res == 10 || res == 27 || res == ' ' ||
1331: res == KEY_LEFT){
1332: break;
1333: }
1334: refresh_all_windows(main_window);
1335: }
1336: /* if ESC or left */
1337: if (res == 27 || res == KEY_LEFT)
1338: break;
1339:
1340: child = item_data();
1341: if (!child || !menu_is_visible(child) || !child->sym)
1342: continue;
1343: switch (res) {
1344: case ' ':
1345: case 10:
1346: case KEY_RIGHT:
1347: sym_set_tristate_value(child->sym, yes);
1348: return;
1349: case 'h':
1350: case '?':
1351: show_help(child);
1352: active = child->sym;
1353: break;
1354: case KEY_EXIT:
1355: return;
1356: }
1357: }
1358: }
1359:
1360: static void conf_string(struct menu *menu)
1361: {
1362: const char *prompt = menu_get_prompt(menu);
1363: char dialog_input_result[256];
1364:
1365: while (1) {
1366: int res;
1367: const char *heading;
1368:
1369: switch (sym_get_type(menu->sym)) {
1370: case S_INT:
1371: heading = _(inputbox_instructions_int);
1372: break;
1373: case S_HEX:
1374: heading = _(inputbox_instructions_hex);
1375: break;
1376: case S_STRING:
1377: heading = _(inputbox_instructions_string);
1378: break;
1379: default:
1380: heading = _("Internal nconf error!");
1381: }
1382: res = dialog_inputbox(main_window,
1383: prompt ? _(prompt) : _("Main Menu"),
1384: heading,
1385: sym_get_string_value(menu->sym),
1386: dialog_input_result,
1387: sizeof(dialog_input_result));
1388: switch (res) {
1389: case 0:
1390: if (sym_set_string_value(menu->sym,
1391: dialog_input_result))
1392: return;
1393: btn_dialog(main_window,
1394: _("You have made an invalid entry."), 0);
1395: break;
1396: case 1:
1397: show_help(menu);
1398: break;
1399: case KEY_EXIT:
1400: return;
1401: }
1402: }
1403: }
1404:
1405: static void conf_load(void)
1406: {
1407: char dialog_input_result[256];
1408: while (1) {
1409: int res;
1410: res = dialog_inputbox(main_window,
1411: NULL, load_config_text,
1412: filename,
1413: dialog_input_result,
1414: sizeof(dialog_input_result));
1415: switch (res) {
1416: case 0:
1417: if (!dialog_input_result[0])
1418: return;
1419: if (!conf_read(dialog_input_result)) {
1420: set_config_filename(dialog_input_result);
1421: sym_set_change_count(1);
1422: return;
1423: }
1424: btn_dialog(main_window, _("File does not exist!"), 0);
1425: break;
1426: case 1:
1427: show_scroll_win(main_window,
1428: _("Load Alternate Configuration"),
1429: load_config_help);
1430: break;
1431: case KEY_EXIT:
1432: return;
1433: }
1434: }
1435: }
1436:
1437: static void conf_save(void)
1438: {
1439: char dialog_input_result[256];
1440: while (1) {
1441: int res;
1442: res = dialog_inputbox(main_window,
1443: NULL, save_config_text,
1444: filename,
1445: dialog_input_result,
1446: sizeof(dialog_input_result));
1447: switch (res) {
1448: case 0:
1449: if (!dialog_input_result[0])
1450: return;
1451: res = conf_write(dialog_input_result);
1452: if (!res) {
1453: set_config_filename(dialog_input_result);
1454: return;
1455: }
1456: btn_dialog(main_window, _("Can't create file! "
1457: "Probably a nonexistent directory."),
1458: 1, "<OK>");
1459: break;
1460: case 1:
1461: show_scroll_win(main_window,
1462: _("Save Alternate Configuration"),
1463: save_config_help);
1464: break;
1465: case KEY_EXIT:
1466: return;
1467: }
1468: }
1469: }
1470:
1471: void setup_windows(void)
1472: {
1473: if (main_window != NULL)
1474: delwin(main_window);
1475:
1476: /* set up the menu and menu window */
1477: main_window = newwin(LINES-2, COLS-2, 2, 1);
1478: keypad(main_window, TRUE);
1479: mwin_max_lines = LINES-7;
1480: mwin_max_cols = COLS-6;
1481:
1482: /* panels order is from bottom to top */
1483: new_panel(main_window);
1484: }
1485:
1486: int main(int ac, char **av)
1487: {
1488: char *mode;
1489:
1490: setlocale(LC_ALL, "");
1491: bindtextdomain(PACKAGE, LOCALEDIR);
1492: textdomain(PACKAGE);
1493:
1494: conf_parse(av[1]);
1495: conf_read(NULL);
1496:
1497: mode = getenv("NCONFIG_MODE");
1498: if (mode) {
1499: if (!strcasecmp(mode, "single_menu"))
1500: single_menu_mode = 1;
1501: }
1502:
1503: /* Initialize curses */
1504: initscr();
1505: /* set color theme */
1506: set_colors();
1507:
1508: cbreak();
1509: noecho();
1510: keypad(stdscr, TRUE);
1511: curs_set(0);
1512:
1513: if (COLS < 75 || LINES < 20) {
1514: endwin();
1515: printf("Your terminal should have at "
1516: "least 20 lines and 75 columns\n");
1517: return 1;
1518: }
1519:
1520: notimeout(stdscr, FALSE);
1521: ESCDELAY = 1;
1522:
1523: /* set btns menu */
1524: curses_menu = new_menu(curses_menu_items);
1525: menu_opts_off(curses_menu, O_SHOWDESC);
1526: menu_opts_on(curses_menu, O_SHOWMATCH);
1527: menu_opts_on(curses_menu, O_ONEVALUE);
1528: menu_opts_on(curses_menu, O_NONCYCLIC);
1529: menu_opts_on(curses_menu, O_IGNORECASE);
1530: set_menu_mark(curses_menu, " ");
1531: set_menu_fore(curses_menu, attributes[MAIN_MENU_FORE]);
1532: set_menu_back(curses_menu, attributes[MAIN_MENU_BACK]);
1533: set_menu_grey(curses_menu, attributes[MAIN_MENU_GREY]);
1534:
1535: set_config_filename(conf_get_configname());
1536: setup_windows();
1537:
1538: /* check for KEY_FUNC(1) */
1539: if (has_key(KEY_F(1)) == FALSE) {
1540: show_scroll_win(main_window,
1541: _("Instructions"),
1542: _(menu_no_f_instructions));
1543: }
1544:
1545: conf_set_message_callback(conf_message_callback);
1546: /* do the work */
1547: while (!global_exit) {
1548: conf(&rootmenu);
1549: if (!global_exit && do_exit() == 0)
1550: break;
1551: }
1552: /* ok, we are done */
1553: unpost_menu(curses_menu);
1554: free_menu(curses_menu);
1555: delwin(main_window);
1556: clear();
1557: refresh();
1558: endwin();
1559: return 0;
1560: }
1561:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.