about summary refs log blame commit diff stats
path: root/src/LYOptions.c
blob: d725f0d2cd082442974d8d005d350381e6e7db58 (plain) (tree)
1
3018
3019
3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034
3035
3036
3037
3038
3039
3040
3041
3042
3043
3044
3045
3046
3047
3048
3049
3050
3051
3052
3053
3054
3055
3056
3057
3058
3059
3060
3061
3062
3063
3064
3065
3066
3067
3068
3069
3070
3071
3072
3073
3074
3075
3076
3077
3078
3079
3080
3081
3082
3083
3084
3085
3086
3087
3088
3089
3090
3091
3092
3093
3094
3095
3096
3097
3098
3099
3100
3101
3102
3103
3104
3105
3106
3107
3108
3109
3110
3111
3112
3113
3114
3115
3116
3117
3118
3119
3120
3121
3122
3123
3124
3125
3126
3127
3128
3129
3130
3131
3132
3133
3134
3135
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
3161
3162
3163
3164
3165
3166
3167
3168
3169
3170
3171
3172
3173
3174
3175
3176
3177
3178
3179
3180
3181
3182
3183
3184
3185
3186
3187
3188
3189
3190
3191
3192
3193
3194
3195
3196
3197
3198
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285
3286
3287
3288
3289
3290
3291
3292
3293
3294
3295
3296
3297
3298
3299
3300
3301
3302
3303
3304
3305
3306
3307
3308
3309
3310
3311
3312
3313
3314
3315
3316
3317
3318
3319
3320
3321
3322
3323
3324
3325
3326
3327
3328
3329
3330
3331
3332
3333
3334
3335
3336
3337
3338
3339
3340
3341
3342
3343
3344
3345
3346
3347
3348
3349
3350
3351
3352
3353
3354
3355
3356
3357
3358
3359
3360
3361
3362
3363
3364
3365
3366
3367
3368
3369
3370
3371
3372
3373
3374
3375
3376
3377
3378
3379
3380
3381
3382
3383
3384
3385
3386
3387
3388
3389
3390
3391
3392
3393
3394
3395
3396
3397
3398
3399
3400
3401
3402
3403
3404
3405
3406
3407
3408
3409
3410
3411
3412
3413
3414
3415
3416
3417
3418
3419
3420
3421
3422
3423
3424
3425
3426
3427
3428
3429
3430
3431
3432
3433
3434
3435
3436
3437
3438
3439
3440
3441
3442
3443
3444
3445
3446
3447
3448
3449
3450
3451
3452
3453
3454
3455
3456
3457
3458
3459
3460
3461
3462
3463
3464
3465
3466
3467
3468
3469
3470
3471
3472
3473
3474
3475
3476
3477
3478
3479
3480
3481
3482
3483
3484
3485
3486
3487
3488
3489
3490
3491
3492
3493
3494
3495
3496
3497
3498
3499
3500
3501
3502
3503
3504
3505
3506
3507
3508
3509
3510
3511
                                                                

























                                                      



                      







































































































                                                                                      
                                              

                                                        
                                                                                   

                                                     
                                                                         













































































































































                                                                           
                                                 
































































                                                                                      
                            





                                                   




































































































































































































                                                                             
                                              



























































































                                                                                      


                                                    

                                                        
                                           



                                                    
                                                                




                                                    
                                               


                                     

                                                       













                                                         
                                              


                                                     
                                       



                                                 
                                                            










                                                 
                                                             













                                                                             
                                           














                                                                               
                                        
                                 

                                                     
                                              

























































                                                                           
                                                      


                                                    
                                           



                                          
                                                                

                                          
                                                                              
                                   
                                                    

                                                       
                                                                                   






                                                       
                                                              







































                                                                                    
                                                          


                                                          
                                       



                                                      
                                                            





                                                         
                                           


                                            

                                                                  






























































































































































































                                                                                                   
                                             


                                                      
                                       



                                                  
                                                            




                                                  
                                           


                                 

                                                     












                                                                
                                                 


                                                          
                                       



                                                      
                                                            




                                                      
                                           


                                   

                                                         


































































































































































































                                                                                 
                                                               


                                                                  
                                                               



                                                                  
                                                          








































































































                                                                       
                                                    


                                                      
                                           



                                                        
                                                                





                                                        
                                               




                                                                  

                                                            












































































































                                                                                      

                      

 
                                            



























                                                                       
                                             



































































































































































                                                                                     
                            





































































































































































































                                                                                 
                                      
                                                      
                                                           
                                                                      

                                     
                                            

                                                   
                                                                         

























                                                                  
                                                                  
                                                                  

                                 
                                        



                                                                          
                        
                                                                  
                                                                                






                                                                              












                                                              
                               




                                               
                      














                                                                                                                           
                                    










                                              
                                                        






































































































































                                                                                      

                                                       

                                     





                                                             















































































































































































                                                                      

                                                                          



































































































                                                                                                 

























                                                                  



                                                                          




















                                                                              
















                                                                       
      
 


























































































































































                                                                                  


                                                          











































































































































































                                                                                      
                                                











































































                                                                        





                                                                                 


                                                    


                                                                        
                                                                          



                                          
























                                                                              













































































































































































































































































































































































































































































































                                                                                       
                                                          







































































































































































































































                                                                                       
                                                                                 

                                                                        
                                            


                                   
                                                                          




































































































































                                                                                         



                                                              
                                                                   












                                                                        

















































































































































































































































































                                                                                          
 
                             
/* $LynxId: LYOptions.c,v 1.163 2013/10/24 00:08:39 tom Exp $ */
#include <HTUtils.h>
#include <HTFTP.h>
#include <HTTP.h>		/* 'reloading' flag */
#include <HTML.h>
#include <LYCurses.h>
#include <LYUtils.h>
#include <LYStrings.h>
#include <LYGlobalDefs.h>
#include <LYHistory.h>
#include <LYOptions.h>
#include <LYSignal.h>
#include <LYClean.h>
#include <LYCharSets.h>
#include <UCMap.h>
#include <UCAux.h>
#include <LYKeymap.h>
#include <LYrcFile.h>
#include <HTAlert.h>
#include <LYBookmark.h>
#include <GridText.h>
#include <LYGetFile.h>
#include <LYReadCFG.h>
#include <LYPrettySrc.h>
#include <HTFile.h>
#include <LYCharUtils.h>

#ifdef USE_COLOR_STYLE
#include <LYStyle.h>
#endif

#include <LYLeaks.h>

BOOLEAN term_options;

#define TOP_LINK  "/"
#define MBM_LINK  "//MBM_MENU"

#define MARGIN_STR (no_margins ? "" : "&nbsp;&nbsp;")
#define MARGIN_LEN (no_margins ?  0 : 2)

static void terminate_options(int sig);

#define COL_OPTION_VALUES 36	/* display column where option values start */

#if defined(USE_SLANG) || defined(COLOR_CURSES)
static BOOLEAN can_do_colors = FALSE;
#endif

static int LYChosenShowColor = SHOW_COLOR_UNKNOWN;	/* whether to show and save */

BOOLEAN LYCheckUserAgent(void)
{
    if (non_empty(LYUserAgent)) {
	if (strstr(LYUserAgent, "Lynx") == 0
	    && strstr(LYUserAgent, "lynx") == 0
	    && strstr(LYUserAgent, "L_y_n_x") == 0
	    && strstr(LYUserAgent, "l_y_n_x") == 0) {
	    return FALSE;
	}
    }
    return TRUE;
}

static void validate_x_display(void)
{
    char *cp;

    if ((cp = LYgetXDisplay()) != NULL) {
	StrAllocCopy(x_display, cp);
    } else {
	FREE(x_display);
    }
}

static void summarize_x_display(char *display_option)
{
    if ((x_display == NULL && *display_option == '\0') ||
	(x_display != NULL && !strcmp(x_display, display_option))) {
	if (x_display == NULL && LYisConfiguredForX == TRUE) {
	    _statusline(VALUE_ACCEPTED_WARNING_X);
	} else if (x_display != NULL && LYisConfiguredForX == FALSE) {
	    _statusline(VALUE_ACCEPTED_WARNING_NONX);
	} else {
	    _statusline(VALUE_ACCEPTED);
	}
    } else {
	if (*display_option) {
	    _statusline(FAILED_TO_SET_DISPLAY);
	} else {
	    _statusline(FAILED_CLEAR_SET_DISPLAY);
	}
    }
}

static void SetupChosenShowColor(void)
{
#if defined(USE_SLANG) || defined(COLOR_CURSES)
    can_do_colors = TRUE;
#if defined(COLOR_CURSES)
    if (LYCursesON)		/* could crash if called before initialization */
	can_do_colors = (has_colors()
			 ? TRUE
			 : FALSE);
#endif
    if (!no_option_save) {
	if (LYChosenShowColor == SHOW_COLOR_UNKNOWN) {
	    switch (LYrcShowColor) {
	    case SHOW_COLOR_NEVER:
		LYChosenShowColor =
		    (LYShowColor >= SHOW_COLOR_ON) ?
		    SHOW_COLOR_ON : SHOW_COLOR_NEVER;
		break;
	    case SHOW_COLOR_ALWAYS:
		if (!can_do_colors)
		    LYChosenShowColor = SHOW_COLOR_ALWAYS;
		else
		    LYChosenShowColor =
			(LYShowColor >= SHOW_COLOR_ON) ?
			SHOW_COLOR_ALWAYS : SHOW_COLOR_OFF;
		break;
	    default:
		LYChosenShowColor =
		    (LYShowColor >= SHOW_COLOR_ON) ?
		    SHOW_COLOR_ON : SHOW_COLOR_OFF;
	    }
	}
    }
#endif /* USE_SLANG || COLOR_CURSES */
}

#ifndef NO_OPTION_MENU
static int boolean_choice(int status,
			  int line,
			  int column,
			  STRING2PTR choices);

#define LYChooseBoolean(status, line, column, choices) \
	(BOOLEAN) boolean_choice(status, line, column, (const char *const*)choices)

#define LYChooseEnum(status, line, column, choices) \
	boolean_choice(status, line, column, (const char *const*)choices)

#define MAXCHOICES 10

/*
 * Values for the options menu.  - FM
 *
 * L_foo values are the Y coordinates for the menu item.
 * B_foo values are the X coordinates for the item's prompt string.
 * C_foo values are the X coordinates for the item's value string.
 */
#define L_EDITOR	 2
#define L_DISPLAY	 3

#define L_HOME		 4
#define C_MULTI		24
#define B_BOOK		34
#define C_DEFAULT	50

#define L_FTPSTYPE	 5
#define L_MAIL_ADDRESS	 6
#define L_SSEARCH	 7
#define L_LANGUAGE	 8
#define L_PREF_CHARSET	 9
#define L_ASSUME_CHARSET (L_PREF_CHARSET + 1)
#define L_CHARSET	10
#define L_RAWMODE	11

#define L_COLOR		L_RAWMODE
#define B_COLOR		44
#define C_COLOR		62

#define L_BOOL_A	12
#define B_VIKEYS	5
#define C_VIKEYS	15
#define B_EMACSKEYS	22
#define C_EMACSKEYS	36
#define B_SHOW_DOTFILES	44
#define C_SHOW_DOTFILES	62

#define L_BOOL_B	13
#define B_SELECT_POPUPS	5
#define C_SELECT_POPUPS	36
#define B_SHOW_CURSOR	44
#define C_SHOW_CURSOR	62

#define L_KEYPAD	14
#define L_LINEED	15
#define L_LAYOUT	16

#ifdef DIRED_SUPPORT
#define L_DIRED		17
#define L_USER_MODE	18
#define L_USER_AGENT	19
#define L_EXEC		20
#else
#define L_USER_MODE	17
#define L_USER_AGENT	18
#define L_EXEC		19
#endif /* DIRED_SUPPORT */

#define L_VERBOSE_IMAGES L_USER_MODE
#define B_VERBOSE_IMAGES 50
#define C_VERBOSE_IMAGES (B_VERBOSE_IMAGES + 21)

/* a kludge to add assume_charset only in ADVANCED mode... */
#define L_Bool_A     (use_assume_charset ? L_BOOL_A     + 1 : L_BOOL_A)
#define L_Bool_B     (use_assume_charset ? L_BOOL_B     + 1 : L_BOOL_B)
#define L_Exec       (use_assume_charset ? L_EXEC       + 1 : L_EXEC)
#define L_Rawmode    (use_assume_charset ? L_RAWMODE    + 1 : L_RAWMODE)
#define L_Charset    (use_assume_charset ? L_CHARSET    + 1 : L_CHARSET)
#define L_Color      (use_assume_charset ? L_COLOR      + 1 : L_COLOR)
#define L_Keypad     (use_assume_charset ? L_KEYPAD     + 1 : L_KEYPAD)
#define L_Lineed     (use_assume_charset ? L_LINEED     + 1 : L_LINEED)
#define L_Layout     (use_assume_charset ? L_LAYOUT     + 1 : L_LAYOUT)
#define L_Dired      (use_assume_charset ? L_DIRED      + 1 : L_DIRED)
#define L_User_Mode  (use_assume_charset ? L_USER_MODE  + 1 : L_USER_MODE)
#define L_User_Agent (use_assume_charset ? L_USER_AGENT + 1 : L_USER_AGENT)

#define LPAREN '('
#define RPAREN ')'

static int add_it(char *text, int len)
{
    if (len) {
	text[len] = '\0';
	LYaddstr(text);
    }
    return 0;
}

/*
 * addlbl() is used instead of plain LYaddstr() in old-style options menu
 * to show hot keys in bold.
 */
static void addlbl(const char *text)
{
    char actual[80];
    int s, d;
    BOOL b = FALSE;

    for (s = d = 0; text[s]; s++) {
	actual[d++] = text[s];
	if (text[s] == LPAREN) {
	    d = add_it(actual, d - 1);
	    lynx_start_bold();
	    b = TRUE;
	    actual[d++] = text[s];
	} else if (text[s] == RPAREN) {
	    d = add_it(actual, d);
	    lynx_stop_bold();
	    b = FALSE;
	}
    }
    add_it(actual, d);
    if (b)
	lynx_stop_bold();
}

#if !defined(VMS) || defined(USE_SLANG)
#define HANDLE_LYOPTIONS \
		    if (term_options) { \
			term_options = FALSE; \
		    } else { \
			AddValueAccepted = TRUE; \
		    } \
		    goto draw_options
#else
#define HANDLE_LYOPTIONS \
		    term_options = FALSE; \
		    if (use_assume_charset != old_use_assume_charset) \
			goto draw_options
#endif /* !VMS || USE_SLANG */

