about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorThomas E. Dickey <dickey@invisible-island.net>1997-11-07 12:30:00 -0500
committerThomas E. Dickey <dickey@invisible-island.net>1997-11-07 12:30:00 -0500
commitb63d287c6f3e67f8574ca2155c661288bc7dcd05 (patch)
tree6a3b376424faf4d50058e91988c2d6eaa49cfbdc /src
parent8f8c57cc7c0e876cd291e2b4de23a52e060b30ba (diff)
downloadlynx-snapshots-b63d287c6f3e67f8574ca2155c661288bc7dcd05.tar.gz
snapshot of project "lynx", label v2-7-1ac_0-93
Diffstat (limited to 'src')
-rw-r--r--src/GridText.c95
-rw-r--r--src/HTAlert.c15
-rw-r--r--src/HTAlert.h5
-rw-r--r--src/HTML.c279
-rw-r--r--src/LYCgi.c58
-rw-r--r--src/LYCurses.c18
-rw-r--r--src/LYCurses.h5
-rw-r--r--src/LYDownload.c7
-rw-r--r--src/LYForms.c19
-rw-r--r--src/LYGetFile.c24
-rw-r--r--src/LYGlobalDefs.h3
-rw-r--r--src/LYHistory.c5
-rw-r--r--src/LYList.c73
-rw-r--r--src/LYList.h2
-rw-r--r--src/LYMain.c7
-rw-r--r--src/LYMainLoop.c509
-rw-r--r--src/LYMap.c238
-rw-r--r--src/LYMap.h8
-rw-r--r--src/LYOptions.c10
-rw-r--r--src/LYPrint.c58
-rw-r--r--src/LYStyle.c4
-rw-r--r--src/LYUtils.c82
-rw-r--r--src/LYUtils.h5
-rw-r--r--src/LYexit.c1
-rw-r--r--src/chrtrans/README.format5
-rw-r--r--src/chrtrans/cp437_uni.tbl6
-rw-r--r--src/chrtrans/iso01_uni.tbl4
-rw-r--r--src/chrtrans/iso01_uni.tbl.orig78
-rw-r--r--src/chrtrans/iso08_uni.tbl12
-rw-r--r--src/chrtrans/makeuctb.c53
-rw-r--r--src/chrtrans/viscii_uni.tbl2
31 files changed, 1485 insertions, 205 deletions
diff --git a/src/GridText.c b/src/GridText.c
index 3eb1cf0a..25ebf20b 100644
--- a/src/GridText.c
+++ b/src/GridText.c
@@ -175,7 +175,8 @@ struct _HText {
 	BOOL			source;		/* Is the text source? */
 	BOOL			toolbar;	/* Toolbar set? */
 	HTList *		tabs;		/* TAB IDs */
-	HTList *		hidden_links;	/* Content-less links */
+	HTList *		hidden_links;	/* Content-less links ... */
+        int			hiddenlinkflag;	/*  ... and how to treat them */
 	BOOL			no_cache;	/* Always refresh? */
 	char			LastChar;	/* For aborbing white space */
 	BOOL			IgnoreExcess;	/* Ignore chars at wrap point */
@@ -472,6 +473,15 @@ PUBLIC HText *	HText_new ARGS1(
     self->stale = YES;
     self->toolbar = NO;
     self->tabs = NULL;
+    /*
+     *  If we are going to render the List Page, always merge in hidden
+     *  links to get the numbering consistent if form fields are numbered
+     *  and show up as hidden links in the list of links. - kw
+     */
+    if (anchor->address && !strcmp(anchor->address, LYlist_temp_url()))
+	self->hiddenlinkflag = HIDDENLINKS_MERGE;
+    else
+	self->hiddenlinkflag = LYHiddenLinks;
     self->hidden_links = NULL;
     self->no_cache = ((anchor->no_cache || anchor->post_data) ?
     							  YES : NO);
@@ -588,9 +598,14 @@ PUBLIC void HText_free ARGS1(
 	    /*
 	     *  Free form fields.
 	     */
-	    if (l->input_field->type == F_OPTION_LIST_TYPE) {
+	    if (l->input_field->type == F_OPTION_LIST_TYPE &&
+		l->input_field->select_list != NULL) {
 		/*
-		 *  Free off option lists.
+		 *  Free off option lists if present.
+		 *  It should always be present for F_OPTION_LIST_TYPE
+		 *  unless we had invalid markup which prevented
+		 *  HText_setLastOptionValue from finishing its job
+		 *  and left the input field in an insane state. - kw
 		 */
 		OptionType *optptr = l->input_field->select_list;
 		OptionType *tmp;
@@ -603,7 +618,7 @@ PUBLIC void HText_free ARGS1(
 		}
 		l->input_field->select_list = NULL;
 		/* 
-		 *  Don't free the value field on option
+		 *  Don't free the value field on sane option
 		 *  lists since it points to a option value
 		 *  same for orig value.
 		 */
@@ -1561,6 +1576,54 @@ PRIVATE void display_page ARGS3(
 
 }
 
+#ifdef NOT_USED
+/*
+ *  Refresh a form link on the current page after it may have changed.
+ *  Could be used after change_form_link after a popup was opened, IF
+ *  refresh of the rest of the screen is not necessary, instead of a
+ *  full display_page - probably only for VMS curses. - kw
+ */
+PUBLIC void refresh_form_link ARGS2(
+    int,		linkno,
+    char *,		target)
+{
+    FormInfo *FormInfo_ptr;
+    /*
+     *  Update links[] for one input link, and call refresh.
+     *  basically redo some things display_page did.
+     */
+    if (linkno >= 0 && linkno < nlinks &&
+	links[linkno].type == WWW_FORM_LINK_TYPE) {
+	FormInfo_ptr = links[linkno].form;
+
+	if (FormInfo_ptr->type == F_RADIO_TYPE) {
+	    if (FormInfo_ptr->num_value)
+		links[linkno].hightext = checked_radio;
+	    else
+		links[linkno].hightext = unchecked_radio;
+
+	} else if (FormInfo_ptr->type == F_CHECKBOX_TYPE) {
+	    if (FormInfo_ptr->num_value)
+		links[linkno].hightext = checked_box;
+	    else
+		links[linkno].hightext = unchecked_box;
+
+	} else if (FormInfo_ptr->type == F_PASSWORD_TYPE) {
+	    links[linkno].hightext = STARS(strlen(FormInfo_ptr->value));
+
+	} else if (FormInfo_ptr->type == F_HIDDEN_TYPE) {
+	    ;			/* should never happen. */
+	} else {  /* TEXT type */
+	    links[linkno].hightext = FormInfo_ptr->value;
+	}
+	/*
+	 *  Bold the link, then update the screen
+	 */
+	highlight(OFF, linkno, target);
+	refresh();
+    }
+}
+#endif /* NOT_USED */
 
 /*			Object Building methods
 **			-----------------------
@@ -2724,7 +2787,7 @@ PUBLIC void HText_endAnchor ARGS2(
 	BOOL remove_numbers_on_empty =
 	    ((keypad_mode == LINKS_ARE_NUMBERED ||
 	      keypad_mode == LINKS_AND_FORM_FIELDS_ARE_NUMBERED) &&
-	     (LYHiddenLinks != HIDDENLINKS_MERGE ||
+	     (text->hiddenlinkflag != HIDDENLINKS_MERGE ||
 	      (LYNoISMAPifUSEMAP &&
 	       HTAnchor_isISMAPScript(
 		   HTAnchor_followMainLink((HTAnchor *)a->anchor)))));
@@ -3072,7 +3135,7 @@ PUBLIC void HText_endAnchor ARGS2(
 	     *  to the hidden links list. - FM
 	     */
 	    a->extent = 0;
-	    if (LYHiddenLinks != HIDDENLINKS_MERGE) {
+	    if (text->hiddenlinkflag != HIDDENLINKS_MERGE) {
 		a->number = 0;
 		HText_AddHiddenLink(text, a);
 	        text->last_anchor_number--;
@@ -5665,7 +5728,7 @@ PRIVATE void HText_AddHiddenLink ARGS2(
      *  retrievals. - FM
      */
     if ((dest = HTAnchor_followMainLink((HTAnchor *)textanchor->anchor)) &&
-	(LYHiddenLinks != HIDDENLINKS_IGNORE ||
+	(text->hiddenlinkflag != HIDDENLINKS_IGNORE ||
 	 HTList_isEmpty(text->hidden_links)))
 	HTList_appendObject(text->hidden_links, HTAnchor_address(dest));
 
@@ -6111,6 +6174,15 @@ PUBLIC char * HText_setLastOptionValue ARGS7(
 	    /*
 	     *  No option items yet.
 	     */
+	    if (text->last_anchor->input_field->type != F_OPTION_LIST_TYPE) {
+		if (TRACE)
+		    fprintf(stderr,
+   "HText_setLastOptionValue: last input_field not OPTION_LIST_TYPE but %d, ignoring!\n",
+			    text->last_anchor->input_field->type);
+		return NULL;
+	    }
+
+
 	    new_ptr = text->last_anchor->input_field->select_list = 
 				(OptionType *) calloc(1, sizeof(OptionType));
 	    if (new_ptr == NULL)
@@ -6173,6 +6245,15 @@ PUBLIC char * HText_setLastOptionValue ARGS7(
 	if (first_option) {
 	    StrAllocCopy(HTCurSelectedOptionValue, new_ptr->name);
 	    text->last_anchor->input_field->num_value = 0;
+	    /*
+	     *  If this is the first option in a popup select list,
+	     *  HText_beginInput may have allocated the value and
+	     *  cp_submit_value fields, so free them now to avoid
+	     *  a memory leak. - kw
+	     */
+            FREE(text->last_anchor->input_field->value);
+            FREE(text->last_anchor->input_field->cp_submit_value);
+
 	    text->last_anchor->input_field->value = 
 		text->last_anchor->input_field->select_list->name;
 	    text->last_anchor->input_field->orig_value = 
diff --git a/src/HTAlert.c b/src/HTAlert.c
index a83014db..0886d81e 100644
--- a/src/HTAlert.c
+++ b/src/HTAlert.c
@@ -55,11 +55,24 @@ PUBLIC void HTProgress ARGS1(
         statusline(Msg);
 }
 
+PRIVATE BOOL conf_cancelled = NO; /* used by HTConfirm only - kw */
+
+PUBLIC BOOL HTLastConfirmCancelled NOARGS
+{
+    if (conf_cancelled) {
+	conf_cancelled = NO;	/* reset */
+	return(YES);
+    } else {
+	return(NO);
+    }
+}
+
 /*	Seek confirmation.				HTConfirm()
 **	------------------
 */
 PUBLIC BOOL HTConfirm ARGS1(CONST char *, Msg)
 {
+    conf_cancelled = NO;
     if (dump_output_immediately) { /* Non-interactive, can't respond */
 	return(NO);
     } else {
@@ -80,6 +93,8 @@ PUBLIC BOOL HTConfirm ARGS1(CONST char *, Msg)
 #endif /* VMS */
 	    if (TOUPPER(c) == 'Y')
 		return(YES);
+	    if (c == 7 || c == 3) /* remember we had ^G or ^C */
+		conf_cancelled = YES;
 	    if (TOUPPER(c) == 'N' || c == 7 || c == 3) /* ^G or ^C cancels */
 		return(NO);
 	}
diff --git a/src/HTAlert.h b/src/HTAlert.h
index bb07b2a1..ce40afb5 100644
--- a/src/HTAlert.h
+++ b/src/HTAlert.h
@@ -40,6 +40,11 @@ extern void HTProgress PARAMS((CONST char * Msg));
 extern BOOLEAN mustshow;
 #define _HTProgress(msg)	mustshow = TRUE, HTProgress(msg)
 
+/*
+ *  Indicates whether last HTConfirm was cancelled (^G or ^C) and
+ *  resets flag. (so only call once!) - kw
+ */
+extern BOOL HTLastConfirmCancelled NOPARAMS;
 
 /*      Display a message, then wait for 'yes' or 'no'.
 **
diff --git a/src/HTML.c b/src/HTML.c
index 15ed71c6..a020ba56 100644
--- a/src/HTML.c
+++ b/src/HTML.c
@@ -243,7 +243,24 @@ PUBLIC void HTML_put_character ARGS2(HTStructured *, me, char, c)
 	return;
 
     default:
-        break;
+	if (me->inSELECT) {
+	    /*
+	     *  If we are within a SELECT not caught by the cases
+	     *  above - HTML_SELECT or HTML_OPTION may not be the
+	     *  last element pushed on the style stack if there were
+	     *  invalid markup tags within a SELECT element.  For error
+	     *  recovery, treat text as part of the OPTION text, it is
+	     *  probably meant to show up as user-visible text.
+	     *  Having A as an open element while in SELECT is really sick,
+	     *  don't make anchor text part of the option text in that case
+	     *  since the option text will probably just be discarded. - kw
+	     */
+	    if (me->sp[0].tag_number == HTML_A)
+		break;
+	    HTChunkPutc(&me->option, c);
+	    return;
+	}
+	break;
     } /* end first switch */
 
     /*
@@ -498,13 +515,57 @@ PUBLIC void HTML_write ARGS3(HTStructured *, me, CONST char*, s, int, l)
         HTML_put_character(me, *p);
 }
 
-#ifndef DONT_TRACK_INTERNAL_LINKS
+/*
+ *  "Internal links" are hyperlinks whose source and destination are
+ *  within the same document, and for which the destination is given
+ *  as a URL Reference with an empty URL, but possibly with a non-empty
+ *  #fragment.  (This terminology re URL-Reference vs. URL follows the
+ *  Fielding URL syntax and semantics drafts).
+ *  Differences:
+ *  (1) The document's base (in whatever way it is given) is not used for
+ *      resolving internal link references.
+ *  (2) Activating an internal link should not result in a new retrieval
+ *      of a copy of the document.
+ *  (3) Internal links are the only way to refer with a hyperlink to a document
+ *      (or a location in it) which is only known as the result of a POST
+ *      request (doesn't have a URL from which the document can be retrieved
+ *      with GET), and can only be used from within that document.
+ *
+ * *If DONT_TRACK_INTERNAL_LINKS is not defined, we keep track of whether a
+ *  link destination was given as an internal link.  This information is
+ *  recorded in the type of the link between anchor objects, and is available
+ *  to the HText object and the mainloop from there.  URL References to
+ *  internal destinations are still resolved into an absolute form before
+ *  being passed on, but using the current stream's retrieval address instead
+ *  of the base URL.
+ *  Examples:  (replace [...] to have a valid absolute URL)
+ *  In document retrieved from [...]/mypath/mydoc.htm w/ base [...]/otherpath/
+ *  a. HREF="[...]/mypath/mydoc.htm"      -> [...]/mypath/mydoc.htm
+ *  b. HREF="[...]/mypath/mydoc.htm#frag" -> [...]/mypath/mydoc.htm#frag
+ *  c. HREF="mydoc.htm"                   -> [...]/otherpath/mydoc.htm
+ *  d. HREF="mydoc.htm#frag"              -> [...]/otherpath/mydoc.htm#frag
+ *  e. HREF=""                -> [...]/mypath/mydoc.htm      (marked internal)
+ *  f. HREF="#frag"           -> [...]/mypath/mydoc.htm#frag (marked internal)
+ *
+ * *If DONT_TRACK_INTERNAL_LINKS is defined, URL-less URL-References are
+ *  resolved differently from URL-References with a non-empty URL (using the
+ *  current stream's retrieval address instead of the base), but we make no
+ *  further distinction.  Resolution is then as in the examples above, execept
+ *  that there is no "(marked internal)".
+ *
+ * *Note that this doesn't apply to form ACTIONs (always resolved using base,
+ *  never marked internal).  Also other references encountered or generated
+ *  are not marked internal, whether they have a URL or not, if in a given
+ *  context an internal link makes no sense (e.g. IMG SRC=).
+ */
 
+#ifndef DONT_TRACK_INTERNAL_LINKS
 /* A flag is used to keep track of whether an "URL reference" encountered
-   had a real "URL" or not.  (This is the terminology of the Fielding
-   Internet Draft.)  In the latter case, it will be marked as an "internal"
-   link.  The flag is set before we start messing around with the string
-   (resolution of relative URLs etc.). - kw */
+   had a real "URL" or not. In the latter case, it will be marked as
+   "internal".  The flag is set before we start messing around with the
+   string (resolution of relative URLs etc.). This variable only used
+   locally here, don't confuse with LYinternal_flag which is for
+   for overriding non-caching similar to LYoverride_no_cache. - kw */
 #define CHECK_FOR_INTERN(s) intern_flag = (s && (*s=='#' || *s=='\0')) ? TRUE : FALSE; 
 
 /* Last argument to pass to HTAnchor_findChildAndLink() calls,
@@ -741,6 +802,25 @@ PRIVATE void HTML_start_element ARGS6(
 		me->inBadBASE = TRUE;
 	    }
 
+	    if (url_type == LYNXIMGMAP_URL_TYPE) {
+		/*
+		 *  These have a are non-standard form, basically
+		 *  strip the prefix or the code below would insert
+		 *  a nonsense host into the pseudo URL.  These
+		 *  should never occur where they would used for
+		 *  resolution of relative URLs anyway.  We can
+		 *  also strip the #map part. - kw
+		 */
+		temp = HTParse(base + 11, "",
+			       PARSE_ACCESS+PARSE_HOST+PARSE_PATH
+			       +PARSE_PUNCTUATION);
+		if (temp) {
+		    FREE(base);
+		    base = temp;
+		    temp = NULL;
+		}
+	    }
+
 	    /* 
 	     *  Get parent's address for defaulted fields.
 	     */
@@ -754,6 +834,7 @@ PRIVATE void HTML_start_element ARGS6(
 		*temp != '\0') {
 	        StrAllocCopy(me->base_href, temp);
 	    } else {
+		FREE(temp);
 	        StrAllocCopy(me->base_href, (temp = HTParse(related, "",
 					 PARSE_ACCESS+PARSE_PUNCTUATION)));
 	    }
@@ -773,6 +854,7 @@ PRIVATE void HTML_start_element ARGS6(
 	        if (!strcmp(me->base_href, "file:")) {
 		    StrAllocCat(me->base_href, "//localhost");
 		} else if (strcmp(me->base_href, "news:")) {
+		    FREE(temp);
 	            StrAllocCat(me->base_href, (temp = HTParse(related, "",
 					    PARSE_HOST+PARSE_PUNCTUATION)));
 		}
@@ -787,7 +869,6 @@ PRIVATE void HTML_start_element ARGS6(
 	    			PARSE_PATH+PARSE_PUNCTUATION)) &&
 		*temp != '\0') {
 	        StrAllocCat(me->base_href, temp);
-		FREE(temp);
 	    } else if (!strcmp(me->base_href, "news:")) {
 	        StrAllocCat(me->base_href, "*");
 	    } else if (!strncmp(me->base_href, "news:", 5) ||
@@ -797,6 +878,7 @@ PRIVATE void HTML_start_element ARGS6(
 	    } else {
 	        StrAllocCat(me->base_href, "/");
 	    }
+	    FREE(temp);
 	    FREE(base);
 
             me->inBASE = TRUE;
@@ -3307,7 +3389,7 @@ PRIVATE void HTML_start_element ARGS6(
 		    FREE(title);
 		}
 	    }
-	    LYAddImageMap(me->map_address, title);
+	    LYAddImageMap(me->map_address, title, me->node_anchor);
 	    FREE(title);
 	}
         break;
@@ -3401,7 +3483,8 @@ PRIVATE void HTML_start_element ARGS6(
 	        StrAllocCopy(alt_string, href);
 	    }
 
-	    LYAddMapElement(me->map_address, href, alt_string, intern_flag);
+	    LYAddMapElement(me->map_address, href, alt_string,
+			    me->node_anchor, intern_flag);
 	    FREE(href);
 	    FREE(alt_string);
 	}
@@ -4622,6 +4705,19 @@ PRIVATE void HTML_start_element ARGS6(
 	    }
 
 	    /*
+	     *  Check for an unclosed SELECT, try to close it if found.
+	     */
+	    if (me->inSELECT) {
+	        if (TRACE) {
+		    fprintf(stderr, "HTML: Missing SELECT end tag, faking it...\n");
+		}
+		if (me->sp->tag_number != HTML_SELECT) {
+		    SET_SKIP_STACK(HTML_SELECT);
+		}
+		HTML_end_element(me, HTML_SELECT, (char **)&include);
+	    }
+
+	    /*
 	     *  Handle the INPUT as for a FORM. - FM
 	     */
 	    if (!(present && present[HTML_INPUT_NAME] &&
@@ -5059,7 +5155,9 @@ PRIVATE void HTML_start_element ARGS6(
 		me->inBadHTML = TRUE;
 		sleep(MessageSecs);
 	    }
-	    SET_SKIP_STACK(HTML_SELECT);
+	    if (me->sp->tag_number != HTML_SELECT) {
+		SET_SKIP_STACK(HTML_SELECT);
+	    }
 	    HTML_end_element(me, HTML_SELECT, (char **)&include);
 	}
 	{
@@ -5086,9 +5184,14 @@ PRIVATE void HTML_start_element ARGS6(
 		}
 
 	        /*
-		 *  Too likely to cause a crash, so we'll ignore it. - FM
-		 */
+		 *  We should have covered all crash possibilities with the
+		 *  current TagSoup parser, so we'll allow it because some
+		 *  people with other browsers use SELECT for "information"
+		 *  popups, outside of FORM blocks, though no Lynx user
+		 *  would do anything that awful, right? - FM
+		 *//***
 		break;
+		***/
 	    }
 
 	    /*
@@ -5815,6 +5918,17 @@ PRIVATE void HTML_end_element ARGS3(
     case HTML_HEAD:
         if (!me->text)
 	    UPDATE_STYLE;
+	if (me->inBASE &&
+	    !strcmp(me->node_anchor->address, LYlist_temp_url())) {
+	    /*  If we are parsing the List Page, and have a BASE after
+	     *  we are done with the HEAD element, propagate it back
+	     *  to the node_anchor object.  The base should have been
+	     *  inserted by showlist() to record what document the List
+	     *  Page is about, and other functions may later look for it
+	     *  in the anchor. - kw
+	     */
+	    StrAllocCopy(me->node_anchor->content_base, me->base_href);
+	}
 	if (HText_hasToolbar(me->text))
 	    HText_appendParagraph(me->text);
 	break;
@@ -6670,7 +6784,9 @@ End_Object:
 		me->inBadHTML = TRUE;
 		sleep(MessageSecs);
 	    }
-	    SET_SKIP_STACK(HTML_SELECT);
+	    if (me->sp->tag_number != HTML_SELECT) {
+		SET_SKIP_STACK(HTML_SELECT);
+	    }
 	    HTML_end_element(me, HTML_SELECT, (char **)&include);
 	}
 
@@ -6907,12 +7023,9 @@ End_Object:
 		    me->inBadHTML = TRUE;
 		    sleep(MessageSecs);
 		}
-
 	        /*
-		 *  Too likely to cause a crash, so we'll ignore it. - kw
+		 *  Hopefully won't crash, so we'll ignore it. - kw
 		 */
-		HTChunkClear(&me->option);
-		break;
 	    }
 
 	    /*
@@ -6971,9 +7084,11 @@ End_Object:
 	        /*
 		 *  Add end option character.
 		 */
-	        HText_appendCharacter(me->text, ']');
-		HText_setLastChar(me->text, ']');
-		me->in_word = YES;
+		if (!me->first_option) {
+		    HText_appendCharacter(me->text, ']');
+		    HText_setLastChar(me->text, ']');
+		    me->in_word = YES;
+		}
 		HText_setIgnoreExcess(me->text, FALSE); 
 	    }
     	    HTChunkClear(&me->option);
@@ -7211,7 +7326,56 @@ PRIVATE void HTML_free ARGS1(HTStructured *, me)
 	    HTML_end_element(me, HTML_FORM, (char **)&include);
 	    me->inFORM = FALSE;
 	}
-
+	if (me->option.size > 0) {
+	    /*
+	     *  If we still have data in the me->option chunk after
+	     *  forcing a close of a still-open form, something must
+	     *  have gone very wrong. - kw
+	     */
+	    if (TRACE) {
+		fprintf(stderr,
+			"HTML_free: ***** SELECT or OPTION not ended properly *****\n");
+	    } else if (!me->inBadHTML) {
+		_statusline(BAD_HTML_USE_TRACE);
+		me->inBadHTML = TRUE;
+		sleep(MessageSecs);
+	    }
+	    HTChunkTerminate(&me->option);
+	    /*
+	     *  Output the left-over data as text, maybe it was invalid
+	     *  markup meant to be shown somewhere. - kw
+	     */
+	    if (TRACE)
+		fprintf(stderr, "           ***** leftover option data: %s\n",
+			me->option.data);
+	    HTML_put_string(me, me->option.data);
+	    HTChunkClear(&me->option);
+	}
+	if (me->textarea.size > 0) {
+	    /*
+	     *  If we still have data in the me->textarea chunk after
+	     *  forcing a close of a still-open form, something must
+	     *  have gone very wrong. - kw
+	     */
+	    if (TRACE) {
+		fprintf(stderr,
+			"HTML_free: ***** TEXTAREA not used properly *****\n");
+	    } else if (!me->inBadHTML) {
+		_statusline(BAD_HTML_USE_TRACE);
+		me->inBadHTML = TRUE;
+		sleep(MessageSecs);
+	    }
+	    HTChunkTerminate(&me->textarea);
+	    /*
+	     *  Output the left-over data as text, maybe it was invalid
+	     *  markup meant to be shown somewhere. - kw
+	     */
+	    if (TRACE)
+		fprintf(stderr, "           ***** leftover textarea data: %s\n",
+			me->textarea.data);
+	    HTML_put_string(me, me->textarea.data);
+	    HTChunkClear(&me->textarea);
+	}
 	/*
 	 *  If we're interactive and have hidden links but no visible
 	 *  links, add a message informing the user about this and
@@ -7235,6 +7399,48 @@ PRIVATE void HTML_free ARGS1(HTStructured *, me)
 	 */
 	HText_endAppend(me->text);
     }
