kconfig/nconf.c
author "Benoît Thébaudeau" <benoit.thebaudeau@advansee.com>
Mon Apr 16 15:25:36 2012 +0200 (2012-04-16)
changeset 2941 13e40098fffc
permissions -rw-r--r--
cc/gcc: update Linaro GCC revisions to 2012.04

Update Linaro GCC with the latest available revisions.

The 4.7 revision is also released, but the infrastructure is not yet ready for
it in CT-NG.

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