void LYoptions(void)
{
#define ShowBool(value) LYaddstr((value) ? "ON " : "OFF")
    static const char *bool_choices[] =
    {
	"OFF",
	"ON",
	NULL
    };
    static const char *const caseless_choices[] =
    {
	"CASE INSENSITIVE",
	"CASE SENSITIVE",
	NULL
    };

#ifdef DIRED_SUPPORT
    static const char *dirList_choices[] =
    {
	"Directories first",
	"Files first",
	"Mixed style",
	NULL
    };
#endif

#if defined(ENABLE_OPTS_CHANGE_EXEC) && (defined(EXEC_LINKS) || defined(EXEC_SCRIPTS))
    static const char *exec_choices[] =
    {
	"ALWAYS OFF",
	"FOR LOCAL FILES ONLY",
#ifndef NEVER_ALLOW_REMOTE_EXEC
	"ALWAYS ON",
#endif				/* !NEVER_ALLOW_REMOTE_EXEC */
	NULL
    };
#endif
    static const char *fileSort_choices[] =
    {
	"By Filename",
	"By Type",
	"By Size",
	"By Date",
	NULL
    };
    static const char *keypad_choices[] =
    {
	"Numbers act as arrows",
	"Links are numbered",
	"Links and form fields are numbered",
	NULL
    };
    static const char *mbm_choices[] =
    {
	"OFF     ",
	"STANDARD",
	"ADVANCED",
	NULL
    };
    static const char *userMode_choices[] =
    {
	"Novice",
	"Intermediate",
	"Advanced",
	NULL
    };

#if defined(ENABLE_OPTS_CHANGE_EXEC) && (defined(EXEC_LINKS) || defined(EXEC_SCRIPTS))
    int itmp;
#endif /* ENABLE_OPTS_CHANGE_EXEC */
    int response, ch;

    /*
     * If the user changes the display we need memory to put it in.
     */
    bstring *my_data = NULL;
    char *choices[MAXCHOICES];
    int CurrentCharSet = current_char_set;
    int CurrentAssumeCharSet = UCLYhndl_for_unspec;
    int CurrentShowColor = LYShowColor;
    BOOLEAN CurrentRawMode = LYRawMode;
    BOOLEAN AddValueAccepted = FALSE;
    BOOL use_assume_charset;

#if defined(VMS) || defined(USE_SLANG)
    BOOL old_use_assume_charset;
#endif

#ifdef DIRED_SUPPORT
#ifdef ENABLE_OPTS_CHANGE_EXEC
    if (LYlines < 24) {
	HTAlert(OPTION_SCREEN_NEEDS_24);
	return;
    }
#else
    if (LYlines < 23) {
	HTAlert(OPTION_SCREEN_NEEDS_23);
	return;
    }
#endif /* ENABLE_OPTS_CHANGE_EXEC */
#else
#ifdef ENABLE_OPTS_CHANGE_EXEC
    if (LYlines < 23) {
	HTAlert(OPTION_SCREEN_NEEDS_23);
	return;
    }
#else
    if (LYlines < 22) {
	HTAlert(OPTION_SCREEN_NEEDS_22);
	return;
    }
#endif /* ENABLE_OPTS_CHANGE_EXEC */
#endif /* DIRED_SUPPORT */

    term_options = FALSE;
    LYStatusLine = (LYlines - 1);	/* screen is otherwise too crowded */
    signal(SIGINT, terminate_options);
    if (no_option_save) {
	if (LYShowColor == SHOW_COLOR_NEVER) {
	    LYShowColor = SHOW_COLOR_OFF;
	} else if (LYShowColor == SHOW_COLOR_ALWAYS) {
	    LYShowColor = SHOW_COLOR_ON;
	}
#if defined(USE_SLANG) || defined(COLOR_CURSES)
    } else {
	SetupChosenShowColor();
#endif /* USE_SLANG || COLOR_CURSES */
    }

    use_assume_charset = (BOOLEAN) (user_mode == ADVANCED_MODE);

  draw_options:

#if defined(VMS) || defined(USE_SLANG)
    old_use_assume_charset = use_assume_charset;
#endif
    /*
     * NOTE that printw() should be avoided for strings that might have
     * non-ASCII or multibyte/CJK characters.  - FM
     */
#if defined(FANCY_CURSES) || defined (USE_SLANG)
    if (enable_scrollback) {
	LYclear();
    } else {
	LYerase();
    }
#else
    LYclear();
#endif /* FANCY_CURSES || USE_SLANG */
    LYmove(0, 5);

    lynx_start_h1_color();
    LYaddstr("         Options Menu (");
    LYaddstr(LYNX_NAME);
    LYaddstr(" Version ");
    LYaddstr(LYNX_VERSION);
    LYaddch(')');
    lynx_stop_h1_color();
    LYmove(L_EDITOR, 5);
    addlbl("(E)ditor                     : ");
    LYaddstr(non_empty(editor) ? editor : "NONE");

    LYmove(L_DISPLAY, 5);
    addlbl("(D)ISPLAY variable           : ");
    LYaddstr(non_empty(x_display) ? x_display : "NONE");

    LYmove(L_HOME, 5);
    addlbl("mu(L)ti-bookmarks: ");
    LYaddstr(mbm_choices[LYMultiBookmarks]);
    LYmove(L_HOME, B_BOOK);
    if (LYMultiBookmarks != MBM_OFF) {
	addlbl("review/edit (B)ookmarks files");
    } else {
	addlbl("(B)ookmark file: ");
	LYaddstr(non_empty(bookmark_page) ? bookmark_page : "NONE");
    }

    LYmove(L_FTPSTYPE, 5);
    addlbl("(F)TP sort criteria          : ");
    LYaddstr((HTfileSortMethod == FILE_BY_NAME ? "By Filename" :
	      (HTfileSortMethod == FILE_BY_SIZE ? "By Size    " :
	       (HTfileSortMethod == FILE_BY_TYPE ? "By Type    " :
		"By Date    "))));

    LYmove(L_MAIL_ADDRESS, 5);
    addlbl("(P)ersonal mail address      : ");
    LYaddstr(non_empty(personal_mail_address) ?
	     personal_mail_address : "NONE");

    LYmove(L_SSEARCH, 5);
    addlbl("(S)earching type             : ");
    LYaddstr(LYcase_sensitive ? "CASE SENSITIVE  " : "CASE INSENSITIVE");

    LYmove(L_Charset, 5);
    addlbl("display (C)haracter set      : ");
    LYaddstr(LYchar_set_names[current_char_set]);

    LYmove(L_LANGUAGE, 5);
    addlbl("preferred document lan(G)uage: ");
    LYaddstr(non_empty(language) ? language : "NONE");

    LYmove(L_PREF_CHARSET, 5);
    addlbl("preferred document c(H)arset : ");
    LYaddstr(non_empty(pref_charset) ? pref_charset : "NONE");

    if (use_assume_charset) {
	LYmove(L_ASSUME_CHARSET, 5);
	addlbl("(^A)ssume charset if unknown : ");
	if (UCAssume_MIMEcharset)
	    LYaddstr(UCAssume_MIMEcharset);
	else
	    LYaddstr((UCLYhndl_for_unspec >= 0) ?
		     LYCharSet_UC[UCLYhndl_for_unspec].MIMEname
		     : "NONE");
    }

    LYmove(L_Rawmode, 5);
    addlbl("Raw 8-bit or CJK m(O)de      : ");
    ShowBool(LYRawMode);

#if defined(USE_SLANG) || defined(COLOR_CURSES)
    LYmove(L_Color, B_COLOR);
    addlbl("show color (&)  : ");
    if (no_option_save) {
	ShowBool(LYShowColor == SHOW_COLOR_OFF);
    } else {
	switch (LYChosenShowColor) {
	case SHOW_COLOR_NEVER:
	    LYaddstr("NEVER     ");
	    break;
	case SHOW_COLOR_OFF:
	    LYaddstr("OFF");
	    break;
	case SHOW_COLOR_ON:
	    LYaddstr("ON ");
	    break;
	case SHOW_COLOR_ALWAYS:
#if defined(COLOR_CURSES)
	    if (!has_colors())
		LYaddstr("Always try");
	    else
#endif
		LYaddstr("ALWAYS    ");
	}
    }
#endif /* USE_SLANG || COLOR_CURSES */

    LYmove(L_Bool_A, B_VIKEYS);
    addlbl("(V)I keys: ");
    ShowBool(vi_keys);

    LYmove(L_Bool_A, B_EMACSKEYS);
    addlbl("e(M)acs keys: ");
    ShowBool(emacs_keys);

    LYmove(L_Bool_A, B_SHOW_DOTFILES);
    addlbl("sho(W) dot files: ");
    ShowBool(!no_dotfiles && show_dotfiles);

    LYmove(L_Bool_B, B_SELECT_POPUPS);
    addlbl("popups for selec(T) fields   : ");
    ShowBool(LYSelectPopups);

    LYmove(L_Bool_B, B_SHOW_CURSOR);
    addlbl("show cursor (@) : ");
    ShowBool(LYShowCursor);

    LYmove(L_Keypad, 5);
    addlbl("(K)eypad mode                : ");
    LYaddstr((fields_are_numbered() && links_are_numbered())
	     ? "Links and form fields are numbered"
	     : (links_are_numbered()
		? "Links are numbered                "
		: (fields_are_numbered()
		   ? "Form fields are numbered          "
		   : "Numbers act as arrows             ")));

    LYmove(L_Lineed, 5);
    addlbl("li(N)e edit style            : ");
    LYaddstr(LYEditorNames[current_lineedit]);

#ifdef EXP_KEYBOARD_LAYOUT
    LYmove(L_Layout, 5);
    addlbl("Ke(Y)board layout            : ");
    LYaddstr(LYKbLayoutNames[current_layout]);
#endif

#ifdef DIRED_SUPPORT
    LYmove(L_Dired, 5);
    addlbl("l(I)st directory style       : ");
    LYaddstr((dir_list_style == FILES_FIRST) ? "Files first      " :
	     ((dir_list_style == MIXED_STYLE) ? "Mixed style      " :
	      "Directories first"));
#endif /* DIRED_SUPPORT */

    LYmove(L_User_Mode, 5);
    addlbl("(U)ser mode                  : ");
    LYaddstr((user_mode == NOVICE_MODE) ? "Novice      " :
	     ((user_mode == INTERMEDIATE_MODE) ? "Intermediate" :
	      "Advanced    "));

    addlbl("  verbose images (!) : ");
    ShowBool(verbose_img);

    LYmove(L_User_Agent, 5);
    addlbl("user (A)gent                 : ");
    LYaddstr(non_empty(LYUserAgent) ? LYUserAgent : "NONE");

#if defined(ENABLE_OPTS_CHANGE_EXEC) && (defined(EXEC_LINKS) || defined(EXEC_SCRIPTS))
    LYmove(L_Exec, 5);
    addlbl("local e(X)ecution links      : ");
#ifndef NEVER_ALLOW_REMOTE_EXEC
    LYaddstr(local_exec ? "ALWAYS ON           " :
	     (local_exec_on_local_files ? "FOR LOCAL FILES ONLY" :
	      "ALWAYS OFF          "));
#else
    LYaddstr(local_exec_on_local_files ? "FOR LOCAL FILES ONLY" :
	     "ALWAYS OFF          ");
#endif /* !NEVER_ALLOW_REMOTE_EXEC */
#endif /* ENABLE_OPTS_CHANGE_EXEC */

    LYmove(LYlines - 3, 2);
    LYaddstr(SELECT_SEGMENT);
    lynx_start_bold();
    LYaddstr(CAP_LETT_SEGMENT);
    lynx_stop_bold();
    LYaddstr(OF_OPT_LINE_SEGMENT);
    if (!no_option_save) {
	LYaddstr(" '");
	lynx_start_bold();
	LYaddstr(">");
	lynx_stop_bold();
	LYaddstr("'");
	LYaddstr(TO_SAVE_SEGMENT);
    }
    LYaddstr(OR_SEGMENT);
    LYaddstr("'");
    lynx_start_bold();
    LYaddstr("r");
    lynx_stop_bold();
    LYaddstr("'");
    LYaddstr(TO_RETURN_SEGMENT);

    response = 0;
    while (response != 'R' &&
	   !LYisNonAlnumKeyname(response, LYK_PREV_DOC) &&
	   response != '>' && !term_options &&
	   !LYCharIsINTERRUPT_NO_letter(response)) {
	if (AddValueAccepted == TRUE) {
	    _statusline(VALUE_ACCEPTED);
	    AddValueAccepted = FALSE;
	}
	LYmove((LYlines - 2), 0);
	lynx_start_prompt_color();
	LYaddstr(COMMAND_PROMPT);
	lynx_stop_prompt_color();

	LYrefresh();
	response = LYgetch_single();
	if (term_options || LYCharIsINTERRUPT_NO_letter(response))
	    response = 'R';
	if (LYisNonAlnumKeyname(response, LYK_REFRESH)) {
	    lynx_force_repaint();
	    goto draw_options;
	}
	switch (response) {
	case 'E':		/* Change the editor. */
	    if (no_editor) {
		_statusline(EDIT_DISABLED);
	    } else if (system_editor) {
		_statusline(EDITOR_LOCKED);
	    } else {
		if (non_empty(editor)) {
		    BStrCopy0(my_data, editor);
		} else {	/* clear the NONE */
		    LYmove(L_EDITOR, COL_OPTION_VALUES);
		    LYaddstr("    ");
		    BStrCopy0(my_data, "");
		}
		_statusline(ACCEPT_DATA);
		LYmove(L_EDITOR, COL_OPTION_VALUES);
		lynx_start_bold();
		ch = LYgetBString(&my_data, FALSE, 0, NORECALL);
		lynx_stop_bold();
		LYmove(L_EDITOR, COL_OPTION_VALUES);
		if (term_options || ch == -1) {
		    LYaddstr(non_empty(editor) ?
			     editor : "NONE");
		} else if (isBEmpty(my_data)) {
		    FREE(editor);
		    LYaddstr("NONE");
		} else {
		    StrAllocCopy(editor, my_data->str);
		    LYaddstr(editor);
		}
		LYclrtoeol();
		if (ch == -1) {
		    HTInfoMsg(CANCELLED);
		    HTInfoMsg("");
		} else {
		    _statusline(VALUE_ACCEPTED);
		}
	    }
	    response = ' ';
	    break;

	case 'D':		/* Change the display. */
	    if (non_empty(x_display)) {
		BStrCopy0(my_data, x_display);
	    } else {		/* clear the NONE */
		LYmove(L_DISPLAY, COL_OPTION_VALUES);
		LYaddstr("    ");
		BStrCopy0(my_data, "");
	    }
	    _statusline(ACCEPT_DATA);
	    LYmove(L_DISPLAY, COL_OPTION_VALUES);
	    lynx_start_bold();
	    ch = LYgetBString(&my_data, FALSE, 0, NORECALL);
	    lynx_stop_bold();
	    LYmove(L_DISPLAY, COL_OPTION_VALUES);

#ifdef VMS
#define CompareEnvVars(a,b) strcasecomp(a, b)
#else
#define CompareEnvVars(a,b) strcmp(a, b)
#endif /* VMS */

	    if ((term_options || ch == -1) ||
		(x_display != NULL &&
		 !CompareEnvVars(x_display, my_data->str))) {
		/*
		 * Cancelled, or a non-NULL display string wasn't changed.  -
		 * FM
		 */
		LYaddstr(non_empty(x_display) ? x_display : "NONE");
		LYclrtoeol();
		if (ch == -1) {
		    HTInfoMsg(CANCELLED);
		    HTInfoMsg("");
		} else {
		    _statusline(VALUE_ACCEPTED);
		}
		response = ' ';
		break;
	    } else if (isBEmpty(my_data)) {
		if ((x_display == NULL) ||
		    (x_display != NULL && *x_display == '\0')) {
		    /*
		     * NULL or zero-length display string wasn't changed.  - FM
		     */
		    LYaddstr("NONE");
		    LYclrtoeol();
		    _statusline(VALUE_ACCEPTED);
		    response = ' ';
		    break;
		}
	    }
	    /*
	     * Set the new DISPLAY variable.  - FM
	     */
	    LYsetXDisplay(my_data->str);
	    validate_x_display();
	    LYaddstr(x_display ? x_display : "NONE");
	    LYclrtoeol();
	    summarize_x_display(my_data->str);
	    response = ' ';
	    break;

	case 'L':		/* Change multibookmarks option. */
	    if (LYMBMBlocked) {
		_statusline(MULTIBOOKMARKS_DISALLOWED);
		response = ' ';
		break;
	    }
	    if (!LYSelectPopups) {
		LYMultiBookmarks = LYChooseEnum(LYMultiBookmarks,
						L_HOME, C_MULTI,
						mbm_choices);
	    } else {
		LYMultiBookmarks = LYChoosePopup(LYMultiBookmarks,
						 L_HOME, (C_MULTI - 1),
						 mbm_choices,
						 3, FALSE, FALSE);
	    }
#if defined(VMS) || defined(USE_SLANG)
	    if (LYSelectPopups) {
		LYmove(L_HOME, C_MULTI);
		LYclrtoeol();
		LYaddstr(mbm_choices[LYMultiBookmarks]);
	    }
#endif /* VMS || USE_SLANG */
#if !defined(VMS) && !defined(USE_SLANG)
	    if (!LYSelectPopups)
#endif /* !VMS && !USE_SLANG */
	    {
		LYmove(L_HOME, B_BOOK);
		LYclrtoeol();
		if (LYMultiBookmarks != MBM_OFF) {
		    LYaddstr(gettext("review/edit B)ookmarks files"));
		} else {
		    LYaddstr(gettext("B)ookmark file: "));
		    LYaddstr(non_empty(bookmark_page) ?
			     bookmark_page : "NONE");
		}
	    }
	    response = ' ';
	    if (LYSelectPopups) {
		HANDLE_LYOPTIONS;
	    }
	    break;

	case 'B':		/* Change the bookmark page location. */
	    /*
	     * Anonymous users should not be allowed to change the bookmark
	     * page.
	     */
	    if (!no_bookmark) {
		if (LYMultiBookmarks != MBM_OFF) {
		    edit_bookmarks();
		    signal(SIGINT, terminate_options);
		    goto draw_options;
		}
		if (non_empty(bookmark_page)) {
		    BStrCopy0(my_data, bookmark_page);
		} else {	/* clear the NONE */
		    LYmove(L_HOME, C_DEFAULT);
		    LYclrtoeol();
		    BStrCopy0(my_data, "");
		}
		_statusline(ACCEPT_DATA);
		LYmove(L_HOME, C_DEFAULT);
		lynx_start_bold();
		ch = LYgetBString(&my_data, FALSE, 0, NORECALL);
		lynx_stop_bold();
		LYmove(L_HOME, C_DEFAULT);
		BStrAlloc(my_data, my_data->len + LY_MAXPATH);	/* lengthen */
		if (term_options ||
		    ch == -1 || isBEmpty(my_data)) {
		    LYaddstr(non_empty(bookmark_page) ?
			     bookmark_page : "NONE");
		} else if (!LYPathOffHomeOK(my_data->str, (size_t) my_data->len)) {
		    LYaddstr(non_empty(bookmark_page) ?
			     bookmark_page : "NONE");
		    LYclrtoeol();
		    _statusline(USE_PATH_OFF_HOME);
		    response = ' ';
		    break;
		} else {
		    StrAllocCopy(bookmark_page, my_data->str);
		    StrAllocCopy(MBM_A_subbookmark[0], bookmark_page);
		    LYaddstr(bookmark_page);
		}
		LYclrtoeol();
		if (ch == -1) {
		    HTInfoMsg(CANCELLED);
		    HTInfoMsg("");
		} else {
		    _statusline(VALUE_ACCEPTED);
		}
	    } else {		/* anonymous */
		_statusline(BOOKMARK_CHANGE_DISALLOWED);
	    }
	    response = ' ';
	    break;

	case 'F':		/* Change ftp directory sorting. */
	    if (!LYSelectPopups) {
		HTfileSortMethod = LYChooseEnum(HTfileSortMethod,
						L_FTPSTYPE, -1,
						fileSort_choices);
	    } else {
		HTfileSortMethod = LYChoosePopup(HTfileSortMethod,
						 L_FTPSTYPE, -1,
						 fileSort_choices,
						 4, FALSE, FALSE);
#if defined(VMS) || defined(USE_SLANG)
		LYmove(L_FTPSTYPE, COL_OPTION_VALUES);
		LYclrtoeol();
		LYaddstr(fileSort_choices[HTfileSortMethod]);
#endif /* VMS || USE_SLANG */
	    }
	    response = ' ';
	    if (LYSelectPopups) {
		HANDLE_LYOPTIONS;
	    }
	    break;

	case 'P':		/* Change personal mail address for From headers. */
	    if (non_empty(personal_mail_address)) {
		BStrCopy0(my_data, personal_mail_address);
	    } else {		/* clear the NONE */
		LYmove(L_MAIL_ADDRESS, COL_OPTION_VALUES);
		LYaddstr("    ");
		BStrCopy0(my_data, "");
	    }
	    _statusline(ACCEPT_DATA);
	    LYmove(L_MAIL_ADDRESS, COL_OPTION_VALUES);
	    lynx_start_bold();
	    ch = LYgetBString(&my_data, FALSE, 0, NORECALL);
	    lynx_stop_bold();
	    LYmove(L_MAIL_ADDRESS, COL_OPTION_VALUES);
	    if (term_options || ch == -1) {
		LYaddstr((personal_mail_address &&
			  *personal_mail_address) ?
			 personal_mail_address : "NONE");
	    } else if (isBEmpty(my_data)) {
		FREE(personal_mail_address);
		LYaddstr("NONE");
	    } else {
		StrAllocCopy(personal_mail_address, my_data->str);
		LYaddstr(personal_mail_address);
	    }
	    LYclrtoeol();
	    if (ch == -1) {
		HTInfoMsg(CANCELLED);
		HTInfoMsg("");
	    } else {
		_statusline(VALUE_ACCEPTED);
	    }
	    response = ' ';
	    break;

	case 'S':		/* Change case sensitivity for searches. */
	    LYcase_sensitive = LYChooseBoolean(LYcase_sensitive,
					       L_SSEARCH, -1,
					       caseless_choices);
	    response = ' ';
	    break;

	case '\001':		/* Change assume_charset setting. */
	    if (use_assume_charset) {
		int i, curval;
		const char **assume_list;
		assume_list = typecallocn(const char *, (unsigned)
					    (LYNumCharsets + 1));

		if (!assume_list) {
		    outofmem(__FILE__, "options");
		}
		for (i = 0; i < LYNumCharsets; i++) {
		    assume_list[i] = LYCharSet_UC[i].MIMEname;
		}
		curval = UCLYhndl_for_unspec;
		if (curval == current_char_set && UCAssume_MIMEcharset) {
		    curval = UCGetLYhndl_byMIME(UCAssume_MIMEcharset);
		}
		if (curval < 0)
		    curval = LYRawMode ? current_char_set : 0;
		if (!LYSelectPopups) {
#ifndef ALL_CHARSETS_IN_O_MENU_SCREEN
		    UCLYhndl_for_unspec =
			assumed_doc_charset_map[(LYChooseEnum(charset_subsets[curval].assumed_idx,
							      L_ASSUME_CHARSET, -1,
							      assumed_charset_choices)
						 ? 1
						 : 0)];
#else
		    UCLYhndl_for_unspec =
			LYChooseEnum(curval,
				     L_ASSUME_CHARSET, -1,
				     assume_list);
#endif
		} else {
#ifndef ALL_CHARSETS_IN_O_MENU_SCREEN
		    UCLYhndl_for_unspec =
			assumed_doc_charset_map[(LYChoosePopup(charset_subsets[curval].assumed_idx,
							       L_ASSUME_CHARSET, -1,
							       assumed_charset_choices,
							       0,
							       FALSE,
							       FALSE)
						 ? 1
						 : 0)];
#else
		    UCLYhndl_for_unspec =
			LYChoosePopup(curval,
				      L_ASSUME_CHARSET, -1,
				      assume_list,
				      0, FALSE, FALSE);
#endif
#if defined(VMS) || defined(USE_SLANG)
		    LYmove(L_ASSUME_CHARSET, COL_OPTION_VALUES);
		    LYclrtoeol();
		    if (UCLYhndl_for_unspec >= 0)
			LYaddstr(LYCharSet_UC[UCLYhndl_for_unspec].MIMEname);
#endif /* VMS || USE_SLANG */
		}

		/*
		 * Set the raw 8-bit or CJK mode defaults and character set if
		 * changed.  - FM
		 */
		if (CurrentAssumeCharSet != UCLYhndl_for_unspec ||
		    UCLYhndl_for_unspec != curval) {
		    if (UCLYhndl_for_unspec != CurrentAssumeCharSet) {
			StrAllocCopy(UCAssume_MIMEcharset,
				     LYCharSet_UC[UCLYhndl_for_unspec].MIMEname);
		    }
		    if (HTCJK != JAPANESE)
			LYRawMode = (BOOLEAN) (UCLYhndl_for_unspec == current_char_set);
		    HTMLSetUseDefaultRawMode(current_char_set, LYRawMode);
		    HTMLSetCharacterHandling(current_char_set);
		    CurrentAssumeCharSet = UCLYhndl_for_unspec;
		    CurrentRawMode = LYRawMode;
#if !defined(VMS) && !defined(USE_SLANG)
		    if (!LYSelectPopups)
#endif /* !VMS && !USE_SLANG */
		    {
			LYmove(L_Rawmode, COL_OPTION_VALUES);
			LYclrtoeol();
			ShowBool(LYRawMode);
		    }
		}
		FREE(assume_list);
		response = ' ';
		if (LYSelectPopups) {
		    HANDLE_LYOPTIONS;
		}
	    } else {
		_statusline(NEED_ADVANCED_USER_MODE);
		AddValueAccepted = FALSE;
	    }
	    break;

	case 'C':		/* Change display charset setting. */
	    if (!LYSelectPopups) {
#ifndef ALL_CHARSETS_IN_O_MENU_SCREEN
		displayed_display_charset_idx = LYChooseEnum(displayed_display_charset_idx,
							     L_Charset, -1,
							     display_charset_choices);
		current_char_set = display_charset_map[displayed_display_charset_idx];
#else
		current_char_set = LYChooseEnum(current_char_set,
						L_Charset, -1,
						LYchar_set_names);
#endif
	    } else {
#ifndef ALL_CHARSETS_IN_O_MENU_SCREEN
		displayed_display_charset_idx = LYChoosePopup(displayed_display_charset_idx,
							      L_Charset, -1,
							      display_charset_choices,
							      0, FALSE, FALSE);
		current_char_set = display_charset_map[displayed_display_charset_idx];
#else
		current_char_set = LYChoosePopup(current_char_set,
						 L_Charset, -1,
						 LYchar_set_names,
						 0, FALSE, FALSE);
#endif

#if defined(VMS) || defined(USE_SLANG)
		LYmove(L_Charset, COL_OPTION_VALUES);
		LYclrtoeol();
		LYaddstr(LYchar_set_names[current_char_set]);
#endif /* VMS || USE_SLANG */
	    }
	    /*
	     * Set the raw 8-bit or CJK mode defaults and character set if
	     * changed.  - FM
	     */
	    if (CurrentCharSet != current_char_set) {
		LYUseDefaultRawMode = TRUE;
		HTMLUseCharacterSet(current_char_set);
		CurrentCharSet = current_char_set;
		CurrentRawMode = LYRawMode;
#if !defined(VMS) && !defined(USE_SLANG)
		if (!LYSelectPopups)
#endif /* !VMS && !USE_SLANG */
		{
		    LYmove(L_Rawmode, COL_OPTION_VALUES);
		    LYclrtoeol();
		    ShowBool(LYRawMode);
		}
#ifdef CAN_SWITCH_DISPLAY_CHARSET
		/* Deduce whether the user wants autoswitch: */
		switch_display_charsets =
		    (current_char_set == auto_display_charset
		     || current_char_set == auto_other_display_charset);
#endif
	    }
	    response = ' ';
	    if (LYSelectPopups) {
		HANDLE_LYOPTIONS;
	    }
	    break;

	case 'O':		/* Change raw mode setting. */
	    LYRawMode = LYChooseBoolean(LYRawMode, L_Rawmode, -1, bool_choices);
	    /*
	     * Set the LYUseDefaultRawMode value and character handling if
	     * LYRawMode was changed.  - FM
	     */
	    if (CurrentRawMode != LYRawMode) {
		HTMLSetUseDefaultRawMode(current_char_set, LYRawMode);
		HTMLSetCharacterHandling(current_char_set);
		CurrentRawMode = LYRawMode;
	    }
	    response = ' ';
	    break;

	case 'G':		/* Change language preference. */
	    if (non_empty(language)) {
		BStrCopy0(my_data, language);
	    } else {		/* clear the NONE */
		LYmove(L_LANGUAGE, COL_OPTION_VALUES);
		LYaddstr("    ");
		BStrCopy0(my_data, "");
	    }
	    _statusline(ACCEPT_DATA);
	    LYmove(L_LANGUAGE, COL_OPTION_VALUES);
	    lynx_start_bold();
	    ch = LYgetBString(&my_data, FALSE, 0, NORECALL);
	    lynx_stop_bold();
	    LYmove(L_LANGUAGE, COL_OPTION_VALUES);
	    if (term_options || ch == -1) {
		LYaddstr(non_empty(language) ?
			 language : "NONE");
	    } else if (isBEmpty(my_data)) {
		FREE(language);
		LYaddstr("NONE");
	    } else {
		StrAllocCopy(language, my_data->str);
		LYaddstr(language);
	    }
	    LYclrtoeol();
	    if (ch == -1) {
		HTInfoMsg(CANCELLED);
		HTInfoMsg("");
	    } else {
		_statusline(VALUE_ACCEPTED);
	    }
	    response = ' ';
	    break;

	case 'H':		/* Change charset preference. */
	    if (non_empty(pref_charset)) {
		BStrCopy0(my_data, pref_charset);
	    } else {		/* clear the NONE */
		LYmove(L_PREF_CHARSET, COL_OPTION_VALUES);
		LYaddstr("    ");
		BStrCopy0(my_data, "");
	    }
	    _statusline(ACCEPT_DATA);
	    LYmove(L_PREF_CHARSET, COL_OPTION_VALUES);
	    lynx_start_bold();
	    ch = LYgetBString(&my_data, FALSE, 0, NORECALL);
	    lynx_stop_bold();
	    LYmove(L_PREF_CHARSET, COL_OPTION_VALUES);
	    if (term_options || ch == -1) {
		LYaddstr(non_empty(pref_charset) ?
			 pref_charset : "NONE");
	    } else if (isBEmpty(my_data)) {
		FREE(pref_charset);
		LYaddstr("NONE");
	    } else {
		StrAllocCopy(pref_charset, my_data->str);
		LYaddstr(pref_charset);
	    }
	    LYclrtoeol();
	    if (ch == -1) {
		HTInfoMsg(CANCELLED);
		HTInfoMsg("");
	    } else {
		_statusline(VALUE_ACCEPTED);
	    }
	    response = ' ';
	    break;

	case 'V':		/* Change VI keys setting. */
	    vi_keys = LYChooseBoolean(vi_keys,
				      L_Bool_A, C_VIKEYS,
				      bool_choices);
	    if (vi_keys) {
		set_vi_keys();
	    } else {
		reset_vi_keys();
	    }
	    response = ' ';
	    break;

	case 'M':		/* Change emacs keys setting. */
	    emacs_keys = LYChooseBoolean(emacs_keys,
					 L_Bool_A, C_EMACSKEYS,
					 bool_choices);
	    if (emacs_keys) {
		set_emacs_keys();
	    } else {
		reset_emacs_keys();
	    }
	    response = ' ';
	    break;

	case 'W':		/* Change show dotfiles setting. */
	    if (no_dotfiles) {
		_statusline(DOTFILE_ACCESS_DISABLED);
	    } else {
		show_dotfiles = LYChooseBoolean(show_dotfiles,
						L_Bool_A,
						C_SHOW_DOTFILES,
						bool_choices);
	    }
	    response = ' ';
	    break;

	case 'T':		/* Change select popups setting. */
	    LYSelectPopups = LYChooseBoolean(LYSelectPopups,
					     L_Bool_B,
					     C_SELECT_POPUPS,
					     bool_choices);
	    response = ' ';
	    break;

#if defined(USE_SLANG) || defined(COLOR_CURSES)
	case '&':		/* Change show color setting. */
	    if (no_option_save) {
#if defined(COLOR_CURSES)
		if (!has_colors()) {
		    char *terminal = LYGetEnv("TERM");

		    if (terminal)
			HTUserMsg2(COLOR_TOGGLE_DISABLED_FOR_TERM,
				   terminal);
		    else
			HTUserMsg(COLOR_TOGGLE_DISABLED);
		    break;
		}
#endif
		LYShowColor = LYChooseEnum((LYShowColor - 1),
					   L_Color,
					   C_COLOR,
					   bool_choices);
		if (LYShowColor == 0) {
		    LYShowColor = SHOW_COLOR_OFF;
		} else {
		    LYShowColor = SHOW_COLOR_ON;
		}
	    } else {		/* !no_option_save */
		BOOLEAN again = FALSE;
		int chosen;

		/*
		 * Copy strings into choice array.
		 */
		choices[0] = NULL;
		StrAllocCopy(choices[0], "NEVER     ");
		choices[1] = NULL;
		StrAllocCopy(choices[1], "OFF       ");
		choices[2] = NULL;
		StrAllocCopy(choices[2], "ON        ");
		choices[3] = NULL;
#if defined(COLOR_CURSES)
		if (!has_colors())
		    StrAllocCopy(choices[3], "Always try");
		else
#endif
		    StrAllocCopy(choices[3], "ALWAYS    ");
		choices[4] = NULL;
		do {
		    if (!LYSelectPopups) {
			chosen = LYChooseEnum(LYChosenShowColor,
					      L_Color,
					      C_COLOR,
					      choices);
		    } else {
			chosen = LYChoosePopup(LYChosenShowColor,
					       L_Color,
					       C_COLOR,
					       choices, 4, FALSE, FALSE);
		    }
#if defined(COLOR_CURSES)
		    again = (BOOLEAN) (chosen == SHOW_COLOR_ON && !has_colors());
		    if (again) {
			char *terminal = LYGetEnv("TERM");

			if (terminal)
			    HTUserMsg2(COLOR_TOGGLE_DISABLED_FOR_TERM,
				       terminal);
			else
			    HTUserMsg(COLOR_TOGGLE_DISABLED);
		    }
#endif
		} while (again);
		LYChosenShowColor = chosen;
#if defined(VMS)
		if (LYSelectPopups) {
		    LYmove(L_Color, C_COLOR);
		    LYclrtoeol();
		    LYaddstr(choices[LYChosenShowColor]);
		}
#endif /* VMS */
#if defined(COLOR_CURSES)
		if (has_colors())
#endif
		    LYShowColor = chosen;
		FREE(choices[0]);
		FREE(choices[1]);
		FREE(choices[2]);
		FREE(choices[3]);
	    }
	    if (CurrentShowColor != LYShowColor) {
		lynx_force_repaint();
	    }
	    CurrentShowColor = LYShowColor;
#ifdef USE_SLANG
	    SLtt_Use_Ansi_Colors = (LYShowColor > SHOW_COLOR_OFF ? TRUE : FALSE);
#endif
	    response = ' ';
	    if (LYSelectPopups && !no_option_save) {
		HANDLE_LYOPTIONS;
	    }
	    break;
#endif /* USE_SLANG or COLOR_CURSES */

	case '@':		/* Change show cursor setting. */
	    LYShowCursor = LYChooseBoolean(LYShowCursor,
					   L_Bool_B,
					   C_SHOW_CURSOR,
					   bool_choices);
	    response = ' ';
	    break;

	case 'K':		/* Change keypad mode. */
	    if (!LYSelectPopups) {
		keypad_mode = LYChooseEnum(keypad_mode,
					   L_Keypad, -1,
					   keypad_choices);
	    } else {
		keypad_mode = LYChoosePopup(keypad_mode,
					    L_Keypad, -1,
					    keypad_choices,
					    3, FALSE, FALSE);
#if defined(VMS) || defined(USE_SLANG)
		LYmove(L_Keypad, COL_OPTION_VALUES);
		LYclrtoeol();
		LYaddstr(keypad_choices[keypad_mode]);
#endif /* VMS || USE_SLANG */
	    }
	    if (keypad_mode == NUMBERS_AS_ARROWS) {
		set_numbers_as_arrows();
	    } else {
		reset_numbers_as_arrows();
	    }
	    response = ' ';
	    if (LYSelectPopups) {
		HANDLE_LYOPTIONS;
	    }
	    break;

	case 'N':		/* Change line editor key bindings. */
	    if (!LYSelectPopups) {
		current_lineedit = LYChooseEnum(current_lineedit,
						L_Lineed, -1,
						LYEditorNames);
	    } else {
		current_lineedit = LYChoosePopup(current_lineedit,
						 L_Lineed, -1,
						 LYEditorNames,
						 0, FALSE, FALSE);
#if defined(VMS) || defined(USE_SLANG)
		LYmove(L_Lineed, COL_OPTION_VALUES);
		LYclrtoeol();
		LYaddstr(LYEditorNames[current_lineedit]);
#endif /* VMS || USE_SLANG */
	    }
	    response = ' ';
	    if (LYSelectPopups) {
		HANDLE_LYOPTIONS;
	    }
	    break;

#ifdef EXP_KEYBOARD_LAYOUT
	case 'Y':		/* Change keyboard layout */
	    if (!LYSelectPopups) {
		current_layout = LYChooseEnum(current_layout,
					      L_Layout, -1,
					      LYKbLayoutNames);
	    } else {
		current_layout = LYChoosePopup(current_layout,
					       L_Layout, -1,
					       LYKbLayoutNames,
					       0, FALSE, FALSE);
#if defined(VMS) || defined(USE_SLANG)
		LYmove(L_Layout, COL_OPTION_VALUES);
		LYclrtoeol();
		LYaddstr(LYKbLayoutNames[current_layout]);
#endif /* VMS || USE_SLANG */
	    }
	    response = ' ';
	    if (LYSelectPopups) {
		HANDLE_LYOPTIONS;
	    }
	    break;
#endif /* EXP_KEYBOARD_LAYOUT */

#ifdef DIRED_SUPPORT
	case 'I':		/* Change local directory sorting. */
	    if (!LYSelectPopups) {
		dir_list_style = LYChooseEnum(dir_list_style,
					      L_Dired, -1,
					      dirList_choices);
	    } else {
		dir_list_style = LYChoosePopup(dir_list_style,
					       L_Dired, -1,
					       dirList_choices,
					       3, FALSE, FALSE);
#if defined(VMS) || defined(USE_SLANG)
		LYmove(L_Dired, COL_OPTION_VALUES);
		LYclrtoeol();
		LYaddstr(dirList_choices[dir_list_style]);
#endif /* VMS || USE_SLANG */
	    }
	    response = ' ';
	    if (LYSelectPopups) {
		HANDLE_LYOPTIONS;
	    }
	    break;
#endif /* DIRED_SUPPORT */

	case 'U':		/* Change user mode. */
	    if (!LYSelectPopups) {
		user_mode = LYChooseEnum(user_mode,
					 L_User_Mode, -1,
					 userMode_choices);
		use_assume_charset = (BOOLEAN) (user_mode >= 2);
	    } else {
		user_mode = LYChoosePopup(user_mode,
					  L_User_Mode, -1,
					  userMode_choices,
					  3, FALSE, FALSE);
		use_assume_charset = (BOOLEAN) (user_mode >= 2);
#if defined(VMS) || defined(USE_SLANG)
		if (use_assume_charset == old_use_assume_charset) {
		    LYmove(L_User_Mode, COL_OPTION_VALUES);
		    LYclrtoeol();
		    LYaddstr(userMode_choices[user_mode]);
		}
#endif /* VMS || USE_SLANG */
	    }
	    LYSetDisplayLines();
	    response = ' ';
	    if (LYSelectPopups) {
		HANDLE_LYOPTIONS;
	    }
	    break;

	case '!':
	    if (!LYSelectPopups) {
		verbose_img = LYChooseBoolean(verbose_img,
					      L_VERBOSE_IMAGES,
					      C_VERBOSE_IMAGES,
					      bool_choices);
	    } else {
		verbose_img = (BOOLEAN) LYChoosePopup(verbose_img,
						      L_VERBOSE_IMAGES,
						      C_VERBOSE_IMAGES,
						      bool_choices,
						      2, FALSE, FALSE);
	    }
	    response = ' ';
	    if (LYSelectPopups) {
		HANDLE_LYOPTIONS;
	    }
	    break;

	case 'A':		/* Change user agent string. */
	    if (!no_useragent) {
		if (non_empty(LYUserAgent)) {
		    BStrCopy0(my_data, LYUserAgent);
		} else {	/* clear the NONE */
		    LYmove(L_HOME, COL_OPTION_VALUES);
		    LYaddstr("    ");
		    BStrCopy0(my_data, "");
		}
		_statusline(ACCEPT_DATA_OR_DEFAULT);
		LYmove(L_User_Agent, COL_OPTION_VALUES);
		lynx_start_bold();
		ch = LYgetBString(&my_data, FALSE, 0, NORECALL);
		lynx_stop_bold();
		LYmove(L_User_Agent, COL_OPTION_VALUES);
		if (term_options || ch == -1) {
		    LYaddstr((LYUserAgent &&
			      *LYUserAgent) ?
			     LYUserAgent : "NONE");
		} else if (isBEmpty(my_data)) {
		    StrAllocCopy(LYUserAgent, LYUserAgentDefault);
		    LYaddstr((LYUserAgent &&
			      *LYUserAgent) ?
			     LYUserAgent : "NONE");
		} else {
		    StrAllocCopy(LYUserAgent, my_data->str);
		    LYaddstr(LYUserAgent);
		}
		LYclrtoeol();
		if (ch == -1) {
		    HTInfoMsg(CANCELLED);
		    HTInfoMsg("");
		} else if (!LYCheckUserAgent()) {
		    _statusline(UA_PLEASE_USE_LYNX);
		} else {
		    _statusline(VALUE_ACCEPTED);
		}
	    } else {		/* disallowed */
		_statusline(UA_CHANGE_DISABLED);
	    }
	    response = ' ';
	    break;

#if defined(ENABLE_OPTS_CHANGE_EXEC) && (defined(EXEC_LINKS) || defined(EXEC_SCRIPTS))
	case 'X':		/* Change local exec restriction. */
	    if (exec_frozen && !LYSelectPopups) {
		_statusline(CHANGE_OF_SETTING_DISALLOWED);
		response = ' ';
		break;
	    }
#ifndef NEVER_ALLOW_REMOTE_EXEC
	    if (local_exec) {
		itmp = 2;
	    } else
#endif /* !NEVER_ALLOW_REMOTE_EXEC */
	    {
		if (local_exec_on_local_files) {
		    itmp = 1;
		} else {
		    itmp = 0;
		}
	    }
	    if (!LYSelectPopups) {
		itmp = LYChooseEnum(itmp,
				    L_Exec, -1,
				    exec_choices);
	    } else {
		itmp = LYChoosePopup(itmp,
				     L_Exec, -1,
				     exec_choices,
				     0, (exec_frozen ? TRUE : FALSE),
				     FALSE);
#if defined(VMS) || defined(USE_SLANG)
		LYmove(L_Exec, COL_OPTION_VALUES);
		LYclrtoeol();
		LYaddstr(exec_choices[itmp]);
#endif /* VMS || USE_SLANG */
	    }
	    if (!exec_frozen) {
		switch (itmp) {
		case 0:
		    local_exec = FALSE;
		    local_exec_on_local_files = FALSE;
		    break;
		case 1:
		    local_exec = FALSE;
		    local_exec_on_local_files = TRUE;
		    break;
#ifndef NEVER_ALLOW_REMOTE_EXEC
		case 2:
		    local_exec = TRUE;
		    local_exec_on_local_files = FALSE;
		    break;
#endif /* !NEVER_ALLOW_REMOTE_EXEC */
		}		/* end switch */
	    }
	    response = ' ';
	    if (LYSelectPopups) {
		HANDLE_LYOPTIONS;
	    }
	    break;
#endif /* ENABLE_OPTS_CHANGE_EXEC */

	case '>':		/* Save current options to RC file. */
	    if (!no_option_save) {
		HTInfoMsg(SAVING_OPTIONS);
		LYrcShowColor = LYChosenShowColor;
		if (save_rc(NULL)) {
		    HTInfoMsg(OPTIONS_SAVED);
		} else {
		    HTAlert(OPTIONS_NOT_SAVED);
		}
	    } else {
		HTInfoMsg(R_TO_RETURN_TO_LYNX);
		/*
		 * Change response so that we don't exit the options menu.
		 */
		response = ' ';
	    }
	    break;

	case 'R':		/* Return to document (quit options menu). */
	    break;

	default:
	    if (!no_option_save) {
		HTInfoMsg(SAVE_OR_R_TO_RETURN_TO_LYNX);
	    } else {
		HTInfoMsg(R_TO_RETURN_TO_LYNX);
	    }
	}			/* end switch */
    }				/* end while */

    term_options = FALSE;
    LYStatusLine = -1;		/* let user_mode have some of the screen */
    signal(SIGINT, cleanup_sig);
    BStrFree(my_data);
    return;
}