+    if (me->option.size > 0) {
+	/*
+	 *  If we still have data in the me->option chunk after
+	 *  forcing a close of a still-open form, something must
+	 *  have gone very wrong. - kw
+	 */
+	if (TRACE) {
+	    fprintf(stderr,
+		    "HTML_free: ***** SELECT or OPTION not ended properly *****\n");
+	} else if (!me->inBadHTML) {
+	    _statusline(BAD_HTML_USE_TRACE);
+	    me->inBadHTML = TRUE;
+	    sleep(MessageSecs);
+	}
+	if (TRACE) {
+	    HTChunkTerminate(&me->option);
+	    fprintf(stderr, "           ***** leftover option data: %s\n",
+		    me->option.data);
+	}
+	HTChunkClear(&me->option);
+    }
+    if (me->textarea.size > 0) {
+	/*
+	 *  If we still have data in the me->textarea chunk after
+	 *  forcing a close of a still-open form, something must
+	 *  have gone very wrong. - kw
+	 */
+	if (TRACE) {
+	    fprintf(stderr,
+		    "HTML_free: ***** TEXTAREA not used properly *****\n");
+	} else if (!me->inBadHTML) {
+	    _statusline(BAD_HTML_USE_TRACE);
+	    me->inBadHTML = TRUE;
+	    sleep(MessageSecs);
+	}
+	if (TRACE) {
+	    HTChunkTerminate(&me->textarea);
+	    fprintf(stderr, "           ***** leftover textarea data: %s\n",
+		    me->textarea.data);
+	}
+	HTChunkClear(&me->textarea);
+    }
 
     if (me->target) {
         (*me->targetClass._free)(me->target);
@@ -7291,6 +7497,37 @@ PRIVATE void HTML_abort ARGS2(HTStructured *, me, HTError, e)
 	HText_endAppend(me->text);
     }
 
+    if (me->option.size > 0) {
+	/*
+	 *  If we still have data in the me->option chunk after
+	 *  forcing a close of a still-open form, something must
+	 *  have gone very wrong. - kw
+	 */
+	if (TRACE) {
+	    fprintf(stderr,
+		    "HTML_abort: ***** SELECT or OPTION not ended properly *****\n");
+	    HTChunkTerminate(&me->option);
+	    fprintf(stderr, "            ***** leftover option data: %s\n",
+		    me->option.data);
+	}
+	HTChunkClear(&me->option);
+    }
+    if (me->textarea.size > 0) {
+	/*
+	 *  If we still have data in the me->textarea chunk after
+	 *  forcing a close of a still-open form, something must
+	 *  have gone very wrong. - kw
+	 */
+	if (TRACE) {
+	    fprintf(stderr,
+		    "HTML_abort: ***** TEXTAREA not used properly *****\n");
+	    HTChunkTerminate(&me->textarea);
+	    fprintf(stderr, "            ***** leftover textarea data: %s\n",
+		    me->textarea.data);
+	}
+	HTChunkClear(&me->textarea);
+    }
+
     if (me->target) {
         (*me->targetClass._abort)(me->target, e);
     }
