kconfig/nconf.c
author danielrubiob@gmail.com
Tue Feb 11 21:34:48 2014 +0100 (2014-02-11)
changeset 3285 a8cb9039fade
permissions -rw-r--r--
complibs/cloog: bump version

Signed-off-by: Daniel Rubio Bonilla <danielrubiob@gmail.com>
[yann.morin.1998@free.fr: re-order versions]
Signed-off-by: "Yann E. MORIN" <yann.morin.1998@free.fr>
Cc: Cody P Schafer <dev@codyps.com>
Message-Id: <c2de3964cd6d5e4173cc.1391984023@uemo>
Patchwork-Id: 318637
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