about summary refs log tree commit diff stats
path: root/src/LYMainLoop.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/LYMainLoop.c')
-rw-r--r--src/LYMainLoop.c689
1 files changed, 458 insertions, 231 deletions
diff --git a/src/LYMainLoop.c b/src/LYMainLoop.c
index 8bdc0ae0..f3e5835e 100644
--- a/src/LYMainLoop.c
+++ b/src/LYMainLoop.c
@@ -1,5 +1,6 @@
 #include <HTUtils.h>
 #include <HTAccess.h>
+#include <HTParse.h>
 #include <HTList.h>
 #include <HTML.h>
 #include <HTFTP.h>
@@ -56,15 +57,13 @@
 
 
 PRIVATE void exit_immediately_with_error_message PARAMS((int state, BOOLEAN first_file));
-PRIVATE void print_status_message PARAMS((CONST linkstruct curlink, char **cp));
+PRIVATE void show_main_statusline PARAMS((CONST linkstruct curlink));
 PRIVATE BOOL confirm_post_resub PARAMS((
     CONST char*		address,
     CONST char*		title,
     int			if_imgmap,
     int			if_file));
 PRIVATE int are_different PARAMS((document *doc1, document *doc2));
-PUBLIC void HTGotoURLs_free NOPARAMS;
-PUBLIC void HTAddGotoURL PARAMS((char *url));
 
 #ifndef DONT_TRACK_INTERNAL_LINKS
 PRIVATE int are_phys_different PARAMS((document *doc1, document *doc2));
@@ -173,10 +172,36 @@ PUBLIC BOOLEAN LYOpenTraceLog NOARGS
 	fprintf(tfp, "\t\t%s (%s)\n\n", LYNX_TRACELOG_TITLE, LYNX_VERSION);
 	/*
 	 *  If TRACE is on, indicate whether the
-	 *  anonymous restrictions are set. - FM
+	 *  anonymous restrictions are set. - FM, LP, kw
+	 *  This is only a summary for convenience - it doesn't
+	 *  take the case of individual -restrictions= options
+	 *  into account. - kw
 	 */
-	if (LYRestricted) {
-	    CTRACE(tfp, "Anonymous restrictions are set.\n");
+	if (LYValidate) {
+	    if (LYRestricted && had_restrictions_default) {
+		CTRACE(tfp, "Validate and some anonymous restrictions are set.\n");
+	    } else if (had_restrictions_default) {
+		CTRACE(tfp, "Validate restrictions set, restriction \"default\" was given.\n");
+	    } else if (LYRestricted) {
+		CTRACE(tfp, "Validate restrictions set, additional anonymous restrictions ignored.\n");
+	    } else {
+		CTRACE(tfp, "Validate restrictions are set.\n");
+	    }
+	    /* But none of the above can actually happen, since there should
+	     * never be a Trace Log with -validate.  If it appears in a log
+	     * file something went wrong! */
+	} else if (LYRestricted) {
+	    if (had_restrictions_all) {
+		CTRACE(tfp, "Anonymous restrictions set, restriction \"all\" was given.\n");
+	    } else {
+		CTRACE(tfp, "Anonymous restrictions are set.\n");
+	    }
+	} else if (had_restrictions_all && had_restrictions_default) {
+	    CTRACE(tfp, "Restrictions \"all\" and \"default\" were given.\n");
+	} else if (had_restrictions_default) {
+	    CTRACE(tfp, "Restriction \"default\" was given.\n");
+	} else if (had_restrictions_all) {
+	    CTRACE(tfp, "\"all\" restrictions are set.\n");
 	}
     }
     return TRUE;
@@ -207,16 +232,29 @@ PRIVATE BOOLEAN LYReopenTracelog ARGS1(BOOLEAN *, trace_flag_ptr)
     return TRUE;
 }
 