diff --git a/src/LYCgi.c b/src/LYCgi.c
index 4f6d0171..6bb32a34 100644
--- a/src/LYCgi.c
+++ b/src/LYCgi.c
@@ -307,8 +307,15 @@ PRIVATE int LYLoadCGI ARGS4(
 	int wstatus;
 #endif
 
-	/* Decode full HTTP response */
-	format_in = HTAtom_for("www/mime");
+	if (anAnchor->isHEAD || keep_mime_headers) {
+
+	    /* Show output as plain text */
+	    format_in = WWW_PLAINTEXT;
+	} else {
+	    
+	    /* Decode full HTTP response */
+	    format_in = HTAtom_for("www/mime");
+	}
 		
 	target = HTStreamStack(format_in,
 			       format_out,
@@ -361,6 +368,7 @@ PRIVATE int LYLoadCGI ARGS4(
 		close(fd2[1]);
 		
 		if (anAnchor->post_data) {
+		    int written, remaining, total_written = 0;
 		    close(fd1[0]);
 
 		    /* We have form data to push across the pipe */
@@ -371,8 +379,41 @@ PRIVATE int LYLoadCGI ARGS4(
 				"LYNXCGI: Writing:\n%s----------------------------------\n",
 				anAnchor->post_data);			
 		    }
-		    write(fd1[1], anAnchor->post_data,
-			  strlen(anAnchor->post_data));
+		    remaining = strlen(anAnchor->post_data);
+		    while ((written = write(fd1[1],
+					    anAnchor->post_data + total_written,
+					    remaining)) != 0) {
+			if (written < 0) {
+#ifdef EINTR
+			    if (errno == EINTR)
+				continue;
+#endif /* EINTR */
+#ifdef ERESTARTSYS
+			    if (errno == ERESTARTSYS)
+				continue;
+#endif /* ERESTARTSYS */
+			    if (TRACE) {
+				perror("LYNXCGI: write() of POST data failed");
+			    }
+			    break;
+			}
+			if (TRACE) {
+			    fprintf(stderr,
+				    "LYNXCGI: Wrote %d bytes of POST data.\n",
+				    written);
+			}
+			total_written += written;
+			remaining -= written;
+			if (remaining == 0)
+			    break;
+		    }
+		    if (remaining != 0) {
+			if (TRACE)
+			    fprintf(stderr,
+				    "LYNXCGI: %d bytes remain unwritten!\n",
+				    remaining);
+		    }
+		    close(fd1[1]);
 		}
 		
 		total_chars = 0;
@@ -404,9 +445,6 @@ PRIVATE int LYLoadCGI ARGS4(
 		    break;
 		}
 #endif /* !HAVE_WAITPID */
-		if (anAnchor->post_data) {
-		    close(fd1[1]);
-		}
 		close(fd2[0]);
 		status = HT_LOADED;
 		
@@ -449,6 +487,10 @@ PRIVATE int LYLoadCGI ARGS4(
 		    add_environment_value(post_len);
 		} else {
 		    close(fileno(stdin));
+
+		    if (anAnchor->isHEAD) {
+			add_environment_value("REQUEST_METHOD=HEAD");
+		    }
 		}
 
 		/* 
@@ -473,7 +515,7 @@ PRIVATE int LYLoadCGI ARGS4(
 		    /* Data for a get/search form */
 		    if (is_www_index) {
 			add_environment_value("REQUEST_METHOD=SEARCH");
-		    } else {
+		    } else if (!anAnchor->isHEAD) {
 			add_environment_value("REQUEST_METHOD=GET");
 		    }
 		    
diff --git a/src/LYCurses.c b/src/LYCurses.c
index 35bfc6eb..b4738a0f 100644
--- a/src/LYCurses.c
+++ b/src/LYCurses.c
@@ -75,7 +75,11 @@ PUBLIC void LY_SLrefresh NOARGS
     return;
 }
 
-PUBLIC void LY_SLclear NOARGS
+/* the following renamed from LY_SLclear since it is more like erase()
+   described in curses man pages than like clear(); but for USE_SLANG
+   clear() is still a macro calling this, and will do the same thing as
+   erase(). - kw */
+PUBLIC void LY_SLerase NOARGS
 {
     SLsmg_gotorc (0, 0);
     SLsmg_erase_eos ();
@@ -409,7 +413,7 @@ PRIVATE void LYsetWAttr ARGS1(WINDOW *, win)
 #endif /* DOSPATH */
 	}
 
-#ifndef __DJGPP__
+#if ( !defined(__DJGPP__) && !defined(_WINDOWS) )
 	if (no_color_video < 0) {
 		no_color_video = tigetnum("ncv");
 	}
@@ -1554,9 +1558,17 @@ PUBLIC void VMSbox ARGS3(
 PUBLIC void lynx_force_repaint NOARGS
 {
 #if defined(COLOR_CURSES)
-    chtype a = (LYShowColor >= SHOW_COLOR_ON) ? COLOR_PAIR(9) : A_NORMAL;
+    chtype a;
+#ifndef USE_COLOR_STYLE
+    if (LYShowColor >= SHOW_COLOR_ON)
+	a = COLOR_PAIR(9);
+    else
+#endif
+	a = A_NORMAL;
     bkgdset(a | ' ');
+#ifndef USE_COLOR_STYLE
     bkgd(a | ' ');
+#endif
     attrset(a);
 #endif
     clearok(curscr, TRUE);
diff --git a/src/LYCurses.h b/src/LYCurses.h
index 1478cade..89d64c5e 100644
--- a/src/LYCurses.h
+++ b/src/LYCurses.h
@@ -177,8 +177,9 @@ extern int PHYSICAL_SLtt_Screen_Cols;
 #define LINES SLtt_Screen_Rows
 #define move SLsmg_gotorc
 #define addstr SLsmg_write_string
-extern void LY_SLclear NOPARAMS;
-#define clear LY_SLclear
+extern void LY_SLerase NOPARAMS;
+#define erase LY_SLerase
+#define clear LY_SLerase
 #define standout SLsmg_reverse_video
 #define standend  SLsmg_normal_video
 #define clrtoeol SLsmg_erase_eol
diff --git a/src/LYDownload.c b/src/LYDownload.c
index 644ade45..0934266f 100644
--- a/src/LYDownload.c
+++ b/src/LYDownload.c
@@ -366,6 +366,7 @@ check_recall:
 	     */
 	    LYDidRename = TRUE;
 	}
+	chmod(buffer, HIDE_CHMOD);
 #else /* Unix: */
 	/*
 	 *  Prevent spoofing of the shell.
@@ -384,10 +385,10 @@ check_recall:
         fflush(stdout);
 	fflush(stderr);
         start_curses();
+#if defined(UNIX)
+	LYRelaxFilePermissions(buffer);
+#endif /* defined(UNIX) */
 #endif /* VMS */
-#if defined(VMS) || defined(UNIX)
-	chmod(buffer, HIDE_CHMOD);
-#endif /*  defined(VMS) || defined(UNIX) */
 
     } else {
 	/*
diff --git a/src/LYForms.c b/src/LYForms.c
index 12e6f032..d9dee701 100644
--- a/src/LYForms.c
+++ b/src/LYForms.c
@@ -88,7 +88,7 @@ PUBLIC int change_form_link ARGS6(
 #if defined(VMS) && !defined(USE_SLANG)
 		    c = DO_NOTHING;
 #else
-		    c = 23;  /* CTRL-W for repaint */
+		    c = 23;  /* CTRL-W refresh without clearok */
 #endif /* VMS && !USE_SLANG */
 		else
 #endif /* FANCY_CURSES || USE_SLANG */
@@ -119,16 +119,17 @@ PUBLIC int change_form_link ARGS6(
 		form->value_cs = opt_ptr->value_cs;
 	    }
 #if defined(FANCY_CURSES) || defined(USE_SLANG)
-	    if (!enable_scrollback && form->num_value == OrigNumValue)
+            if (!enable_scrollback)
 #if defined(VMS) && !defined(USE_SLANG)
-		c = DO_NOTHING;
-#else
-		c = 23;  /* CTRL-W for repaint */
-#endif /* VMS && !USE_SLANG */
-	    else
+                if (form->num_value == OrigNumValue)
+                    c = DO_NOTHING;
+                else
+#endif /* VMS && !USE_SLANG*/
+		c = 23;	 /* CTRL-W refresh without clearok */
+            else
 #endif /* FANCY_CURSES || USE_SLANG */
-		c = 12;  /* CTRL-L for repaint */
-	    break;
+                c = 12;  /* CTRL-L for repaint */
+            break;
 
 	case F_RADIO_TYPE:
 	    if (form->disabled == YES)
diff --git a/src/LYGetFile.c b/src/LYGetFile.c
index 08551035..863c905a 100644
--- a/src/LYGetFile.c
+++ b/src/LYGetFile.c
@@ -24,6 +24,7 @@
 #include "LYKeymap.h"
 #include "LYBookmark.h"
 #include "LYMap.h"
+#include "LYList.h"
 #ifdef VMS
 #include "HTVMSUtils.h"
 #endif /* VMS */
@@ -251,6 +252,27 @@ Try_Redirected_URL:
 			return(NULLFILE);
 		    }
 		}
+		if (WWWDoc.post_data &&
+		    url_type != HTTP_URL_TYPE &&
+		    url_type != HTTPS_URL_TYPE &&
+		    url_type != LYNXCGI_URL_TYPE &&
+		    url_type != LYNXIMGMAP_URL_TYPE &&
+		    url_type != GOPHER_URL_TYPE &&
+		    url_type != CSO_URL_TYPE &&
+		    url_type != PROXY_URL_TYPE &&
+		    !(url_type == FILE_URL_TYPE &&
+		      *(LYlist_temp_url()) &&
+		      !strncmp(WWWDoc.address, LYlist_temp_url(),
+			       strlen(LYlist_temp_url())))) {
+		    if (TRACE)
+			fprintf(stderr,
+				"getfile: dropping post_data!\n");
+		    HTAlert("POST not supported for this URL - ignoring POST data!");
+		    FREE(doc->post_data);
+		    FREE(doc->post_content_type);
+		    WWWDoc.post_data = NULL;
+		    WWWDoc.post_content_type = NULL;
+		}
 #ifndef VMS
 #ifdef SYSLOG_REQUESTED_URLS
 		syslog(LOG_INFO|LOG_LOCAL5, "%s", doc->address);
@@ -350,7 +372,7 @@ Try_Redirected_URL:
 		    WWWDoc.safe = doc->safe;
 #ifndef DONT_TRACK_INTERNAL_LINKS
 		    if (doc->internal_link && !reloading) {
-			LYoverride_no_cache = TRUE;
+			LYinternal_flag = TRUE;
 		    }
 #endif
 
diff --git a/src/LYGlobalDefs.h b/src/LYGlobalDefs.h
index bff8c881..ee2939b6 100644
--- a/src/LYGlobalDefs.h
+++ b/src/LYGlobalDefs.h
@@ -146,7 +146,8 @@ extern char *lynx_temp_space;
 extern char *lynx_save_space;
 extern BOOLEAN LYforce_HTML_mode;
 extern BOOLEAN LYforce_no_cache;
-extern BOOLEAN LYoverride_no_cache;
+extern BOOLEAN LYoverride_no_cache;  /* don't need fresh copy, from history */
+extern BOOLEAN LYinternal_flag; /* don't need fresh copy, was internal link */
 extern BOOLEAN LYresubmit_posts;
 extern BOOLEAN user_mode; /* novice or advanced */
 extern BOOLEAN is_www_index;
diff --git a/src/LYHistory.c b/src/LYHistory.c
index 1a3a3990..cb6751e3 100644
--- a/src/LYHistory.c
+++ b/src/LYHistory.c
@@ -507,7 +507,7 @@ PUBLIC BOOLEAN historytarget ARGS1(
 	&& !(LYforce_no_cache == TRUE && LYoverride_no_cache == FALSE)) {
 #ifndef DONT_TRACK_INTERNAL_LINKS
 	LYforce_no_cache = FALSE;
-	LYoverride_no_cache = TRUE;
+	LYinternal_flag = TRUE;
 	newdoc->internal_link = TRUE;
 	treat_as_intern = TRUE;
 #endif
@@ -533,7 +533,8 @@ PUBLIC BOOLEAN historytarget ARGS1(
 		LYoverride_no_cache == FALSE)) &&
 	      !(treat_as_intern && !reloading)) ||
 	     text == NULL) &&
