about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorThomas E. Dickey <dickey@invisible-island.net>1999-06-29 13:01:29 -0400
committerThomas E. Dickey <dickey@invisible-island.net>1999-06-29 13:01:29 -0400
commit83824f14360f92f8a3a47ac5f136bb077b141065 (patch)
tree9b21f7145d93e54ad67f57e8807f20493dfcbc3d /src
parent5be99e2ee1a17028574fcbd90b9ba2c09555585e (diff)
downloadlynx-snapshots-83824f14360f92f8a3a47ac5f136bb077b141065.tar.gz
snapshot of project "lynx", label v2-8-3_3
Diffstat (limited to 'src')
-rw-r--r--src/HTAlert.c39
-rw-r--r--src/HTInit.c4
-rw-r--r--src/HTML.c278
-rw-r--r--src/LYCharSets.c2
-rw-r--r--src/LYCharUtils.c24
-rw-r--r--src/LYCharUtils.h3
-rw-r--r--src/LYCookie.c301
-rw-r--r--src/LYCookie.h15
-rw-r--r--src/LYCurses.h4
-rw-r--r--src/LYDownload.c18
-rw-r--r--src/LYGetFile.c2
-rw-r--r--src/LYGlobalDefs.h1
-rw-r--r--src/LYHistory.c52
-rw-r--r--src/LYKeymap.c2
-rw-r--r--src/LYLeaks.c3
-rw-r--r--src/LYLocal.c408
-rw-r--r--src/LYLocal.h5
-rw-r--r--src/LYMail.c2
-rw-r--r--src/LYMain.c2
-rw-r--r--src/LYMainLoop.c14
-rw-r--r--src/LYOptions.c36
-rw-r--r--src/LYPrint.c13
-rw-r--r--src/LYReadCFG.c1
-rw-r--r--src/LYShowInfo.c11
-rw-r--r--src/LYStrings.c5
-rw-r--r--src/LYUtils.c165
-rw-r--r--src/LYUtils.h3
27 files changed, 999 insertions, 414 deletions
diff --git a/src/HTAlert.c b/src/HTAlert.c
index 4889f719..29abf7c1 100644
--- a/src/HTAlert.c
+++ b/src/HTAlert.c
@@ -48,12 +48,14 @@ PUBLIC void HTAlwaysAlert ARGS2(
 		    "%s %s!\n",
 		    extra_prefix, Msg);
 	    fflush(stdout);
+	    LYstore_message2(ALERT_FORMAT, Msg);
 	    sleep(AlertSecs);
 	} else {
 	    fprintf(((TRACE) ? stdout : stderr),
 		    ALERT_FORMAT,
 		    (Msg == 0) ? "" : Msg);
 	    fflush(stdout);
+	    LYstore_message2(ALERT_FORMAT, Msg);
 	    sleep(AlertSecs);
 	    fprintf(((TRACE) ? stdout : stderr), "\n");
 	}
@@ -211,6 +213,12 @@ PUBLIC BOOL HTConfirmDefault ARGS2(CONST char *, Msg, int, Dft)
 
     conf_cancelled = NO;
     if (dump_output_immediately) { /* Non-interactive, can't respond */
+	if (Dft == DFT_CONFIRM) {
+	    CTRACE(tfp, "Confirm: %s (%c/%c) ", Msg, *msg_yes, *msg_no);
+	} else {
+	    CTRACE(tfp, "Confirm: %s (%c) ", Msg, (Dft == YES) ? *msg_yes : *msg_no);
+	}
+	CTRACE(tfp, "- NO, not interactive.\n");
 	result = NO;
     } else {
 	char *msg = NULL;
@@ -219,6 +227,9 @@ PUBLIC BOOL HTConfirmDefault ARGS2(CONST char *, Msg, int, Dft)
 	    HTSprintf0(&msg, "%s (%c/%c) ", Msg, *msg_yes, *msg_no);
 	else
 	    HTSprintf0(&msg, "%s (%c) ", Msg, (Dft == YES) ? *msg_yes : *msg_no);
+	if (LYTraceLogFP) {
+	    CTRACE(tfp, "Confirm: %s", msg);
+	}
 	_statusline(msg);
 	FREE(msg);
 
@@ -236,11 +247,15 @@ PUBLIC BOOL HTConfirmDefault ARGS2(CONST char *, Msg, int, Dft)
 	    } else if (TOUPPER(c) == TOUPPER(*msg_yes)) {
 		result = YES;
 	    } else if (TOUPPER(c) == TOUPPER(*msg_no)) {
-		return(NO);
+		result = NO;
 	    } else if (Dft != DFT_CONFIRM) {
-		return(Dft);
+		result = Dft;
+		break;
 	    }
 	}
+	CTRACE(tfp, "- %s%s.\n",
+	       (result != NO) ? "YES" : "NO",
+	       conf_cancelled ? ", cancelled" : "");
     }
     return (result);
 }