static int widest_choice(STRING2PTR choices)
{
    int n, width = 0;

    for (n = 0; choices[n] != NULL; ++n) {
	int len = (int) strlen(choices[n]);

	if (width < len)
	    width = len;
    }
    return width;
}

static void show_choice(const char *choice,
			int width)
{
    int len = (int) strlen(choice);

    LYaddstr(choice);
    while (len++ < width)
	LYaddch(' ');
}

/*
 * Take a status code, prompt the user for a new status, and return it.
 */
static int boolean_choice(int cur_choice,
			  int line,
			  int column,
			  STRING2PTR choices)
{
    int response = 0;
    int cmd = 0;
    int number = 0;
    int col = (column >= 0 ? column : COL_OPTION_VALUES);
    int orig_choice = cur_choice;
    int width = widest_choice(choices);

    /*
     * Get the number of choices and then make number zero-based.
     */
    for (number = 0; choices[number] != NULL; number++) ;	/* empty loop body */
    number--;

    /*
     * Update the statusline.
     */
    _statusline(ANY_KEY_CHANGE_RET_ACCEPT);

    /*
     * Highlight the current choice.
     */
    LYmove(line, col);
    lynx_start_reverse();
    show_choice(choices[cur_choice], width);
    if (LYShowCursor)
	LYmove(line, (col - 1));
    LYrefresh();

    /*
     * Get the keyboard entry, and leave the cursor at the choice, to indicate
     * that it can be changed, until the user accepts the current choice.
     */
    term_options = FALSE;
    while (1) {
	LYmove(line, col);
	if (term_options == FALSE) {
	    response = LYgetch_single();
	}
	if (term_options || LYCharIsINTERRUPT_NO_letter(response)) {
	    /*
	     * Control-C or Control-G.
	     */
	    response = '\n';
	    term_options = TRUE;
	    cur_choice = orig_choice;
	}
#ifdef VMS
	if (HadVMSInterrupt) {
	    HadVMSInterrupt = FALSE;
	    response = '\n';
	    term_options = TRUE;
	    cur_choice = orig_choice;
	}
#endif /* VMS */
	if ((response != '\n' && response != '\r') &&
	    (cmd = LKC_TO_LAC(keymap, response)) != LYK_ACTIVATE) {
	    switch (cmd) {
	    case LYK_HOME:
		cur_choice = 0;
		break;

	    case LYK_END:
		cur_choice = number;
		break;

	    case LYK_REFRESH:
		lynx_force_repaint();
		LYrefresh();
		break;

	    case LYK_QUIT:
	    case LYK_ABORT:
	    case LYK_PREV_DOC:
		cur_choice = orig_choice;
		term_options = TRUE;
		break;

	    case LYK_PREV_PAGE:
	    case LYK_UP_HALF:
	    case LYK_UP_TWO:
	    case LYK_PREV_LINK:
	    case LYK_LPOS_PREV_LINK:
	    case LYK_FASTBACKW_LINK:
	    case LYK_UP_LINK:
	    case LYK_LEFT_LINK:
		if (cur_choice == 0)
		    cur_choice = number;	/* go back to end */
		else
		    cur_choice--;
		break;

	    case LYK_1:
	    case LYK_2:
	    case LYK_3:
	    case LYK_4:
	    case LYK_5:
	    case LYK_6:
	    case LYK_7:
	    case LYK_8:
	    case LYK_9:
		if ((cmd - LYK_1 + 1) <= number) {
		    cur_choice = cmd - LYK_1 + 1;
		    break;
		}		/* else fall through! */
	    default:
		if (cur_choice == number)
		    cur_choice = 0;	/* go over the top and around */
		else
		    cur_choice++;
	    }			/* end of switch */
	    show_choice(choices[cur_choice], width);
	    if (LYShowCursor)
		LYmove(line, (col - 1));
	    LYrefresh();
	} else {
	    /*
	     * Unhighlight choice.
	     */
	    LYmove(line, col);
	    lynx_stop_reverse();
	    show_choice(choices[cur_choice], width);

	    if (term_options) {
		term_options = FALSE;
		HTInfoMsg(CANCELLED);
		HTInfoMsg("");
	    } else {
		_statusline(VALUE_ACCEPTED);
	    }
	    return cur_choice;
	}
    }
}
#endif /* !NO_OPTION_MENU */

