about summary refs log tree commit diff stats
path: root/src/LYOptions.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/LYOptions.c')
-rw-r--r--src/LYOptions.c1896
1 files changed, 1640 insertions, 256 deletions
diff --git a/src/LYOptions.c b/src/LYOptions.c
index b26ee2ad..774279d2 100644
--- a/src/LYOptions.c
+++ b/src/LYOptions.c
@@ -15,9 +15,25 @@
 #include "LYrcFile.h"
 #include "HTAlert.h"
 #include "LYBookmark.h"
+#include "GridText.h"
 
 #include "LYLeaks.h"
 
+#ifndef BOXVERT
+#ifdef ALT_CHAR_SET
+#define BOXVERT 0   /* use alt char set for popup window vertical borders */
+#else
+#define BOXVERT '*'	/* character for popup window vertical borders */
+#endif
+#endif
+#ifndef BOXHORI
+#ifdef ALT_CHAR_SET
+#define BOXHORI 0   /* use alt char set for popup window horizontal borders */
+#else
+#define BOXHORI '*'	/* character for popup window horizontal borders */
+#endif
+#endif
+
 #define FREE(x) if (x) {free(x); x = NULL;}
 
 #ifdef VMS
@@ -30,8 +46,18 @@
 
 BOOLEAN term_options;
 PRIVATE void terminate_options  PARAMS((int sig));
-PRIVATE int boolean_choice PARAMS((int status, int line,
-				   int column, char **choices));
+PRIVATE int boolean_choice PARAMS((
+	int		status,
+	int		line,
+	int		column,
+	char **		choices));
+PRIVATE int popup_choice PARAMS((
+	int		cur_choice,
+	int		line,
+	int		column,
+	char **		choices, 
+	int		i_length,
+	int		disabled));
 
 #define MAXCHOICES 10
 
@@ -41,7 +67,7 @@ PRIVATE void option_statusline ARGS1(
     /*
      *  Make sure we have a pointer to a string.
      */
-    if (text == 0)
+    if (text == NULL)
         return;
 
     /*
@@ -64,7 +90,9 @@ PUBLIC void options NOARGS
     int itmp;
 #endif /* ALLOW_USERS_TO_CHANGE_EXEC_WITHIN_OPTIONS */
     int response, ch;
-    /* if the user changes the display I need memory to put it in */
+    /*
+     *  If the user changes the display we need memory to put it in.
+     */
     char display_option[256]; 
 #ifndef VMS
     static char putenv_command[142];
@@ -72,6 +100,7 @@ PUBLIC void options NOARGS
     char *choices[MAXCHOICES];
     int CurrentCharSet = current_char_set;
     BOOLEAN CurrentRawMode = LYRawMode;
+    BOOLEAN AddValueAccepted = FALSE;
     
 #ifdef DIRED_SUPPORT
 #ifdef ALLOW_USERS_TO_CHANGE_EXEC_WITHIN_OPTIONS
@@ -132,7 +161,7 @@ draw_options:
     addstr((LYMultiBookmarks ?
     	      (LYMBMAdvanced ? "ADVANCED"
 	      		     : "STANDARD")
-			     : "OFF"));
+			     : "OFF     "));
     move(L_HOME, B_BOOK);
     if (LYMultiBookmarks) {
         addstr("review/edit B)ookmarks files");
@@ -143,10 +172,10 @@ draw_options:
 
     move(L_FTPSTYPE, 5);
     addstr("F)TP sort criteria           : ");
-    addstr((HTfileSortMethod==FILE_BY_NAME ? "By Filename" :
-	   (HTfileSortMethod==FILE_BY_SIZE ? "By Size" : 
-	   (HTfileSortMethod==FILE_BY_TYPE ? "By Type" :
-	   				     "By Date"))));
+    addstr((HTfileSortMethod == FILE_BY_NAME ? "By Filename" :
+	   (HTfileSortMethod == FILE_BY_SIZE ? "By Size    " : 
+	   (HTfileSortMethod == FILE_BY_TYPE ? "By Type    " :
+	   				       "By Date    "))));
 
     move(L_MAIL_ADDRESS, 5);
     addstr("P)ersonal mail address       : ");
@@ -155,7 +184,7 @@ draw_options:
 
     move(L_SSEARCH, 5); 
     addstr("S)earching type              : ");
-    addstr(case_sensitive ? "CASE SENSITIVE" : "CASE INSENSITIVE");
+    addstr(case_sensitive ? "CASE SENSITIVE  " : "CASE INSENSITIVE");
 
     move(L_CHARSET, 5);
     addstr("display (C)haracter set      : "); 
@@ -163,7 +192,7 @@ draw_options:
     
     move(L_RAWMODE, 5);
     addstr("Raw 8-bit or CJK m(O)de      : ");
-    addstr(LYRawMode ? "ON" : "OFF");
+    addstr(LYRawMode ? "ON " : "OFF");
 
     move(L_LANGUAGE, 5);
     addstr("preferred document lan(G)uage: ");
@@ -175,24 +204,31 @@ draw_options:
 
     move(L_BOOL_A, B_VIKEYS);
     addstr("V)I keys: ");
-    addstr(vi_keys ? "ON" : "OFF");
+    addstr(vi_keys ? "ON " : "OFF");
     
     move(L_BOOL_A, B_EMACSKEYS);
     addstr("e(M)acs keys: ");
-    addstr(emacs_keys ? "ON" : "OFF");
+    addstr(emacs_keys ? "ON " : "OFF");
     
     move(L_BOOL_A, B_SHOW_DOTFILES);
     addstr("sho(W) dot files: ");
-    addstr((!no_dotfiles && show_dotfiles) ? "ON" : "OFF");
+    addstr((!no_dotfiles && show_dotfiles) ? "ON " : "OFF");
 
-    move(L_SELECT_POPUPS, 5);
+    move(L_BOOL_B, B_SELECT_POPUPS);
     addstr("popups for selec(T) fields   : ");
-    addstr(LYSelectPopups ? "ON" : "OFF");
+    addstr(LYSelectPopups ? "ON " : "OFF");
+
+    move(L_BOOL_B, B_SHOW_CURSOR);
+    addstr("show cursor (@) : ");
+    addstr(LYShowCursor ? "ON " : "OFF");
 
-    move(L_KEYPAD, 5); 
-    addstr("K)eypad mode                 : "); 
-    addstr((keypad_mode == NUMBERS_AS_ARROWS) ? "Numbers act as arrows" : 
-						"Links are numbered");
+    move(L_KEYPAD, 5);
+    addstr("K)eypad mode                 : ");
+    addstr((keypad_mode == NUMBERS_AS_ARROWS) ?
+				"Numbers act as arrows             " :
+	 ((keypad_mode == LINKS_ARE_NUMBERED) ?
+				"Links are numbered                " :
+				"Links and form fields are numbered"));
 
     move(L_LINEED, 5);
     addstr("li(N)e edit style            : ");
@@ -201,16 +237,16 @@ draw_options:
 #ifdef DIRED_SUPPORT
     move(L_DIRED, 5);
     addstr("l(I)st directory style       : ");
-    addstr((dir_list_style == FILES_FIRST) ? "Files first          " :
-	  ((dir_list_style == MIXED_STYLE) ? "Mixed style          " : 
-					     "Directories first    "));
+    addstr((dir_list_style == FILES_FIRST) ? "Files first      " :
+	  ((dir_list_style == MIXED_STYLE) ? "Mixed style      " : 
+					     "Directories first"));
 #endif /* DIRED_SUPPORT */
 
     move(L_USER_MODE, 5);
     addstr("U)ser mode                   : ");
-    addstr(  (user_mode == NOVICE_MODE) ? "Novice" : 
+    addstr(  (user_mode == NOVICE_MODE) ? "Novice      " : 
       ((user_mode == INTERMEDIATE_MODE) ? "Intermediate" :
-					  "Advanced"));
+					  "Advanced    "));
 
     move(L_USER_AGENT, 5);
     addstr("user (A)gent                 : ");
@@ -220,12 +256,12 @@ draw_options:
     move(L_EXEC, 5);
     addstr("local e(X)ecution links      : ");
 #ifndef NEVER_ALLOW_REMOTE_EXEC
-    addstr(		  local_exec ? "ALWAYS ON" :
+    addstr(		  local_exec ? "ALWAYS ON           " :
           (local_exec_on_local_files ? "FOR LOCAL FILES ONLY" :
-				       "ALWAYS OFF"));
+				       "ALWAYS OFF          "));
 #else
     addstr(local_exec_on_local_files ? "FOR LOCAL FILES ONLY" :
-				       "ALWAYS OFF");
+				       "ALWAYS OFF          ");
 #endif /* NEVER_ALLOW_REMOTE_EXEC */
 #endif /* ALLOW_USERS_TO_CHANGE_EXEC_WITHIN_OPTIONS */
 