@@ -478,17 +493,16 @@ PUBLIC BOOL HTConfirmCookie ARGS4(
     if ((de = (domain_entry *)dp) == NULL)
 	return FALSE;
 
-#ifdef ENHANCED_COOKIES
     /*	If the user has specified a list of domains to allow or deny
     **	from the config file, then they'll already have de->bv set to
     **	ACCEPT_ALWAYS or REJECT_ALWAYS so we can relax and let the
-    **	default cookie handling code cope with this fine.  I hope.
+    **	default cookie handling code cope with this fine.
     */
-#endif
+
     /*
     **	If the user has specified a constant action, don't prompt at all.
     */
-    if (de->bv == ACCEPT_ALWAYS || de->bv == FROM_FILE)
+    if (de->bv == ACCEPT_ALWAYS)
 	return TRUE;
     if (de->bv == REJECT_ALWAYS)
 	return FALSE;
@@ -505,19 +519,14 @@ PUBLIC BOOL HTConfirmCookie ARGS4(
     /*
     **	Estimate how much of the cookie we can show.
     */
-    if (de != NULL) {
-	if (de->bv == ACCEPT_ALWAYS)
-	    return TRUE;
-	if (de->bv == REJECT_ALWAYS)
-	    return FALSE;
-    }
     if(!LYAcceptAllCookies) {
 	int namelen, valuelen, space_free, percentage;
 	char *message = 0;
 
-	space_free = (((LYcols - 1)
-		   - strlen(ADVANCED_COOKIE_CONFIRMATION))
-		   - strlen(server));
+	space_free = ((LYcols - 1)
+		      - (strlen(ADVANCED_COOKIE_CONFIRMATION)
+			 - 10)		/* %s and %.*s and %.*s chars */
+		      - strlen(server));
 	if (space_free < 0)
 	    space_free = 0;
 	namelen = strlen(name);
diff --git a/src/HTInit.c b/src/HTInit.c
index d65298d7..b5f39fb7 100644
--- a/src/HTInit.c
+++ b/src/HTInit.c
@@ -530,7 +530,9 @@ PRIVATE int PassesTest ARGS1(
     /*
      *  Save overhead of system() calls by faking these. - FM
      */
-    if (0 == strcasecomp(mc->testcommand, "test -n \"$DISPLAY\"")) {
+    if (0 == strcmp(mc->testcommand, "test \"$DISPLAY\"") ||
+	0 == strcmp(mc->testcommand, "test \"$DISPLAY\" != \"\"") ||
+	0 == strcasecomp(mc->testcommand, "test -n \"$DISPLAY\"")) {
 	FREE(mc->testcommand);
 	CTRACE(tfp, "PassesTest: Testing for XWINDOWS environment.\n");
     	if (LYgetXDisplay() != NULL) {
diff --git a/src/HTML.c b/src/HTML.c
index 36143414..4849b24b 100644
--- a/src/HTML.c
+++ b/src/HTML.c
@@ -1720,11 +1720,33 @@ PRIVATE void HTML_start_element ARGS6(
 		"HTML: ****** Maximum nesting of %d divisions exceeded!\n",
 		MAX_NESTING);
 	}
+	if (me->inP)
+	    LYEnsureSingleSpace(me); /* always at least break line - kw */
 	if (ElementNumber == HTML_CENTER) {
 	    me->DivisionAlignments[me->Division_Level] = HT_CENTER;
 	    change_paragraph_style(me, styles[HTML_DCENTER]);
 	    UPDATE_STYLE;
 	    me->current_default_alignment = styles[HTML_DCENTER]->alignment;
+	} else if (me->List_Nesting_Level >= 0 &&
+		   !(present && present[HTML_DIV_ALIGN] &&
+		     value[HTML_DIV_ALIGN] &&
+		     (!strcasecomp(value[HTML_DIV_ALIGN], "center") ||
+		      !strcasecomp(value[HTML_DIV_ALIGN], "right")))) {
+	    if (present && present[HTML_DIV_ALIGN])
+		me->current_default_alignment = HT_LEFT;
+	    else if (me->Division_Level == 0)
+		me->current_default_alignment = HT_LEFT;
+	    else if (me->sp[0].tag_number == HTML_UL ||
+		     me->sp[0].tag_number == HTML_OL ||
+		     me->sp[0].tag_number == HTML_MENU ||
+		     me->sp[0].tag_number == HTML_DIR ||
+		     me->sp[0].tag_number == HTML_LI ||
+		     me->sp[0].tag_number == HTML_LH ||
+		     me->sp[0].tag_number == HTML_DD)
+		me->current_default_alignment = HT_LEFT;
+	    LYHandlePlike(me, present, value, include, HTML_DIV_ALIGN, TRUE);
+	    me->DivisionAlignments[me->Division_Level] =
+		me->current_default_alignment;
 	} else if (present && present[HTML_DIV_ALIGN] &&
 		   value[HTML_DIV_ALIGN] && *value[HTML_DIV_ALIGN]) {
 	    if (!strcasecomp(value[HTML_DIV_ALIGN], "center")) {
@@ -1779,7 +1801,8 @@ PRIVATE void HTML_start_element ARGS6(
 	    (me->sp[0].tag_number == HTML_UL ||
 	     me->sp[0].tag_number == HTML_OL ||
 	     me->sp[0].tag_number == HTML_MENU ||
-	     me->sp[0].tag_number == HTML_DIR)) {
+	     me->sp[0].tag_number == HTML_DIR ||
+	     me->sp[0].tag_number == HTML_LI)) {
 	    if (HTML_dtd.tags[HTML_LH].contents == SGML_EMPTY) {
 		ElementNumber = HTML_LH;
 	    } else {
@@ -1844,7 +1867,8 @@ PRIVATE void HTML_start_element ARGS6(
 	break;
 
     case HTML_P:
-	LYHandleP(me, present, value, include, TRUE);
+	LYHandlePlike(me, present, value, include, HTML_P_ALIGN, TRUE);
+	CHECK_ID(HTML_P_ID);
 	break;
 
     case HTML_BR:
@@ -2525,97 +2549,107 @@ PRIVATE void HTML_start_element ARGS6(
 	HText_appendParagraph(me->text);
 	me->sp->style->alignment = HT_LEFT;
 	CHECK_ID(HTML_LI_ID);
-	if (me->sp[0].tag_number == HTML_OL) {
-	    char number_string[20];
-	    int counter, seqnum;
-	    char seqtype;
-
-	    counter = me->List_Nesting_Level < 11 ?
-			   me->List_Nesting_Level : 11;
-	    if (present && present[HTML_LI_TYPE] && value[HTML_LI_TYPE]) {
-		if (*value[HTML_LI_TYPE] == '1') {
-		    me->OL_Type[counter] = '1';
-		} else if (*value[HTML_LI_TYPE] == 'A') {
-		    me->OL_Type[counter] = 'A';
-		} else if (*value[HTML_LI_TYPE] == 'a') {
-		    me->OL_Type[counter] = 'a';
-		} else if (*value[HTML_LI_TYPE] == 'I') {
-		    me->OL_Type[counter] = 'I';
-		} else if (*value[HTML_LI_TYPE] == 'i') {
-		    me->OL_Type[counter] = 'i';
+	{
+	    int surrounding_tag_number = me->sp[0].tag_number;
+	    /*
+	     *  No, a LI should never occur directly within another LI,
+	     *  but this may result from incomplete error recovery.
+	     *  So check one more surrounding level in this case. - kw
+	     */
+	    if (surrounding_tag_number == HTML_LI &&
+		me->sp < (me->stack + MAX_NESTING - 1))
+		surrounding_tag_number = me->sp[1].tag_number;
+	    if (surrounding_tag_number == HTML_OL) {
+		char number_string[20];
+		int counter, seqnum;
+		char seqtype;
+
+		counter = me->List_Nesting_Level < 11 ?
+		    me->List_Nesting_Level : 11;
+		if (present && present[HTML_LI_TYPE] && value[HTML_LI_TYPE]) {
+		    if (*value[HTML_LI_TYPE] == '1') {
+			me->OL_Type[counter] = '1';
+		    } else if (*value[HTML_LI_TYPE] == 'A') {
+			me->OL_Type[counter] = 'A';
+		    } else if (*value[HTML_LI_TYPE] == 'a') {
+			me->OL_Type[counter] = 'a';
+		    } else if (*value[HTML_LI_TYPE] == 'I') {
+			me->OL_Type[counter] = 'I';
+		    } else if (*value[HTML_LI_TYPE] == 'i') {
+			me->OL_Type[counter] = 'i';
+		    }
 		}
-	    }
-	    if (present && present[HTML_LI_VALUE] &&
-		((value[HTML_LI_VALUE] != NULL) &&
-		 (*value[HTML_LI_VALUE] != '\0')) &&
-		((isdigit(*value[HTML_LI_VALUE])) ||
-		 (*value[HTML_LI_VALUE] == '-' &&
-		  isdigit(*(value[HTML_LI_VALUE] + 1))))) {
-		seqnum = atoi(value[HTML_LI_VALUE]);
-		if (seqnum <= OL_VOID)
-		    seqnum = OL_VOID + 1;
-		seqtype = me->OL_Type[counter];
-		if (seqtype != '1' && seqnum < 1)
-		    seqnum = 1;
-		me->OL_Counter[counter] = seqnum + 1;
-	    } else if (me->OL_Counter[counter] >= OL_VOID) {
-		seqnum = me->OL_Counter[counter]++;
-		seqtype = me->OL_Type[counter];
-		if (seqtype != '1' && seqnum < 1) {
-		    seqnum = 1;
+		if (present && present[HTML_LI_VALUE] &&
+		    ((value[HTML_LI_VALUE] != NULL) &&
+		     (*value[HTML_LI_VALUE] != '\0')) &&
+		    ((isdigit(*value[HTML_LI_VALUE])) ||
+		     (*value[HTML_LI_VALUE] == '-' &&
+		      isdigit(*(value[HTML_LI_VALUE] + 1))))) {
+		    seqnum = atoi(value[HTML_LI_VALUE]);
+		    if (seqnum <= OL_VOID)
+			seqnum = OL_VOID + 1;
+		    seqtype = me->OL_Type[counter];
+		    if (seqtype != '1' && seqnum < 1)
+			seqnum = 1;
 		    me->OL_Counter[counter] = seqnum + 1;
-		}
-	    } else {
-		seqnum = me->Last_OL_Count + 1;
-		seqtype = me->Last_OL_Type;
-		for (i = (counter - 1); i >= 0; i--) {
-		    if (me->OL_Counter[i] > OL_VOID) {
-			seqnum = me->OL_Counter[i]++;
-			seqtype = me->OL_Type[i];
-			i = 0;
+		} else if (me->OL_Counter[counter] >= OL_VOID) {
+		    seqnum = me->OL_Counter[counter]++;
+		    seqtype = me->OL_Type[counter];
+		    if (seqtype != '1' && seqnum < 1) {
+			seqnum = 1;
+			me->OL_Counter[counter] = seqnum + 1;
+		    }
+		} else {
+		    seqnum = me->Last_OL_Count + 1;
+		    seqtype = me->Last_OL_Type;
+		    for (i = (counter - 1); i >= 0; i--) {
+			if (me->OL_Counter[i] > OL_VOID) {
+			    seqnum = me->OL_Counter[i]++;
+			    seqtype = me->OL_Type[i];
+			    i = 0;
+			}
 		    }
 		}
-	    }
-	    if (seqtype == 'A') {
-		sprintf(number_string, LYUppercaseA_OL_String(seqnum));
-	    } else if (seqtype == 'a') {
-		sprintf(number_string, LYLowercaseA_OL_String(seqnum));
-	    } else if (seqtype == 'I') {
-		sprintf(number_string, LYUppercaseI_OL_String(seqnum));
-	    } else if (seqtype == 'i') {
-		sprintf(number_string, LYLowercaseI_OL_String(seqnum));
-	    } else {
-		sprintf(number_string, "%2d.", seqnum);
-	    }
-	    me->Last_OL_Count = seqnum;
-	    me->Last_OL_Type = seqtype;
-	    /*
-	     *	Hack, because there is no append string!
-	     */
-	    for (i = 0; number_string[i] != '\0'; i++)
-		if (number_string[i] == ' ')
-		    HTML_put_character(me, HT_NON_BREAK_SPACE);
-		else
-		    HTML_put_character(me, number_string[i]);
+		if (seqtype == 'A') {
+		    sprintf(number_string, LYUppercaseA_OL_String(seqnum));
+		} else if (seqtype == 'a') {
+		    sprintf(number_string, LYLowercaseA_OL_String(seqnum));
+		} else if (seqtype == 'I') {
+		    sprintf(number_string, LYUppercaseI_OL_String(seqnum));
+		} else if (seqtype == 'i') {
+		    sprintf(number_string, LYLowercaseI_OL_String(seqnum));
+		} else {
+		    sprintf(number_string, "%2d.", seqnum);
+		}
+		me->Last_OL_Count = seqnum;
+		me->Last_OL_Type = seqtype;
+		/*
+		 *	Hack, because there is no append string!
+		 */
+		for (i = 0; number_string[i] != '\0'; i++)
+		    if (number_string[i] == ' ')
+			HTML_put_character(me, HT_NON_BREAK_SPACE);
+		    else
+			HTML_put_character(me, number_string[i]);
 
-	    /*
-	     *	Use HTML_put_character so that any other spaces
-	     *	coming through will be collapsed.  We'll use
-	     *	nbsp, so it won't break at the spacing character
-	     *	if there are no spaces in the subsequent text up
-	     *	to the right margin, but will declare it as a
-	     *	normal space to ensure collapsing if a normal
-	     *	space does immediately follow it. - FM
-	     */
-	    HTML_put_character(me, HT_NON_BREAK_SPACE);
-	    HText_setLastChar(me->text, ' ');
-	} else if (me->sp[0].tag_number == HTML_UL) {
-	    /*
-	     *	Hack, because there is no append string!
-	     */
-	    HTML_put_character(me, HT_NON_BREAK_SPACE);
-	    HTML_put_character(me, HT_NON_BREAK_SPACE);
-	    switch(me->List_Nesting_Level % 7) {
+		/*
+		 *	Use HTML_put_character so that any other spaces
+		 *	coming through will be collapsed.  We'll use
+		 *	nbsp, so it won't break at the spacing character
+		 *	if there are no spaces in the subsequent text up
+		 *	to the right margin, but will declare it as a
+		 *	normal space to ensure collapsing if a normal
+		 *	space does immediately follow it. - FM
+		 */
+		HTML_put_character(me, HT_NON_BREAK_SPACE);
+		HText_setLastChar(me->text, ' ');
+	    } else if (surrounding_tag_number == HTML_UL) {
+		/*
+		 *	Hack, because there is no append string!
+		 */
+		HTML_put_character(me, HT_NON_BREAK_SPACE);
+		HTML_put_character(me, HT_NON_BREAK_SPACE);
+		switch(me->List_Nesting_Level % 7) {
 		case 0:
 		    HTML_put_character(me, '*');
 		    break;
@@ -2638,25 +2672,26 @@ PRIVATE void HTML_start_element ARGS6(
 		    HTML_put_character(me, '=');
 		    break;
 
+		}
+		/*
+		 *	Keep using HTML_put_character so that any other
+		 *	spaces coming through will be collapsed.  We use
+		 *	nbsp, so we won't wrap at the spacing character
+		 *	if there are no spaces in the subsequent text up
+		 *	to the right margin, but will declare it as a
+		 *	normal space to ensure collapsing if a normal
+		 *	space does immediately follow it. - FM
+		 */
+		HTML_put_character(me, HT_NON_BREAK_SPACE);
+		HText_setLastChar(me->text, ' ');
+	    } else {
+		/*
+		 *	Hack, because there is no append string!
+		 */
+		HTML_put_character(me, HT_NON_BREAK_SPACE);
+		HTML_put_character(me, HT_NON_BREAK_SPACE);
+		HText_setLastChar(me->text, ' ');
 	    }
-	    /*
-	     *	Keep using HTML_put_character so that any other
-	     *	spaces coming through will be collapsed.  We use
-	     *	nbsp, so we won't wrap at the spacing character
-	     *	if there are no spaces in the subsequent text up
-	     *	to the right margin, but will declare it as a
-	     *	normal space to ensure collapsing if a normal
-	     *	space does immediately follow it. - FM
-	     */
-	    HTML_put_character(me, HT_NON_BREAK_SPACE);
-	    HText_setLastChar(me->text, ' ');
-	} else {
-	    /*
-	     *	Hack, because there is no append string!
-	     */
-	    HTML_put_character(me, HT_NON_BREAK_SPACE);
-	    HTML_put_character(me, HT_NON_BREAK_SPACE);
-	    HText_setLastChar(me->text, ' ');
 	}
 	me->in_word = NO;
 	me->inP = FALSE;
@@ -4628,7 +4663,7 @@ PRIVATE void HTML_start_element ARGS6(
 			HText_appendCharacter(me->text,
 					      LY_UNDERLINE_END_CHAR);
 		    }
-#else 
+#else
 		    CTRACE(tfp, "Attempting to fake as: %s\n", I.type);
 #endif /* EXP_FILE_UPLOAD */
 #ifdef NOTDEFINED
@@ -5696,7 +5731,8 @@ PRIVATE void HTML_end_element ARGS3(
 	    (me->sp[0].tag_number == HTML_UL ||
 	     me->sp[0].tag_number == HTML_OL ||
 	     me->sp[0].tag_number == HTML_MENU ||
-	     me->sp[0].tag_number == HTML_DIR) &&
+	     me->sp[0].tag_number == HTML_DIR ||
+	     me->sp[0].tag_number == HTML_LI) &&
 	    (element_number == HTML_H1 ||
 	     element_number == HTML_H2 ||
 	     element_number == HTML_H3 ||
@@ -5742,7 +5778,8 @@ PRIVATE void HTML_end_element ARGS3(
 	    (me->sp[0].tag_number == HTML_UL ||
 	     me->sp[0].tag_number == HTML_OL ||
 	     me->sp[0].tag_number == HTML_MENU ||
-	     me->sp[0].tag_number == HTML_DIR) &&
+	     me->sp[0].tag_number == HTML_DIR ||
+	     me->sp[0].tag_number == HTML_LI) &&
 	    (element_number == HTML_H1 ||
 	     element_number == HTML_H2 ||
 	     element_number == HTML_H3 ||
@@ -5944,14 +5981,23 @@ PRIVATE void HTML_end_element ARGS3(
     case HTML_DIV:
 	if (me->Division_Level >= 0)
 	    me->Division_Level--;
-	if (me->Division_Level >= 0)
-	    me->sp->style->alignment =
+	if (me->Division_Level >= 0) {
+	    if (me->sp->style->alignment !=
+		me->DivisionAlignments[me->Division_Level]) {
+		if (me->inP)
+		    LYEnsureSingleSpace(me);
+		me->sp->style->alignment =
 				me->DivisionAlignments[me->Division_Level];
+	    }
+	}
 	change_paragraph_style(me, me->sp->style);
-	UPDATE_STYLE;
+	if (me->style_change) {
+	    actually_set_style(me);
+	    if (me->List_Nesting_Level >= 0)
+		HText_NegateLineOne(me->text);
+	} else if (me->inP)
+	    LYEnsureSingleSpace(me);
 	me->current_default_alignment = me->sp->style->alignment;
-	if (me->List_Nesting_Level >= 0)
-	    HText_NegateLineOne(me->text);
 	break;
 
     case HTML_H1:			/* header styles */
@@ -5988,9 +6034,9 @@ PRIVATE void HTML_end_element ARGS3(
 	break;
 
     case HTML_P:
-	LYHandleP(me,
+	LYHandlePlike(me,
 		 (CONST BOOL*)0, (CONST char **)0,
-		 include,
+		 include, 0,
 		 FALSE);
 	break;
 
diff --git a/src/LYCharSets.c b/src/LYCharSets.c
index e58cc37e..8890f9df 100644
--- a/src/LYCharSets.c
+++ b/src/LYCharSets.c
@@ -21,7 +21,7 @@ extern HTCJKlang HTCJK;
 PUBLIC HTkcode kanji_code = NOKANJI;
 PUBLIC BOOLEAN LYHaveCJKCharacterSet = FALSE;
 PUBLIC BOOLEAN DisplayCharsetMatchLocale = TRUE;
-PUBLIC BOOL force_old_UCLYhndl_on_reload;
+PUBLIC BOOL force_old_UCLYhndl_on_reload = FALSE;
 PUBLIC int forced_UCLYhdnl;
 extern void UCInit NOARGS;
 extern int UCInitialized;
diff --git a/src/LYCharUtils.c b/src/LYCharUtils.c
index 717409ce..5e15c2a2 100644
--- a/src/LYCharUtils.c
+++ b/src/LYCharUtils.c
@@ -133,8 +133,8 @@ PUBLIC void LYEntify ARGS2(
 	    *q++ = *p;
 	}
     }
-    StrAllocCopy(*str, cp);
-    FREE(cp);
+    FREE(*str);
+    *str = cp;
 }
 
 /*
@@ -367,7 +367,8 @@ PUBLIC void LYFillLocalFileURL ARGS2(
 	char curdir[LY_MAXPATH];
 	temp2 = wwwName(Current_Dir(curdir));
 #endif /* VMS */
-	LYAddHtmlSep(href);
+	if (!LYIsHtmlSep(*temp2))
+	    LYAddHtmlSep(href);
 	/*
 	 *  Check for pathological cases - current dir has chars which
 	 *  MUST BE URL-escaped - kw
@@ -3084,11 +3085,12 @@ free_META_copies:
 **  current paragraph and subsequent text when a P
 **  end tag is present or not in the markup. - FM
 */
-PUBLIC void LYHandleP ARGS5(
+PUBLIC void LYHandlePlike ARGS6(
 	HTStructured *, 	me,
 	CONST BOOL*,		present,
 	CONST char **,		value,
 	char **,		include GCC_UNUSED,
+	int,			align_idx,
 	BOOL,			start)
 {
     if (TRUE) {
@@ -3151,7 +3153,8 @@ PUBLIC void LYHandleP ARGS5(
 
 	if (LYoverride_default_alignment(me)) {
 	    me->sp->style->alignment = LYstyles(me->sp[0].tag_number)->alignment;
-	} else if (me->List_Nesting_Level >= 0 ||
+	} else if ((me->List_Nesting_Level >= 0 &&
+		    strncmp(me->sp->style->name, "Div", 3)) ||
 		   ((me->Division_Level < 0) &&
 		    (!strcmp(me->sp->style->name, "Normal") ||
 		     !strcmp(me->sp->style->name, "Preformatted")))) {
@@ -3161,19 +3164,18 @@ PUBLIC void LYHandleP ARGS5(
 	}
 
 	if (start) {
-	    if (present && present[HTML_P_ALIGN] && value[HTML_P_ALIGN]) {
-		if (!strcasecomp(value[HTML_P_ALIGN], "center") &&
+	    if (present && present[align_idx] && value[align_idx]) {
+		if (!strcasecomp(value[align_idx], "center") &&
 		    !(me->List_Nesting_Level >= 0 && !me->inP))
 		    me->sp->style->alignment = HT_CENTER;
-		else if (!strcasecomp(value[HTML_P_ALIGN], "right") &&
+		else if (!strcasecomp(value[align_idx], "right") &&
 		    !(me->List_Nesting_Level >= 0 && !me->inP))
 		    me->sp->style->alignment = HT_RIGHT;
-		else if (!strcasecomp(value[HTML_P_ALIGN], "left") ||
-			 !strcasecomp(value[HTML_P_ALIGN], "justify"))
+		else if (!strcasecomp(value[align_idx], "left") ||
+			 !strcasecomp(value[align_idx], "justify"))
 		    me->sp->style->alignment = HT_LEFT;
 	    }
 
-	    CHECK_ID(HTML_P_ID);
 	}
 
 	/*
diff --git a/src/LYCharUtils.h b/src/LYCharUtils.h
index dc5a6c7f..d518d3ae 100644
--- a/src/LYCharUtils.h
+++ b/src/LYCharUtils.h
@@ -63,11 +63,12 @@ extern void LYHandleMETA PARAMS((
 	CONST BOOL*		present,
 	CONST char **		value,
 	char ** 		include));
-extern void LYHandleP PARAMS((
+extern void LYHandlePlike PARAMS((
 	HTStructured *		me,
 	CONST BOOL*		present,
 	CONST char **		value,
 	char ** 		include,
+	int			align_idx,
 	BOOL			start));
 extern void LYHandleSELECT PARAMS((
 	HTStructured *		me,
diff --git a/src/LYCookie.c b/src/LYCookie.c
index bd0bab72..e93b27f2 100644
--- a/src/LYCookie.c
+++ b/src/LYCookie.c
@@ -74,6 +74,9 @@
 #define max_cookies_global 500
 #define max_cookies_buffer 4096
 
+/* default for new domains, one of the invcheck_behaviour_t values: */
+#define DEFAULT_INVCHECK_BV INVCHECK_QUERY
+
 /*
 **  The first level of the cookie list is a list indexed by the domain
 **  string; cookies with the same domain will be placed in the same
@@ -271,6 +274,9 @@ PRIVATE void store_cookie ARGS3(
     CONST char *ptr;
     domain_entry *de = NULL;
     BOOL Replacement = FALSE;
+    int invprompt_reasons = 0;	/* what is wrong with this cookie - kw */
+#define FAILS_COND1 0x01
+#define FAILS_COND4 0x02
 
     if (co == NULL)
 	return;
@@ -294,7 +300,7 @@ PRIVATE void store_cookie ARGS3(
     for (hl = domain_list; hl != NULL; hl = hl->next) {
 	de = (domain_entry *)hl->object;
 	if ((de != NULL && de->domain != NULL) &&
-	    !strcmp(co->domain, de->domain)) {
+	    !strcasecomp(co->domain, de->domain)) {
 		cookie_list = de->cookie_list;
 		break;
 	}
@@ -316,32 +322,21 @@ PRIVATE void store_cookie ARGS3(
      * if set to INVCHECK_QUERY.
      */
     if (strncmp(co->path, path, co->pathlen) != 0) {
-	if((de != NULL && de->invcheck_bv != INVCHECK_LOOSE)
-	    || de == NULL) {
-		if(de != NULL && de->invcheck_bv == INVCHECK_STRICT) {
-		    CTRACE(tfp, "store_cookie: Rejecting because '%s' is not a prefix of '%s'.\n",
-			co->path, path);
-		    freeCookie(co);
-		    co = NULL;
-		    return;
-		} else if ((de != NULL
-		    && de->invcheck_bv == INVCHECK_QUERY)
-		    || de == NULL) {
-			char *msg = 0;
-			HTSprintf0(&msg,
-			    INVALID_COOKIE_PATH_CONFIRMATION,
-			    co->path, path);
-			if (!HTConfirm(msg)) {
-			    CTRACE(tfp, "store_cookie: Rejecting because '%s' is not a prefix of '%s'.\n",
-				co->path, path);
-			    freeCookie(co);
-			    co = NULL;
-			    FREE(msg);
-			    return;
-			} else {
-			    FREE(msg);
-			}
-		}
+	invcheck_behaviour_t invcheck_bv = (de ? de->invcheck_bv
+	    				       : DEFAULT_INVCHECK_BV);
+	switch (invcheck_bv) {
+	case INVCHECK_LOOSE:
+	    break;		/* continue as if nothing were wrong */
+
+	case INVCHECK_QUERY:
+	    invprompt_reasons |= FAILS_COND1;
+	    break;		/* will prompt later if we get that far */
+
+	case INVCHECK_STRICT:
+	    CTRACE(tfp, "store_cookie: Rejecting because '%s' is not a prefix of '%s'.\n",
+		   co->path, path);
+	    freeCookie(co);
+	    return;
 	}
     }
     /*
@@ -356,7 +351,6 @@ PRIVATE void store_cookie ARGS3(
 	    CTRACE(tfp, "store_cookie: Rejecting because '%s' has no dot.\n",
 		    hostname);
 	    freeCookie(co);
-	    co = NULL;
 	    return;
 	}
 
@@ -371,7 +365,6 @@ PRIVATE void store_cookie ARGS3(
 	    CTRACE(tfp, "store_cookie: Rejecting domain '%s'.\n",
 		    co->domain);
 	    freeCookie(co);
-	    co = NULL;
 	    return;
 	}
 	ptr = strchr((co->domain + 1), '.');
@@ -379,7 +372,6 @@ PRIVATE void store_cookie ARGS3(
 	    CTRACE(tfp, "store_cookie: Rejecting domain '%s'.\n",
 		    co->domain);
 	    freeCookie(co);
-	    co = NULL;
 	    return;
 	}
 
@@ -391,7 +383,6 @@ PRIVATE void store_cookie ARGS3(
 	    CTRACE(tfp, "store_cookie: Rejecting domain '%s' for host '%s'.\n",
 		    co->domain, hostname);
 	    freeCookie(co);
-	    co = NULL;
 	    return;
 	}
 
@@ -406,36 +397,61 @@ PRIVATE void store_cookie ARGS3(
 	 */
 	ptr = ((hostname + strlen(hostname)) - strlen(co->domain));
 	if (strchr(hostname, '.') < ptr) {
-		if((de != NULL && de->invcheck_bv != INVCHECK_LOOSE)
-		    || de == NULL) {
-			if(de != NULL && de->invcheck_bv == INVCHECK_STRICT) {
-			    CTRACE(tfp, "store_cookie: Rejecting domain '%s' for host '%s'.\n",
-				co->domain,
-				hostname);
-			    freeCookie(co);
-			    co = NULL;
-			    return;
-			} else if ((de != NULL
-			    && de->invcheck_bv == INVCHECK_QUERY)
-			    || de == NULL) {
-				char *msg = 0;
-				HTSprintf0(&msg,
-				    INVALID_COOKIE_DOMAIN_CONFIRMATION,
-				    co->domain,
-				    hostname);
-				if (!HTConfirm(msg)) {
-				    CTRACE(tfp, "store_cookie: Rejecting domain '%s' for host '%s'.\n",
+	    invcheck_behaviour_t invcheck_bv = (de ? de->invcheck_bv
+						   : DEFAULT_INVCHECK_BV);
+	    switch (invcheck_bv) {
+	    case INVCHECK_LOOSE:
+		break;		/* continue as if nothing were wrong */
+
+	    case INVCHECK_QUERY:
+		invprompt_reasons |= FAILS_COND4;
+		break;		/* will prompt later if we get that far */
+
+	    case INVCHECK_STRICT:
+		CTRACE(tfp, "store_cookie: Rejecting because '%s' is not a prefix of '%s'.\n",
+		       co->path, path);
+		freeCookie(co);
+		return;
+	    }
+	}
+    }
+
+    /*
+     *  If we found reasons for issuing an invalid cookie confirmation
+     *  prompt, do that now.  Rejection by the user here is the last
+     *  chance to completely ignore this cookie; after it passes this
+     *  hurdle, it may at least supersede a previous cookie (even if
+     *  it finally gets rejected). - kw
+     */
+    if (invprompt_reasons) {
+	char *msg = 0;
+	if (invprompt_reasons & FAILS_COND4) {
+	    HTSprintf0(&msg,
+		       INVALID_COOKIE_DOMAIN_CONFIRMATION,
+		       co->domain,
+		       hostname);
+	    if (!HTConfirmDefault(msg, NO)) {
+		CTRACE(tfp, "store_cookie: Rejecting domain '%s' for host '%s'.\n",
 					co->domain,
 					hostname);
-				    freeCookie(co);
-				    co = NULL;
-				    FREE(msg);
-				    return;
-				}
-				FREE(msg);
-			}
-		}
+		freeCookie(co);
+		FREE(msg);
+		return;
+	    }
+	}
+	if (invprompt_reasons & FAILS_COND1) {
+	    HTSprintf0(&msg,
+		       INVALID_COOKIE_PATH_CONFIRMATION,
+		       co->path, path);
+	    if (!HTConfirmDefault(msg, NO)) {
+		CTRACE(tfp, "store_cookie: Rejecting because '%s' is not a prefix of '%s'.\n",
+		       co->path, path);
+		freeCookie(co);
+		FREE(msg);
+		return;
+	    }
 	}
+	FREE(msg);
     }
 
     if (hl == NULL) {
@@ -447,21 +463,20 @@ PRIVATE void store_cookie ARGS3(
 	    outofmem(__FILE__, "store_cookie");
 #if 0	/* was: ifdef EXP_PERSISTENT_COOKIES */
 	/*
-	 * Ok, this is a problem.  The first cookie for a domain
-	 * effectively sets the policy for that whole domain - for
-	 * something like Netlink, where there are lots of websites
-	 * under www.netlink.co.uk, this isn't sensible.  However,
-	 * taking this sort of decision down to cookie level also
-	 * isn't sensible.  Perhaps something based on the domain
-	 * and the path in conjunction makes more sense?  - RP
+	 * The default behavior for this new domain could be set
+	 * differently if the cookie comes from a file, as the
+	 * code had it originally, but there doesn't seem to be
+	 * a good reason for it any more; setting more permissive
+	 * behavior for individual domains is now possible via
+	 * configuration options. - kw
 	 */
 	if (persistent_cookies
 	 && (co->flags & COOKIE_FLAG_FROM_FILE))
-	    de->bv = FROM_FILE;
+	    de->bv = ACCEPT_ALWAYS; /* ?? */
 	else
 #endif
 	    de->bv = QUERY_USER;
-	de->invcheck_bv = INVCHECK_QUERY; /* should this go here? */
+	de->invcheck_bv = DEFAULT_INVCHECK_BV; /* should this go here? */
 	cookie_list = de->cookie_list = HTList_new();
 	StrAllocCopy(de->domain, co->domain);
 	HTList_appendObject(domain_list, de);
@@ -490,7 +505,7 @@ PRIVATE void store_cookie ARGS3(
 	 *  Check if this cookie matches the one we're inserting.
 	 */
 	} else if ((c2) &&
-		   !strcmp(co->domain, c2->domain) &&
+		   !strcasecomp(co->domain, c2->domain) &&
 		   !strcmp(co->path, c2->path) &&
 		   !strcmp(co->name, c2->name)) {
 	    HTList_removeObject(cookie_list, c2);
@@ -547,7 +562,12 @@ PRIVATE void store_cookie ARGS3(
     /*
      * Don't add the cookie if the value is NULL. - BJP
      */
-    } else if (co->value[0] == '\0') {
+	/*
+	 * Presence of value is now needed (indicated normally by '='),
+	 * but it can now be an empty string.
+	 * - kw 1999-06-24
+	 */
+    } else if (co->value == NULL) { /* should not happen - kw */
 	CTRACE(tfp, "store_cookie: Value is NULL! Not storing cookie.\n");
 	freeCookie(co);
 	co = NULL;
@@ -940,16 +960,27 @@ PRIVATE void LYProcessSetCookies ARGS6(
 		    break;
 		}
 	    } else if (*p == '"') {
+		BOOLEAN escaped = FALSE;
 		/*
-		 *  It's a quoted string.
+		 *  It looks like quoted string.
 		 */
 		p++;
 		value_start = p;
-		while (*p != '\0' && *p != '"')
+		while (*p != '\0' && (*p != '"' || escaped)) {
+		    escaped = (!escaped && *p == '\\');
 		    p++;
-		value_end = p;
-		if (*p == '"')
+		}
+		if (p != value_start && *p == '"' && !escaped) {
+		    value_end = p;
 		    p++;
+		    Quoted = TRUE;
+		} else {
+		    value_start--;
+		    value_end = p;
+		    if (*p)
+			p++;
+		    Quoted = FALSE;
+		}
 	    } else {
 		/*
 		 *  Otherwise, it's an unquoted string.
@@ -987,7 +1018,12 @@ PRIVATE void LYProcessSetCookies ARGS6(
 	    BOOLEAN known_attr = NO;
 	    char *value = NULL;
 
-	    if (value_end > value_start) {
+	    if (value_start && value_end >= value_start) {
+		/*
+		 * Presence of value is now needed (indicated normally by '=')
+		 * to start a cookie, but it can now be an empty string.
+		 * - kw 1999-06-24
+		 */
 		int value_len = (value_end - value_start);
 
 		if (value_len > max_cookies_buffer) {
@@ -1218,8 +1254,11 @@ PRIVATE void LYProcessSetCookies ARGS6(
 	     * no value?  This seems to be needed for sites that reset a
 	     * cookie by nulling out the value.  If this causes problems,
 	     * we can go back to the original behavior above.  - BJP
+	     *
+	     * Presence of value is now needed (indicated normally by '='),
+	     * but it can now be an empty string. - kw 1999-06-24
 	     */
-	    if (!known_attr) {
+	    if (!known_attr && value && value_end >= value_start) {
 		/*
 		 *  If we've started a cookie, and it's not too big,
 		 *  save it in the CombinedCookies list. - FM
@@ -1441,17 +1480,27 @@ PRIVATE void LYProcessSetCookies ARGS6(
 		    break;
 		}
 	    } else if (*p == '"') {
+		BOOLEAN escaped = FALSE;
 		/*
-		 *  It's a quoted string.
+		 *  It looks like quoted string.
 		 */
 		p++;
 		value_start = p;
-		while (*p != '\0' && *p != '"')
+		while (*p != '\0' && (*p != '"' || escaped)) {
+		    escaped = (!escaped && *p == '\\');
 		    p++;
-		value_end = p;
-		if (*p == '"')
+		}
+		if (p != value_start && *p == '"' && !escaped) {
+		    value_end = p;
 		    p++;
-		Quoted = TRUE;
+		    Quoted = TRUE;
+		} else {
+		    value_start--;
+		    value_end = p;
+		    if (*p)
+			p++;
+		    Quoted = FALSE;
+		}
 	    } else {
 		/*
 		 *  Otherwise, it's an unquoted string.
@@ -1489,7 +1538,12 @@ PRIVATE void LYProcessSetCookies ARGS6(
 	    BOOLEAN known_attr = NO;
 	    char *value = NULL;
 
-	    if (value_end > value_start) {
+	    if (value_start && value_end >= value_start) {
+		/*
+		 * Presence of value is now needed (indicated normally by '=')
+		 * to start a cookie, but it can now be an empty string.
+		 * - kw 1999-06-24
+		 */
 		int value_len = (value_end - value_start);
 
 		if (value_len > max_cookies_buffer) {
@@ -1497,7 +1551,7 @@ PRIVATE void LYProcessSetCookies ARGS6(
 		}
 		value = (char *)calloc(1, value_len + 1);
 		if (value == NULL)
-		    outofmem(__FILE__, "LYProcessSetCookie");
+		    outofmem(__FILE__, "LYProcessSetCookies");
 		LYstrncpy(value, value_start, value_len);
 	    }
 	    if (len == 6 && !strncasecomp(attr_start, "secure", 6)) {
@@ -1705,8 +1759,11 @@ PRIVATE void LYProcessSetCookies ARGS6(
 	     * no value?  This seems to be needed for sites that reset a
 	     * cookie by nulling out the value.  If this causes problems,
 	     * we can go back to the original behavior above.  - BJP
+	     *
+	     * Presence of value is now needed (indicated normally by '='),
+	     * but it can now be an empty string. - kw 1999-06-24
 	     */
-	    if (!known_attr) {
+	    if (!known_attr && value && value_end >= value_start) {
 		/*
 		 *  If we've started a cookie, and it's not too big,
 		 *  save it in the CombinedCookies list. - FM
@@ -1924,7 +1981,7 @@ PUBLIC char * LYCookie ARGS4(
 		 */
 		header = scan_cookie_sublist(hostname, path, port,
 					     de->cookie_list, header, secure);
-	    } else if (de->bv == QUERY_USER && de->invcheck_bv == INVCHECK_QUERY) {
+	    } else if (de->bv == QUERY_USER && de->invcheck_bv == DEFAULT_INVCHECK_BV) {
 		/*
 		 *  No cookies in this domain, and no default
 		 *  accept/reject choice was set by the user,
@@ -1998,7 +2055,10 @@ PUBLIC void LYLoadCookies ARGS1 (
 	while(buf[i] != '\n' && buf[i] != 0) {
 	    i++;
 	}
-	buf[i] = '\0';
+	if (buf[i] == '\n') {
+	    buf[i++] = '\t';	/* add sep after line if enough space - kw */
+	    buf[i] = '\0';
+	}
 
 	/*
 	 * Tokenise the cookie line into its component parts -
@@ -2010,6 +2070,12 @@ PUBLIC void LYLoadCookies ARGS1 (
 	 * 'fixed' by using strsep instead of strtok.  No idea
 	 * what kind of platform problems this might introduce. - RP
 	 */
+	/*
+	 * This fails when the path is blank
+	 *
+	 * sscanf(buf, "%s\t%s\t%s\t%s\t%d\t%s\t%[ -~]",
+	 *  domain, what, path, secure, &expires, name, value);
+	 */
 	CTRACE(tfp, "LYLoadCookies: tokenising %s\n", buf);
 	tok_ptr = buf;
 	tok_out = LYstrsep(&tok_ptr, "\t");
@@ -2025,15 +2091,14 @@ PUBLIC void LYLoadCookies ARGS1 (
 	     */
 	    tok_out = LYstrsep(&tok_ptr, "\t");
 	}
-	expires = atol(expires_a);
 
-	/*
-	 * This fails when the path is blank
-	 *
-	 * sscanf(buf, "%s\t%s\t%s\t%s\t%d\t%s\t%[ -~]",
-	 *  domain, what, path, secure, &expires, name, value);
-	 */
+	if (tok_values[tok_loop].s) {
+	    /* tok_out in above loop must have been NULL prematurely - kw */
+	    CTRACE(tfp, "*** wrong format: not enough tokens, ignoring line!\n");
+	    continue;
+	}
 
+	expires = atol(expires_a);
 	CTRACE(tfp, "expires:\t%s\n", ctime(&expires));
 /* 	CTRACE(tfp, "%s\t%s\t%s\t%s\t%ld\t%s\t%s\tREADCOOKIE\n", */
 /* 	    domain, what, path, secure, (long) expires, name, value); */
@@ -2041,7 +2106,15 @@ PUBLIC void LYLoadCookies ARGS1 (
 	StrAllocCopy(moo->domain, domain);
 	StrAllocCopy(moo->path, path);
 	StrAllocCopy(moo->name, name);
-	StrAllocCopy(moo->value, value);
+	if (value && value[0] == '"' &&
+	    value[1] && value[strlen(value)-1] == '"' &&
+	    value[strlen(value)-2] != '\\') {
+	    value[strlen(value)-1] = '\0';
+	    StrAllocCopy(moo->value, value+1);
+	    moo->quoted = TRUE;
+	} else {
+	    StrAllocCopy(moo->value, value);
+	}
 	moo->pathlen = strlen(moo->path);
 	/*
 	 *  Justification for following flags:
@@ -2171,11 +2244,15 @@ PUBLIC void LYStoreCookies ARGS1 (
 		continue;
 	    }
 
-	    fprintf(cookie_handle, "%s\t%s\t%s\t%s\t%ld\t%s\t%s\n",
+	    fprintf(cookie_handle, "%s\t%s\t%s\t%s\t%ld\t%s\t%s%s%s\n",
 		de->domain,
-		"FALSE", co->path,
+		    (de->domain[0] == '.') ? "TRUE" : "FALSE",
+		    co->path,
 		co->flags & COOKIE_FLAG_SECURE ? "TRUE" : "FALSE",
-		(long) co->expires, co->name, co->value);
+		(long) co->expires, co->name,
+		    (co->quoted ? "\"" : ""),
+		    co->value,
+		    (co->quoted ? "\"" : ""));
 
 	    CTRACE(tfp, "STORED\n");
 	}
@@ -2264,7 +2341,7 @@ PRIVATE int LYHandleCookies ARGS4 (
 		 *  First object in the list always is empty. - FM
 		 */
 		continue;
-	    if (!strcmp(domain, de->domain)) {
+	    if (!strcasecomp(domain, de->domain)) {
 		FREE(domain);
 		/*
 		 *  We found the domain.  Check
@@ -2527,11 +2604,6 @@ Delete_all_cookies_in_domain:
 	    case (QUERY_USER):
 		HTSprintf0(&buf, COOKIES_ALLOWED_VIA_PROMPT);
 		break;
-	    case (FROM_FILE):
-#if 0 /* not used any more - kw */
-		HTSprintf0(&buf, COOKIES_READ_FROM_FILE);
-#endif
-		break;
 	}
 	PUTS(buf);
 	HTSprintf0(&buf, "\n");
@@ -2673,8 +2745,11 @@ PUBLIC void cookie_domain_flag_set ARGS2(
     char *strsmall = NULL;
     int isexisting = FALSE;
 
-    if (str == NULL)
-	outofmem(__FILE__, "cookie_set_invcheck");
+    if (str == NULL) {
+	HTAlwaysAlert(gettext("Internal"),
+		      gettext("cookie_domain_flag_set error, aborting program"));
+	exit_immediately(-1);
+    }
 
     /*
      * Is this the first domain we're handling?  If so, initialize
@@ -2695,6 +2770,11 @@ PUBLIC void cookie_domain_flag_set ARGS2(
 
     while ((strsmall = LYstrsep(str, ",")) != 0) {
 
+	if (*strsmall == '\0')
+	    /* Never add a domain for empty string.  It would actually
+	     * make more sense to use strtok here. - kw */
+	    continue;
+
 	/*
 	 * Check the list of existing domains to see if this is a
 	 * re-setting of an already existing domains -- if so, just
@@ -2704,7 +2784,7 @@ PUBLIC void cookie_domain_flag_set ARGS2(
 	for (hl = domain_list; hl != NULL; hl = hl->next) {
 	    de2 = (domain_entry *)hl->object;
 	    if ((de2 != NULL && de2->domain != NULL) &&
-		!strcmp(strsmall, de2->domain)) {
+		!strcasecomp(strsmall, de2->domain)) {
 			isexisting = TRUE;
 			break;
 	    } else {
@@ -2720,16 +2800,13 @@ PUBLIC void cookie_domain_flag_set ARGS2(
 
 	    switch(flag) {
 		case (FLAG_ACCEPT_ALWAYS): de->bv = ACCEPT_ALWAYS;
-					   de->invcheck_bv = INVCHECK_QUERY;
+					   de->invcheck_bv = DEFAULT_INVCHECK_BV;
 					   break;
 		case (FLAG_REJECT_ALWAYS): de->bv = REJECT_ALWAYS;
-					   de->invcheck_bv = INVCHECK_QUERY;
+					   de->invcheck_bv = DEFAULT_INVCHECK_BV;
 					   break;
 		case (FLAG_QUERY_USER):    de->bv = QUERY_USER;
-					   de->invcheck_bv = INVCHECK_QUERY;
-					   break;
-		case (FLAG_FROM_FILE):     de->bv = FROM_FILE;
-					   de->invcheck_bv = INVCHECK_QUERY;
+					   de->invcheck_bv = DEFAULT_INVCHECK_BV;
 					   break;
 		case (FLAG_INVCHECK_QUERY): de->invcheck_bv = INVCHECK_QUERY;
 					    de->bv = QUERY_USER;
@@ -2753,8 +2830,6 @@ PUBLIC void cookie_domain_flag_set ARGS2(
 					   break;
 		case (FLAG_QUERY_USER): de2->bv = QUERY_USER;
 					   break;
-		case (FLAG_FROM_FILE): de2->bv = FROM_FILE;
-					   break;
 		case (FLAG_INVCHECK_QUERY): de2->invcheck_bv = INVCHECK_QUERY;
 					   break;
 		case (FLAG_INVCHECK_STRICT): de2->invcheck_bv = INVCHECK_STRICT;
diff --git a/src/LYCookie.h b/src/LYCookie.h
index b811e371..5e599191 100644
--- a/src/LYCookie.h
+++ b/src/LYCookie.h
@@ -7,10 +7,10 @@
 
 #include <HTList.h>
 
-typedef enum {ACCEPT_ALWAYS, REJECT_ALWAYS, QUERY_USER, FROM_FILE} behaviour;
+typedef enum {ACCEPT_ALWAYS, REJECT_ALWAYS, QUERY_USER} behaviour_t;
 typedef enum {INVCHECK_QUERY,
 	      INVCHECK_STRICT,
-	      INVCHECK_LOOSE} invcheck_behaviour;
+	      INVCHECK_LOOSE} invcheck_behaviour_t;
 typedef enum {FLAG_ACCEPT_ALWAYS,
 	      FLAG_REJECT_ALWAYS,
 	      FLAG_QUERY_USER,
@@ -21,8 +21,8 @@ typedef enum {FLAG_ACCEPT_ALWAYS,
 
 struct _domain_entry {
     char *	domain;  /* Domain for which these cookies are valid */
-    behaviour	bv;
-    invcheck_behaviour	invcheck_bv;
+    behaviour_t	bv;
+    invcheck_behaviour_t	invcheck_bv;
     HTList *	cookie_list;
 };
 typedef struct _domain_entry domain_entry;
@@ -40,13 +40,6 @@ extern void LYStoreCookies PARAMS((
 	char *		cookie_file));
 extern void LYLoadCookies PARAMS((
 	char * 		cookie_file));
-extern void cookie_add_acceptlist PARAMS((
-	char *		acceptdomains));
-extern void cookie_add_rejectlist PARAMS((
-	char *		rejectdomains));
-extern void cookie_set_invcheck PARAMS((
-	char *	 	domains,
-        invcheck_behaviour setting));
 extern void cookie_domain_flag_set PARAMS((
 	char * 		domainstr,
 	int 		flag));
diff --git a/src/LYCurses.h b/src/LYCurses.h
index 5505e9ca..51c116e1 100644
--- a/src/LYCurses.h
+++ b/src/LYCurses.h
@@ -306,8 +306,8 @@ extern int  lynx_chg_color PARAMS((int, int, int));
 #undef  standend
 #define standend() 		lynx_standout(FALSE)
 #else
-#define LYaddAttr		attrset
-#define LYaddWAttr		wattrset
+#define LYaddAttr		attron
+#define LYaddWAttr		wattron
 #define LYsubAttr		attroff
 #define LYsubWAttr		wattroff
 #endif
diff --git a/src/LYDownload.c b/src/LYDownload.c
index eaf1690b..5b079b32 100644
--- a/src/LYDownload.c
+++ b/src/LYDownload.c
@@ -91,7 +91,14 @@ PUBLIC void LYDownload ARGS1(
 #ifdef DIRED_SUPPORT
     /* FIXME: use HTLocalName */
     if (!strncmp(file, "file://localhost", 16))
+#ifdef __DJGPP__
+    {
+	file += 17;
+	file = HTDOS_name(file);
+    }
+#else
 	file += 16;
+#endif /* __DJGPP__ */
     else if (!strncmp(file, "file:", 5))
 	file += 5;
     HTUnEscape(file);
@@ -469,7 +476,7 @@ PUBLIC int LYdownload_options ARGS2(
 	char **,	newfile,
 	char *, 	data_file)
 {
-    static char tempfile[LY_MAXPATH];
+    static char tempfile[LY_MAXPATH] = "\0";
     char *downloaded_url = NULL;
     char *sug_filename = NULL;
     FILE *fp0;
@@ -482,8 +489,13 @@ PUBLIC int LYdownload_options ARGS2(
     StrAllocCopy(sug_filename, *newfile);
     change_sug_filename(sug_filename);
 
-    LYRemoveTemp(tempfile);
-    if ((fp0 = LYOpenTemp(tempfile, HTML_SUFFIX, "w")) == NULL) {
+    if (LYReuseTempfiles) {
+	fp0 = LYOpenTempRewrite(tempfile, HTML_SUFFIX, "w");
+    } else {
+	LYRemoveTemp(tempfile);
+	fp0 = LYOpenTemp(tempfile, HTML_SUFFIX, "w");
+    }
+    if (fp0 == NULL) {
 	HTAlert(CANNOT_OPEN_TEMP);
 	return(-1);
     }
diff --git a/src/LYGetFile.c b/src/LYGetFile.c
index 2bb09ea3..aa95cd9e 100644
--- a/src/LYGetFile.c
+++ b/src/LYGetFile.c
@@ -54,7 +54,7 @@ PUBLIC int HTNoDataOK = 0;
 
 /*
  *  getfile is the main mechanism to load a new document (or a previously
- *  laoded one whose rendering is cached in a HText structure) from
+ *  loaded one whose rendering is cached in a HText structure) from
  *  mainloop, nearly everything goes through it.
  *  It should return one of the values
  *     NORMAL     - requested document loaded successfully, usually [always?]
diff --git a/src/LYGlobalDefs.h b/src/LYGlobalDefs.h
index 91923705..9148285e 100644
--- a/src/LYGlobalDefs.h
+++ b/src/LYGlobalDefs.h
@@ -383,6 +383,7 @@ extern BOOLEAN LYPrependBaseToSource;
 extern BOOLEAN LYPrependCharsetToSource;
 extern BOOLEAN LYQuitDefaultYes;
 extern BOOLEAN LYNonRestartingSIGWINCH;
+extern BOOLEAN LYReuseTempfiles;
 
 #ifndef VMS
 extern BOOLEAN LYNoCore;
diff --git a/src/LYHistory.c b/src/LYHistory.c
index eef57082..6edc58c0 100644
--- a/src/LYHistory.c
+++ b/src/LYHistory.c
@@ -395,13 +395,18 @@ PUBLIC void LYpop_num ARGS2(
 PUBLIC int showhistory ARGS1(
 	char **,	newfile)
 {
-    static char tempfile[LY_MAXPATH];
+    static char tempfile[LY_MAXPATH] = "\0";
     char *Title = NULL;
     int x = 0;
     FILE *fp0;
 
-    LYRemoveTemp(tempfile);
-    if ((fp0 = LYOpenTemp(tempfile, HTML_SUFFIX, "w")) == NULL) {
+    if (LYReuseTempfiles) {
+	fp0 = LYOpenTempRewrite(tempfile, HTML_SUFFIX, "w");
+    } else {
+	LYRemoveTemp(tempfile);
+	fp0 = LYOpenTemp(tempfile, HTML_SUFFIX, "w");
+    }
+    if (fp0 == NULL) {
 	HTAlert(CANNOT_OPEN_TEMP);
 	return(-1);
     }
@@ -413,7 +418,7 @@ PUBLIC int showhistory ARGS1(
 
     BeginInternalPage(fp0, HISTORY_PAGE_TITLE, HISTORY_PAGE_HELP);
 
-    fprintf(fp0, "<tr align=right> <a href=\"LYNXMESSAGES:\">[%s]</a> </tr>\n",
+    fprintf(fp0, "<p align=right> <a href=\"LYNXMESSAGES:\">[%s]</a>\n",
 		 STATUSLINES_TITLE);
 
     fprintf(fp0, "<pre>\n");
@@ -557,7 +562,7 @@ PUBLIC BOOLEAN historytarget ARGS1(
 PUBLIC int LYShowVisitedLinks ARGS1(
 	char **,	newfile)
 {
-    static char tempfile[LY_MAXPATH];
+    static char tempfile[LY_MAXPATH] = "\0";
     char *Title = NULL;
     char *Address = NULL;
     int x;
@@ -568,8 +573,13 @@ PUBLIC int LYShowVisitedLinks ARGS1(
     if (!cur)
 	return(-1);
 
-    LYRemoveTemp(tempfile);
-    if ((fp0 = LYOpenTemp(tempfile, HTML_SUFFIX, "w")) == NULL) {
+    if (LYReuseTempfiles) {
+	fp0 = LYOpenTempRewrite(tempfile, HTML_SUFFIX, "w");
+    } else {
+	LYRemoveTemp(tempfile);
+	fp0 = LYOpenTemp(tempfile, HTML_SUFFIX, "w");
+    }
+    if (fp0 == NULL) {
 	HTAlert(CANNOT_OPEN_TEMP);
 	return(-1);
     }
@@ -683,13 +693,19 @@ PRIVATE void to_stack ARGS1(char *, str)
 PUBLIC int LYshow_statusline_messages ARGS1(
     document *,			      newdoc)
 {
-    static char tempfile[LY_MAXPATH];
+    static char tempfile[LY_MAXPATH] = "\0";
     static char *info_url;
     FILE *fp0;
     int i;
+    char *temp = NULL;
 
-    LYRemoveTemp(tempfile);
-    if ((fp0 = LYOpenTemp (tempfile, HTML_SUFFIX, "w")) == 0) {
+    if (LYReuseTempfiles) {
+	fp0 = LYOpenTempRewrite(tempfile, HTML_SUFFIX, "w");
+    } else {
+	LYRemoveTemp(tempfile);
+	fp0 = LYOpenTemp(tempfile, HTML_SUFFIX, "w");
+    }
+    if (fp0 == NULL) {
 	HTAlert(CANNOT_OPEN_TEMP);
 	return(NOT_FOUND);
     }
@@ -704,13 +720,19 @@ PUBLIC int LYshow_statusline_messages ARGS1(
     /* print messages in reverse order: */
     i = topOfStack;
     while (--i >= 0) {
-	if (buffstack[i] != NULL)
-	    fprintf(fp0,  "<li> <em>%s</em>\n",  buffstack[i]);
+	if (buffstack[i] != NULL) {
+	    StrAllocCopy(temp, buffstack[i]);
+	    LYEntify(&temp, TRUE);
+	    fprintf(fp0,  "<li> <em>%s</em>\n",	 temp);
+	}
     }
     i = STATUSBUFSIZE;
     while (--i >= topOfStack) {
-	if (buffstack[i] != NULL)
-	fprintf(fp0,  "<li> <em>%s</em>\n",  buffstack[i]);
+	if (buffstack[i] != NULL) {
+	    StrAllocCopy(temp, buffstack[i]);
+	    LYEntify(&temp, TRUE);
+	    fprintf(fp0,  "<li> <em>%s</em>\n",	 temp);
+	}
     }
 
     fprintf(fp0, "</ol>\n");
@@ -772,6 +794,7 @@ PUBLIC void LYstore_message2 ARGS2(
     if (message != NULL) {
 	char *temp = NULL;
 	HTSprintf(&temp, message, (argument == 0) ? "" : argument);
+	LYEntify(&temp, TRUE);
 	to_stack(temp);
     }
 }
@@ -782,6 +805,7 @@ PUBLIC void LYstore_message ARGS1(
     if (message != NULL) {
 	char *temp = NULL;
 	StrAllocCopy(temp, message);
+	LYEntify(&temp, TRUE);
 	to_stack(temp);
     }
 }
diff --git a/src/LYKeymap.c b/src/LYKeymap.c
index 3999898c..be169559 100644
--- a/src/LYKeymap.c
+++ b/src/LYKeymap.c
@@ -893,7 +893,7 @@ PUBLIC int lkcstring_to_lkc ARGS1(
 #ifndef USE_SLANG
 	   if (c >= 0) {
 	       if ((c&LKC_MASK) > 255 && !(c & LKC_ISLKC))
-		   return (-1);	/* Don't accept untranslatable curses KEY_* */
+		   return (-1);	/* Don't accept untranslated curses KEY_* */
 	       else
 		   c &= ~LKC_ISLKC;
 	   }
diff --git a/src/LYLeaks.c b/src/LYLeaks.c
index 70c8d8a1..0d8ff2bf 100644
--- a/src/LYLeaks.c
+++ b/src/LYLeaks.c
@@ -129,7 +129,6 @@ PUBLIC void LYLeaks NOARGS
 		}
 	    }
 	    fprintf(Fp_leakagesink, "\n");
-	    FREE(ALp_head->vp_Alloced);
 	    fprintf(Fp_leakagesink, "%s\t%d\n",
 				    gettext("ByteSize:"),
 				    (int)(ALp_head->st_Bytes));
@@ -151,6 +150,8 @@ PUBLIC void LYLeaks NOARGS
 			gettext("LineCount:"),
 			ALp_head->SL_realloc.ssi_LineNumber);
 	    }
+	    fflush(Fp_leakagesink);
+	    FREE(ALp_head->vp_Alloced);
 	}
 
 	/*
diff --git a/src/LYLocal.c b/src/LYLocal.c
index df254292..7409535a 100644
--- a/src/LYLocal.c
+++ b/src/LYLocal.c
@@ -82,6 +82,10 @@
 #define EXT_Z      ".Z"
 #endif
 
+#ifndef DIRED_MAXBUF
+#define DIRED_MAXBUF 512
+#endif
+
 PRIVATE int LYExecv PARAMS((
 	char *		path,
 	char ** 	argv,
@@ -91,6 +95,15 @@ PRIVATE int LYExecv PARAMS((
 PUBLIC char LYPermitFileURL[LY_MAXPATH] = "\0";
 PUBLIC char LYDiredFileURL[LY_MAXPATH] = "\0";
 
+#ifdef OK_INSTALL
+PUBLIC char LYInstallFileURL[LY_MAXPATH] = "\0";
+#ifdef FNAMES_8_3
+#define INSTALLDIRS_FILE "instdirs.htm"
+#else
+#define INSTALLDIRS_FILE ".installdirs.html"
+#endif /* FNAMES_8_3 */
+#endif /* OK_INSTALL */
+
 PRIVATE char *get_filename PARAMS((
 	char *		prompt,
 	char *		buf,
@@ -105,8 +118,8 @@ PRIVATE BOOLEAN permit_location PARAMS((
 
 PRIVATE char *render_item PARAMS((
 	CONST char *	s,
-	char *		path,
-	char *		dir,
+	CONST char *	path,
+	CONST char *	dir,
 	char *		buf,
 	int		bufsize,
 	BOOLEAN 	url_syntax));
@@ -136,10 +149,17 @@ struct dired_menu {
 { 0,		      "", "New Directory",
 "(in current directory)", "LYNXDIRED://NEW_FOLDER%d",		NULL },
 
+#ifdef OK_INSTALL
 { DE_FILE,	      "", "Install",
-"(of current selection)", "LYNXDIRED://INSTALL_SRC%p",		NULL },
+"selected file to new location", "LYNXDIRED://INSTALL_SRC%p",	NULL },
+/* The following (installing a directory) doesn't work for me, at least
+   with the "install" from GNU fileutils 4.0.  I leave it in anyway, in
+   case one compiles with INSTALL_PATH / INSTALL_ARGS defined to some
+   other command for which it works (like a script, or maybe "cp -a"). - kw
+*/
 { DE_DIR,	      "", "Install",
-"(of current selection)", "LYNXDIRED://INSTALL_SRC%p",		NULL },
+"selected directory to new location", "LYNXDIRED://INSTALL_SRC%p",	NULL },
+#endif /* OK_INSTALL */
 
 { DE_FILE,	      "", "Modify File Name",
 "(of current selection)", "LYNXDIRED://MODIFY_NAME%p",		NULL },
@@ -249,6 +269,11 @@ struct dired_menu {
 { DE_TAG,	      "", "Move all tagged items to another location.",
 		      "", "LYNXDIRED://MOVE_TAGGED%d",		NULL },
 
+#ifdef OK_INSTALL
+{ DE_TAG,	      "", "Install tagged files into another directory.",
+		      "", "LYNXDIRED://INSTALL_SRC%00",		NULL },
+#endif
+
 { DE_TAG,	      "", "Remove all tagged files and directories.",
 		      "", "LYNXDIRED://REMOVE_TAGGED",		NULL },
 
@@ -259,7 +284,7 @@ struct dired_menu {
 		    NULL, NULL, 				NULL }
 };
 
-PRIVATE BOOLEAN cannot_stat ARGS1(char *, name)
+PRIVATE BOOLEAN cannot_stat ARGS1(CONST char *, name)
 {
     char *tmpbuf = 0;
     HTSprintf(&tmpbuf, gettext("Unable to get status of '%s'."), name);
@@ -268,10 +293,12 @@ PRIVATE BOOLEAN cannot_stat ARGS1(char *, name)
     return FALSE;
 }
 
-PRIVATE BOOLEAN ok_stat ARGS2(char *, name, struct stat*, sb)
+#define OK_STAT(name, sb) (stat(name, sb) == 0)
+
+PRIVATE BOOLEAN ok_stat ARGS2(CONST char *, name, struct stat*, sb)
 {
     CTRACE(tfp, "testing ok_stat(%s)\n", name);
-    if (stat(name, sb) < 0) {
+    if (!OK_STAT(name, sb)) {
 	return cannot_stat(name);
     }
     return TRUE;
@@ -300,20 +327,23 @@ PRIVATE BOOLEAN ok_file_or_dir ARGS1(struct stat*, sb)
     return TRUE;
 }
 
-PRIVATE BOOLEAN ok_localname ARGS2(char*, dst, char*, src)
+#ifdef OK_INSTALL		/* currently only used in local_install */
+PRIVATE BOOLEAN ok_localname ARGS2(char*, dst, CONST char*, src)
 {
-    char *s = HTfullURL_toFile(strip_trailing_slash(src));
     struct stat dir_info;
 
-    if (!ok_stat(s, &dir_info)
+    if (!ok_stat(src, &dir_info)
      || !ok_file_or_dir(&dir_info)) {
-	FREE(s);
 	return FALSE;
     }
-    strcpy(dst, s);
-    FREE(s);
+    if (strlen(src) >= DIRED_MAXBUF) {
+	CTRACE(tfp, "filename too long in ok_localname!\n");
+	return FALSE;
+    }
+    strcpy(dst, src);
     return TRUE;
 }
+#endif /* OK_INSTALL */
 
 PRIVATE int move_file ARGS2(char *, source, char *, target)
 {
@@ -335,7 +365,7 @@ PRIVATE BOOLEAN not_already_exists ARGS1(char *, name)
 {
     struct stat dir_info;
 
-    if (stat(name, &dir_info) == -1) {
+    if (!OK_STAT(name, &dir_info)) {
 	if (errno != ENOENT) {
 	    cannot_stat(name);
 	} else {
@@ -437,7 +467,7 @@ PRIVATE BOOLEAN modify_tagged ARGS1(
     ino_t inode;
     uid_t owner;
     char tmpbuf[1024];
-    char *savepath = NULL;
+    char *savepath;
     char *srcpath = NULL;
     struct stat dir_info;
     int count = 0;
@@ -471,21 +501,28 @@ PRIVATE BOOLEAN modify_tagged ARGS1(
 	    cp = HTList_lastObject(tagged);
 	    testpath = NULL;	/* Won't be needed any more in this function,
 				   set to NULL as a flag. */
-	    if (!cp)	/* Last resort, should never happen. */
-		cp = "/";
 	}
 
 	if (testpath == NULL) {
 	    /*
 	     *	Get the directory containing the file or subdir.
 	     */
-	    cp = HTfullURL_toFile(strip_trailing_slash(cp));
-	    savepath = HTParse(".", cp, PARSE_PATH+PARSE_PUNCTUATION);
+	    if (cp) {
+		cp = strip_trailing_slash(cp);
+		cp = HTParse(".", cp, PARSE_PATH+PARSE_PUNCTUATION);
+		savepath = HTURLPath_toFile(cp, TRUE);
+		FREE(cp);
+	    } else {	/* Last resort, should never happen. */
+		savepath = HTURLPath_toFile(".", TRUE);
+	    }
 	} else {
-	    cp = HTfullURL_toFile(cp);
-	    StrAllocCopy(savepath, cp);
+	    if (!strncmp(cp, "file://localhost", 16)) {
+		cp += 16;
+	    } else if (!strncmp(cp, "file:", 5)) {
+		cp += 5;
+	    }
+	    savepath = HTURLPath_toFile(cp, TRUE);
 	}
-	FREE(cp);
 
 	if (!ok_stat(savepath, &dir_info)) {
 	    FREE(savepath);
@@ -556,8 +593,7 @@ PRIVATE BOOLEAN modify_tagged ARGS1(
 	     *  Move all tagged items to the target location.
 	     */
 	    while ((cp = (char *)HTList_nextObject(tag)) != NULL) {
-		cp = HTfullURL_toFile(cp);
-		StrAllocCopy(srcpath, cp);
+		srcpath = HTfullURL_toFile(cp);
 
 		if (move_file(srcpath, savepath) < 0) {
 		    FREE(cp);
@@ -565,7 +601,7 @@ PRIVATE BOOLEAN modify_tagged ARGS1(
 			count = -1;
 		    break;
 		}
-		FREE(cp);
+		FREE(srcpath);
 		++count;
 	    }
 	    clear_tags();
@@ -584,9 +620,9 @@ PRIVATE BOOLEAN modify_name ARGS1(
 	char *, 	testpath)
 {
     char *cp;
-    char tmpbuf[512];
-    char newpath[512];
-    char savepath[512];
+    char tmpbuf[DIRED_MAXBUF];
+    char newpath[DIRED_MAXBUF];
+    char savepath[DIRED_MAXBUF];
     struct stat dir_info;
 
     /*
@@ -642,8 +678,8 @@ PRIVATE BOOLEAN modify_location ARGS1(
     ino_t inode;
     uid_t owner;
     char tmpbuf[1024];
-    char newpath[512];
-    char savepath[512];
+    char newpath[DIRED_MAXBUF];
+    char savepath[DIRED_MAXBUF];
     struct stat dir_info;
 
     /*
@@ -725,15 +761,14 @@ PUBLIC BOOLEAN local_modify ARGS2(
 {
     int c, ans;
     char *cp;
-    char testpath[512]; /* a bit ridiculous */
+    char testpath[DIRED_MAXBUF]; /* a bit ridiculous */
     int count;
 
     if (!HTList_isEmpty(tagged)) {
 	cp = HTpartURL_toFile(doc->address);
-	strcpy(testpath, cp);
-	FREE(cp);
 
-	count = modify_tagged(testpath);
+	count = modify_tagged(cp);
+	FREE(cp);
 
 	if (doc->link > (nlinks-count - 1))
 	    doc->link = (nlinks-count - 1);
@@ -762,6 +797,10 @@ PUBLIC BOOLEAN local_modify ARGS2(
 
     if (strchr("NLP", ans) != NULL) {
 	cp = HTfullURL_toFile(links[doc->link].lname);
+	if (strlen(cp) >= DIRED_MAXBUF) {
+	    FREE(cp);
+	    return 0;
+	}
 	strcpy(testpath, cp);
 	FREE(cp);
 
@@ -794,8 +833,8 @@ PRIVATE BOOLEAN create_file ARGS1(
 	char *, 	current_location)
 {
     int code = FALSE;
-    char tmpbuf[512];
-    char testpath[512];
+    char tmpbuf[DIRED_MAXBUF];
+    char testpath[DIRED_MAXBUF];
     char *args[5];
     char *bad_chars = ".~/";
 
@@ -842,8 +881,8 @@ PRIVATE BOOLEAN create_directory ARGS1(
 	char *, 	current_location)
 {
     int code = FALSE;
-    char tmpbuf[512];
-    char testpath[512];
+    char tmpbuf[DIRED_MAXBUF];
+    char testpath[DIRED_MAXBUF];
     char *args[5];
     char *bad_chars = ".~/";
 
@@ -888,16 +927,20 @@ PUBLIC BOOLEAN local_create ARGS1(
 {
     int c, ans;
     char *cp;
-    char testpath[512];
-
-    _statusline(gettext("Create file or directory (f or d): "));
-    c = LYgetch();
-    ans = TOUPPER(c);
+    char testpath[DIRED_MAXBUF];
 
     cp = HTfullURL_toFile(doc->address);
+    if (strlen(cp) >= DIRED_MAXBUF) {
+	FREE(cp);
+	return 0;
+    }
     strcpy(testpath,cp);
     FREE(cp);
 
+    _statusline(gettext("Create file or directory (f or d): "));
+    c = LYgetch();
+    ans = TOUPPER(c);
+
     if (ans == 'F') {
 	return(create_file(testpath));
     } else if (ans == 'D') {
@@ -980,7 +1023,7 @@ PUBLIC BOOLEAN local_remove ARGS1(
 	document *,	doc)
 {
     char *cp, *tp;
-    char testpath[512];
+    char testpath[DIRED_MAXBUF];
     int count, i;
 
     if (!HTList_isEmpty(tagged)) {
@@ -996,6 +1039,10 @@ PUBLIC BOOLEAN local_remove ARGS1(
     cp = links[doc->link].lname;
     if (is_url(cp) == FILE_URL_TYPE) {
 	tp = HTfullURL_toFile(cp);
+	if (strlen(tp) >= DIRED_MAXBUF) {
+	    FREE(tp);
+	    return 0;
+	}
 	strcpy(testpath, tp);
 	FREE(tp);
 
@@ -1058,22 +1105,19 @@ PRIVATE BOOLEAN permit_location ARGS3(
 	 *  Create form.
 	 */
 	FILE *fp0;
-	char local_src[LY_MAXPATH];
 	char * user_filename;
 	char * group_name;
 
-	cp = HTfullURL_toFile(strip_trailing_slash(srcpath));
-	strcpy(local_src, cp);
-	FREE(cp);
+	srcpath = strip_trailing_slash(srcpath);
 
 	/*
 	 *  A couple of sanity tests.
 	 */
-	if (!ok_lstat(local_src, &dir_info)
+	if (!ok_lstat(srcpath, &dir_info)
 	 || !ok_file_or_dir(&dir_info))
 	    return 0;
 
-	user_filename = LYPathLeaf(local_src);
+	user_filename = LYPathLeaf(srcpath);
 
 	LYRemoveTemp(tempfile);
 	if ((fp0 = LYOpenTemp(tempfile, HTML_SUFFIX, "w")) == NULL) {
@@ -1089,7 +1133,7 @@ PRIVATE BOOLEAN permit_location ARGS3(
 
 	group_name = HTAA_GidToName (dir_info.st_gid);
 	LYstrncpy(LYValidPermitFile,
-		  local_src,
+		  srcpath,
 		  (sizeof(LYValidPermitFile) - 1));
 
 	fprintf(fp0, "<Html><Head>\n<Title>%s</Title>\n</Head>\n<Body>\n",
@@ -1194,10 +1238,14 @@ PRIVATE BOOLEAN permit_location ARGS3(
 	*cp++ = '\0';	/* Null terminate file name and
 			   start working on the masks. */
 
-	if ((destpath = HTfullURL_toFile(destpath)) == 0)
+	/* Will now operate only on filename part. */
+	if ((destpath = HTURLPath_toFile(destpath, TRUE)) == 0)
 		return(0);
-
-	strcpy(tmpdst, destpath);	/* operate only on filename */
+	if (strlen(destpath) >= LY_MAXPATH) {
+	    FREE(destpath);
+	    return(0);
+	}
+	strcpy(tmpdst, destpath);
 	FREE(destpath);
 	destpath = tmpdst;
 
@@ -1358,15 +1406,20 @@ PRIVATE char * DirectoryOf ARGS1(
 }
 
 #ifdef __DJGPP__
-/*  Convert filenames to acceptable 8+3 names when necessary
-*/
+/*
+ * Convert filenames to acceptable 8+3 names when necessary.  Make a copy of
+ * the parameter if we must modify it.
+ */
 PRIVATE char * LYonedot ARGS1(
 	char *,		line)
 {
     char *dot;
+    static char line1[LY_MAXPATH];
+
     if (pathconf (line, _PC_NAME_MAX) <= 12) {
+	strcpy(line1, line);
 	for (;;) {
-	    if ((dot = strrchr(line, '.')) == 0
+	    if ((dot = strrchr(line1, '.')) == 0
 	     || LYLastPathSep(dot) != 0) {
 		break;
 	    } else if (strlen(dot) == 1) {
@@ -1375,6 +1428,7 @@ PRIVATE char * LYonedot ARGS1(
 		*dot = '_';
 	    }
 	}
+	return(line1);
     }
     return(line);
 }
@@ -1428,15 +1482,19 @@ PUBLIC int local_dired ARGS1(
     } else if (!strncmp(line, "LYNXDIRED://NEW_FOLDER", 22)) {
 	if (create_directory(&line[22]) > 0)
 	    LYforce_no_cache = TRUE;
+#ifdef OK_INSTALL
     } else if (!strncmp(line, "LYNXDIRED://INSTALL_SRC", 23)) {
 	local_install(NULL, &line[23], &tp);
-	StrAllocCopy(doc->address, tp);
-	FREE(tp);
+	if (tp) {
+	    FREE(doc->address);
+	    doc->address = tp;
+	}
 	FREE(line);
 	return 0;
     } else if (!strncmp(line, "LYNXDIRED://INSTALL_DEST", 24)) {
 	local_install(&line[24], NULL, &tp);
 	LYpop(doc);
+#endif /* OK_INSTALL */
     } else if (!strncmp(line, "LYNXDIRED://MODIFY_NAME", 23)) {
 	if (modify_name(&line[23]) > 0)
 	LYforce_no_cache = TRUE;
@@ -1449,13 +1507,14 @@ PUBLIC int local_dired ARGS1(
 #ifdef OK_PERMIT
     } else if (!strncmp(line, "LYNXDIRED://PERMIT_SRC", 22)) {
 	permit_location(NULL, &line[22], &tp);
-	if (tp)
+	if (tp) {
 	    /*
 	     *	One of the checks may have failed.
 	     */
-	    StrAllocCopy(doc->address, tp);
+	    FREE(doc->address);
+	    doc->address = tp;
+	}
 	FREE(line);
-	FREE(tp);
 	return 0;
     } else if (!strncmp(line, "LYNXDIRED://PERMIT_LOCATION", 27)) {
 	permit_location(&line_url[27], NULL, &tp);
@@ -1619,7 +1678,7 @@ PUBLIC int local_dired ARGS1(
 	    }
 	    _statusline(tmpbuf);
 	    stop_curses();
-	    printf("%s\n", tmpbuf);
+	    printf("%s\r\n", tmpbuf);
 	    LYSystem(buffer);
 #ifdef VMS
 	    HadVMSInterrupt = FALSE;
@@ -1646,11 +1705,11 @@ PUBLIC int dired_options ARGS2(
 	char **,	newfile)
 {
     static char tempfile[LY_MAXPATH];
-    char path[512], dir[512]; /* much too large */
+    char *path;
+    char *dir;
     lynx_html_item_type *nxt;
     struct stat dir_info;
     FILE *fp0;
-    char *cp = NULL;
     char *dir_url;
     char *path_url;
     BOOLEAN nothing_tagged;
@@ -1670,26 +1729,23 @@ PUBLIC int dired_options ARGS2(
     LYLocalFileToURL(newfile, tempfile);
     strcpy(LYDiredFileURL, *newfile);
 
-    cp = HTpartURL_toFile(doc->address);
-    strcpy(dir, cp);
-    LYTrimPathSep(dir);
-    FREE(cp);
-
     if (doc->link > -1 && doc->link < (nlinks+1)) {
-	cp = HTfullURL_toFile(links[doc->link].lname);
-	strcpy(path, cp);
+	path = HTfullURL_toFile(links[doc->link].lname);
 	LYTrimPathSep(path);
-	FREE(cp);
 
 	if (!ok_lstat(path, &dir_info)) {
 	    LYCloseTempFP(fp0);
+	    FREE(path);
 	    return 0;
 	}
 
     } else {
-	path[0] = '\0';
+	StrAllocCopy(path, "");
     }
 
+    dir = HTfullURL_toFile(doc->address);
+    LYTrimPathSep(dir);
+
     nothing_tagged = (HTList_isEmpty(tagged));
 
     BeginInternalPage(fp0, DIRED_MENU_TITLE, DIRED_MENU_HELP);
@@ -1778,6 +1834,7 @@ PUBLIC int dired_options ARGS2(
 	FREE(dir_url);
 	FREE(path_url);
     }
+    FREE(path);
 
     if (uploaders != NULL) {
 	fprintf(fp0, "<p>Upload to current directory:<p>\n");
@@ -1789,6 +1846,7 @@ PUBLIC int dired_options ARGS2(
 		    count, dir, nxt->name);
 	}
     }
+    FREE(dir);
 
     EndInternalPage(fp0);
     LYCloseTempFP(fp0);
@@ -1831,6 +1889,72 @@ PRIVATE char *get_filename ARGS3(
     return buf;
 }
 
+#ifdef OK_INSTALL
+
+#define LYEXECV_MAX_ARGC 15
+/* these are quasi-constant once they have been allocated: */
+static char ** install_argp = NULL;	/* args for execv install */
+static char * install_path = NULL; 	/* auxiliary */
+#ifdef LY_FIND_LEAKS
+PRIVATE void clear_install_path NOARGS
+{
+    FREE(install_argp);
+    FREE(install_path);
+}
+#endif /* LY_FIND_LEAKS */
+/*
+ *  Fill in args array for execv (or execvp etc.) call, after first
+ *  allocating it if necessary.  No fancy parsing, cmd_args is just
+ *  split at spaces.  Leave room for reserve additional args to be
+ *  added by caller.
+ *  On success *argvp points to new args vector, *pathp is auxiliary.
+ *  On success returns index of next argument, else -1.
+ *  This is generic enough that it could be used for other calls than
+ *  install, except the atexit call.  Go through this trouble for install
+ *  because INSTALL_ARGS may be significant, and someone may configure it
+ *  with more than one significant flags. - kw
+ */
+PRIVATE int fill_argv_for_execv ARGS5(
+    char ***,		argvp,
+    char **,		pathp,
+    char *,		cmd_path,
+    CONST char *,	cmd_args,
+    int,		reserve)
+{
+    int n = 0;
+
+    char **args;
+    char *cp;
+    if (*argvp == NULL) {
+	*argvp = (char **)calloc(LYEXECV_MAX_ARGC+1, sizeof(char *));
+	if (!*argvp)
+	    return(-1);
+#ifdef LY_FIND_LEAKS
+	atexit(clear_install_path);
+#endif
+    }
+    args = *argvp;
+    args[n++] = cmd_path;
+    if (cmd_args) {
+	StrAllocCopy(*pathp, cmd_args);
+	cp = strtok(*pathp, " ");
+	if (cp) {
+	    while (cp && (n < LYEXECV_MAX_ARGC - reserve)) {
+		args[n++] = cp;
+		cp = strtok(NULL, " ");
+	    }
+	    if (cp && (n >= LYEXECV_MAX_ARGC - reserve)) {
+		CTRACE(tfp, "Too many args for '%s' in '%s'!\n",
+		       cmd_path ? cmd_path : "<null>" , cmd_args);
+		return(-1);
+	    }
+	} else {
+	    args[n++] = *pathp;
+	}
+    }
+    args[n] = (char *)0;
+    return(n);
+}
 /*
  *  Install the specified file or directory.
  */
@@ -1840,71 +1964,173 @@ PUBLIC BOOLEAN local_install ARGS3(
 	char **,	newpath)
 {
     char *tmpbuf = NULL;
-    char savepath[512]; /* This will be the link that is to be installed. */
+    static char savepath[DIRED_MAXBUF]; /* This will be the link that
+					   is to be installed. */
     struct stat dir_info;
-    char *args[6];
+    char **args;
     HTList *tag;
+    char *cp = NULL;
+    char *tmpdest = NULL;
     int count = 0;
-    int n = 0, src;	/* indices into 'args[]' */
+    int n = 0;		/* indices into 'args[]' */
+    static int src = -1;
 
     /*
      *	Determine the status of the selected item.
      */
     if (srcpath) {
-	if (!ok_localname(savepath, srcpath))
+	srcpath = strip_trailing_slash(srcpath);
+	if (is_url(srcpath)) {
+	    char *local_src = HTfullURL_toFile(srcpath);
+	    if (!ok_localname(savepath, local_src)) {
+		FREE(local_src);
+		return 0;
+	    }
+	    FREE(local_src);
+	} else if (!HTList_isEmpty(tagged) &&
+		   srcpath[0] == '\0') {
+	    savepath[0] = '\0';	/* will always use tagged list - kw */
+	} else if (!ok_localname(savepath, srcpath)) {
 	    return 0;
-
+	}
 	LYforce_no_cache = TRUE;
 	LYLocalFileToURL(newpath, Home_Dir());
-	StrAllocCat(*newpath, "/.installdirs.html");
+	LYAddHtmlSep(newpath);
+	StrAllocCat(*newpath, INSTALLDIRS_FILE);
+	LYstrncpy(LYInstallFileURL,
+		  *newpath,
+		  (sizeof(LYInstallFileURL) - 1));
 	return 0;
     }
 
+    /* deal with ~/ or /~/ at the beginning - kw */
+    if (destpath[0] == '~' &&
+	(destpath[1] == '/' || destpath[1] == '\0')) {
+	cp = &destpath[1];
+    } else if (destpath[0] == '/' && destpath[1] == '~' &&
+	       (destpath[2] == '/' || destpath[2] == '\0')) {
+	cp = &destpath[2];
+    }
+    if (cp) {
+	/* If found, allocate new string, make destpath point to it - kw */
+	StrAllocCopy(tmpdest, Home_Dir());
+	if (cp[0] && cp[1]) {
+	    LYAddPathSep(&tmpdest);
+	    StrAllocCat(tmpdest, cp + 1);
+	}
+	destpath = tmpdest;
+    }
+
     destpath = strip_trailing_slash(destpath);
 
     if (!ok_stat(destpath, &dir_info)) {
+	FREE(tmpdest);
 	return 0;
     } else if (!S_ISDIR(dir_info.st_mode)) {
 	HTAlert(gettext("The selected item is not a directory!  Request ignored."));
+	FREE(tmpdest);
 	return 0;
     } else if (0 /*directory not writable*/) {
 	HTAlert(gettext("Install in the selected directory not permitted."));
+	FREE(tmpdest);
 	return 0;
     }
 
     statusline(gettext("Just a moment, ..."));
-    args[n++] = "install";
+
+    /* fill in the fixed args, if not already done - kw */
+    if (src > 0 && install_argp) {
+	n = src;
+	n++;
+    } else {
+	n = fill_argv_for_execv(&install_argp, &install_path,
+				"install",
 #ifdef INSTALL_ARGS
-    args[n++] = INSTALL_ARGS;
+				INSTALL_ARGS,
+#else
+				NULL,
 #endif /* INSTALL_ARGS */
-    src = n++;
+				2);
+	if (n <= 0) {
+	    src = 0;
+	    HTAlert(gettext("Error buiding install args"));
+	    FREE(tmpdest);
+	    return 0;
+	}
+	src = n++;
+    }
+    args = install_argp;
+
     args[n++] = destpath;
     args[n] = (char *)0;
-    HTSprintf(&tmpbuf, "install %s", destpath);
     tag = tagged;
 
     if (HTList_isEmpty(tagged)) {
+	/* simplistic detection of identical src and dest - kw */
+	if (!strcmp(savepath, destpath)) {
+	    HTUserMsg2(gettext("Source and target are the same: %s"),
+		       savepath);
+	    FREE(tmpdest);
+	    return(-1);		/* don't do it */
+	} else if (!strncmp(savepath, destpath, strlen(destpath)) &&
+		   LYIsPathSep(savepath[strlen(destpath)]) &&
+#ifdef DOSPATH
+		   !strchr(savepath + strlen(destpath) + 1, '\\') &&
+#endif
+		   !strchr(savepath + strlen(destpath) + 1, '/')) {
+	    HTUserMsg2(gettext("Already in target directory: %s"),
+		       savepath);
+	    FREE(tmpdest);
+	    return 0;		/* don't do it */
+	}
 	args[src] = savepath;
-	if (LYExecv(INSTALL_PATH, args, tmpbuf) <= 0)
+	HTSprintf(&tmpbuf, "install %s in %s", savepath, destpath);
+	if (LYExecv(INSTALL_PATH, args, tmpbuf) <= 0) {
+	    FREE(tmpbuf);
+	    FREE(tmpdest);
 	    return (-1);
+	}
 	count++;
     } else {
 	char *name;
+	HTSprintf(&tmpbuf, "install in %s", destpath);
 	while ((name = (char *)HTList_nextObject(tag))) {
 	    int err;
 	    args[src] = HTfullURL_toFile(name);
+
+	    /* simplistic detection of identical src and dest - kw */
+	    if (!strcmp(args[src], destpath)) {
+		HTUserMsg2(gettext("Source and target are the same: %s"),
+			   args[src]);
+		FREE(args[src]);
+		continue;	/* skip this source file */
+	    } else if (!strncmp(args[src], destpath, strlen(destpath)) &&
+		       LYIsPathSep(args[src][strlen(destpath)]) &&
+#ifdef DOSPATH
+		       !strchr(args[src] + strlen(destpath) + 1, '\\') &&
+#endif
+		       !strchr(args[src] + strlen(destpath) + 1, '/')) {
+		HTUserMsg2(gettext("Already in target directory: %s"),
+			   args[src]);
+		FREE(args[src]);
+		continue;	/* skip this source file */
+	    }
 	    err = (LYExecv(INSTALL_PATH, args, tmpbuf) <= 0);
 	    FREE(args[src]);
-	    if (err)
+	    if (err) {
+		FREE(tmpdest);
 		return ((count == 0) ? -1 : count);
+	    }
 	    count++;
 	}
 	clear_tags();
     }
     FREE(tmpbuf);
+    FREE(tmpdest);
     HTInfoMsg(gettext("Installation complete"));
     return count;
 }
+#endif /* OK_INSTALL */
 
 /*
  *  Clear DIRED tags.
@@ -1990,13 +2216,13 @@ PUBLIC void add_menu_item ARGS1(
  */
 PRIVATE char * render_item ARGS6(
 	CONST char *, 	s,
-	char *, 	path,
-	char *, 	dir,
+	CONST char *, 	path,
+	CONST char *, 	dir,
 	char *, 	buf,
 	int,		bufsize,
 	BOOLEAN,	url_syntax)
 {
-    char *cp;
+    CONST char *cp;
     char *bp;
     char overrun = '\0';
     char *taglist = NULL;
@@ -2081,6 +2307,7 @@ PRIVATE char * render_item ARGS6(
     *bp = '\0';
     return buf;
 }
+
 #endif /* DIRED_SUPPORT */
 
 /*
@@ -2169,7 +2396,8 @@ PRIVATE int LYExecv ARGS3(
     }
     start_curses();
     if (tmpbuf != 0) {
-	HTAlert(tmpbuf);
+	if (rc == 0)
+	    HTAlert(tmpbuf);
 	FREE(tmpbuf);
     }
 
diff --git a/src/LYLocal.h b/src/LYLocal.h
index 029718d1..143e3914 100644
--- a/src/LYLocal.h
+++ b/src/LYLocal.h
@@ -35,11 +35,16 @@
 extern char LYPermitFileURL[];
 extern char LYDiredFileURL[];
 extern char LYUploadFileURL[];
+#ifdef OK_INSTALL
+extern char LYInstallFileURL[];
+#endif
 
 extern BOOLEAN local_create PARAMS((document *doc));
 extern BOOLEAN local_modify PARAMS((document *doc, char **newpath));
 extern BOOLEAN local_remove PARAMS((document *doc));
+#ifdef OK_INSTALL
 extern BOOLEAN local_install PARAMS((char *destpath, char *srcpath, char **newpath));
+#endif
 
 /* MainLoop needs to know about this one for atexit cleanup */
 extern void clear_tags NOPARAMS;
diff --git a/src/LYMail.c b/src/LYMail.c
index 340f14c9..37764eab 100644
--- a/src/LYMail.c
+++ b/src/LYMail.c
@@ -1852,7 +1852,7 @@ PUBLIC void reply_by_mail ARGS4(
     sleep(AlertSecs);
     start_curses();
     goto cleandown;
-#else /* Unix: */
+#else /* not VMS: */
     /*
      *	Send the tmpfile into sendmail.
      */
diff --git a/src/LYMain.c b/src/LYMain.c
index e422853b..1c7f6c87 100644
--- a/src/LYMain.c
+++ b/src/LYMain.c
@@ -409,6 +409,7 @@ PUBLIC int partial_threshold = -1;  /* # of lines to be d/l'ed until we repaint
 #endif
 
 PUBLIC BOOLEAN LYNonRestartingSIGWINCH = FALSE;
+PUBLIC BOOLEAN LYReuseTempfiles = FALSE;
 
 /* These are declared in cutil.h for current freeWAIS libraries. - FM */
 #ifdef DECLARE_WAIS_LOGFILES
@@ -2561,6 +2562,7 @@ static int restrictions_fun ARGS1(
 #ifndef NO_CONFIG_INFO
 ,"   lynxcfg_xinfo   disable extended lynx.cfg viewing and reloading"
 #endif
+,"   mail            disallow mail"
 ,"   multibook       disallow multiple bookmark files"
 ,"   news_post       disallow USENET News posting."
 ,"   option_save     disallow saving options in .lynxrc"
diff --git a/src/LYMainLoop.c b/src/LYMainLoop.c
index 51cfb467..47ac1d67 100644
--- a/src/LYMainLoop.c
+++ b/src/LYMainLoop.c
@@ -743,6 +743,7 @@ try_again:
 		    LYCancelledFetch = FALSE;
 		    ForcePush = FALSE;
 		    LYforce_HTML_mode = FALSE;
+		    force_old_UCLYhndl_on_reload = FALSE;
 		    if (traversal) {
 			crawl_ok = FALSE;
 			if (traversal_link_to_add) {
@@ -1121,6 +1122,7 @@ try_again:
 	   LYPermitURL = FALSE;		/* only for LYValidate or check_realm */
 	   ForcePush = FALSE;		/* only set for some PRINT requests. */
 	   LYforce_HTML_mode = FALSE;
+	   force_old_UCLYhndl_on_reload = FALSE;
 	   popped_doc = FALSE;
 
 	} /* end if (LYforce_no_cache || force_load || are_different(...)) */
@@ -1761,6 +1763,7 @@ new_cmd:  /*
 	   *  back through the getch() loop.
 	   */
 
+	force_old_UCLYhndl_on_reload = FALSE;
 	CTRACE_FLUSH(tfp);
 
 	switch(cmd) {
@@ -3329,6 +3332,9 @@ new_cmd:  /*
 			 (strcmp(curdoc.address, LYPermitFileURL) ||
 			  strcmp((curdoc.title ? curdoc.title : ""),
 				PERMIT_OPTIONS_TITLE)) &&
+#ifdef OK_INSTALL
+			 strcmp(curdoc.address, LYInstallFileURL) &&
+#endif /* OK_INSTALL */
 			 (strcmp(curdoc.address, LYUploadFileURL) ||
 			  strcmp((curdoc.title ? curdoc.title : ""),
 				UPLOAD_OPTIONS_TITLE))) ||
@@ -3509,7 +3515,9 @@ new_cmd:  /*
 			   *  unescaping of other chars. - KW
 			   */
 			  HTUnEscapeSome(newdoc.address,"/");
-			  strip_trailing_slash(newdoc.address);
+			  /* avoid stripping final slash for root dir - kw */
+			  if (strcasecomp(newdoc.address, "file://localhost/"))
+			      strip_trailing_slash(newdoc.address);
 		    }
 #endif /* DIRED_SUPPORT  && !__DJGPP__ */
 		    if (!strncmp(curdoc.address, "LYNXCOOKIE:", 11)) {
@@ -4738,12 +4746,12 @@ if (!LYUseFormsOptions) {
 	    }
 	    break;
 
-#ifdef DIRED_SUPPORT
+#if defined(DIRED_SUPPORT) && defined(OK_INSTALL)
 	case LYK_INSTALL:  /* install a file into system area */
 	    if (lynx_edit_mode && nlinks > 0 && !no_dired_support)
 		local_install(NULL, links[curdoc.link].lname, &newdoc.address);
 	    break;
-#endif /* DIRED_SUPPORT */
+#endif /* DIRED_SUPPORT && OK_INSTALL */
 
 	case LYK_INFO:	/* show document info */
 	    /*
diff --git a/src/LYOptions.c b/src/LYOptions.c
index 560b29e8..7bc6e1d0 100644
--- a/src/LYOptions.c
+++ b/src/LYOptions.c
@@ -3553,17 +3553,22 @@ PUBLIC int postoptions ARGS1(
 	return(NULLFILE);
     }
 
+    data = break_data(newdoc->post_data);
 
-    /*-------------------------------------------------
-     * kludge gen_options() call:
-     *--------------------------------------------------*/
-
-    if (strstr(newdoc->address, "LYNXOPTIONS:/") && !newdoc->post_data) {
-	int status = gen_options(&newdoc->address);
-	if (status == NOT_FOUND)
-	    return(NOT_FOUND);
+    if (!data) {
+	int status;
+
+	/*-------------------------------------------------
+	 * kludge gen_options() call:
+	 *--------------------------------------------------*/
+	status = gen_options(&newdoc->address);
+	if (status != NORMAL) {
+	    HTAlwaysAlert("Unexpected way of accessing", newdoc->address);
+	    FREE(newdoc->address);
+	    return(status);
+	}
 
-	/* exit to getfile() cyrcle */
+	/* exit to getfile() cycle */
 	WWWDoc.address = newdoc->address;
 	WWWDoc.post_data = newdoc->post_data;
 	WWWDoc.post_content_type = newdoc->post_content_type;
@@ -3576,9 +3581,6 @@ PUBLIC int postoptions ARGS1(
 	return(NORMAL);
     }
 
-
-    data = break_data(newdoc->post_data);
-
     for (i = 0; data[i].tag != NULL; i++) {
 	/*
 	 * Paranoid security.
@@ -4085,13 +4087,17 @@ PRIVATE int gen_options ARGS1(
 #if defined(USE_SLANG) || defined(COLOR_CURSES)
     BOOLEAN can_do_colors;
 #endif
-    static char tempfile[LY_MAXPATH];
+    static char tempfile[LY_MAXPATH] = "\0";
     FILE *fp0;
     size_t cset_len = 0;
     size_t text_len = COLS - 38;	/* cf: PutLabel */
 
-    LYRemoveTemp(tempfile);
-    fp0 = LYOpenTemp(tempfile, HTML_SUFFIX, "w");
+    if (LYReuseTempfiles) {
+	fp0 = LYOpenTempRewrite(tempfile, HTML_SUFFIX, "w");
+    } else {
+	LYRemoveTemp(tempfile);
+	fp0 = LYOpenTemp(tempfile, HTML_SUFFIX, "w");
+    }
     if (fp0 == NULL) {
 	HTAlert(UNABLE_TO_OPEN_TEMPFILE);
 	return(NOT_FOUND);
diff --git a/src/LYPrint.c b/src/LYPrint.c
index 810a1ab7..489e88ae 100644
--- a/src/LYPrint.c
+++ b/src/LYPrint.c
@@ -986,6 +986,7 @@ PRIVATE void send_file_to_screen ARGS3(
     if (Lpansi) {
 	printf("\n\014");	/* Form feed */
 	printf("\033[4i");
+	fflush(stdout);  /* refresh to screen */
 	Lpansi = FALSE;
     } else {
 	fprintf(stdout,"\n\n%s", PRESS_RETURN_TO_FINISH);
@@ -995,7 +996,6 @@ PRIVATE void send_file_to_screen ARGS3(
 	HadVMSInterrupt = FALSE;
 #endif /* VMS */
     }
-    fflush(stdout);  /* refresh to screen */
     start_curses();
 
 done:
@@ -1237,15 +1237,20 @@ PUBLIC int print_options ARGS3(
 	char **,	printed_url,
 	int,		lines_in_file)
 {
-    static char my_temp[LY_MAXPATH];
+    static char my_temp[LY_MAXPATH] = "\0";
     char *buffer = 0;
     int count;
     int pages;
     FILE *fp0;
     lynx_printer_item_type *cur_printer;
 
-    LYRemoveTemp(my_temp);
-    if ((fp0 = LYOpenTemp(my_temp, HTML_SUFFIX, "w")) == NULL) {
+    if (LYReuseTempfiles) {
+	fp0 = LYOpenTempRewrite(my_temp, HTML_SUFFIX, "w");
+    } else {
+	LYRemoveTemp(my_temp);
+	fp0 = LYOpenTemp(my_temp, HTML_SUFFIX, "w");
+    }
+    if (fp0 == NULL) {
 	HTAlert(UNABLE_TO_OPEN_PRINTOP_FILE);
 	return(-1);
     }
diff --git a/src/LYReadCFG.c b/src/LYReadCFG.c
index a8cc016b..5a535ffc 100644
--- a/src/LYReadCFG.c
+++ b/src/LYReadCFG.c
@@ -1181,6 +1181,7 @@ static Config_Type Config_Table [] =
      PARSE_SET("prepend_charset_to_source", CONF_BOOL, &LYPrependCharsetToSource),
      PARSE_FUN("printer", CONF_FUN, printer_fun),
      PARSE_SET("quit_default_yes", CONF_BOOL, &LYQuitDefaultYes),
+     PARSE_SET("reuse_tempfiles", CONF_BOOL, &LYReuseTempfiles),
 #ifndef NO_RULES
      PARSE_FUN("rule", CONF_FUN, HTSetConfiguration),
      PARSE_FUN("rulesfile", CONF_FUN, cern_rulesfile_fun),
diff --git a/src/LYShowInfo.c b/src/LYShowInfo.c
index 56340c16..d7389761 100644
--- a/src/LYShowInfo.c
+++ b/src/LYShowInfo.c
@@ -33,7 +33,7 @@ PUBLIC int showinfo ARGS4(
 	document *,	newdoc,
 	char *, 	owner_address)
 {
-    static char tempfile[LY_MAXPATH];
+    static char tempfile[LY_MAXPATH] = "\0";
     int url_type;
     FILE *fp0;
     char *Address = NULL, *Title = NULL;
@@ -48,8 +48,13 @@ PUBLIC int showinfo ARGS4(
     struct stat dir_info;
 #endif /* DIRED_SUPPORT */
 
-    LYRemoveTemp(tempfile);
-    if ((fp0 = LYOpenTemp (tempfile, HTML_SUFFIX, "w")) == 0) {
+    if (LYReuseTempfiles) {
+	fp0 = LYOpenTempRewrite(tempfile, HTML_SUFFIX, "w");
+    } else {
+	LYRemoveTemp(tempfile);
+	fp0 = LYOpenTemp(tempfile, HTML_SUFFIX, "w");
+    }
+    if (fp0 == NULL) {
 	HTAlert(CANNOT_OPEN_TEMP);
 	return(-1);
     }
diff --git a/src/LYStrings.c b/src/LYStrings.c
index 5fa74a85..01981de5 100644
--- a/src/LYStrings.c
+++ b/src/LYStrings.c
@@ -2737,11 +2737,6 @@ PUBLIC char *LYstrsep ARGS2(
     if (!stringp || !*stringp)		/* nothing to do? */
 	return 0;			/* then don't fall on our faces */
 
-    if (!**stringp) {			/* empty string: */
-	*stringp = 0;			/* let caller see he's done; */
-	return 0;			/* no tokens in an empty string */
-    }
-
     out = *stringp;			/* save the start of the string */
     tmp = strpbrk(*stringp, delim);
     if (tmp) {
diff --git a/src/LYUtils.c b/src/LYUtils.c
index 157cef47..73ff1bf3 100644
--- a/src/LYUtils.c
+++ b/src/LYUtils.c
@@ -17,6 +17,10 @@
 #include <LYMainLoop.h>
 #include <LYKeymap.h>
 
+#ifndef NO_GROUPS
+#include <HTFile.h>
+#endif
+
 #ifdef DJGPP_KEYHANDLER
 #include <bios.h>
 #endif /* DJGPP_KEYHANDLER */
@@ -6114,6 +6118,165 @@ PUBLIC FILE *LYReopenTemp ARGS1(
 }
 
 /*
+ * Open a temp-file for writing, possibly re-using a previously used
+ * name and file.
+ * If a non-empty fname is given, it is reused if it indicates a file
+ * previously registered as a temp file and, in case the file still
+ * exists, if it looks like we can write to it safely.  Otherwise a
+ * new temp file (with new name) will be generated and returned in fname.
+ *
+ * File permissions are set so that the file is not readable by unprivileged
+ * other users.
+ *
+ * Suffix is only used if fname is not being reused.
+ * The mode should be "w", others are possible (they may be passed on)
+ * but probably don't make sense. - kw
+ */
+PUBLIC FILE *LYOpenTempRewrite ARGS3(
+	char *,		fname,
+	CONST char *,	suffix,
+	CONST char *,	mode)
+{
+    FILE *fp = 0;
+    BOOL txt = TRUE;
+    char wrt = 'r';
+    BOOL registered = NO;
+    BOOL writable_exists = NO;
+    BOOL is_ours = NO;
+    BOOL still_open = NO;
+    LY_TEMP *p;
+    struct stat stat_buf;
+
+    CTRACE(tfp, "LYOpenTempRewrite(%s,%s,%s)\n", fname, suffix, mode);
+    if (*fname == '\0')		/* first time, no filename yet */
+	return (LYOpenTemp(fname, suffix, mode));
+
+    for (p = ly_temp; p != 0; p = p->next) {
+	if (!strcmp(fname, p->name)) {
+	    registered = YES;
+	    if (p->file != 0)
+		still_open = YES;
+	    CTRACE(tfp, "...used before%s\n",
+		still_open ? ", still open!" : ".");
+	    break;
+	}
+    }
+
+    if (registered) {
+#ifndef NO_GROUPS
+	writable_exists = HTEditable(fname); /* existing, can write */
+#else
+	writable_exists = (stat(fname, &stat_buf) == 0); /* existing, assume can write */
+#endif
+
+	if (writable_exists) {
+#ifdef UNIX
+	    is_ours = IsOurFile(fname);
+#else
+	    is_ours = TRUE;	/* assume ok, if we get to here */
+#endif
+	}
+	CTRACE(tfp, "...%s%s\n",
+	       writable_exists ?
+#ifndef NO_GROUPS
+	       "exists and is writable, "
+#else
+	       "exists, "
+#endif
+	       : "",
+	       is_ours ? "is our file." : "is NOT our file.");
+    }
+
+    /*
+     *  Note that in cases where LYOpenTemp is called as fallback below,
+     *  we don't call LYRemoveTemp first.  That may be appropriate in some
+     *  cases, but not trying to remove a weird existing file seems safer
+     *  and could help diagnose an unusual situation.  (They may be removed
+     *  anyway later.)
+     */
+    if (still_open) {
+	/*
+	 * This should probably not happen.  Make a new one.
+	 */
+	return (LYOpenTemp(fname, suffix, mode));
+    } else if (is_ours) {
+	/*
+	 *  Yes, it exists, is writable if we checked, and everything
+	 *  looks ok so far.  This should be the most regular case.
+	 *  We truncate and then append, this avoids having a small
+	 *  window in which the file doesn't exist. - kw
+	 */
+	if (truncate(fname, 0) != 0) {
+	    CTRACE(tfp, "... truncate(%s,0) failed: %s\n",
+		   fname, LYStrerror(errno));
+	    return (LYOpenTemp(fname, suffix, mode));
+	} else {
+	    return (LYReopenTemp(fname));
+	}
+    } else if (writable_exists) {
+	/*
+	 *  File exists, writable if we checked, but something is wrong
+	 *  with it.
+	 */
+	return (LYOpenTemp(fname, suffix, mode));
+#ifndef NO_GROUPS
+    } else if (registered && (lstat(fname, &stat_buf) == 0)) {
+	/*
+	 *  Exists but not writable, and something is wrong with it.
+	 */
+	return (LYOpenTemp(fname, suffix, mode));
+#endif
+    } else if (!registered) {
+	/*
+	 *  Not registered.  It should have been registered at one point
+	 *  though, otherwise we wouldn't be called like this.
+	 */
+	return (LYOpenTemp(fname, suffix, mode));
+    } else {
+	/*
+	 *  File does not exist, but is registered as a temp file.
+	 *  It must have been removed by some means other than
+	 *  LYRemoveTemp.  Reuse the name!
+	 */
+    }
+
+    while (*mode != '\0') {
+	switch (*mode++) {
+	case 'w':	wrt = 'w';	break;
+	case 'a':	wrt = 'a';	break;
+	case 'b':	txt = FALSE;	break;
+	default:
+		CTRACE(tfp, "%s @%d: BUG\n", __FILE__, __LINE__);
+		return fp;
+	}
+    }
+
+    if (txt) {
+	switch (wrt) {
+	case 'w':
+	    fp = LYNewTxtFile (fname);
+	    break;
+	case 'a':
+	    fp = LYAppendToTxtFile (fname);
+	    break;
+	}
+    } else {
+	fp = LYNewBinFile (fname);
+    }
+    p->file = fp;
+
+    CTRACE(tfp, "... LYOpenTempRewrite(%s), %s\n", fname,
+	   (fp) ? "ok" : "failed");
+    /*
+     *  We could fall back to trying LYOpenTemp() here in case of failure.
+     *  After all the checks already done above a filure here should be
+     *  pretty unusual though, so maybe it's better to let the user notice
+     *  that something went wrong, and not try to fix it up. - kw
+     */
+    return fp;
+}
+
+/*
  * Special case of LYOpenTemp, used for manipulating bookmark file, i.e., with
  * renaming.
  */
@@ -6536,7 +6699,7 @@ PUBLIC void LYAddPathSep0 ARGS1(
  * Check if a given string contains a path separator
  */
 PUBLIC char * LYLastPathSep ARGS1(
-	char *,		path)
+	CONST char *,	path)
 {
     char *result;
 #ifdef DOSPATH
diff --git a/src/LYUtils.h b/src/LYUtils.h
index 8a8608f3..10cf755b 100644
--- a/src/LYUtils.h
+++ b/src/LYUtils.h
@@ -71,9 +71,10 @@ extern FILE *LYNewBinFile PARAMS((char * name));
 extern FILE *LYNewTxtFile PARAMS((char * name));
 extern FILE *LYOpenScratch PARAMS((char *result, CONST char *prefix));
 extern FILE *LYOpenTemp PARAMS((char *result, CONST char *suffix, CONST char *mode));
+extern FILE *LYOpenTempRewrite PARAMS((char *result, CONST char *suffix, CONST char *mode));
 extern FILE *LYReopenTemp PARAMS((char *name));
 extern char *Current_Dir PARAMS((char * pathname));
-extern char *LYLastPathSep PARAMS((char *path));
+extern char *LYLastPathSep PARAMS((CONST char *path));
 extern char *LYPathLeaf PARAMS((char * pathname));
 extern char *LYSysShell NOPARAMS;
 extern char *LYgetXDisplay NOPARAMS;