static void terminate_options(int sig GCC_UNUSED)
{
    term_options = TRUE;
    /*
     * Reassert the AST.
     */
    signal(SIGINT, terminate_options);
#ifdef VMS
    /*
     * Refresh the screen to get rid of the "interrupt" message.
     */
    if (!dump_output_immediately) {
	lynx_force_repaint();
	LYrefresh();
    }
#endif /* VMS */
}

/*
 * Multi-Bookmark On-Line editing support.  - FMG & FM
 */
void edit_bookmarks(void)
{
    int response = 0, def_response = 0;
    int MBM_current = 1;

#define MULTI_OFFSET 8
    int a;			/* misc counter */
    bstring *my_data = NULL;

    /*
     * We need (MBM_V_MAXFILES + MULTI_OFFSET) lines to display the whole list
     * at once.  Otherwise break it up into two segments.  We know it won't be
     * less than that because 'o'ptions needs 23-24 at LEAST.
     */
    term_options = FALSE;
    signal(SIGINT, terminate_options);

  draw_bookmark_list:
    /*
     * Display menu of bookmarks.  NOTE that we avoid printw()'s to increase
     * the chances that any non-ASCII or multibyte/CJK characters will be
     * handled properly.  - FM
     */
#if defined(FANCY_CURSES) || defined (USE_SLANG)
    if (enable_scrollback) {
	LYclear();
    } else {
	LYerase();
    }
#else
    LYclear();
#endif /* FANCY_CURSES || USE_SLANG */
    LYmove(0, 5);
    lynx_start_h1_color();
    if (LYlines < (MBM_V_MAXFILES + MULTI_OFFSET)) {
	char *ehead_buffer = 0;

	HTSprintf0(&ehead_buffer, MULTIBOOKMARKS_EHEAD_MASK, MBM_current);
	LYaddstr(ehead_buffer);
	FREE(ehead_buffer);
    } else {
	LYaddstr(MULTIBOOKMARKS_EHEAD);
    }
    lynx_stop_h1_color();

    if (LYlines < (MBM_V_MAXFILES + MULTI_OFFSET)) {
	for (a = ((MBM_V_MAXFILES / 2 + 1) * (MBM_current - 1));
	     a <= (MBM_current * MBM_V_MAXFILES / 2); a++) {
	    LYmove((3 + a) - ((MBM_V_MAXFILES / 2 + 1) * (MBM_current - 1)), 5);
	    LYaddch(UCH(LYindex2MBM(a)));
	    LYaddstr(" : ");
	    if (MBM_A_subdescript[a])
		LYaddstr(MBM_A_subdescript[a]);
	    LYmove((3 + a) - ((MBM_V_MAXFILES / 2 + 1) * (MBM_current - 1)), 35);
	    LYaddstr("| ");
	    if (MBM_A_subbookmark[a]) {
		LYaddstr(MBM_A_subbookmark[a]);
	    }
	}
    } else {
	for (a = 0; a <= MBM_V_MAXFILES; a++) {
	    LYmove(3 + a, 5);
	    LYaddch(UCH(LYindex2MBM(a)));
	    LYaddstr(" : ");
	    if (MBM_A_subdescript[a])
		LYaddstr(MBM_A_subdescript[a]);
	    LYmove(3 + a, 35);
	    LYaddstr("| ");
	    if (MBM_A_subbookmark[a]) {
		LYaddstr(MBM_A_subbookmark[a]);
	    }
	}
    }

    /*
     * Only needed when we have 2 screens.
     */
    if (LYlines < MBM_V_MAXFILES + MULTI_OFFSET) {
	LYmove((LYlines - 4), 0);
	LYaddstr("'");
	lynx_start_bold();
	LYaddstr("[");
	lynx_stop_bold();
	LYaddstr("' ");
	LYaddstr(PREVIOUS);
	LYaddstr(", '");
	lynx_start_bold();
	LYaddstr("]");
	lynx_stop_bold();
	LYaddstr("' ");
	LYaddstr(NEXT_SCREEN);
    }

    LYmove((LYlines - 3), 0);
    if (!no_option_save) {
	LYaddstr("'");
	lynx_start_bold();
	LYaddstr(">");
	lynx_stop_bold();
	LYaddstr("'");
	LYaddstr(TO_SAVE_SEGMENT);
    }
    LYaddstr(OR_SEGMENT);
    LYaddstr("'");
    lynx_start_bold();
    LYaddstr("^G");
    lynx_stop_bold();
    LYaddstr("'");
    LYaddstr(TO_RETURN_SEGMENT);

    while (!term_options &&
	   !LYisNonAlnumKeyname(response, LYK_PREV_DOC) &&
	   !LYCharIsINTERRUPT_NO_letter(response) && response != '>') {

	LYmove((LYlines - 2), 0);
	lynx_start_prompt_color();
	LYaddstr(MULTIBOOKMARKS_LETTER);
	lynx_stop_prompt_color();

	LYrefresh();
	response = (def_response ? def_response : LYgetch_single());
	def_response = 0;

	/*
	 * Check for a cancel.
	 */
	if (term_options || LYCharIsINTERRUPT_NO_letter(response) ||
	    LYisNonAlnumKeyname(response, LYK_PREV_DOC))
	    continue;

	/*
	 * Check for a save.
	 */
	if (response == '>') {
	    if (!no_option_save) {
		HTInfoMsg(SAVING_OPTIONS);
		if (save_rc(NULL))
		    HTInfoMsg(OPTIONS_SAVED);
		else
		    HTAlert(OPTIONS_NOT_SAVED);
	    } else {
		HTInfoMsg(R_TO_RETURN_TO_LYNX);
		/*
		 * Change response so that we don't exit the options menu.
		 */
		response = ' ';
	    }
	    continue;
	}

	/*
	 * Check for a refresh.
	 */
	if (LYisNonAlnumKeyname(response, LYK_REFRESH)) {
	    lynx_force_repaint();
	    continue;
	}

	/*
	 * Move between the screens - if we can't show it all at once.
	 */
	if ((response == ']' ||
	     LYisNonAlnumKeyname(response, LYK_NEXT_PAGE)) &&
	    LYlines < (MBM_V_MAXFILES + MULTI_OFFSET)) {
	    MBM_current++;
	    if (MBM_current >= 3)
		MBM_current = 1;
	    goto draw_bookmark_list;
	}
	if ((response == '[' ||
	     LYisNonAlnumKeyname(response, LYK_PREV_PAGE)) &&
	    LYlines < (MBM_V_MAXFILES + MULTI_OFFSET)) {
	    MBM_current--;
	    if (MBM_current <= 0)
		MBM_current = 2;
	    goto draw_bookmark_list;
	}

	/*
	 * Instead of using 26 case statements, we set up a scan through the
	 * letters and edit the lines that way.
	 */
	for (a = 0; a <= MBM_V_MAXFILES; a++) {
	    if (LYMBM2index(response) == a) {
		if (LYlines < (MBM_V_MAXFILES + MULTI_OFFSET)) {
		    if (MBM_current == 1 && a > (MBM_V_MAXFILES / 2)) {
			MBM_current = 2;
			def_response = response;
			goto draw_bookmark_list;
		    }
		    if (MBM_current == 2 && a < (MBM_V_MAXFILES / 2)) {
			MBM_current = 1;
			def_response = response;
			goto draw_bookmark_list;
		    }
		}
		_statusline(ACCEPT_DATA);

		if (a > 0) {
		    lynx_start_bold();
		    if (LYlines < (MBM_V_MAXFILES + MULTI_OFFSET))
			LYmove((3 + a)
			       - ((MBM_V_MAXFILES / 2 + 1) * (MBM_current - 1)),
			       9);
		    else
			LYmove((3 + a), 9);
		    BStrCopy0(my_data,
			      (!MBM_A_subdescript[a] ?
			       "" : MBM_A_subdescript[a]));
		    (void) LYgetBString(&my_data, FALSE, 0, NORECALL);
		    lynx_stop_bold();

		    if (isBEmpty(my_data)) {
			FREE(MBM_A_subdescript[a]);
		    } else {
			StrAllocCopy(MBM_A_subdescript[a], my_data->str);
		    }
		    if (LYlines < (MBM_V_MAXFILES + MULTI_OFFSET))
			LYmove((3 + a)
			       - ((MBM_V_MAXFILES / 2 + 1)
				  * (MBM_current - 1)),
			       5);
		    else
			LYmove((3 + a), 5);
		    LYaddch(UCH(LYindex2MBM(a)));
		    LYaddstr(" : ");
		    if (MBM_A_subdescript[a])
			LYaddstr(MBM_A_subdescript[a]);
		    LYclrtoeol();
		    LYrefresh();
		}

		if (LYlines < (MBM_V_MAXFILES + MULTI_OFFSET))
		    LYmove((3 + a)
			   - ((MBM_V_MAXFILES / 2 + 1)
			      * (MBM_current - 1)),
			   35);
		else
		    LYmove((3 + a), 35);
		LYaddstr("| ");

		lynx_start_bold();
		BStrCopy0(my_data, NonNull(MBM_A_subbookmark[a]));
		(void) LYgetBString(&my_data, FALSE, 0, NORECALL);
		lynx_stop_bold();

		if (isBEmpty(my_data)) {
		    if (a == 0)
			StrAllocCopy(MBM_A_subbookmark[a], bookmark_page);
		    else
			FREE(MBM_A_subbookmark[a]);
		} else {
		    BStrAlloc(my_data, my_data->len + LY_MAXPATH);
		    if (!LYPathOffHomeOK(my_data->str, (size_t) my_data->len)) {
			LYMBM_statusline(USE_PATH_OFF_HOME);
			LYSleepAlert();
		    } else {
			StrAllocCopy(MBM_A_subbookmark[a], my_data->str);
			if (a == 0) {
			    StrAllocCopy(bookmark_page, MBM_A_subbookmark[a]);
			}
		    }
		}
		if (LYlines < (MBM_V_MAXFILES + MULTI_OFFSET))
		    LYmove((3 + a)
			   - ((MBM_V_MAXFILES / 2 + 1)
			      * (MBM_current - 1)),
			   35);
		else
		    LYmove((3 + a), 35);
		LYaddstr("| ");
		if (MBM_A_subbookmark[a])
		    LYaddstr(MBM_A_subbookmark[a]);
		LYclrtoeol();
		LYParkCursor();
		break;
	    }
	}			/* end for */
    }				/* end while */

    BStrFree(my_data);
    term_options = FALSE;
    signal(SIGINT, cleanup_sig);
}

#if defined(USE_CURSES_PADS) || !defined(NO_OPTION_MENU) || (defined(USE_MOUSE) && (defined(NCURSES) || defined(PDCURSES)))

/*
 * This function offers the choices for values of an option via a popup window
 * which functions like that for selection of options in a form.  - FM
 *
 * Also used for mouse popups with ncurses; this is indicated by for_mouse.
 */
int popup_choice(int cur_choice,
		 int line,
		 int column,
		 STRING2PTR choices,
		 int i_length,
		 int disabled,
		 int for_mouse)
{
    if (column < 0)
	column = (COL_OPTION_VALUES - 1);

    term_options = FALSE;
    cur_choice = LYhandlePopupList(cur_choice,
				   line,
				   column,
				   (STRING2PTR) choices,
				   -1,
				   i_length,
				   disabled,
				   for_mouse);
    switch (cur_choice) {
    case LYK_QUIT:
    case LYK_ABORT:
    case LYK_PREV_DOC:
	term_options = TRUE;
	if (!for_mouse) {
	    HTUserMsg(CANCELLED);
	}
	break;
    }

    if (disabled || term_options) {
	_statusline("");
    } else if (!for_mouse) {
	_statusline(VALUE_ACCEPTED);
    }
    return (cur_choice);
}

#endif /* !NO_OPTION_MENU */
#ifndef NO_OPTION_FORMS