@@ -252,121 +288,124 @@ draw_options:
     addstr(TO_RETURN_SEGMENT);
 
     while (TOUPPER(response) != 'R' &&
-    	   !LYisNonAlnumKeyname(response, LYK_PREV_DOC) &&
+	   !LYisNonAlnumKeyname(response, LYK_PREV_DOC) &&
            response != '>' && !term_options &&
 	   response != 7 &&  response != 3) {
+	if (AddValueAccepted == TRUE) {
+	    option_statusline(VALUE_ACCEPTED);
+	    AddValueAccepted = FALSE;
+	}
+	move((LYlines - 2), 0);
+	lynx_start_prompt_color ();
+	addstr(COMMAND_PROMPT);
+	lynx_stop_prompt_color ();
 
-           move(LYlines-2, 0);
-           lynx_start_prompt_color ();
-	   addstr(COMMAND_PROMPT);
-           lynx_stop_prompt_color ();
-
-	   refresh();
-           response = LYgetch();
-	   if (term_options || response == 7 || response == 3)
-	       response = 'R';
-	   if (LYisNonAlnumKeyname(response, LYK_REFRESH)) {
-	       clearok(curscr, TRUE);
-	       goto draw_options;
-	   }
-	   switch (response) {
-	 	case 'e':  /* change the editor */
-		case 'E':
-	                if (no_editor) {
-			    option_statusline(EDIT_DISABLED);
-	                } else if (system_editor ) {
-			    option_statusline(EDITOR_LOCKED);
-			} else {
-			    if (editor && *editor)
-			        strcpy(display_option, editor);
-			    else {  /* clear the NONE */
-				move(L_EDITOR, COL_OPTION_VALUES);
-				addstr("    ");
-			        *display_option = '\0';
-			    }
-			    option_statusline(ACCEPT_DATA);
-			    move(L_EDITOR, COL_OPTION_VALUES);  
-			    standout();
-			    ch = LYgetstr(display_option, VISIBLE,
-			    		  sizeof(display_option), NORECALL);
-			    standend();
-			    move(L_EDITOR, COL_OPTION_VALUES);
-			    if (term_options || ch == -1) {
-			        addstr((editor && *editor) ?
-						    editor : "NONE");
-			    } else if (*display_option == '\0') {
-				FREE(editor);
-				addstr("NONE");
-			    } else {
-			        StrAllocCopy(editor, display_option);
-				addstr(display_option);
-			    }
-			    clrtoeol();
-			    option_statusline(VALUE_ACCEPTED);
-			}
-			response = ' ';
-			break;
+	refresh();
+	response = LYgetch();
+	if (term_options || response == 7 || response == 3)
+	    response = 'R';
+	if (LYisNonAlnumKeyname(response, LYK_REFRESH)) {
+	    clearok(curscr, TRUE);
+	    goto draw_options;
+	}
+	switch (response) {
+	    case 'e':	/* Change the editor. */
+	    case 'E':
+	        if (no_editor) {
+		    option_statusline(EDIT_DISABLED);
+		} else if (system_editor ) {
+		    option_statusline(EDITOR_LOCKED);
+		} else {
+		    if (editor && *editor)
+			strcpy(display_option, editor);
+		    else {  /* clear the NONE */
+			move(L_EDITOR, COL_OPTION_VALUES);
+			addstr("    ");
+			*display_option = '\0';
+		    }
+		    option_statusline(ACCEPT_DATA);
+		    move(L_EDITOR, COL_OPTION_VALUES);  
+		    standout();
+		    ch = LYgetstr(display_option, VISIBLE,
+				  sizeof(display_option), NORECALL);
+		    standend();
+		    move(L_EDITOR, COL_OPTION_VALUES);
+		    if (term_options || ch == -1) {
+		        addstr((editor && *editor) ?
+					    editor : "NONE");
+		    } else if (*display_option == '\0') {
+			FREE(editor);
+			addstr("NONE");
+		    } else {
+		        StrAllocCopy(editor, display_option);
+			addstr(display_option);
+		    }
+		    clrtoeol();
+		    option_statusline(VALUE_ACCEPTED);
+		}
+		response = ' ';
+		break;
 
-		case 'd':  /* change the display */
-		case 'D':
-			if (display && *display) {
-			    strcpy(display_option, display);
-			} else {  /* clear the NONE */
-			    move(L_DISPLAY, COL_OPTION_VALUES);
-			    addstr("    ");
-			    *display_option = '\0';
-			}
-			option_statusline(ACCEPT_DATA);
-	                move(L_DISPLAY, COL_OPTION_VALUES);
-			standout();
-			ch = LYgetstr(display_option, VISIBLE,
-				      sizeof(display_option), NORECALL);
-			standend();
-	                move(L_DISPLAY, COL_OPTION_VALUES);
-			if ((term_options || ch == -1) ||
-			    (display != NULL &&
+	    case 'd':	/* Change the display. */
+	    case 'D':
+		if (display && *display) {
+		    strcpy(display_option, display);
+		} else {  /* clear the NONE */
+		    move(L_DISPLAY, COL_OPTION_VALUES);
+		    addstr("    ");
+		    *display_option = '\0';
+		}
+		option_statusline(ACCEPT_DATA);
+		move(L_DISPLAY, COL_OPTION_VALUES);
+		standout();
+		ch = LYgetstr(display_option, VISIBLE,
+			      sizeof(display_option), NORECALL);
+		standend();
+		move(L_DISPLAY, COL_OPTION_VALUES);
+		if ((term_options || ch == -1) ||
+		    (display != NULL &&
 #ifdef VMS
-			     0 == strcasecomp(display, display_option)))
+		     !strcasecomp(display, display_option)))
 #else
-			     0 == strcmp(display, display_option)))
+		     !strcmp(display, display_option)))
 #endif /* VMS */
-			{
-			    /*
-			     *  Cancelled, or a non-NULL display string
-			     *  wasn't changed. - FM
-			     */
-			    addstr((display && *display) ? display : "NONE");
-			    clrtoeol();
-			    option_statusline(VALUE_ACCEPTED);
-			    response = ' ';
-			    break;
-			} else if (*display_option == '\0') {
-			    if ((display == NULL) ||
-			        (display != NULL && *display == '\0')) {
-				/*
-				 *  NULL or zero-length display string
-				 *  wasn't changed. - FM
-				 */
-			        addstr("NONE");
-				clrtoeol();
-				option_statusline(VALUE_ACCEPTED);
-				response = ' ';
-				break;
-			    }
-			}
+		{
+		    /*
+		     *  Cancelled, or a non-NULL display string
+		     *  wasn't changed. - FM
+		     */
+		    addstr((display && *display) ? display : "NONE");
+		    clrtoeol();
+		    option_statusline(VALUE_ACCEPTED);
+		    response = ' ';
+		    break;
+		} else if (*display_option == '\0') {
+		    if ((display == NULL) ||
+		        (display != NULL && *display == '\0')) {
 			/*
-			 *  Set the new DISPLAY variable. - FM
+			 *  NULL or zero-length display string
+			 *  wasn't changed. - FM
 			 */
+		        addstr("NONE");
+			clrtoeol();
+			option_statusline(VALUE_ACCEPTED);
+			response = ' ';
+			break;
+		    }
+		}
+		/*
+		 *  Set the new DISPLAY variable. - FM
+		 */
 #ifdef VMS
-			{
-			    int i;
-			    for (i = 0; display_option[i]; i++)
-			        display_option[i] = TOUPPER(display_option[i]);
-			    Define_VMSLogical(DISPLAY, display_option);
-			}
+		{
+		    int i;
+		    for (i = 0; display_option[i]; i++)
+		        display_option[i] = TOUPPER(display_option[i]);
+		    Define_VMSLogical(DISPLAY, display_option);
+		}
 #else