-PRIVATE void do_change_link ARGS1(
+PRIVATE int do_change_link ARGS1(
 	char *,		prev_target)
 {
     /* Is there a mouse-clicked link waiting? */
     int mouse_tmp = get_mouse_link();
     /* If yes, use it as the link */
     if (mouse_tmp != -1) {
+	if (curdoc.link >= 0 && curdoc.link < nlinks &&
+	    curdoc.link != mouse_tmp) {
 	highlight(OFF, curdoc.link, prev_target);
+	}
+	if (mouse_tmp < 0 || mouse_tmp >= nlinks) {
+	    char *msgtmp = NULL;
+	    HTSprintf0(&msgtmp,
+		       gettext("Internal error: Invalid mouse link %d!"),
+		       mouse_tmp);
+	    HTAlert(msgtmp);
+	    FREE(msgtmp);
+	    return(-1);		/* indicates unexpected error */
+	}
 	curdoc.link = mouse_tmp;
     }
+    return(0);			/* indicates OK */
 }
 
 /*
@@ -238,6 +276,7 @@ int mainloop NOARGS
     char user_input_buffer[1024];
     char *owner_address = NULL;  /* Holds the responsible owner's address     */
     char *ownerS_address = NULL; /* Holds owner's address during source fetch */
+    CONST char *cshelpfile = NULL;
     BOOLEAN first_file = TRUE;
     BOOLEAN popped_doc = FALSE;
     BOOLEAN refresh_screen = FALSE;
@@ -283,11 +322,13 @@ int mainloop NOARGS
     newdoc.post_data = NULL;
     newdoc.post_content_type = NULL;
     newdoc.bookmark = NULL;
+    newdoc.internal_link = FALSE;
     curdoc.address = NULL;
     curdoc.title = NULL;
     curdoc.post_data = NULL;
     curdoc.post_content_type = NULL;
     curdoc.bookmark = NULL;
+    curdoc.internal_link = FALSE;
 #ifdef USE_HASH
     curdoc.style = NULL;
     newdoc.style = NULL;
@@ -305,7 +346,6 @@ initialize:
     StrAllocCopy(newdoc.title, gettext("Entry into main screen"));
     newdoc.isHEAD = FALSE;
     newdoc.safe = FALSE;
-    newdoc.internal_link = FALSE;
     newdoc.line = 1;
     newdoc.link = 0;
 
@@ -600,43 +640,74 @@ try_again:
 		     *	Do any error logging, if appropriate.
 		     */
 		    LYoverride_no_cache = FALSE; /* Was TRUE if popped. - FM */
-		    popped_doc = FALSE;		 /* Was TRUE if popped. - FM */
 		    LYinternal_flag = FALSE;	 /* Reset to default. - kw */
 		    if (trace_mode_flag == TRUE) {
 			WWW_TraceFlag = TRUE;
 			trace_mode_flag = FALSE;
 			fprintf(tfp, "Turning TRACE back on.\n\n");
 		    }
-		    if (error_logging &&
-			first_file && owner_address && !LYCancelledFetch) {
+		    if (!first_file && !LYCancelledFetch) {
 			/*
+			 *  Do error mail sending and/or traversal
+			 *  stuff.  Note that the links[] elements may
+			 *  not be valid at this point, if we did call
+			 *  HTuncache_current_document!   This should
+			 *  not have happened for traversal, but for
+			 *  sending error mail check that HTMainText
+			 *  exists for this reason. - kw
+			 */
+			if (error_logging && nhist > 0 && !popped_doc &&
+			    !LYUserSpecifiedURL &&
+			    HTMainText &&
+			    nlinks > 0 && curdoc.link < nlinks &&
+			    strncmp(newdoc.address ? newdoc.address : "",
+				    "LYNXHIST:", 9) &&
+			    strncmp(newdoc.address ? newdoc.address : "",
+				    "LYNXCOOKIE:", 11)) {
+			    char *mail_owner = NULL;
+			    if (owner_address &&
+				strncasecomp(owner_address, "mailto:", 7)) {
+				mail_owner = owner_address + 7;
+			    }
+			    /*
 			 *  Email a bad link message to the owner of
-			 *  the document (but NOT to lynx-dev). - FM
+			 *  the document, or to ALERTMAIL if defined,
+			 *  but NOT to lynx-dev (it is rejected in
+			 *  mailmsg). - FM, kw
 			 */
-			if (strncasecomp(owner_address, "mailto:", 7)) {
-			    if (strncasecomp((owner_address + 7),
-					     "lynx-dev@", 9)) {
+#ifndef ALERTMAIL
+			    if (mail_owner)
+#endif
 				mailmsg(curdoc.link,
-					(owner_address+7),
+					mail_owner,
 					history[nhist-1].address,
 					history[nhist-1].title);
-			    }
 			}
-		    }
-		    if (traversal && !first_file && !LYCancelledFetch) {
-			FILE *ofp;
+			if (traversal) {
+			    FILE *ofp;
 
-			if ((ofp = LYAppendToTxtFile(TRAVERSE_ERRORS)) == NULL) {
-			    if ((ofp = LYNewTxtFile(TRAVERSE_ERRORS)) == NULL) {
-				perror(NOOPEN_TRAV_ERR_FILE);
-				exit_immediately(-1);
+			    if ((ofp = LYAppendToTxtFile(TRAVERSE_ERRORS)) == NULL) {
+				if ((ofp = LYNewTxtFile(TRAVERSE_ERRORS)) == NULL) {
+				    perror(NOOPEN_TRAV_ERR_FILE);
+				    exit_immediately(-1);
+				}
+			    }
+			    if (nhist > 0) {
+				fprintf(ofp,
+					"%s %s\tin %s\n",
+					popped_doc ?
+					newdoc.address : links[curdoc.link].lname,
+					links[curdoc.link].target,
+					history[nhist-1].address);
+			    } else {
+				fprintf(ofp,
+					"%s %s\t\n",
+					popped_doc ?
+					newdoc.address : links[curdoc.link].lname,
+					links[curdoc.link].target);
 			    }
+			    fclose(ofp);
 			}
-			fprintf(ofp, "%s %s\tin %s\n",
-				     links[curdoc.link].lname,
-				     links[curdoc.link].target,
-				     history[nhist-1].address);
-			fclose(ofp);
 		    }
 
 		    /*
@@ -727,13 +798,23 @@ try_again:
 		    }
 
 		   /*
+		    *  If we're going to pop from history because
+		    *  getfile didn't succeed, reset LYforce_no_cache
+		    *  first.  This would have been done in HTAccess.c
+		    *  if the request got that far, but the URL may
+		    *  have been handled or rejected in getfile without
+		    *  taking care of that. - kw
+		    */
+		    LYforce_no_cache = FALSE;
+		   /*
 		    *  Retrieval of a newdoc just failed, and just
 		    *  going to try_again would pop the next doc
 		    *  from history and try to get it without further
 		    *  questions.  This may not be the right thing to do if
 		    *  we have POST data, so fake a PREV_DOC key if it seems
-		    *  that some prompting should be done.  Dunno about the
-		    *  traversal logic, so I leave that case alone.
+		    *  that some prompting should be done.  This doesn't
+		    *  affect the traversal logic, since with traversal
+		    *  POST data can never occur. - kw
 		    */
 		   if (history[nhist - 1].post_data &&
 		       !history[nhist - 1].safe) {
@@ -933,7 +1014,7 @@ try_again:
 		     */
 #ifdef DISP_PARTIAL
 		    /* Newline = newdoc.line; */
-		    /* - alreary set and probably updated in partial mode */
+		    /* - already set and probably updated in partial mode */
 		    /* incremental rendering stage already closed (but see below) */
 
 		    if (Newline != Newline_partial || display_partial == TRUE) {
@@ -1037,7 +1118,7 @@ try_again:
 	   LYNoRefererForThis = FALSE;	/* always reset on return here */
 	   reloading = FALSE;		/* only set for RELOAD and RESUBMIT */
 	   HEAD_request = FALSE;	/* only set for HEAD requests */
-	   LYPermitURL = FALSE;		/* only set for LYValidate */
+	   LYPermitURL = FALSE;		/* only for LYValidate or check_realm */
 	   ForcePush = FALSE;		/* only set for some PRINT requests. */
 	   LYforce_HTML_mode = FALSE;
 	   popped_doc = FALSE;
@@ -1058,9 +1139,27 @@ try_again:
 	 *  then the window size changed recently.
 	 */
 	if (recent_sizechange) {
+	    /*
+	     *  First we need to make sure the display library - curses, slang,
+	     *  whatever - gets notified about the change, and gets a chance
+	     *  to update external structures appropriately.  Hopefully the
+	     *  stop_curses()/start_curses() sequence achieves this, at least
+	     *  if the display library has a way to get the new screen size
+	     *  from the OS.
+	     *  However, at least for ncurses, the update of the internal
+	     *  structures will come still too late - the changed screen
+	     *  size is detected in doupdate(), which would only be called
+	     *  (indirectly through the HText_pageDisplay below) after the
+	     *  WINDOW structures are already filled based on the old size.
+	     *  So we notify the ncurses library directly here. - kw
+	     */
+#ifdef NCURSES_VERSION		/* FIXME: check for specific version? */
+	    resizeterm(LYlines, LYcols);
+#else
 		stop_curses();
 		start_curses();
 		clear();
+#endif
 		refresh_screen = TRUE; /* to force a redraw */
 		if (HTMainText)	/* to REALLY force it... - kw */
 		    HText_setStale(HTMainText);
@@ -1220,7 +1319,7 @@ try_again:
 	 *  Trying to accomodate HTreparse_document() logic
 	 *  with mainloop events.  Working out of force_load cycle
 	 *  set all the necessary flags here, from case NORMAL
-	 *  (see also LYK_SOURCE, some staff implemented directly there).
+	 *  (see also LYK_SOURCE, some stuff implemented directly there).
 	 */
 	if (from_source_cache) {
 	    from_source_cache = FALSE; /* done */
@@ -1285,7 +1384,10 @@ try_again:
 		    /*
 		     *	We may have popped a doc (possibly in local_dired)
 		     *	which didn't have any links when it was pushed, but
-		     *	does have links now (e.g., a file was created) - KW
+		     *	does have links now (e.g., a file was created).
+		     *  Code below assumes that curdoc.link is valid and
+		     *  that (curdoc.link==-1) only occurs if (nlinks==0)
+		     *  is true. - KW
 		     */
 		    curdoc.link = 0;
 		}
@@ -1322,6 +1424,20 @@ try_again:
 	     */
 	    more = HText_canScrollDown();
 
+	    /*
+	     *  Adjust curdoc.link as above; nlinks may have changed,
+	     *  if the refresh_screen flag was set as a result of
+	     *  a size change.
+	     *  Code below assumes that curdoc.link is valid and
+	     *  that (curdoc.link==-1) only occurs if (nlinks==0)
+	     *  is true. - kw
+	     */
+	    if (curdoc.link >= nlinks) {
+		curdoc.link = nlinks - 1;
+	    } else if (curdoc.link < 0 && nlinks > 0) {
+		curdoc.link = 0;
+	    }
+
 	    if (user_mode == NOVICE_MODE)
 		noviceline(more);  /* print help message */
 	    refresh_screen = FALSE;
@@ -1340,7 +1456,7 @@ try_again:
 	 *  to tell the user other misc info.
 	 */
 	if (!show_help) {
-	   print_status_message(links[curdoc.link], &cp);
+	   show_main_statusline(links[curdoc.link]);
 	} else {
 	   show_help = FALSE;
 	}
@@ -1397,6 +1513,8 @@ try_again:
 		 links[curdoc.link].form->type == F_TEXT_SUBMIT_TYPE ||
 		 links[curdoc.link].form->type == F_PASSWORD_TYPE ||
 		 links[curdoc.link].form->type == F_TEXTAREA_TYPE)) {
+
+		BOOLEAN use_last_tfpos;
 		/*
 		 *  Replace novice lines if in NOVICE_MODE.
 		 */
@@ -1406,12 +1524,33 @@ try_again:
 		    move(LYlines-1,0); clrtoeol();
 		    addstr(FORM_NOVICELINE_TWO);
 		}
-		c = change_form_link(&links[curdoc.link],
+		use_last_tfpos = (real_cmd==LYK_LPOS_PREV_LINK ||
+				  real_cmd==LYK_LPOS_NEXT_LINK);
+		real_c = change_form_link(&links[curdoc.link],
 				     &newdoc, &refresh_screen,
 				     links[curdoc.link].form->name,
-				     links[curdoc.link].form->value);
+					  links[curdoc.link].form->value,
+					  use_last_tfpos, FALSE);
 
-		if (c == '\n' || c == '\r') {
+		c = (real_c==LKC_DONE) ? DO_NOTHING : LKC_TO_C(real_c);
+		if (c != DO_NOTHING &&
+		    peek_mouse_link() != -1 && peek_mouse_link() != -2)
+		    old_c = 0;
+		if (peek_mouse_link() >= 0 &&
+		    LKC_TO_LAC(keymap,real_c) != LYK_CHANGE_LINK) {
+		    do_change_link(prev_target);
+		    if ((c == '\n' || c == '\r') &&
+			links[curdoc.link].type == WWW_FORM_LINK_TYPE &&
+			(links[curdoc.link].form->type == F_TEXT_TYPE ||
+			 links[curdoc.link].form->type == F_TEXT_SUBMIT_TYPE ||
+			 links[curdoc.link].form->type == F_PASSWORD_TYPE ||
+			 links[curdoc.link].form->type == F_TEXTAREA_TYPE)) {
+			c = DO_NOTHING;
+		    }
+		} else
+		    switch (c) {
+		    case '\n':
+		    case '\r':
 #ifdef AUTOGROW
 		    /*
 		     *  If on the bottom line of a TEXTAREA, and the user hit
@@ -1429,6 +1568,8 @@ try_again:
 		     */
 		    if ((links[curdoc.link].type       == WWW_FORM_LINK_TYPE &&
 			 links[curdoc.link].form->type == F_TEXTAREA_TYPE)
+/*			&&
+			 (peek_mouse_link() == -1) */
 			&&
 			 ((curdoc.link == nlinks-1)
 			 ||
@@ -1464,17 +1605,17 @@ try_again:
 		   }
 #endif /* AUTOGROW */
 
-#ifdef FASTTAB
 		    /*
-		     *	Make return act like down-arrow.
+		     *	Make return in input field (if it was returned
+		     *  by change_form_link) act as LYK_NEXT_LINK,
+		     *  independent of what key (if any) is mapped to
+		     *  LYK_NEXT_LINK. - kw
 		     */
-		    c = DNARROW;
-#else
-		    /*
-		     *	Make return act like tab.
-		     */
-		    c = '\t';
-#endif /* FASTTAB */
+		    c = LAC_TO_LKC0(LYK_NEXT_LINK);
+		    break;
+		default:
+		    if (old_c != c && old_c != real_c && c != real_c)
+			real_c = c;
 		}
 	    } else {
 		/*
@@ -1496,6 +1637,19 @@ try_again:
 		    goto new_cmd;
 		}
 #endif /* !VMS */
+		if (LKC_HAS_ESC_MOD(c) && EditBinding(c) != LYE_FORM_PASS) {
+		    /*
+		     *  If ESC + <key> was read (and not recognized as a
+		     *  terminal escape sequence for another key), ignore
+		     *  the ESC modifier and act on <key> only if the line
+		     *  editor binding would have passed the same ESC-modified
+		     *  lynxkeycode back to us if it had been pressed in a
+		     *  text input field.  Otherwise set interesting part
+		     *  so that it will map to 0, to prevent that ESC + <key>
+		     *  acts like <key>, which might be unexpected. - kw
+		     */
+		    c = (c & ~LKC_MASK) | LAC_TO_LKC(0);
+		}
 		if (old_c != real_c) {
 		    old_c = 0;
 		}
@@ -1527,10 +1681,14 @@ new_keyboard_input:
 	     *	"traversal_host" are searched - this keeps the search
 	     *	from crossing to other servers (a feature, not a bug!).
 	     */
-	    rlink_exists = (nlinks > 0 && links[curdoc.link].lname != NULL);
+	    BOOLEAN rlink_rejected = FALSE;
+	    rlink_exists = (nlinks > 0 &&
+			    links[curdoc.link].type != WWW_FORM_LINK_TYPE &&
+			    links[curdoc.link].lname != NULL);
 	    if (rlink_exists) {
+		rlink_rejected = lookup_reject(links[curdoc.link].lname);
 		rlink_allowed =
-		    (!lookup_reject(links[curdoc.link].lname) &&
+		    (!rlink_rejected &&
 		     traversal_host && links[curdoc.link].lname &&
 		     !strncmp(traversal_host,
 			      (strncmp(links[curdoc.link].lname,
@@ -1565,7 +1723,8 @@ new_keyboard_input:
 		    c = RTARROW;
 		}
 	    } else { /* no good right link, so only down and left arrow ok*/
-		if (rlink_exists)
+		if (rlink_exists /* && !rlink_rejected */)
+		    /* uncomment in previous line to avoid duplicates - kw */
 		    add_to_reject_list(links[curdoc.link].lname);
 		if (more_links ||
 		    (curdoc.link > -1 && curdoc.link < nlinks-1))
@@ -1588,11 +1747,11 @@ new_keyboard_input:
 	    } /* right link not NULL or link to another site*/
 	} /* traversal */
 
-	cmd = keymap[c+1];  /* add 1 to map EOF to 0 */
+	cmd = LKC_TO_LAC(keymap,c);  /* adds 1 to map EOF to 0 */
 
 #if defined(DIRED_SUPPORT) && defined(OK_OVERRIDE)
-	if (lynx_edit_mode && key_override[c+1] && !no_dired_support)
-	  cmd = key_override[c+1];
+	if (lynx_edit_mode && !no_dired_support && LKC_TO_LAC(key_override,c))
+	  cmd = LKC_TO_LAC(key_override,c);
 #endif /* DIRED_SUPPORT && OK_OVERRIDE */
 
 	real_cmd = cmd;
@@ -1607,7 +1766,15 @@ new_cmd:  /*
 	switch(cmd) {
 	case 0: /* unmapped character */
 	default:
-	    if (more)
+	    if (curdoc.link >= 0 && curdoc.link < nlinks &&
+		links[curdoc.link].type == WWW_FORM_LINK_TYPE &&
+		(links[curdoc.link].form->type == F_TEXT_TYPE ||
+		 links[curdoc.link].form->type == F_TEXT_SUBMIT_TYPE ||
+		 links[curdoc.link].form->type == F_PASSWORD_TYPE ||
+		 links[curdoc.link].form->type == F_TEXTAREA_TYPE))
+		
+		show_main_statusline(links[curdoc.link]);
+	    else if (more)
 		_statusline(MOREHELP);
 	    else
 		_statusline(HELP);
@@ -2303,6 +2470,7 @@ new_cmd:  /*
 	    break;
 
 	case LYK_PREV_LINK:
+	case LYK_LPOS_PREV_LINK:
 	    if (curdoc.link > 0) {	     /* previous link */
 		/*
 		 *  Unhighlight current link.
@@ -2345,6 +2513,7 @@ new_cmd:  /*
 	    break;
 
 	case LYK_NEXT_LINK:
+	case LYK_LPOS_NEXT_LINK:
 	    if (curdoc.link < nlinks-1) {	/* next link */
 		highlight(OFF, curdoc.link, prev_target);
 #ifdef FASTTAB
@@ -2860,7 +3029,8 @@ new_cmd:  /*
 	    if (nlinks > 0) {
 		if (links[curdoc.link].type == WWW_FORM_LINK_TYPE &&
 		    links[curdoc.link].form->type != F_SUBMIT_TYPE &&
-		    links[curdoc.link].form->type != F_IMAGE_SUBMIT_TYPE) {
+		    links[curdoc.link].form->type != F_IMAGE_SUBMIT_TYPE &&
+		    links[curdoc.link].form->type != F_TEXT_SUBMIT_TYPE) {
 		    if (old_c == real_c)
 			break;
 		    old_c = real_c;
@@ -2873,11 +3043,11 @@ new_cmd:  /*
 	    } /* fall through to LYK_ACTIVATE */
 
 	case LYK_ACTIVATE:			/* follow a link */
-	    {
-	     /* Is there a mouse-clicked link waiting? */
-	     int mouse_tmp = get_mouse_link();
-	     /* If yes, use it as the link */
-	     if (mouse_tmp != -1) curdoc.link = mouse_tmp;
+	case LYK_SUBMIT:	/* follow a link, submit TEXT_SUBMIT input */
+	    if (do_change_link(prev_target) == -1) {
+		LYforce_no_cache = FALSE;
+		reloading = FALSE;
+		continue;	/* mouse stuff was confused, ignore - kw */
 	    }
 	     if (nlinks > 0) {
 		if (links[curdoc.link].type == WWW_FORM_LINK_TYPE) {
@@ -3014,36 +3184,107 @@ new_cmd:  /*
 			    !strncmp(curdoc.address, "file:", 5)) {
 			    LYNoRefererForThis = TRUE;
 			}
-			StrAllocCopy(newdoc.title,
-				     links[curdoc.link].hightext);
+			if (links[curdoc.link].form->submit_method
+				     != URL_MAIL_METHOD) {
+			    StrAllocCopy(newdoc.title,
+					 links[curdoc.link].hightext);
+			}
+		    }
+		    /*
+		     *	Normally we don't get here for text input fields,
+		     *  but it can happen as a result of mouse positioning.
+		     *  In that case the statusline will not have updated
+		     *  info, so update it now. - kw
+		     */
+
+		    if (links[curdoc.link].form->type == F_TEXT_TYPE ||
+			links[curdoc.link].form->type == F_TEXT_SUBMIT_TYPE ||
+			links[curdoc.link].form->type == F_PASSWORD_TYPE ||
+			links[curdoc.link].form->type == F_TEXTAREA_TYPE) {
+			show_formlink_statusline(links[curdoc.link].form);
 		    }
+ 
 		    c = change_form_link(&links[curdoc.link],
 					 &newdoc, &refresh_screen,
 					 links[curdoc.link].form->name,
-					 links[curdoc.link].form->value);
-		    if (HTOutputFormat == HTAtom_for("www/download") &&
+					 links[curdoc.link].form->value,
+					 FALSE,
+					 (real_cmd==LYK_SUBMIT ||
+					  real_cmd==LYK_NOCACHE ||
+					  real_cmd==LYK_DOWNLOAD ||
+					  real_cmd==LYK_HEAD));
+		    if (c != LKC_DONE || refresh_screen) {
+			/*
+			 *  Cannot have been a submit field for which
+			 *  newdoc was filled in. - kw
+			 */
+			if ((links[curdoc.link].form->type == F_SUBMIT_TYPE ||
+			     links[curdoc.link].form->type == F_IMAGE_SUBMIT_TYPE ||
+			     links[curdoc.link].form->type == F_TEXT_SUBMIT_TYPE) &&
+			    links[curdoc.link].form->submit_method
+				     != URL_MAIL_METHOD) {
+			    /*
+			     *  Try to undo change of newdoc.title done above.
+			     */
+			    if (HText_getTitle()) {
+				StrAllocCopy(newdoc.title, HText_getTitle());
+			    } else if (curdoc.title) {
+				StrAllocCopy(newdoc.title, curdoc.title);
+			    }
+			}
+		    } else {
+			if (HTOutputFormat == HTAtom_for("www/download") &&
 			newdoc.post_data != NULL &&
 			newdoc.safe == FALSE) {
-			if ((HText_POSTReplyLoaded(&newdoc) == TRUE) &&
-			    HTConfirm(CONFIRM_POST_RESUBMISSION) == FALSE) {
-			    HTInfoMsg(CANCELLED);
-			    HTOutputFormat = WWW_PRESENT;
-			    LYforce_no_cache = FALSE;
-			    StrAllocCopy(newdoc.address, curdoc.address);
-			    StrAllocCopy(newdoc.title, curdoc.title);
-			    StrAllocCopy(newdoc.post_data, curdoc.post_data);
-			    StrAllocCopy(newdoc.post_content_type,
-					 curdoc.post_content_type);
-			    StrAllocCopy(newdoc.bookmark, curdoc.bookmark);
-			    newdoc.isHEAD = curdoc.isHEAD;
-			    newdoc.safe = curdoc.safe;
-			    newdoc.internal_link = curdoc.internal_link;
-			    break;
+			    if ((HText_POSTReplyLoaded(&newdoc) == TRUE) &&
+				HTConfirm(CONFIRM_POST_RESUBMISSION) == FALSE) {
+				HTInfoMsg(CANCELLED);
+				HTOutputFormat = WWW_PRESENT;
+				LYforce_no_cache = FALSE;
+				StrAllocCopy(newdoc.address, curdoc.address);
+				StrAllocCopy(newdoc.title, curdoc.title);
+				StrAllocCopy(newdoc.post_data, curdoc.post_data);
+				StrAllocCopy(newdoc.post_content_type,
+					     curdoc.post_content_type);
+				StrAllocCopy(newdoc.bookmark, curdoc.bookmark);
+				newdoc.isHEAD = curdoc.isHEAD;
+				newdoc.safe = curdoc.safe;
+				newdoc.internal_link = curdoc.internal_link;
+				break;
+			    }
+			}
+			/*
+			 *  Moved here from earlier to only apply when it
+			 *  should.   Anyway, why should realm checking be
+			 *  overridden for form submissions, this seems to
+			 *  be an unnecessary loophole??  But that's the way
+			 *  it was, maybe there is some reason.
+			 *  However, at least make sure this doesn't weaken
+			 *  restrictions implied by -validate!
+			 *  - kw 1999-05-25
+			 */
+			if (check_realm && !LYValidate) {
+			    LYPermitURL = TRUE;
 			}
 		    }
-		    if (c == 23) {
+		    if (c == LKC_DONE) {
+			c = DO_NOTHING;
+		    } else if (c == 23) {
 			c = DO_NOTHING;
 			refresh_screen = TRUE;
+		    } else
+			switch (LKC_TO_C(c)) {
+			case '\n':
+			case '\r':
+			    /*  Avoid getting stuck with repeatedly calling
+			    **  the second change_form_link() instead of the
+			    **  first for text input fields. - kw
+			    */
+			    if (peek_mouse_link() == -1 ||
+				peek_mouse_link() == curdoc.link)
+				c = DO_NOTHING;
+			default:
+			    break;
 		    }
 		    goto new_keyboard_input;
 		} else {
@@ -3055,7 +3296,12 @@ new_cmd:  /*
 		     */
 		    if (no_file_url &&
 			!strncmp(links[curdoc.link].lname, "file:", 5)) {
-			if (strncmp(curdoc.address, "file:", 5)) {
+			if (strncmp(curdoc.address, "file:", 5) &&
+			    !((!strncmp(curdoc.address, "LYNXKEYMAP:", 11) ||
+			       !strncmp(curdoc.address, "LYNXCOOKIE:", 11)) &&
+			      !strncmp(links[curdoc.link].lname,
+				       helpfilepath,
+				       strlen(helpfilepath)))) {
 			    HTAlert(FILE_SERVED_LINKS_DISALLOWED);
 			    reloading = FALSE;
 			    break;
@@ -3697,12 +3943,15 @@ check_goto_URL:
 		       !strncmp(user_input_buffer, "wais:", 5)) {
 		HTUserMsg(GOTO_WAIS_DISALLOWED);
 
+	    } else if (no_goto_configinfo &&
+		       (!strncmp(user_input_buffer, "LYNXCFG:", 8) ||
+			!strncmp(user_input_buffer, "LYNXCOMPILEOPTS:", 16))) {
+		HTUserMsg(GOTO_SPECIAL_DISALLOWED);
+
 	    } else if (!strncmp(user_input_buffer, "LYNXCOOKIE:", 11) ||
 		       !strncmp(user_input_buffer, "LYNXDIRED:", 10) ||
 		       !strncmp(user_input_buffer, "LYNXDOWNLOAD:", 13) ||
 		       !strncmp(user_input_buffer, "LYNXOPTIONS:", 12) ||
-		       !strncmp(user_input_buffer, "LYNXCFG:", 8) ||
-		       !strncmp(user_input_buffer, "LYNXCOMPILEOPTS:", 16) ||
 		       !strncmp(user_input_buffer, "LYNXPRINT:", 10)) {
 		HTUserMsg(GOTO_SPECIAL_DISALLOWED);
 
@@ -3734,12 +3983,30 @@ check_goto_URL:
 	    }
 	    break;
 
+	case LYK_DWIMHELP:		/* show context-dependent help file */
+	    /*
+	     *  Currently a different help file form the main
+	     *  'helpfile' is shown only if current link is a
+	     *  text input form field. - kw
+	     */
+	    if (curdoc.link >= 0 && curdoc.link < nlinks &&
+		links[curdoc.link].type == WWW_FORM_LINK_TYPE &&
+		(links[curdoc.link].form->type == F_TEXT_TYPE ||
+		 links[curdoc.link].form->type == F_TEXT_SUBMIT_TYPE ||
+		 links[curdoc.link].form->type == F_PASSWORD_TYPE ||
+		 links[curdoc.link].form->type == F_TEXTAREA_TYPE)) {
+		cshelpfile = LYLineeditHelpURL();
+	    }
+	    /* fall through to LYK_HELP */
+
 	case LYK_HELP:			/* show help file */
-	    if (!STREQ(curdoc.address, helpfile)) {
+	    if (cshelpfile == NULL)
+		cshelpfile = helpfile;
+	    if (!STREQ(curdoc.address, cshelpfile)) {
 		/*
 		 *  Set the filename.
 		 */
-		StrAllocCopy(newdoc.address, helpfile);
+		StrAllocCopy(newdoc.address, cshelpfile);
 		/*
 		 *  Make a name for this help file.
 		 */
@@ -3751,6 +4018,7 @@ check_goto_URL:
 		newdoc.safe = FALSE;
 		newdoc.internal_link = FALSE;
 	    }
+	    cshelpfile = NULL;	/* reset pointer - kw */
 	    break;
 
 	case LYK_INDEX:  /* index file */
@@ -3958,6 +4226,9 @@ if (!LYUseFormsOptions) {
 		newdoc.safe = FALSE;
 		newdoc.internal_link = FALSE;
 		LYforce_no_cache = TRUE;
+		/* change to 'if (check_realm && !LYValidate)' and
+		   make change near top of getfile to forbid
+		   using forms options menu with -validate:  - kw */
 		if (LYValidate || check_realm) {
 		    LYPermitURL = TRUE;
 		}
@@ -4302,14 +4573,8 @@ if (!LYUseFormsOptions) {
 	    break;
 #endif /* DIRED_SUPPORT */
 
-	case LYK_EDIT:	/* edit */
-	    if (no_editor) {
-		if (old_c != real_c) {
-		    old_c = real_c;
-		    HTUserMsg(EDIT_DISABLED);
-		}
-		break;
-	    }
+	case LYK_DWIMEDIT:	/* context-dependent edit */
+
 #ifdef AUTOEXTEDIT
 	    /*
 	     *  If we're in a forms TEXTAREA, invoke the editor on *its*
@@ -4338,8 +4603,25 @@ if (!LYUseFormsOptions) {
 		HTUserMsg (CANNOT_EDIT_FIELD);
 		break;
 	    }
+
+	    if (no_editor) {
+		if (old_c != real_c) {
+		    old_c = real_c;
+		    HTUserMsg(ANYEDIT_DISABLED);
+		}
+		break;
+	    } /* fall through */
 #endif /* AUTOEXTEDIT */
 
+	case LYK_EDIT:	/* edit */
+	    if (no_editor) {
+		if (old_c != real_c) {
+		    old_c = real_c;
+		    HTUserMsg(EDIT_DISABLED);
+		}
+		break;
+	    }
+
 #ifdef DIRED_SUPPORT
 	    /*
 	     *	Allow the user to edit the link rather
@@ -4469,6 +4751,8 @@ if (!LYUseFormsOptions) {
 	     */
 	    if (strcmp((curdoc.title ? curdoc.title : ""),
 		       SHOWINFO_TITLE)) {
+		if (do_change_link(prev_target) == -1)
+		    break;	/* mouse stuff was confused, ignore - kw */
 		if (showinfo(&curdoc, HText_getNumOfLines(),
 			     &newdoc, owner_address) < 0)
 		    break;
@@ -4495,7 +4779,14 @@ if (!LYUseFormsOptions) {
 	    if (no_editor) {
 		if (old_c != real_c) {
 		    old_c = real_c;
-		    HTUserMsg(EDIT_DISABLED);
+		    HTUserMsg(ANYEDIT_DISABLED);
+		}
+		break;
+	    }
+	    if (!editor || *editor == '\0') {
+		if (old_c != real_c) {
+		    old_c = real_c;
+		    HTUserMsg(NO_EDITOR);
 		}
 		break;
 	    }
@@ -4529,7 +4820,7 @@ if (!LYUseFormsOptions) {
 
 	    } else {
 
-		HTInfoMsg (NOT_IN_TEXTAREA);
+		HTInfoMsg (NOT_IN_TEXTAREA_NOEDIT);
 	    }
 	    break;
 
@@ -4557,6 +4848,30 @@ if (!LYUseFormsOptions) {
 	    if (links[curdoc.link].type       == WWW_FORM_LINK_TYPE &&
 		links[curdoc.link].form->type == F_TEXTAREA_TYPE)   {
 
+		/*
+		 *  Reject attempts to use this for gaining access to
+		 *  local files when such access is restricted:
+		 *  if no_file_url was set via the file_url restriction,
+		 *  if no_goto_file was set for the anonymous account,
+		 *  or if HTDirAccess was set to HT_DIR_FORBID or
+		 *  HT_DIR_SELECTIVE via the -nobrowse or -selective
+		 *  switches, it is assumed that inserting files or
+		 *  checking for existence of files needs to be denied. - kw
+		 */
+		if (no_file_url || no_goto_file ||
+		    HTDirAccess == HT_DIR_FORBID ||
+		    HTDirAccess == HT_DIR_SELECTIVE) {
+		    if (old_c != real_c) {
+			old_c = real_c;
+			if (no_goto_file)
+			    HTUserMsg(GOTO_FILE_DISALLOWED);
+			else
+			    HTUserMsg(NOAUTH_TO_ACCESS_FILES);
+			HTInfoMsg(FILE_INSERT_CANCELLED);
+		    }
+		    break;
+		}
+		
 		n = HText_InsertFile (&links[curdoc.link]);
 
 		/*
@@ -4939,7 +5254,7 @@ if (!LYUseFormsOptions) {
 			 *  save either that or the link. - FM
 			 */
 			_statusline(BOOK_D_L_OR_CANCEL);
-			c = LYgetch();
+			c = LYgetch_for(FOR_SINGLEKEY);
 			if (TOUPPER(c) == 'D') {
 			    save_bookmark_link(curdoc.address, curdoc.title);
 			    refresh_screen = TRUE; /* MultiBookmark support */
@@ -4975,7 +5290,7 @@ if (!LYUseFormsOptions) {
 			     */
 			    _statusline(BOOK_L_OR_CANCEL);
 			}
-			c = LYgetch();
+			c = LYgetch_for(FOR_SINGLEKEY);
 		    }
 		    if (TOUPPER(c) == 'L') {
 			if (curdoc.post_data != NULL &&
@@ -5015,7 +5330,7 @@ if (!LYUseFormsOptions) {
 		    break;
 		} else {
 		    _statusline(BOOK_D_OR_CANCEL);
-		    c = LYgetch();
+		    c = LYgetch_for(FOR_SINGLEKEY);
 		    if (TOUPPER(c) == 'D') {
 			save_bookmark_link(curdoc.address, curdoc.title);
 			refresh_screen = TRUE; /* MultiBookmark support */
@@ -5118,10 +5433,13 @@ check_add_bookmark_to_self:
 			DOWNLOAD_OPTIONS_TITLE))
 		break;
 
+	    if (do_change_link(prev_target) == -1)
+		continue;	/* mouse stuff was confused, ignore - kw */
 	    if (nlinks > 0) {
 		if (links[curdoc.link].type == WWW_FORM_LINK_TYPE) {
 		    if (links[curdoc.link].form->type == F_SUBMIT_TYPE ||
-			links[curdoc.link].form->type == F_IMAGE_SUBMIT_TYPE) {
+			links[curdoc.link].form->type == F_IMAGE_SUBMIT_TYPE ||
+			links[curdoc.link].form->type == F_TEXT_SUBMIT_TYPE) {
 			if (links[curdoc.link].form->submit_method ==
 				 URL_MAIL_METHOD) {
 			    if (old_c != real_c) {
@@ -5244,6 +5562,7 @@ check_add_bookmark_to_self:
 				    "LYNXPRINT:", 10) ||
 			   !strncmp(links[curdoc.link].lname,
 				    "LYNXOPTIONS:", 12) ||
+     /* @@@ should next two be downloadable? - kw */
 			   !strncmp(links[curdoc.link].lname,
 				    "LYNXCFG:", 8) ||
 			   !strncmp(links[curdoc.link].lname,
@@ -5447,13 +5766,14 @@ check_add_bookmark_to_self:
 	    if (nlinks > 0 &&
 		(links[curdoc.link].type != WWW_FORM_LINK_TYPE ||
 		 links[curdoc.link].form->type == F_SUBMIT_TYPE ||
-		 links[curdoc.link].form->type == F_IMAGE_SUBMIT_TYPE)) {
+		 links[curdoc.link].form->type == F_IMAGE_SUBMIT_TYPE ||
+		 links[curdoc.link].form->type == F_TEXT_SUBMIT_TYPE)) {
 		/*
 		 *  We have links, and the current link is a
 		 *  normal link or a form's submit button. - FM
 		 */
 		_statusline(HEAD_D_L_OR_CANCEL);
-		c = LYgetch();
+		c = LYgetch_for(FOR_SINGLEKEY);
 		if (TOUPPER(c) == 'D') {
 		    char *scheme = strncmp(curdoc.address, "LYNXIMGMAP:", 11) ?
 			curdoc.address : curdoc.address + 11;
@@ -5534,7 +5854,7 @@ check_add_bookmark_to_self:
 		     *	current document, not the form link. - FM
 		     */
 		    _statusline(HEAD_D_OR_CANCEL);
-		    c = LYgetch();
+		    c = LYgetch_for(FOR_SINGLEKEY);
 		} else {
 		    /*
 		     *	No links, so we can just assume that
@@ -5935,21 +6255,21 @@ PRIVATE int are_phys_different ARGS2(
 /*
  *  Utility for freeing the list of goto URLs. - FM
  */
-PUBLIC void HTGotoURLs_free NOARGS
+#ifdef LY_FIND_LEAKS
+PRIVATE void HTGotoURLs_free NOARGS
 {
     char *url;
     HTList *cur = Goto_URLs;
 
-    if (!cur)
-	return;
-
-    while (NULL != (url = (char *)HTList_nextObject(cur))) {
-	FREE(url);
+    if (cur != 0) {
+	while (NULL != (url = (char *)HTList_nextObject(cur))) {
+	    FREE(url);
+	}
+	HTList_delete(Goto_URLs);
+	Goto_URLs = NULL;
     }
-    HTList_delete(Goto_URLs);
-    Goto_URLs = NULL;
-    return;
 }
+#endif
 
 /*
  *  Utility for listing Goto URLs, making any
@@ -5996,9 +6316,8 @@ PUBLIC void HTAddGotoURL ARGS1(
  *  put a message on the screen
  *  to tell the user other misc info.
  */
-PRIVATE void print_status_message ARGS2(
-	CONST linkstruct,	curlink,
-	char **,		cp)
+PRIVATE void show_main_statusline ARGS1(
+    CONST linkstruct,	curlink)
 {
     /*
      *	Make sure form novice lines are replaced.
@@ -6007,16 +6326,16 @@ PRIVATE void print_status_message ARGS2(
 	noviceline(more);
     }
 
-    /*
-     *	If we are in forms mode then explicitly
-     *	tell the user what each kind of link is.
-     */
     if (HTisDocumentSource()) {
 	/*
 	 *  Currently displaying HTML source.
 	 */
 	_statusline(SOURCE_HELP);
 
+    /*
+     *	If we are in forms mode then explicitly
+     *	tell the user what each kind of link is.
+     */
 #ifdef INDICATE_FORMS_MODE_FOR_ALL_LINKS_ON_PAGE
     } else if (lynx_mode == FORMS_LYNX_MODE && nlinks > 0) {
 #else
@@ -6030,109 +6349,7 @@ PRIVATE void print_status_message ARGS2(
 #endif /* NORMAL_NON_FORM_LINK_STATUSLINES_FOR_ALL_USER_MODES */
 #endif /* INDICATE_FORMS_MODE_FOR_ALL_LINKS_ON_PAGE */
 	if (curlink.type == WWW_FORM_LINK_TYPE) {
-	    switch(curlink.form->type) {
-	    case F_PASSWORD_TYPE:
-		if (curlink.form->disabled == YES)
-		    statusline(FORM_LINK_PASSWORD_UNM_MSG);
-		else
-		    statusline(FORM_LINK_PASSWORD_MESSAGE);
-		break;
-	    case F_OPTION_LIST_TYPE:
-		if (curlink.form->disabled == YES)
-		    statusline(FORM_LINK_OPTION_LIST_UNM_MSG);
-		else
-		    statusline(FORM_LINK_OPTION_LIST_MESSAGE);
-		break;
-	    case F_CHECKBOX_TYPE:
-		if (curlink.form->disabled == YES)
-		    statusline(FORM_LINK_CHECKBOX_UNM_MSG);
-		else
-		    statusline(FORM_LINK_CHECKBOX_MESSAGE);
-		break;
-	    case F_RADIO_TYPE:
-		if (curlink.form->disabled == YES)
-		    statusline(FORM_LINK_RADIO_UNM_MSG);
-		else
-		    statusline(FORM_LINK_RADIO_MESSAGE);
-		break;
-	    case F_TEXT_SUBMIT_TYPE:
-		if (curlink.form->disabled == YES) {
-		    statusline(FORM_LINK_TEXT_SUBMIT_UNM_MSG);
-		} else if (curlink.form->submit_method ==
-			 URL_MAIL_METHOD) {
-		    if (no_mail)
-			statusline(FORM_LINK_TEXT_SUBMIT_MAILTO_DIS_MSG);
-		    else
-			statusline(FORM_LINK_TEXT_SUBMIT_MAILTO_MSG);
-		} else if (curlink.form->no_cache) {
-		    statusline(FORM_LINK_TEXT_RESUBMIT_MESSAGE);
-		} else {
-		    statusline(FORM_LINK_TEXT_SUBMIT_MESSAGE);
-		}
-		break;
-	    case F_SUBMIT_TYPE:
-	    case F_IMAGE_SUBMIT_TYPE:
-		if (curlink.form->disabled == YES) {
-		    statusline(FORM_LINK_SUBMIT_DIS_MSG);
-		} else if (curlink.form->submit_method ==
-			 URL_MAIL_METHOD) {
-		    if (no_mail) {
-			statusline(FORM_LINK_SUBMIT_MAILTO_DIS_MSG);
-		    } else {
-			if(user_mode == ADVANCED_MODE) {
-			    char *submit_str = NULL;
-
-			    StrAllocCopy(submit_str, FORM_LINK_SUBMIT_MAILTO_PREFIX);
-			    StrAllocCat(submit_str, curlink.form->submit_action);
-			    statusline(submit_str);
-			    FREE(submit_str);
-			} else {
-			    statusline(FORM_LINK_SUBMIT_MAILTO_MSG);
-			}
-		    }
-		} else if (curlink.form->no_cache) {
-		    if(user_mode == ADVANCED_MODE) {
-			char *submit_str = NULL;
-
-			StrAllocCopy(submit_str, FORM_LINK_RESUBMIT_PREFIX);
-			StrAllocCat(submit_str, curlink.form->submit_action);
-			statusline(submit_str);
-			FREE(submit_str);
-		    } else {
-			statusline(FORM_LINK_RESUBMIT_MESSAGE);
-		    }
-		} else {
-		    if(user_mode == ADVANCED_MODE) {
-			char *submit_str = NULL;
-
-			StrAllocCopy(submit_str, FORM_LINK_SUBMIT_PREFIX);
-			StrAllocCat(submit_str, curlink.form->submit_action);
-			statusline(submit_str);
-			FREE(submit_str);
-		    } else {
-			statusline(FORM_LINK_SUBMIT_MESSAGE);
-		    }
-		}
-		break;
-	    case F_RESET_TYPE:
-		if (curlink.form->disabled == YES)
-		    statusline(FORM_LINK_RESET_DIS_MSG);
-		else
-		    statusline(FORM_LINK_RESET_MESSAGE);
-		break;
-	    case F_TEXT_TYPE:
-		if (curlink.form->disabled == YES)
-		    statusline(FORM_LINK_TEXT_UNM_MSG);
-		else
-		    statusline(FORM_LINK_TEXT_MESSAGE);
-		break;
-	    case F_TEXTAREA_TYPE:
-		if (curlink.form->disabled == YES)
-		    statusline(FORM_LINK_TEXT_UNM_MSG);
-		else
-		    statusline(FORM_LINK_TEXTAREA_MESSAGE);
-		break;
-	    }
+	    show_formlink_statusline(curlink.form);
 	} else {
 	    statusline(NORMAL_LINK_MESSAGE);
 	}
@@ -6151,24 +6368,23 @@ PRIVATE void print_status_message ARGS2(
 	/*
 	 *  Show the URL or, for some internal links, the fragment
 	 */
-	*cp = NULL;
+	char *cp = NULL;
 	if (curlink.type == WWW_INTERN_LINK_TYPE &&
 	    strncmp(curlink.lname, "LYNXIMGMAP:", 11)) {
-	    *cp = strchr(curlink.lname, '#');
+	    cp = strchr(curlink.lname, '#');
 	}
-	if (!(*cp))
-	    *cp = curlink.lname;
+	if (!cp)
+	    cp = curlink.lname;
 	if (more) {
 	    if (is_www_index)
-		_user_message("-more- -index- %s",
-					 *cp);
+		_user_message("-more- -index- %s", cp);
 	    else
-		_user_message("-more- %s",*cp);
+		_user_message("-more- %s", cp);
 	} else {
 	    if (is_www_index)
-		_user_message("-index- %s",*cp);
+		_user_message("-index- %s", cp);
 	    else
-		statusline(*cp);
+		statusline(cp);
 	}
     } else if (is_www_index && more) {
 	char buf[128];
@@ -6192,6 +6408,17 @@ PRIVATE void print_status_message ARGS2(
     move((LYlines - 1), (LYcols - 1));
 }
 
+/*
+ *  Public function for redrawing the statusline appropriate for the
+ *  selected link.  It should only be called at times when curdoc.link,
+ *  nlinks, and the links[] array are valid. - kw
+ */
+PUBLIC void repaint_main_statusline NOARGS
+{
+    if (curdoc.link >= 0 && curdoc.link < nlinks)
+	show_main_statusline(links[curdoc.link]);
+}
+
 
 PRIVATE void exit_immediately_with_error_message ARGS2(
 	int,		state,