/*
 * I'm paranoid about mistyping strings.  Also, this way they get combined
 * so we don't have to worry about the intelligence of the compiler.
 * We don't need to burn memory like it's cheap.  We're better than that.
 */
#define SELECTED(flag) (flag) ? selected_string : ""
#define DISABLED(flag) (flag) ? disabled_string : ""

typedef struct {
    int value;
    const char *LongName;
    const char *HtmlName;
} OptValues;

typedef struct {
    char *tag;
    char *value;
} PostPair;

static const char selected_string[] = "selected";
static const char disabled_string[] = "disabled";
static const char on_string[] = N_("ON");
static const char off_string[] = N_("OFF");
static const char never_string[] = N_("NEVER");
static const char always_string[] = N_("ALWAYS");
static OptValues bool_values[] =
{
    {FALSE, N_("OFF"), "OFF"},
    {TRUE, N_("ON"), "ON"},
    {0, 0, 0}
};

static const char *secure_string = "secure";
static char *secure_value = NULL;
static const char *save_options_string = "save_options";

/*
 * Personal Preferences
 */
static const char *cookies_string = RC_SET_COOKIES;
static const char *cookies_ignore_all_string = N_("ignore");
static const char *cookies_up_to_user_string = N_("ask user");
static const char *cookies_accept_all_string = N_("accept all");
static const char *x_display_string = RC_DISPLAY;
static const char *editor_string = RC_FILE_EDITOR;
static const char *emacs_keys_string = RC_EMACS_KEYS;

#if defined(ENABLE_OPTS_CHANGE_EXEC) && (defined(EXEC_LINKS) || defined(EXEC_SCRIPTS))
#define EXEC_ALWAYS 2
#define EXEC_LOCAL  1
#define EXEC_NEVER  0
static const char *exec_links_string = RC_RUN_ALL_EXECUTION_LINKS;
static OptValues exec_links_values[] =
{
    {EXEC_NEVER, N_("ALWAYS OFF"), "ALWAYS OFF"},
    {EXEC_LOCAL, N_("FOR LOCAL FILES ONLY"), "FOR LOCAL FILES ONLY"},
#ifndef NEVER_ALLOW_REMOTE_EXEC
    {EXEC_ALWAYS, N_("ALWAYS ON"), "ALWAYS ON"},
#endif
    {0, 0, 0}
};
#endif /* ENABLE_OPTS_CHANGE_EXEC */

#ifdef EXP_KEYBOARD_LAYOUT
static const char *kblayout_string = RC_KBLAYOUT;
#endif
static const char *keypad_mode_string = RC_KEYPAD_MODE;
static OptValues keypad_mode_values[] =
{
    {NUMBERS_AS_ARROWS, N_("Numbers act as arrows"),
     "number_arrows"},
    {LINKS_ARE_NUMBERED, N_("Links are numbered"),
     "links_numbered"},
    {LINKS_AND_FIELDS_ARE_NUMBERED,
     N_("Links and form fields are numbered"),
     "links_and_forms"},
    {FIELDS_ARE_NUMBERED,
     N_("Form fields are numbered"),
     "forms_numbered"},
    {0, 0, 0}
};
static const char *lineedit_mode_string = RC_LINEEDIT_MODE;
static const char *mail_address_string = RC_PERSONAL_MAIL_ADDRESS;
static const char *personal_name_string = RC_PERSONAL_MAIL_NAME;
static const char *search_type_string = RC_CASE_SENSITIVE_SEARCHING;

#ifndef DISABLE_FTP
static const char *anonftp_password_string = RC_ANONFTP_PASSWORD;
#endif

static OptValues search_type_values[] =
{
    {FALSE, N_("Case insensitive"), "case_insensitive"},
    {TRUE, N_("Case sensitive"), "case_sensitive"},
    {0, 0, 0}
};

#if defined(USE_SLANG) || defined(COLOR_CURSES)
static const char *show_color_string = RC_SHOW_COLOR;
static OptValues show_color_values[] =
{
    {SHOW_COLOR_NEVER, never_string, never_string},
    {SHOW_COLOR_OFF, off_string, off_string},
    {SHOW_COLOR_ON, on_string, on_string},
    {SHOW_COLOR_ALWAYS, always_string, always_string},
    {0, 0, 0}
};
#endif

#ifdef USE_COLOR_STYLE
static const char *color_style_string = RC_COLOR_STYLE;
static OptValues *color_style_values;
static HTList *color_style_list;
#endif

#ifdef USE_DEFAULT_COLORS
static const char *default_colors_string = RC_DEFAULT_COLORS;
#endif

static const char *show_cursor_string = RC_SHOW_CURSOR;

static const char *underline_links_string = RC_UNDERLINE_LINKS;

#ifdef USE_SCROLLBAR
static const char *show_scrollbar_string = RC_SCROLLBAR;
#endif

static const char prompt_dft_string[] = N_("prompt normally");
static const char prompt_yes_string[] = N_("force yes-response");
static const char prompt_no_string[] = N_("force no-response");
static OptValues prompt_values[] =
{
    {FORCE_PROMPT_DFT, prompt_dft_string, prompt_dft_string},
    {FORCE_PROMPT_YES, prompt_yes_string, prompt_yes_string},
    {FORCE_PROMPT_NO, prompt_no_string, prompt_no_string},
    {0, 0, 0}
};

static const char *cookie_prompt_string = RC_FORCE_COOKIE_PROMPT;

#ifdef USE_SSL
static const char *ssl_prompt_string = RC_FORCE_SSL_PROMPT;
#endif

static const char *user_mode_string = RC_USER_MODE;
static OptValues user_mode_values[] =
{
    {NOVICE_MODE, N_("Novice"), "Novice"},
    {INTERMEDIATE_MODE, N_("Intermediate"), "Intermediate"},
    {ADVANCED_MODE, N_("Advanced"), "Advanced"},
    {0, 0, 0}
};

static const char *vi_keys_string = RC_VI_KEYS;

static const char *visited_links_string = RC_VISITED_LINKS;
static OptValues visited_links_values[] =
{
    {VISITED_LINKS_AS_FIRST_V, N_("By First Visit"), "first_visited"},
    {VISITED_LINKS_AS_FIRST_V | VISITED_LINKS_REVERSE,
     N_("By First Visit Reversed"), "first_visited_reversed"},
    {VISITED_LINKS_AS_TREE, N_("As Visit Tree"), "visit_tree"},
    {VISITED_LINKS_AS_LATEST, N_("By Last Visit"), "last_visited"},
    {VISITED_LINKS_AS_LATEST | VISITED_LINKS_REVERSE,
     N_("By Last Visit Reversed"), "last_visited_reversed"},
    {0, 0, 0}
};

/*
 * Document Layout
 */
static const char *DTD_recovery_string = RC_TAGSOUP;
static OptValues DTD_type_values[] =
{
	/* Old_DTD variable */
    {TRUE, N_("relaxed (TagSoup mode)"), "tagsoup"},
    {FALSE, N_("strict (SortaSGML mode)"), "sortasgml"},
    {0, 0, 0}
};

static const char *bad_html_string = RC_BAD_HTML;
static OptValues bad_html_values[] =
{
    {BAD_HTML_IGNORE, N_("Ignore"), "ignore"},
    {BAD_HTML_TRACE, N_("Add to trace-file"), "trace"},
    {BAD_HTML_MESSAGE, N_("Add to LYNXMESSAGES"), "message"},
    {BAD_HTML_WARN, N_("Warn, point to trace-file"), "warn"},
    {0, 0, 0}
};

static const char *select_popups_string = RC_SELECT_POPUPS;
static const char *images_string = "images";
static const char *images_ignore_all_string = N_("ignore");
static const char *images_use_label_string = N_("as labels");
static const char *images_use_links_string = N_("as links");

static const char *verbose_images_string = RC_VERBOSE_IMAGES;
static OptValues verbose_images_type_values[] =
{
	/* verbose_img variable */
    {FALSE, N_("OFF"), "OFF"},
    {TRUE, N_("show filename"), "ON"},
    {0, 0, 0}
};

/*
 * Bookmark Options
 */
static const char *mbm_string = RC_MULTI_BOOKMARK;
static OptValues mbm_values[] =
{
    {MBM_OFF, N_("OFF"), "OFF"},
    {MBM_STANDARD, N_("STANDARD"), "STANDARD"},
    {MBM_ADVANCED, N_("ADVANCED"), "ADVANCED"},
    {0, 0, 0}
};

static const char *single_bookmark_string = RC_BOOKMARK_FILE;

#ifdef USE_SESSIONS
static const char *auto_session_string = RC_AUTO_SESSION;
static const char *single_session_string = RC_SESSION_FILE;
#endif

/*
 * Character Set Options
 */
static const char *assume_char_set_string = RC_ASSUME_CHARSET;
static const char *display_char_set_string = RC_CHARACTER_SET;
static const char *raw_mode_string = RC_RAW_MODE;

#ifdef USE_LOCALE_CHARSET
static const char *locale_charset_string = RC_LOCALE_CHARSET;
#endif

static const char *html5_charsets_string = RC_HTML5_CHARSETS;

/*
 * File Management Options
 */
static const char *show_dotfiles_string = RC_SHOW_DOTFILES;
static const char *no_pause_string = RC_NO_PAUSE;

#ifdef DIRED_SUPPORT
static const char *dired_list_string = RC_DIR_LIST_STYLE;
static OptValues dired_list_values[] =
{
    {DIRS_FIRST, N_("Directories first"), "dired_dir"},
    {FILES_FIRST, N_("Files first"), "dired_files"},
    {MIXED_STYLE, N_("Mixed style"), "dired_mixed"},
    {0, 0, 0}
};

#ifdef LONG_LIST
static const char *dired_sort_string = RC_DIR_LIST_ORDER;
static OptValues dired_sort_values[] =
{
    {ORDER_BY_NAME, N_("By Name"), "dired_by_name"},
    {ORDER_BY_TYPE, N_("By Type"), "dired_by_type"},
    {ORDER_BY_SIZE, N_("By Size"), "dired_by_size"},
    {ORDER_BY_DATE, N_("By Date"), "dired_by_date"},
    {ORDER_BY_MODE, N_("By Mode"), "dired_by_mode"},
#ifndef NO_GROUPS
    {ORDER_BY_USER, N_("By User"), "dired_by_user"},
    {ORDER_BY_GROUP, N_("By Group"), "dired_by_group"},
#endif
    {0, 0, 0}
};
#endif /* LONG_LIST */
#endif /* DIRED_SUPPORT */

#ifndef DISABLE_FTP
static const char *passive_ftp_string = RC_FTP_PASSIVE;

static const char *ftp_sort_string = RC_FILE_SORTING_METHOD;
static OptValues ftp_sort_values[] =
{
    {FILE_BY_NAME, N_("By Name"), "ftp_by_name"},
    {FILE_BY_TYPE, N_("By Type"), "ftp_by_type"},
    {FILE_BY_SIZE, N_("By Size"), "ftp_by_size"},
    {FILE_BY_DATE, N_("By Date"), "ftp_by_date"},
    {0, 0, 0}
};
#endif

#ifdef USE_READPROGRESS
static const char *show_rate_string = RC_SHOW_KB_RATE;
static OptValues rate_values[] =
{
    {rateOFF, N_("Do not show rate"), "rate_off"},
    {rateBYTES, N_("Show %s/sec rate"), "rate_bytes"},
    {rateKB, N_("Show %s/sec rate"), "rate_kb"},
#ifdef USE_READPROGRESS
    {rateEtaBYTES, N_("Show %s/sec, ETA"), "rate_eta_bytes"},
    {rateEtaKB, N_("Show %s/sec, ETA"), "rate_eta_kb"},
    {rateEtaBYTES2, N_("Show %s/sec (2-digits), ETA"), "rate_eta_bytes2"},
    {rateEtaKB2, N_("Show %s/sec (2-digits), ETA"), "rate_eta_kb2"},
#endif
#ifdef USE_PROGRESSBAR
    {rateBAR, N_("Show progressbar"), "rate_bar"},
#endif
    {0, 0, 0}
};
#endif /* USE_READPROGRESS */

/*
 * Presentation (MIME) types used in "Accept".
 */
static const char *preferred_media_string = RC_PREFERRED_MEDIA_TYPES;
static OptValues media_values[] =
{
    {mediaOpt1, N_("Accept lynx's internal types"), "media_opt1"},
    {mediaOpt2, N_("Also accept lynx.cfg's types"), "media_opt2"},
    {mediaOpt3, N_("Also accept user's types"), "media_opt3"},
    {mediaOpt4, N_("Also accept system's types"), "media_opt4"},
    {mediaALL, N_("Accept all types"), "media_all"},
    {0, 0, 0}
};

static const char *preferred_encoding_string = RC_PREFERRED_ENCODING;
static OptValues encoding_values[] =
{
    {encodingNONE, N_("None"), "encoding_none"},
#if defined(USE_ZLIB) || defined(GZIP_PATH)
    {encodingGZIP, N_("gzip"), "encoding_gzip"},
    {encodingDEFLATE, N_("deflate"), "encoding_deflate"},
#endif
#if defined(USE_ZLIB) || defined(COMPRESS_PATH)
    {encodingCOMPRESS, N_("compress"), "encoding_compress"},
#endif
#if defined(USE_BZLIB) || defined(BZIP2_PATH)
    {encodingBZIP2, N_("bzip2"), "encoding_bzip2"},
#endif
    {encodingALL, N_("All"), "encoding_all"},
    {0, 0, 0}
};

/*
 * Headers transferred to remote server
 */
static const char *preferred_doc_char_string = RC_PREFERRED_CHARSET;
static const char *preferred_doc_lang_string = RC_PREFERRED_LANGUAGE;
static const char *send_user_agent_string = RC_SEND_USERAGENT;
static const char *user_agent_string = RC_USERAGENT;

#define PutHeader(fp, Name) \
	fprintf(fp, "\n%s<em>%s</em>\n", MARGIN_STR, LYEntifyTitle(&buffer, Name));

#define PutCheckBox(fp, Name, Value, disable) \
	fprintf(fp,\
	"<input type=\"checkbox\" name=\"%s\" %s %s>\n",\
		Name, Value ? "checked" : "", disable_all?disabled_string:disable)

#define PutTextInput(fp, Name, Value, Size, disable) \
	fprintf(fp,\
	"<input size=%d type=\"text\" name=\"%s\" value=\"%s\" %s>\n",\
		(int) Size, Name, Value, disable_all?disabled_string:disable)

#define PutOption(fp, flag, html, name) \
	fprintf(fp,"<option value=\"%s\" %s>%s\n", html, SELECTED(flag), gettext(name))

#define BeginSelect(fp, text) \
	fprintf(fp,"<select name=\"%s\" %s>\n", text, disable_all?disabled_string:"")

#define MaybeSelect(fp, flag, text) \
	fprintf(fp,"<select name=\"%s\" %s>\n", text, disable_all?disabled_string:DISABLED(flag))

#define EndSelect(fp)\
	fprintf(fp,"</select>\n")

static void PutOptValues(FILE *fp, int value,
			 OptValues * table)
{
    while (table->LongName != 0) {
	if (table->HtmlName) {
	    PutOption(fp,
		      value == table->value,
		      table->HtmlName,
		      table->LongName);
	}
	table++;
    }
}

static BOOLEAN GetOptValues(OptValues * table, char *value,
			    int *result)
{
    while (table->LongName != 0) {
	if (table->HtmlName && !strcmp(value, table->HtmlName)) {
	    *result = table->value;
	    return TRUE;
	}
	table++;
    }
    return FALSE;
}

#ifdef USE_COLOR_STYLE
void build_lss_enum(HTList *list)
{
    int count = HTList_count(list);

    FREE(color_style_values);
    if (count != 0) {
	LSS_NAMES *obj;
	int position = 0;

	color_style_values = typecallocn(OptValues, count + 2);

	if (color_style_values == NULL)
	    outofmem(__FILE__, "build_lss_enum");

	color_style_values[position++] = bool_values[0];
	while ((obj = HTList_objectAt(list, position - 1)) != 0) {
	    color_style_values[position].value = position;
	    color_style_values[position].LongName = obj->given;
	    color_style_values[position].HtmlName = obj->given;
	    position++;
	}
    }
    color_style_list = list;
}

/*
 * Find the current lss-file in the list, to get the default value for the
 * form.
 */
static int get_color_style_value(void)
{
    int result = 0;

    if (LYuse_color_style && non_empty(lynx_lss_file)) {
	LSS_NAMES *obj;
	int position = 1;

	while ((obj = HTList_objectAt(color_style_list, position - 1)) != 0) {
	    if (obj->actual != 0 && !strcmp(obj->actual, lynx_lss_file)) {
		result = position;
		break;
	    } else if (!strcmp(obj->given, lynx_lss_file)) {
		result = position;
		break;
	    }
	    ++position;
	}
    }
    return result;
}

/*
 * Return the pathname found in the given list-item.
 */
static char *get_color_style_config(int code)
{
    char *result = 0;

    if (LYuse_color_style) {
	LSS_NAMES *obj;

	if ((obj = HTList_objectAt(color_style_list, code - 1)) != 0) {
	    result = obj->actual;
	}
    }
    return result;
}
#endif

/*
 * Break cgi line into array of pairs of pointers.  Don't bother trying to
 * be efficient.  We're not called all that often.
 * We come in with a string looking like:
 * tag1=value1&tag2=value2&...&tagN=valueN
 * We leave with an array of post_pairs.  The last element in the array
 * will have a tag pointing to NULL.
 * Not pretty, but works.  Hey, if strings can be null terminate arrays...
 */
static PostPair *break_data(bstring *data)
{
    char *p;
    PostPair *q = NULL;
    int count = 0;

    if (isBEmpty(data))
	return NULL;

    p = BStrData(data);
    CTRACE((tfp, "break_data %s\n", p));

    q = typecalloc(PostPair);
    if (q == NULL)
	outofmem(__FILE__, "break_data(calloc)");

    assert(q != NULL);

    do {
	/*
	 * First, break up on '&', sliding 'p' on down the line.
	 */
	q[count].value = LYstrsep(&p, "&");
	/*
	 * Then break up on '=', sliding value down, and setting tag.
	 */
	q[count].tag = LYstrsep(&(q[count].value), "=");

	/*
	 * Clean them up a bit, in case user entered a funky string.
	 */
	HTUnEscape(q[count].tag);

	/* In the value field we have '+' instead of ' '. So do a simple
	 * find&replace on the value field before UnEscaping() - SKY
	 */
	{
	    size_t i, len;

	    len = strlen(q[count].value);
	    for (i = 0; i < len; i++) {
		if (q[count].value[i] == '+') {
#ifdef UNIX
		    /*
		     * Allow for special case of options which begin with a "+" on
		     * Unix - TD
		     */
		    if (i > 0
			&& q[count].value[i + 1] == '+'
			&& isalnum(UCH(q[count].value[i + 2]))) {
			q[count].value[i++] = ' ';
			i++;
			continue;
		    }
#endif
		    q[count].value[i] = ' ';
		}
	    }
	}
	HTUnEscape(q[count].value);
	CTRACE((tfp, "...item[%d] tag=%s, value=%s\n",
		count, q[count].tag, q[count].value));

	count++;
	/*
	 * Like I said, screw efficiency.  Sides, realloc is fast on
	 * Linux ;->
	 */
	q = typeRealloc(PostPair, q, (unsigned) (count + 1));
	if (q == NULL)
	    outofmem(__FILE__, "break_data(realloc)");

	assert(q != NULL);

	q[count].tag = NULL;
    } while (p != NULL && p[0] != '\0');
    return q;
}