-			sprintf(putenv_command, "DISPLAY=%s", display_option);
-			putenv(putenv_command);
+		sprintf(putenv_command, "DISPLAY=%s", display_option);
+		putenv(putenv_command);
 #endif /* VMS */
 			if ((display = getenv(DISPLAY)) != NULL &&
 			    *display == '\0') {
@@ -396,7 +435,7 @@ draw_options:
 			response = ' ';
 			break;
 
-		case 'l':
+		case 'l':	/* Change multibookmarks option. */
 		case 'L':
 			if (LYMBMBlocked) {
 			    option_statusline(MULTIBOOKMARKS_DISALLOWED);
@@ -410,20 +449,38 @@ draw_options:
 			choices[2] = NULL;
 			StrAllocCopy(choices[2],"ADVANCED");
 			choices[3] = NULL;
-			LYMultiBookmarks = boolean_choice(LYMultiBookmarks *
-                                                          (1 + LYMBMAdvanced),
+		if (!LYSelectPopups) {
+		    LYMultiBookmarks = boolean_choice((LYMultiBookmarks *
+						       (1 + LYMBMAdvanced)),
                                                           L_HOME, C_MULTI,
                                                           choices);
-			FREE(choices[0]);
-			FREE(choices[1]);
-			FREE(choices[2]);
+		} else {
+		    LYMultiBookmarks = popup_choice((LYMultiBookmarks *
+						     (1 + LYMBMAdvanced)),
+						    L_HOME, (C_MULTI - 1),
+						    choices,
+						    3, FALSE);
+		}
                         if (LYMultiBookmarks == 2) {
                             LYMultiBookmarks = TRUE;
                             LYMBMAdvanced = TRUE;
                         } else {
                             LYMBMAdvanced = FALSE;
                         }
-			
+#if defined(VMS) || defined(USE_SLANG)
+		if (LYSelectPopups) {
+		    move(L_HOME, C_MULTI);
+		    clrtoeol();
+		    addstr(choices[(LYMultiBookmarks * (1 + LYMBMAdvanced))]);
+		}
+#endif /* VMS || USE_SLANG */
+		FREE(choices[0]);
+		FREE(choices[1]);
+		FREE(choices[2]);
+#if !defined(VMS) && !defined(USE_SLANG)
+		if (!LYSelectPopups)
+#endif /* !VMS && !USE_SLANG */
+		{
 			move(L_HOME, B_BOOK);
 			clrtoeol();
     			if (LYMultiBookmarks) {
@@ -433,13 +490,27 @@ draw_options:
 			    addstr((bookmark_page && *bookmark_page) ?
 			    			       bookmark_page : "NONE");
     			}
+		}
 			response = ' ';
+		if (LYSelectPopups) {
+#if !defined(VMS) || defined(USE_SLANG)
+		    if (term_options) {
+		        term_options = FALSE;
+	            } else {
+		        AddValueAccepted = TRUE;
+		    }
+		    goto draw_options;
+#else
+		    term_options = FALSE;
+#endif /* !VMS || USE_SLANG */
+		}
 			break;
 
-		case 'b':  /* change the bookmark page location */
+		case 'b':	/* Change the bookmark page location. */
 		case 'B':
-			/* anonymous users should not be allowed to
-			 * change the bookmark page
+			/*
+			 *  Anonymous users should not be allowed to
+			 *  change the bookmark page.
 			 */
 			if (!no_bookmark) {
 			    if (LYMultiBookmarks) {
@@ -447,9 +518,9 @@ draw_options:
 				signal(SIGINT, terminate_options);
 				goto draw_options;
 			    }
-			    if (bookmark_page && *bookmark_page)
+		    if (bookmark_page && *bookmark_page) {
 			        strcpy(display_option, bookmark_page);
-			    else {  /* clear the NONE */
+		    } else {  /* clear the NONE */
 				move(L_HOME, C_DEFAULT);
 				clrtoeol();
 			        *display_option = '\0';
@@ -487,9 +558,11 @@ draw_options:
 			response = ' ';
 			break;
 
-		case 'f':
-		case 'F':
-                        /* copy strings into choice array */
+		case 'f':	/* Change ftp directory sorting. */
+		case 'F':	/*  (also local for non-DIRED)   */
+                        /*
+			 *  Copy strings into choice array.
+			 */
                         choices[0] = NULL;
                         StrAllocCopy(choices[0],"By Filename");
                         choices[1] = NULL;
@@ -499,19 +572,45 @@ draw_options:
                         choices[3] = NULL;
                         StrAllocCopy(choices[3],"By Date    ");
                         choices[4] = NULL;
+		if (!LYSelectPopups) {
                         HTfileSortMethod = boolean_choice(HTfileSortMethod,
-                                               L_FTPSTYPE, -1, choices);
+						      L_FTPSTYPE, -1,
+						      choices);
+		} else {
+		    HTfileSortMethod = popup_choice(HTfileSortMethod,
+						    L_FTPSTYPE, -1,
+						    choices,
+						    4, FALSE);
+#if defined(VMS) || defined(USE_SLANG)
+		    move(L_FTPSTYPE, COL_OPTION_VALUES);
+		    clrtoeol();
+		    addstr(choices[HTfileSortMethod]);
+#endif /* VMS || USE_SLANG */
+		}
                         FREE(choices[0]);
                         FREE(choices[1]);
                         FREE(choices[2]);
+                        FREE(choices[3]);
 			response = ' ';
+		if (LYSelectPopups) {
+#if !defined(VMS) || defined(USE_SLANG)
+		    if (term_options) {
+		        term_options = FALSE;
+	            } else {
+		        AddValueAccepted = TRUE;
+		    }
+		    goto draw_options;
+#else
+		    term_options = FALSE;
+#endif /* !VMS || USE_SLANG */
+		}
                         break;
 
-		case 'p':  /* change personal mail address for From headers */
+		case 'p': /* Change personal mail address for From headers. */
 		case 'P':
-			if (personal_mail_address && *personal_mail_address)
+		if (personal_mail_address && *personal_mail_address) {
 			    strcpy(display_option, personal_mail_address);
-			else {  /* clear the NONE */
+		} else {  /* clear the NONE */
 			    move(L_MAIL_ADDRESS, COL_OPTION_VALUES);
 			    addstr("    ");
 			    *display_option = '\0';
@@ -539,9 +638,11 @@ draw_options:
 			response = ' ';
 			break;
 
-		case 's':
+		case 's':	/* Change case sentitivity for searches. */
 		case 'S':
-			/* copy strings into choice array */
+			/*
+			 *  Copy strings into choice array.
+			 */
 			choices[0] = NULL;
 			StrAllocCopy(choices[0],"CASE INSENSITIVE");
 			choices[1] = NULL;
@@ -554,10 +655,23 @@ draw_options:
 			response = ' ';
 			break;
 
-		case 'c':
+		case 'c':	/* Change charset setting. */
 		case 'C':
+		if (!LYSelectPopups) {
 			current_char_set = boolean_choice(current_char_set,
-			    		L_CHARSET, -1, LYchar_set_names);
+		    				      L_CHARSET, -1,
+						      LYchar_set_names);
+		} else {
+		    current_char_set = popup_choice(current_char_set,
+						    L_CHARSET, -1,
+						    LYchar_set_names,
+						    0, FALSE);
+#if defined(VMS) || defined(USE_SLANG)
+		    move(L_CHARSET, COL_OPTION_VALUES);
+		    clrtoeol();
+		    addstr(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
@@ -568,30 +682,47 @@ draw_options:
 			    HTMLUseCharacterSet(current_char_set);
 			    CurrentCharSet = current_char_set;
 			    CurrentRawMode = LYRawMode;
+#if !defined(VMS) && !defined(USE_SLANG)
+		    if (!LYSelectPopups)
+#endif /* !VMS && !USE_SLANG */
+		    {
 			    move(L_RAWMODE, COL_OPTION_VALUES);
 			    clrtoeol();
 			    addstr(LYRawMode ? "ON " : "OFF");
 			}
+		}
 			response = ' ';
+		if (LYSelectPopups) {
+#if !defined(VMS) || defined(USE_SLANG)
+		    if (term_options) {
+		        term_options = FALSE;
+	            } else {
+		        AddValueAccepted = TRUE;
+		    }
+		    goto draw_options;
+#else
+		    term_options = FALSE;
+#endif /* !VMS || USE_SLANG */
+		}
 			break;
 
-		case 'o':
+		case 'o':	/* Change raw mode setting. */
 		case 'O':
-			/* copy strings into choice array */
+			/*
+			 *  Copy strings into choice array.
+			 */
 			choices[0] = NULL;
 			StrAllocCopy(choices[0], "OFF");
 			choices[1] = NULL;
 			StrAllocCopy(choices[1], "ON ");
 			choices[2] = NULL;
-			LYRawMode = boolean_choice(LYRawMode,
-						   L_RAWMODE, -1, choices);
+		LYRawMode = boolean_choice(LYRawMode, L_RAWMODE, -1, choices);
 			/*
 			 *  Set the LYUseDefaultRawMode value and character
 			 *  handling if LYRawMode was changed. - FM
 			 */
 			if (CurrentRawMode != LYRawMode) {
-			    HTMLSetUseDefaultRawMode(current_char_set,
-			    			     LYRawMode);
+		    HTMLSetUseDefaultRawMode(current_char_set, LYRawMode);
 			    HTMLSetCharacterHandling(current_char_set);
 			    CurrentRawMode = LYRawMode;
 			}
@@ -600,11 +731,11 @@ draw_options:
 			response = ' ';
 			break;
 
-		case 'g':  /* change language preference */
+		case 'g':	/* Change language preference. */
 		case 'G':
-			if (language && *language)
+		if (language && *language) {
 			    strcpy(display_option, language);
-			else {  /* clear the NONE */
+		} else {  /* clear the NONE */
 			    move(L_LANGUAGE, COL_OPTION_VALUES);
 			    addstr("    ");
 			    *display_option = '\0';
@@ -631,11 +762,11 @@ draw_options:
 			response = ' ';
 			break;
 
-		case 'h':  /* change character set preference */
+		case 'h':	/* Change charset preference. */
 		case 'H':
-			if (pref_charset && *pref_charset)
+		if (pref_charset && *pref_charset) {
 			    strcpy(display_option, pref_charset);
-			else {  /* clear the NONE */
+		} else {  /* clear the NONE */
 			    move(L_PREF_CHARSET, COL_OPTION_VALUES);
 			    addstr("    ");
 			    *display_option = '\0';
@@ -662,9 +793,11 @@ draw_options:
 			response = ' ';
 			break;
 
-		case 'v':
+		case 'v':	/* Change VI keys setting. */
 		case 'V':
-			/* copy strings into choice array */
+			/*
+			 *  Copy strings into choice array.
+			 */
 			choices[0] = NULL;
 			StrAllocCopy(choices[0],"OFF");
 			choices[1] = NULL;
@@ -673,18 +806,21 @@ draw_options:
 			vi_keys = boolean_choice(vi_keys,
 						 L_BOOL_A, C_VIKEYS,
 						 choices);
-			if (vi_keys)
+		if (vi_keys) {
                             set_vi_keys();
-                        else
+		} else {
                             reset_vi_keys();
+		}
 			FREE(choices[0]);
 			FREE(choices[1]);
 			response = ' ';
 			break;
 
-		case 'M':
+		case 'M':	/* Change emacs keys setting. */
 		case 'm':
-			/* copy strings into choice array */
+			/*
+			 *  Copy strings into choice array.
+			 */
 			choices[0] = NULL;
 			StrAllocCopy(choices[0],"OFF");
 			choices[1] = NULL;
@@ -693,21 +829,24 @@ draw_options:
 			emacs_keys = boolean_choice(emacs_keys,
 						    L_BOOL_A, C_EMACSKEYS,
 						    choices);
-                        if (emacs_keys)
+		if (emacs_keys) {
                             set_emacs_keys();
-                        else
+		} else {
                             reset_emacs_keys();
+		}
 			FREE(choices[0]);
 			FREE(choices[1]);
 			response = ' ';
 			break;
 
-		case 'W':
+		case 'W':	/* Change show dotfiles setting. */
 		case 'w':
 			   if (no_dotfiles) {
 			       option_statusline(DOTFILE_ACCESS_DISABLED);
 			   } else {
-			       /* copy strings into choice array */
+			       /*
+			        *  Copy strings into choice array.
+				*/
 			       choices[0] = NULL;
 			       StrAllocCopy(choices[0],"OFF");
 			       choices[1] = NULL;
@@ -723,52 +862,134 @@ draw_options:
 			   response = ' ';
 			   break;
 
-		case 't':
+		case 't':	/* Change select popups setting. */
 		case 'T':
-			/* copy strings into choice array */
+			/*
+			 *  Copy strings into choice array.
+			 */
 			choices[0] = NULL;
 			StrAllocCopy(choices[0], "OFF");
 			choices[1] = NULL;
 			StrAllocCopy(choices[1], "ON ");
 			choices[2] = NULL;
 			LYSelectPopups = boolean_choice(LYSelectPopups,
-							L_SELECT_POPUPS, -1,
+							L_BOOL_B,
+							C_SELECT_POPUPS,
 							choices);
 			FREE(choices[0]);
 			FREE(choices[1]);
 			response = ' ';
 			break;
 
-		case 'k':
+		case '@':	/* Change show cursor setting. */
+			/*
+			 *  Copy strings into choice array.
+			 */
+			choices[0] = NULL;
+			StrAllocCopy(choices[0], "OFF");
+			choices[1] = NULL;
+			StrAllocCopy(choices[1], "ON ");
+			choices[2] = NULL;
+			LYShowCursor = boolean_choice(LYShowCursor,
+						      L_BOOL_B,
+						      C_SHOW_CURSOR,
+						      choices);
+			FREE(choices[0]);
+			FREE(choices[1]);
+			response = ' ';
+			break;
+
+		case 'k':	/* Change keypad mode. */
 		case 'K':
-			/* copy strings into choice array */
+			/*
+			 *  Copy strings into choice array.
+			 */
 			choices[0] = NULL;
-			StrAllocCopy(choices[0],"Numbers act as arrows");
+			StrAllocCopy(choices[0],
+				     "Numbers act as arrows             ");
 			choices[1] = NULL;
-			StrAllocCopy(choices[1],"Links are numbered   ");
+			StrAllocCopy(choices[1],
+				     "Links are numbered                ");
 			choices[2] = NULL;
+			StrAllocCopy(choices[2],
+				     "Links and form fields are numbered");
+			choices[3] = NULL;
+		if (!LYSelectPopups) {
 			keypad_mode = boolean_choice(keypad_mode,
-			       			     L_KEYPAD, -1, choices);
-                        if (keypad_mode == NUMBERS_AS_ARROWS)
+						 L_KEYPAD, -1,
+						 choices);
+		} else {
+		    keypad_mode = popup_choice(keypad_mode,
+					       L_KEYPAD, -1,
+					       choices,
+					       3, FALSE);
+#if defined(VMS) || defined(USE_SLANG)
+		    move(L_KEYPAD, COL_OPTION_VALUES);
+		    clrtoeol();
+		    addstr(choices[keypad_mode]);
+#endif /* VMS || USE_SLANG */
+		}
+		if (keypad_mode == NUMBERS_AS_ARROWS) {
                             set_numbers_as_arrows();
-                        else
+		} else {
                             reset_numbers_as_arrows();
+		}
 			FREE(choices[0]);
 			FREE(choices[1]);
+			FREE(choices[2]);
 			response = ' ';
+		if (LYSelectPopups) {
+#if !defined(VMS) || defined(USE_SLANG)
+		    if (term_options) {
+		        term_options = FALSE;
+	            } else {
+		        AddValueAccepted = TRUE;
+		    }
+		    goto draw_options;
+#else
+		    term_options = FALSE;
+#endif /* !VMS || USE_SLANG */
+		}
 			break;
 
-		case 'n':
+		case 'n':	/* Change line editor key bindings. */
 		case 'N':
+		if (!LYSelectPopups) {
 			current_lineedit = boolean_choice(current_lineedit,
-			    		L_LINEED, -1, LYLineeditNames);
+						      L_LINEED, -1,
+						      LYLineeditNames);
+		} else {
+		    current_lineedit = popup_choice(current_lineedit,
+						    L_LINEED, -1,
+						    LYLineeditNames,
+						    0, FALSE);
+#if defined(VMS) || defined(USE_SLANG)
+		    move(L_LINEED, COL_OPTION_VALUES);
+		    clrtoeol();
+		    addstr(LYLineeditNames[current_lineedit]);
+#endif /* VMS || USE_SLANG */
+		}
 			response = ' ';
+		if (LYSelectPopups) {
+#if !defined(VMS) || defined(USE_SLANG)
+		    if (term_options) {
+		        term_options = FALSE;
+	            } else {
+		        AddValueAccepted = TRUE;
+		    }
+		    goto draw_options;
+#else
+		    term_options = FALSE;
+#endif /* !VMS || USE_SLANG */
+		}
 			break;
 
 #ifdef DIRED_SUPPORT
-		case 'i':
+		case 'i':	/* Change local directory sorting. */
 		case 'I':
-			/* copy strings into choice array */
+			/*
+			 *  Copy strings into choice array.
+			 */
 			choices[0] = NULL;
 			StrAllocCopy(choices[0],"Directories first");
 			choices[1] = NULL;
@@ -776,18 +997,45 @@ draw_options:
 			choices[2] = NULL;
 			StrAllocCopy(choices[2],"Mixed style      ");
 			choices[3] = NULL;
+		if (!LYSelectPopups) {
 			dir_list_style = boolean_choice(dir_list_style,
-							L_DIRED, -1, choices);
+						    L_DIRED, -1,
+						    choices);
+		} else {
+		    dir_list_style = popup_choice(dir_list_style,
+						  L_DIRED, -1,
+						  choices,
+						  3, FALSE);
+#if defined(VMS) || defined(USE_SLANG)
+		    move(L_DIRED, COL_OPTION_VALUES);
+		    clrtoeol();
+		    addstr(choices[dir_list_style]);
+#endif /* VMS || USE_SLANG */
+		}
 			FREE(choices[0]);
 			FREE(choices[1]);
 			FREE(choices[2]);
 			response = ' ';
+		if (LYSelectPopups) {
+#if !defined(VMS) || defined(USE_SLANG)
+		    if (term_options) {
+		        term_options = FALSE;
+	            } else {
+		        AddValueAccepted = TRUE;
+		    }
+		    goto draw_options;
+#else
+		    term_options = FALSE;
+#endif /* !VMS || USE_SLANG */
+		}
 			break;
 #endif /* DIRED_SUPPORT */
 
-		case 'u':
+		case 'u':	/* Change user mode. */
 		case 'U':
-			/* copy strings into choice array */
+			/*
+			 *  Copy strings into choice array.
+			 */
 			choices[0] = NULL;
 			StrAllocCopy(choices[0],"Novice      ");
 			choices[1] = NULL;
@@ -795,24 +1043,50 @@ draw_options:
 			choices[2] = NULL;
 			StrAllocCopy(choices[2],"Advanced    ");
 			choices[3] = NULL;
+		if (!LYSelectPopups) {
 			user_mode = boolean_choice(user_mode,
-						   L_USER_MODE, -1, choices);
+					       L_USER_MODE, -1,
+					       choices);
+		} else {
+		    user_mode = popup_choice(user_mode,
+					     L_USER_MODE, -1,
+					     choices,
+					     3, FALSE);
+#if defined(VMS) || defined(USE_SLANG)
+		    move(L_USER_MODE, COL_OPTION_VALUES);
+		    clrtoeol();
+		    addstr(choices[user_mode]);
+#endif /* VMS || USE_SLANG */
+		}
 			FREE(choices[0]);
 			FREE(choices[1]);
 			FREE(choices[2]);
-			if(user_mode == NOVICE_MODE)
-			   display_lines = LYlines-4;
-			else
+		if (user_mode == NOVICE_MODE) {
+		    display_lines = (LYlines - 4);
+		} else {
 			   display_lines = LYlines-2;
+		}
 			response = ' ';
+		if (LYSelectPopups) {
+#if !defined(VMS) || defined(USE_SLANG)
+		    if (term_options) {
+		        term_options = FALSE;
+	            } else {
+		        AddValueAccepted = TRUE;
+		    }
+		    goto draw_options;
+#else
+		    term_options = FALSE;
+#endif /* !VMS || USE_SLANG */
+		}
 			break;
 
-		case 'a':
+		case 'a':	/* Change user agent string. */
 		case 'A':
 			if (!no_useragent) {
-			    if (LYUserAgent && *LYUserAgent)
+		    if (LYUserAgent && *LYUserAgent) {
 			        strcpy(display_option, LYUserAgent);
-			    else {  /* clear the NONE */
+		    } else {  /* clear the NONE */
 				move(L_HOME, COL_OPTION_VALUES);
 				addstr("    ");
 			        *display_option = '\0';
@@ -852,22 +1126,29 @@ draw_options:
 			break;
 
 #ifdef ALLOW_USERS_TO_CHANGE_EXEC_WITHIN_OPTIONS
-		case 'x':  /* local exec */
+		case 'x':	/* Change local exec restriction. */
 		case 'X':
-			if (!exec_frozen) {
+		if (exec_frozen && !LYSelectPopups) {
+		    option_statusline(CHANGE_OF_SETTING_DISALLOWED);
+		    response = ' ';
+		    break;
+		}
 #ifndef NEVER_ALLOW_REMOTE_EXEC
 			    if (local_exec) {
 				itmp = 2;
-			    } else {
+		} else
 #else
 			  {
 #endif /* NEVER_ALLOW_REMOTE_EXEC */
-			  	if (local_exec_on_local_files)
+		    if (local_exec_on_local_files) {
 				    itmp= 1;
-				else
+		    } else {
 				    itmp = 0;
 			   }
-			   /* copy strings into choice array */
+		}
+			   /*
+			    *  Copy strings into choice array.
+			    */
 			   choices[0] = NULL;
 			   StrAllocCopy(choices[0],"ALWAYS OFF          ");
 			   choices[1] = NULL;
@@ -877,57 +1158,79 @@ draw_options:
 			   StrAllocCopy(choices[2],"ALWAYS ON           ");
 			   choices[3] = NULL;
 #endif /* NEVER_ALLOW_REMOTE_EXEC */
-			   itmp = boolean_choice(itmp, L_EXEC, -1, choices);
-  
+		if (!LYSelectPopups) {
+		    itmp = boolean_choice(itmp,
+					  L_EXEC, -1,
+					  choices);
+		} else {
+		    itmp = popup_choice(itmp,
+					L_EXEC, -1,
+					choices,
+					0, (exec_frozen ? TRUE : FALSE));
+#if defined(VMS) || defined(USE_SLANG)
+		    move(L_EXEC, COL_OPTION_VALUES);
+		    clrtoeol();
+		    addstr(choices[itmp]);
+#endif /* VMS || USE_SLANG */
+		}
 			   FREE(choices[0]);
 			   FREE(choices[1]);
 #ifndef NEVER_ALLOW_REMOTE_EXEC
 			   FREE(choices[2]);
 #endif /* NEVER_ALLOW_REMOTE_EXEC */
+		if (!exec_frozen) {
 			   switch(itmp) {
 			      case 0:
 				  local_exec = FALSE;
 				  local_exec_on_local_files = FALSE;
-				  response = ' ';
 				  break;
 			      case 1:
 				  local_exec = FALSE;
 				  local_exec_on_local_files = TRUE;
-				  response = ' ';
 				  break;
 #ifndef NEVER_ALLOW_REMOTE_EXEC
 			      case 2:
 				  local_exec = TRUE;
 				  local_exec_on_local_files = FALSE;
-				  response = ' ';
 				  break;
 #endif /* NEVER_ALLOW_REMOTE_EXEC */
 			  } /* end switch */
-			} else {
-			   option_statusline(CHANGE_OF_SETTING_DISALLOWED);
 			}
 			response = ' ';
+		if (LYSelectPopups) {
+#if !defined(VMS) || defined(USE_SLANG)
+		    if (exec_frozen || term_options) {
+		        term_options = FALSE;
+	            } else {
+		        AddValueAccepted = TRUE;
+		    }
+		    goto draw_options;
+#else
+		    term_options = FALSE;
+#endif /* !VMS || USE_SLANG */
+		}
 			break;
 #endif /* ALLOW_USERS_TO_CHANGE_EXEC_WITHIN_OPTIONS */
 
-		case '>':
+		case '>':	/* Save current options to RC file. */
                         if (!no_option_save) {
                             option_statusline(SAVING_OPTIONS);
-                            if(save_rc())
+		    if (save_rc()) {
 				option_statusline(OPTIONS_SAVED);
-			    else 
+		    } else {
 				HTAlert(OPTIONS_NOT_SAVED);
-
+		    }
                         } else {
 			    option_statusline(R_TO_RETURN_TO_LYNX);
-			    /* change response so that we don't exit
-			     * the options menu 
+			    /*
+			     *  Change response so that we don't exit
+			     *  the options menu.
 			     */
 			    response = ' ';
 			} 
 			break;
 
-		case 'r':
+		case 'r':	/* Return to document (quit options menu). */
 		case 'R':
 			break;
 
@@ -949,17 +1252,25 @@ draw_options:
  *  and return it.
  */
 PRIVATE int boolean_choice ARGS4(
-	int,		status,
+	int,		cur_choice,
 	int,		line,
 	int,		column,
 	char **,	choices)
 {
     int response = 0;
-    int respcmd;
+    int cmd = 0;
     int number = 0;
     int col = (column >= 0 ? column : COL_OPTION_VALUES);
+    int orig_choice = cur_choice;
+#ifdef VMS
+    extern BOOLEAN HadVMSInterrupt; /* Flag from cleanup_sig() AST */
+#endif /* VMS */
 	
-    for (; choices[number] != NULL; number++)
+    /*
+     *  Get the number of choices and then make
+     *  number zero-based.
+     */
+    for (number = 0; choices[number] != NULL; number++)
 	;  /* empty loop body */
 
     number--;
@@ -970,11 +1281,13 @@ PRIVATE int boolean_choice ARGS4(
     option_statusline(ANY_KEY_CHANGE_RET_ACCEPT);
 
     /*
-     *  Highlight the current selection.
+     *  Highlight the current choice.
      */
     move(line, col);
     standout();
-    addstr(choices[status]);
+    addstr(choices[cur_choice]);
+    if (LYShowCursor)
+	move(line, (col - 1));
     refresh();
 
     /*
@@ -983,37 +1296,63 @@ PRIVATE int boolean_choice ARGS4(
      *  it can be changed, until the user accepts
      *  the current choice.
      */
+    term_options = FALSE;
     while (1) {
 	move(line, col);
+	if (term_options == FALSE) {
 	response = LYgetch();
-	if (term_options || response == 7 || response == 3)
+	}
+	if (term_options || response == 7 || response == 3) {
+	     /*
+	      *  Control-C or Control-G.
+	      */
+	    response = '\n';
+	    term_options = TRUE;
+	    cur_choice = orig_choice;
+	}
+#ifdef VMS
+	if (HadVMSInterrupt) {
+	    HadVMSInterrupt = FALSE;
 	    response = '\n';
-	if (response != '\n' && response != '\r') {
-	     respcmd = keymap[response+1];
-#if defined(DIRED_SUPPORT) && defined(OK_OVERRIDE)
-                     /* does this make sense here? dunno.. - kw */
-	     if (!respcmd && override[response+1] && !no_dired_support)
-	       respcmd = override[response+1];
-#endif /* DIRED_SUPPORT && OK_OVERRIDE */
-	     switch (respcmd) {
+	    term_options = TRUE;
+	    cur_choice = orig_choice;
+	}
+#endif /* VMS */
+	if ((response != '\n' && response != '\r') &&
+	    (cmd = keymap[response+1]) != LYK_ACTIVATE) {
+	     switch (cmd) {
+		case LYK_HOME:
+		    cur_choice = 0;
+		    break;
+
+		case LYK_END:
+		    cur_choice = number;
+		    break;
+
+		case LYK_REFRESH:
+		    clearok(curscr, TRUE);
+		    refresh();
+		    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_UP_LINK:
 	     case LYK_LEFT_LINK:
-	     case LYK_PREV_DOC:
-		if(status == 0)
-		    status = number;  /* go back to end */
+		if(cur_choice == 0)
+		    cur_choice = number;  /* go back to end */
 		else
-		    status--;
-		break;
-	     case LYK_END:
-		status = number;
+		    cur_choice--;
 		break;
 		
-	     case LYK_HOME:
-		status = 0;
-		break;
 	     case LYK_1:
 	     case LYK_2:
 	     case LYK_3:
@@ -1023,28 +1362,37 @@ PRIVATE int boolean_choice ARGS4(
 	     case LYK_7:
 	     case LYK_8:
 	     case LYK_9:
-	       if((respcmd - LYK_1 + 1) <= number) {
-		 status = respcmd -LYK_1 + 1;
+	       if((cmd - LYK_1 + 1) <= number) {
+		 cur_choice = cmd -LYK_1 + 1;
 		 break;
 	       }  /* else fall through! */
 	     default:
-	    if (status == number)
-		status = 0;  /* go over the top and around */
+	    if (cur_choice == number)
+		cur_choice = 0;  /* go over the top and around */
 	    else
-		status++;
+		cur_choice++;
 	      }  /* end of switch */
-	    addstr(choices[status]);
+	    addstr(choices[cur_choice]);
+	    if (LYShowCursor)
+		move(line, (col - 1));
 	    refresh();
 	} else {
 	    /*
-	     *  Unhighlight selection.
+	     *  Unhighlight choice.
 	     */
 	    move(line, col);
 	    standend();
-	    addstr(choices[status]);
+	    addstr(choices[cur_choice]);
 
+	    if (term_options) {
+	        term_options = FALSE;
+		option_statusline(CANCELLED);
+		sleep(InfoSecs);
+		option_statusline("");
+	    } else {
 	    option_statusline(VALUE_ACCEPTED);
-	    return(status);
+	    }
+	    return(cur_choice);
 	}
     }
 }
@@ -1053,10 +1401,14 @@ PRIVATE void terminate_options ARGS1(
 	int,		sig)
 {
     term_options=TRUE;
-    /* Reassert the AST */
+    /*
+     *  Reassert the AST.
+     */
     signal(SIGINT, terminate_options);
 #ifdef VMS
-    /* refresh the screen to get rid of the "interrupt" message */
+    /*
+     *  Refresh the screen to get rid of the "interrupt" message.
+     */
     if (!dump_output_immediately) {
 	clearok(curscr, TRUE);
 	refresh();
@@ -1345,3 +1697,1035 @@ draw_bookmark_list:
     term_options = FALSE;
     signal(SIGINT, cleanup_sig);
 }
+
+/*
+**  This function prompts for a choice or page number.
+**  If a 'g' or 'p' suffix is included, that will be
+**  loaded into c.  Otherwise, c is zeroed. - FM
+*/
+PRIVATE int get_popup_choice_number ARGS1(
+	int *,		c)
+{
+    char temp[120];
+
+    /*
+     *  Load the c argument into the prompt buffer.
+     */
+    temp[0] = *c;
+    temp[1] = '\0';
+    option_statusline(OPTION_CHOICE_NUMBER);
+
+    /*
+     *  Get the number, possibly with a suffix, from the user.
+     */
+    if (LYgetstr(temp, VISIBLE, sizeof(temp), NORECALL) < 0 ||
+        *temp == 0 || term_options) {
+	option_statusline(CANCELLED);
+	sleep(InfoSecs);
+	*c = '\0';
+	term_options = FALSE;
+	return(0);
+    }
+
+    /*
+     *  If we had a 'g' or 'p' suffix, load it into c.
+     *  Otherwise, zero c.  Then return the number.
+     */
+    if (strchr(temp, 'g') != NULL || strchr(temp, 'G') != NULL) {
+        *c = 'g';
+    } else if (strchr(temp, 'p') != NULL || strchr(temp, 'P') != NULL) {
+        *c = 'p';
+    } else {
+        *c = '\0';
+    }
+    return(atoi(temp));
+}
+
+/*
+ *  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
+ */
+PRIVATE int popup_choice ARGS6(
+	int,		cur_choice,
+	int,		line,
+	int,		column,
+	char **,	choices,
+	int,		i_length,
+	int,		disabled)
+{
+    int ly = line;
+    int lx = (column >= 0 ? column : (COL_OPTION_VALUES - 1));
+    int c = 0, cmd = 0, i = 0, j = 0;
+    int orig_choice = cur_choice;
+#ifndef USE_SLANG
+    WINDOW * form_window;
+#endif /* !USE_SLANG */
+    int num_choices = 0, top, bottom, length = -1, width = 0;
+    char ** Cptr = choices;
+    int window_offset = 0;
+    int DisplayLines = (LYlines - 2);
+    char Cnum[64];
+    int Lnum;
+    int npages;
+#ifdef VMS
+    extern BOOLEAN HadVMSInterrupt; /* Flag from cleanup_sig() AST */
+#endif /* VMS */
+    static char prev_target[512]; 		/* Search string buffer */
+    static char prev_target_buffer[512];	/* Next search buffer */
+    static BOOL first = TRUE;
+    char *cp;
+    int ch = 0, recall;
+    int QueryTotal;
+    int QueryNum;
+    BOOLEAN FirstRecall = TRUE;
+    BOOLEAN ReDraw = FALSE;
+    int number;
+    char buffer[512];
+
+    /*
+     * Initialize the search string buffer. - FM
+     */
+    if (first) {
+	*prev_target_buffer = '\0';
+	first = FALSE;
+    }
+    *prev_target = '\0';
+    QueryTotal = (search_queries ? HTList_count(search_queries) : 0);
+    recall = ((QueryTotal >= 1) ? RECALL : NORECALL);
+    QueryNum = QueryTotal;
+
+    /*
+     *  Count the number of choices to be displayed, where
+     *  num_choices ranges from 0 to n, and set width to the
+     *  longest choice string length.  Also set Lnum to the
+     *  length for the highest choice number, then decrement
+     *  num_choices so as to be zero-based.  The window width
+     *  will be based on the sum of width and Lnum. - FM
+     */
+    for (num_choices = 0; Cptr[num_choices] != NULL; num_choices++) {
+	if (strlen(Cptr[num_choices]) > width) {
+	    width = strlen(Cptr[num_choices]);
+	}
+    }
+    sprintf(Cnum, "%d: ", num_choices);
+    Lnum = strlen(Cnum);
+    num_choices--;
+
+    /*
+     *  Let's assume for the sake of sanity that ly is the number
+     *   corresponding to the line the option is on.
+     *  Let's also assume that cur_choice is the number of the
+     *   choice that should be initially selected, with 0 being
+     *   the first choice.
+     *  So what we have, is the top equal to the current screen line
+     *   subtracting the cur_choice + 1 (the one must be for the top
+     *   line we will draw in a box).  If the top goes under 0, then
+     *   consider it 0.
+     */
+    top = ly - (cur_choice + 1);
+    if (top < 0)
+	top = 0;
+
+    /*
+     *  Check and see if we need to put the i_length parameter up to
+     *  the number of real choices.
+     */
+    if (i_length < 1) {
+        i_length = num_choices;
+    } else {
+        /*
+	 *  Otherwise, it is really one number too high.
+	 */
+	i_length--;
+    }
+
+    /*
+     *  The bottom is the value of the top plus the number of choices
+     *  to view plus 3 (one for the top line, one for the bottom line,
+     *  and one to offset the 0 counted in the num_choices).
+     */
+    bottom = top + i_length + 3;
+
+    /*
+     *  Hmm...  If the bottom goes beyond the number of lines available,
+     */
+    if (bottom > DisplayLines) {
+        /*
+	 *  Position the window at the top if we have more
+	 *  choices than will fit in the window.
+	 */
+	if ((i_length + 3) > DisplayLines) {
+	    top = 0;
+            bottom = (top + (i_length + 3));
+	    if (bottom > DisplayLines)
+	        bottom = (DisplayLines + 1);
+	} else {
+	    /*
+	     *  Try to position the window so that the selected choice will
+	     *    appear where the choice box currently is positioned.
+	     *  It could end up too high, at this point, but we'll move it
+	     *    down latter, if that has happened.
+	     */
+	    top = (DisplayLines + 1) - (i_length + 3);
+	    bottom = (DisplayLines + 1);
+	}
+    }
+
+    /*
+     *  This is really fun, when the length is 4, it means 0 to 4, or 5.
+     */
+    length = (bottom - top) - 2;
+
+    /*
+     *  Move the window down if it's too high.
+     */
+    if (bottom < ly + 2) {
+        bottom = ly + 2;
+	if (bottom > DisplayLines + 1)
+	    bottom = DisplayLines + 1;
+	top = bottom - length - 2;
+    }
+
+    /*
+     *  Set up the overall window, including the boxing characters ('*'),
+     *  if it all fits.  Otherwise, set up the widest window possible. - FM
+     */
+#ifdef USE_SLANG
+    SLsmg_fill_region(top, lx - 1, bottom - top, (Lnum + width + 4), ' ');
+#else
+    if (!(form_window = newwin(bottom - top, (Lnum + width + 4),
+			       top, (lx - 1))) &&
+        !(form_window = newwin(bottom - top, 0, top, 0))) {
+	option_statusline(POPUP_FAILED);
+        return(orig_choice);
+    }
+    scrollok(form_window, TRUE);
+#endif /* USE_SLANG */
+
+    /*
+     *  Clear the command line and write
+     *  the popup statusline. - FM
+     */
+    move((LYlines - 2), 0);
+    clrtoeol();
+    if (disabled) {
+	option_statusline(CHOICE_LIST_UNM_MSG);
+    } else {
+	option_statusline(CHOICE_LIST_MESSAGE);
+    }
+
+    /*
+     *  Set up the window_offset for choices.
+     *   cur_choice ranges from 0...n
+     *   length ranges from 0...m
+     */
+    if (cur_choice >= length) {
+        window_offset = cur_choice - length + 1;
+    }
+
+    /*
+     *  Compute the number of popup window pages. - FM
+     */
+    npages = ((num_choices + 1) > length) ?
+		(((num_choices + 1) + (length - 1))/(length))
+					  : 1;
+/*
+ *  OH!  I LOVE GOTOs! hack hack hack
+ */
+redraw:
+    Cptr = choices;
+
+    /*
+     *  Display the boxed choices.
+     */
+    for (i = 0; i <= num_choices; i++) {
+        if (i >= window_offset && i - window_offset < length) {
+	    sprintf(Cnum, "%s%d: ",
+			   ((num_choices > 8 && i < 9) ?
+						   " " : ""),
+			   (i + 1));
+#ifdef USE_SLANG
+	    SLsmg_gotorc(top + ((i + 1) - window_offset), (lx - 1 + 2));
+	    addstr(Cnum);
+	    SLsmg_write_nstring(Cptr[i], width);
+#else
+	    wmove(form_window, ((i + 1) - window_offset), 2);
+	    wclrtoeol(form_window);
+	    waddstr(form_window, Cnum);
+	    waddstr(form_window, Cptr[i]);
+#endif /* USE_SLANG */
+	}
+    }
+#ifdef USE_SLANG
+    SLsmg_draw_box(top, (lx - 1), (bottom - top), (Lnum + width + 4));
+#else
+#ifdef VMS
+    VMSbox(form_window, (bottom - top), (Lnum + width + 4));
+#else
+    box(form_window, BOXVERT, BOXHORI);
+#endif /* VMS */
+    wrefresh(form_window);
+#endif /* USE_SLANG */
+    Cptr = NULL;
+
+    /*
+     *  Loop on user input.
+     */
+    while (cmd != LYK_ACTIVATE) {
+        /*
+	 *  Unreverse cur choice.
+	 */
+	if (Cptr != NULL) {
+	    sprintf(Cnum, "%s%d: ",
+			  ((num_choices > 8 && i < 9) ?
+						  " " : ""),
+			  (i + 1));
+#ifdef USE_SLANG
+	    SLsmg_gotorc((top + ((i + 1) - window_offset)), (lx - 1 + 2));
+	    addstr(Cnum);
+	    SLsmg_write_nstring(Cptr[i], width);
+#else
+	    wmove(form_window, ((i + 1) - window_offset), 2);
+	    waddstr(form_window, Cnum);
+            waddstr(form_window, Cptr[i]);
+#endif /* USE_SLANG */
+	}
+	Cptr = choices;
+	i = cur_choice;
+	sprintf(Cnum, "%s%d: ",
+		      ((num_choices > 8 && i < 9) ?
+					      " " : ""),
+		      (i + 1));
+#ifdef USE_SLANG
+	SLsmg_gotorc((top + ((i + 1) - window_offset)), (lx - 1 + 2));
+	addstr(Cnum);
+	SLsmg_set_color(2);
+	SLsmg_write_nstring(Cptr[i], width);
+	SLsmg_set_color(0);
+	/*
+	 *  If LYShowCursor is ON, move the cursor to the left
+	 *  of the current choice, so that blind users, who are
+	 *  most likely to have LYShowCursor ON, will have it's
+	 *  string spoken or passed to the braille interface as
+	 *  each choice is made current.  Otherwise, move it to
+	 *  the bottom, right column of the screen, to "hide"
+	 *  the cursor as for the main document, and let sighted
+	 *  users rely on the current choice's highlighting or
+	 *  color without the distraction of a blinking cursor
+	 *  in the window. - FM
+	 */
+	if (LYShowCursor)
+	    SLsmg_gotorc((top + ((i + 1) - window_offset)), (lx - 1 + 1));
+	else
+	    SLsmg_gotorc((LYlines - 1), (LYcols - 1));
+	SLsmg_refresh();
+#else
+	wmove(form_window, ((i + 1) - window_offset), 2);
+	waddstr(form_window, Cnum);
+	wstart_reverse(form_window);
+	waddstr(form_window, Cptr[i]);
+	wstop_reverse(form_window);
+	/*
+	 *  If LYShowCursor is ON, move the cursor to the left
+	 *  of the current choice, so that blind users, who are
+	 *  most likely to have LYShowCursor ON, will have it's
+	 *  string spoken or passed to the braille interface as
+	 *  each choice is made current.  Otherwise, leave it to
+	 *  the right of the current choice, since we can't move
+	 *  it out of the window, and let sighted users rely on
+	 *  the highlighting of the current choice without the
+	 *  distraction of a blinking cursor preceding it. - FM
+	 */
+	if (LYShowCursor)
+	    wmove(form_window, ((i + 1) - window_offset), 1);
+	wrefresh(form_window);
+#endif /* USE_SLANG  */
+
+	term_options = FALSE;
+	c = LYgetch();
+	if (term_options || c == 3 || c == 7) {
+	     /*
+	      *  Control-C or Control-G
+	      */
+	    cmd = LYK_QUIT;
+	} else {
+	    cmd = keymap[c+1];
+	}
+#ifdef VMS
+	if (HadVMSInterrupt) {
+	    HadVMSInterrupt = FALSE;
+	    cmd = LYK_QUIT;
+	}
+#endif /* VMS */
+
+        switch(cmd) {
+	    case LYK_F_LINK_NUM:
+		c = '\0';
+	    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:
+		/*
+		 *  Get a number from the user, possibly with
+		 *  a 'g' or 'p' suffix (which will be loaded
+		 *  into c). - FM & LE
+		 */
+		number = get_popup_choice_number((int *)&c);
+
+		/*
+		 *  Check for a 'p' suffix. - FM
+		 */
+		if (c == 'p') {
+		    /*
+		     *  Treat 1 or less as the first page. - FM
+		     */
+		    if (number <= 1) {
+		        if (window_offset == 0) {
+			    option_statusline(ALREADY_AT_CHOICE_BEGIN);
+			    sleep(MessageSecs);
+			    if (disabled) {
+				option_statusline(CHOICE_LIST_UNM_MSG);
+			    } else {
+				option_statusline(CHOICE_LIST_MESSAGE);
+			    }
+			    break;
+			}
+			window_offset = 0;
+			cur_choice = 0;
+			if (disabled) {
+			    option_statusline(CHOICE_LIST_UNM_MSG);
+			} else {
+			    option_statusline(CHOICE_LIST_MESSAGE);
+			}
+			goto redraw;
+		    }
+
+		    /*
+		     *  Treat a number equal to or greater than the
+		     *  number of pages as the last page. - FM
+		     */
+		    if (number >= npages) {
+		        if (window_offset >= ((num_choices - length) + 1)) {
+			    option_statusline(ALREADY_AT_CHOICE_END);
+			    sleep(MessageSecs);
+			    if (disabled) {
+				option_statusline(CHOICE_LIST_UNM_MSG);
+			    } else {
+				option_statusline(CHOICE_LIST_MESSAGE);
+			    }
+			    break;
+			}
+			window_offset = ((npages - 1) * length);
+			if (window_offset > (num_choices - length)) {
+			    window_offset = (num_choices - length + 1);
+			}
+			if (cur_choice < window_offset)
+			    cur_choice = window_offset;
+			if (disabled) {
+			    option_statusline(CHOICE_LIST_UNM_MSG);
+   			} else {
+			    option_statusline(CHOICE_LIST_MESSAGE);
+			}
+			goto redraw;
+		    }
+
+		    /*
+		     *  We want an intermediate page. - FM
+		     */
+		    if (((number - 1) * length) == window_offset) {
+			sprintf(buffer, ALREADY_AT_CHOICE_PAGE, number);
+			option_statusline(buffer);
+			sleep(MessageSecs);
+			if (disabled) {
+			    option_statusline(CHOICE_LIST_UNM_MSG);
+			} else {
+			    option_statusline(CHOICE_LIST_MESSAGE);
+			}
+			break;
+		    }
+		    cur_choice = window_offset = ((number - 1) * length);
+		    if (disabled) {
+			option_statusline(CHOICE_LIST_UNM_MSG);
+   		    } else {
+			option_statusline(CHOICE_LIST_MESSAGE);
+		    }
+		    goto redraw;
+
+		}
+
+		/*
+		 *  Check for a positive number, which signifies
+		 *  that a choice should be sought. - FM
+		 */
+		if (number > 0) {
+		    /*
+		     *  Decrement the number so as to correspond
+		     *  with our cur_choice values. - FM
+		     */
+		    number--;
+
+		    /*
+		     *  If the number is in range and had no legal
+		     *  suffix, select the indicated choice. - FM
+		     */
+		    if (number <= num_choices && c == '\0') {
+			cur_choice = number;
+			cmd = LYK_ACTIVATE;
+			break;
+		    }
+
+		    /*
+		     *  Verify that we had a 'g' suffix,
+		     *  and act on the number. - FM
+		     */
+		    if (c == 'g') {
+			if (cur_choice == number) {
+			    /*
+			     *  The choice already is current. - FM
+			     */
+			    sprintf(buffer,
+			    	    CHOICE_ALREADY_CURRENT, (number + 1));
+			    option_statusline(buffer);
+			    sleep(MessageSecs);
+			    if (disabled) {
+				option_statusline(CHOICE_LIST_UNM_MSG);
+   			    } else {
+				option_statusline(CHOICE_LIST_MESSAGE);
+			    }
+			    break;
+			}
+
+			if (number <= num_choices) {
+			    /*
+			     *  The number is in range and had a 'g'
+			     *  suffix, so make it the current choice,
+			     *  scrolling if needed. - FM
+			     */
+			    j = (number - cur_choice);
+			    cur_choice = number;
+			    if ((j > 0) &&
+			        (cur_choice - window_offset) >= length) {
+				window_offset += j;
+				if (window_offset > (num_choices - length + 1))
+				    window_offset = (num_choices - length + 1);
+			    } else if ((cur_choice - window_offset) < 0) {
+				window_offset -= abs(j);
+				if (window_offset < 0)
+				    window_offset = 0;
+			    }
+			    if (disabled) {
+				option_statusline(CHOICE_LIST_UNM_MSG);
+   			    } else {
+				option_statusline(CHOICE_LIST_MESSAGE);
+			    }
+			    goto redraw;
+			}
+
+			/*
+			 *  Not in range. - FM
+			 */
+			option_statusline(BAD_CHOICE_NUM_ENTERED);
+			sleep(MessageSecs);
+		    }
+		}
+
+		/*
+		 *  Restore the popup statusline. - FM
+		 */
+		if (disabled) {
+		    option_statusline(CHOICE_LIST_UNM_MSG);
+   		} else {
+		    option_statusline(CHOICE_LIST_MESSAGE);
+		}
+		break;
+
+            case LYK_PREV_LINK:
+	    case LYK_UP_LINK:
+
+		if (cur_choice > 0)
+		    cur_choice--;
+
+		/*
+		 *  Scroll the window up if necessary.
+		 */
+		if ((cur_choice - window_offset) < 0) {
+		    window_offset--;
+		    goto redraw;
+		}
+                break;
+
+            case LYK_NEXT_LINK:
+	    case LYK_DOWN_LINK:
+		if (cur_choice < num_choices)
+                    cur_choice++;
+
+		/*
+		 *  Scroll the window down if necessary
+		 */
+		if ((cur_choice - window_offset) >= length) {
+		    window_offset++;
+		    goto redraw;
+		}
+                break;
+
+	    case LYK_NEXT_PAGE:
+		/*
+		 *  Okay, are we on the last page of the choices list?
+		 *  If not then,
+		 */
+		if (window_offset != (num_choices - length + 1)) {
+		    /*
+		     *  Modify the current choice to not be a
+		     *  coordinate in the list, but a coordinate
+		     *  on the item selected in the window.
+		     */
+		    cur_choice -= window_offset;
+
+		    /*
+		     *  Page down the proper length for the list.
+		     *  If simply to far, back up.
+		     */
+		    window_offset += length;
+		    if (window_offset > (num_choices - length)) {
+		        window_offset = (num_choices - length + 1);
+		    }
+
+		    /*
+		     *  Readjust the current choice to be a choice
+		     *  list coordinate rather than window.
+		     *  Redraw this thing.
+		     */
+		    cur_choice += window_offset;
+		    goto redraw;
+		}
+		else if (cur_choice < num_choices) {
+		    /*
+		     *  Already on last page of the choice list so
+		     *  just redraw it with the last item selected.
+		     */
+		    cur_choice = num_choices;
+		}
+		break;
+
+	    case LYK_PREV_PAGE:
+		/*
+		 *  Are we on the first page of the choice list?
+		 *  If not then,
+		 */
+		if (window_offset != 0) {
+		    /*
+		     *  Modify the current choice to not be a choice
+		     *  list coordinate, but a window coordinate.
+		     */
+		    cur_choice -= window_offset;
+
+		    /*
+		     *  Page up the proper length.
+		     *  If too far, back up.
+		     */
+		    window_offset -= length;
+		    if (window_offset < 0) {
+		        window_offset = 0;
+		    }
+
+		    /*
+		     *  Readjust the current choice.
+		     */
+		    cur_choice += window_offset;
+		    goto redraw;
+		} else if (cur_choice > 0) {
+		    /*
+		     *  Already on the first page so just
+		     *  back up to the first item.
+		     */
+		    cur_choice = 0;
+		}
+		break;
+
+	    case LYK_HOME:
+	        cur_choice = 0;
+		if (window_offset > 0) {
+		    window_offset = 0;
+		    goto redraw;
+		}
+		break;
+
+	    case LYK_END:
+	        cur_choice = num_choices;
+		if (window_offset != (num_choices - length + 1)) {
+		    window_offset = (num_choices - length + 1);
+		    goto redraw;
+		}
+		break;
+
+            case LYK_DOWN_TWO:
+	        cur_choice += 2;
+		if (cur_choice > num_choices)
+                    cur_choice = num_choices;
+
+		/*
+		 *  Scroll the window down if necessary.
+		 */
+		if ((cur_choice - window_offset) >= length) {
+		    window_offset += 2;
+		    if (window_offset > (num_choices - length + 1))
+		        window_offset = (num_choices - length + 1);
+		    goto redraw;
+		}
+                break;
+
+	    case LYK_UP_TWO:
+	        cur_choice -= 2;
+		if (cur_choice < 0)
+		    cur_choice = 0;
+
+		/*
+		 *  Scroll the window up if necessary.
+		 */
+		if ((cur_choice - window_offset) < 0) {
+		    window_offset -= 2;
+		    if (window_offset < 0)
+		        window_offset = 0;
+		    goto redraw;
+		}
+                break;
+
+            case LYK_DOWN_HALF:
+	        cur_choice += (length/2);
+		if (cur_choice > num_choices)
+                    cur_choice = num_choices;
+
+		/*
+		 *  Scroll the window down if necessary.
+		 */
+		if ((cur_choice - window_offset) >= length) {
+		    window_offset += (length/2);
+		    if (window_offset > (num_choices - length + 1))
+		        window_offset = (num_choices - length + 1);
+		    goto redraw;
+		}
+                break;
+
+	    case LYK_UP_HALF:
+	        cur_choice -= (length/2);
+		if (cur_choice < 0)
+		    cur_choice = 0;
+
+		/*
+		 *  Scroll the window up if necessary.
+		 */
+		if ((cur_choice - window_offset) < 0) {
+		    window_offset -= (length/2);
+		    if (window_offset < 0)
+		        window_offset = 0;
+		    goto redraw;
+		}
+                break;
+
+	    case LYK_REFRESH:
+	        clearok(curscr, TRUE);
+	        refresh();
+		break;
+
+	    case LYK_NEXT:
+		if (recall && *prev_target_buffer == '\0') {
+		    /*
+		     *  We got a 'n'ext command with no prior query
+		     *  specified within the popup window.  See if
+		     *  one was entered when the popup was retracted,
+		     *  and if so, assume that's what's wanted.  Note
+		     *  that it will become the default within popups,
+		     *  unless another is entered within a popup.  If
+		     *  the within popup default is to be changed at
+		     *  that point, use WHEREIS ('/') and enter it,
+		     *  or the up- or down-arrow keys to seek any of
+		     *  the previously entered queries, regardless of
+		     *  whether they were entered within or outside
+		     *  of a popup window. - FM
+		     */
+		    if ((cp = (char *)HTList_objectAt(search_queries,
+	    					      0)) != NULL) {
+			strcpy(prev_target_buffer, cp);
+			QueryNum = 0;
+			FirstRecall = FALSE;
+		    }
+		}
+	        strcpy(prev_target, prev_target_buffer);
+	    case LYK_WHEREIS:
+	        if (*prev_target == '\0' ) {
+		    option_statusline(ENTER_WHEREIS_QUERY);
+		    if ((ch = LYgetstr(prev_target, VISIBLE,
+	    		 	       sizeof(prev_target_buffer),
+				       recall)) < 0) {
+			/*
+			 *  User cancelled the search via ^G. - FM
+			 */
+			option_statusline(CANCELLED);
+			sleep(InfoSecs);
+			goto restore_popup_statusline;
+		    }
+		}
+
+check_recall:
+		if (*prev_target == '\0' &&
+		    !(recall && (ch == UPARROW || ch == DNARROW))) {
+		    /*
+		     *  No entry.  Simply break.   - FM
+		     */
+	            option_statusline(CANCELLED);
+		    sleep(InfoSecs);
+		    goto restore_popup_statusline;
+		}
+
+		if (recall && ch == UPARROW) {
+		    if (FirstRecall) {
+		        /*
+			 *  Use the current string or
+			 *  last query in the list. - FM
+			 */
+			FirstRecall = FALSE;
+			if (*prev_target_buffer) {
+			    for (QueryNum = (QueryTotal - 1);
+			         QueryNum > 0; QueryNum--) {
+				if ((cp = (char *)HTList_objectAt(
+							search_queries,
+	    						QueryNum)) != NULL &&
+				    !strcmp(prev_target_buffer, cp)) {
+				    break;
+				}
+			    }
+			} else {
+			    QueryNum = 0;
+			}
+		    } else {
+			/*
+			 *  Go back to the previous query in the list. - FM
+			 */
+			QueryNum++;
+		    }
+		    if (QueryNum >= QueryTotal)
+			/*
+			 *  Roll around to the last query in the list. - FM
+			 */
+			QueryNum = 0;
+		    if ((cp = (char *)HTList_objectAt(search_queries,
+	    					      QueryNum)) != NULL) {
+			strcpy(prev_target, cp);
+			if (*prev_target_buffer &&
+			    !strcmp(prev_target_buffer, prev_target)) {
+			    option_statusline(EDIT_CURRENT_QUERY);
+			} else if ((*prev_target_buffer && QueryTotal == 2) ||
+				   (!(*prev_target_buffer) &&
+				      QueryTotal == 1)) {
+			    option_statusline(EDIT_THE_PREV_QUERY);
+			} else {
+			    option_statusline(EDIT_A_PREV_QUERY);
+			}
+			if ((ch = LYgetstr(prev_target, VISIBLE,
+				sizeof(prev_target_buffer), recall)) < 0) {
+			    /*
+			     *  User cancelled the search via ^G. - FM
+			     */
+			    option_statusline(CANCELLED);
+			    sleep(InfoSecs);
+			    goto restore_popup_statusline;
+			}
+			goto check_recall;
+		    }
+		} else if (recall && ch == DNARROW) {
+		    if (FirstRecall) {
+		    /*
+		     *  Use the current string or
+		     *  first query in the list. - FM
+		     */
+		    FirstRecall = FALSE;
+		    if (*prev_target_buffer) {
+			for (QueryNum = 0;
+			     QueryNum < (QueryTotal - 1); QueryNum++) {
+			    if ((cp = (char *)HTList_objectAt(
+							search_queries,
+							QueryNum)) != NULL &&
+				!strcmp(prev_target_buffer, cp)) {
+				    break;
+			    }
+			}
+		    } else {
+			QueryNum = (QueryTotal - 1);
+		    }
+		} else {
+		    /*
+		     *  Advance to the next query in the list. - FM
+		     */
+		    QueryNum--;
+		}
+		if (QueryNum < 0)
+		    /*
+		     *  Roll around to the first query in the list. - FM
+		     */
+		    QueryNum = (QueryTotal - 1);
+		    if ((cp = (char *)HTList_objectAt(search_queries,
+	    					      QueryNum)) != NULL) {
+			strcpy(prev_target, cp);
+			if (*prev_target_buffer &&
+			    !strcmp(prev_target_buffer, prev_target)) {
+			    option_statusline(EDIT_CURRENT_QUERY);
+			} else if ((*prev_target_buffer &&
+				    QueryTotal == 2) ||
+				   (!(*prev_target_buffer) &&
+				    QueryTotal == 1)) {
+			    option_statusline(EDIT_THE_PREV_QUERY);
+			} else {
+			    option_statusline(EDIT_A_PREV_QUERY);
+			}
+			if ((ch = LYgetstr(prev_target, VISIBLE,
+					   sizeof(prev_target_buffer),
+					   recall)) < 0) {
+			    /*
+			     * User cancelled the search via ^G. - FM
+			     */
+			    option_statusline(CANCELLED);
+			    sleep(InfoSecs);
+			    goto restore_popup_statusline;
+	    		}
+			goto check_recall;
+		    }
+ 		}
+		/*
+		 *  Replace the search string buffer with the new target. - FM
+		 */
+		strcpy(prev_target_buffer, prev_target);
+		HTAddSearchQuery(prev_target_buffer);
+
+		/*
+		 *  Start search at the next choice. - FM
+		 */
+		for (j = 1; Cptr[i+j] != NULL; j++) {
+		    sprintf(buffer, "%s%d: %s",
+				    ((num_choices > 8 && (j + i) < 9) ?
+								  " " : ""),
+				    (i + j + 1),
+				    Cptr[i+j]);
+		    if (case_sensitive) {
+			if (strstr(buffer, prev_target_buffer) != NULL)
+			    break;
+		    } else {
+			if (LYstrstr(buffer, prev_target_buffer) != NULL)
+			    break;
+		    }
+		}
+		if (Cptr[i+j] != NULL) {
+		    /*
+		     *  We have a hit, so make that choice the current. - FM
+		     */
+		    cur_choice += j;
+		    /*
+		     *  Scroll the window down if necessary.
+		     */
+		    if ((cur_choice - window_offset) >= length) {
+		        window_offset += j;
+			if (window_offset > (num_choices - length + 1))
+			    window_offset = (num_choices - length + 1);
+			ReDraw = TRUE;
+		    }
+		    goto restore_popup_statusline;
+		}
+
+		/*
+		 *  If we started at the beginning, it can't be present. - FM
+		 */
+		if (cur_choice == 0) {
+		    _user_message(STRING_NOT_FOUND, prev_target_buffer);
+		    sleep(MessageSecs);
+		    goto restore_popup_statusline;
+		}
+
+		/*
+		 *  Search from the beginning to the current choice. - FM
+		 */
+		for (j = 0; j < cur_choice; j++) {
+		    sprintf(buffer, "%s%d: %s",
+				    ((num_choices > 8 && j < 9) ?
+							    " " : ""),
+				    (j + 1),
+				    Cptr[j]);
+		    if (case_sensitive) {
+			if (strstr(buffer, prev_target_buffer) != NULL)
+			    break;
+		    } else {
+			if (LYstrstr(buffer, prev_target_buffer) != NULL)
+			    break;
+		    }
+		}
+		if (j < cur_choice) {
+		    /*
+		     *  We have a hit, so make that choice the current. - FM
+		     */
+		    j = (cur_choice - j);
+		    cur_choice -= j;
+		    /*
+		     *  Scroll the window up if necessary.
+		     */
+		    if ((cur_choice - window_offset) < 0) {
+		        window_offset -= j;
+			if (window_offset < 0)
+			    window_offset = 0;
+			ReDraw = TRUE;
+		    }
+		    goto restore_popup_statusline;
+		}
+
+		/*
+		 *  Didn't find it in the preceding choices either. - FM
+		 */
+		_user_message(STRING_NOT_FOUND, prev_target_buffer);
+		sleep(MessageSecs);
+
+restore_popup_statusline:
+		/*
+		 *  Restore the popup statusline and
+		 *  reset the search variables. - FM
+		 */
+		if (disabled)
+		    option_statusline(CHOICE_LIST_UNM_MSG);
+   		else
+		    option_statusline(CHOICE_LIST_MESSAGE);
+		*prev_target = '\0';
+		QueryTotal = (search_queries ? HTList_count(search_queries)
+					     : 0);
+		recall = ((QueryTotal >= 1) ? RECALL : NORECALL);
+		QueryNum = QueryTotal;
+		if (ReDraw == TRUE) {
+		    ReDraw = FALSE;
+		    goto redraw;
+		}
+		break;
+
+	    case LYK_QUIT:
+	    case LYK_ABORT:
+	    case LYK_PREV_DOC:
+		cur_choice = orig_choice;
+		term_options = TRUE;
+		option_statusline(CANCELLED);
+		sleep(MessageSecs);
+		cmd = LYK_ACTIVATE; /* to exit */
+		break;
+        }
+    }
+#ifndef USE_SLANG
+    delwin(form_window);
+#endif /* !USE_SLANG */
+
+    if (disabled || term_options) {
+	option_statusline("");
+        return(orig_choice);
+    } else {
+	option_statusline(VALUE_ACCEPTED);
+	return(cur_choice);
+    }
+}