diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 16:37:15 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 16:37:15 +0000 |
commit | ae5d181b854d3ccb373b6bc01b4869e44ff4d87a (patch) | |
tree | 91f59efb48c56a84cc798e012fccb667b63d3fee /src/LYOptions.c | |
parent | Initial commit. (diff) | |
download | lynx-ae5d181b854d3ccb373b6bc01b4869e44ff4d87a.tar.xz lynx-ae5d181b854d3ccb373b6bc01b4869e44ff4d87a.zip |
Adding upstream version 2.9.0dev.12.upstream/2.9.0dev.12upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r-- | src/LYOptions.c | 4365 |
1 files changed, 4365 insertions, 0 deletions
diff --git a/src/LYOptions.c b/src/LYOptions.c new file mode 100644 index 0000000..828aacc --- /dev/null +++ b/src/LYOptions.c @@ -0,0 +1,4365 @@ +/* $LynxId: LYOptions.c,v 1.186 2023/01/05 09:17:16 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 ? "" : " ") +#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); + } + } +} + +#if defined(USE_SLANG) || defined(COLOR_CURSES) +static void SetupChosenShowColor(void) +{ + 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", + "Minimal", + 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" : + ((user_mode == ADVANCED_MODE) ? "Advanced " : + "Minimal "))); + + 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 + 1, 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 == ADVANCED_MODE); + } else { + user_mode = LYChoosePopup(user_mode, + L_User_Mode, -1, + userMode_choices, + 3, FALSE, FALSE); + use_assume_charset = (BOOLEAN) (user_mode == ADVANCED_MODE); +#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 = 0; + + if (choice != 0) { + 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; + +#define END_OPTIONS {0, 0, 0} + +#define HasOptValues(table) (((table) != NULL) && ((table)->LongName != NULL)) + +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"}, + END_OPTIONS +}; + +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 + END_OPTIONS +}; +#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"}, + END_OPTIONS +}; +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"}, + END_OPTIONS +}; + +#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}, + END_OPTIONS +}; +#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}, + END_OPTIONS +}; +static const char *cookie_prompt_string = RC_FORCE_COOKIE_PROMPT; + +static const char RFC_2109_string[] = N_("RFC 2109"); +static const char RFC_2965_string[] = N_("RFC 2965"); +static const char RFC_6265_string[] = N_("RFC 6265"); +static OptValues cookies_values[] = +{ + {COOKIES_RFC_2109, RFC_2109_string, RFC_2109_string}, + {COOKIES_RFC_2965, RFC_2965_string, RFC_2965_string}, + {COOKIES_RFC_6265, RFC_6265_string, RFC_6265_string}, + END_OPTIONS +}; +static const char *cookie_version_string = RC_COOKIE_VERSION; + +#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"}, + {MINIMAL_MODE, N_("Minimal"), "Minimal"}, + END_OPTIONS +}; + +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"}, + END_OPTIONS +}; + +/* + * 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"}, + END_OPTIONS +}; + +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"}, + END_OPTIONS +}; + +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"}, + END_OPTIONS +}; + +static const char *collapse_br_tags_string = RC_COLLAPSE_BR_TAGS; +static OptValues collapse_br_tags_values[] = +{ + /* LYCollapseBRs variable */ + {FALSE, N_("OFF"), "OFF"}, + {TRUE, N_("collapse"), "ON"}, + END_OPTIONS +}; + +static const char *trim_blank_lines_string = RC_TRIM_BLANK_LINES; +static OptValues trim_blank_lines_values[] = +{ + /* LYtrimBlankLines variable */ + {FALSE, N_("OFF"), "OFF"}, + {TRUE, N_("trim-lines"), "ON"}, + END_OPTIONS +}; + +/* + * 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"}, + END_OPTIONS +}; + +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_IDN2 +static const char *idna_mode_string = RC_IDNA_MODE; +static OptValues idna_values[] = +{ + {LYidna2003, N_("IDNA 2003"), "idna2003"}, + {LYidna2008, N_("IDNA 2008"), "idna2008"}, + {LYidnaTR46, N_("IDNA TR46"), "idnaTR46"}, + {LYidnaCompat, N_("IDNA Compatible"), "idnaCompat"}, + END_OPTIONS +}; +#endif + +#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"}, + END_OPTIONS +}; + +#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 + END_OPTIONS +}; +#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"}, + END_OPTIONS +}; +#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 + END_OPTIONS +}; +#endif /* USE_READPROGRESS */ + +static const char *preferred_content_string = RC_PREFERRED_CONTENT_TYPE; +static OptValues content_values[] = +{ + {contentBINARY, STR_BINARY, STR_BINARY}, + {contentTEXT, STR_PLAINTEXT, STR_PLAINTEXT}, + {contentHTML, STR_HTML, STR_HTML}, + END_OPTIONS +}; + +/* + * 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"}, + END_OPTIONS +}; + +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 +#if defined(USE_BROTLI) || defined(BROTLI_PATH) + {encodingBROTLI, N_("brotli"), "encoding_brotli"}, +#endif + {encodingALL, N_("All"), "encoding_all"}, + END_OPTIONS +}; + +/* + * Headers transferred to remote server + */ +static const char *http_protocol_string = RC_HTTP_PROTOCOL; +static OptValues http_protocol_values[] = +{ + {HTTP_1_0, N_("HTTP 1.0"), "HTTP_1_0"}, + {HTTP_1_1, N_("HTTP 1.1"), "HTTP_1_1"}, + END_OPTIONS +}; + +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; + +static const char *ssl_client_certificate_file = RC_SSL_CLIENT_CERT_FILE; +static const char *ssl_client_key_file = RC_SSL_CLIENT_KEY_FILE; + +#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 +#ifdef LY_FIND_LEAKS +void free_colorstyle_leaks(void) +{ + FREE(color_style_values); +} +#endif + +void build_lss_enum(HTList *list) +{ + int count = HTList_count(list); + +#ifdef LY_FIND_LEAKS + atexit(free_colorstyle_leaks); +#endif + + 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)"); + + 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)"); + + 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 Version: SELECT */ + if (!strcmp(data[i].tag, cookie_version_string)) + GetOptValues(cookies_values, data[i].value, &cookie_version); + + /* 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; + } + } + + /* Collapse BR Tags: ON/OFF */ + if (!strcmp(data[i].tag, collapse_br_tags_string) + && GetOptValues(collapse_br_tags_values, data[i].value, &code)) { + if (LYCollapseBRs != code) { + LYCollapseBRs = (BOOLEAN) code; + need_reload = TRUE; + } + } + + /* Trim Blank Lines: ON/OFF */ + if (!strcmp(data[i].tag, trim_blank_lines_string) + && GetOptValues(trim_blank_lines_values, data[i].value, &code)) { + if (LYtrimBlankLines != code) { + LYtrimBlankLines = (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; + } + } +#ifdef USE_IDN2 + /* Internationalized Domain Names: SELECT */ + if (!strcmp(data[i].tag, idna_mode_string) + && GetOptValues(idna_values, data[i].value, &code)) { + LYidnaMode = code; + } +#endif + + /* 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 Content Type: SELECT */ + if (!strcmp(data[i].tag, preferred_content_string)) { + GetOptValues(content_values, data[i].value, &LYContentType); + } + + /* 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; + } + } + + /* + * HTTP protocol: SELECT + */ + if (!strcmp(data[i].tag, http_protocol_string)) { + GetOptValues(http_protocol_values, data[i].value, &HTprotocolLevel); + } + + /* Send User Agent: INPUT */ + if (!strcmp(data[i].tag, send_user_agent_string)) { + LYSendUserAgent = (BOOLEAN) !strcasecomp(data[i].value, "ON"); + } + + if (!strcmp(data[i].tag, ssl_client_certificate_file)) { + FREE(SSL_client_cert_file); + StrAllocCopy(SSL_client_cert_file, data[i].value); + } + + if (!strcmp(data[i].tag, ssl_client_key_file)) { + FREE(SSL_client_key_file); + StrAllocCopy(SSL_client_key_file, data[i].value); + } + + /* 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 */ + + 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)))) { + /* + * 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 = (long) 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 saveable 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, NonNull(name))); + + if (will_save_rc(value) && !no_option_save) { + while (need++ < want) + fprintf(fp, " "); + } else { + want -= 3; + if (need < want) { + fprintf(fp, " "); + ++need; + } + fprintf(fp, "(!)"); + while (need++ < want) { + fprintf(fp, " "); + } + } + 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 Version: SELECT */ + PutLabel(fp0, gettext("Cookie RFC-version"), cookie_version_string); + BeginSelect(fp0, cookie_version_string); + PutOptValues(fp0, cookie_version, cookies_values); + 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); + + PutLabel(fp0, gettext("SSL client certificate file"), ssl_client_certificate_file); + PutTextInput(fp0, ssl_client_certificate_file, + NonNull(SSL_client_cert_file), text_len, ""); + + PutLabel(fp0, gettext("SSL client key file"), ssl_client_key_file); + PutTextInput(fp0, ssl_client_key_file, + NonNull(SSL_client_key_file), text_len, ""); + +#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[DigitsOf(i) + 3]; + + 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[DigitsOf(i) + 3]; + + 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[DigitsOf(i) + 3]; + 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); + } + +#ifdef USE_IDN2 + /* Internationalized Domain Names: SELECT */ + { + PutLabel(fp0, gettext("Internationalized domain names"), idna_mode_string); + BeginSelect(fp0, idna_mode_string); + for (i = 0; idna_values[i].value != 0; i++) { + PutOption(fp0, idna_values[i].value == LYidnaMode, + idna_values[i].HtmlName, + idna_values[i].LongName); + } + EndSelect(fp0); + } +#endif + + /* 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 */ + if (HasOptValues(color_style_values)) { + 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); + + /* Collapse BR Tags: ON/OFF */ + PutLabel(fp0, gettext("Collapse BR tags"), collapse_br_tags_string); + BeginSelect(fp0, collapse_br_tags_string); + PutOptValues(fp0, LYCollapseBRs, collapse_br_tags_values); + EndSelect(fp0); + + /* Trim blank lines: ON/OFF */ + PutLabel(fp0, gettext("Trim blank lines"), trim_blank_lines_string); + BeginSelect(fp0, trim_blank_lines_string); + PutOptValues(fp0, LYtrimBlankLines, trim_blank_lines_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 content type: SELECT */ + PutLabel(fp0, gettext("Preferred content type"), preferred_content_string); + BeginSelect(fp0, preferred_content_string); + PutOptValues(fp0, LYContentType, content_values); + EndSelect(fp0); + + /* 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, ""); + + /* HTTP protocol SELECT */ + PutLabel(fp0, gettext("HTTP protocol"), http_protocol_string); + BeginSelect(fp0, http_protocol_string); + PutOptValues(fp0, HTprotocolLevel, http_protocol_values); + EndSelect(fp0); + + /* 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 */ |