static BOOL isLynxOptionsPage(const char *address, const char *portion)
{
    BOOL result = FALSE;

    if (!strncasecomp(address, STR_LYNXOPTIONS, LEN_LYNXOPTIONS)) {
	unsigned len = (unsigned) strlen(portion);

	address += LEN_LYNXOPTIONS;
	if (!strncasecomp(address, portion, (int) len)
	    && (address[len] == '\0' || LYIsHtmlSep(address[len]))) {
	    result = TRUE;
	}
    }
    return result;
}

static int gen_options(char **newfile);

/*
 * Handle options from the pseudo-post.  I think we really only need
 * post_data here, but bring along everything just in case.  It's only a
 * pointer.  MRC
 *
 * Options are processed in order according to gen_options(), we should not
 * depend on it and add boolean flags where the order is essential (save,
 * character sets...)
 *
 * Security:  some options are disabled in gen_options() under certain
 * conditions.  We *should* duplicate the same conditions here in postoptions()
 * to prevent user with a limited access from editing HTML options code
 * manually (e.g., doing 'e'dit in 'o'ptions) and submit it to access the
 * restricted items.  Prevent spoofing attempts from index overrun. - LP
 *
 * Exit status: NULLFILE (reload) or NORMAL (use HText cache).
 *
 * On exit, got the document which was current before the Options menu:
 *
 *   (from cache) nothing changed or no visual effect supposed:
 *             editor name, e-mail, etc.
 *
 *   (reload locally) to see the effect of certain changes:
 *             display_char_set, assume_charset, etc.
 *             (use 'need_reload' flag where necessary).
 *
 *   (reload from remote server and uncache on a proxy)
 *             few options changes should be transferred to remote server:
 *             preferred language, fake browser name, etc.
 *             (use 'need_end_reload' flag).
 */

int postoptions(DocInfo *newdoc)
{
    PostPair *data = 0;
    DocAddress WWWDoc;		/* need on exit */
    int i;
    int code = 0;
    BOOLEAN save_all = FALSE;
    int display_char_set_old = current_char_set;
    int old_media_value = LYAcceptMedia;
    BOOLEAN raw_mode_old = LYRawMode;
    BOOLEAN assume_char_set_changed = FALSE;
    BOOLEAN need_reload = FALSE;
    BOOLEAN need_end_reload = FALSE;

#if defined(USE_SLANG) || defined(COLOR_CURSES)
    int CurrentShowColor = LYShowColor;
#endif
#ifdef USE_DEFAULT_COLORS
    BOOLEAN current_default_colors = LYuse_default_colors;
#endif

    /*-------------------------------------------------
     * kludge a link from mbm_menu, the URL was:
     * "<a href=\"" LYNXOPTIONS_PAGE(MBM_MENU) "\">Goto multi-bookmark menu</a>\n"
     *--------------------------------------------------*/

    if (isLynxOptionsPage(newdoc->address, MBM_LINK)) {
	FREE(newdoc->post_data);
	if (no_bookmark) {
	    HTAlert(BOOKMARK_CHANGE_DISALLOWED);	/* anonymous */
	    return (NULLFILE);
	} else if (dump_output_immediately) {
	    return (NOT_FOUND);
	} else {
	    edit_bookmarks();
	    return (NULLFILE);
	}
    } else if (!isLynxOptionsPage(newdoc->address, "/")) {
	HTAlert(RANDOM_URL_DISALLOWED);
	return NULLFILE;
    }

    data = break_data(newdoc->post_data);

    if (!data) {
	int status;

	/*-------------------------------------------------
	 * kludge gen_options() call:
	 *--------------------------------------------------*/
	status = gen_options(&newdoc->address);
	if (status != NORMAL) {
	    HTAlwaysAlert("Unexpected way of accessing", newdoc->address);
	    FREE(newdoc->address);
	    return (status);
	}

	/* exit to getfile() cycle */
	WWWDoc.address = newdoc->address;
	WWWDoc.post_data = newdoc->post_data;
	WWWDoc.post_content_type = newdoc->post_content_type;
	WWWDoc.bookmark = newdoc->bookmark;
	WWWDoc.isHEAD = newdoc->isHEAD;
	WWWDoc.safe = newdoc->safe;

	if (!HTLoadAbsolute(&WWWDoc))
	    return (NOT_FOUND);
	LYRegisterUIPage(newdoc->address, UIP_OPTIONS_MENU);
#ifdef DIRED_SUPPORT
	lynx_edit_mode = FALSE;
#endif /* DIRED_SUPPORT */
	return (NORMAL);
    }

    if (!LYIsUIPage3(HTLoadedDocumentURL(), UIP_OPTIONS_MENU, 0) &&
	!LYIsUIPage3(HTLoadedDocumentURL(), UIP_VLINKS, 0)) {
	char *buf = NULL;

	/*  We may have been spoofed? */
	HTSprintf0(&buf,
		   gettext("Use %s to invoke the Options menu!"),
		   key_for_func_ext(LYK_OPTIONS, FOR_PANEL));
	HTAlert(buf);
	FREE(buf);
	FREE(data);
	return (NOT_FOUND);
    }

    /*
     * Checkbox will be missing from data if unchecked.
     */
    LYSendUserAgent = FALSE;

    for (i = 0; data[i].tag != NULL; i++) {
	/*
	 * This isn't really for security, but rather for avoiding that the
	 * user may revisit an older instance from the history stack and submit
	 * stuff which accidentally undoes changes that had been done from a
	 * newer instance.  - kw
	 */
	if (!strcmp(data[i].tag, secure_string)) {
	    if (!secure_value || strcmp(data[i].value, secure_value)) {
		char *buf = NULL;

		/*
		 * We probably came from an older instance of the Options
		 * page that had been on the history stack. - kw
		 */
		HTSprintf0(&buf,
			   gettext("Use %s to invoke the Options menu!"),
			   key_for_func_ext(LYK_OPTIONS, FOR_PANEL));
		HTAlert(buf);
		FREE(data);
		return (NULLFILE);
	    }
	    FREE(secure_value);
	}

	/* Save options */
	if (!strcmp(data[i].tag, save_options_string) && (!no_option_save)) {
	    save_all = TRUE;
	}

	/* Cookies: SELECT */
	if (!strcmp(data[i].tag, cookies_string)) {
	    if (!strcmp(data[i].value, cookies_ignore_all_string)) {
		LYSetCookies = FALSE;
	    } else if (!strcmp(data[i].value, cookies_up_to_user_string)) {
		LYSetCookies = TRUE;
		LYAcceptAllCookies = FALSE;
	    } else if (!strcmp(data[i].value, cookies_accept_all_string)) {
		LYSetCookies = TRUE;
		LYAcceptAllCookies = TRUE;
	    }
	}

	/* X Display: INPUT */
	if (!strcmp(data[i].tag, x_display_string)) {
	    LYsetXDisplay(data[i].value);
	    validate_x_display();
	    summarize_x_display(data[i].value);
	}

	/* Editor: INPUT */
	if (!strcmp(data[i].tag, editor_string)) {
	    FREE(editor);
	    StrAllocCopy(editor, data[i].value);
	}

	/* Emacs keys: ON/OFF */
	if (!strcmp(data[i].tag, emacs_keys_string)
	    && GetOptValues(bool_values, data[i].value, &code)) {
	    if ((emacs_keys = (BOOLEAN) code) != FALSE) {
		set_emacs_keys();
	    } else {
		reset_emacs_keys();
	    }
	}

	/* Execution links: SELECT */
#if defined(ENABLE_OPTS_CHANGE_EXEC) && (defined(EXEC_LINKS) || defined(EXEC_SCRIPTS))
	if (!strcmp(data[i].tag, exec_links_string)
	    && GetOptValues(exec_links_values, data[i].value, &code)) {
#ifndef NEVER_ALLOW_REMOTE_EXEC
	    local_exec = (BOOLEAN) (code == EXEC_ALWAYS);
#endif /* !NEVER_ALLOW_REMOTE_EXEC */
	    local_exec_on_local_files = (BOOLEAN) (code == EXEC_LOCAL);
	}
#endif /* ENABLE_OPTS_CHANGE_EXEC */

	/* Keypad Mode: SELECT */
	if (!strcmp(data[i].tag, keypad_mode_string)) {
	    int newval = 0;

	    if (GetOptValues(keypad_mode_values, data[i].value, &newval)
		&& keypad_mode != newval) {
		keypad_mode = newval;
		need_reload = TRUE;
		if (keypad_mode == NUMBERS_AS_ARROWS) {
		    set_numbers_as_arrows();
		} else {
		    reset_numbers_as_arrows();
		}
	    }
	}

	/* Line edit style: SELECT */
	if (!strcmp(data[i].tag, lineedit_mode_string)) {
	    int newval = atoi(data[i].value);
	    int j;

	    /* prevent spoofing attempt */
	    for (j = 0; LYEditorNames[j]; j++) {
		if (j == newval)
		    current_lineedit = newval;
	    }
	}
#ifdef EXP_KEYBOARD_LAYOUT
	/* Keyboard layout: SELECT */
	if (!strcmp(data[i].tag, kblayout_string)) {
	    int newval = atoi(data[i].value);
	    int j;

	    /* prevent spoofing attempt */
	    for (j = 0; LYKbLayoutNames[j]; j++) {
		if (j == newval)
		    current_layout = newval;
	    }
	}
#endif /* EXP_KEYBOARD_LAYOUT */

	/* Mail Address: INPUT */
	if (!strcmp(data[i].tag, mail_address_string)) {
	    FREE(personal_mail_address);
	    StrAllocCopy(personal_mail_address, data[i].value);
	}
#ifndef NO_ANONYMOUS_EMAIL
	/* Personal Name: INPUT */
	if (!strcmp(data[i].tag, personal_name_string)) {
	    FREE(personal_mail_name);
	    StrAllocCopy(personal_mail_name, data[i].value);
	}
#endif

	/* Anonymous FTP Password: INPUT */
#ifndef DISABLE_FTP
	if (!strcmp(data[i].tag, anonftp_password_string)) {
	    FREE(anonftp_password);
	    StrAllocCopy(anonftp_password, data[i].value);
	}
#endif

	/* Search Type: SELECT */
	if (!strcmp(data[i].tag, search_type_string)
	    && GetOptValues(search_type_values, data[i].value, &code)) {
	    LYcase_sensitive = (BOOLEAN) code;
	}

	/* HTML error tolerance: SELECT */
	if (!strcmp(data[i].tag, DTD_recovery_string)
	    && GetOptValues(DTD_type_values, data[i].value, &code)) {
	    if (Old_DTD != code) {
		Old_DTD = code;
		HTSwitchDTD(!Old_DTD);
		need_reload = TRUE;
	    }
	}

	/* Bad HTML warnings: SELECT */
	if (!strcmp(data[i].tag, bad_html_string)
	    && GetOptValues(bad_html_values, data[i].value, &code)) {
	    cfg_bad_html = code;
	}

	/* Select Popups: ON/OFF */
	if (!strcmp(data[i].tag, select_popups_string)
	    && GetOptValues(bool_values, data[i].value, &code)) {
	    LYSelectPopups = (BOOLEAN) code;
	}
#if defined(USE_SLANG) || defined(COLOR_CURSES)
	/* Show Color: SELECT */
	if (!strcmp(data[i].tag, show_color_string)
	    && GetOptValues(show_color_values, data[i].value,
			    &LYChosenShowColor)) {
	    if (can_do_colors)
		LYShowColor = LYChosenShowColor;
	    if (CurrentShowColor != LYShowColor) {
		lynx_force_repaint();
	    }
#ifdef USE_SLANG
	    SLtt_Use_Ansi_Colors = (LYShowColor > SHOW_COLOR_OFF ? TRUE : FALSE);
#endif
	}
#endif /* USE_SLANG || COLOR_CURSES */

#ifdef USE_COLOR_STYLE
	/* Color Style: ON/OFF */
	if (!strcmp(data[i].tag, color_style_string)
	    && GetOptValues(color_style_values, data[i].value, &code)) {
	    if (code) {
		LYuse_color_style = TRUE;
		StrAllocCopy(lynx_lss_file, get_color_style_config(code));
		reinit_color_styles();
	    } else {
		LYuse_color_style = FALSE;
	    }
	    update_color_style();
	    lynx_force_repaint();
	}
#endif

#ifdef USE_DEFAULT_COLORS
	/* Default Colors: ON/OFF */
	if (!strcmp(data[i].tag, default_colors_string)
	    && GetOptValues(bool_values, data[i].value, &code)) {
	    LYuse_default_colors = (BOOLEAN) code;
	    if (current_default_colors != LYuse_default_colors) {
		CTRACE((tfp, "default_colors changed, updating colors...\n"));
		if (has_colors()) {
		    if (LYuse_default_colors) {
			use_default_colors();
		    } else {
			restart_curses();
		    }
		    update_default_colors();
		    lynx_force_repaint();
		}
	    }
	}
#endif

	/* Show Cursor: ON/OFF */
	if (!strcmp(data[i].tag, show_cursor_string)
	    && GetOptValues(bool_values, data[i].value, &code)) {
	    LYShowCursor = (BOOLEAN) code;
	}

	/* Underline links: ON/OFF */
	if (!strcmp(data[i].tag, underline_links_string)
	    && GetOptValues(bool_values, data[i].value, &code)) {
	    LYUnderlineLinks = (BOOLEAN) code;
	}
#ifdef USE_SCROLLBAR
	/* Show Scrollbar: ON/OFF */
	if (!strcmp(data[i].tag, show_scrollbar_string)
	    && GetOptValues(bool_values, data[i].value, &code)) {
	    LYShowScrollbar = (BOOLEAN) code;
	    need_reload = TRUE;
	}
#endif

	/* Cookie Prompting: SELECT */
	if (!strcmp(data[i].tag, cookie_prompt_string))
	    GetOptValues(prompt_values, data[i].value, &cookie_noprompt);

#ifdef USE_SSL
	/* SSL Prompting: SELECT */
	if (!strcmp(data[i].tag, ssl_prompt_string))
	    GetOptValues(prompt_values, data[i].value, &ssl_noprompt);
#endif

	/* User Mode: SELECT */
	if (!strcmp(data[i].tag, user_mode_string)
	    && GetOptValues(user_mode_values, data[i].value, &user_mode)) {
	    LYSetDisplayLines();
	}

	/* Type of visited pages page: SELECT */
	if (!strcmp(data[i].tag, visited_links_string))
	    GetOptValues(visited_links_values, data[i].value, &Visited_Links_As);

	/* Show Images: SELECT */
	if (!strcmp(data[i].tag, images_string)) {
	    if (!strcmp(data[i].value, images_ignore_all_string)
		&& !(pseudo_inline_alts == FALSE && clickable_images == FALSE)) {
		pseudo_inline_alts = FALSE;
		clickable_images = FALSE;
		need_reload = TRUE;
	    } else if (!strcmp(data[i].value, images_use_label_string)
		       && !(pseudo_inline_alts == TRUE && clickable_images == FALSE)) {
		pseudo_inline_alts = TRUE;
		clickable_images = FALSE;
		need_reload = TRUE;
	    } else if (!strcmp(data[i].value, images_use_links_string)
		       && !(clickable_images == TRUE)) {
		clickable_images = TRUE;
		need_reload = TRUE;
	    }
	}

	/* Verbose Images: ON/OFF */
	if (!strcmp(data[i].tag, verbose_images_string)
	    && GetOptValues(verbose_images_type_values, data[i].value, &code)) {
	    if (verbose_img != code) {
		verbose_img = (BOOLEAN) code;
		need_reload = TRUE;
	    }
	}

	/* VI Keys: ON/OFF */
	if (!strcmp(data[i].tag, vi_keys_string)
	    && GetOptValues(bool_values, data[i].value, &code)) {
	    if ((vi_keys = (BOOLEAN) code) != FALSE) {
		set_vi_keys();
	    } else {
		reset_vi_keys();
	    }
	}

	/* Bookmarks File Menu: SELECT */
	if (!strcmp(data[i].tag, mbm_string) && (!LYMBMBlocked)) {
	    GetOptValues(mbm_values, data[i].value, &LYMultiBookmarks);
	}

	/* Default Bookmarks filename: INPUT */
	if (!strcmp(data[i].tag, single_bookmark_string) && (!no_bookmark)) {
	    if (strcmp(data[i].value, "")) {
		FREE(bookmark_page);
		StrAllocCopy(bookmark_page, data[i].value);
	    }
	}
#ifdef USE_SESSIONS
	/* Auto Session: ON/OFF */
	if (!strcmp(data[i].tag, auto_session_string)
	    && GetOptValues(bool_values, data[i].value, &code)) {
	    LYAutoSession = (BOOLEAN) code;
	}

	/* Default Session filename: INPUT */
	if (!strcmp(data[i].tag, single_session_string)) {
	    if (strcmp(data[i].value, "")) {
		FREE(LYSessionFile);
		StrAllocCopy(LYSessionFile, data[i].value);
	    }
	}
#endif

	/* Assume Character Set: SELECT */
	if (!strcmp(data[i].tag, assume_char_set_string)) {
	    int newval = UCGetLYhndl_byMIME(data[i].value);

	    if (newval >= 0
		&& ((raw_mode_old &&
		     newval != safeUCGetLYhndl_byMIME(UCAssume_MIMEcharset))
		    || (!raw_mode_old &&
			newval != UCLYhndl_for_unspec)
		)) {

		UCLYhndl_for_unspec = newval;
		StrAllocCopy(UCAssume_MIMEcharset, data[i].value);
		assume_char_set_changed = TRUE;
	    }
	}
#ifdef USE_LOCALE_CHARSET
	/* Use locale-based character set: ON/OFF */
	if (!strcmp(data[i].tag, locale_charset_string)
	    && GetOptValues(bool_values, data[i].value, &code)) {
	    LYLocaleCharset = (BOOLEAN) code;
	}
#endif
	/* Use HTML5 charset replacements: ON/OFF */
	if (!strcmp(data[i].tag, html5_charsets_string)
	    && GetOptValues(bool_values, data[i].value, &code)) {
	    html5_charsets = (BOOLEAN) code;
	    assume_char_set_changed = TRUE;
	}

	/* Display Character Set: SELECT */
	if (!strcmp(data[i].tag, display_char_set_string)) {
	    int newval = atoi(data[i].value);
	    int j;

	    /* prevent spoofing attempt */
	    for (j = 0; LYchar_set_names[j]; j++) {
		if (j == newval)
		    current_char_set = newval;
	    }
	}

	/* Raw Mode: ON/OFF */
	if (!strcmp(data[i].tag, raw_mode_string)
	    && GetOptValues(bool_values, data[i].value, &code)) {
	    LYRawMode = (BOOLEAN) code;
	}
#ifndef DISABLE_FTP
	/*
	 * passive ftp: ON/OFF
	 */
	if (!strcmp(data[i].tag, passive_ftp_string)) {
	    ftp_passive = (BOOLEAN) code;
	}

	/*
	 * ftp sort: SELECT
	 */
	if (!strcmp(data[i].tag, ftp_sort_string)) {
	    GetOptValues(ftp_sort_values, data[i].value, &HTfileSortMethod);
	}
#endif /* DISABLE_FTP */

#ifdef DIRED_SUPPORT
	/* Local Directory Style: SELECT */
	if (!strcmp(data[i].tag, dired_list_string)) {
	    GetOptValues(dired_list_values, data[i].value, &dir_list_style);
	}
#ifdef LONG_LIST
	/* Local Directory Order: SELECT */
	if (!strcmp(data[i].tag, dired_sort_string)) {
	    GetOptValues(dired_sort_values, data[i].value, &dir_list_order);
	}
#endif /* LONG_LIST */
#endif /* DIRED_SUPPORT */

	/* Show dot files: ON/OFF */
	if (!strcmp(data[i].tag, show_dotfiles_string) && (!no_dotfiles)
	    && GetOptValues(bool_values, data[i].value, &code)) {
	    show_dotfiles = (BOOLEAN) code;
	}

	/* Pause when showing messages: ON/OFF */
	if (!strcmp(data[i].tag, no_pause_string)
	    && GetOptValues(bool_values, data[i].value, &code)) {
	    no_pause = (BOOLEAN) !code;
	}
#ifdef USE_READPROGRESS
	/* Show Transfer Rate: enumerated value */
	if (!strcmp(data[i].tag, show_rate_string)
	    && GetOptValues(rate_values, data[i].value, &code)) {
	    LYTransferRate = code;
	}
#endif /* USE_READPROGRESS */

	/* Preferred Media Type: SELECT */
	if (!strcmp(data[i].tag, preferred_media_string)) {
	    GetOptValues(media_values, data[i].value, &LYAcceptMedia);
	}

	/* Preferred Encoding: SELECT */
	if (!strcmp(data[i].tag, preferred_encoding_string)) {
	    GetOptValues(encoding_values, data[i].value, &LYAcceptEncoding);
	}

	/* Preferred Document Character Set: INPUT */
	if (!strcmp(data[i].tag, preferred_doc_char_string)) {
	    if (strcmp(pref_charset, data[i].value)) {
		FREE(pref_charset);
		StrAllocCopy(pref_charset, data[i].value);
		need_end_reload = TRUE;
	    }
	}

	/* Preferred Document Language: INPUT */
	if (!strcmp(data[i].tag, preferred_doc_lang_string)) {
	    if (strcmp(language, data[i].value)) {
		FREE(language);
		StrAllocCopy(language, data[i].value);
		need_end_reload = TRUE;
	    }
	}

	/* Send User Agent: INPUT */
	if (!strcmp(data[i].tag, send_user_agent_string)) {
	    LYSendUserAgent = (BOOLEAN) !strcasecomp(data[i].value, "ON");
	}

	/* User Agent: INPUT */
	if (!strcmp(data[i].tag, user_agent_string) && (!no_useragent)) {
	    if (strcmp(LYUserAgent, data[i].value)) {
		need_end_reload = TRUE;
		FREE(LYUserAgent);
		/* ignore Copyright warning ? */
		StrAllocCopy(LYUserAgent,
			     *(data[i].value)
			     ? data[i].value
			     : LYUserAgentDefault);
		if (!LYCheckUserAgent()) {
		    HTAlert(UA_PLEASE_USE_LYNX);
		}
	    }
	}
    }				/* end of loop */

    /*
     * Process the flags:
     */
#ifdef USE_LOCALE_CHARSET
    LYFindLocaleCharset();
#endif

    if (old_media_value != LYAcceptMedia)
	HTFilterPresentations();

    if (display_char_set_old != current_char_set ||
	raw_mode_old != LYRawMode ||
	assume_char_set_changed) {
	/*
	 * charset settings: the order is essential here.
	 */
	if (display_char_set_old != current_char_set) {
	    /*
	     * Set the LYUseDefaultRawMode value and character handling if
	     * LYRawMode was changed.  - FM
	     */
	    LYUseDefaultRawMode = TRUE;
	    HTMLUseCharacterSet(current_char_set);
#ifdef CAN_SWITCH_DISPLAY_CHARSET
	    /* Deduce whether the user wants autoswitch: */
	    switch_display_charsets =
		(current_char_set == auto_display_charset
		 || current_char_set == auto_other_display_charset);
#endif
	}
	if (assume_char_set_changed && HTCJK != JAPANESE) {
	    LYRawMode = (BOOLEAN) (UCLYhndl_for_unspec == current_char_set);
	}
	if (raw_mode_old != LYRawMode || assume_char_set_changed) {
	    /*
	     * Set the raw 8-bit or CJK mode defaults and character set if
	     * changed.  - FM
	     */
	    HTMLSetUseDefaultRawMode(current_char_set, LYRawMode);
	    HTMLSetCharacterHandling(current_char_set);
	}
	need_reload = TRUE;
    }
    /* end of charset settings */
    /*
     * FIXME: Golly gee, we need to write all of this out now, don't we?
     */
    BStrFree(newdoc->post_data);
    FREE(data);
    if (save_all) {
	HTInfoMsg(SAVING_OPTIONS);
	LYrcShowColor = LYChosenShowColor;
	if (save_rc(NULL)) {
	    HTInfoMsg(OPTIONS_SAVED);
	} else {
	    HTAlert(OPTIONS_NOT_SAVED);
	}
    }

    /*
     * Exit:  working around the previous document.  Being out of
     * mainloop()/getfile() cycle, do things manually.
     */
    CTRACE((tfp, "\nLYOptions.c/postoptions(): exiting...\n"));
    CTRACE((tfp, "                            need_reload = %s\n",
	    need_reload ? "TRUE" : "FALSE"));
    CTRACE((tfp, "                            need_end_reload = %s\n",
	    need_end_reload ? "TRUE" : "FALSE"));

    /*  Options menu was pushed before postoptions(), so pop-up. */
    LYpop(newdoc);
    WWWDoc.address = newdoc->address;
    WWWDoc.post_data = newdoc->post_data;
    WWWDoc.post_content_type = newdoc->post_content_type;
    WWWDoc.bookmark = newdoc->bookmark;
    WWWDoc.isHEAD = newdoc->isHEAD;
    WWWDoc.safe = newdoc->safe;
    LYforce_no_cache = FALSE;	/* ! */
    LYoverride_no_cache = TRUE;	/* ! */
    /*
     * Working out of getfile() cycle we reset *no_cache manually here so
     * HTLoadAbsolute() will return "Document already in memory":  it was
     * forced reloading Options Menu again without this (overhead).
     *
     * Probably *no_cache was set in a wrong position because of
     * the internal page...
     */
    if (!HTLoadAbsolute(&WWWDoc))
	return (NOT_FOUND);

    HTuncache_current_document();	/* will never use again */

    /*
     * Return to previous doc, not to options menu!  Reload the document we had
     * before the options menu but uncache only when necessary (Hurrah, user!):
     */
    LYpop(newdoc);
    WWWDoc.address = newdoc->address;
    WWWDoc.post_data = newdoc->post_data;
    WWWDoc.post_content_type = newdoc->post_content_type;
    WWWDoc.bookmark = newdoc->bookmark;
    WWWDoc.isHEAD = newdoc->isHEAD;
    WWWDoc.safe = newdoc->safe;
    LYforce_no_cache = FALSE;	/* see below */
    LYoverride_no_cache = TRUE;	/* see below */
    /*
     * Re-setting of *no_cache is probably not required here but this is a
     * guarantee against _double_ reloading over the net in case prev document
     * has its own "no cache" attribute and options menu set "need_reload"
     * also.  Force this HTLoadAbsolute() to return "Document already in
     * memory".
     */
    if (!HTLoadAbsolute(&WWWDoc))
	return (NOT_FOUND);

    /*
     * Now most interesting part: reload document when necessary.
     * **********************************************************
     */

    reloading = FALSE;		/* set manually */
    /* force end-to-end reload from remote server if change LYUserAgent or
     * language or pref_charset (marked by need_end_reload flag above), from
     * old-style LYK_OPTIONS (mainloop):
     */
    if ((need_end_reload == TRUE &&
	 (StrNCmp(newdoc->address, "http", 4) == 0 ||
	  isLYNXCGI(newdoc->address) == 0))) {
	/*
	 * An option has changed which may influence content negotiation, and
	 * the resource is from a http or https or lynxcgi URL (the only
	 * protocols which currently do anything with this information).  Set
	 * reloading = TRUE so that proxy caches will be flushed, which is
	 * necessary until the time when all proxies understand HTTP 1.1 Vary: 
	 * and all Servers properly use it...  Treat like case LYK_RELOAD (see
	 * comments there).  - KW
	 */
	reloading = TRUE;	/* global flag */
	need_reload = TRUE;	/* this was probably already TRUE, don't worry */
    }

    if (need_reload == FALSE) {
	/*  no uncache, already loaded */
	CTRACE((tfp, "LYOptions.c/postoptions(): now really exit.\n\n"));
	return (NORMAL);
    } else {
	/*  update HText cache */

	/*
	 * see LYK_RELOAD & LYK_OPTIONS in mainloop for details...
	 */
	if (HTisDocumentSource()) {
	    srcmode_for_next_retrieval(1);
	}
#ifdef USE_SOURCE_CACHE
	if (reloading == FALSE) {
	    /* one more attempt to be smart enough: */
	    if (HTcan_reparse_document()) {
		if (!HTreparse_document())
		    srcmode_for_next_retrieval(0);
		CTRACE((tfp, "LYOptions.c/postoptions(): now really exit.\n\n"));
		return (NORMAL);
	    }
	}
#endif
	if (newdoc->post_data != NULL && !newdoc->safe &&
	    confirm_post_resub(newdoc->address, newdoc->title, 2, 1) == FALSE) {
	    HTInfoMsg(WILL_NOT_RELOAD_DOC);
	    if (HTisDocumentSource()) {
		srcmode_for_next_retrieval(0);
	    }
	    return (NORMAL);
	}

	HEAD_request = HTLoadedDocumentIsHEAD();
	/*  uncache and load again */
	HTuncache_current_document();
	LYpush(newdoc, FALSE);
	CTRACE((tfp, "LYOptions.c/postoptions(): now really exit.\n\n"));
	return (NULLFILE);
    }

    /******** Done! **************************************************/
}