-	    HTConfirm(CONFIRM_POST_RESUBMISSION) == TRUE) {
+	    (!strncmp(newdoc->address, "LYNXIMGMAP:", 11) ||
+	     HTConfirm(CONFIRM_POST_RESUBMISSION) == TRUE)) {
 	    LYforce_no_cache = TRUE;
 	    LYoverride_no_cache = FALSE;
 	} else if (text != NULL) {
diff --git a/src/LYList.c b/src/LYList.c
index 804da051..f5225c7b 100644
--- a/src/LYList.c
+++ b/src/LYList.c
@@ -8,8 +8,8 @@
 #include "HTUtils.h"
 #include "tcp.h"
 #include "LYUtils.h"
-#include "LYList.h"
 #include "GridText.h"
+#include "LYList.h"
 #include "LYSignal.h"
 #include "LYGlobalDefs.h"
 #include "LYCharUtils.h"
@@ -36,13 +36,18 @@
 
 static char list_filename[256] = "\0";
 
+/*
+ *  Returns the name of the file used for the List Page, if one has
+ *  been created, as a full URL; otherwise, returns an empty string.
+ * - kw
+ */
 PUBLIC char * LYlist_temp_url NOARGS
 {
     return list_filename;
 }
 
 PUBLIC int showlist ARGS2(
-	char **,	newfile,
+	document *,	newdoc,
 	BOOLEAN,	titles)
 {
     int cnt;
@@ -51,6 +56,7 @@ PUBLIC int showlist ARGS2(
     static BOOLEAN first = TRUE;
     FILE *fp0;
     char *Address = NULL, *Title = NULL, *cp = NULL;
+    BOOLEAN intern_w_post = FALSE;
     char *desc = "unknown field or link";
 
     refs = HText_sourceAnchors(HTMainText);
@@ -90,13 +96,24 @@ PUBLIC int showlist ARGS2(
 	return(-1);
     }
 
-    StrAllocCopy(*newfile, list_filename);
+    StrAllocCopy(newdoc->address, list_filename);
     LYforce_HTML_mode = TRUE;	/* force this file to be HTML */
     LYforce_no_cache = TRUE;	/* force this file to be new */
 
 
     fprintf(fp0, "<head>\n");
     LYAddMETAcharsetToFD(fp0, -1);
+    if (strchr(HTLoadedDocumentURL(), '"') == NULL) {
+	/*
+	 *  Insert a BASE tag so there is some way to relate the List Page
+	 *  file to its underlying document after we are done.  It won't
+	 *  be actually used for resolving relative URLs. - kw
+	 */
+	StrAllocCopy(Address, HTLoadedDocumentURL());
+	LYEntify(&Address, FALSE);
+	fprintf(fp0, "<base href=\"%s\">\n", Address);
+	FREE(Address);
+    }
     fprintf(fp0, "<title>%s</title>\n</head>\n<body>\n",
 		 LIST_PAGE_TITLE);
     fprintf(fp0, "<h1>You have reached the List Page</h1>\n");
@@ -130,10 +147,16 @@ PUBLIC int showlist ARGS2(
 	     *  ensure that the link numbers on the list page match the
 	     *  numbering in the original document, but won't create a
 	     *  forward link to the form. - FM && LE
+	     *
+	     *  Changed to create a fake hidden link, to get the numbering
+	     *  right in connection with always treating this file as
+	     *  HIDDENLINKS_MERGE in GridText.c - kw
 	     */
 	    if (keypad_mode == LINKS_AND_FORM_FIELDS_ARE_NUMBERED) {
 		HText_FormDescNumber(cnt, (char **)&desc);
-		fprintf(fp0, "<li>[%d](<em>%s</em>)</a>\n", cnt, desc);
+		/* fprintf(fp0, "<li>[%d](<em>%s</em>)\n", cnt, desc); */
+		fprintf(fp0, "<li><a id=%d href='#%d'></a>(<em>%s</em>)\n",
+			cnt, cnt, desc);
 	    }
 	    continue;
 	}
@@ -144,6 +167,19 @@ PUBLIC int showlist ARGS2(
 	dest = dest_intl ?
 	    dest_intl : HTAnchor_followMainLink((HTAnchor *)child);
 	parent = HTAnchor_parent(dest);
+	if (!intern_w_post && dest_intl &&
+	    HTMainAnchor && HTMainAnchor->post_data &&
+	    parent->post_data &&
+	    !strcmp(HTMainAnchor->post_data, parent->post_data)) {
+	    /*
+	     *  Set flag to note that we had at least one internal link,
+	     *  if the document from which we are generating the list
+	     *  has assosiated POST data; after an extra check that the
+	     *  link destination really has hthe same POST data so that
+	     *  we can believe it is an internal link.
+	     */
+	    intern_w_post = TRUE;
+	}
 	address =  HTAnchor_address(dest);
 	title = titles ? HTAnchor_title(parent) : NULL;
 	StrAllocCopy(Address, address);
@@ -196,6 +232,26 @@ PUBLIC int showlist ARGS2(
     fprintf(fp0,"\n</%s>\n</body>\n", ((keypad_mode == NUMBERS_AS_ARROWS) ?
     				       "ol" : "ul"));
 
+    /*
+     *  Make necessary changes to newdoc before returning to caller.
+     *  If the intern_w_post flag is set, we keep the POST data in
+     *  newdoc that have been passed in.  They should be the same as
+     *  in the loaded locument for which we generated the list.
+     *  In that case the file we have written will be associated with
+     *  the same POST data when it is loaded after we are done here,
+     *  so that following one of the links we have marked as "internal
+     *  link" can lead back to the underlying document with the right
+     *  address+post_data combination. - kw
+     */
+    if (intern_w_post) {
+	newdoc->internal_link = TRUE;
+    } else {
+	FREE(newdoc->post_data);
+	FREE(newdoc->post_content_type);
+	newdoc->internal_link = FALSE;
+    }
+    newdoc->isHEAD = FALSE;
+    newdoc->safe = FALSE;
     fclose(fp0);
     return(0);
 }      
@@ -256,6 +312,15 @@ PUBLIC void printlist ARGS2(
 		continue;
 	    }
 	    dest = HTAnchor_followMainLink((HTAnchor *)child);
+	    /*
+	     *  Ignore if child anchor points to itself, i.e. we had
+	     *  something like <A NAME=xyz HREF="#xyz"> and it is not
+	     *  treated as a hidden link.  Useful if someone 'P'rints
+	     *  the List Page (which isn't a very useful action to do,
+	     *  but anyway...) - kw
+	     */
+	    if (dest == (HTAnchor *)child)
+		continue;
 	    parent = HTAnchor_parent(dest);
 	    title = titles ? HTAnchor_title(parent) : NULL;
 	    address =  HTAnchor_address(dest);
diff --git a/src/LYList.h b/src/LYList.h
index e1e0b8de..4a717284 100644
--- a/src/LYList.h
+++ b/src/LYList.h
@@ -3,7 +3,7 @@
 #define LYLIST_H
 
 extern char * LYlist_temp_url NOPARAMS;
-extern int showlist PARAMS((char **newfile, BOOLEAN titles));
+extern int showlist PARAMS((document *newdoc, BOOLEAN titles));
 extern void printlist PARAMS((FILE *fp, BOOLEAN titles));
 
 #define LIST_PAGE_TITLE  "Lynx List Page"
diff --git a/src/LYMain.c b/src/LYMain.c
index b5749c9e..5a6875e3 100644
--- a/src/LYMain.c
+++ b/src/LYMain.c
@@ -164,7 +164,8 @@ PUBLIC int LYrcShowColor = SHOW_COLOR_UNKNOWN;  /* ... as last read or written *
 PUBLIC BOOLEAN LYShowCursor = SHOW_CURSOR; /* to show or not to show */
 PUBLIC BOOLEAN LYUseDefShoCur = TRUE;	/* Command line -show_cursor toggle */
 PUBLIC BOOLEAN LYforce_no_cache = FALSE;
-PUBLIC BOOLEAN LYoverride_no_cache = FALSE;
+PUBLIC BOOLEAN LYoverride_no_cache = FALSE;/*override no-cache b/c history etc*/
+PUBLIC BOOLEAN LYinternal_flag = FALSE;	/* override no-cache b/c internal link*/
 PUBLIC BOOLEAN LYresubmit_posts = ALWAYS_RESUBMIT_POSTS;
 PUBLIC BOOLEAN LYUserSpecifiedURL = TRUE;/* always TRUE  the first time */
 PUBLIC BOOLEAN LYJumpFileURL = FALSE;	 /* always FALSE the first time */
@@ -1563,7 +1564,7 @@ PUBLIC int main ARGS2(
     /*
      *  Check for a valid HEAD request. - FM
      */
-    if (HEAD_request && strncmp(startfile, "http", 4)) {
+    if (HEAD_request && LYCanDoHEAD(startfile) != TRUE) {
         fprintf(stderr,
  "The '-head' switch is for http HEAD requests and cannot be used for\n'%s'.\n",
 		startfile);
@@ -1584,7 +1585,7 @@ PUBLIC int main ARGS2(
     /*
      *  Check for a valid MIME headers request. - FM
      */
-    if (keep_mime_headers && strncmp(startfile, "http", 4)) {
+    if (keep_mime_headers && LYCanDoHEAD(startfile) != TRUE) {
         fprintf(stderr,
  "The '-mime_header' switch is for http URLs and cannot be used for\n'%s'.\n",
 		startfile);
diff --git a/src/LYMainLoop.c b/src/LYMainLoop.c
index 12e43f5b..11020387 100644
--- a/src/LYMainLoop.c
+++ b/src/LYMainLoop.c
@@ -56,6 +56,11 @@
 #include "LYexit.h"
 #include "LYLeaks.h"
 
+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));
 PRIVATE int are_phys_different PARAMS((document *doc1, document *doc2));
 PUBLIC void HTGotoURLs_free NOPARAMS;
@@ -129,7 +134,8 @@ PRIVATE void free_mainloop_variables NOARGS
 
 int mainloop NOARGS
 {
-    int c = 0, real_c = 0, old_c = 0, cmd, real_cmd = LYK_DO_NOTHING;
+    int c = 0, real_c = 0, old_c = 0;
+    int cmd = LYK_DO_NOTHING, real_cmd = LYK_DO_NOTHING;
     int getresult;
     int arrowup = FALSE, show_help = FALSE;
     int lines_in_file = -1;
@@ -336,11 +342,11 @@ try_again:
 
 
 #ifndef DONT_TRACK_INTERNAL_LINKS
-#define NONINTERNAL_OR_DIFFERENT(c,n) TRUE
+#define NO_INTERNAL_OR_DIFFERENT(c,n) TRUE
 #define NONINTERNAL_OR_PHYS_DIFFERENT(p,n) (!curdoc.internal_link || \
 			   are_phys_different(p,n))
 #else /* TRACK_INTERNAL_LINKS */
-#define NONINTERNAL_OR_DIFFERENT(c,n) are_different(c,n)
+#define NO_INTERNAL_OR_DIFFERENT(c,n) are_different(c,n)
 #define NONINTERNAL_OR_PHYS_DIFFERENT(p,n) are_different(p,n)
 #endif /* TRACK_INTERNAL_LINKS */
 
@@ -354,6 +360,7 @@ try_again:
 		    */
 		    if (curdoc.internal_link &&
 			!are_phys_different(&curdoc, &newdoc)) {
+		        LYinternal_flag = TRUE;
 		        LYoverride_no_cache = TRUE;
 			LYforce_no_cache = FALSE;
 			try_internal = TRUE;
@@ -362,7 +369,7 @@ try_again:
 			if ((newdoc.bookmark != NULL) ||
 			(newdoc.post_data != NULL && !newdoc.safe &&
 			 LYresubmit_posts &&
-			    NONINTERNAL_OR_DIFFERENT(&curdoc, &newdoc))) {
+			    NO_INTERNAL_OR_DIFFERENT(&curdoc, &newdoc))) {
 		        LYoverride_no_cache = FALSE;
 		    } else {
 		        LYoverride_no_cache = TRUE;
@@ -374,10 +381,10 @@ try_again:
 		     *  Make SURE this is an appropriate request. - FM
 		     */
 		    if (newdoc.address) {
-			if (!strncmp(newdoc.address, "http", 4)) {
+			if (LYCanDoHEAD(newdoc.address) == TRUE) {
 			    newdoc.isHEAD = TRUE;
 			} else if (!strncmp(newdoc.address, "LYNXIMGMAP:", 11)) {
-			    if (!strncmp(newdoc.address + 11, "http", 4)) {
+			    if (LYCanDoHEAD(newdoc.address + 11) == TRUE) {
 				StrAllocCopy(temp, newdoc.address + 11);
 				FREE(newdoc.address);
 				newdoc.address = temp;
@@ -505,6 +512,7 @@ try_again:
 		     */
 		    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;
@@ -595,6 +603,7 @@ try_again:
 		     */
 		    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;
@@ -632,11 +641,11 @@ try_again:
 			*/
 		       if (first_file && homepage &&
 #ifdef VMS
-			   strcasecomp(homepage, startfile) != 0)
+			   strcasecomp(homepage, startfile) != 0
 #else
-			   strcmp(homepage, startfile) != 0)
+			   strcmp(homepage, startfile) != 0
 #endif /* VMS */
-			{
+			   ) {
 			   /* 
 			    *  Couldn't return to the first file but there is a
 			    *  homepage we can use instead. Useful for when the
@@ -655,6 +664,7 @@ try_again:
 			   newdoc.isHEAD = FALSE;
 			   newdoc.safe = FALSE;
 			   newdoc.internal_link = FALSE;
+			   goto try_again;
 		       } else {
 		           if (!dump_output_immediately)
 			       cleanup();
@@ -688,6 +698,48 @@ try_again:
 		       }
 		    }
 
+		   /*
+		    *  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.
+		    */
+		   if (history[nhist - 1].post_data &&
+		       !history[nhist - 1].safe) {
+                       /*  Set newdoc fields, just in case the PREV_DOC
+                        *  gets cancelled. - kw */
+		       if (!curdoc.address) {
+			   StrAllocCopy(newdoc.address, HTLoadedDocumentURL());
+			   StrAllocCopy(newdoc.title, HTLoadedDocumentTitle());
+			   if (HTMainAnchor && HTMainAnchor->post_data) {
+			       StrAllocCopy(newdoc.post_data,
+					    HTMainAnchor->post_data);
+			       StrAllocCopy(newdoc.post_content_type,
+					    HTMainAnchor->post_content_type);
+			   } else {
+			       FREE(newdoc.post_data);
+			   }
+			   newdoc.isHEAD = HTLoadedDocumentIsHEAD();
+			   newdoc.safe = HTLoadedDocumentIsSafe();
+			   newdoc.internal_link = FALSE;
+		       } else {
+			   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);
+			   newdoc.isHEAD = curdoc.isHEAD;
+			   newdoc.safe = curdoc.safe;
+			   newdoc.internal_link = curdoc.internal_link;
+			   newdoc.line = curdoc.line;
+			   newdoc.link = curdoc.link;
+		       }
+		       cmd = LYK_PREV_DOC;
+		       goto new_cmd;
+		       }
 		    goto try_again;
                     break;
 
@@ -696,6 +748,7 @@ try_again:
 		     *  Marvelously, we got the document!
 		     */
 		    LYoverride_no_cache = 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;
@@ -728,10 +781,12 @@ try_again:
 			len = strlen(cp);
 #ifdef VMS
 			if (!strncasecomp(temp, cp, len) &&
+			    strlen(temp) > len)
 #else
 			if (!strncmp(temp, cp, len) &&
+			    strlen(temp) > len)
 #endif /* VMS */
-			    strlen(temp) > len) {
+			{
 			    /*
 			     *  We're interactive and this might be a
 			     *  bookmark file entered as a startfile
@@ -755,11 +810,11 @@ try_again:
 			    for (i = 0; i <= MBM_V_MAXFILES; i++) {
 				if (MBM_A_subbookmark[i] &&
 #ifdef VMS
-				    !strcasecomp(cp, MBM_A_subbookmark[i]))
+				    !strcasecomp(cp, MBM_A_subbookmark[i])
 #else
-				    !strcmp(cp, MBM_A_subbookmark[i]))
+				    !strcmp(cp, MBM_A_subbookmark[i])
 #endif /* VMS */
-				{
+				    ) {
 				    StrAllocCopy(BookmarkPage,
 						 MBM_A_subbookmark[i]);
 				    break;
@@ -943,7 +998,7 @@ try_again:
 	   LYforce_HTML_mode = FALSE;
 	   popped_doc = FALSE;
 
-  	} /* end if (STREQ(newdoc.address, curdoc.address) */
+  	} /* end if (LYforce_no_cache || force_load || are_different(...)) */
 
         if (dump_output_immediately) {
 	    if (crawl) {
@@ -1165,7 +1220,10 @@ try_again:
 	 *  Refresh the screen if neccessary.
 	 */
 	if (refresh_screen) {
-	    clear();
+	    if (enable_scrollback)
+		clear();
+	    else
+		erase();
 	    HText_pageDisplay(Newline, prev_target);
 
 #ifdef DIRED_SUPPORT
@@ -1629,22 +1687,112 @@ new_cmd:  /*
 		 */
 		StrAllocCopy(newdoc.address, links[lindx].lname);
 		StrAllocCopy(newdoc.title, links[lindx].hightext);
+#ifndef DONT_TRACK_INTERNAL_LINKS
 		/*
-		 *  Might be an anchor in the same doc from a POST
-		 *  form.  If so, don't free the content. -- FM
+		 *  For internal links, retain POST content if present.
+		 *  If we are on the List Page, prevent pushing it on
+		 *  the history stack.  Otherwise set try_internal to
+		 *  signal that the top of the loop should attempt to
+		 *  reposition directly, without calling getfile. - kw
 		 */
 		if (links[lindx].type == WWW_INTERN_LINK_TYPE) {
-		    LYoverride_no_cache = TRUE;
+		    LYinternal_flag = TRUE;
 		    newdoc.internal_link = TRUE;
-		    if (0==strcmp(curdoc.address, LYlist_temp_url()) &&
-			0==strcmp((curdoc.title ? curdoc.title : ""),
-				      LIST_PAGE_TITLE)) {
+		    if (0==strcmp((curdoc.title ? curdoc.title : ""),
+				      LIST_PAGE_TITLE) &&
+			0==strcmp(HTLoadedDocumentURL(), LYlist_temp_url())) {
+			if (!curdoc.post_data ||
+			    /*
+			     *  Normal case - List Page is not associated
+			     *  with post data. - kw
+			     */
+			    (!LYresubmit_posts && curdoc.post_data &&
+			     history[nhist - 1].post_data &&
+			     !strcmp(curdoc.post_data,
+				     history[nhist - 1].post_data) &&
+			     HText_getContentBase() &&
+			     !strncmp(HText_getContentBase(),
+				      strncmp(history[nhist - 1].address,
+					      "LYNXIMGMAP:", 11) ?
+				      history[nhist - 1].address :
+				      history[nhist - 1].address + 11,
+				      strlen(HText_getContentBase())))) {
+			    /*
+			     *  Normal case - as best as we can check, the
+			     *  document at the top of the history stack
+			     *  seems to be the document the List Page is
+			     *  about (or a LYNXIMGMAP derived from it),
+			     *  and LYresubmit_posts is not set, so don't
+			     *  prompt here.  If we actually have to repeat
+			     *  a POST because, against expectations, the
+			     *  underlying document isn't cached any more,
+			     *  HTAccess will prompt for confirmation,
+			     *  unless we had LYK_NOCACHE. - kw
+			     */
+			    LYinternal_flag = TRUE;
+			} else {
+			    HTLastConfirmCancelled(); /* reset flag */
+			    if (!confirm_post_resub(newdoc.address,
+						    newdoc.title,
+						    (LYresubmit_posts &&
+						     HText_POSTReplyLoaded(&newdoc)) ? 1 : 2,
+						    2)) {
+				if (HTLastConfirmCancelled() ||
+				    (LYresubmit_posts &&
+				     !HText_POSTReplyLoaded(&newdoc))) {
+				    /* cancel the whole thing */
+				    LYforce_no_cache = FALSE;
+				    reloading = FALSE;
+				    StrAllocCopy(newdoc.address, curdoc.address);
+				    StrAllocCopy(newdoc.title, curdoc.title);
+				    newdoc.internal_link = curdoc.internal_link;
+				    _statusline(CANCELLED);
+				    sleep(InfoSecs);
+				    if (nlinks > 0)
+					HText_pageDisplay(curdoc.line, prev_target);
+				    break;
+				} else if (LYresubmit_posts) {
+				    /* If LYresubmit_posts is set, and the
+				       answer was No, and we have a cached
+				       copy, then use it. - kw */
+				    LYforce_no_cache = FALSE;
+				} else {
+				    /* if No, but not ^C or ^G, drop
+				     * the post data.  Maybe the link
+				     * wasn't meant to be internal after
+				     * all, here we can recover from that
+				     * assumption. - kw */
+				    FREE(newdoc.post_data);
+				    FREE(newdoc.post_content_type);
+				    newdoc.internal_link = FALSE;
+				    _statusline(DISCARDING_POST_DATA);
+				    sleep(AlertSecs);
+				}
+			    }
+			}
+			/*
+			 *  Don't push the List Page if we follow an
+			 *  internal link given by it. - kw
+			 */
 			FREE(curdoc.address);
 		    } else
 			try_internal = TRUE;
+		    if (!(LYresubmit_posts && newdoc.post_data))
+			LYinternal_flag = TRUE;
 		    force_load = TRUE;
 		    break;
+		} else {
+		    /*
+		     *  Free POST content if not an internal link. - kw
+		     */
+		    FREE(newdoc.post_data);
+		    FREE(newdoc.post_content_type);
 		}
+#endif /* DONT_TRACK_INTERNAL_LINKS */
+		/*
+		 *  Might be an anchor in the same doc from a POST
+		 *  form.  If so, don't free the content. -- FM
+		 */
 		if (are_different(&curdoc, &newdoc)) {
 		    FREE(newdoc.post_data);
 		    FREE(newdoc.post_content_type);
@@ -1742,7 +1890,8 @@ new_cmd:  /*
 	     */
 	    if ((curdoc.post_data != NULL &&
 	         curdoc.safe != TRUE) &&
-		HTConfirm(CONFIRM_POST_RESUBMISSION) == FALSE) {
+		confirm_post_resub(curdoc.address, curdoc.title,
+				   1, 1) == FALSE) {
 		_statusline(CANCELLED);
 		sleep(InfoSecs);
 		break;
@@ -1832,7 +1981,8 @@ new_cmd:  /*
 	     */
 	    if ((curdoc.post_data != NULL &&
 	         curdoc.safe != TRUE) &&
-		HTConfirm(CONFIRM_POST_RESUBMISSION) == FALSE) {
+		confirm_post_resub(curdoc.address, NULL,
+				   0, 0) == FALSE) {
 		_statusline(WILL_NOT_RELOAD_DOC);
 		sleep(InfoSecs);
 	    } else {
@@ -1863,7 +2013,8 @@ new_cmd:  /*
 		 */
 		if ((curdoc.post_data != NULL &&
 		     curdoc.safe != TRUE) &&
-		    HTConfirm(CONFIRM_POST_RESUBMISSION) == FALSE) {
+		    confirm_post_resub(curdoc.address, NULL,
+				       0, 0) == FALSE) {
 		    _statusline(WILL_NOT_RELOAD_DOC);
 		    sleep(InfoSecs);
 		} else {
@@ -1894,7 +2045,8 @@ new_cmd:  /*
 	     */
 	    if ((curdoc.post_data != NULL &&
 	         curdoc.safe != TRUE) &&
-		HTConfirm(CONFIRM_POST_RESUBMISSION) == FALSE) {
+		confirm_post_resub(curdoc.address, NULL,
+				   1, 1) == FALSE) {
 		_statusline(WILL_NOT_RELOAD_DOC);
 		sleep(InfoSecs);
 	    } else {
@@ -1919,7 +2071,8 @@ new_cmd:  /*
 	     */
 	    if ((curdoc.post_data != NULL &&
 	         curdoc.safe != TRUE) &&
-		HTConfirm(CONFIRM_POST_RESUBMISSION) == FALSE) {
+		confirm_post_resub(curdoc.address, NULL,
+				   1, 1) == FALSE) {
 		_statusline(WILL_NOT_RELOAD_DOC);
 		sleep(InfoSecs);
 	    } else {
@@ -2080,9 +2233,7 @@ new_cmd:  /*
 
 	case LYK_REFRESH:
 	   refresh_screen = TRUE;
-#if defined(VMS) || defined(USE_SLANG)
 	   lynx_force_repaint();
-#endif /* VMS || USE_SLANG */
 	   break;
 
 	case LYK_HOME:
@@ -2398,8 +2549,12 @@ new_cmd:  /*
 		 */
 		DocAddress WWWDoc;
 		HTParentAnchor *tmpanchor;
+		HText *text;
+		BOOLEAN conf = FALSE, first = TRUE;
 
+		HTLastConfirmCancelled(); /* reset flag */
 		while (nhist > 0) {
+		    conf = FALSE;
 		    if (history[(nhist - 1)].post_data == NULL) {
 			break;
 		    }
@@ -2414,12 +2569,29 @@ new_cmd:  /*
 		    if (HTAnchor_safe(tmpanchor)) {
 			break;
 		    }
-		    if (((HText *)HTAnchor_document(tmpanchor) == NULL ||
-			 (LYresubmit_posts &&
-			  NONINTERNAL_OR_PHYS_DIFFERENT(
+		    if (((text =
+			  (HText *)HTAnchor_document(tmpanchor)) == NULL &&
+			 (!strncmp(WWWDoc.address, "LYNXIMGMAP:", 11) ||
+			 (conf = confirm_post_resub(WWWDoc.address,
+						    history[(nhist - 1)].title,
+						    0, 0))
+			  == FALSE)) ||
+			((LYresubmit_posts && !conf &&
+			  (NONINTERNAL_OR_PHYS_DIFFERENT(
 			      (document *)&history[(nhist - 1)],
-			      &curdoc))) &&
-			HTConfirm(CONFIRM_POST_RESUBMISSION) == FALSE) {
+			      &curdoc) ||
+			   NONINTERNAL_OR_PHYS_DIFFERENT(
+			       (document *)&history[(nhist - 1)],
+			       &newdoc))) &&
+			 !confirm_post_resub(WWWDoc.address,
+					     history[(nhist - 1)].title,
+					     2, 2))) {
+			if (HTLastConfirmCancelled()) {
+			    if (!first && curdoc.internal_link)
+				FREE(curdoc.address);
+			    cmd = LYK_DO_NOTHING;
+			    goto new_cmd;
+			}
 			if (nhist == 1) {
 			    _statusline(CANCELLED);
 			    sleep(InfoSecs);
@@ -2429,13 +2601,29 @@ new_cmd:  /*
 			} else {
 			    _user_message(WWW_SKIP_MESSAGE, WWWDoc.address);
 			    sleep(MessageSecs);
-			    LYpop(&curdoc);
+			    do {
+				LYpop(&curdoc);
+			    } while (nhist > 1 && !are_different(
+				(document *)&history[(nhist - 1)],
+				&curdoc));
+			    first = FALSE; /* have popped at least one */
 			    continue;
 			}
 		    } else {
+			/*
+			 *  Break from loop; if user just confirmed to
+			 *  load again because document wasn't in cache,
+			 *  set LYforce_no_cache to avoid unnecessary
+			 *  repeat question down the road. - kw
+			 */
+			if (conf)
+			    LYforce_no_cache = TRUE;
 			break;
 		    }
 		}
+		
+		if (!first)
+		    curdoc.internal_link = FALSE;
 
 		/*
 		 *  Set newdoc.address to empty to pop a file.
@@ -2494,6 +2682,7 @@ new_cmd:  /*
 			if (links[curdoc.link].form->disabled == YES) {
 			    HTOutputFormat = WWW_PRESENT;
 			    LYforce_no_cache = FALSE;
+			    reloading = FALSE;
 			    break;
 			}
 			/*
@@ -2506,6 +2695,7 @@ new_cmd:  /*
 			    sleep(MessageSecs);
 			    HTOutputFormat = WWW_PRESENT;
 			    LYforce_no_cache = FALSE;
+			    reloading = FALSE;
 			    break;
 			}
 	    		/*
@@ -2517,6 +2707,7 @@ new_cmd:  /*
 			    HTAlert(FORM_MAILTO_DISALLOWED);
 			    HTOutputFormat = WWW_PRESENT;
 			    LYforce_no_cache = FALSE;
+			    reloading = FALSE;
 			    break;
 			}
 			/*
@@ -2530,6 +2721,7 @@ new_cmd:  /*
 			    HTAlert(FILE_ACTIONS_DISALLOWED);
 			    HTOutputFormat = WWW_PRESENT;
 			    LYforce_no_cache = FALSE;
+			    reloading = FALSE;
 			    break;
 			}
 			/*
@@ -2586,6 +2778,7 @@ new_cmd:  /*
 			    }
 			    HTOutputFormat = WWW_PRESENT;
 			    LYforce_no_cache = FALSE;
+			    reloading = FALSE;
 			    break;
 			}
 #ifdef NOTDEFINED /* We're disabling form inputs instead of using this. - FM */
@@ -2601,6 +2794,7 @@ new_cmd:  /*
 	"Enctype multipart/form-data not yet supported!  Cannot submit.");
 				HTOutputFormat = WWW_PRESENT;
 				LYforce_no_cache = FALSE;
+				reloading = FALSE;
 				break;
 	    		    }
 			}
@@ -2656,9 +2850,11 @@ new_cmd:  /*
 		        !strncmp(links[curdoc.link].lname, "file:", 5)) {
 			if (strncmp(curdoc.address, "file:", 5)) {
 			    HTAlert(FILE_SERVED_LINKS_DISALLOWED);
+			    reloading = FALSE;
 			    break;
 			} else if (curdoc.bookmark != NULL) {
 			    HTAlert(FILE_BOOKMARKS_DISALLOWED);
+			    reloading = FALSE;
 			    break;
 			}
 		    }
@@ -2691,7 +2887,8 @@ new_cmd:  /*
 			(!strncmp(links[curdoc.link].lname,
 				  "LYNXHIST:", 9) &&
 			 strcmp((curdoc.title ? curdoc.title : ""),
-				HISTORY_PAGE_TITLE)) ||
+				HISTORY_PAGE_TITLE) &&
+			 strcmp(curdoc.address, LYlist_temp_url())) ||
 			(!strncmp(links[curdoc.link].lname,
 				  "LYNXPRINT:", 10) &&
 			 strcmp((curdoc.title ? curdoc.title : ""),
@@ -2699,6 +2896,7 @@ new_cmd:  /*
 			    HTAlert(SPECIAL_VIA_EXTERNAL_DISALLOWED);
 			    HTOutputFormat = WWW_PRESENT;
 			    LYforce_no_cache = FALSE;
+			    reloading = FALSE;
 			    break;
 			}
 		    /*
@@ -2707,6 +2905,13 @@ new_cmd:  /*
 		    StrAllocCopy(newdoc.address, links[curdoc.link].lname);
 		    StrAllocCopy(newdoc.title, links[curdoc.link].hightext);
 #ifndef DONT_TRACK_INTERNAL_LINKS
+		/*
+		 *  For internal links, retain POST content if present.
+		 *  If we are on the List Page, prevent pushing it on
+		 *  the history stack.  Otherwise set try_internal to
+		 *  signal that the top of the loop should attempt to
+		 *  reposition directly, without calling getfile. - kw
+		 */
 		    /*
 		     *  Might be an internal link anchor in the same doc.
 		     *  If so, take the try_internal shortcut if we didn't
@@ -2715,19 +2920,105 @@ new_cmd:  /*
 		    newdoc.internal_link =
 			(links[curdoc.link].type == WWW_INTERN_LINK_TYPE);
 		    if (newdoc.internal_link) {
+			/*
+			 *  Special case of List Page document with an
+			 *  internal link indication, which may really stand
+			 *  for an internal link within the document the
+			 *  List Page is about. - kw
+			 */
 			if (0==strcmp(curdoc.address, LYlist_temp_url()) &&
 			    0==strcmp((curdoc.title ? curdoc.title : ""),
 				      LIST_PAGE_TITLE)) {
+			    if (!curdoc.post_data ||
+				/*
+				 *  Normal case - List Page is not associated
+				 *  with post data. - kw
+				 */
+				(!LYresubmit_posts && curdoc.post_data &&
+				history[nhist - 1].post_data &&
+				!strcmp(curdoc.post_data,
+					 history[nhist - 1].post_data) &&
+				HText_getContentBase() &&
+				!strncmp(HText_getContentBase(),
+					 strncmp(history[nhist - 1].address,
+						 "LYNXIMGMAP:", 11) ?
+					 history[nhist - 1].address :
+					 history[nhist - 1].address + 11,
+					 strlen(HText_getContentBase())))) {
+				/*
+				 *  Normal case - as best as we can check, the
+				 *  document at the top of the history stack
+				 *  seems to be the document the List Page is
+				 *  about (or a LYNXIMGMAP derived from it),
+				 *  and LYresubmit_posts is not set, so don't
+				 *  prompt here.  If we actually have to repeat
+				 *  a POST because, against expectations, the
+				 *  underlying document isn't cached any more,
+				 *  HTAccess will prompt for confirmation,
+				 *  unless we had LYK_NOCACHE. - kw
+				 */
+				LYinternal_flag = TRUE;
+			    } else {
+				HTLastConfirmCancelled(); /* reset flag */
+				if (!confirm_post_resub(newdoc.address,
+							newdoc.title,
+						(LYresubmit_posts &&
+				       HText_POSTReplyLoaded(&newdoc)) ? 1 : 2,
+						        2)) {
+				    if (HTLastConfirmCancelled() ||
+					(LYresubmit_posts &&
+					 cmd != LYK_NOCACHE &&
+					 !HText_POSTReplyLoaded(&newdoc))) {
+					/* cancel the whole thing */
+					LYforce_no_cache = FALSE;
+					reloading = FALSE;
+					StrAllocCopy(newdoc.address, curdoc.address);
+					StrAllocCopy(newdoc.title, curdoc.title);
+					newdoc.internal_link = curdoc.internal_link;
+					_statusline(CANCELLED);
+					sleep(InfoSecs);
+					break;
+				    } else if (LYresubmit_posts &&
+					       cmd != LYK_NOCACHE) {
+					/* If LYresubmit_posts is set, and the
+					   answer was No, and the key wasn't
+					   NOCACHE, and we have a cached copy,
+					   then use it. - kw */
+					LYforce_no_cache = FALSE;
+				    } else {
+					/* if No, but not ^C or ^G, drop
+					 * the post data.  Maybe the link
+					 * wasn't meant to be internal after
+					 * all, here we can recover from that
+					 * assumption. - kw */
+					FREE(newdoc.post_data);
+					FREE(newdoc.post_content_type);
+					newdoc.internal_link = FALSE;
+					_statusline(DISCARDING_POST_DATA);
+					sleep(AlertSecs);
+				    }
+				}
+			    }
+			    /*
+			     *  Don't push the List Page if we follow an
+			     *  internal link given by it. - kw
+			     */
 			    FREE(curdoc.address);
 			} else if (cmd != LYK_NOCACHE) {
 			    try_internal = TRUE;
 			}
-			LYoverride_no_cache = TRUE;	/* ??? */
+			if (!(LYresubmit_posts && newdoc.post_data))
+			    LYinternal_flag = TRUE;
 			/* We still set force_load so that history pushing
 			** etc. will be done.  - kw */
 			force_load = TRUE;
 			break;
 		    } else {
+			/*
+			 *  Free POST content if not an internal link. - kw
+			 */
+		        FREE(newdoc.post_data);
+		        FREE(newdoc.post_content_type);
 		    }
 #endif /* TRACK_INTERNAL_LINKS */
 		    /*
@@ -3309,7 +3600,8 @@ check_goto_URL:
 		 */
 		if ((curdoc.post_data != NULL &&
 		     curdoc.safe != TRUE) &&
-		    HTConfirm(CONFIRM_POST_RESUBMISSION) == FALSE) {
+		    confirm_post_resub(curdoc.address, curdoc.title,
+				       2, 1) == FALSE) {
 		    _statusline(WILL_NOT_RELOAD_DOC);
 		    sleep(InfoSecs);
 	    
@@ -3814,6 +4106,10 @@ check_goto_URL:
 				     curdoc.bookmark);
 	    } else {	/* behave like REFRESH for backward compatability */
 	        refresh_screen = TRUE;
+		if (old_c != real_c) {
+		    old_c = real_c;
+		    lynx_force_repaint();
+		}
 		break;
 	    }
 	    if (TOUPPER(c) == 'Y') {
@@ -3914,15 +4210,16 @@ check_goto_URL:
 	    /*
 	     *  Print list page to file.
 	     */
-	    if (showlist(&newdoc.address, TRUE) < 0)
+	    if (showlist(&newdoc, TRUE) < 0)
 		break;
 	    StrAllocCopy(newdoc.title, LIST_PAGE_TITLE);
-	    FREE(newdoc.post_data);
-	    FREE(newdoc.post_content_type);
-	    FREE(newdoc.bookmark);
-	    newdoc.isHEAD = FALSE;
-	    newdoc.safe = FALSE;
-	    newdoc.internal_link = FALSE;
+	    /*
+	     *  showlist will sett newdoc's other fields. It may leave
+	     *  post_data intact so the list can be used to follow
+	     *  internal links in the current document even if it is
+	     *  a POST response. - kw
+	     */
+
 	    refresh_screen = TRUE;  /* redisplay */
 	    if (LYValidate || check_realm) {
 		LYPermitURL = TRUE;
@@ -4207,6 +4504,14 @@ check_goto_URL:
 			     *  exists in this bookmark file. - FM
 			     */
 			    _statusline(MULTIBOOKMARKS_SELF);
+			} else if (curdoc.post_data != NULL &&
+				   links[curdoc.link].type == WWW_INTERN_LINK_TYPE) {
+			    /*
+			     *  Internal link, and document has POST content.
+			     */
+			    _statusline(NOBOOK_POST_FORM);
+			    sleep(MessageSecs);
+			    break;
 			} else {
 		            /*
 			     *  Only offer the link in a document with
@@ -4219,6 +4524,15 @@ check_goto_URL:
 			c = LYgetch();
 		    }
 		    if (TOUPPER(c) == 'L') {
+			if (curdoc.post_data != NULL &&
+			    links[curdoc.link].type == WWW_INTERN_LINK_TYPE) {
+			    /*
+			     *  Internal link, and document has POST content.
+			     */
+			    _statusline(NOBOOK_POST_FORM);
+			    sleep(MessageSecs);
+			    break;
+			}
 		        /*
 			 *  User does want to save the link. - FM
 			 */
@@ -4468,7 +4782,8 @@ check_add_bookmark_to_self:
 #endif /* DIRED_SUPPORT */
 
 		} else if (!strcmp((curdoc.title ? curdoc.title : ""),
-				   HISTORY_PAGE_TITLE)) {
+				   HISTORY_PAGE_TITLE) &&
+		    !strncmp(links[curdoc.link].lname, "LYNXHIST:", 9)) {
 		    int number = atoi(links[curdoc.link].lname+9);
 		    if ((history[number].post_data != NULL &&
 		         history[number].safe != TRUE) &&
@@ -4528,18 +4843,27 @@ check_add_bookmark_to_self:
 		     */
                     StrAllocCopy(newdoc.address, links[curdoc.link].lname);
                     StrAllocCopy(newdoc.title, links[curdoc.link].hightext);
-		    newdoc.internal_link = FALSE;
+#ifndef DONT_TRACK_INTERNAL_LINKS
+		    /*
+		     *  Might be an internal link in the same doc from a
+		     *  POST form.  If so, don't free the content. - kw
+		     */
+		    if (links[curdoc.link].type != WWW_INTERN_LINK_TYPE)
+#else
 		    /*
 		     *  Might be an anchor in the same doc from a POST
 		     *  form.  If so, don't free the content. -- FM
 		     */
-		    if (are_different(&curdoc, &newdoc)) {
+		    if (are_different(&curdoc, &newdoc))
+#endif /* TRACK_INTERNAL_LINKS */
+		    {
 			FREE(newdoc.post_data);
 			FREE(newdoc.post_content_type);
 			FREE(newdoc.bookmark);
 			newdoc.isHEAD = FALSE;
 			newdoc.safe = FALSE;
 		    }
+		    newdoc.internal_link = FALSE;
                     newdoc.link = 0;
 	            HTOutputFormat = HTAtom_for("www/download");
 		    /*
@@ -4744,7 +5068,7 @@ check_add_bookmark_to_self:
 		if (TOUPPER(c) == 'D') {
 		    char *scheme = strncmp(curdoc.address, "LYNXIMGMAP:", 11) ?
 			curdoc.address : curdoc.address + 11;
-		    if (strncmp(scheme, "http", 4)) {
+		    if (LYCanDoHEAD(scheme) != TRUE) {
 		        _statusline(DOC_NOT_HTTP_URL);
 			sleep(MessageSecs);
 		    } else {
@@ -4776,6 +5100,7 @@ check_add_bookmark_to_self:
 		    	strncmp(links[curdoc.link].lname, "http", 4) &&
 		    	strncmp(links[curdoc.link].lname,
 				"LYNXIMGMAP:http", 15) &&
+			LYCanDoHEAD(links[curdoc.link].lname) != TRUE &&
 			(links[curdoc.link].type != WWW_INTERN_LINK_TYPE ||
 			 !curdoc.address ||
 			 strncmp(curdoc.address, "http", 4))) {
@@ -4787,6 +5112,8 @@ check_add_bookmark_to_self:
 			sleep(MessageSecs);
 		    } else if (links[curdoc.link].type == WWW_FORM_LINK_TYPE &&
 		    	       strncmp(links[curdoc.link].form->submit_action,
+							      "lynxcgi:", 8) &&
+		    	       strncmp(links[curdoc.link].form->submit_action,
 								 "http", 4)) {
 			_statusline(FORM_ACTION_NOT_HTTP_URL);
 			sleep(MessageSecs);
@@ -4799,8 +5126,6 @@ check_add_bookmark_to_self:
 		    } else {
 			HEAD_request = TRUE;
 			LYforce_no_cache = TRUE;
-			StrAllocCopy(newdoc.title, links[curdoc.link].hightext);
-			StrAllocCat(newdoc.title, " - (HEAD)");
 			cmd = LYK_ACTIVATE;
 			goto new_cmd;
 		    }
@@ -4844,7 +5169,7 @@ check_add_bookmark_to_self:
 		     *  a HEAD request is appropriate for the
 		     *  current document. - FM
 		     */ 
-		    if (strncmp(scheme, "http", 4)) {
+		    if (LYCanDoHEAD(scheme) != TRUE) {
 		        _statusline(DOC_NOT_HTTP_URL);
 			sleep(MessageSecs);
 		    } else {
@@ -4998,6 +5323,88 @@ check_add_bookmark_to_self:
     }
 }
 
+/*
+ *  Ask a post resubmission prompt with some indication of what would
+ *  be resubmitted, useful especially for going backward in history.
+ *  Try to use parts of the address or, if given, the title, depending
+ *  on how much fits on the statusline.
+ *  if_imgmap and if_file indicate how to handle an address that is
+ *  a "LYNXIMGMAP:", or a "file:" URL (presumably the List Page file),
+ *  respectively: 0: auto-deny, 1: auto-confirm, 2: prompt.
+ *  - kw
+ */
+
+PRIVATE BOOL confirm_post_resub ARGS4(
+    CONST char*,	address,
+    CONST char*,	title,
+    int,		if_imgmap,
+    int,		if_file)
+{
+    size_t len1;
+    CONST char *msg = CONFIRM_POST_RESUBMISSION_TO;
+    char buf[240];
+    char *temp = NULL;
+    BOOL res;
+    size_t maxlen = LYcols - 6;
+    if (!address) {
+	return(NO);
+    } else if (!strncmp(address, "LYNXIMGMAP:", 11)) {
+	if (if_imgmap <= 0)
+	    return(NO);
+	else if (if_imgmap == 1)
+	    return(YES);
+	else
+	    msg = CONFIRM_POST_LIST_RELOAD;
+    } else if (!strncmp(address, "file:", 5)) {
+	if (if_file <= 0)
+	    return(NO);
+	else if (if_file == 1)
+	    return(YES);
+	else
+	    msg = CONFIRM_POST_LIST_RELOAD;
+    } else if (dump_output_immediately) {
+	return(NO);
+    }
+    if (maxlen >= sizeof(buf))
+	maxlen = sizeof(buf) - 1;
+    if ((len1 = strlen(msg)) +
+	strlen(address) <= maxlen) {
+	sprintf(buf, msg, address);
+	return HTConfirm(buf);
+    }
+    if (len1 + strlen(temp = HTParse(address, "",
+				     PARSE_ACCESS+PARSE_HOST+PARSE_PATH
+				     +PARSE_PUNCTUATION)) <= maxlen) {
+	sprintf(buf, msg, temp);
+	res = HTConfirm(buf);
+	FREE(temp);
+	return(res);
+    }
+    FREE(temp);
+    if (title && (len1 + strlen(title) <= maxlen)) {
+	sprintf(buf, msg, title);
+	return HTConfirm(buf);
+    }
+    if (len1 + strlen(temp = HTParse(address, "",
+				     PARSE_ACCESS+PARSE_HOST
+				     +PARSE_PUNCTUATION)) <= maxlen) {
+	sprintf(buf, msg, temp);
+	res = HTConfirm(buf);
+	FREE(temp);
+	return(res);
+    }
+    FREE(temp);
+    if ((temp = HTParse(address, "", PARSE_HOST)) && *temp &&
+	len1 + strlen(temp) <= maxlen) {
+	sprintf(buf, msg, temp);
+	res = HTConfirm(buf);
+	FREE(temp);
+	return(res);
+    }
+    FREE(temp);
+    return HTConfirm(CONFIRM_POST_RESUBMISSION);
+}
+
 PRIVATE int are_different ARGS2(
 	document *,	doc1,
 	document *,	doc2)
diff --git a/src/LYMap.c b/src/LYMap.c
index 103a41eb..1c2a194e 100644
--- a/src/LYMap.c
+++ b/src/LYMap.c
@@ -53,13 +53,14 @@ PRIVATE HTList * LynxMaps = NULL;
 PUBLIC BOOL LYMapsOnly = FALSE;
 
 /* 
- *  Utility for freeing the list of MAPs. - FM
+ *  Utility for freeing a list of MAPs.
  */
-PRIVATE void LYLynxMaps_free NOARGS
+PUBLIC void ImageMapList_free ARGS1(
+    HTList *,		theList)
 {
     LYImageMap *map;
     LYMapElement *element;
-    HTList *cur = LynxMaps;
+    HTList *cur = theList;
     HTList *current;
 
     if (!cur)
@@ -81,36 +82,92 @@ PRIVATE void LYLynxMaps_free NOARGS
 	}
 	FREE(map);
     }
-    HTList_delete(LynxMaps);
+    HTList_delete(theList);
+    return;
+}
+
+/* 
+ *  Utility for freeing the global list of MAPs. - kw
+ */
+PRIVATE void LYLynxMaps_free NOARGS
+{
+    ImageMapList_free(LynxMaps);
     LynxMaps = NULL;
     return;
 }
 
+/*
+ *  We keep two kinds of lists:
+ *  - A global list (LynxMaps) shared by MAPs from all documents that
+ *    do not have POST data.
+ *  - For each response to a POST which contains MAPs, a list specific
+ *    to this combination of URL and post_data.  It is kept in the
+ *    HTParentAnchor structure and is freed when the document is removed
+ *    from memory, in the course of normal removal of anchors.
+ *    MAPs from POST responses can only be accessed via internal links,
+ *    i.e. from within the same document (with the same post_data).
+ *    The notion of "same document" is extended, so that LYNXIMGMAP:
+ *    and List Page screens are logically part of the document on which
+ *    they are based. - kw
+ *
+ *  If DONT_TRACK_INTERNAL_LINKS is defined, only the global list will
+ *  be used for all MAPs.
+ *
+ */
+
 /* 
- *  Utility for creating an LYImageMap list (LynxMaps), if it doesn't
+ *  Utility for creating an LYImageMap list, if it doesn't
  *  exist already, adding LYImageMap entry structures if needed, and
  *  removing any LYMapElements in a pre-existing LYImageMap entry so that
  *  it will have only those from AREA tags for the current analysis of
  *  MAP element content. - FM
  */
-PUBLIC BOOL LYAddImageMap ARGS2(
+PUBLIC BOOL LYAddImageMap ARGS3(
 	char *,		address,
-	char *,		title)
+	char *,		title,
+	HTParentAnchor *, node_anchor)
 {
     LYImageMap *new = NULL;
     LYImageMap *old = NULL;
     HTList *cur = NULL;
+    HTList *theList = NULL;
     HTList *curele = NULL;
     LYMapElement *ele = NULL;
 
     if (!(address && *address))
         return FALSE;
+    if (!(node_anchor && node_anchor->address))
+	return FALSE;
 
-    if (!LynxMaps) {
-        LynxMaps = HTList_new();
-	atexit(LYLynxMaps_free);
-    } else {
-        cur = LynxMaps;
+    /*
+     *  Set theList to either the global LynxMaps list or, if we
+     *  are associated with post data, the specific list.  The
+     *  list is created if it doesn't already exist. - kw
+     */
+#ifndef DONT_TRACK_INTERNAL_LINKS
+    if (node_anchor->post_data) {
+	/*
+	 *  We are handling a MAP element found while parsing
+	 *  node_anchor's stream of data, and node_anchor has
+	 *  post_data associated and should therefore represent
+	 *  a POST response, so use the specific list. - kw
+	 */
+	theList = node_anchor->imaps;
+	if (!theList) {
+	    theList = node_anchor->imaps = HTList_new();
+	}
+    } else
+#endif
+    {
+	if (!LynxMaps) {
+	    LynxMaps = HTList_new();
+	    atexit(LYLynxMaps_free);
+	}
+	theList = LynxMaps;
+    }
+
+    if (theList) {
+        cur = theList;
 	while (NULL != (old = (LYImageMap *)HTList_nextObject(cur))) {
 	    if (!strcmp(old->address, address)) {
 		FREE(old->address);
@@ -141,31 +198,59 @@ PUBLIC BOOL LYAddImageMap ARGS2(
     if (title && *title)
         StrAllocCopy(new->title, title);
     if (new != old)
-        HTList_addObject(LynxMaps, new);
+        HTList_addObject(theList, new);
     return TRUE;
 }
 
 /* 
  * Utility for adding LYMapElements to LYImageMaps
- * in the LynxMaps list. - FM
+ * in the appropriate list. - FM
  */
-PUBLIC BOOL LYAddMapElement ARGS4(
+PUBLIC BOOL LYAddMapElement ARGS5(
 	char *,		map,
 	char *,		address,
 	char *,		title,
+	HTParentAnchor *, node_anchor,
 	BOOL,		intern_flag)
 {
     LYMapElement *new = NULL;
     LYImageMap *theMap = NULL;
+    HTList *theList = NULL;
     HTList *cur = NULL;
 
     if (!(map && *map && address && *address))
         return FALSE;
+    if (!(node_anchor && node_anchor->address))
+	return FALSE;
 
-    if (!LynxMaps)
-        LYAddImageMap(map, NULL);
+    /*
+     *  Set theList to either the global LynxMaps list or, if we
+     *  are associated with post data, the specific list.  The
+     *  list should already exist, since this function is only called
+     *  if the AREA tag we are handling was within a MAP element
+     *  in node_anchor's stream of data, so that LYAddImageMap has
+     *  been called. - kw
+     */
+#ifndef DONT_TRACK_INTERNAL_LINKS
+    if (node_anchor->post_data) {
+	/*
+	 *  We are handling an AREA tag found while parsing
+	 *  node_anchor's stream of data, and node_anchor has
+	 *  post_data associated and should therefore represent
+	 *  a POST response, so use the specific list. - kw
+	 */
+	theList = node_anchor->imaps;
+	if (!theList)
+	    return FALSE;
+    } else
+#endif
+    {
+	if (!LynxMaps)
+	    LYAddImageMap(map, NULL, node_anchor);
+	theList = LynxMaps;
+    }
 
-    cur = LynxMaps;
+    cur = theList;
     while (NULL != (theMap = (LYImageMap *)HTList_nextObject(cur))) {
         if (!strcmp(theMap->address, map)) {
 	    break;
@@ -224,6 +309,82 @@ PUBLIC BOOL LYHaveImageMap ARGS1(
     return FALSE;
 }
 
+/*
+ *  Fills in a Doccaddress structure for getting the HTParentAnchor of
+ *  the underlying resource.  ALso returns a pointer to that anchor in
+ *  *punderlying if we are dealing with POST data. - kw
+ *
+ *  address  is the address of the underlying resource, i.e. the one
+ *           containing the MAP element, the MAP's name appended as
+ *	     fragment is ignored.
+ *  anAnchor is the LYNXIMGMAP: anchor; if it is associated with POST
+ *           data, we want the specific list, otherwise the global list.
+ */
+PRIVATE void fill_DocAddress ARGS4(
+    DocAddress *,	wwwdoc,
+    char *,		address,
+    HTParentAnchor *,	anAnchor,
+    HTParentAnchor **,	punderlying)
+{
+    HTParentAnchor * underlying;
+    if (anAnchor && anAnchor->post_data) {
+	wwwdoc->address = address;
+        wwwdoc->post_data = anAnchor->post_data;
+        wwwdoc->post_content_type = anAnchor->post_content_type;
+        wwwdoc->bookmark = NULL;
+	wwwdoc->isHEAD = FALSE;
+	wwwdoc->safe = FALSE;
+	underlying = HTAnchor_parent(HTAnchor_findAddress(wwwdoc));
+	if (underlying->safe)
+	    wwwdoc->safe = TRUE;
+	if (punderlying)
+	    *punderlying = underlying;
+    } else {
+	wwwdoc->address = address;
+        wwwdoc->post_data = NULL;
+        wwwdoc->post_content_type = NULL;
+        wwwdoc->bookmark = NULL;
+	wwwdoc->isHEAD = FALSE;
+	wwwdoc->safe = FALSE;
+	if (punderlying)
+	    *punderlying = NULL;
+    }
+}
+
+/*
+ *  Get the appropriate list for creating a LYNXIMGMAP: pseudo-
+ *  document: either the global list (LynxMaps), or the specific
+ *  list if a List Page for a POST response is requested.  Also
+ *  fill in the DocAddress structure etc. by calling fill_DocAddress().
+ *
+ *  address is the address of the underlying resource, i.e. the one
+ *          containing the MAP element, the MAP's name appended as
+ *	    fragment is ignored.
+ *  anchor  is the LYNXIMGMAP: anchor for which LYLoadIMGmap() is
+ *          requested; if it is associated with POST data, we want the
+ *	    specific list for this combination of address+post_data.
+ *
+ * if DONT_TRACK_INTERNAL_LINKS is defined, the Anchor passed to
+ * LYLoadIMGmap() will never have post_data, so that the global list
+ * will be used. - kw
+ */
+PRIVATE HTList * get_the_list ARGS4(
+    DocAddress *,	wwwdoc,
+    char *,		address,
+    HTParentAnchor *,	anchor,
+    HTParentAnchor **,	punderlying)
+{
+    if (anchor && anchor->post_data) {
+	fill_DocAddress(wwwdoc, address, anchor, punderlying);
+	if (punderlying && *punderlying)
+	    return (*punderlying)->imaps;
+	return anchor->imaps;
+    } else {
+	fill_DocAddress(wwwdoc, address, NULL, punderlying);
+	return LynxMaps;
+    }
+}
+
 /* 	LYLoadIMGmap - F.Macrides (macrides@sci.wfeb.edu)
 **	------------
 **  	Create a text/html stream with a list of links
@@ -243,10 +404,12 @@ PRIVATE int LYLoadIMGmap ARGS4 (
     LYImageMap *theMap = NULL;
     char *MapTitle = NULL;
     char *MapAddress = NULL;
+    HTList *theList;
     HTList *cur = NULL;
     char *address = NULL;
     char *cp = NULL;
     DocAddress WWWDoc;
+    HTParentAnchor * underlying;
     BOOL old_cache_setting = LYforce_no_cache;
     BOOL old_reloading = reloading;
     HTFormat old_format_out = HTOutputFormat;
@@ -259,13 +422,17 @@ PRIVATE int LYLoadIMGmap ARGS4 (
 	return(HT_NOT_LOADED);
     }
 
-    if (!LynxMaps) {
-	WWWDoc.address = address;
-        WWWDoc.post_data = NULL;
-        WWWDoc.post_content_type = NULL;
-        WWWDoc.bookmark = NULL;
-	WWWDoc.isHEAD = FALSE;
-	WWWDoc.safe = FALSE;
+    theList = get_the_list(&WWWDoc, address, anAnchor, &underlying);
+    if (WWWDoc.safe)
+	anAnchor->safe = TRUE;
+
+    if (!theList) {
+	if (anAnchor->post_data && !WWWDoc.safe &&
+	    ((underlying && underlying->document && !LYforce_no_cache) ||
+	     HTConfirm("LYNXIMGMAP: " CONFIRM_POST_RESUBMISSION) != TRUE)) {
+	    HTAlert("Image map from POST response not available!");
+	    return(HT_NOT_LOADED);
+	}
         LYforce_no_cache = TRUE;
 	reloading = TRUE;
 	HTOutputFormat = WWW_PRESENT;
@@ -282,26 +449,27 @@ PRIVATE int LYLoadIMGmap ARGS4 (
 	reloading = old_reloading;
 	HTOutputFormat = old_format_out;
 	LYMapsOnly = FALSE;
+	theList = get_the_list(&WWWDoc, address, anAnchor, &underlying);
     }
 
-    if (!LynxMaps) {
+    if (!theList) {
 	HTAlert(MAPS_NOT_AVAILABLE);
 	return(HT_NOT_LOADED);
     }
 
-    cur = LynxMaps;
+    cur = theList;
     while (NULL != (theMap = (LYImageMap *)HTList_nextObject(cur))) {
         if (!strcmp(theMap->address, address)) {
 	    break;
 	}
     }
     if (!(theMap && theMap->elements)) {
-	WWWDoc.address = address;
-        WWWDoc.post_data = NULL;
-        WWWDoc.post_content_type = NULL;
-        WWWDoc.bookmark = NULL;
-	WWWDoc.isHEAD = FALSE;
-	WWWDoc.safe = FALSE;
+	if (anAnchor->post_data && !WWWDoc.safe &&
+	    ((underlying && underlying->document && !LYforce_no_cache) ||
+	    HTConfirm("LYNXIMGMAP: " CONFIRM_POST_RESUBMISSION) != TRUE)) {
+	    HTAlert("Image map from POST response not available!");
+	    return(HT_NOT_LOADED);
+	}
         LYforce_no_cache = TRUE;
 	reloading = TRUE;
 	HTOutputFormat = WWW_PRESENT;
@@ -318,7 +486,7 @@ PRIVATE int LYLoadIMGmap ARGS4 (
 	reloading = old_reloading;
 	HTOutputFormat = old_format_out;
 	LYMapsOnly = FALSE;
-	cur = LynxMaps;
+	cur = get_the_list(&WWWDoc, address, anAnchor, &underlying);
 	while (NULL != (theMap = (LYImageMap *)HTList_nextObject(cur))) {
 	    if (!strcmp(theMap->address, address)) {
 		break;
@@ -330,7 +498,9 @@ PRIVATE int LYLoadIMGmap ARGS4 (
 	}
     }
 
+#ifdef DONT_TRACK_INTERNAL_LINKS
     anAnchor->no_cache = TRUE;
+#endif
 
     target = HTStreamStack(format_in, 
 			   format_out,
diff --git a/src/LYMap.h b/src/LYMap.h
index 48829eb7..a0ef6337 100644
--- a/src/LYMap.h
+++ b/src/LYMap.h
@@ -4,7 +4,11 @@
 
 extern BOOL LYMapsOnly;
 
-extern BOOL LYAddImageMap PARAMS((char *address, char *title));
-extern BOOL LYAddMapElement PARAMS((char *map, char *address, char *title, BOOL intern_flag));
+extern void ImageMapList_free PARAMS((HTList * list));
+extern BOOL LYAddImageMap PARAMS((char *address, char *title,
+				  HTParentAnchor *node_anchor));
+extern BOOL LYAddMapElement PARAMS((char *map, char *address, char *title,
+				    HTParentAnchor *node_anchor,
+				    BOOL intern_flag));
 
 #endif /* LYMAP_H */
diff --git a/src/LYOptions.c b/src/LYOptions.c
index 61f9e187..8eaa64a0 100644
--- a/src/LYOptions.c
+++ b/src/LYOptions.c
@@ -205,7 +205,10 @@ draw_options:
      *  might have non-ASCII or multibyte/CJK characters. - FM
      */
     response = 0;
-    clear();
+    if (enable_scrollback)
+	clear();
+    else
+	erase();
     move(0, 5);
 
     lynx_start_h1_color ();
@@ -1792,7 +1795,10 @@ draw_bookmark_list:
      *  to increase the chances that any non-ASCII or multibyte/CJK
      *  characters will be handled properly. - FM
      */
-    clear();
+    if (enable_scrollback)
+	clear();
+    else
+	erase();
     move(0, 5);
 
     lynx_start_h1_color ();
diff --git a/src/LYPrint.c b/src/LYPrint.c
index 5ded8fc1..b466ff74 100644
--- a/src/LYPrint.c
+++ b/src/LYPrint.c
@@ -16,16 +16,14 @@
 #include "LYHistory.h"
 #include "LYSystem.h"
 #include "LYList.h"
+#include "LYCharSets.h"  /* To get current charset for mail header. */
 #ifdef VMS
 #include "HTVMSUtils.h"
 #endif /* VMS */
 #ifdef DOSPATH
 #include "HTDOS.h"
 #endif
-#ifdef EXP_CHARTRANS
-#include "LYCharSets.h"  /* to get current charset for mail header */
 extern BOOLEAN LYHaveCJKCharacterSet;
-#endif
 
 #include "LYLeaks.h"
 
@@ -104,19 +102,23 @@ PUBLIC int printfile ARGS1(
     WWWDoc.safe = newdoc->safe;
     if (!HTLoadAbsolute(&WWWDoc))
         return(NOT_FOUND);
-  
+
+    /*
+     *  If we have an explicit content-base, we may use it even
+     *  if not in source mode. - kw
+     */
+    if (HText_getContentBase()) {
+	StrAllocCopy(content_base, HText_getContentBase());
+	collapse_spaces(content_base);
+	if (!(content_base && *content_base)) {
+	    FREE(content_base);
+	}
+    }
     /*
      *  If document is source, load the content_base
      *  and content_location strings. - FM
      */
     if (HTisDocumentSource()) {
-    	if (HText_getContentBase()) {
-	    StrAllocCopy(content_base, HText_getContentBase());
-	    collapse_spaces(content_base);
-	    if (!(content_base && *content_base)) {
-	        FREE(content_base);
-	    }
-	}
     	if (HText_getContentLocation()) {
 	    StrAllocCopy(content_location, HText_getContentLocation());
 	    collapse_spaces(content_location);
@@ -433,13 +435,16 @@ PUBLIC int printfile ARGS1(
 		    }
 		}
 
-                if ((outfile_fp = LYNewTxtFile(buffer)) == NULL) {
+                if ((outfile_fp = fopen(buffer,"w")) == NULL) {
 		    HTAlert(CANNOT_WRITE_TO_FILE);
 		    _statusline(NEW_FILENAME_PROMPT);
 		    FirstRecall = TRUE;
 		    FnameNum = FnameTotal;
 		    goto retry;
                 }
+#ifdef VMS
+		chmod(buffer, 0600);
+#endif
 
 		if (HTisDocumentSource()) {
 		    /*
@@ -611,7 +616,6 @@ PUBLIC int printfile ARGS1(
 		 *  if the document has 8-bit characters and we we seem
 		 *  to have a valid charset.  - kw
 		 */
-#ifdef EXP_CHARTRANS
 		use_cte = HTLoadedDocumentEightbit();
 		disp_charset = LYCharSet_UC[current_char_set].MIMEname;
 		/*
@@ -623,10 +627,12 @@ PUBLIC int printfile ARGS1(
 		    strncasecomp(disp_charset, "x-", 2) == 0) {
 		    disp_charset = NULL;
 		}
-#else
-		use_cte = NO;
-		disp_charset = NULL;
-#endif /* EXP_CHARTRANS */
+#ifdef NOTDEFINED
+		/*  Enable this if indicating an 8-bit transfer without
+                 *  also indicating the charset causes problems. - kw */
+		if (use_cte && !disp_charse)
+		    use_cte = FALSE;
+#endif /* NOTDEFINED */
 		use_type =  (disp_charset || HTisDocumentSource());
 		use_mime = (use_cte || use_type);
 
@@ -648,10 +654,6 @@ PUBLIC int printfile ARGS1(
 		    } else {
 		        fprintf(outfile_fp, "\n");
 		    }
-		    fprintf(outfile_fp, "Content-Base: %s\n",
-		    			content_base);
-		    fprintf(outfile_fp, "Content-Location: %s\n",
-		    			content_location);
 		} else {
 		    /*
 		     *  Add Content-Type: text/plain if we have 8-bit
@@ -665,6 +667,20 @@ PUBLIC int printfile ARGS1(
 		    }
 		}
 		/*
+		 *  If we are using MIME headers, add content-base and
+		 *  content-location if we have them.  This will always
+		 *  be the case if the document is source. - kw
+		 */
+		if (use_mime) {
+		    if (content_base)
+		        fprintf(outfile_fp, "Content-Base: %s\n",
+				content_base);
+		    if (content_location)
+			fprintf(outfile_fp, "Content-Location: %s\n",
+				content_location);
+		}
+
+		/*
 		 *  Add the To, Subject, and X-URL headers. - FM
 		 */
 		fprintf(outfile_fp, "To: %s\nSubject: %s\n",
diff --git a/src/LYStyle.c b/src/LYStyle.c
index 160eff5f..a596214e 100644
--- a/src/LYStyle.c
+++ b/src/LYStyle.c
@@ -237,6 +237,10 @@ where OBJECT is one of EM,STRONG,B,I,U,BLINK etc.\n\n", buffer);
  {
 	parse_attributes(mono,fg,bg,DSTYLE_HIGH,"high");
  }
+ else if (!strcmp(element, "normal")) /* added - kw */
+ {
+	parse_attributes(mono,fg,bg,DSTYLE_NORMAL,"html");
+ }
  /* this may vanish */
  else if (!strncasecmp(element, "candy", 5)) /* [INLINE]'s */
  {
diff --git a/src/LYUtils.c b/src/LYUtils.c
index a39042f3..47a2fca1 100644
--- a/src/LYUtils.c
+++ b/src/LYUtils.c
@@ -1897,11 +1897,18 @@ PUBLIC void statusline ARGS1(
 		int a=(strncmp(buffer, "Alert", 5) || !hashStyles[s_alert].name ? s_status : s_alert);
 		LynxChangeStyle (a, ABS_ON, 1);
 		addstr(buffer);
-		wbkgdset(stdscr, (lynx_has_color
-			? hashStyles[a].color
-			: hashStyles[a].mono) | ' ');
+		wbkgdset(stdscr,
+			 ((lynx_has_color && LYShowColor >= SHOW_COLOR_ON)
+			  ? hashStyles[a].color
+			  :A_NORMAL) | ' ');
 		clrtoeol();
-		wbkgdset(stdscr, hashStyles[s_normal].color | ' ');
+		if (s_normal != NOSTYLE)
+		    wbkgdset(stdscr, hashStyles[s_normal].color | ' ');
+		else
+		    wbkgdset(stdscr,
+			     ((lynx_has_color && LYShowColor >= SHOW_COLOR_ON)
+			      ? displayStyles[DSTYLE_NORMAL].color
+			      : A_NORMAL) | ' ');
 		LynxChangeStyle (a, ABS_OFF, 0);
 	}
 #endif
@@ -2697,6 +2704,47 @@ PUBLIC int is_url ARGS1(
 }
 
 /*
+ *  Determine whether we allow HEAD and related flags for a URL. - kw
+ */
+PUBLIC BOOLEAN LYCanDoHEAD ARGS1(
+    CONST char *,	address
+    )
+{
+    char *temp0 = NULL;
+    int isurl;
+    if (!(address && *address))
+	return FALSE;
+    if (!strncmp(address, "http", 4))
+	return TRUE;
+    /* Make copy for is_url() since caller may not care for case changes */
+    StrAllocCopy(temp0, address);
+    isurl = is_url(temp0);
+    FREE(temp0);
+    if (!isurl)
+	return FALSE;
+    if (isurl == LYNXCGI_URL_TYPE) {
+#if defined(LYNXCGI_LINKS) && !defined(VMS)
+	return TRUE;
+#else
+	return FALSE;
+#endif
+    }
+    if (isurl == NEWS_URL_TYPE || isurl == NNTP_URL_TYPE) {
+	char *temp = HTParse(address, "", PARSE_PATH);
+	char *cp = strrchr(temp, '/');
+	if (strchr((cp ? cp : temp), '@') != NULL) {
+	    FREE(temp);
+	    return TRUE;
+	}
+	if (cp && isdigit(cp[1]) && strchr(cp, '-') == NULL) {
+	    FREE(temp);
+	    return TRUE;
+	}
+	FREE(temp);
+    }
+    return FALSE;
+}
+/*
  *  Remove backslashes from any string.
  */
 PUBLIC void remove_backslashes ARGS1(
@@ -5530,3 +5578,29 @@ PUBLIC FILE *LYAppendToTxtFile ARGS1(char *, name)
 #endif
     return fp;
 }
+
+#ifdef UNIX
+/*
+ *  Restore normal permisions to a copy of a file that we have created
+ *  with temp file restricted permissions.  The normal umask should
+ *  apply for user files. - kw
+ */
+PUBLIC void LYRelaxFilePermissions ARGS1(CONST char *, name)
+{
+    int mode;
+    struct stat stat_buf;
+    if (stat(name, &stat_buf) == 0 &&
+	S_ISREG(stat_buf.st_mode) &&
+	(mode = (stat_buf.st_mode & 0777)) == HIDE_CHMOD) {
+	/*
+	 *  It looks plausible that this is a file we created with
+	 *  temp file paranoid permissions (and the umask wasn't even
+	 *  more restrictive when it was copied). - kw
+	 */
+	int save = umask(HIDE_UMASK);
+	mode = ((mode & 0700) | 0066) & ~save;
+	umask(save);
+	chmod(name, mode);
+    }
+}
+#endif
diff --git a/src/LYUtils.h b/src/LYUtils.h
index 7af31349..9b8a8b35 100644
--- a/src/LYUtils.h
+++ b/src/LYUtils.h
@@ -25,6 +25,7 @@ extern void LYAddLocalhostAlias PARAMS((char *alias));
 extern BOOLEAN LYisLocalAlias PARAMS((char *filename));
 extern int LYCheckForProxyURL PARAMS((char *filename));
 extern int is_url PARAMS((char *filename));
+extern BOOLEAN LYCanDoHEAD PARAMS((CONST char *address));
 extern void remove_backslashes PARAMS((char *buf));
 extern char *quote_pathname PARAMS((char *pathname));
 extern BOOLEAN inlocaldomain NOPARAMS;
@@ -61,7 +62,9 @@ extern int putenv PARAMS((CONST char *string));
 FILE *LYNewBinFile PARAMS((char * name));
 FILE *LYNewTxtFile PARAMS((char * name));
 FILE *LYAppendToTxtFile PARAMS((char * name));
-
+#ifdef UNIX
+extern void LYRelaxFilePermissions PARAMS((CONST char * name));
+#endif
 /*
  *  Whether or not the status line must be shown.
  */
diff --git a/src/LYexit.c b/src/LYexit.c
index 625c05e3..74ce16c3 100644
--- a/src/LYexit.c
+++ b/src/LYexit.c
@@ -107,6 +107,7 @@ PUBLIC void LYexit ARGS1(
 #endif /* exit */
 
 #ifndef VMS	/*  On VMS, the VMSexit() handler does these. - FM */
+    fflush(stderr);
     if (LYOutOfMemory == TRUE) {
 	LYOutOfMemory = FALSE;
 	printf("\r\n%s\r\n\r\n", MEMORY_EXHAUSTED_ABORT);
diff --git a/src/chrtrans/README.format b/src/chrtrans/README.format
index 58f0b1cc..0ec556a2 100644
--- a/src/chrtrans/README.format
+++ b/src/chrtrans/README.format
@@ -96,11 +96,14 @@ d) string replacement definitions:
  * Syntax accepted:
  *      <unicode>	:<replace>
  *      <unicode range>	:<replace>
+ *      <unicode>	"<C replace>"
+ *      <unicode range>	"<C replace>"
  *
  * where <unicode range> ::= <unicode>-<unicode>
  * and <unicode> ::= U+<h><h><h><h>
  * and <h> ::= <hexadecimal digit>
- * and <replace> any string not containing '\n' or '\0'
+ * and <replace> any string not containing '\n' or '\0', taken verbatim
+ * and <C replace> any string, with backslash having the usual C meaning
 
 Motivation:
 
diff --git a/src/chrtrans/cp437_uni.tbl b/src/chrtrans/cp437_uni.tbl
index ed97a69c..6bfbab22 100644
--- a/src/chrtrans/cp437_uni.tbl
+++ b/src/chrtrans/cp437_uni.tbl
@@ -1,7 +1,5 @@
 #Shall this become the "default" translation?
-#Meaning of that is currently unclear...  It's different
-#from the default input or defualt output charset...
-#but there has to be exactly one table marked as "default".
+#There has to be exactly one table marked as "default".
 D0
 #
 #The MIME name of this charset. 
@@ -287,7 +285,7 @@ OIBM PC character set
 0xff	U+00a0	#NO-BREAK SPACE
 
 U+03ac:a'
-U+03ad:î'
+U+03ad "\356'"	#:î'
 U+03ae:h'
 U+03af:i'
 U+03cc:o'
diff --git a/src/chrtrans/iso01_uni.tbl b/src/chrtrans/iso01_uni.tbl
index 14f71ff3..d2147771 100644
--- a/src/chrtrans/iso01_uni.tbl
+++ b/src/chrtrans/iso01_uni.tbl
@@ -21,7 +21,7 @@ OISO Latin 1
 0x63	U+0063 U+0107 U+0109 U+010B U+010D
 0x64-0x7e	idem
 0xa0-0xff	idem
-#0x00	U+fffd   # don't let failed char lookups return '\0'
+#0x00	U+fffd   # don't let failed char lookups return 0
 # Mappings of C0 control chars from original, disabled
 #0x01	U+263A
 #0x02	U+263B
@@ -75,4 +75,4 @@ U+2122:(TM)
 0x27    U+2019-U+201b   # various single quotation marks
 0x22    U+201c-U+201f   # various double quotation marks
 
-U+2297:(×)
\ No newline at end of file
+U+2297 "(\327)"
\ No newline at end of file
diff --git a/src/chrtrans/iso01_uni.tbl.orig b/src/chrtrans/iso01_uni.tbl.orig
new file mode 100644
index 00000000..14f71ff3
--- /dev/null
+++ b/src/chrtrans/iso01_uni.tbl.orig
@@ -0,0 +1,78 @@
+#
+# Unicode mapping table for ISO 8859-1 fonts iso01.*
+# [use: unicode_start iso01.f16 iso01]
+#
+#Shall this become the "default" translation?
+#Meaning of that is currently not well defined.  It is different
+#from the default input or default output charset...
+#but there has to be exactly one table marked as "default".
+D0
+#
+#The MIME name of this charset. 
+Miso-8859-1
+
+#Name as a Display Charset (used on Options screen)
+OISO Latin 1
+
+0x20	U+0020  U+1360 
+0x21-0x62	idem
+# The following line is an example for mapping several accented versions
+# of small letter 'c' to 'c':
+0x63	U+0063 U+0107 U+0109 U+010B U+010D
+0x64-0x7e	idem
+0xa0-0xff	idem
+#0x00	U+fffd   # don't let failed char lookups return '\0'
+# Mappings of C0 control chars from original, disabled
+#0x01	U+263A
+#0x02	U+263B
+#0x03	U+2665
+#0x04	U+2666
+#0x05	U+2663
+#0x06	U+2660
+#0x07	U+2022
+#0x08	U+25D8
+#0x09	U+25CB
+#0x0A	U+25D9
+#0x0B	U+2642
+#0x0C	U+2640
+#0x0D	U+266A
+#0x0E	U+266B
+#0x0E	U+266C
+#0x0F	U+263C
+#0x10	U+25B6
+#0x10	U+25BA
+#0x11	U+25C0
+#0x11	U+25C4
+#0x12	U+2195
+#0x13	U+203C
+#0x14	U+00B6
+#0x15	U+00A7
+#0x16	U+25AC
+#0x17	U+21A8
+#0x18	U+2191
+#0x19	U+2193
+#0x1A	U+2192
+#0x1B	U+2190
+#0x1C	U+221F
+#0x1C	U+2319
+#0x1D	U+2194
+#0x1E	U+25B2
+#0x1F	U+25BC
+#0x7f		U+2302
+
+0xd0	U+0110	# Dstrok and ETH are nearly the same...
+
+# Dont wanna see these:
+# POP DIRECTIONAL FORMATTING      202C
+U+202c:
+# LEFT-TO-RIGHT OVERRIDE  202D
+U+202d:
+
+# TRADE MARK SIGN:
+U+2122:(TM)
+
+0x60    U+2018          # left single quotation mark
+0x27    U+2019-U+201b   # various single quotation marks
+0x22    U+201c-U+201f   # various double quotation marks
+
+U+2297:(×)
\ No newline at end of file
diff --git a/src/chrtrans/iso08_uni.tbl b/src/chrtrans/iso08_uni.tbl
index f11dff4a..d1c33b1d 100644
--- a/src/chrtrans/iso08_uni.tbl
+++ b/src/chrtrans/iso08_uni.tbl
@@ -89,12 +89,12 @@ OISO 8859-8 Hebrew
 #Hebrew points - map to empty string
 U+05B0-U+05C2:
 
-#HEBREW LETTER DOUBLE VAV
-U+05F0:åå
-#HEBREW LETTER VAV YOD
-U+05F1:éå
-#HEBREW LETTER DOUBLE YOD
-U+05F2:éé
+#HEBREW LETTER DOUBLE VAV	#U+05F0:åå
+U+05F0 "\345\345"
+#HEBREW LETTER VAV YOD		#U+05F1:éå
+U+05F1 "\351\345"
+#HEBREW LETTER DOUBLE YOD	#U+05F2:éé
+U+05F2 "\351\351"
 
 
 # TRADE MARK SIGN:
diff --git a/src/chrtrans/makeuctb.c b/src/chrtrans/makeuctb.c
index e0630cc3..ad95c534 100644
--- a/src/chrtrans/makeuctb.c
+++ b/src/chrtrans/makeuctb.c
@@ -256,7 +256,8 @@ PUBLIC int main ARGS2(
 	if ((p = strchr(buffer, '\n')) != NULL) {
 	    *p = '\0';
 	} else {
-	    fprintf(stderr, "%s: Warning: line too long\n", tblname);
+	    fprintf(stderr, "%s: Warning: line too long or incomplete\n",
+		    tblname);
 	}
 
 	/*
@@ -268,11 +269,14 @@ PUBLIC int main ARGS2(
 	 *	<range>		<unicode range>
 	 *      <unicode>	:<replace>
 	 *      <unicode range>	:<replace>
+	 *      <unicode>	"<C replace>"
+	 *      <unicode range>	"<C replace>"
 	 *
 	 *  where <range> ::= <fontpos>-<fontpos>
 	 *  and <unicode> ::= U+<h><h><h><h>
 	 *  and <h> ::= <hexadecimal digit>
 	 *  and <replace> any string not containing '\n' or '\0'
+	 *  and <C replace> any string with C backslash escapes 
 	 */
 	p = buffer;
 	while (*p == ' ' || *p == '\t') {
@@ -405,24 +409,51 @@ PUBLIC int main ARGS2(
 		    p++;
 		}
 	    }
-	    if (*p != ':') {
-		fprintf(stderr, "No ':' where expected: %s\n", buffer);
+
+	    if (*p != ':' && *p != '"') {
+		fprintf(stderr, "No ':' or '\"' where expected: %s\n",
+			buffer);
 		continue;
 	    }
 
-	    tbuf = (char *) malloc (4*strlen(++p) + 1);
+	    tbuf = (char *) malloc (4*strlen(p));
 	    if (!(p1 = tbuf)) {
 		fprintf(stderr, "%s: Out of memory\n", tblname);
 		exit(EX_DATAERR);
 	    }
-	    for (ch = *p; (ch = *p) != '\0'; p++, p1++) {
-		if ((unsigned char)ch < 32 || ch == '\\' || ch == '\"' ||
-		    (unsigned char)ch >= 127) {
-		    sprintf(p1, "\\%.3o", (unsigned char)ch); 
+	    if (*p == '"') {
+		/*
+		 *  handle "<C replace>"
+		 *  Copy chars verbatim until first '"' not \-escaped or
+		 *  end of buffer
+		 */
+		int escaped = 0;
+		for (ch = *++p; (ch = *p) != '\0'; p++) {
+		    if (escaped) {
+			escaped = 0;
+		    } else if (ch == '"') {
+			break;
+		    } else if (ch == '\\') {
+			escaped = 1;
+		    }
+		    *p1++ = ch;
+		}
+		if (escaped || ch != '"') {
+		    fprintf(stderr, "Warning: String not terminated: %s\n",
+			    buffer);
+		    if (escaped)
+			*p1++ = '\n';
+		}
+	    } else {		/* we had ':' */
+		for (ch = *++p; (ch = *p) != '\0'; p++, p1++) {
+		    if ((unsigned char)ch < 32 || ch == '\\' || ch == '\"' ||
+			(unsigned char)ch >= 127) {
+			sprintf(p1, "\\%.3o", (unsigned char)ch); 
 /*		    fprintf(stderr, "%s\n", tbuf); */
-		    p1 += 3;
-		} else {
-		    *p1 = ch;
+			p1 += 3;
+		    } else {
+			*p1 = ch;
+		    }
 		}
 	    }
 	    *p1 = '\0';
diff --git a/src/chrtrans/viscii_uni.tbl b/src/chrtrans/viscii_uni.tbl
index 006fa0ea..33677163 100644
--- a/src/chrtrans/viscii_uni.tbl
+++ b/src/chrtrans/viscii_uni.tbl
@@ -210,7 +210,7 @@ U+001a:^Z
 0x86	U+1ea8
 0xa6	U+1ea9
 0x06	U+1eaa
-U+1eaa:Â~
+U+1eaa "\302~"  # A with circumflex (same code as in iso-8859-1) and tilde
 0xe7	U+1eab
 0x87	U+1eac
 0xa7	U+1ead