static char *NewSecureValue(void)
{
    static char oops[] = "?";

    FREE(secure_value);
    if ((secure_value = typeMallocn(char, 80)) != 0) {
#if defined(RAND_MAX)
	long key = lynx_rand();

#else
	long key = (long) secure_value + (long) time(0);
#endif
	sprintf(secure_value, "%ld", key);
	return secure_value;
    }
    return oops;
}

#define LABEL_LEN 33

/*
 * Note: the 'value' we are passing here is a local copy of the "same" string
 * as is used in LYrcFile.c to index the savable options.
 */
static void PutLabel(FILE *fp, const char *name,
		     const char *value)
{
    int have = (int) strlen(name);
    int want = LABEL_LEN;
    int need = LYstrExtent(name, have, want);
    char *buffer = NULL;

    fprintf(fp, "%s%s", MARGIN_STR, LYEntifyTitle(&buffer, name));

    if (will_save_rc(value) && !no_option_save) {
	while (need++ < want)
	    fprintf(fp, "&nbsp;");
    } else {
	want -= 3;
	if (need < want) {
	    fprintf(fp, "&nbsp;");
	    ++need;
	}
	fprintf(fp, "(!)");
	while (need++ < want) {
	    fprintf(fp, "&nbsp;");
	}
    }
    fprintf(fp, ": ");
    FREE(buffer);
}

/*
 * For given a list of the .lynxrc names for boolean flags that make up a
 * composite setting, check if any are not writable for the .lynxrc file.  If
 * so, return that name, so the subsequence will_save_rc() check in PutLabel()
 * will flag the composite as not-saved.
 */
static const char *check_if_write_lynxrc(STRING2PTR table)
{
    int n;
    const char *result = NULL;

    for (n = 0; table[n] != 0; ++n) {
	result = table[n];
	if (!will_save_rc(result))
	    break;
    }
    return result;
}

/*
 * The options menu treats "Cookies" as a single enumeration, but it is read
 * from lynx.cfg (and perhaps .lynxrc) as a set of booleans.  Check if any are
 * not writable to .lynxrc, so we can show the user. 
 */
static const char *will_save_cookies(void)
{
    static const char *table[] =
    {
	RC_SET_COOKIES,		/* LYSetCookies */
	RC_ACCEPT_ALL_COOKIES,	/* LYAcceptAllCookies */
	NULL
    };

    return check_if_write_lynxrc(table);
}

/*
 * The options menu treats "Show images" as a single enumeration, but it is
 * read from lynx.cfg (and perhaps .lynxrc) as a set of booleans.  Check if any
 * are not writable to .lynxrc, so we can show the user. 
 */
static const char *will_save_images(void)
{
    static const char *table[] =
    {
	RC_MAKE_PSEUDO_ALTS_FOR_INLINES,	/* pseudo_inline_alts */
	RC_MAKE_LINKS_FOR_ALL_IMAGES,	/* clickable_images */
	NULL
    };

    return check_if_write_lynxrc(table);
}

/*
 * The visited-links menu is used from the visited-links page as well as the
 * options page.
 */
void LYMenuVisitedLinks(FILE *fp0, int disable_all)
{
    BeginSelect(fp0, visited_links_string);
    PutOptValues(fp0, Visited_Links_As, visited_links_values);
    EndSelect(fp0);
}

/*
 * Okay, someone wants to change options.  So, let's gen up a form for them
 * and pass it around.  Gor, this is ugly.  Be a lot easier in Bourne with
 * "here" documents.  :->
 * Basic Strategy:  For each option, throw up the appropriate type of
 * control, giving defaults as appropriate.  If nothing else, we're
 * probably going to test every control there is.  MRC
 *
 * This function is synchronized with postoptions().  Read the comments in
 * postoptions() header if you change something in gen_options().
 */
static int gen_options(char **newfile)
{
    static char tempfile[LY_MAXPATH] = "\0";

    int i;
    char *buffer = NULL;
    BOOLEAN disable_all = FALSE;
    FILE *fp0;
    size_t cset_len = 0;
    size_t text_len = (size_t) ((LYcolLimit > 45)
				? LYcolLimit - (LABEL_LEN + 2 + MARGIN_LEN)
				: 7);	/* cf: PutLabel */

    if ((fp0 = InternalPageFP(tempfile, TRUE)) == 0)
	return (NOT_FOUND);

    LYLocalFileToURL(newfile, tempfile);

    /* This should not be needed if we regenerate the temp file every time with
     * a new name, which just happened above in the case
     * LYReuseTempfiles==FALSE.  Even for LYReuseTempfiles=TRUE, code at the
     * end of postoptions() may remove an older cached version from memory if
     * that version of the page was left by submitting changes.  - kw
     * 1999-11-27
     * If access to the actual file via getfile() later fails (maybe because of
     * some restrictions), mainloop may leave this flag on after popping the
     * previous doc which is then unnecessarily reloaded.  But I changed
     * mainloop to reset the flag.  - kw 1999-05-24
     */
    LYforce_no_cache = TRUE;

    /*
     * Without LYUseFormsOptions set we should maybe not even get here.
     * However, it's possible we do; disable the form in that case. - kw
     */
#ifndef NO_OPTION_MENU
    if (!LYUseFormsOptions)
	disable_all = TRUE;
#endif

    BeginInternalPage(fp0, OPTIONS_TITLE, NULL);	/* help link below */

    /*
     * I do C, not HTML.  Feel free to pretty this up.
     */
    fprintf(fp0, "<form action=\"%s\" method=\"post\">\n", STR_LYNXOPTIONS);
    /*
     * use following with some sort of one shot secret key akin to NCSA
     * (or was it CUTE?) telnet one shot password to allow ftp to self.
     * to prevent spoofing.
     */
    fprintf(fp0, "<input name=\"%s\" type=\"hidden\" value=\"%s\">\n",
	    secure_string, NewSecureValue());

    /*
     * visible text begins here
     */

    /* Submit/Reset/Help */
    fprintf(fp0, "<p align=center>\n");
    if (!disable_all) {
	fprintf(fp0,
		"<input type=\"submit\" value=\"%s\"> - \n",
		LYEntifyValue(&buffer, ACCEPT_CHANGES));
	fprintf(fp0,
		"<input type=\"reset\" value=\"%s\"> - \n",
		LYEntifyValue(&buffer, RESET_CHANGES));
	fprintf(fp0,
		"%s - \n",
		LYEntifyTitle(&buffer, CANCEL_CHANGES));
    }
    fprintf(fp0, "<a href=\"%s%s\">%s</a>\n",
	    helpfilepath, LYEntifyTitle(&buffer, OPTIONS_HELP), TO_HELP);

    /* Save options */
    if (!no_option_save) {
	if (!disable_all) {
	    fprintf(fp0, "<p align=center>%s: ", LYEntifyTitle(&buffer, SAVE_OPTIONS));
	    fprintf(fp0, "<input type=\"checkbox\" name=\"%s\">\n",
		    save_options_string);
	}
	fprintf(fp0, "<br>%s\n",
		LYEntifyTitle(&buffer,
			      gettext("(options marked with (!) will not be saved)")));
    }

    /*
     * preformatted text follows
     */
    fprintf(fp0, "<pre>\n");

    PutHeader(fp0, gettext("General Preferences"));
    /*****************************************************************/

    /* User Mode: SELECT */
    PutLabel(fp0, gettext("User mode"), user_mode_string);
    BeginSelect(fp0, user_mode_string);
    PutOptValues(fp0, user_mode, user_mode_values);
    EndSelect(fp0);

    /* Editor: INPUT */
    PutLabel(fp0, gettext("Editor"), editor_string);
    PutTextInput(fp0, editor_string, NonNull(editor), text_len,
		 DISABLED(no_editor || system_editor));

    /* Search Type: SELECT */
    PutLabel(fp0, gettext("Type of Search"), search_type_string);
    BeginSelect(fp0, search_type_string);
    PutOptValues(fp0, LYcase_sensitive, search_type_values);
    EndSelect(fp0);

    PutHeader(fp0, gettext("Security and Privacy"));
    /*****************************************************************/

    /* Cookies: SELECT */
    PutLabel(fp0, gettext("Cookies"), will_save_cookies());
    BeginSelect(fp0, cookies_string);
    PutOption(fp0, !LYSetCookies,
	      cookies_ignore_all_string,
	      cookies_ignore_all_string);
    PutOption(fp0, LYSetCookies && !LYAcceptAllCookies,
	      cookies_up_to_user_string,
	      cookies_up_to_user_string);
    PutOption(fp0, LYSetCookies && LYAcceptAllCookies,
	      cookies_accept_all_string,
	      cookies_accept_all_string);
    EndSelect(fp0);

    /* Cookie Prompting: SELECT */
    PutLabel(fp0, gettext("Invalid-Cookie Prompting"), cookie_prompt_string);
    BeginSelect(fp0, cookie_prompt_string);
    PutOptValues(fp0, cookie_noprompt, prompt_values);
    EndSelect(fp0);

#ifdef USE_SSL
    /* SSL Prompting: SELECT */
    PutLabel(fp0, gettext("SSL Prompting"), ssl_prompt_string);
    BeginSelect(fp0, ssl_prompt_string);
    PutOptValues(fp0, ssl_noprompt, prompt_values);
    EndSelect(fp0);
#endif

    PutHeader(fp0, gettext("Keyboard Input"));
    /*****************************************************************/

    /* Keypad Mode: SELECT */
    PutLabel(fp0, gettext("Keypad mode"), keypad_mode_string);
    BeginSelect(fp0, keypad_mode_string);
    PutOptValues(fp0, keypad_mode, keypad_mode_values);
    EndSelect(fp0);

    /* Emacs keys: ON/OFF */
    PutLabel(fp0, gettext("Emacs keys"), emacs_keys_string);
    BeginSelect(fp0, emacs_keys_string);
    PutOptValues(fp0, emacs_keys, bool_values);
    EndSelect(fp0);

    /* VI Keys: ON/OFF */
    PutLabel(fp0, gettext("VI keys"), vi_keys_string);
    BeginSelect(fp0, vi_keys_string);
    PutOptValues(fp0, vi_keys, bool_values);
    EndSelect(fp0);

    /* Line edit style: SELECT */
    if (LYEditorNames[1]) {	/* well, at least 2 line edit styles available */
	PutLabel(fp0, gettext("Line edit style"), lineedit_mode_string);
	BeginSelect(fp0, lineedit_mode_string);
	for (i = 0; LYEditorNames[i]; i++) {
	    char temp[16];

	    sprintf(temp, "%d", i);
	    PutOption(fp0, i == current_lineedit, temp, LYEditorNames[i]);
	}
	EndSelect(fp0);
    }
#ifdef EXP_KEYBOARD_LAYOUT
    /* Keyboard layout: SELECT */
    PutLabel(fp0, gettext("Keyboard layout"), kblayout_string);
    BeginSelect(fp0, kblayout_string);
    for (i = 0; LYKbLayoutNames[i]; i++) {
	char temp[16];

	sprintf(temp, "%d", i);
	PutOption(fp0, i == current_layout, temp, LYKbLayoutNames[i]);
    }
    EndSelect(fp0);
#endif /* EXP_KEYBOARD_LAYOUT */

    /*
     * Display and Character Set
     */
    PutHeader(fp0, gettext("Display and Character Set"));
    /*****************************************************************/

#ifdef USE_LOCALE_CHARSET
    /* Use locale-based character set: ON/OFF */
    PutLabel(fp0, gettext("Use locale-based character set"), locale_charset_string);
    BeginSelect(fp0, locale_charset_string);
    PutOptValues(fp0, LYLocaleCharset, bool_values);
    EndSelect(fp0);
#else
#define LYLocaleCharset FALSE
#endif
    PutLabel(fp0, gettext("Use HTML5 charset replacements"), html5_charsets_string);
    BeginSelect(fp0, html5_charsets_string);
    PutOptValues(fp0, html5_charsets, bool_values);
    EndSelect(fp0);

    /* Display Character Set: SELECT */
    PutLabel(fp0, gettext("Display character set"), display_char_set_string);
    MaybeSelect(fp0, LYLocaleCharset, display_char_set_string);
    for (i = 0; LYchar_set_names[i]; i++) {
	char temp[10];
	size_t len = strlen(LYchar_set_names[i]);

	if (len > cset_len)
	    cset_len = len;
	sprintf(temp, "%d", i);
#ifdef USE_CHARSET_CHOICE
	if (!charset_subsets[i].hide_display)
#endif
	    PutOption(fp0, i == current_char_set, temp, LYchar_set_names[i]);
    }
    EndSelect(fp0);

    /* Assume Character Set: SELECT */
    {
	int curval;

	curval = UCLYhndl_for_unspec;

	/*
	 * FIXME: If bogus value in lynx.cfg, then in old way, that is the
	 * string that was displayed.  Now, user will never see that.  Good
	 * or bad?  I don't know.  MRC
	 */
	if (curval == current_char_set) {
	    /* ok, LYRawMode, so use UCAssume_MIMEcharset */
	    curval = safeUCGetLYhndl_byMIME(UCAssume_MIMEcharset);
	}
	PutLabel(fp0, gettext("Assumed document character set"), assume_char_set_string);
	BeginSelect(fp0, assume_char_set_string);
	for (i = 0; i < LYNumCharsets; i++) {
#ifdef USE_CHARSET_CHOICE
	    if (!charset_subsets[i].hide_assumed)
#endif
		PutOption(fp0, i == curval,
			  LYCharSet_UC[i].MIMEname,
			  LYCharSet_UC[i].MIMEname);
	}
	EndSelect(fp0);
    }

    /* Raw Mode: ON/OFF */
    if (LYHaveCJKCharacterSet) {
	/*
	 * Since CJK people hardly mixed with other world
	 * we split the header to make it more readable:
	 * "CJK mode" for CJK display charsets, and "Raw 8-bit" for others.
	 */
	PutLabel(fp0, gettext("CJK mode"), raw_mode_string);
    } else {
	PutLabel(fp0, gettext("Raw 8-bit"), raw_mode_string);
    }

    BeginSelect(fp0, raw_mode_string);
    PutOptValues(fp0, LYRawMode, bool_values);
    EndSelect(fp0);

    /* X Display: INPUT */
    PutLabel(fp0, gettext("X Display"), x_display_string);
    PutTextInput(fp0, x_display_string, NonNull(x_display), text_len, "");

    /*
     * Document Appearance
     */
    PutHeader(fp0, gettext("Document Appearance"));
    /*****************************************************************/

    /* Show Color: SELECT */
#if defined(USE_SLANG) || defined(COLOR_CURSES)
    SetupChosenShowColor();
    PutLabel(fp0, gettext("Show color"), show_color_string);
    if (no_option_save) {
	MaybeSelect(fp0, !can_do_colors, show_color_string);
	if (LYShowColor == SHOW_COLOR_NEVER) {
	    LYShowColor = SHOW_COLOR_OFF;
	} else if (LYShowColor == SHOW_COLOR_ALWAYS) {
	    LYShowColor = SHOW_COLOR_ON;
	}
	PutOptValues(fp0, LYShowColor - SHOW_COLOR_OFF, bool_values);
    } else {
	BeginSelect(fp0, show_color_string);
	if (can_do_colors) {
	    show_color_values[2].HtmlName = on_string;
	    show_color_values[3].LongName = always_string;
	} else {
	    show_color_values[2].HtmlName = NULL;	/* suppress "ON" - kw */
	    show_color_values[3].LongName = "Always try";
	}
	PutOptValues(fp0, LYChosenShowColor, show_color_values);
    }
    EndSelect(fp0);
#endif /* USE_SLANG || COLOR_CURSES */

#ifdef USE_COLOR_STYLE
    /* Color style: ON/OFF */
    PutLabel(fp0, gettext("Color style"), color_style_string);
    BeginSelect(fp0, color_style_string);
    PutOptValues(fp0, get_color_style_value(), color_style_values);
    EndSelect(fp0);
#endif

#ifdef USE_DEFAULT_COLORS
    /* Default colors: ON/OFF */
    if (has_colors()) {
	PutLabel(fp0, gettext("Default colors"), default_colors_string);
	BeginSelect(fp0, default_colors_string);
	PutOptValues(fp0, LYuse_default_colors, bool_values);
	EndSelect(fp0);
    }
#endif

    /* Show cursor: ON/OFF */
    PutLabel(fp0, gettext("Show cursor"), show_cursor_string);
    BeginSelect(fp0, show_cursor_string);
    PutOptValues(fp0, LYShowCursor, bool_values);
    EndSelect(fp0);

    /* Underline links: ON/OFF */
    PutLabel(fp0, gettext("Underline links"), underline_links_string);
    BeginSelect(fp0, underline_links_string);
    PutOptValues(fp0, LYUnderlineLinks, bool_values);
    EndSelect(fp0);

#ifdef USE_SCROLLBAR
    /* Show scrollbar: ON/OFF */
    PutLabel(fp0, gettext("Show scrollbar"), show_scrollbar_string);
    BeginSelect(fp0, show_scrollbar_string);
    PutOptValues(fp0, LYShowScrollbar, bool_values);
    EndSelect(fp0);
#endif

    /* Select Popups: ON/OFF */
    PutLabel(fp0, gettext("Popups for select fields"), select_popups_string);
    BeginSelect(fp0, select_popups_string);
    PutOptValues(fp0, LYSelectPopups, bool_values);
    EndSelect(fp0);

    /* HTML error recovery: SELECT */
    PutLabel(fp0, gettext("HTML error recovery"), DTD_recovery_string);
    BeginSelect(fp0, DTD_recovery_string);
    PutOptValues(fp0, Old_DTD, DTD_type_values);
    EndSelect(fp0);

    /* Bad HTML messages: SELECT */
    PutLabel(fp0, gettext("Bad HTML messages"), bad_html_string);
    BeginSelect(fp0, bad_html_string);
    PutOptValues(fp0, cfg_bad_html, bad_html_values);
    EndSelect(fp0);

    /* Show Images: SELECT */
    PutLabel(fp0, gettext("Show images"), will_save_images());
    BeginSelect(fp0, images_string);
    PutOption(fp0, !pseudo_inline_alts && !clickable_images,
	      images_ignore_all_string,
	      images_ignore_all_string);
    PutOption(fp0, pseudo_inline_alts && !clickable_images,
	      images_use_label_string,
	      images_use_label_string);
    PutOption(fp0, clickable_images,
	      images_use_links_string,
	      images_use_links_string);
    EndSelect(fp0);

    /* Verbose Images: ON/OFF */
    PutLabel(fp0, gettext("Verbose images"), verbose_images_string);
    BeginSelect(fp0, verbose_images_string);
    PutOptValues(fp0, verbose_img, verbose_images_type_values);
    EndSelect(fp0);

    /*
     * Headers Transferred to Remote Servers
     */
    PutHeader(fp0, gettext("Headers Transferred to Remote Servers"));
    /*****************************************************************/

    /* Mail Address: INPUT */
    PutLabel(fp0, gettext("Personal mail address"), mail_address_string);
    PutTextInput(fp0, mail_address_string,
		 NonNull(personal_mail_address), text_len, "");

#ifndef NO_ANONYMOUS_EMAIL
    PutLabel(fp0, gettext("Personal name for mail"), personal_name_string);
    PutTextInput(fp0, personal_name_string,
		 NonNull(personal_mail_name), text_len, "");
#endif

    /* Anonymous FTP Address: INPUT */
#ifndef DISABLE_FTP
    PutLabel(fp0, gettext("Password for anonymous ftp"), anonftp_password_string);
    PutTextInput(fp0, anonftp_password_string,
		 NonNull(anonftp_password), text_len, "");
#endif

    /* Preferred media type: SELECT */
    PutLabel(fp0, gettext("Preferred media type"), preferred_media_string);
    BeginSelect(fp0, preferred_media_string);
    PutOptValues(fp0, LYAcceptMedia, media_values);
    EndSelect(fp0);

    /* Preferred encoding: SELECT */
    PutLabel(fp0, gettext("Preferred encoding"), preferred_encoding_string);
    BeginSelect(fp0, preferred_encoding_string);
    PutOptValues(fp0, LYAcceptEncoding, encoding_values);
    EndSelect(fp0);

    /* Preferred Document Character Set: INPUT */
    PutLabel(fp0, gettext("Preferred document character set"), preferred_doc_char_string);
    PutTextInput(fp0, preferred_doc_char_string,
		 NonNull(pref_charset), cset_len + 2, "");

    /* Preferred Document Language: INPUT */
    PutLabel(fp0, gettext("Preferred document language"), preferred_doc_lang_string);
    PutTextInput(fp0, preferred_doc_lang_string,
		 NonNull(language), cset_len + 2, "");

    /* User Agent: INPUT */
    if (!no_useragent) {
	PutLabel(fp0, gettext("Send User-Agent header"), send_user_agent_string);
	PutCheckBox(fp0, send_user_agent_string, LYSendUserAgent, "");
	PutLabel(fp0, gettext("User-Agent header"), user_agent_string);
	PutTextInput(fp0, user_agent_string,
		     NonNull(LYUserAgent), text_len, "");
    }

    /*
     * Listing and Accessing Files
     */
    PutHeader(fp0, gettext("Listing and Accessing Files"));
    /*****************************************************************/

#ifndef DISABLE_FTP
    /* FTP sort: SELECT */
    PutLabel(fp0, gettext("Use Passive FTP"), passive_ftp_string);
    BeginSelect(fp0, passive_ftp_string);
    PutOptValues(fp0, ftp_passive, bool_values);
    EndSelect(fp0);

    /* FTP sort: SELECT */
    PutLabel(fp0, gettext("FTP sort criteria"), ftp_sort_string);
    BeginSelect(fp0, ftp_sort_string);
    PutOptValues(fp0, HTfileSortMethod, ftp_sort_values);
    EndSelect(fp0);
#endif /* DISABLE_FTP */

#ifdef DIRED_SUPPORT
    /* Local Directory Sort: SELECT */
    PutLabel(fp0, gettext("Local directory sort criteria"), dired_list_string);
    BeginSelect(fp0, dired_list_string);
    PutOptValues(fp0, dir_list_style, dired_list_values);
    EndSelect(fp0);
#ifdef LONG_LIST
    /* Local Directory Order: SELECT */
    PutLabel(fp0, gettext("Local directory sort order"), dired_sort_string);
    BeginSelect(fp0, dired_sort_string);
    PutOptValues(fp0, dir_list_order, dired_sort_values);
    EndSelect(fp0);
#endif /* LONG_LIST */
#endif /* DIRED_SUPPORT */

    /* Show dot files: ON/OFF */
    if (!no_dotfiles) {
	PutLabel(fp0, gettext("Show dot files"), show_dotfiles_string);
	BeginSelect(fp0, show_dotfiles_string);
	PutOptValues(fp0, show_dotfiles, bool_values);
	EndSelect(fp0);
    }

    /* Execution links: SELECT */
#if defined(ENABLE_OPTS_CHANGE_EXEC) && (defined(EXEC_LINKS) || defined(EXEC_SCRIPTS))
    PutLabel(fp0, gettext("Execution links"), exec_links_string);
    BeginSelect(fp0, exec_links_string);
#ifndef NEVER_ALLOW_REMOTE_EXEC
    PutOptValues(fp0, local_exec
		 ? EXEC_ALWAYS
		 : (local_exec_on_local_files
		    ? EXEC_LOCAL
		    : EXEC_NEVER),
		 exec_links_values);
#else
    PutOptValues(fp0, local_exec_on_local_files
		 ? EXEC_LOCAL
		 : EXEC_NEVER,
		 exec_links_values);
#endif /* !NEVER_ALLOW_REMOTE_EXEC */
    EndSelect(fp0);
#endif /* ENABLE_OPTS_CHANGE_EXEC */

    PutLabel(fp0, gettext("Pause when showing message"), no_pause_string);
    BeginSelect(fp0, no_pause_string);
    PutOptValues(fp0, !no_pause, bool_values);
    EndSelect(fp0);

#ifdef USE_READPROGRESS
    /* Show transfer rate: SELECT */
    PutLabel(fp0, gettext("Show transfer rate"), show_rate_string);
    BeginSelect(fp0, show_rate_string);
    for (i = 0; rate_values[i].LongName != 0; ++i) {
	char *message = NULL;

	HTSprintf0(&message,
		   rate_values[i].LongName,
		   HTProgressUnits(rate_values[i].value));
	PutOption(fp0,
		  LYTransferRate == rate_values[i].value,
		  rate_values[i].HtmlName,
		  message);
	FREE(message);
    }
    EndSelect(fp0);
#endif /* USE_READPROGRESS */

    /*
     * Special Files and Screens
     */
    PutHeader(fp0, gettext("Special Files and Screens"));
    /*****************************************************************/

    /* Multi-Bookmark Mode: SELECT */
    if (!LYMBMBlocked) {
	PutLabel(fp0, gettext("Multi-bookmarks"), mbm_string);
	BeginSelect(fp0, mbm_string);
	PutOptValues(fp0, LYMultiBookmarks, mbm_values);
	EndSelect(fp0);
    }

    /* Bookmarks File Menu: LINK/INPUT */
    if (LYMultiBookmarks) {
	PutLabel(fp0, gettext("Review/edit Bookmarks files"), mbm_string);
	fprintf(fp0, "<a href=\"%s\">%s</a>\n",
		LYNXOPTIONS_PAGE(MBM_LINK),
		LYEntifyTitle(&buffer, gettext("Goto multi-bookmark menu")));
    } else {
	PutLabel(fp0, gettext("Bookmarks file"), single_bookmark_string);
	PutTextInput(fp0, single_bookmark_string,
		     NonNull(bookmark_page), text_len, "");
    }

#ifdef USE_SESSIONS
    /* Auto Session: ON/OFF */
    PutLabel(fp0, gettext("Auto Session"), auto_session_string);
    BeginSelect(fp0, auto_session_string);
    PutOptValues(fp0, LYAutoSession, bool_values);
    EndSelect(fp0);

    /* Session File Menu: INPUT */
    PutLabel(fp0, gettext("Session file"), single_session_string);
    PutTextInput(fp0, single_session_string,
		 NonNull(LYSessionFile), text_len, "");
#endif

    /* Visited Pages: SELECT */
    PutLabel(fp0, gettext("Visited Pages"), visited_links_string);
    LYMenuVisitedLinks(fp0, disable_all);

    if (!no_lynxcfg_info) {
	fprintf(fp0, "\n  %s<a href=\"%s\">lynx.cfg</a>.\n",
		LYEntifyTitle(&buffer, gettext("View the file ")),
		STR_LYNXCFG);
    }

    fprintf(fp0, "\n</pre>\n");

    /* Submit/Reset */
    if (!disable_all) {
	fprintf(fp0, "<p align=center>\n");
	fprintf(fp0,
		"<input type=\"submit\" value=\"%s\"> - \n",
		LYEntifyValue(&buffer, ACCEPT_CHANGES));
	fprintf(fp0,
		"<input type=\"reset\" value=\"%s\"> - \n",
		LYEntifyValue(&buffer, RESET_CHANGES));
	fprintf(fp0, "%s\n", LYEntifyTitle(&buffer, CANCEL_CHANGES));
    }

    /*
     * close HTML
     */
    fprintf(fp0, "</form>\n");
    EndInternalPage(fp0);

    FREE(buffer);

    LYCloseTempFP(fp0);
    return (NORMAL);
}

#endif /* !NO_OPTION_FORMS */