about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/GridText.c86
-rw-r--r--src/GridText.h14
-rw-r--r--src/HTAlert.c9
-rw-r--r--src/HTFWriter.c7
-rw-r--r--src/HTML.c135
-rw-r--r--src/LYCharSets.h14
-rw-r--r--src/LYCharUtils.c36
-rw-r--r--src/LYClean.c2
-rw-r--r--src/LYCurses.c65
-rw-r--r--src/LYEditmap.c4
-rw-r--r--src/LYForms.c83
-rw-r--r--src/LYGetFile.c2
-rw-r--r--src/LYGlobalDefs.h78
-rw-r--r--src/LYHistory.c152
-rw-r--r--src/LYHistory.h10
-rw-r--r--src/LYKeymap.c22
-rw-r--r--src/LYKeymap.h9
-rw-r--r--src/LYMain.c355
-rw-r--r--src/LYMainLoop.c208
-rw-r--r--src/LYOptions.c44
-rw-r--r--src/LYReadCFG.c16
-rw-r--r--src/LYStrings.c278
-rw-r--r--src/LYStrings.h94
-rw-r--r--src/LYStyle.c32
-rw-r--r--src/LYUtils.c317
-rw-r--r--src/LYUtils.h17
-rw-r--r--src/TRSTable.c213
-rw-r--r--src/TRSTable.h2
-rw-r--r--src/UCAuto.c230
-rw-r--r--src/UCdomap.c102
-rw-r--r--src/Xsystem.c6
31 files changed, 1849 insertions, 793 deletions
diff --git a/src/GridText.c b/src/GridText.c
index 8c2078d9..ad5abbfe 100644
--- a/src/GridText.c
+++ b/src/GridText.c
@@ -170,7 +170,7 @@ typedef struct _line {
 	char	data[1];		/* Space for terminator at least! */
 } HTLine;
 
-#if defined(USE_COLOR_STYLE) 
+#if defined(USE_COLOR_STYLE)
 typedef struct _HTStyleChangePool {
 	HTStyleChange	data[4092];
 	struct _HTStyleChangePool* next;
@@ -399,7 +399,7 @@ struct _HText {
 
 	HTStream *		target;			/* Output stream */
 	HTStreamClass		targetClass;		/* Output routines */
-#if defined(USE_COLOR_STYLE) 
+#if defined(USE_COLOR_STYLE)
 	HTStyleChangePool*	styles_pool;
 #endif
 };
@@ -921,7 +921,7 @@ PUBLIC void HText_free ARGS1(
 	return;
 
     HTAnchor_setDocument(self->node_anchor, (HyperDoc *)0);
-#if defined(USE_COLOR_STYLE) 
+#if defined(USE_COLOR_STYLE)
     POOL_FREE(HTStyleChangePool,self->styles_pool);
 #endif
     while (YES) {	/* Free off line array */
@@ -1796,13 +1796,11 @@ PRIVATE void display_page ARGS3(
 	LYCursesON) {
 	charset_last_displayed = current_char_set;
 #ifdef EXP_CHARTRANS_AUTOSWITCH
-#ifdef LINUX
 	/*
 	 *  Currently implemented only for LINUX
 	 */
 	UCChangeTerminalCodepage(current_char_set,
 				 &LYCharSet_UC[current_char_set]);
-#endif /* LINUX */
 #endif /* EXP_CHARTRANS_AUTOSWITCH */
     }
 
@@ -2370,7 +2368,7 @@ PRIVATE void split_line ARGS2(
     HTLine * line = (HTLine *)LY_CALLOC(1, LINE_SIZE(MAX_LINE)+2);
     if (line == NULL)
 	outofmem(__FILE__, "split_line_1");
-#if defined(USE_COLOR_STYLE) 
+#if defined(USE_COLOR_STYLE)
     line->styles = stylechanges_buffers[stylechanges_buffers_free = (stylechanges_buffers_free + 1) &1];
 #endif
     ctrl_chars_on_this_line = 0; /*reset since we are going to a new line*/
@@ -2786,7 +2784,7 @@ PRIVATE void split_line ARGS2(
     if (temp == NULL)
 	outofmem(__FILE__, "split_line_2");
     memcpy(temp, previous, LINE_SIZE(previous->size));
-#if defined(USE_COLOR_STYLE) 
+#if defined(USE_COLOR_STYLE)
     ALLOC_IN_POOL((text->styles_pool),HTStyleChangePool,previous->numstyles,temp->styles);
     memcpy(temp->styles, previous->styles, sizeof(HTStyleChange)*previous->numstyles);
     if (!temp->styles)
@@ -3112,7 +3110,7 @@ PRIVATE void split_line ARGS2(
 	    jline = allocHTLine(previous->size+spare);
 	    if (jline == NULL)
 		outofmem(__FILE__, "split_line_1");
-#if defined(USE_COLOR_STYLE) 
+#if defined(USE_COLOR_STYLE)
 	    jline->styles = previous->styles;
 #endif
 	    jdata = jline->data;
@@ -4634,7 +4632,9 @@ PRIVATE int HText_insertBlanksInStblLines ARGS2(
     int *	newpos;
     int		ninserts, lineno;
     int		first_lineno, last_lineno, first_lineno_pass2;
+#ifdef EXP_NESTED_TABLES
     int		last_nonempty = -1;
+#endif
     int		added_chars_before = 0;
     TextAnchor * a;
     int lines_changed = 0;
@@ -4680,8 +4680,8 @@ PRIVATE int HText_insertBlanksInStblLines ARGS2(
 		int ip;
 		CTRACE((tfp, "line %d first to adjust  --  newpos:", lineno));
 		for (ip = 0; ip < ncols; ip++)
-		    fprintf(tfp, " %d", newpos[ip]);
-		fprintf(tfp, "\n");
+		    CTRACE((tfp, " %d", newpos[ip]));
+		CTRACE((tfp, "\n"));
 	    }
 	}
 	if (line == me->last_line) {
@@ -4703,8 +4703,10 @@ PRIVATE int HText_insertBlanksInStblLines ARGS2(
 	    int width = HText_TrueLineSize(line, me, FALSE);
 	    if (width > max_width)
 		max_width = width;
+#ifdef EXP_NESTED_TABLES
 	    if (width && last_nonempty < lineno)
 		last_nonempty = lineno;
+#endif
 	    CTRACE((tfp, "line %d true/max width:%d/%d oldpos: NONE\n",
 		   lineno, width, max_width));
 	    continue;
@@ -4744,15 +4746,17 @@ PRIVATE int HText_insertBlanksInStblLines ARGS2(
 	    int width = HText_TrueLineSize(line, me, FALSE);
 	    if (width > max_width)
 		max_width = width;
+#ifdef EXP_NESTED_TABLES
 	    if (width && last_nonempty < lineno)
 		last_nonempty = lineno;
+#endif
 	    if (TRACE) {
 		int ip;
 		CTRACE((tfp, "line %d true/max width:%d/%d oldpos:",
 		       lineno, width, max_width));
 		for (ip = 0; ip < ninserts; ip++)
-		    fprintf(tfp, " %d", oldpos[ip]);
-		fprintf(tfp, "\n");
+		    CTRACE((tfp, " %d", oldpos[ip]));
+		CTRACE((tfp, "\n"));
 	    }
 	}
     }
@@ -4844,8 +4848,10 @@ PRIVATE int HText_insertBlanksInStblLines ARGS2(
 	    CTRACE((tfp, " %d:%d", lineno, table_offset - line->offset));
 	    line->offset = table_offset;
 	}
+#ifdef EXP_NESTED_TABLES
 	if (max_width)
 	    Stbl_update_enclosing(me->stbl, max_width, last_nonempty);
+#endif
     }
     CTRACE((tfp, " %d:done\n", lineno));
     free(oldpos);
@@ -4868,12 +4874,16 @@ PUBLIC void HText_cancelStbl ARGS1(
 	return;
     }
     CTRACE((tfp, "cancelStbl: ok, will do.\n"));
+#ifdef EXP_NESTED_TABLES
     stbl = me->stbl;
     while (stbl) {
 	STable_info *enclosing = Stbl_get_enclosing(stbl);
 	Stbl_free(stbl);
 	stbl = enclosing;
     }
+#else
+    Stbl_free(me->stbl);
+#endif
     me->stbl = NULL;
 }
 
@@ -4883,16 +4893,25 @@ PUBLIC void HText_startStblTABLE ARGS2(
 	HText *,	me,
 	short,		alignment)
 {
+#ifdef EXP_NESTED_TABLES
     STable_info *current = me->stbl;
+#endif
 
     if (!me)
 	return;
+#ifdef EXP_NESTED_TABLES
     if (current)
 	new_line(me);
+#else
+    if (me->stbl)
+	HText_cancelStbl(me);	/* auto cancel previously open table */
+#endif
     me->stbl = Stbl_startTABLE(alignment);
     if (me->stbl) {
 	CTRACE((tfp, "startStblTABLE: started.\n"));
+#ifdef EXP_NESTED_TABLES
 	Stbl_set_enclosing(me->stbl, current, me->last_anchor_before_stbl);
+#endif
 	me->last_anchor_before_stbl = me->last_anchor;
     } else {
 	CTRACE((tfp, "startStblTABLE: failed.\n"));
@@ -4906,7 +4925,7 @@ PUBLIC int HText_endStblTABLE ARGS1(
 	HText *,	me)
 {
     int ncols, lines_changed = 0;
-    STable_info *enclosing;
+    STable_info *enclosing = NULL;
 
     if (!me || !me->stbl) {
 	CTRACE((tfp, "endStblTABLE: ignored.\n"));
@@ -4925,10 +4944,16 @@ PUBLIC int HText_endStblTABLE ARGS1(
 	NumOfLines_partial -= lines_changed;  /* fake */
 #endif  /* DISP_PARTIAL */
     }
+#ifdef EXP_NESTED_TABLES
     enclosing = Stbl_get_enclosing(me->stbl);
     me->last_anchor_before_stbl = Stbl_get_last_anchor_before(me->stbl);
+#endif
     Stbl_free(me->stbl);
+#ifdef EXP_NESTED_TABLES
     me->stbl = enclosing;
+#else
+    me->stbl = NULL;
+#endif
     return enclosing != 0;
 }
 
@@ -6123,7 +6148,7 @@ re_parse:
 PUBLIC void HText_dump ARGS1(
 	HText *,	text GCC_UNUSED)
 {
-    fprintf(tfp, "HText: Dump called\n");
+    CTRACE((tfp, "HText: Dump called\n"));
 }
 
 
@@ -7285,6 +7310,12 @@ PUBLIC BOOL HText_select ARGS1(
 	}
 #endif /* DISP_PARTIAL */
 
+#ifdef CAN_SWITCH_DISPLAY_CHARSET
+	/* text->UCLYhndl is not reset by META, so use a more circumvent way */
+	if ( text->node_anchor->UCStages->s[UCT_STAGE_HTEXT].LYhndl
+	     != current_char_set )
+	    Switch_Display_Charset(text->node_anchor->UCStages->s[UCT_STAGE_HTEXT].LYhndl, 0);
+#endif
 	if (HTMainText) {
 	    if (HText_hasUTF8OutputSet(HTMainText) &&
 		HTLoadedDocumentEightbit() &&
@@ -9553,24 +9584,24 @@ PUBLIC char * HText_setLastOptionValue ARGS7(
     }
 
     if (TRACE) {
-	fprintf(tfp,"HText_setLastOptionValue:%s value=%s",
+	CTRACE((tfp, "HText_setLastOptionValue:%s value=%s",
 		(order == LAST_ORDER) ? " LAST_ORDER" : "",
-		value);
-	fprintf(tfp,"            val_cs=%d \"%s\"",
+		value));
+	CTRACE((tfp,"            val_cs=%d \"%s\"",
 			val_cs,
 			(val_cs >= 0 ?
-			 LYCharSet_UC[val_cs].MIMEname : "<UNKNOWN>"));
+			 LYCharSet_UC[val_cs].MIMEname : "<UNKNOWN>")));
 	if (submit_value) {
-	    fprintf(tfp, " (submit_val_cs %d \"%s\") submit_value%s=%s\n",
+	    CTRACE((tfp, " (submit_val_cs %d \"%s\") submit_value%s=%s\n",
 		    submit_val_cs,
 		    (submit_val_cs >= 0 ?
 		     LYCharSet_UC[submit_val_cs].MIMEname : "<UNKNOWN>"),
 		    (HTCurSelectGroupType == F_CHECKBOX_TYPE) ?
 						  "(ignored)" : "",
-		    submit_value);
+		    submit_value));
 	}
 	else {
-	    fprintf(tfp,"\n");
+	    CTRACE((tfp,"\n"));
 	}
     }
     return(ret_Value);
@@ -10829,7 +10860,7 @@ PUBLIC int HText_SubmitForm ARGS4(
 
 		    if ((fd = fopen(val_used, "rb")) == 0) {
 			/* We can't open the file, what do we do? */
-			HTAlert("Can't open file for uploading");
+			HTAlert(gettext("Can't open file for uploading"));
 			goto exit_disgracefully;
 		    }
 		    StrAllocCopy(escaped2, "");
@@ -10840,7 +10871,7 @@ PUBLIC int HText_SubmitForm ARGS4(
 		    }
 		    if (ferror(fd)) {
 			/* We got an error reading the file, what do we do? */
-			HTAlert("Short read from file, problem?");
+			HTAlert(gettext("Short read from file, problem?"));
 			LYCloseInput(fd);
 			goto exit_disgracefully;
 		    }
@@ -12357,7 +12388,7 @@ PRIVATE void update_subsequent_anchors ARGS4(
 	}
     }
 
-exit:
+finish:
     /*
      *  Fixup various global variables.
      */
@@ -12374,11 +12405,8 @@ exit:
 
 hang_detected:  /* uglyness has happened; inform user and do the best we can */
 
-    printf ("\007");  /* beep the user */
-    fflush (NULL);
-    HTAlert ("Hang Detect: TextAnchor struct corrupted - suggest aborting!");
-    HTAlert ("Hang Detect: TextAnchor struct corrupted - suggest aborting!");
-    goto exit;
+    HTAlert(gettext("Hang Detect: TextAnchor struct corrupted - suggest aborting!"));
+    goto finish;
 }
 
 
diff --git a/src/GridText.h b/src/GridText.h
index 843e8bd9..47fbeb04 100644
--- a/src/GridText.h
+++ b/src/GridText.h
@@ -61,8 +61,6 @@ extern char * HTCurSelectGroupSize;
 extern HText * HTMainText;		/* Equivalent of main window */
 extern HTParentAnchor * HTMainAnchor;	/* Anchor for HTMainText */
 
-extern int WWW_TraceFlag;
-
 #if defined(VMS) && defined(VAXC) && !defined(__DECC)
 extern int HTVirtualMemorySize;
 #endif /* VMS && VAXC && !__DECC */
@@ -172,16 +170,16 @@ extern int HText_HiddenLinkCount PARAMS((HText *text));
 extern char * HText_HiddenLinkAt PARAMS((HText *text, int number));
 
 /* "simple table" stuff */
-extern void HText_cancelStbl PARAMS((HText *));
-extern void HText_startStblTABLE PARAMS((HText *, short));
 extern int HText_endStblTABLE PARAMS((HText *));
-extern void HText_startStblTR PARAMS((HText *, short));
-extern void HText_endStblTR PARAMS((HText *));
-extern void HText_startStblTD PARAMS((HText *, int, int, short, BOOL));
+extern void HText_cancelStbl PARAMS((HText *));
+extern void HText_endStblCOLGROUP PARAMS((HText *));
 extern void HText_endStblTD PARAMS((HText *));
+extern void HText_endStblTR PARAMS((HText *));
 extern void HText_startStblCOL PARAMS((HText *, int, short, BOOL));
-extern void HText_endStblCOLGROUP PARAMS((HText *));
 extern void HText_startStblRowGroup PARAMS((HText *, short));
+extern void HText_startStblTABLE PARAMS((HText *, short));
+extern void HText_startStblTD PARAMS((HText *, int, int, short, BOOL));
+extern void HText_startStblTR PARAMS((HText *, short));
 
 /* forms stuff */
 extern void HText_beginForm PARAMS((
diff --git a/src/HTAlert.c b/src/HTAlert.c
index cd1d5a56..e9917a1a 100644
--- a/src/HTAlert.c
+++ b/src/HTAlert.c
@@ -145,9 +145,11 @@ PRIVATE char *sprint_bytes ARGS3(
     }
 
     u = kbunits;
-    if ((LYTransferRate == rateKB) && (n >= 10 * kb_units))
+    if ( (LYTransferRate == rateKB || LYTransferRate == rateEtaKB_maybe)
+	 && (n >= 10 * kb_units) )
 	sprintf(s, "%ld", n/kb_units);
-    else if ((LYTransferRate == rateKB) && (n >= kb_units))
+    else if ((LYTransferRate == rateKB || LYTransferRate == rateEtaKB_maybe)
+	     && (n > 999))	/* Avoid switching between 1016b/s and 1K/s */
 	sprintf(s, "%.2g", ((double)n)/kb_units);
     else {
 	sprintf(s, "%ld", n);
@@ -264,6 +266,9 @@ PUBLIC void HTReadProgress ARGS2(
 	    CTRACE((tfp, "%s\n", line));
 	}
     }
+#ifdef LY_FIND_LEAKS
+    FREE(line);
+#endif
 }
 
 PRIVATE BOOL conf_cancelled = NO; /* used by HTConfirm only - kw */
diff --git a/src/HTFWriter.c b/src/HTFWriter.c
index c19dcca3..ff75c6e0 100644
--- a/src/HTFWriter.c
+++ b/src/HTFWriter.c
@@ -1030,7 +1030,6 @@ PUBLIC HTStream* HTCompressed ARGS3(
      *	or a download request, in which case we won't bother to
      *	uncompress the file. - FM
      */
-    CTRACE((tfp, "FIXME %s @%d\n", __FILE__, __LINE__));
     if (!(anchor && anchor->content_encoding && anchor->content_type)) {
 	/*
 	 *  We have no idea what we're dealing with,
@@ -1041,16 +1040,10 @@ PUBLIC HTStream* HTCompressed ARGS3(
 	return me;
     }
     n = HTList_count(HTPresentations);
-    CTRACE((tfp, "FIXME %s @%d\n", __FILE__, __LINE__));
     for (i = 0; i < n; i++) {
 	Pres = (HTPresentation *)HTList_objectAt(HTPresentations, i);
-	CTRACE((tfp, "FIXME %s @%d '%s', '%s' (%s)\n", __FILE__, __LINE__,
-	    Pres->rep->name,
-	    anchor->content_type,
-	    anchor->content_encoding));
 	if (!strcasecomp(Pres->rep->name, anchor->content_type) &&
 	    Pres->rep_out == WWW_PRESENT) {
-    CTRACE((tfp, "FIXME %s @%d\n", __FILE__, __LINE__));
 	    /*
 	     *	We have a presentation mapping for it. - FM
 	     */
diff --git a/src/HTML.c b/src/HTML.c
index e682e451..8973cab0 100644
--- a/src/HTML.c
+++ b/src/HTML.c
@@ -1099,7 +1099,7 @@ PRIVATE int HTML_start_element ARGS6(
 	force_current_tag_style = FALSE;
     }
 
-    CTRACE((tfp, "CSS.elt:<%s>\n", HTML_dtd.tags[element_number].name));
+    CTRACE2(TRACE_STYLE, (tfp, "CSS.elt:<%s>\n", HTML_dtd.tags[element_number].name));
 
     if (current_tag_style == -1) {	/* Append class_name */
 #if !OPT_SCN
@@ -1129,10 +1129,12 @@ PRIVATE int HTML_start_element ARGS6(
 	    if (!hashStyles[hcode].name) { /* None such -> classless version */
 		hcode = ohcode;
 		*oend = '\0';
-		CTRACE((tfp, "STYLE.start_element: <%s> (class <%s> not configured), hcode=%d.\n",
+		CTRACE2(TRACE_STYLE,
+			(tfp, "STYLE.start_element: <%s> (class <%s> not configured), hcode=%d.\n",
 			HTML_dtd.tags[element_number].name, class_name, hcode));
 	    } else {
-		CTRACE((tfp, "STYLE.start_element: <%s>.<%s>, hcode=%d.\n",
+		CTRACE2(TRACE_STYLE,
+			(tfp, "STYLE.start_element: <%s>.<%s>, hcode=%d.\n",
 			HTML_dtd.tags[element_number].name, class_name, hcode));
 		class_used = 1;
 	    }
@@ -1147,25 +1149,23 @@ PRIVATE int HTML_start_element ARGS6(
 #if !OPT_SCN
     if (TRACE)
     {
-	fprintf(tfp, "CSSTRIM:%s -> %d", myHash, hcode);
-	if (hashStyles[hcode].code!=hcode)
-	{
+	CTRACE((tfp, "CSSTRIM:%s -> %d", myHash, hcode));
+	if (hashStyles[hcode].code != hcode) {
 	    char *rp = strrchr(myHash, '.');
-	    fprintf(tfp, " (undefined) %s\n", myHash);
-	    if (rp)
-	    {
+	    CTRACE((tfp, " (undefined) %s\n", myHash));
+	    if (rp) {
 		int hcd;
-		*rp='\0'; /* trim the class */
+		*rp = '\0'; /* trim the class */
 		hcd = hash_code(myHash);
-		fprintf(tfp, "CSS:%s -> %d", myHash, hcd);
+		CTRACE((tfp, "CSS:%s -> %d", myHash, hcd));
 		if (hashStyles[hcd].code!=hcd)
-		    fprintf(tfp, " (undefined) %s\n", myHash);
+		    CTRACE((tfp, " (undefined) %s\n", myHash));
 		else
-		    fprintf(tfp, " ca=%d\n", hashStyles[hcd].color);
+		    CTRACE((tfp, " ca=%d\n", hashStyles[hcd].color));
 	    }
+	} else {
+	    CTRACE((tfp, " ca=%d\n", hashStyles[hcode].color));
 	}
-	else
-	    fprintf(tfp, " ca=%d\n", hashStyles[hcode].color);
     }
 #endif
     } else { /* (current_tag_style!=-1)	 */
@@ -1185,7 +1185,8 @@ PRIVATE int HTML_start_element ARGS6(
 	    class_string[0] = '\0';
 	}
 	hcode = current_tag_style;
-	CTRACE((tfp, "STYLE.start_element: <%s>, hcode=%d.\n",
+	CTRACE2(TRACE_STYLE,
+		(tfp, "STYLE.start_element: <%s>, hcode=%d.\n",
 		HTML_dtd.tags[element_number].name, hcode));
 	current_tag_style = -1;
     }
@@ -1218,10 +1219,13 @@ PRIVATE int HTML_start_element ARGS6(
 	if (!hashStyles[hcode].name) { /* None such -> classless version */
 	    hcode = ohcode;
 	    *oend = '\0';
-	    CTRACE((tfp, "STYLE.start_element: type <%s> not configured.\n", type));
+	    CTRACE2(TRACE_STYLE,
+		    (tfp, "STYLE.start_element: type <%s> not configured.\n",
+			   type));
 	} else {
-	    CTRACE((tfp, "STYLE.start_element: <%s>.type.<%s>, hcode=%d.\n",
-		    HTML_dtd.tags[element_number].name, type, hcode));
+	    CTRACE2(TRACE_STYLE,
+		    (tfp, "STYLE.start_element: <%s>.type.<%s>, hcode=%d.\n",
+			  HTML_dtd.tags[element_number].name, type, hcode));
 	}
     }
 #endif	/* OPT_SCN && !OMIT_SCN_KEEPING */
@@ -1452,9 +1456,8 @@ PRIVATE int HTML_start_element ARGS6(
 #ifndef USE_COLOR_STYLE
 		if (!strcasecomp(value[HTML_LINK_REL], "StyleSheet") ||
 		    !strcasecomp(value[HTML_LINK_REL], "Style")) {
-		    CTRACE((tfp, "HTML: StyleSheet link found.\n"));
-		    CTRACE((tfp,
-				"        StyleSheets not yet implemented.\n"));
+		    CTRACE2(TRACE_STYLE, (tfp, "HTML: StyleSheet link found.\n"));
+		    CTRACE2(TRACE_STYLE, (tfp, "        StyleSheets not yet implemented.\n"));
 		    FREE(href);
 		    break;
 		}
@@ -1654,7 +1657,8 @@ PRIVATE int HTML_start_element ARGS6(
 	    {
 		char *tmp = 0;
 		HTSprintf0(&tmp, "link.%s.%s", value[HTML_LINK_CLASS], title);
-		CTRACE((tfp, "STYLE.link: using style <%s>\n", tmp));
+		CTRACE2(TRACE_STYLE,
+			(tfp, "STYLE.link: using style <%s>\n", tmp));
 
 		HText_characterStyle(me->text, hash_code(tmp), 1);
 		HTML_put_string(me, title);
@@ -5800,7 +5804,9 @@ PRIVATE int HTML_start_element ARGS6(
 	 *  table tracking code.  Cancel tracking, it would only make
 	 *  things worse. - kw
 	 */
-	/* HText_cancelStbl(me->text); ** Not needed with new TRST */
+#ifndef EXP_NESTED_TABLES
+	HText_cancelStbl(me->text);
+#endif
 	if (me->inA) {
 	    SET_SKIP_STACK(HTML_A);
 	    HTML_end_element(me, HTML_A, include);
@@ -6109,7 +6115,8 @@ PRIVATE int HTML_start_element ARGS6(
 
     if (ReallyEmptyTagNum(element_number))
     {
-	CTRACE((tfp, "STYLE.begin_element:ending \"EMPTY\" element style\n"));
+	CTRACE2(TRACE_STYLE,
+		(tfp, "STYLE.begin_element:ending \"EMPTY\" element style\n"));
 	HText_characterStyle(me->text, HCODE_TO_STACK_OFF(hcode), STACK_OFF);
 
 #if !OPT_SCN
@@ -6239,8 +6246,9 @@ PRIVATE int HTML_end_element ARGS3(
 	    (me->sp < (me->stack + MAX_NESTING - 1)))
 	    me->sp[0].tag_number = HTML_OBJECT;
 	if (me->skip_stack > 0) {
-	    CTRACE((tfp, "HTML:end_element: Internal call (level %d), leaving on stack - %s\n",
-		    me->skip_stack, NONNULL(me->sp->style->name)));
+	    CTRACE2(TRACE_STYLE,
+		    (tfp, "HTML:end_element: Internal call (level %d), leaving on stack - %s\n",
+			  me->skip_stack, NONNULL(me->sp->style->name)));
 	    me->skip_stack--;
 	} else if (element_number == HTML_OBJECT &&
 		   me->sp[0].tag_number != HTML_OBJECT &&
@@ -6253,12 +6261,12 @@ PRIVATE int HTML_end_element ARGS3(
 	     *	didn't push because the SGML parser was supposed
 	     *  to go on parsing the contents non-literally. - kw
 	     */
-	    CTRACE((tfp,
-		   "HTML:end_element[%d]: %s (level %d), %s - %s\n",
-		   (int) STACKLEVEL(me),
-		   "Special OBJECT handling", me->objects_mixed_open,
-		   "leaving on stack",
-		   NONNULL(me->sp->style->name)));
+	    CTRACE2(TRACE_STYLE,
+		    (tfp, "HTML:end_element[%d]: %s (level %d), %s - %s\n",
+			   (int) STACKLEVEL(me),
+			   "Special OBJECT handling", me->objects_mixed_open,
+			   "leaving on stack",
+			   NONNULL(me->sp->style->name)));
 	    me->objects_mixed_open--;
 	} else if (me->stack_overrun == TRUE &&
 	    element_number != me->sp[0].tag_number) {
@@ -6315,22 +6323,24 @@ PRIVATE int HTML_end_element ARGS3(
 		     *  so pop the FIG and pretend that's what we are
 		     *  being called for. - kw
 		     */
-		    CTRACE((tfp,
-			"HTML:end_element[%d]: %s (level %d), %s - %s\n",
-			(int) STACKLEVEL(me),
-			"Special OBJECT->FIG handling", me->objects_figged_open,
-			"treating as end FIG",
-			NONNULL(me->sp->style->name)));
+		    CTRACE2(TRACE_STYLE,
+			    (tfp, "HTML:end_element[%d]: %s (level %d), %s - %s\n",
+				  (int) STACKLEVEL(me),
+				  "Special OBJECT->FIG handling",
+				  me->objects_figged_open,
+				  "treating as end FIG",
+				  NONNULL(me->sp->style->name)));
 		    me->objects_figged_open--;
 		    element_number = HTML_FIG;
 		}
 	    }
 	    (me->sp)++;
-	    CTRACE((tfp, "HTML:end_element[%d]: Popped style off stack - %s\n",
-			(int) STACKLEVEL(me),
-			NONNULL(me->sp->style->name)));
+	    CTRACE2(TRACE_STYLE,
+		    (tfp, "HTML:end_element[%d]: Popped style off stack - %s\n",
+			  (int) STACKLEVEL(me),
+			  NONNULL(me->sp->style->name)));
 	} else {
-	    CTRACE((tfp,
+	    CTRACE2(TRACE_STYLE, (tfp,
   "Stack underflow error!  Tried to pop off more styles than exist in stack\n"));
 	}
     }
@@ -6447,8 +6457,9 @@ PRIVATE int HTML_end_element ARGS3(
 	 *  we'll just ignore. - FM
 	 */
 	HTChunkTerminate(&me->style_block);
-	CTRACE((tfp, "HTML: STYLE content =\n%s\n",
-			    me->style_block.data));
+	CTRACE2(TRACE_STYLE,
+		(tfp, "HTML: STYLE content =\n%s\n",
+		      me->style_block.data));
 	HTChunkClear(&me->style_block);
 	break;
 
@@ -7614,6 +7625,9 @@ End_Object:
 	break;
 
     case HTML_TABLE:
+#ifndef EXP_NESTED_TABLES
+	me->inTABLE = FALSE;
+#endif
 	if (!strcmp(me->sp->style->name, "Preformatted")) {
 	    break;
 	}
@@ -7624,7 +7638,11 @@ End_Object:
 				me->DivisionAlignments[me->Division_Level];
 	change_paragraph_style(me, me->sp->style);
 	UPDATE_STYLE;
+#ifdef EXP_NESTED_TABLES
 	me->inTABLE = HText_endStblTABLE(me->text);
+#else
+	HText_endStblTABLE(me->text);
+#endif
 	me->current_default_alignment = me->sp->style->alignment;
 	if (me->List_Nesting_Level >= 0)
 	    HText_NegateLineOne(me->text);
@@ -7720,8 +7738,9 @@ End_Object:
 
 	if (!ReallyEmptyTagNum(element_number))
 	{
-	    CTRACE((tfp, "STYLE.end_element: ending non-\"EMPTY\" style <%s...>\n",
-		    HTML_dtd.tags[element_number].name));
+	    CTRACE2(TRACE_STYLE,
+		    (tfp, "STYLE.end_element: ending non-\"EMPTY\" style <%s...>\n",
+			  HTML_dtd.tags[element_number].name));
 	    HText_characterStyle(me->text, HCODE_TO_STACK_OFF(hcode), STACK_OFF);
 	}
     }
@@ -7891,8 +7910,8 @@ PRIVATE void HTML_free ARGS1(HTStructured *, me)
 		    "Bad HTML: SELECT or OPTION not ended properly *****\n"));
 	if (TRACE) {
 	    HTChunkTerminate(&me->option);
-	    fprintf(tfp, "HTML_free: ***** leftover option data: %s\n",
-		    me->option.data);
+	    CTRACE((tfp, "HTML_free: ***** leftover option data: %s\n",
+			 me->option.data));
 	}
 	HTChunkClear(&me->option);
     }
@@ -7907,8 +7926,8 @@ PRIVATE void HTML_free ARGS1(HTStructured *, me)
 		    "Bad HTML: TEXTAREA not used properly *****\n"));
 	if (TRACE) {
 	    HTChunkTerminate(&me->textarea);
-	    fprintf(tfp, "HTML_free: ***** leftover textarea data: %s\n",
-		    me->textarea.data);
+	    CTRACE((tfp, "HTML_free: ***** leftover textarea data: %s\n",
+			 me->textarea.data));
 	}
 	HTChunkClear(&me->textarea);
     }
@@ -7981,11 +8000,10 @@ PRIVATE void HTML_abort ARGS2(HTStructured *, me, HTError, e)
 	 *  have gone very wrong. - kw
 	 */
 	if (TRACE) {
-	    fprintf(tfp,
-		    "HTML_abort: SELECT or OPTION not ended properly *****\n");
+	    CTRACE((tfp, "HTML_abort: SELECT or OPTION not ended properly *****\n"));
 	    HTChunkTerminate(&me->option);
-	    fprintf(tfp, "HTML_abort: ***** leftover option data: %s\n",
-		    me->option.data);
+	    CTRACE((tfp, "HTML_abort: ***** leftover option data: %s\n",
+			 me->option.data));
 	}
 	HTChunkClear(&me->option);
     }
@@ -7996,11 +8014,10 @@ PRIVATE void HTML_abort ARGS2(HTStructured *, me, HTError, e)
 	 *  have gone very wrong. - kw
 	 */
 	if (TRACE) {
-	    fprintf(tfp,
-		    "HTML_abort: TEXTAREA not used properly *****\n");
+	    CTRACE((tfp, "HTML_abort: TEXTAREA not used properly *****\n"));
 	    HTChunkTerminate(&me->textarea);
-	    fprintf(tfp, "HTML_abort: ***** leftover textarea data: %s\n",
-		    me->textarea.data);
+	    CTRACE((tfp, "HTML_abort: ***** leftover textarea data: %s\n",
+			 me->textarea.data));
 	}
 	HTChunkClear(&me->textarea);
     }
diff --git a/src/LYCharSets.h b/src/LYCharSets.h
index 2f7591c2..d5372e0d 100644
--- a/src/LYCharSets.h
+++ b/src/LYCharSets.h
@@ -96,6 +96,9 @@ extern void init_charset_subsets NOPARAMS;
 #if !defined(NO_AUTODETECT_DISPLAY_CHARSET)
 #  ifdef __EMX__
 #    define CAN_AUTODETECT_DISPLAY_CHARSET
+#    ifdef EXP_CHARTRANS_AUTOSWITCH
+#      define CAN_SWITCH_DISPLAY_CHARSET
+#    endif
 #  endif
 #endif
 
@@ -103,4 +106,15 @@ extern void init_charset_subsets NOPARAMS;
 extern int auto_display_charset;
 #endif
 
+#ifdef CAN_SWITCH_DISPLAY_CHARSET
+extern int Switch_Display_Charset PARAMS((int ord, int really));
+extern int Find_Best_Display_Charset PARAMS((int ord));
+extern char *charsets_directory;
+extern char *charset_switch_rules;
+extern int switch_display_charsets;
+extern int auto_other_display_charset;
+extern int codepages[2];
+extern int real_charsets[2];	/* Non "auto-" charsets for the codepages */
+#endif
+
 #endif /* LYCHARSETS_H */
diff --git a/src/LYCharUtils.c b/src/LYCharUtils.c
index 87b5b728..6bb34184 100644
--- a/src/LYCharUtils.c
+++ b/src/LYCharUtils.c
@@ -2834,6 +2834,29 @@ PUBLIC void LYHandleMETA ARGS4(
 	    *cp4 = '\0';
 	    cp4 = cp3;
 	    chndl = UCGetLYhndl_byMIME(cp3);
+
+#ifdef CAN_SWITCH_DISPLAY_CHARSET
+	    /* Allow a switch to a more suitable display charset */
+	    if (Switch_Display_Charset (chndl, 0)) {
+		/* UCT_STAGE_STRUCTURED and UCT_STAGE_HTEXT
+		   should have the same setting for UCInfoStage. */
+		int structured = HTAnchor_getUCInfoStage(me->node_anchor,
+							 UCT_STAGE_STRUCTURED);
+		me->outUCLYhndl = current_char_set;
+		HTAnchor_setUCInfoStage(me->node_anchor,
+					current_char_set,
+					UCT_STAGE_HTEXT,
+					UCT_SETBY_MIME); /* highest priorty! */
+		HTAnchor_setUCInfoStage(me->node_anchor,
+					current_char_set,
+					UCT_STAGE_STRUCTURED,
+					UCT_SETBY_MIME); /* highest priorty! */
+		me->outUCI = HTAnchor_getUCInfoStage(me->node_anchor,
+						     UCT_STAGE_HTEXT);
+		/* The SGML stage will be reset in change_chartrans_handling */
+	    }
+#endif
+
 	    if (UCCanTranslateFromTo(chndl, current_char_set)) {
 		chartrans_ok = YES;
 		StrAllocCopy(me->node_anchor->charset, cp4);
@@ -3595,16 +3618,15 @@ PUBLIC int LYLegitimizeHREF ARGS4(
 	    !strncmp(path, "/..", 3)) {
 	    cp = (path + 3);
 	    if (LYIsHtmlSep(*cp) || *cp == '\0') {
-		if ((me->inBASE ?
-	       me->base_href[4] : me->node_anchor->address[4]) == 's') {
+		if ((me->inBASE
+		   ? me->base_href[4]
+		   : me->node_anchor->address[4]) == 's') {
 		    str = "s";
 		}
 		if (TRACE) {
-		    fprintf(tfp,
-			 "LYLegitimizeHREF: Bad value '%s' for http%s URL.\n",
-			   *href, str);
-		    fprintf(tfp,
-			 "                  Stripping lead dots.\n");
+		    CTRACE((tfp, "LYLegitimizeHREF: Bad value '%s' for http%s URL.\n",
+				 *href, str);)
+		    CTRACE((tfp, "                  Stripping lead dots.\n"));
 		} else if (!me->inBadHREF) {
 		    HTUserMsg(BAD_PARTIAL_REFERENCE);
 		    me->inBadHREF = TRUE;
diff --git a/src/LYClean.c b/src/LYClean.c
index cb6a5c91..22bb32cb 100644
--- a/src/LYClean.c
+++ b/src/LYClean.c
@@ -172,12 +172,10 @@ PUBLIC void cleanup NOARGS
     }
 
 #ifdef EXP_CHARTRANS_AUTOSWITCH
-#ifdef LINUX
     /*
      *	Currently implemented only for LINUX: Restore original font.
      */
     UCChangeTerminalCodepage(-1, (LYUCcharset*)0);
-#endif /* LINUX */
 #endif /* EXP_CHARTRANS_AUTOSWITCH */
 
 #ifdef EXP_PERSISTENT_COOKIES
diff --git a/src/LYCurses.c b/src/LYCurses.c
index c9f8c16b..fe9642b6 100644
--- a/src/LYCurses.c
+++ b/src/LYCurses.c
@@ -377,7 +377,7 @@ PUBLIC void setHashStyle ARGS5(
 {
     bucket* ds = &hashStyles[style];
 
-    CTRACE((tfp, "CSS(SET): <%s> hash=%d, ca=%#x, ma=%#x\n", element, style, color, mono));
+    CTRACE2(TRACE_STYLE, (tfp, "CSS(SET): <%s> hash=%d, ca=%#x, ma=%#x\n", element, style, color, mono));
 
     ds->color = color;
     ds->cattr = cattr;
@@ -398,15 +398,15 @@ PRIVATE int LYAttrset ARGS3(
     if (lynx_has_color
      && LYShowColor >= SHOW_COLOR_ON
      && color >= 0) {
-	CTRACE((tfp, "CSS:LYAttrset color (%s)\n", attr_to_string(color)));
+	CTRACE2(TRACE_STYLE, (tfp, "CSS:LYAttrset color (%s)\n", attr_to_string(color)));
 	wattrset(win, color);
 	return color;
     } else if (mono >= 0) {
-	CTRACE((tfp, "CSS:LYAttrset mono (%s)\n", attr_to_string(mono)));
+	CTRACE2(TRACE_STYLE, (tfp, "CSS:LYAttrset mono (%s)\n", attr_to_string(mono)));
 	wattrset(win, mono);
 	return mono;
     } else {
-	CTRACE((tfp, "CSS:LYAttrset (A_NORMAL)\n"));
+	CTRACE2(TRACE_STYLE, (tfp, "CSS:LYAttrset (A_NORMAL)\n"));
 	wattrset(win, A_NORMAL);
 	return A_NORMAL;
     }
@@ -433,13 +433,13 @@ PRIVATE void curses_w_style ARGS3(
 
 
     if (!ds->name) {
-	CTRACE((tfp, "CSS.CS:Style %d not configured\n",style));
+	CTRACE2(TRACE_STYLE, (tfp, "CSS.CS:Style %d not configured\n",style));
 #if !OMIT_SCN_KEEPING
 	return;
 #endif
     }
 
-    CTRACE((tfp, "CSS.CS:<%s%s> (%d)\n",(dir?"":"/"),ds->name,ds->code));
+    CTRACE2(TRACE_STYLE, (tfp, "CSS.CS:<%s%s> (%d)\n",(dir?"":"/"),ds->name,ds->code));
 
     getyx (win, YP, XP);
 
@@ -463,7 +463,7 @@ PRIVATE void curses_w_style ARGS3(
 
     case STACK_ON: /* remember the current attributes */
 	if (last_colorattr_ptr > 127) {
-	    CTRACE((tfp,"........... %s (0x%x) %s\r\n",
+	    CTRACE2(TRACE_STYLE, (tfp,"........... %s (0x%x) %s\r\n",
 			"attribute cache FULL, dropping last",
 			last_styles[last_colorattr_ptr],
 			"in LynxChangeStyle(curses_w_style)"));
@@ -488,7 +488,7 @@ PRIVATE void curses_w_style ARGS3(
 	     && style != s_aedit_sel
 	     && style != s_aedit_pad
 	     && style != s_aedit_arr ) {
-	    CTRACE((tfp, "CACHED: <%s> @(%d,%d)\n", ds->name, YP, XP));
+	    CTRACE2(TRACE_STYLE, (tfp, "CACHED: <%s> @(%d,%d)\n", ds->name, YP, XP));
 	    if (win == LYwin) cached_styles[YP][XP] = style;
 	}
 	LYAttrset(win, ds->color, ds->mono);
@@ -508,14 +508,14 @@ PUBLIC void wcurses_css ARGS3(
 
     while (try_again) {
 	int tmpHash = hash_code(name);
-	CTRACE((tfp, "CSSTRIM:trying to set [%s] style - ", name));
+	CTRACE2(TRACE_STYLE, (tfp, "CSSTRIM:trying to set [%s] style - ", name));
 	if (tmpHash == NOSTYLE) {
 	    char *class = strrchr(name, '.');
-	    CTRACE((tfp, "undefined, trimming at %p\n", class));
+	    CTRACE2(TRACE_STYLE, (tfp, "undefined, trimming at %p\n", class));
 	    if (class)	*class = '\0';
 	    else	try_again = 0;
 	} else {
-	    CTRACE((tfp, "ok (%d)\n", hash_code(name)));
+	    CTRACE2(TRACE_STYLE, (tfp, "ok (%d)\n", hash_code(name)));
 	    curses_w_style(win, hash_code(name), dir);
 	    try_again = 0;
 	}
@@ -669,7 +669,7 @@ PUBLIC int lynx_chg_color ARGS3(
 PUBLIC void lynx_set_color ARGS1(int, a)
 {
     if (lynx_has_color && LYShowColor >= SHOW_COLOR_ON) {
-	attrset(lynx_color_cfg[a].attr
+	wattrset(LYwin, lynx_color_cfg[a].attr
 		| (((a+1) < COLOR_PAIRS)
 			? COLOR_PAIR(a+1)
 			: A_NORMAL));
@@ -742,7 +742,7 @@ PUBLIC void LYnoVideo ARGS1(
  * If newterm is not defined, assume a curses subset which
  * supports only initscr.  --gil
  */
-#if defined(HAVE_NEWTERM) && defined(HAVE_DELSCREEN) && !defined(NCURSES) && !defined(HAVE_RESIZETERM)
+#if defined(HAVE_NEWTERM) && defined(HAVE_DELSCREEN) && !(defined(NCURSES) && defined(HAVE_RESIZETERM))
 static SCREEN *LYscreen = NULL;
 #define LYDELSCR() { \
 if (recent_sizechange) { \
@@ -901,25 +901,32 @@ PUBLIC void start_curses NOARGS
 	 *  and one time only!
 	 */
 #if defined(HAVE_NEWTERM)
-#if !defined(NCURSES) && !defined(HAVE_RESIZETERM)
-	/*
-	 * Put screen geometry in environment variables used by
-	 * XOpen curses before calling newterm().  I believe this
-	 * completes work left unfinished by AJL & FM -- gil
-	 */
-	static char lines_putenv[] = "LINES=abcde",
-		    cols_putenv[]  = "COLUMNS=abcde";
+#if !(defined(NCURSES) && !defined(HAVE_RESIZETERM))
 	BOOLEAN savesize;
 
 	savesize = recent_sizechange;
 	size_change(0);
 	recent_sizechange = savesize;    /* avoid extra redraw */
-	sprintf(lines_putenv + 6, "%d", LYlines & 0xfff);
-	sprintf(cols_putenv  + 8, "%d", LYcols  & 0xfff);
-	putenv(lines_putenv);
-	putenv(cols_putenv);
-	CTRACE((tfp, "start_curses putenv %s, %s\n", lines_putenv, cols_putenv));
-#endif /* !defined(NCURSES) && !defined(HAVE_RESIZETERM) */
+#if defined(__MVS__)
+	{
+	    /*
+	     * The requirement to do this may be a bug in OS/390.
+	     *
+	     * Put screen geometry in environment variables used by
+	     * XOpen curses before calling newterm().  I believe this
+	     * completes work left unfinished by AJL & FM -- gil
+	     */
+	    static char lines_putenv[] = "LINES=abcde",
+			cols_putenv[]  = "COLUMNS=abcde";
+
+	    sprintf(lines_putenv + 6, "%d", LYlines & 0xfff);
+	    sprintf(cols_putenv  + 8, "%d", LYcols  & 0xfff);
+	    putenv(lines_putenv);
+	    putenv(cols_putenv);
+	    CTRACE((tfp, "start_curses putenv %s, %s\n", lines_putenv, cols_putenv));
+	}
+#endif /* defined(__MVS__) */
+#endif /* !(defined(NCURSES) && defined(HAVE_RESIZETERM)) */
 	if (!(LYscreen = newterm(NULL,stdout,stdin))) {  /* start curses */
 	    fprintf(tfp, "%s\n",
 		gettext("Terminal initialisation failed - unknown terminal type?"));
@@ -1523,7 +1530,7 @@ PUBLIC void LYwaddnstr ARGS3(
     if (TRACE) {
 	int y, x;
 	LYGetYX(y, x);
-	CTRACE((tfp, "[%2d,%2d] LYwaddnstr(%.*s)\n", y, x, (int) len, s));
+	CTRACE2(TRACE_STYLE, (tfp, "[%2d,%2d] LYwaddnstr(%.*s)\n", y, x, (int) len, s));
     }
 #endif
     while (len > 0) {
@@ -2108,7 +2115,7 @@ PUBLIC void lynx_force_repaint NOARGS
     wbkgd(LYwin, a | ' ');
 #endif
 #endif
-    attrset(a);
+    wattrset(LYwin, a);
 #endif /* COLOR_CURSES */
     clearok(curscr, TRUE);
 }
diff --git a/src/LYEditmap.c b/src/LYEditmap.c
index 44ae1cbb..6ddffe04 100644
--- a/src/LYEditmap.c
+++ b/src/LYEditmap.c
@@ -49,7 +49,7 @@ LYE_NOP,        LYE_ENTER,      LYE_FORWW,      LYE_ABORT,
 LYE_BACKW,      LYE_NOP,        LYE_DELN,       LYE_NOP,
 /* ^P           XON             ^R              XOFF    */
 
-#ifdef WIN_EX
+#ifdef CAN_CUT_AND_PASTE
 LYE_UPPER,      LYE_ERASE,      LYE_LKCMD,      LYE_PASTE,
 #else
 LYE_UPPER,      LYE_ERASE,      LYE_LKCMD,      LYE_NOP,
@@ -295,7 +295,7 @@ LYE_NOP,        LYE_ENTER,      LYE_FORWW,      LYE_ABORT,
 LYE_BACKW,      LYE_NOP,        LYE_DELPW,      LYE_NOP,
 /* ^P           XON             ^R              XOFF    */
 
-#ifdef WIN_EX
+#ifdef CAN_CUT_AND_PASTE
 LYE_DELNW,      LYE_ERASE,      LYE_LKCMD,      LYE_PASTE,
 #else
 LYE_DELNW,      LYE_ERASE,      LYE_LKCMD,      LYE_NOP,
diff --git a/src/LYForms.c b/src/LYForms.c
index 9fd54d06..cc5ccf1e 100644
--- a/src/LYForms.c
+++ b/src/LYForms.c
@@ -6,10 +6,9 @@
 #include <GridText.h>
 #include <LYCharSets.h>
 #include <UCAux.h>
+#include <LYGlobalDefs.h>
 #include <LYUtils.h>
-#include <LYStructs.h>  /* includes HTForms.h */
 #include <LYStrings.h>
-#include <LYGlobalDefs.h>
 #include <LYKeymap.h>
 #include <LYClean.h>
 
@@ -600,56 +599,64 @@ again:
 	    break;
 	}
 
-#if defined(WIN_EX)	/* 1998/10/01 (Thu) 19:19:22 */
-
-#define FORM_PASTE_MAX	8192
-
+#ifdef CAN_CUT_AND_PASTE	/* 1998/10/01 (Thu) 19:19:22 */
 	if (action == LYE_PASTE) {
-	    unsigned char buff[FORM_PASTE_MAX];
-	    int i, len;
+	    unsigned char *s = get_clip_grab(), *e;
+	    char *buf = NULL;
+	    int len;
 
-	    len = get_clip(buff, FORM_PASTE_MAX);
+	    if (!s)
+		break;
+	    len = strlen(s);
+	    e = s + len;
 
 	    if (len > 0) {
-		i = 0;
-		while ((ch = buff[i]) != '\0') {
+		unsigned char *e1 = s;
 
-		    if (ch == '\r') {
-			i++;
-			continue;
-		    }
-		    if (ch == '\n') {
-			i++;
-			len = strlen(buff + i);
-			if (len > 0) {
-			    put_clip(buff + i);
-			}
-			break;
-		    }
-
-		    LYLineEdit(&MyEdit, ch, TRUE);
-
-		    if (MyEdit.strlen >= max_length) {
-			HaveMaxlength = TRUE;
-		    } else if (HaveMaxlength &&
-			       MyEdit.strlen < max_length) {
-			HaveMaxlength = FALSE;
-			_statusline(ENTER_TEXT_ARROWS_OR_TAB);
-		    }
-		    i++;
+		while (e1 < e) {
+		    if (*e1 < ' ') { /* Stop here? */
+			if (e1 > s)
+			    LYEditInsert(&MyEdit, s, e1 - s, -1, TRUE);
+			s = e1;
+			if (*e1 == '\t') { /* Replace by space */
+			    LYEditInsert(&MyEdit, " ", 1, -1, TRUE);
+			    s = ++e1;
+			} else
+			    break;
+		    } else
+			++e1;
+		}
+		if (e1 > s)
+		    LYEditInsert(&MyEdit, s, e1 - s, -1, TRUE);
+		while (e1 < e && *e1 == '\r')
+		    e1++;
+		if (e1 + 1 < e && *e1 == '\n')
+		    StrAllocCopy(buf, e1 + 1);	/* Survive _release() */
+		get_clip_release();
+		if (MyEdit.strlen >= max_length) {
+		    HaveMaxlength = TRUE;
+		} else if (HaveMaxlength &&
+			   MyEdit.strlen < max_length) {
+		    HaveMaxlength = FALSE;
+		    _statusline(ENTER_TEXT_ARROWS_OR_TAB);
 		}
 		if (strcmp(value, MyEdit.buffer) != 0) {
 		    Edited = TRUE;
 		}
+		if (buf) {
+		    put_clip(buf);
+		    FREE(buf);
+		    ch = '\n';		/* Sometimes moves to the next line */
+		    break;
+		}
 		LYRefreshEdit(&MyEdit);
-
 	    } else {
 		HTInfoMsg("Clipboard empty or Not text data.");
-		return(DO_NOTHING);
+		continue;
 	    }
-	    break;
 	}
-#else
+#endif
+#ifndef WIN_EX
 	if (action == LYE_AIX &&
 	    (HTCJK == NOCJK && LYlowest_eightbit[current_char_set] > 0x97))
 	    break;
diff --git a/src/LYGetFile.c b/src/LYGetFile.c
index 35ab4619..3ea3e2b9 100644
--- a/src/LYGetFile.c
+++ b/src/LYGetFile.c
@@ -831,7 +831,7 @@ Try_Redirected_URL:
 			    LYrefresh();
 			}
 #endif /* USE_SLANG */
-			fprintf(tfp,"\n");
+			CTRACE((tfp, "\n"));
 		    }
 		    if (!HTLoadAbsolute(&WWWDoc)) {
 			/*
diff --git a/src/LYGlobalDefs.h b/src/LYGlobalDefs.h
index 0900f6d3..3f754c7c 100644
--- a/src/LYGlobalDefs.h
+++ b/src/LYGlobalDefs.h
@@ -140,6 +140,12 @@ typedef enum {
 #endif
 } TransferRate;
 
+#ifdef EXP_READPROGRESS
+#  define rateEtaKB_maybe	rateEtaKB
+#else
+#  define rateEtaKB_maybe	rateKB
+#endif
+
 extern BOOLEAN LYCursesON;  	/* start_curses()->TRUE, stop_curses()->FALSE */
 extern BOOLEAN LYJumpFileURL;   /* URL from the jump file shortcuts? */
 extern BOOLEAN LYNewsPosting;	/* News posting supported if TRUE */
@@ -167,6 +173,7 @@ extern BOOLEAN is_www_index;
 extern BOOLEAN jump_buffer;     /* TRUE if offering default shortcut */
 extern BOOLEAN long_url_ok;
 extern BOOLEAN lynx_mode;
+extern BOOLEAN more;		/* is there more document to display? */
 extern BOOLEAN news_ok;
 extern BOOLEAN recent_sizechange;
 extern BOOLEAN rlogin_ok;
@@ -206,35 +213,24 @@ extern int display_lines;	/* number of lines in the display */
 extern int dump_output_width;
 extern int keypad_mode;		/* NUMBERS_AS_ARROWS or LINKS_ARE_NUMBERED */
 extern int lynx_temp_subspace;
-extern BOOLEAN more;		/* is there more document to display? */
 extern int user_mode;		/* novice or advanced */
 extern int www_search_result;
 
-extern BOOLEAN had_restrictions_default; /* flags to note whether we have... */
+extern BOOLEAN exec_frozen;
 extern BOOLEAN had_restrictions_all;     /* parsed these restriction options */
-extern BOOLEAN no_inside_telnet;  /* this and following are restrictions */
-extern BOOLEAN no_outside_telnet;
-extern BOOLEAN no_telnet_port;
-extern BOOLEAN no_inside_news;
-extern BOOLEAN no_outside_news;
-extern BOOLEAN no_inside_ftp;
-extern BOOLEAN no_outside_ftp;
-extern BOOLEAN no_inside_rlogin;
-extern BOOLEAN no_outside_rlogin;
-extern BOOLEAN no_suspend;
-extern BOOLEAN no_editor;
-extern BOOLEAN no_shell;
+extern BOOLEAN had_restrictions_default; /* flags to note whether we have... */
 extern BOOLEAN no_bookmark;
-extern BOOLEAN no_multibook;
 extern BOOLEAN no_bookmark_exec;
-extern BOOLEAN no_option_save;
-extern BOOLEAN no_download;
-extern BOOLEAN no_print;          /* TRUE to disable printing */
+extern BOOLEAN no_chdir;
+extern BOOLEAN no_compileopts_info;
 extern BOOLEAN no_disk_save;
+extern BOOLEAN no_dotfiles;
+extern BOOLEAN no_download;
+extern BOOLEAN no_editor;
 extern BOOLEAN no_exec;
-extern BOOLEAN no_lynxcgi;
-extern BOOLEAN exec_frozen;
+extern BOOLEAN no_file_url;
 extern BOOLEAN no_goto;
+extern BOOLEAN no_goto_configinfo;
 extern BOOLEAN no_goto_cso;
 extern BOOLEAN no_goto_file;
 extern BOOLEAN no_goto_finger;
@@ -253,20 +249,27 @@ extern BOOLEAN no_goto_snews;
 extern BOOLEAN no_goto_telnet;
 extern BOOLEAN no_goto_tn3270;
 extern BOOLEAN no_goto_wais;
-extern BOOLEAN no_goto_configinfo;
+extern BOOLEAN no_inside_ftp;
+extern BOOLEAN no_inside_news;
+extern BOOLEAN no_inside_rlogin;
+extern BOOLEAN no_inside_telnet;  /* this and following are restrictions */
 extern BOOLEAN no_jump;
-extern BOOLEAN no_file_url;
-extern BOOLEAN no_newspost;
-extern BOOLEAN no_mail;
-extern BOOLEAN no_dotfiles;
-extern BOOLEAN no_useragent;
 extern BOOLEAN no_lynxcfg_info;
-#ifndef NO_CONFIG_INFO
 extern BOOLEAN no_lynxcfg_xinfo;
-#ifdef HAVE_CONFIG_H
-extern BOOLEAN no_compileopts_info;
-#endif
-#endif
+extern BOOLEAN no_lynxcgi;
+extern BOOLEAN no_mail;
+extern BOOLEAN no_multibook;
+extern BOOLEAN no_newspost;
+extern BOOLEAN no_option_save;
+extern BOOLEAN no_outside_ftp;
+extern BOOLEAN no_outside_news;
+extern BOOLEAN no_outside_rlogin;
+extern BOOLEAN no_outside_telnet;
+extern BOOLEAN no_print;          /* TRUE to disable printing */
+extern BOOLEAN no_shell;
+extern BOOLEAN no_suspend;
+extern BOOLEAN no_telnet_port;
+extern BOOLEAN no_useragent;
 
 extern BOOLEAN no_statusline;
 extern BOOLEAN no_filereferer;
@@ -293,9 +296,10 @@ extern BOOLEAN nolist;
 extern BOOLEAN historical_comments;
 extern BOOLEAN minimal_comments;
 extern BOOLEAN soft_dquotes;
+
 #ifdef SOURCE_CACHE
-extern int LYCacheSource;
 extern BOOLEAN source_cache_file_error;
+extern int LYCacheSource;
 #define SOURCE_CACHE_NONE	0
 #define SOURCE_CACHE_FILE	1
 #define SOURCE_CACHE_MEMORY	2
@@ -304,6 +308,7 @@ extern int LYCacheSourceForAborted;
 #define SOURCE_CACHE_FOR_ABORTED_KEEP 1
 #define SOURCE_CACHE_FOR_ABORTED_DROP 0
 #endif
+
 extern BOOLEAN LYCancelDownload;
 extern BOOLEAN LYRestricted;	/* whether we had -anonymous option */
 extern BOOLEAN LYValidate;
@@ -423,10 +428,7 @@ extern BOOLEAN LYSeekFragAREAinCur;
 extern BOOLEAN LYSeekFragMAPinCur;
 extern BOOLEAN LYStripDotDotURLs;	/* Try to fix ../ in some URLs?  */
 extern BOOLEAN LYUseBuiltinSuffixes;
-extern BOOLEAN LYUseTraceLog;		/* Use a TRACE log?		 */
 extern BOOLEAN dont_wrap_pre;
-extern FILE *LYTraceLogFP;		/* Pointer for TRACE log	 */
-extern char *LYTraceLogPath;		/* Path for TRACE log		 */
 extern char *MBM_A_subbookmark[MBM_V_MAXFILES+1];
 extern char *MBM_A_subdescript[MBM_V_MAXFILES+1];
 
@@ -443,6 +445,12 @@ extern int justify_max_void_percent;
 extern BOOLEAN with_backspaces;
 #endif
 
+#ifndef NO_LYNX_TRACE
+extern BOOLEAN LYUseTraceLog;		/* Use a TRACE log?		 */
+extern FILE *LYTraceLogFP;		/* Pointer for TRACE log	 */
+extern char *LYTraceLogPath;		/* Path for TRACE log		 */
+#endif
+
 extern BOOL force_empty_hrefless_a;
 extern int connect_timeout;
 
diff --git a/src/LYHistory.c b/src/LYHistory.c
index 3592724d..31d39c92 100644
--- a/src/LYHistory.c
+++ b/src/LYHistory.c
@@ -38,6 +38,8 @@ PRIVATE VisitedLink *Latest_tree;
 PRIVATE VisitedLink *First_tree;
 PRIVATE VisitedLink *Last_by_first;
 
+PRIVATE int nhist_extra;
+
 #ifdef LY_FIND_LEAKS
 /*
  *  Utility for freeing the list of visited links. - FM
@@ -66,6 +68,20 @@ PRIVATE void Visited_Links_free NOARGS
 }
 #endif /* LY_FIND_LEAKS */
 
+#ifdef DEBUG
+PRIVATE void trace_history ARGS1(
+	CONST char *,	tag)
+{
+    if (TRACE) {
+	CTRACE((tfp, "HISTORY %s %d/%d (%d extra)\n",
+		     tag, nhist, MAXHIST, nhist_extra));
+	CTRACE_FLUSH(tfp);
+    }
+}
+#else
+#define trace_history(tag) /* nothing */
+#endif /* DEBUG */
+
 /*
  *  Utility for listing visited links, making any repeated
  *  links the most current in the list. - FM
@@ -254,9 +270,41 @@ PUBLIC BOOLEAN LYwouldPush ARGS2(
 }
 
 /*
+ *  Free the information in the last history entry.
+ */
+PRIVATE void clean_extra NOARGS
+{
+    trace_history("clean_extra");
+    nhist += nhist_extra;
+    while (nhist_extra > 0) {
+	nhist--;
+	FREE(history[nhist].title);
+	FREE(history[nhist].address);
+	FREE(history[nhist].post_data);
+	FREE(history[nhist].post_content_type);
+	FREE(history[nhist].bookmark);
+	nhist_extra--;
+    }
+    trace_history("...clean_extra");
+}
+
+/* What is the relationship to are_different() from the mainloop?! */
+PRIVATE int are_identical ARGS2(
+	histstruct *,	doc,
+	document *,	doc1)
+{
+     return (	STREQ(doc1->address, doc->address)
+		&& !strcmp(doc1->post_data ? doc1->post_data : "",
+			   doc->post_data ?  doc->post_data : "")
+		&& !strcmp(doc1->bookmark ? doc1->bookmark : "",
+			   doc->bookmark ?  doc->bookmark : "")
+		&& doc1->isHEAD == doc->isHEAD );
+}
+
+/*
  *  Push the current filename, link and line number onto the history list.
  */
-PUBLIC void LYpush ARGS2(
+PUBLIC int LYpush ARGS2(
 	document *,	doc,
 	BOOLEAN,	force_push)
 {
@@ -264,7 +312,7 @@ PUBLIC void LYpush ARGS2(
      *	Don't push NULL file names.
      */
     if (*doc->address == '\0')
-	return;
+	return 0;
 
     /*
      *	Check whether this is a document we
@@ -277,48 +325,59 @@ PUBLIC void LYpush ARGS2(
 	if (!LYwouldPush(doc->title, doc->address)) {
 	    if (!LYforce_no_cache)
 		LYoverride_no_cache = TRUE;
-	    return;
+	    return 0;
 	}
     }
 
     /*
      *	If file is identical to one before it, don't push it.
      */
-    if (nhist> 1 &&
-	STREQ(history[nhist-1].address, doc->address) &&
-	!strcmp(history[nhist-1].post_data ?
-		history[nhist-1].post_data : "",
-		doc->post_data ?
-		doc->post_data : "") &&
-	!strcmp(history[nhist-1].bookmark ?
-		history[nhist-1].bookmark : "",
-		doc->bookmark ?
-		doc->bookmark : "") &&
-	history[nhist-1].isHEAD == doc->isHEAD) {
+    if ( nhist > 1 && are_identical(&(history[nhist-1]), doc)) {
 	if (history[nhist-1].internal_link == doc->internal_link) {
 	    /* But it is nice to have the last position remembered!
 	       - kw */
 	    history[nhist-1].link = doc->link;
 	    history[nhist-1].line = doc->line;
-	    return;
+	    return 0;
 	}
     }
+
+    /*
+     *	If file is identical to the current document, just move the pointer.
+     */
+    if ( nhist_extra >= 1 && are_identical(&(history[nhist]), doc)) {
+	history[nhist].link = doc->link;
+	history[nhist].line = doc->line;
+	nhist_extra--;
+	nhist++;
+	trace_history("LYpush: just move the cursor");
+	return 1;
+    }
+
+    clean_extra();
+
     /*
      *	OK, push it if we have stack space.
      */
     if (nhist < MAXHIST)  {
 	history[nhist].link = doc->link;
 	history[nhist].line = doc->line;
+
 	history[nhist].title = NULL;
 	LYformTitle(&(history[nhist].title), doc->title);
+
 	history[nhist].address = NULL;
 	StrAllocCopy(history[nhist].address, doc->address);
+
 	history[nhist].post_data = NULL;
 	StrAllocCopy(history[nhist].post_data, doc->post_data);
+
 	history[nhist].post_content_type = NULL;
 	StrAllocCopy(history[nhist].post_content_type, doc->post_content_type);
+
 	history[nhist].bookmark = NULL;
 	StrAllocCopy(history[nhist].bookmark, doc->bookmark);
+
 	history[nhist].isHEAD = doc->isHEAD;
 	history[nhist].safe = doc->safe;
 
@@ -417,6 +476,7 @@ PUBLIC void LYpush ARGS2(
 	CTRACE((tfp, "\nLYpush: MAXHIST reached for:\n        address:%s\n        title:%s\n",
 		    doc->address, doc->title));
     }
+    return 1;
 }
 
 /*
@@ -426,6 +486,7 @@ PUBLIC void LYpop ARGS1(
 	document *,	doc)
 {
     if (nhist > 0) {
+	clean_extra();
 	nhist--;
 	doc->link = history[nhist].link;
 	doc->line = history[nhist].line;
@@ -452,6 +513,61 @@ PUBLIC void LYpop ARGS1(
 }
 
 /*
+ *  Move to the previous filename, link and line number from the history list.
+ */
+PUBLIC void LYhist_prev ARGS1(
+	document *,	doc)
+{
+    trace_history("LYhist_prev");
+    if (nhist > 0 && (nhist_extra || nhist < MAXHIST)) {
+	nhist--;
+	nhist_extra++;
+	LYpop_num(nhist, doc);
+	trace_history("...LYhist_prev");
+    }
+}
+
+/*
+ *  Called before calling LYhist_prev().
+ */
+PUBLIC void LYhist_prev_register ARGS1(
+	document *,	doc)
+{
+    trace_history("LYhist_prev_register");
+    if (nhist > 1) {
+	if (nhist_extra) {	/* Make something to return back */
+	    /* Store the new position */
+	    history[nhist].link = doc->link;
+	    history[nhist].line = doc->line;
+	} else if (nhist < MAXHIST) { /* push will fail */
+	    if (LYpush(doc, 0)) {
+		nhist--;
+		nhist_extra++;
+	    }
+	}
+	trace_history("...LYhist_prev_register");
+    }
+}
+
+/*
+ *  Move to the next filename, link and line number from the history list.
+ */
+PUBLIC int LYhist_next ARGS2(
+	document *,	doc,
+	document *,	newdoc)
+{
+    if (nhist_extra <= 1)	/* == 1 when we are the last one */
+	return 0;
+    /* Store the new position */
+    history[nhist].link = doc->link;
+    history[nhist].line = doc->line;
+    nhist++;
+    nhist_extra--;
+    LYpop_num(nhist, newdoc);
+    return 1;
+}
+
+/*
  *  Pop the specified hist entry, link and line number from the history
  *  list but don't actually remove the entry, just return it.
  *  (This procedure is badly named :)
@@ -460,7 +576,7 @@ PUBLIC void LYpop_num ARGS2(
 	int,		number,
 	document *,	doc)
 {
-    if (number >= 0 && nhist > number) {
+    if (number >= 0 && nhist + nhist_extra > number) {
 	doc->link = history[number].link;
 	doc->line = history[number].line;
 	StrAllocCopy(doc->title, history[number].title);
@@ -513,7 +629,7 @@ PUBLIC int showhistory ARGS1(
     fprintf(fp0, "<pre>\n");
 
     fprintf(fp0, "<em>%s</em>\n", gettext("You selected:"));
-    for (x = nhist-1; x >= 0; x--) {
+    for (x = nhist + nhist_extra - 1; x >= 0; x--) {
 	/*
 	 *  The number of the document in the hist stack,
 	 *  its title in a link, and its address. - FM
@@ -573,7 +689,7 @@ PUBLIC BOOLEAN historytarget ARGS1(
 	strlen(newdoc->address) < 10 || !isdigit(UCH(*(newdoc->address+9))))
 	return(FALSE);
 
-    if ((number = atoi(newdoc->address+9)) > nhist || number < 0)
+    if ((number = atoi(newdoc->address+9)) > nhist + nhist_extra || number < 0)
 	return(FALSE);
 
     /*
diff --git a/src/LYHistory.h b/src/LYHistory.h
index f929e1d1..fecb67f9 100644
--- a/src/LYHistory.h
+++ b/src/LYHistory.h
@@ -8,14 +8,16 @@
 extern BOOLEAN LYwouldPush PARAMS((CONST char *title, CONST char *docurl));
 extern BOOLEAN historytarget PARAMS((document *newdoc));
 extern int LYShowVisitedLinks PARAMS((char **newfile));
+extern int LYhist_next PARAMS((document *doc, document *newdoc));
+extern int LYpush PARAMS((document *doc, BOOLEAN force_push));
 extern int showhistory PARAMS((char **newfile));
 extern void LYAddVisitedLink PARAMS((document *doc));
+extern void LYhist_prev PARAMS((document *doc));
+extern void LYhist_prev_register PARAMS((document *doc));
 extern void LYpop PARAMS((document *doc));
 extern void LYpop_num PARAMS((int number, document *doc));
-extern void LYpush PARAMS((document *doc, BOOLEAN force_push));
-
-extern void LYstore_message2 PARAMS((CONST char *message, CONST char *argument));
-extern void LYstore_message PARAMS((CONST char *message));
 extern void LYstatusline_messages_on_exit PARAMS((char **buf));
+extern void LYstore_message PARAMS((CONST char *message));
+extern void LYstore_message2 PARAMS((CONST char *message, CONST char *argument));
 
 #endif /* LYHISTORY_H */
diff --git a/src/LYKeymap.c b/src/LYKeymap.c
index 0508710c..75549f98 100644
--- a/src/LYKeymap.c
+++ b/src/LYKeymap.c
@@ -1,7 +1,7 @@
 #include <HTUtils.h>
 #include <LYUtils.h>
-#include <LYKeymap.h>
 #include <LYGlobalDefs.h>
+#include <LYKeymap.h>
 #include <LYCharSets.h>		/* for LYlowest_eightbit - kw */
 #include <HTAccess.h>
 #include <HTFormat.h>
@@ -742,6 +742,9 @@ PRIVATE Kcmd revmap[] = {
 	LYK_PREV_DOC, "PREV_DOC",
 	"go back to the previous document" ),
     DATA(
+	LYK_NEXT_DOC, "NEXT_DOC",
+	"undo going back to the previous document" ),
+    DATA(
 	LYK_ACTIVATE, "ACTIVATE",
 	"go to the document given by the current link" ),
     DATA(
@@ -930,9 +933,6 @@ PRIVATE Kcmd revmap[] = {
     DATA(
 	LYK_CHG_CENTER, "CHANGE_CENTER",
 	"toggle center alignment in HTML TABLE" ),
-    DATA(
-	LYK_TO_CLIPBOARD, "TO_CLIPBOARD",
-	"link's URL to Clip Board" ),
 #endif
 #ifdef KANJI_CODE_OVERRIDE
     DATA(
@@ -956,6 +956,14 @@ PRIVATE Kcmd revmap[] = {
 	LYK_LINEWRAP_TOGGLE, "LINEWRAP_TOGGLE",
 	"toggle linewrap on/off" ),
 #endif
+#ifdef CAN_CUT_AND_PASTE
+    DATA(
+	LYK_PASTE_URL, "PASTE_URL",
+	"Goto the URL in the clipboard" ),
+    DATA(
+	LYK_TO_CLIPBOARD, "TO_CLIPBOARD",
+	"link's URL to Clip Board" ),
+#endif
     DATA(
 	LYK_UNKNOWN, NULL,
 	"" )
@@ -1047,9 +1055,9 @@ PRIVATE struct emap ekmap[] = {
   {"SETMARK",	LYE_SETMARK,	"emacs-like set-mark-command"},
   {"XPMARK",	LYE_XPMARK,	"emacs-like exchange-point-and-mark"},
   {"KILLREG",	LYE_KILLREG,	"emacs-like kill-region"},
-  {"YANK",	LYE_YANK,	"emacs-like yank"}
-#if defined(WIN_EX)
-, {"PASTE",	LYE_PASTE,	"ClipBoard to Lynx"}
+  {"YANK",	LYE_YANK,	"emacs-like yank"},
+#ifdef CAN_CUT_AND_PASTE
+  {"PASTE",	LYE_PASTE,	"ClipBoard to Lynx"},
 #endif
 };
 
diff --git a/src/LYKeymap.h b/src/LYKeymap.h
index a207a702..8d783f7f 100644
--- a/src/LYKeymap.h
+++ b/src/LYKeymap.h
@@ -155,6 +155,7 @@ typedef enum {
   , LYK_LEFT_LINK
   , LYK_HISTORY
   , LYK_PREV_DOC
+  , LYK_NEXT_DOC
   , LYK_ACTIVATE
   , LYK_SUBMIT	/* mostly like LYK_ACTIVATE, for mouse use, don't map */
   , LYK_GOTO
@@ -236,7 +237,6 @@ typedef enum {
 
 #ifdef SH_EX
   , LYK_CHG_CENTER
-  , LYK_TO_CLIPBOARD
 #endif /* SH_EX */
 
 #ifdef KANJI_CODE_OVERRIDE
@@ -257,6 +257,13 @@ typedef enum {
 #define LYK_LINEWRAP_TOGGLE LYK_UNKNOWN
 #endif
 
+#ifdef CAN_CUT_AND_PASTE
+  , LYK_PASTE_URL
+  , LYK_TO_CLIPBOARD
+#else
+#define LYK_PASTE_URL      LYK_UNKNOWN
+#define LYK_TO_CLIPBOARD   LYK_UNKNOWN
+#endif
 } LYKeymapCode;
 
 /*
diff --git a/src/LYMain.c b/src/LYMain.c
index 2a7abe38..371bc591 100644
--- a/src/LYMain.c
+++ b/src/LYMain.c
@@ -209,34 +209,19 @@ PUBLIC BOOLEAN system_editor = FALSE;
 
 PUBLIC BOOLEAN had_restrictions_default = FALSE;
 PUBLIC BOOLEAN had_restrictions_all = FALSE;
-#ifdef USE_EXTERNALS
-PUBLIC BOOLEAN no_externals = FALSE;
-#endif
-PUBLIC BOOLEAN no_inside_telnet = FALSE;
-PUBLIC BOOLEAN no_outside_telnet = FALSE;
-PUBLIC BOOLEAN no_telnet_port = FALSE;
-#ifndef DISABLE_NEWS
-PUBLIC BOOLEAN no_inside_news = FALSE;
-PUBLIC BOOLEAN no_outside_news = FALSE;
-#endif
-PUBLIC BOOLEAN no_inside_ftp = FALSE;
-PUBLIC BOOLEAN no_outside_ftp = FALSE;
-PUBLIC BOOLEAN no_inside_rlogin = FALSE;
-PUBLIC BOOLEAN no_outside_rlogin = FALSE;
-PUBLIC BOOLEAN no_suspend = FALSE;
-PUBLIC BOOLEAN no_editor = FALSE;
-PUBLIC BOOLEAN no_shell = FALSE;
+
+PUBLIC BOOLEAN exec_frozen = FALSE;
 PUBLIC BOOLEAN no_bookmark = FALSE;
-PUBLIC BOOLEAN no_multibook = FALSE;
 PUBLIC BOOLEAN no_bookmark_exec = FALSE;
-PUBLIC BOOLEAN no_option_save = FALSE;
-PUBLIC BOOLEAN no_print = FALSE;
-PUBLIC BOOLEAN no_download = FALSE;
+PUBLIC BOOLEAN no_chdir = FALSE;
 PUBLIC BOOLEAN no_disk_save = FALSE;
+PUBLIC BOOLEAN no_dotfiles = NO_DOT_FILES;
+PUBLIC BOOLEAN no_download = FALSE;
+PUBLIC BOOLEAN no_editor = FALSE;
 PUBLIC BOOLEAN no_exec = FALSE;
-PUBLIC BOOLEAN no_lynxcgi = FALSE;
-PUBLIC BOOLEAN exec_frozen = FALSE;
+PUBLIC BOOLEAN no_file_url = FALSE;
 PUBLIC BOOLEAN no_goto = FALSE;
+PUBLIC BOOLEAN no_goto_configinfo = FALSE;
 PUBLIC BOOLEAN no_goto_cso = FALSE;
 PUBLIC BOOLEAN no_goto_file = FALSE;
 PUBLIC BOOLEAN no_goto_finger = FALSE;
@@ -248,27 +233,41 @@ PUBLIC BOOLEAN no_goto_lynxcgi = FALSE;
 PUBLIC BOOLEAN no_goto_lynxexec = FALSE;
 PUBLIC BOOLEAN no_goto_lynxprog = FALSE;
 PUBLIC BOOLEAN no_goto_mailto = FALSE;
-#ifndef DISABLE_NEWS
-PUBLIC BOOLEAN no_goto_news = FALSE;
-PUBLIC BOOLEAN no_goto_nntp = FALSE;
-#endif
 PUBLIC BOOLEAN no_goto_rlogin = FALSE;
-#ifndef DISABLE_NEWS
-PUBLIC BOOLEAN no_goto_snews = FALSE;
-#endif
 PUBLIC BOOLEAN no_goto_telnet = FALSE;
 PUBLIC BOOLEAN no_goto_tn3270 = FALSE;
 PUBLIC BOOLEAN no_goto_wais = FALSE;
-PUBLIC BOOLEAN no_goto_configinfo = FALSE;
+PUBLIC BOOLEAN no_inside_ftp = FALSE;
+PUBLIC BOOLEAN no_inside_rlogin = FALSE;
+PUBLIC BOOLEAN no_inside_telnet = FALSE;
 PUBLIC BOOLEAN no_jump = FALSE;
-PUBLIC BOOLEAN no_file_url = FALSE;
+PUBLIC BOOLEAN no_lynxcfg_info = FALSE;
+PUBLIC BOOLEAN no_lynxcgi = FALSE;
+PUBLIC BOOLEAN no_mail = FALSE;
+PUBLIC BOOLEAN no_multibook = FALSE;
+PUBLIC BOOLEAN no_option_save = FALSE;
+PUBLIC BOOLEAN no_outside_ftp = FALSE;
+PUBLIC BOOLEAN no_outside_rlogin = FALSE;
+PUBLIC BOOLEAN no_outside_telnet = FALSE;
+PUBLIC BOOLEAN no_print = FALSE;
+PUBLIC BOOLEAN no_shell = FALSE;
+PUBLIC BOOLEAN no_suspend = FALSE;
+PUBLIC BOOLEAN no_telnet_port = FALSE;
+PUBLIC BOOLEAN no_useragent = FALSE;
+
 #ifndef DISABLE_NEWS
+PUBLIC BOOLEAN no_goto_news = FALSE;
+PUBLIC BOOLEAN no_goto_nntp = FALSE;
+PUBLIC BOOLEAN no_goto_snews = FALSE;
+PUBLIC BOOLEAN no_inside_news = FALSE;
 PUBLIC BOOLEAN no_newspost = FALSE;
+PUBLIC BOOLEAN no_outside_news = FALSE;
 #endif
-PUBLIC BOOLEAN no_mail = FALSE;
-PUBLIC BOOLEAN no_dotfiles = NO_DOT_FILES;
-PUBLIC BOOLEAN no_useragent = FALSE;
-PUBLIC BOOLEAN no_lynxcfg_info = FALSE;
+
+#ifdef USE_EXTERNALS
+PUBLIC BOOLEAN no_externals = FALSE;
+#endif
+
 #ifndef NO_CONFIG_INFO
 PUBLIC BOOLEAN no_lynxcfg_xinfo = FALSE;
 #ifdef HAVE_CONFIG_H
@@ -427,7 +426,7 @@ PUBLIC char *LYCookieSQueryCheckDomains = NULL;  /* check w/a query */
 #ifndef DISABLE_BIBP
 PUBLIC BOOLEAN no_goto_bibp = FALSE;
 PUBLIC char *BibP_globalserver = NULL;   /* global server for bibp: links */
-PUBLIC char *BibP_bibhost = NULL;        /* local server for bibp: links  */
+PUBLIC char *BibP_bibhost = NULL;	 /* local server for bibp: links  */
 PUBLIC BOOLEAN BibP_bibhost_checked = FALSE;  /*  until LYCheckBibHost   */
 PUBLIC BOOLEAN BibP_bibhost_available = FALSE;  /* until check succeeds  */
 #endif
@@ -437,7 +436,7 @@ BOOLEAN persistent_cookies = FALSE;	/* disabled by default! */
 PUBLIC char *LYCookieFile = NULL;	/* cookie read file */
 PUBLIC char *LYCookieSaveFile = NULL;	/* cookie save file */
 #endif /* EXP_PERSISTENT_COOKIES */
-PUBLIC int LYTransferRate = rateKB;
+PUBLIC int LYTransferRate = rateEtaKB_maybe;
 PUBLIC char *XLoadImageCommand = NULL;	/* Default image viewer for X */
 PUBLIC BOOLEAN LYNoISMAPifUSEMAP = FALSE; /* Omit ISMAP link if MAP present? */
 PUBLIC int LYHiddenLinks = HIDDENLINKS_SEPARATE; /* Show hidden links? */
@@ -497,12 +496,6 @@ PUBLIC BOOLEAN LYUseBuiltinSuffixes = TRUE;
 PUBLIC int LYNoZapKey = 0; /* 0: off (do z checking), 1: full, 2: initially */
 #endif
 
-/* These are declared in cutil.h for current freeWAIS libraries. - FM */
-#ifdef DECLARE_WAIS_LOGFILES
-PUBLIC char *log_file_name = NULL; /* for WAIS log file name	in libWWW */
-PUBLIC FILE *logfile = NULL;	   /* for WAIS log file output	in libWWW */
-#endif /* DECLARE_WAIS_LOGFILES */
-
 #ifndef DISABLE_NEWS
 extern int HTNewsChunkSize; /* Number of news articles per chunk (HTNews.c) */
 extern int HTNewsMaxChunk;  /* Max news articles before chunking (HTNews.c) */
@@ -541,6 +534,7 @@ PRIVATE BOOLEAN no_options_further=FALSE; /* set to TRUE after '--' argument */
 
 PRIVATE BOOL parse_arg PARAMS((char **arg, unsigned mask, int *i));
 PRIVATE void print_help_and_exit PARAMS((int exit_status)) GCC_NORETURN;
+PRIVATE void print_help_strings PARAMS((CONST char * name, CONST char * help, CONST char * value, BOOLEAN option));
 
 #ifndef VMS
 PUBLIC BOOLEAN LYNoCore = NO_FORCED_CORE_DUMP;
@@ -831,7 +825,7 @@ PRIVATE BOOL cleanup_win32(DWORD fdwCtrlType)
     switch (fdwCtrlType) {
     case CTRL_CLOSE_EVENT:
 	cleanup_sig(-1);
-    	return TRUE;
+	return TRUE;
     default:
 	return FALSE;
     }
@@ -1189,9 +1183,11 @@ PUBLIC int main ARGS2(
      *	file, if specified, NOW.  Also, if we only want
      *	the help menu, output that and exit. - FM
      */
+#ifndef NO_LYNX_TRACE
     if (getenv("LYNX_TRACE") != 0) {
 	WWW_TraceFlag = TRUE;
     }
+#endif
     for (i = 1; i < argc; i++) {
 	parse_arg(&argv[i], 2, &i);
     }
@@ -1519,6 +1515,10 @@ PUBLIC int main ARGS2(
 	}
 	LYStdinArgs_free();
     }
+#ifdef CAN_SWITCH_DISPLAY_CHARSET
+    if (current_char_set == auto_display_charset) /* Better: explicit option */
+	switch_display_charsets = 1;
+#endif
 
 #undef TTY_DEVICE
 #undef NUL_DEVICE
@@ -2542,7 +2542,7 @@ PRIVATE int display_charset_fun ARGS1(
     int i = UCGetLYhndl_byMIME(next_arg);
 
 #ifdef CAN_AUTODETECT_DISPLAY_CHARSET
-    if (i < 0 && !stricmp(next_arg,"auto"))
+    if (i < 0 && !strcasecomp(next_arg, "auto"))
 	i = auto_display_charset;
 #endif
     if (i < 0) {	/* do nothing here: so fallback to lynx.cfg */
@@ -2839,100 +2839,179 @@ PRIVATE int post_data_fun ARGS1(
 PRIVATE int restrictions_fun ARGS1(
 	char *,			next_arg)
 {
-    static CONST char *Usage[] = {
- ""
-,"   USAGE: lynx -restrictions=[option][,option][,option]"
-,"   List of Options:"
-,"   ?               when used alone, list restrictions in effect."
-,"   all             restricts all options."
-,"   bookmark        disallow changing the location of the bookmark file."
-,"   bookmark_exec   disallow execution links via the bookmark file"
+    static CONST struct {
+	CONST char *name;
+	CONST char *help;
+    } table[] = {
+	{ "all", "restricts all options." },
+	{ "bookmark", "disallow changing the location of the bookmark file" },
+	{ "bookmark_exec", "disallow execution links via the bookmark file" },
 #if defined(DIRED_SUPPORT) && defined(OK_PERMIT)
-,"   change_exec_perms  disallow changing the eXecute permission on files"
-,"                   (but still allow it for directories) when local file"
-,"                   management is enabled."
+	{ "change_exec_perms", "\
+disallow changing the eXecute permission on files\n\
+(but still allow it for directories) when local file\n\
+management is enabled." },
 #endif /* DIRED_SUPPORT && OK_PERMIT */
 #if defined(HAVE_CONFIG_H) && !defined(NO_CONFIG_INFO)
-,"   compileopts_info  disable info on options used to compile the binary"
-#endif
-,"   default         same as commandline option -anonymous.  Sets the"
-,"                   default service restrictions for anonymous users.  Set to"
-,"                   all restricted, except for: inside_telnet, outside_telnet,"
-,"                   inside_ftp, outside_ftp, inside_rlogin, outside_rlogin,"
-,"                   inside_news, outside_news, telnet_port, jump, mail, print,"
-,"                   exec, and goto.  The settings for these, as well as"
-,"                   additional goto restrictions for specific URL schemes"
-,"                   that are also applied, are derived from definitions"
-,"                   within userdefs.h."
+	{ "compileopts_info", "\
+disable info on options used to compile the binary" },
+#endif
+{ "default", "\
+same as commandline option -anonymous.  Sets the\n\
+default service restrictions for anonymous users.  Set to\n\
+all restricted, except for: inside_telnet, outside_telnet,\n\
+inside_ftp, outside_ftp, inside_rlogin, outside_rlogin,\n\
+inside_news, outside_news, telnet_port, jump, mail, print,\n\
+exec, and goto.  The settings for these, as well as\n\
+additional goto restrictions for specific URL schemes\n\
+that are also applied, are derived from definitions\n\
+within userdefs.h." },
 #ifdef DIRED_SUPPORT
-,"   dired_support   disallow local file management"
+	{ "dired_support", "disallow local file management" },
 #endif /* DIRED_SUPPORT */
-,"   disk_save       disallow saving to disk in the download and print menus"
-,"   dotfiles        disallow access to, or creation of, hidden (dot) files"
-,"   download        disallow some downloaders in the download menu"
-,"   editor          disallow editing"
-,"   exec            disable execution scripts"
-,"   exec_frozen     disallow the user from changing the execution link option"
+	{ "disk_save", "disallow saving to disk in the download and print menus" },
+	{ "dotfiles", "disallow access to, or creation of, hidden (dot) files" },
+	{ "download", "disallow some downloaders in the download menu" },
+	{ "editor", "disallow editing" },
+	{ "exec", "disable execution scripts" },
+	{ "exec_frozen", "disallow the user from changing the execution link option" },
 #ifdef USE_EXTERNALS
-,"   externals       disable passing URLs to some external programs"
+	{ "externals", "disable passing URLs to some external programs" },
 #endif
-,"   file_url        disallow using G)oto, served links or bookmarks for"
-,"                   file: URL's"
-,"   goto            disable the 'g' (goto) command"
+	{ "file_url", "\
+disallow using G)oto, served links or bookmarks for\n\
+file: URL's" },
+	{ "goto", "disable the 'g' (goto) command" },
 #if !defined(HAVE_UTMP) || defined(VMS) /* not selective */
-,"   inside_ftp      disallow ftps for people coming from inside your"
-,"                   domain (utmp required for selectivity)"
-,"   inside_news     disallow USENET news reading and posting for people coming"
-,"                   from inside your domain (utmp required for selectivity)"
-,"   inside_rlogin   disallow rlogins for people coming from inside your"
-,"                   domain (utmp required for selectivity)"
-,"   inside_telnet   disallow telnets for people coming from inside your"
-,"                   domain (utmp required for selectivity)"
+	{ "inside_ftp", "\
+disallow ftps coming from inside your\n\
+domain (utmp required for selectivity)" },
+	{ "inside_news", "\
+disallow USENET news reading and posting coming\n\
+from inside your domain (utmp required for selectivity)" },
+	{ "inside_rlogin", "\
+disallow rlogins coming from inside your\n\
+domain (utmp required for selectivity)" },
+	{ "inside_telnet", "\
+disallow telnets coming from inside your\n\
+domain (utmp required for selectivity)" },
 #else
-,"   inside_ftp      disallow ftps for people coming from inside your domain"
-,"   inside_news     disallow USENET news reading and posting for people coming"
-,"                   from inside your domain"
-,"   inside_rlogin   disallow rlogins for people coming from inside your domain"
-,"   inside_telnet   disallow telnets for people coming from inside your domain"
+	{ "inside_ftp", "\
+disallow ftps coming from inside your domain" },
+	{ "inside_news", "\
+disallow USENET news reading and posting coming\n\
+from inside your domain" },
+	{ "inside_rlogin", "\
+disallow rlogins coming from inside your domain" },
+	{ "inside_telnet", "\
+disallow telnets coming from inside your domain" },
 #endif /* HAVE_UTMP || VMS */
-,"   jump            disable the 'j' (jump) command"
-,"   lynxcfg_info    disable viewing of lynx.cfg configuration file info"
+	{ "jump", "disable the 'j' (jump) command" },
+	{ "lynxcfg_info", "\
+disable viewing of lynx.cfg configuration file info" },
 #ifndef NO_CONFIG_INFO
-,"   lynxcfg_xinfo   disable extended lynx.cfg viewing and reloading"
+	{ "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"
+	{ "mail", "disallow mail" },
+	{ "multibook", "disallow multiple bookmark files" },
+	{ "news_post", "disallow USENET News posting." },
+	{ "option_save", "disallow saving options in .lynxrc" },
 #if !defined(HAVE_UTMP) || defined(VMS) /* not selective */
-,"   outside_ftp     disallow ftps for people coming from outside your"
-,"                   domain (utmp required for selectivity)"
-,"   outside_news    disallow USENET news reading and posting for people coming"
-,"                   from outside your domain (utmp required for selectivity)"
-,"   outside_rlogin  disallow rlogins for people coming from outside your"
-,"                   domain (utmp required for selectivity)"
-,"   outside_telnet  disallow telnets for people coming from outside your"
-,"                   domain (utmp required for selectivity)"
+	{ "outside_ftp", "\
+disallow ftps coming from outside your\n\
+domain (utmp required for selectivity)" },
+	{ "outside_news", "\
+disallow USENET news reading and posting coming\n\
+from outside your domain (utmp required for selectivity)" },
+	{ "outside_rlogin", "\
+disallow rlogins coming from outside your\n\
+domain (utmp required for selectivity)" },
+	{ "outside_telnet", "\
+disallow telnets coming from outside your\n\
+domain (utmp required for selectivity)" },
 #else
-,"   outside_ftp     disallow ftps for people coming from outside your domain"
-,"   outside_news    disallow USENET news reading and posting for people coming"
-,"                   from outside your domain"
-,"   outside_rlogin  disallow rlogins for people coming from outside your domain"
-,"   outside_telnet  disallow telnets for people coming from outside your domain"
+	{ "outside_ftp", "\
+disallow ftp coming from outside your domain" },
+	{ "outside_news", "\
+disallow USENET news reading and posting coming\n\
+from outside your domain" },
+	{ "outside_rlogin", "\
+disallow rlogins coming from outside your domain" },
+	{ "outside_telnet", "\
+disallow telnets coming from outside your domain" },
 #endif /* !HAVE_UTMP || VMS */
-,"   print           disallow most print options"
-,"   shell           disallow shell escapes, and lynxexec, lynxprog or lynxcgi"
-,"                   G)oto's"
-,"   suspend         disallow Control-Z suspends with escape to shell"
-,"   telnet_port     disallow specifying a port in telnet G)oto's"
-,"   useragent       disallow modifications of the User-Agent header"
+	{ "print", "disallow most print options" },
+	{ "shell", "\
+disallow shell escapes, and lynxexec, lynxprog or lynxcgi\n\
+G)oto's" },
+	{ "suspend", "disallow Control-Z suspends with escape to shell" },
+	{ "telnet_port", "disallow specifying a port in telnet G)oto's" },
+	{ "useragent", "disallow modifications of the User-Agent header" },
     };
-    size_t n;
+    static CONST char *Usage[] = {
+ ""
+,"USAGE: lynx -restrictions=[option][,option][,option]"
+,"List of Options:"
+,"  ?                 when used alone, list restrictions in effect."
+
+    };
+    unsigned j, k, column = 0;
+    CONST char *name;
+    CONST char *value;
+    BOOLEAN found, first;
 
     if (next_arg == 0 || *next_arg == '\0') {
 	SetOutputMode( O_TEXT );
-	for (n = 0; n < TABLESIZE(Usage); n++)
-	    printf("%s\n", Usage[n]);
+	for (j = 0; j < TABLESIZE(Usage); j++) {
+	    printf("%s\n", Usage[j]);
+	}
+	for (j = 0; j < TABLESIZE(table); j++) {
+	    if (!strcmp(table[j].name, "all")
+	     || !strcmp(table[j].name, "default")) {
+		value = NULL;
+	    } else {
+		switch (find_restriction(table[j].name, -1)) {
+		case TRUE:
+		    value = "on";
+		    break;
+		case FALSE:
+		    value = "off";
+		    break;
+		default:
+		    value = "?";
+		    break;
+		}
+	    }
+	    print_help_strings (
+		table[j].name, table[j].help, value, FALSE);
+	}
+	first = TRUE;
+	for (j = 0; ; j++) {
+	    found = FALSE;
+	    if ((name = index_to_restriction(j)) == 0) {
+		break;
+	    }
+	    for (k = 0; k < TABLESIZE(table); k++) {
+		if (!strcmp(name, table[k].name)) {
+		    found = TRUE;
+		}
+	    }
+	    if (!found) {
+		if (first) {
+		    printf("Other restrictions (see the user's guide):\n");
+		}
+		printf("%s%s", column ? ", " : "  ", name);
+		column += 2 + strlen(name);
+		if (column > 50) {
+		    column = 0;
+		    printf("\n");
+		}
+		first = FALSE;
+	    }
+	}
+	if (column)
+	    printf("\n");
 	SetOutputMode( O_BINARY );
 	exit(EXIT_SUCCESS);
     } else if (*next_arg == '?') {
@@ -2998,11 +3077,11 @@ PRIVATE int version_fun ARGS1(
 #ifdef OPENSSL_VERSION_TEXT
     LYstrncpy(SSLLibraryVersion, OPENSSL_VERSION_TEXT, sizeof(SSLLibraryVersion)-1);
     if ((SSLcp = strchr(SSLLibraryVersion, ' ')) != NULL) {
-        *SSLcp++ = ' ';
-        if ((SSLcp = strchr(SSLcp, ' ')) != NULL) {
-            *SSLcp = '\0';
-            printf(", %s", SSLLibraryVersion);
-        }
+	*SSLcp++ = ' ';
+	if ((SSLcp = strchr(SSLcp, ' ')) != NULL) {
+	    *SSLcp = '\0';
+	    printf(", %s", SSLLibraryVersion);
+	}
     }
 #endif /* OPENSSL_VERSION_TEXT */
     printf("\n");
@@ -3622,10 +3701,16 @@ treated '>' as a co-terminator for double-quotes and tags"
       "turn on \"Textfields Need Activation\" mode"
    ),
 #endif
+#ifndef NO_LYNX_TRACE
    PARSE_SET(
       "trace",		2|SET_ARG,		&WWW_TraceFlag,
       "turns on Lynx trace mode"
    ),
+   PARSE_SET(
+      "trace_mask",	2|INT_ARG,		&WWW_TraceMask,
+      "customize Lynx trace mode"
+   ),
+#endif
    PARSE_FUN(
       "traversal",	4|FUNCTION_ARG,		traversal_fun,
       "traverse all http links derived from startfile"
@@ -3679,19 +3764,20 @@ treated '>' as a co-terminator for double-quotes and tags"
    {NULL, 0, 0, NULL}
 };
 
-PRIVATE void print_help_strings ARGS3(
+PRIVATE void print_help_strings ARGS4(
 	CONST char *,	name,
 	CONST char *,	help,
-	CONST char *,	value)
+	CONST char *,	value,
+	BOOLEAN,	option)
 {
     int pad;
     int c;
     int first;
     int field_width = 20;
 
-    pad = field_width - (4 + (int) strlen (name));
+    pad = field_width - (2 + option + (int) strlen (name));
 
-    fprintf (stdout, "   -%s", name);
+    fprintf (stdout, "  %s%s", option ? "-" : "", name);
 
     if (*help != '=') {
 	pad--;
@@ -3743,9 +3829,9 @@ PRIVATE void print_help_and_exit ARGS1(int, exit_status)
 #ifdef VMS
     print_help_strings("",
 "receive the arguments from stdin (enclose\n\
-in double-quotes (\"-\") on VMS)", NULL);
+in double-quotes (\"-\") on VMS)", NULL, TRUE);
 #else
-    print_help_strings("", "receive options and arguments from stdin", NULL);
+    print_help_strings("", "receive options and arguments from stdin", NULL, TRUE);
 #endif /* VMS */
 
     for (p = Arg_Table; p->name != 0; p++) {
@@ -3775,7 +3861,7 @@ in double-quotes (\"-\") on VMS)", NULL);
 		value = 0;
 		break;
 	}
-	print_help_strings(p->name, p->help_string, value);
+	print_help_strings(p->name, p->help_string, value, TRUE);
     }
 
     SetOutputMode( O_BINARY );
@@ -3926,6 +4012,7 @@ PRIVATE BOOL parse_arg ARGS3(
 #endif
 	ParseFunc fun;
 	char *next_arg = NULL;
+	char *temp_ptr = NULL;
 
 	if ((p->name[0] != *arg_name)
 	    || (0 == arg_eqs_parse (p->name, arg_name, &next_arg))) {
@@ -3989,7 +4076,7 @@ PRIVATE BOOL parse_arg ARGS3(
 
 	case INT_ARG:
 	     if ((q->int_value != 0) && (next_arg != 0))
-		 *(q->int_value) = atoi (next_arg);
+		 *(q->int_value) = strtol (next_arg, &temp_ptr, 0);
 	     break;
 
 	case STRING_ARG:
diff --git a/src/LYMainLoop.c b/src/LYMainLoop.c
index 6ed06b29..434d804d 100644
--- a/src/LYMainLoop.c
+++ b/src/LYMainLoop.c
@@ -255,14 +255,7 @@ PRIVATE void free_mainloop_variables NOARGS
 }
 #endif /* LY_FIND_LEAKS */
 
-PUBLIC FILE *TraceFP NOARGS
-{
-    if (LYTraceLogFP != 0) {
-	return LYTraceLogFP;
-    }
-    return stderr;
-}
-
+#ifndef NO_LYNX_TRACE
 PRIVATE void TracelogOpenFailed NOARGS
 {
     WWW_TraceFlag = FALSE;
@@ -274,8 +267,47 @@ PRIVATE void TracelogOpenFailed NOARGS
     }
 }
 
+PRIVATE BOOLEAN LYReopenTracelog ARGS1(BOOLEAN *, trace_flag_ptr)
+{
+    CTRACE((tfp, "\nTurning off TRACE for fetch of log.\n"));
+    LYCloseTracelog();
+    if ((LYTraceLogFP = LYAppendToTxtFile(LYTraceLogPath)) == NULL) {
+	TracelogOpenFailed();
+	return FALSE;
+    }
+    if (TRACE) {
+	WWW_TraceFlag = FALSE;
+	*trace_flag_ptr = TRUE;
+    }
+    return TRUE;
+}
+
+PRIVATE void turn_trace_back_on ARGS1(BOOLEAN *, trace_flag_ptr)
+{
+    if (*trace_flag_ptr == TRUE) {
+	WWW_TraceFlag = TRUE;
+	*trace_flag_ptr = FALSE;
+	fprintf(tfp, "Turning TRACE back on.\n\n");
+    }
+}
+#else
+#define LYReopenTracelog(flag) TRUE
+#define turn_trace_back_on(flag) /*nothing*/
+#endif /* NO_LYNX_TRACE */
+
+PUBLIC FILE *TraceFP NOARGS
+{
+#ifndef NO_LYNX_TRACE
+    if (LYTraceLogFP != 0) {
+	return LYTraceLogFP;
+    }
+#endif /* NO_LYNX_TRACE */
+    return stderr;
+}
+
 PUBLIC BOOLEAN LYOpenTraceLog NOARGS
 {
+#ifndef NO_LYNX_TRACE
     if (TRACE && LYUseTraceLog && LYTraceLogFP == NULL) {
 	/*
 	 * If we can't open it for writing, give up.  Otherwise, on VMS close
@@ -331,32 +363,31 @@ PUBLIC BOOLEAN LYOpenTraceLog NOARGS
 	    CTRACE((tfp, "\"all\" restrictions are set.\n"));
 	}
     }
+#endif /* NO_LYNX_TRACE */
     return TRUE;
 }
 
 PUBLIC void LYCloseTracelog NOARGS
 {
+#ifndef NO_LYNX_TRACE
     if (LYTraceLogFP != 0) {
 	fflush(stdout);
 	fflush(stderr);
 	fclose(LYTraceLogFP);
 	LYTraceLogFP = 0;
     }
+#endif /* NO_LYNX_TRACE */
 }
 
-PRIVATE BOOLEAN LYReopenTracelog ARGS1(BOOLEAN *, trace_flag_ptr)
+PUBLIC void handle_LYK_TRACE_TOGGLE NOARGS
 {
-    CTRACE((tfp, "\nTurning off TRACE for fetch of log.\n"));
-    LYCloseTracelog();
-    if ((LYTraceLogFP = LYAppendToTxtFile(LYTraceLogPath)) == NULL) {
-	TracelogOpenFailed();
-	return FALSE;
-    }
-    if (TRACE) {
-	WWW_TraceFlag = FALSE;
-	*trace_flag_ptr = TRUE;
-    }
-    return TRUE;
+#ifndef NO_LYNX_TRACE
+    WWW_TraceFlag = ! WWW_TraceFlag;
+    if (LYOpenTraceLog())
+	HTUserMsg(WWW_TraceFlag ? TRACE_ON : TRACE_OFF);
+#else
+    HTUserMsg(TRACE_DISABLED);
+#endif /* NO_LYNX_TRACE */
 }
 
 PUBLIC void LYSetNewline ARGS1(
@@ -3845,6 +3876,15 @@ PRIVATE BOOLEAN handle_LYK_OPTIONS ARGS2(
     return FALSE;
 }
 
+PRIVATE void handle_NEXT_DOC NOARGS
+{
+    if (LYhist_next(&curdoc, &newdoc)) {
+	FREE(curdoc.address);		/* avoid push */
+	return;
+    }
+    HTUserMsg(gettext("No next document present"));
+}
+
 PRIVATE void handle_LYK_NEXT_LINK ARGS3(
     int,	c,
     int *,	old_c,
@@ -4034,8 +4074,8 @@ PRIVATE int handle_PREV_DOC ARGS3(
 		    return 2;
 		} else {
 		    HTUserMsg2(WWW_SKIP_MESSAGE, WWWDoc.address);
-		    do {
-			LYpop(&curdoc);
+		    do {	/* Should be LYhist_prev when _next supports */
+			LYpop(&curdoc);		/* skipping of forms */
 		    } while (nhist > 1 && !are_different(
 			(document *)&history[(nhist - 1)],
 			&curdoc));
@@ -4061,6 +4101,7 @@ PRIVATE int handle_PREV_DOC ARGS3(
 	/*
 	 *  Set newdoc.address to empty to pop a file.
 	 */
+	LYhist_prev_register(&curdoc);	/* Why not call _prev instead of zeroing address?  */
 	FREE(newdoc.address);
 #ifdef DIRED_SUPPORT
 	if (lynx_edit_mode) {
@@ -4512,6 +4553,7 @@ PRIVATE void handle_LYK_TOOLBAR ARGS4(
 PRIVATE void handle_LYK_TRACE_LOG ARGS1(
     BOOLEAN *,	trace_flag_ptr)
 {
+#ifndef NO_LYNX_TRACE
     /*
      *	Check whether we've started a TRACE log
      *	in this session. - FM
@@ -4554,13 +4596,9 @@ PRIVATE void handle_LYK_TRACE_LOG ARGS1(
 	LYPermitURL = TRUE;
     }
     LYforce_no_cache = TRUE;
-}
-
-PUBLIC void handle_LYK_TRACE_TOGGLE NOARGS
-{
-    WWW_TraceFlag = ! WWW_TraceFlag;
-    if (LYOpenTraceLog())
-	HTUserMsg(WWW_TraceFlag ? TRACE_ON : TRACE_OFF);
+#else
+    HTUserMsg(TRACE_DISABLED);
+#endif /* NO_LYNX_TRACE */
 }
 
 #ifdef DIRED_SUPPORT
@@ -5042,6 +5080,11 @@ PUBLIC void handle_LYK_CHDIR NOARGS
     static char buf[LY_MAXPATH];
     char *p = NULL;
 
+    if (no_chdir) {
+	HTUserMsg(CHDIR_DISABLED);
+	return;
+    }
+
     _statusline(gettext("cd to:"));
     /* some people may prefer automatic clearing of the previous user input,
        here, to do this, just uncomment next line - VH */
@@ -5339,7 +5382,7 @@ try_again:
 		     *	If newdoc.address is empty then pop a file
 		     *	and load it.  - FM
 		     */
-		    LYpop(&newdoc);
+		    LYhist_prev(&newdoc);
 		    popped_doc = TRUE;
 
 
@@ -5532,11 +5575,7 @@ try_again:
 		     */
 		    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;
-			fprintf(tfp, "Turning TRACE back on.\n\n");
-		    }
+		    turn_trace_back_on(&trace_mode_flag);
 		    if (!first_file && !LYCancelledFetch) {
 			/*
 			 *  Do error mail sending and/or traversal
@@ -5622,11 +5661,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;
-			fprintf(tfp, "Turning TRACE back on.\n\n");
-		    }
+		    turn_trace_back_on(&trace_mode_flag);
 		    FREE(newdoc.address); /* to pop last doc */
 		    FREE(newdoc.bookmark);
 		    LYJumpFileURL = FALSE;
@@ -5755,11 +5790,7 @@ try_again:
 		     */
 		    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;
-			fprintf(tfp, "Turning TRACE back on.\n\n");
-		    }
+		    turn_trace_back_on(&trace_mode_flag);
 
 		    /*
 		     *	If it's the first file and we're interactive,
@@ -6041,8 +6072,9 @@ try_again:
 	     *  WINDOW structures are already filled based on the old size.
 	     *  So we notify the ncurses library directly here. - kw
 	     */
-#if defined(HAVE_RESIZETERM)
+#if defined(NCURSES) && defined(HAVE_RESIZETERM)
 	    resizeterm(LYlines, LYcols);
+	    wresize(LYwin, LYlines, LYcols);
 #else
 	    stop_curses();
 	    start_curses();
@@ -6897,14 +6929,86 @@ new_cmd:  /*
 	    handle_LYK_DOWN_HALF(&old_c, real_c);
 	    break;
 
-#if defined(WIN_EX) && defined(SH_EX)	/*1997/12/22 (Mon) 09:28:56 */
+#ifdef CAN_CUT_AND_PASTE
 	case LYK_TO_CLIPBOARD:	/* ^S */
 	    {
-		if (put_clip(links[curdoc.link].lname) == 0) {
-		    HTInfoMsg("URL to Clip Board.");
-		} else {
+		char *s;
+		int c;
+
+		/* The logic resembles one of ADD_BOOKMARK */
+		if (nlinks > 0 && links[curdoc.link].lname
+		    && links[curdoc.link].type != WWW_FORM_LINK_TYPE) {
+		    /* Makes sense to copy a link */
+		    _statusline("Copy D)ocument's or L)ink's URL to clipboard or C)ancel?");
+		    c = LYgetch_single();
+		    if (c == 'D')
+			s = curdoc.address;
+		    else if (c == 'C')
+			break;
+		    else
+			s = links[curdoc.link].lname;
+		} else
+		    s = curdoc.address;
+		if (!s && !*s)
 		    HTInfoMsg("Current URL is empty.");
+		if (put_clip(s))
+		    HTInfoMsg("Copy to clipboard failed.");
+		else if (s == curdoc.address)
+		    HTInfoMsg("Document URL put to clipboard.");
+		else
+		    HTInfoMsg("Link URL put to clipboard.");
+	    }
+	    break;
+
+	case LYK_PASTE_URL:
+	    if (no_goto && !LYValidate) { /*  Go to not allowed. - FM */
+		HTUserMsg(GOTO_DISALLOWED);
+	    } else {
+		unsigned char *s = get_clip_grab(), *e, *t;
+		char *buf;
+		int len;
+
+		if (!s)
+		    break;
+		len = strlen(s);
+		e = s + len;
+		while (s < e && strchr(" \t\n\r", *s))
+		    s++;
+		while (s < e && strchr(" \t\n\r", e[-1]))
+		    e--;
+		if (s >= e) {
+		    HTInfoMsg("No URL in the clipboard.");
+		    break;
 		}
+		buf = (char*)malloc(e - s + 1);
+		strncpy(buf, s, e - s);
+		buf[e - s] = '\0';
+		t = buf;
+
+		while (s < e) {
+		    if (strchr(" \t\n\r", *s)) {
+			int nl = 0;	/* Keep whitespace without NL - file names! */
+			unsigned char *s1 = s;
+
+			while (strchr(" \t\n\r", *s)) {
+			    if (!nl && *s == '\n')
+				nl = 1;
+			    s++;
+			}
+			if (!nl) {
+			    while (s1 < s) {
+				if (*s1 != '\r' && *s1 != '\r')
+				    *t = *s1;
+				t++, s1++;
+			    }
+			}
+		    } else
+			*t++ = *s++;
+		}
+		*t = '\0';
+		get_clip_release();
+		do_check_goto_URL(buf, &temp, &force_load);
+		free(buf);
 	    }
 	    break;
 #endif
@@ -7029,6 +7133,10 @@ new_cmd:  /*
 	    }
 	    break;
 
+	case LYK_NEXT_DOC:	/* undo back up a level */
+	    handle_NEXT_DOC();
+	    break;
+
 	case LYK_NOCACHE: /* Force submission of form or link with no-cache */
 	    if (!handle_LYK_NOCACHE(&old_c, real_c))
 		break;
diff --git a/src/LYOptions.c b/src/LYOptions.c
index bf157c3c..0ef88dec 100644
--- a/src/LYOptions.c
+++ b/src/LYOptions.c
@@ -989,6 +989,12 @@ draw_options:
 			LYclrtoeol();
 			LYaddstr(LYRawMode ? "ON " : "OFF");
 		    }
+#ifdef CAN_SWITCH_DISPLAY_CHARSET
+		    /* Deduce whether the user wants autoswitch: */
+		    switch_display_charsets =
+			(current_char_set == auto_display_charset
+			    || current_char_set == auto_other_display_charset);
+#endif
 		}
 		response = ' ';
 		if (LYSelectPopups) {
@@ -2955,24 +2961,30 @@ PUBLIC int postoptions ARGS1(
 	 * charset settings: the order is essential here.
 	 */
 	if (display_char_set_old != current_char_set) {
-		/*
-		 *  Set the LYUseDefaultRawMode value and character
-		 *  handling if LYRawMode was changed. - FM
-		 */
-		LYUseDefaultRawMode = TRUE;
-		HTMLUseCharacterSet(current_char_set);
-	    }
+	    /*
+	     *  Set the LYUseDefaultRawMode value and character
+	     *  handling if LYRawMode was changed. - FM
+	     */
+	    LYUseDefaultRawMode = TRUE;
+	    HTMLUseCharacterSet(current_char_set);
+#ifdef CAN_SWITCH_DISPLAY_CHARSET
+	    /* Deduce whether the user wants autoswitch: */
+	    switch_display_charsets =
+		 (current_char_set == auto_display_charset
+		  || current_char_set == auto_other_display_charset);
+#endif
+	}
 	if (assume_char_set_changed && HTCJK != JAPANESE) {
-		LYRawMode = (BOOL) (UCLYhndl_for_unspec == current_char_set);
-	    }
+	    LYRawMode = (BOOL) (UCLYhndl_for_unspec == current_char_set);
+	}
 	if (raw_mode_old != LYRawMode || assume_char_set_changed) {
-		/*
-		 *  Set the raw 8-bit or CJK mode defaults and
-		 *  character set if changed. - FM
-		 */
-		HTMLSetUseDefaultRawMode(current_char_set, LYRawMode);
-		HTMLSetCharacterHandling(current_char_set);
-	    }
+	    /*
+	     *  Set the raw 8-bit or CJK mode defaults and
+	     *  character set if changed. - FM
+	     */
+	    HTMLSetUseDefaultRawMode(current_char_set, LYRawMode);
+	    HTMLSetCharacterHandling(current_char_set);
+	}
 	need_reload = TRUE;
      } /* end of charset settings */
 
diff --git a/src/LYReadCFG.c b/src/LYReadCFG.c
index 814da7e4..1369a8df 100644
--- a/src/LYReadCFG.c
+++ b/src/LYReadCFG.c
@@ -377,13 +377,13 @@ PUBLIC int check_color ARGS2(
 {
     int i;
 
-    CTRACE((tfp, "check_color(%s,%d)\n", color, the_default));
+    CTRACE2(TRACE_STYLE, (tfp, "check_color(%s,%d)\n", color, the_default));
     if (!strcasecomp(color, "default")) {
 #if USE_DEFAULT_COLORS
 	if (!default_color_reset)
 	    the_default = DEFAULT_COLOR;
 #endif	/* USE_DEFAULT_COLORS */
-	CTRACE((tfp, "=> default %d\n", the_default));
+	CTRACE2(TRACE_STYLE, (tfp, "=> default %d\n", the_default));
 	return the_default;
     }
     if (!strcasecomp(color, "nocolor"))
@@ -393,11 +393,11 @@ PUBLIC int check_color ARGS2(
 	if (!strcasecomp(color, Color_Strings[i])) {
 	    int c = ColorCode(i);
 
-	    CTRACE((tfp, "=> %d\n", c));
+	    CTRACE2(TRACE_STYLE, (tfp, "=> %d\n", c));
 	    return c;
 	}
     }
-    CTRACE((tfp, "=> ERR_COLOR\n"));
+    CTRACE2(TRACE_STYLE, (tfp, "=> ERR_COLOR\n"));
     return ERR_COLOR;
 }
 
@@ -602,7 +602,9 @@ static int character_set_fun ARGS1(
 
     if (i < 0) {
 #ifdef CAN_AUTODETECT_DISPLAY_CHARSET
-	if (auto_display_charset >= 0 && !strnicmp(value,"AutoDetect ",11))
+	if (auto_display_charset >= 0
+	    && (!strnicmp(value,"AutoDetect ",11)
+		|| !strnicmp(value,"AutoDetect-2 ",13)))
 	    current_char_set = auto_display_charset;
 #endif
 	/* do nothing here: so fallback to userdefs.h */
@@ -1431,6 +1433,10 @@ static Config_Type Config_Table [] =
      PARSE_SET("bold_name_anchors", CONF_BOOL, &bold_name_anchors),
      PARSE_SET("case_sensitive_always_on", CONF_BOOL, &case_sensitive),
      PARSE_FUN("character_set", CONF_FUN, character_set_fun),
+#ifdef CAN_SWITCH_DISPLAY_CHARSET
+     PARSE_SET("charset_switch_rules", CONF_STR, &charset_switch_rules),
+     PARSE_SET("charsets_directory", CONF_STR, &charsets_directory),
+#endif
      PARSE_SET("checkmail", CONF_BOOL, &check_mail),
      PARSE_SET("collapse_br_tags", CONF_BOOL, &LYCollapseBRs),
 #ifdef USE_COLOR_TABLE
diff --git a/src/LYStrings.c b/src/LYStrings.c
index 93de4326..7ea81384 100644
--- a/src/LYStrings.c
+++ b/src/LYStrings.c
@@ -1,9 +1,9 @@
 #include <HTUtils.h>
 #include <HTCJK.h>
 #include <UCAux.h>
+#include <LYGlobalDefs.h>
 #include <LYUtils.h>
 #include <LYStrings.h>
-#include <LYGlobalDefs.h>
 #include <GridText.h>
 #include <LYKeymap.h>
 #include <LYClean.h>
@@ -806,7 +806,6 @@ static SLKeyMap_List_Type *Keymap_List;
 #define MOUSE_KEYSYM 0x0400
 #endif
 
-
 #define SQUOTE '\''
 #define DQUOTE '"'
 #define ESCAPE '\\'
@@ -2014,34 +2013,34 @@ re_read:
 		 */
 		goto re_read;
 	    }
-	   /*
-	    *  Yep, we agree there was a change.  Return now so that
-	    *  the caller can react to it. - kw
-	    */
-	   c = DO_NOTHING;
-	   break;
+	    /*
+	     *  Yep, we agree there was a change.  Return now so that
+	     *  the caller can react to it. - kw
+	     */
+	    c = DO_NOTHING;
+	    break;
 #endif /* KEY_RESIZE */
 
 /* The following maps PDCurses keys away from lynx reserved values */
 #if (defined(_WINDOWS) || defined(__DJGPP__)) && !defined(USE_SLANG)
 	case KEY_F(2):
-	   c = 0x213;
-	   break;
+	    c = 0x213;
+	    break;
 	case KEY_F(3):
-	   c = 0x214;
-	   break;
+	    c = 0x214;
+	    break;
 	case KEY_F(4):
-	   c = 0x215;
-	   break;
+	    c = 0x215;
+	    break;
 	case KEY_F(5):
-	   c = 0x216;
-	   break;
+	    c = 0x216;
+	    break;
 	case KEY_F(6):
-	   c = 0x217;
-	   break;
+	    c = 0x217;
+	    break;
 	case KEY_F(7):
-	   c = 0x218;
-	   break;
+	    c = 0x218;
+	    break;
 #endif /* PDCurses */
 
 #if defined(USE_MOUSE)
@@ -2128,7 +2127,7 @@ re_read:
 #endif
 		    }
 		    if (lac == LYK_ACTIVATE && mouse_link == -1) {
-			HTAlert("No link chosen");
+			HTAlert(gettext("No link chosen"));
 			lac = LYK_REFRESH;
 		    }
 		    c = LAC_TO_LKC(lac);
@@ -2195,7 +2194,7 @@ re_read:
 			}
 		    }
 		} else {
-		/* for Windows 95 */
+		    /* for Windows 95 */
 		    tick_count = GetTickCount();
 
 		    /* Guard Mouse button miss click */
@@ -2661,6 +2660,123 @@ PRIVATE int prev_pos ARGS2(
 }
 #endif /* SUPPORT_MULTIBYTE_EDIT */
 
+#ifdef EXP_KEYBOARD_LAYOUT
+static int map_active = 0;
+#else
+#define map_active 0
+#endif
+
+PUBLIC int LYEditInsert ARGS5(
+	EDREC *,	edit,
+	unsigned char *,s,
+	int,		len,
+	int,		map,
+	BOOL,		maxMessage)
+{
+    int length = strlen(Buf);
+    int remains = MaxLen - (length + len);
+    int edited = 0, overflow = 0;
+
+    /*
+     *  ch is (presumably) printable character.
+     */
+    if (remains < 0) {
+	overflow = 1;
+	len = 0;
+	if (MaxLen > length)	/* Insert as much as we can */
+	    len = MaxLen - length;
+	else
+	    goto finish;
+    }
+    Buf[length + len] = '\0';
+    for(; length >= Pos; length--)    /* Make room */
+	Buf[length + len] = Buf[length];
+#ifdef EXP_KEYBOARD_LAYOUT
+    if (map < 0)
+	map = map_active;
+    if (map && LYCharSet_UC[current_char_set].enc == UCT_ENC_UTF8) {
+	unsigned char *e = s + len, *t = Buf + Pos;
+	char *tail = 0;
+
+	while (s < e) {
+	    char utfbuf[8];
+	    int l = 1;
+
+	    utfbuf[0] = *s;
+	    if ( *s < 128 && LYKbLayouts[current_layout][*s] ) {
+		UCode_t ucode = LYKbLayouts[current_layout][*s];
+
+		if (ucode > 127) {
+		    if (UCConvertUniToUtf8(ucode, utfbuf)) {
+			l = strlen(utfbuf);
+			remains -= l - 1;
+			if (remains < 0) {
+			    if (tail)
+				strcpy(t, tail);
+			    FREE(tail);
+			    len = (char*)t - Buf;
+			    overflow = 1;
+			    goto finish;
+			}
+			if (l > 1 && !tail)
+			    StrAllocCopy((char*)tail, Buf + Pos + len);
+		    } else
+			utfbuf[0] = '?';
+		} else
+		    utfbuf[0] = UCH(ucode);
+	    }
+	    strncpy(t, utfbuf, l);
+	    edited = 1;
+	    t += l;
+	    s++;
+	}
+	if (tail)
+	    strcpy(t, tail);
+	len = (char*)t - (Buf + Pos);
+	FREE(tail);
+    } else if (map) {
+	unsigned char *e = s + len, *t = Buf + Pos;
+
+	while (s < e) {
+	    int ch;
+
+	    if ( *s < 128 && LYKbLayouts[current_layout][*s] ) {
+		ch = UCTransUniChar(LYKbLayouts[current_layout][*s],
+				    current_char_set);
+		if (ch < 0)
+		    ch = '?';
+	    } else
+		ch = *s;
+	    *t = UCH(ch);
+	    t++, s++;
+	}
+	edited = 1;
+    }
+    else
+#endif	/* defined EXP_KEYBOARD_LAYOUT */
+	{
+	    strncpy(Buf + Pos, (char *) s, len);
+	    edited = 1;
+	}
+
+  finish:
+    Pos += len;
+    StrLen += len;
+    if (edited)
+	edit->dirty = TRUE;
+    if (overflow && maxMessage)
+	_statusline(MAXLEN_REACHED_DEL_OR_MOV);
+#ifdef ENHANCED_LINEEDIT
+    if (Mark > Pos)
+	Mark += len;
+    else if (Mark < -1 - Pos)
+	Mark -= len;
+    if (Mark >= 0)
+	Mark = -1 - Mark;		/* Disable it */
+#endif
+    return edited;
+}
+
 PUBLIC int LYEdit1 ARGS4(
 	EDREC *,	edit,
 	int,		ch,
@@ -2672,9 +2788,6 @@ PUBLIC int LYEdit1 ARGS4(
      */
     int i;
     int length;
-#ifdef EXP_KEYBOARD_LAYOUT
-    static int map_active = 0;
-#endif
 
     if (MaxLen <= 0)
 	return(0); /* Be defensive */
@@ -2703,64 +2816,13 @@ PUBLIC int LYEdit1 ARGS4(
 	    return(ch);
 	/* FALLTHRU */
 #endif
-    case LYE_CHAR:
-#ifdef EXP_KEYBOARD_LAYOUT
-	if (map_active && ch < 128 && ch >= 0 &&
-	    LYKbLayouts[current_layout][ch]) {
-	    UCode_t ucode = LYKbLayouts[current_layout][ch];
-	    if (LYCharSet_UC[current_char_set].enc == UCT_ENC_UTF8) {
-		if (ucode > 127) {
-		    char utfbuf[8];
-		    utfbuf[0] = 0;
-		    if (UCConvertUniToUtf8(ucode, utfbuf)) {
-			int ulen = strlen(utfbuf);
-			i = 0;
-			if (ulen > 1) {
-			    if (Pos + ulen - 1 <= (MaxLen) &&
-				StrLen + ulen - 1 < (MaxLen)) {
-				for (i = 0; i < ulen-1; i++)
-				    LYEdit1(edit, utfbuf[i], LYE_CHAR, FALSE);
-				length = strlen(&Buf[0]);
-				StrLen = length;
-			    } else {
-				if (maxMessage)
-				    _statusline(MAXLEN_REACHED_DEL_OR_MOV);
-				return 0;
-			    }
-			}
-			ch = UCH(utfbuf[i]);
-		    }
-		} else {
-		    ch = UCH(ucode);
-		}
-	    } else {
-		ch = UCTransUniChar(ucode, current_char_set);
-		if (ch < 0)
-		    ch = '?';
-	    }
-	}
-#endif
-	/*
-	 *  ch is (presumably) printable character.
-	 */
-	if (Pos <= (MaxLen) && StrLen < (MaxLen)) {
-#ifdef ENHANCED_LINEEDIT
-	    if (Mark > Pos)
-		Mark++;
-	    else if (Mark < -1 - Pos)
-		Mark--;
-	    if (Mark >= 0)
-		Mark = -1 - Mark;		/* Disable it */
-#endif
-	    for(i = length; i >= Pos; i--)    /* Make room */
-		Buf[i+1] = Buf[i];
-	    Buf[length+1]='\0';
-	    Buf[Pos] = UCH(ch);
-	    Pos++;
-	} else if (maxMessage) {
-	    _statusline(MAXLEN_REACHED_DEL_OR_MOV);
-	}
-	break;
+    case LYE_CHAR: {
+	unsigned char uch = UCH(ch);
+
+	LYEditInsert(edit, &uch, 1, map_active, maxMessage);
+	return 0;			/* All changes already registered */
+    }
+    break;
 
     case LYE_C1CHAR:
 	/*
@@ -2984,10 +3046,10 @@ PUBLIC int LYEdit1 ARGS4(
 		Buf[i] = Buf[i + offset];
 	    i -= offset;
 #ifdef ENHANCED_LINEEDIT
-            if (Mark >= 0)
-                Mark = -1 - Mark;		/* Disable it */
-            if (Mark <= -1 - Pos)
-                Mark += offset;
+	    if (Mark >= 0)
+		Mark = -1 - Mark;		/* Disable it */
+	    if (Mark <= -1 - Pos)
+		Mark += offset;
 #endif
 	}
 #endif /* SUPPORT_MULTIBYTE_EDIT */
@@ -3326,8 +3388,9 @@ PUBLIC void LYRefreshEdit ARGS1(
 	estyle = s_prompt_edit;
     else
 	estyle = s_aedit;
-    CTRACE((tfp, "STYLE.getstr: switching to <edit.%s>.\n",
-	    prompting ? "prompt" : "active"));
+    CTRACE2(TRACE_STYLE,
+	    (tfp, "STYLE.getstr: switching to <edit.%s>.\n",
+		  prompting ? "prompt" : "active"));
     if (estyle != NOSTYLE)
 	curses_style(estyle, STACK_ON);
     else
@@ -4688,28 +4751,39 @@ again:
 	    CTRACE((tfp, "LYgetstr(%s) LYE_ENTER\n", inputline));
 	    return(ch);
 
-#if defined(WIN_EX)
+#ifdef CAN_CUT_AND_PASTE
 	/* 1998/10/01 (Thu) 15:05:49 */
 
-#define PASTE_MAX	512
-
 	case LYE_PASTE:
 	    {
-		unsigned char buff[PASTE_MAX];
-		int i, len;
+		unsigned char *s = get_clip_grab(), *e;
+		int len;
 
-		len = get_clip(buff, PASTE_MAX);
+		if (!s)
+		    break;
+		len = strlen(s);
+		e = s + len;
 
 		if (len > 0) {
-		    i = 0;
-		    while ((ch = buff[i]) != '\0') {
-			if (ch == '\r' || ch == '\n')
-			    break;
-			if (ch >= ' ')
-			    LYLineEdit(&MyEdit, ch, FALSE);
-			i++;
+		    unsigned char *e1 = s;
+
+		    while (e1 < e) {
+			if (*e1 < ' ') { /* Stop here? */
+			    if (e1 > s)
+				LYEditInsert(&MyEdit, s, e1 - s, map_active, TRUE);
+			    s = e1;
+			    if (*e1 == '\t') { /* Replace by space */
+				LYEditInsert(&MyEdit, " ", 1, map_active, TRUE);
+				s = ++e1;
+			    } else
+				break;
+			} else
+			    ++e1;
 		    }
+		    if (e1 > s)
+			LYEditInsert(&MyEdit, s, e1 - s, map_active, TRUE);
 		}
+		get_clip_release();
 		break;
 	    }
 #endif
diff --git a/src/LYStrings.h b/src/LYStrings.h
index 77d813e1..3c1f0898 100644
--- a/src/LYStrings.h
+++ b/src/LYStrings.h
@@ -207,68 +207,70 @@ typedef struct _EditFieldData {
 
 /* line-edit action encoding */
 
-#define LYE_NOP 0		  /* Do Nothing            */
-#define LYE_CHAR  (LYE_NOP   +1)  /* Insert printable char */
-#define LYE_ENTER (LYE_CHAR  +1)  /* Input complete, return char/lynxkeycode */
-#define LYE_TAB   (LYE_ENTER +1)  /* Input complete, return TAB  */
-#define LYE_STOP  (LYE_TAB   +1)  /* Input complete, deactivate  */
-#define LYE_ABORT (LYE_STOP  +1)  /* Input cancelled       */
+typedef enum {
+    LYE_NOP = 0			/* Do Nothing		 */
+    ,LYE_CHAR			/* Insert printable char */
+    ,LYE_ENTER			/* Input complete, return char/lynxkeycode */
+    ,LYE_TAB			/* Input complete, return TAB  */
+    ,LYE_STOP			/* Input complete, deactivate  */
+    ,LYE_ABORT			/* Input cancelled	 */
 
-#define LYE_FORM_PASS (LYE_ABORT +1)  /* In form fields: input complete,
-					 return char / lynxkeycode;
-					 Elsewhere: Do Nothing */
+    ,LYE_FORM_PASS		/* In form fields: input complete,
+				   return char / lynxkeycode;
+				   Elsewhere: Do Nothing */
 
-#define LYE_DELN  (LYE_FORM_PASS +1)  /* Delete next/curr char */
-#define LYE_DELC  (LYE_DELN)      /* Obsolete (DELC case was equiv to DELN) */
-#define LYE_DELP  (LYE_DELN  +1)  /* Delete prev      char */
-#define LYE_DELNW (LYE_DELP  +1)  /* Delete next word      */
-#define LYE_DELPW (LYE_DELNW +1)  /* Delete prev word      */
+    ,LYE_DELN			/* Delete next/curr char */
+    ,LYE_DELC			/* Obsolete (DELC case was equiv to DELN) */
+    ,LYE_DELP			/* Delete prev	    char */
+    ,LYE_DELNW			/* Delete next word	 */
+    ,LYE_DELPW			/* Delete prev word	 */
 
-#define LYE_ERASE (LYE_DELPW +1)  /* Erase the line        */
+    ,LYE_ERASE			/* Erase the line	 */
 
-#define LYE_BOL   (LYE_ERASE +1)  /* Go to begin of line   */
-#define LYE_EOL   (LYE_BOL   +1)  /* Go to end   of line   */
-#define LYE_FORW  (LYE_EOL   +1)  /* Cursor forwards       */
-#define LYE_FORW_RL (LYE_FORW +1) /* Cursor forwards or right link */
-#define LYE_BACK  (LYE_FORW_RL+1) /* Cursor backwards      */
-#define LYE_BACK_LL (LYE_BACK+1)  /* Cursor backwards or left link */
-#define LYE_FORWW (LYE_BACK_LL+1) /* Word forward          */
-#define LYE_BACKW (LYE_FORWW +1)  /* Word back             */
+    ,LYE_BOL			/* Go to begin of line	 */
+    ,LYE_EOL			/* Go to end   of line	 */
+    ,LYE_FORW			/* Cursor forwards	 */
+    ,LYE_FORW_RL		/* Cursor forwards or right link */
+    ,LYE_BACK			/* Cursor backwards	 */
+    ,LYE_BACK_LL		/* Cursor backwards or left link */
+    ,LYE_FORWW			/* Word forward		 */
+    ,LYE_BACKW			/* Word back		 */
 
-#define LYE_LOWER (LYE_BACKW +1)  /* Lower case the line   */
-#define LYE_UPPER (LYE_LOWER +1)  /* Upper case the line   */
+    ,LYE_LOWER			/* Lower case the line	 */
+    ,LYE_UPPER			/* Upper case the line	 */
 
-#define LYE_LKCMD (LYE_UPPER +1)  /* Invoke command prompt */
+    ,LYE_LKCMD			/* Invoke command prompt */
 
-#define LYE_AIX   (LYE_LKCMD +1)  /* Hex 97                */
+    ,LYE_AIX			/* Hex 97		 */
 
-#define LYE_DELBL (LYE_AIX   +1)  /* Delete back to BOL    */
-#define LYE_DELEL (LYE_DELBL +1)  /* Delete thru EOL       */
+    ,LYE_DELBL			/* Delete back to BOL	 */
+    ,LYE_DELEL			/* Delete thru EOL	 */
 
-#define LYE_SWMAP (LYE_DELEL +1)  /* Switch input keymap   */
+    ,LYE_SWMAP			/* Switch input keymap	 */
 
-#define LYE_TPOS  (LYE_SWMAP +1)  /* Transpose characters  */
+    ,LYE_TPOS			/* Transpose characters	 */
 
-#define LYE_SETM1 (LYE_TPOS  +1)  /* Set modifier 1 flag   */
-#define LYE_SETM2 (LYE_SETM1 +1)  /* Set modifier 2 flag   */
-#define LYE_UNMOD (LYE_SETM2 +1)  /* Fall back to no-modifier command */
+    ,LYE_SETM1			/* Set modifier 1 flag	 */
+    ,LYE_SETM2			/* Set modifier 2 flag	 */
+    ,LYE_UNMOD			/* Fall back to no-modifier command */
 
-#define LYE_C1CHAR  (LYE_UNMOD   +1)  /* Insert C1 char if printable */
+    ,LYE_C1CHAR			/* Insert C1 char if printable */
 
-#define LYE_SETMARK (LYE_C1CHAR  +1)  /* emacs-like set-mark-command */
-#define LYE_XPMARK  (LYE_SETMARK +1)  /* emacs-like exchange-point-and-mark */
-#define LYE_KILLREG (LYE_XPMARK  +1)  /* emacs-like kill-region */
-#define LYE_YANK    (LYE_KILLREG +1)  /* emacs-like yank */
-#if defined(WIN_EX)
-#define LYE_PASTE (LYE_YANK +1)	  /* ClipBoard to Lynx	   */
+    ,LYE_SETMARK		/* emacs-like set-mark-command */
+    ,LYE_XPMARK			/* emacs-like exchange-point-and-mark */
+    ,LYE_KILLREG		/* emacs-like kill-region */
+    ,LYE_YANK			/* emacs-like yank */
+#ifdef CAN_CUT_AND_PASTE
+    ,LYE_PASTE			/* ClipBoard to Lynx	   */
 #endif
+} LYEditCodes;
 /* All preceding values must be within 0x00..0x7f - kw */
 
 /*  The following are meant to be bitwise or-ed:  */
-#define LYE_DF       0x80         /* Flag to set modifier 3 AND do other
-				     action */
-#define LYE_FORM_LAC 0x1000       /* Flag to pass lynxactioncode given by
-				     lower bits.  Doesn't fit in a char! */
+#define LYE_DF       0x80       /* Flag to set modifier 3 AND do other
+				   action */
+#define LYE_FORM_LAC 0x1000     /* Flag to pass lynxactioncode given by
+				   lower bits.  Doesn't fit in a char! */
 
 
 #if defined(USE_KEYMAPS)
@@ -344,4 +346,6 @@ extern int escape_bound;
 /* Dummy initializer for LYEditmap.c */
 extern int LYEditmapDeclared NOPARAMS;
 
+int LYEditInsert PARAMS((EditFieldData *edit, unsigned char *s,	int len, int map_active, BOOL maxMessage));
+
 #endif /* LYSTRINGS_H */
diff --git a/src/LYStyle.c b/src/LYStyle.c
index 60c8e195..b2b40e69 100644
--- a/src/LYStyle.c
+++ b/src/LYStyle.c
@@ -1,6 +1,6 @@
 /* character level styles for Lynx
  * (c) 1996 Rob Partington -- donated to the Lyncei (if they want it :-)
- * @Id: LYStyle.c 1.42 Mon, 12 Feb 2001 17:33:21 -0800 dickey @
+ * @Id: LYStyle.c 1.43 Mon, 26 Feb 2001 18:41:57 -0800 dickey @
  */
 #include <HTUtils.h>
 #include <HTML.h>
@@ -88,7 +88,7 @@ PRIVATE void parse_attributes ARGS5(char*,mono,char*,fg,char*,bg,int,style,char*
     int cA = A_NORMAL;
     int newstyle = hash_code(element);
 
-    CTRACE((tfp, "CSS(PA):style d=%d / h=%d, e=%s\n", style, newstyle,element));
+    CTRACE2(TRACE_STYLE, (tfp, "CSS(PA):style d=%d / h=%d, e=%s\n", style, newstyle,element));
 
     mA = string_to_attr(mono);
     if (!mA) {
@@ -113,13 +113,13 @@ PRIVATE void parse_attributes ARGS5(char*,mono,char*,fg,char*,bg,int,style,char*
 	    }
 	}
     }
-    CTRACE((tfp, "CSS(CP):%d\n", colorPairs));
+    CTRACE2(TRACE_STYLE, (tfp, "CSS(CP):%d\n", colorPairs));
 
     fA = check_color(fg, default_fg);
     bA = check_color(bg, default_bg);
 
     if (style == -1) {			/* default */
-	CTRACE((tfp, "CSS(DEF):default_fg=%d, default_bg=%d\n", fA, bA));
+	CTRACE2(TRACE_STYLE, (tfp, "CSS(DEF):default_fg=%d, default_bg=%d\n", fA, bA));
 	default_fg = fA;
 	default_bg = bA;
 	default_color_reset = TRUE;
@@ -160,7 +160,7 @@ PRIVATE void parse_attributes ARGS5(char*,mono,char*,fg,char*,bg,int,style,char*
 	     && curPair < 255)
 		our_pairs[cA == A_BOLD][fA][bA] = curPair + 1;
 	}
-	CTRACE((tfp, "CSS(CURPAIR):%d\n", curPair));
+	CTRACE2(TRACE_STYLE, (tfp, "CSS(CURPAIR):%d\n", curPair));
 	if (style < DSTYLE_ELEMENTS)
 	    setStyle(style, COLOR_PAIR(curPair)|cA, cA, mA);
 	setHashStyle(newstyle, COLOR_PAIR(curPair)|cA, cA, mA, element);
@@ -168,7 +168,7 @@ PRIVATE void parse_attributes ARGS5(char*,mono,char*,fg,char*,bg,int,style,char*
     else
     {
 	if (lynx_has_color && fA != NO_COLOR) {
-	    CTRACE((tfp, "CSS(NC): maximum of %d colorpairs exhausted\n", COLOR_PAIRS - 1));
+	    CTRACE2(TRACE_STYLE, (tfp, "CSS(NC): maximum of %d colorpairs exhausted\n", COLOR_PAIRS - 1));
 	}
 	/* only mono is set */
 	if (style < DSTYLE_ELEMENTS)
@@ -253,7 +253,7 @@ where OBJECT is one of EM,STRONG,B,I,U,BLINK etc.\n\n"), buffer);
 	}
     }
 
-    CTRACE((tfp, "CSSPARSE:%s => %d %s\n",
+    CTRACE2(TRACE_STYLE, (tfp, "CSSPARSE:%s => %d %s\n",
 		element, hash_code(element),
 		(hashStyles[hash_code(element)].name ? "used" : "")));
 
@@ -382,7 +382,7 @@ PUBLIC void parse_userstyles NOARGS
 	initialise_default_stylesheet();
     } else {
 	while ((name = HTList_nextObject(cur)) != NULL) {
-	    CTRACE((tfp, "LSS:%s\n", name ? name : "!?! empty !?!"));
+	    CTRACE2(TRACE_STYLE, (tfp, "LSS:%s\n", name ? name : "!?! empty !?!"));
 	    if (name != NULL)
 		parse_style(name);
 	}
@@ -414,14 +414,14 @@ PRIVATE void HStyle_addStyle ARGS1(char*,buffer)
     strtolower(name);
     if (!strncasecomp(name, "default:", 8)) /* default fg/bg */
     {
-	CTRACE( (tfp, "READCSS.default%s:%s\n",
+	CTRACE2(TRACE_STYLE, (tfp, "READCSS.default%s:%s\n",
 		 (default_color_reset ? ".ignore" : ""),
 		 name ? name : "!?! empty !?!"));
 	if (!default_color_reset)
 	    parse_style(name);
 	return;				/* do not need to process it again */
     }
-    CTRACE((tfp, "READCSS:%s\n", name ? name : "!?! empty !?!"));
+    CTRACE2(TRACE_STYLE, (tfp, "READCSS:%s\n", name ? name : "!?! empty !?!"));
     HTList_addObject (lss_styles, name);
 }
 
@@ -440,14 +440,14 @@ PRIVATE int style_readFromFileREC ARGS2(char*, file, int, toplevel)
     char *buffer = NULL;
     int len;
 
-    CTRACE((tfp, "CSS:Reading styles from file: %s\n", file ? file : "?!? empty ?!?"));
+    CTRACE2(TRACE_STYLE, (tfp, "CSS:Reading styles from file: %s\n", file ? file : "?!? empty ?!?"));
     if (file == NULL || *file == '\0')
 	return -1;
     fh = fopen(file, TXT_R);
     if (!fh)
     {
 	/* this should probably be an alert or something */
-	CTRACE((tfp, "CSS:Can't open style file '%s', using defaults\n", file));
+	CTRACE2(TRACE_STYLE, (tfp, "CSS:Can't open style file '%s', using defaults\n", file));
 	return -1;
     }
 
@@ -520,7 +520,9 @@ PUBLIC void FastTrimColorClass ARGS5 (
     char* tag_start = *pstylename_end;
     BOOLEAN found = FALSE;
 
-    CTRACE((tfp, "STYLE.fast-trim: [%s] from [%s]: ", tag_name, stylename));
+    CTRACE2(TRACE_STYLE,
+	    (tfp, "STYLE.fast-trim: [%s] from [%s]: ",
+		  tag_name, stylename));
     while (tag_start >= stylename)
     {
 	for (; (tag_start >= stylename) && (*tag_start != ';') ; --tag_start)
@@ -535,7 +537,7 @@ PUBLIC void FastTrimColorClass ARGS5 (
 	*tag_start = '\0';
 	*pstylename_end = tag_start;
     }
-    CTRACE((tfp, found ? "success.\n" : "failed.\n"));
+    CTRACE2(TRACE_STYLE, (tfp, found ? "success.\n" : "failed.\n"));
     *phcode = hash_code(tag_start+1);
 }
 
@@ -551,7 +553,7 @@ PUBLIC void cache_tag_styles NOARGS
     {
 	strcpy(buf, HTML_dtd.tags[i].name);
 	LYLowerCase(buf);
-	cached_tag_styles[i] =hash_code(buf);
+	cached_tag_styles[i] = hash_code(buf);
     }
 }
 
diff --git a/src/LYUtils.c b/src/LYUtils.c
index 61a746bf..5b754ddf 100644
--- a/src/LYUtils.c
+++ b/src/LYUtils.c
@@ -6,9 +6,9 @@
 #include <HTAlert.h>
 #include <LYCurses.h>
 #include <LYHistory.h>
-#include <LYUtils.h>
 #include <LYStrings.h>
 #include <LYGlobalDefs.h>
+#include <LYUtils.h>
 #include <LYSignal.h>
 #include <GridText.h>
 #include <LYClean.h>
@@ -41,6 +41,15 @@ extern int exec_command(char * cmd, int wait_flag); /* xsystem.c */
 #include <bios.h>
 #endif /* DJGPP_KEYHANDLER */
 
+#ifdef __EMX__
+#  define BOOLEAN OS2_BOOLEAN		/* Conflicts, but is used */
+#  undef HT_ERROR			/* Conflicts too */
+#  define INCL_PM			/* I want some PM functions.. */
+#  define INCL_DOSPROCESS		/* TIB PIB. */
+#  include <os2.h>
+#  undef BOOLEAN
+#endif
+
 #ifdef VMS
 #include <descrip.h>
 #include <libclidef.h>
@@ -266,8 +275,9 @@ PUBLIC void highlight ARGS3(
 		 *  until we find one.
 		 */
 	    if (LYP >= 0 && LYP < CACHEH && LXP >= 0 && LXP < CACHEW) {
-		CTRACE((tfp, "STYLE.highlight.off: cached style @(%d,%d): ",
-			LYP, LXP));
+		CTRACE2(TRACE_STYLE,
+			(tfp, "STYLE.highlight.off: cached style @(%d,%d): ",
+			      LYP, LXP));
 		s = cached_styles[LYP][LXP];
 		if (s == 0) {
 		    for (x = LXP-1; x >= 0; x--) {
@@ -289,11 +299,11 @@ PUBLIC void highlight ARGS3(
 		    CTRACE((tfp, "found %d.\n", s));
 		}
 	    } else {
-		CTRACE((tfp, "STYLE.highlight.off: can't use cache.\n"));
+		CTRACE2(TRACE_STYLE, (tfp, "STYLE.highlight.off: can't use cache.\n"));
 		s = s_a;
 	    }
 	} else {
-	    CTRACE((tfp, "STYLE.highlight.on: @(%d,%d).\n", LYP, LXP));
+	    CTRACE2(TRACE_STYLE, (tfp, "STYLE.highlight.on: @(%d,%d).\n", LYP, LXP));
 	}
 	LYmove(LYP, LXP);
 	LynxChangeStyle(s, STACK_ON);
@@ -321,7 +331,7 @@ PUBLIC void highlight ARGS3(
 	    if (flag == OFF) {
 		hl2_drawn = TRUE;
 		redraw_lines_of_link(cur);
-		CTRACE((tfp, "STYLE.highlight.off: NOFIX branch @(%d,%d).\n", LYP, LXP));
+		CTRACE2(TRACE_STYLE, (tfp, "STYLE.highlight.off: NOFIX branch @(%d,%d).\n", LYP, LXP));
 	    } else
 #endif
 	    if (!hl1_drawn) {
@@ -352,9 +362,10 @@ PUBLIC void highlight ARGS3(
 #ifndef USE_COLOR_STYLE
 	    lynx_start_link_color (flag == ON, links[cur].inUnderline);
 #else
-	    CTRACE((tfp, "STYLE.highlight.line2: @(%d,%d), style=%d.\n",
-		    links[cur].ly + 1, links[cur].hightext2_offset,
-		    flag == ON ? s_alink : s_a));
+	    CTRACE2(TRACE_STYLE,
+		    (tfp, "STYLE.highlight.line2: @(%d,%d), style=%d.\n",
+			  links[cur].ly + 1, links[cur].hightext2_offset,
+			  flag == ON ? s_alink : s_a));
 	    LynxChangeStyle(flag == ON ? s_alink : s_a, ABS_ON);
 #endif
 
@@ -3472,6 +3483,16 @@ PUBLIC void size_change ARGS1(
 #endif /* TIOCGSIZE */
 #endif /* HAVE_SIZECHANGE */
 
+#ifdef __EMX__
+    {
+	int scrsize[2];
+
+	_scrsize(scrsize);
+	LYcols = scrsize[0];
+	LYlines = scrsize[1];
+    }
+#endif
+
     if (LYlines <= 0)
 	LYlines = DFT_ROWS;
     if (LYcols <= 0)
@@ -3876,9 +3897,10 @@ PRIVATE int fmt_tempname ARGS3(
     }
 #else
 #ifdef USE_RAND_TEMPNAME
+#define SIZE_TEMPNAME ((MAX_TEMPNAME / BITS_PER_CHAR) + 1)
     static BOOL first = TRUE;
     static int names_used = 0;
-    static unsigned char *used_tempname;
+    static unsigned char used_tempname[SIZE_TEMPNAME];
     unsigned offset, mask;
 #endif
     static unsigned counter;
@@ -3892,13 +3914,9 @@ PRIVATE int fmt_tempname ARGS3(
      * Prefer a random value rather than a counter.
      */
 #ifdef USE_RAND_TEMPNAME
-#define SIZE_TEMPNAME ((MAX_TEMPNAME / BITS_PER_CHAR) + 1)
     if (first) {
 	lynx_srand((unsigned)((long)time((time_t *)0) + (long)result));
 	first = FALSE;
-	used_tempname = typecallocn(unsigned char, SIZE_TEMPNAME);
-	if (used_tempname == 0)
-	    outofmem(__FILE__, "fmt_tempname");
     }
 
     /* We don't really need all of the bits from rand().  The high-order bits
@@ -3924,7 +3942,7 @@ PRIVATE int fmt_tempname ARGS3(
 	}
     }
     if (names_used >= MAX_TEMPNAME)
-	HTAlert("Too many tempfiles");
+	HTAlert(gettext("Too many tempfiles"));
 #else
     counter++;
 #endif
@@ -4059,6 +4077,9 @@ PRIVATE CONST struct {
     { "mail",		&no_mail,		CAN_ANONYMOUS_MAIL },
     { "dotfiles",	&no_dotfiles,		TRUE },
     { "useragent",	&no_useragent,		TRUE },
+#ifdef SUPPORT_CHDIR
+    { "chdir",		&no_chdir,		TRUE },
+#endif
 #ifdef DIRED_SUPPORT
     { "dired_support",	&no_dired_support,	TRUE },
 #ifdef OK_PERMIT
@@ -4075,9 +4096,41 @@ PRIVATE CONST struct {
     { "compileopts_info", &no_compileopts_info,	CAN_ANONYMOUS_VIEW_COMPILEOPTS_INFO },
 #endif
 #endif
+    /* put "goto" restrictions on the end, since they are a refinement */
 #ifndef DISABLE_BIBP
-    { "bibp:",		&no_goto_bibp,		TRUE },
+    { "goto_bibp",	&no_goto_bibp,		CAN_ANONYMOUS_GOTO_BIBP	},
+#endif
+#ifdef HAVE_CONFIG_H
+#ifndef NO_CONFIG_INFO
+    { "goto_configinfo", &no_goto_configinfo,	CAN_ANONYMOUS_GOTO_CONFIGINFO },
+#endif
+#endif
+    { "goto_cso",	&no_goto_cso,		CAN_ANONYMOUS_GOTO_CSO },
+    { "goto_file",	&no_goto_file,		CAN_ANONYMOUS_GOTO_FILE },
+#ifndef DISABLE_FINGER
+    { "goto_finger",	&no_goto_finger,	CAN_ANONYMOUS_GOTO_FINGER },
+#endif
+    { "goto_ftp",	&no_goto_ftp,		CAN_ANONYMOUS_GOTO_FTP },
+#ifndef DISABLE_GOPHER
+    { "goto_gopher",	&no_goto_gopher,	CAN_ANONYMOUS_GOTO_GOPHER },
+#endif
+    { "goto_http",	&no_goto_http,		CAN_ANONYMOUS_GOTO_HTTP },
+    { "goto_https",	&no_goto_https,		CAN_ANONYMOUS_GOTO_HTTPS },
+    { "goto_lynxcgi",	&no_goto_lynxcgi,	CAN_ANONYMOUS_GOTO_LYNXCGI },
+    { "goto_lynxexec",	&no_goto_lynxexec,	CAN_ANONYMOUS_GOTO_LYNXEXEC },
+    { "goto_lynxprog",	&no_goto_lynxprog,	CAN_ANONYMOUS_GOTO_LYNXPROG },
+    { "goto_mailto",	&no_goto_mailto,	CAN_ANONYMOUS_GOTO_MAILTO },
+#ifndef DISABLE_NEWS
+    { "goto_news",	&no_goto_news,		CAN_ANONYMOUS_GOTO_NEWS },
+    { "goto_nntp",	&no_goto_nntp,		CAN_ANONYMOUS_GOTO_NNTP },
 #endif
+    { "goto_rlogin",	&no_goto_rlogin,	CAN_ANONYMOUS_GOTO_RLOGIN },
+#ifndef DISABLE_NEWS
+    { "goto_snews",	&no_goto_snews,		CAN_ANONYMOUS_GOTO_SNEWS },
+#endif
+    { "goto_telnet",	&no_goto_telnet,	CAN_ANONYMOUS_GOTO_TELNET },
+    { "goto_tn3270",	&no_goto_tn3270,	CAN_ANONYMOUS_GOTO_TN3270 },
+    { "goto_wais",	&no_goto_wais,		CAN_ANONYMOUS_GOTO_WAIS },
 };
 
 /*  This will make no difference between '-' and '_'. It does only in/equality
@@ -4086,9 +4139,9 @@ PRIVATE CONST struct {
     value of zero) for compare of commandline options -VH
  */
 PUBLIC BOOL strn_dash_equ ARGS3(
-	CONST char*	,p1,
-	CONST char*	,p2,
-	int	,len)
+	CONST char*,	p1,
+	CONST char*,	p2,
+	int,		len)
 {
     while (len--) {
 	if (!*p2)
@@ -4124,13 +4177,44 @@ PUBLIC BOOL strn_dash_equ ARGS3(
 #	define RESTRICT_NM_EQU(a,b,len) STRNEQ(a,b,len)
 #endif
 
+/*
+ * Returns the inx'th name from the restrictions table, or null if inx is
+ * out of range.
+ */
+PUBLIC CONST char *index_to_restriction ARGS1(
+    int,	inx)
+{
+    if (inx >= 0 && inx < (int) TABLESIZE(restrictions))
+	return restrictions[inx].name;
+    return NULL;
+}
+
+/*
+ * Returns the value TRUE/FALSE of a given restriction, or -1 if it is not
+ * one that we recognize.
+ */
+PUBLIC int find_restriction ARGS2(
+    CONST char *,	name,
+    int,		len)
+{
+    unsigned i;
+    if (len < 0)
+	len = strlen(name);
+    for (i=0; i < TABLESIZE(restrictions); i++) {
+	if (RESTRICT_NM_EQU(name, restrictions[i].name, len)) {
+	    return (*restrictions[i].flag);
+	}
+    }
+    return -1;
+}
 
 PUBLIC void parse_restrictions ARGS1(
-	CONST char *,	s)
+    CONST char *,	s)
 {
     CONST char *p;
     CONST char *word;
     unsigned i;
+    BOOLEAN found;
 
     p = s;
     while (*p) {
@@ -4141,20 +4225,28 @@ PUBLIC void parse_restrictions ARGS1(
 	while (*p != ',' && *p != '\0')
 	    p++;
 
+	found = FALSE;
 	if (RESTRICT_NM_EQU(word, "all", p-word)) {
+	    found = TRUE;
 	    for (i = N_SPECIAL_RESTRICT_OPTIONS; i < TABLESIZE(restrictions); i++)
 		*(restrictions[i].flag) = TRUE;
 	} else if (RESTRICT_NM_EQU(word, "default", p-word)) {
+	    found = TRUE;
 	    for (i = N_SPECIAL_RESTRICT_OPTIONS; i < TABLESIZE(restrictions); i++)
 		*(restrictions[i].flag) = !restrictions[i].can;
 	} else {
 	    for (i=0; i < TABLESIZE(restrictions); i++) {
 		if (RESTRICT_NM_EQU(word, restrictions[i].name, p-word)) {
 		    *(restrictions[i].flag) = TRUE;
+		    found = TRUE;
 		    break;
 		}
 	    }
 	}
+	if (!found) {
+	    printf("%s: %.*s", gettext("unknown restriction"), p-word, word);
+	    exit(EXIT_FAILURE);
+	}
 	if (*p)
 	    p++;
     }
@@ -4176,9 +4268,11 @@ PUBLIC void print_restrictions_to_fd ARGS1(
     FILE *,	fp)
 {
     unsigned i, count = 0;
+
     for (i=0; i < TABLESIZE(restrictions); i++) {
-	if (*(restrictions[i].flag) == TRUE)
+	if (*(restrictions[i].flag) == TRUE) {
 	    count++;
+	}
     }
     if (!count) {
 	fprintf(fp, gettext("No restrictions set.\n"));
@@ -4187,7 +4281,12 @@ PUBLIC void print_restrictions_to_fd ARGS1(
     fprintf(fp, gettext("Restrictions set:\n"));
     for (i=0; i < TABLESIZE(restrictions); i++) {
 	if (*(restrictions[i].flag) == TRUE) {
-	    fprintf(fp, "   %s\n", restrictions[i].name);
+	    /* if "goto" is restricted, don't bother tell about its
+	     * refinements
+	     */
+	    if (strncmp(restrictions[i].name, "goto_", 5)
+	     || !no_goto)
+		fprintf(fp, "   %s\n", restrictions[i].name);
 	}
     }
 }
@@ -7606,13 +7705,7 @@ PUBLIC int LYSystem ARGS1(
     set_errno(saved_errno);	/* may have been clobbered */
 #endif
 #ifdef __EMX__			/* Check whether the screen size changed */
-    _scrsize(scrsize+2);
-    if ((scrsize[0] != scrsize[2]) || (scrsize[1] != scrsize[3])) {
-	CTRACE((tfp, "EMX update size...\n"));
-	LYcols = scrsize[2];
-	LYlines = scrsize[3];
-	recent_sizechange = TRUE;
-    }
+    size_change(0);
 #endif
     return code;
 }
@@ -7745,6 +7838,131 @@ PUBLIC void LYsetXDisplay ARGS1(
     }
 }
 
+#ifdef __EMX__
+
+static int proc_type = -1;
+static PPIB pib;
+HAB hab;
+HMQ hmq;
+
+PRIVATE void morph_PM NOARGS
+{
+    PTIB tib;
+    int first = 0;
+
+    if (proc_type == -1) {
+	DosGetInfoBlocks(&tib, &pib);
+	proc_type = pib->pib_ultype;
+	first = 1;
+    }
+    if (pib->pib_ultype != 3)		/* 2 is VIO */
+	pib->pib_ultype = 3;		/* 3 is PM */
+    if (first)
+	hab = WinInitialize(0);
+    /* 64 messages if before OS/2 3.0, ignored otherwise */
+    hmq = WinCreateMsgQueue(hab, 64);
+    WinCancelShutdown(hmq, 1);	/* Do not inform us on shutdown */
+}
+
+PRIVATE void unmorph_PM NOARGS
+{
+    WinDestroyMsgQueue(hmq);
+    pib->pib_ultype = proc_type;
+}
+
+PUBLIC int size_clip NOARGS
+{
+    return 8192;
+}
+
+/* Code partialy stolen from FED editor. */
+
+PUBLIC int put_clip ARGS1(char *, s)
+{
+    int sz = strlen(s) + 1;
+    int ret = EOF, nl = 0;
+    char *pByte = 0, *s1 = s, c, *t;
+
+    while ((c = *s1++)) {
+	if (c == '\r' && *s1 == '\n')
+	    s1++;
+	else if (c == '\n')
+	    nl++;
+    }
+    if (DosAllocSharedMem((PPVOID)&pByte, 0, sz + nl,
+			  PAG_WRITE | PAG_COMMIT | OBJ_GIVEABLE | OBJ_GETTABLE))
+	return ret;
+
+    if (!nl)
+	memcpy(pByte, s, sz);
+    else {
+	t = pByte;
+	while ((c = *t++ = *s++))
+	    if (c == '\n' && (t == pByte + 1 || t[-2] != '\r'))
+		t[-1] = '\r', *t++ = '\n';
+    }
+
+    morph_PM();
+    if(!hab)
+	goto fail;
+
+    WinOpenClipbrd(hab);
+    WinEmptyClipbrd(hab);
+    if (WinSetClipbrdData(hab, (ULONG) pByte, CF_TEXT, CFI_POINTER))
+	ret = 0;
+    WinCloseClipbrd(hab);
+    unmorph_PM();
+    if (ret == 0)
+	return 0;
+  fail:
+    DosFreeMem((PPVOID)&pByte);
+    return EOF;
+}
+
+static int clip_open;
+
+/* get_clip_grab() returns a pointer to the string in the system area.
+   get_clip_release() should be called ASAP after this. */
+
+PUBLIC char* get_clip_grab NOARGS
+{
+    char *ClipData;
+    ULONG ulFormat;
+    int sz;
+
+    morph_PM();
+    if(!hab)
+	return 0;
+    if (clip_open)
+	get_clip_release();
+
+    WinQueryClipbrdFmtInfo(hab, CF_TEXT, &ulFormat);
+    if(ulFormat != CFI_POINTER) {
+	unmorph_PM();
+	return 0;
+    }
+    WinOpenClipbrd(hab);
+    clip_open = 1;
+    ClipData = (char *)WinQueryClipbrdData(hab, CF_TEXT);
+    sz = strlen(ClipData);
+    if(!ClipData || !sz) {
+	get_clip_release();
+	return 0;
+    }
+    return ClipData;
+}
+
+PUBLIC void get_clip_release NOARGS
+{
+    if (!clip_open)
+	return;
+    WinCloseClipbrd(hab);
+    clip_open = 0;
+    unmorph_PM();
+}
+
+#endif
+
 #if defined(WIN_EX)	/* 1997/10/16 (Thu) 20:13:28 */
 
 #define	MAX_DOS_PATH	128	/* exactly 80 */
@@ -7798,10 +8016,15 @@ PUBLIC int put_clip(char *szBuffer)
     return 0;
 }
 
-PUBLIC int get_clip(char *szBuffer, int size)
+static HANDLE m_hLogData;
+static int m_locked;
+
+/* get_clip_grab() returns a pointer to the string in the system area.
+   get_clip_release() should be called ASAP after this. */
+
+PUBLIC char* get_clip_grab()
 {
     HANDLE hWnd;
-    HANDLE m_hLogData;
     LPTSTR pLogData;
     int val;
 
@@ -7810,28 +8033,26 @@ PUBLIC int get_clip(char *szBuffer, int size)
 	return 0;
     }
 
-    lstrcpy(szBuffer, "");
     m_hLogData = GetClipboardData(CF_TEXT);
 
     if (m_hLogData == NULL) {
-	val = 0;
-    } else {
-	pLogData = (LPTSTR) GlobalLock(m_hLogData);
-
-	val = strlen((LPTSTR) pLogData);
-	if (size > val)
-	    lstrcpy(szBuffer, (LPTSTR) pLogData);
-	else {
-	    val = size - 1;
-	    lstrcpyn(szBuffer, (LPTSTR) pLogData, val);
-	    szBuffer[val] = '\0';
-	}
-
-	GlobalUnlock(m_hLogData);
+	CloseClipboard();
+	m_locked = 0;
+	return 0;
     }
-    CloseClipboard();
+    pLogData = (LPTSTR) GlobalLock(m_hLogData);
 
-    return val;
+    m_locked = 1;
+    return pLogData;
+}
+
+PUBLIC void get_clip_release()
+{
+    if (!m_locked)
+	return;
+    GlobalUnlock(m_hLogData);
+    CloseClipboard();
+    m_locked = 0;
 }
 
 
diff --git a/src/LYUtils.h b/src/LYUtils.h
index c7671bc3..bc6ee44d 100644
--- a/src/LYUtils.h
+++ b/src/LYUtils.h
@@ -82,6 +82,7 @@ extern BOOLEAN LYisLocalHost PARAMS((char *filename));
 extern BOOLEAN LYisRootPath PARAMS((char *path));
 extern BOOLEAN inlocaldomain NOPARAMS;
 extern CONST char *Home_Dir NOPARAMS;
+extern CONST char *index_to_restriction PARAMS(( int	inx));
 extern FILE *LYAppendToTxtFile PARAMS((char * name));
 extern FILE *LYNewBinFile PARAMS((char * name));
 extern FILE *LYNewTxtFile PARAMS((char * name));
@@ -104,6 +105,7 @@ extern int LYOpenInternalPage PARAMS((FILE **fp0, char **newfile));
 extern int LYRemoveTemp PARAMS((char *name));
 extern int LYSystem PARAMS((char *command));
 extern int LYValidateOutput PARAMS((char * filename));
+extern int find_restriction PARAMS((CONST char * name, int len));
 extern int is_url PARAMS((char *filename));
 extern int number2arrows PARAMS((int number));
 extern time_t LYmktime PARAMS((char *string, BOOL absolute));
@@ -174,9 +176,20 @@ extern void LYRegisterUIPage PARAMS((CONST char * url, UIP_t type));
 #define LYUnRegisterUIPage(type) LYRegisterUIPage(NULL, type)
 extern void LYUIPages_free NOPARAMS;
 
-#if defined(WIN_EX)	/* 1997/10/16 (Thu) 20:13:28 */
+#ifdef CAN_CUT_AND_PASTE
 extern int put_clip(char *szBuffer);
-extern int get_clip(char *szBuffer, int size);
+/* get_clip_grab() returns a pointer to the string in the system area.
+   get_clip_release() should be called ASAP after this. */
+extern char* get_clip_grab(void);
+extern void  get_clip_release(void);
+#  ifdef WIN_EX
+#    define size_clip()	8192
+#  else
+extern int size_clip();
+#  endif
+#endif
+
+#if defined(WIN_EX)	/* 1997/10/16 (Thu) 20:13:28 */
 extern char *HTDOS_short_name(char *path);
 extern char *w32_strerror(DWORD ercode);
 #endif
diff --git a/src/TRSTable.c b/src/TRSTable.c
index 1037cf5f..8b752135 100644
--- a/src/TRSTable.c
+++ b/src/TRSTable.c
@@ -28,16 +28,16 @@
 			      value means cell was reserved by ROWSPAN */
 #define EOCOLG (-2)	/* sumcols' Line field isn't used for line info, this
 			      special value means end of COLGROUP */
-#ifndef NO_AGRESSIVE_NEWROW
-#  define NO_AGRESSIVE_NEWROW	0
+#ifndef NO_AGGRESSIVE_NEWROW
+#  define NO_AGGRESSIVE_NEWROW	0
 #endif
 
 typedef enum {
     CS_invalid = -1,		/* cell "before the first",
 				   or empty lines after [ce]bc,
 				   or TRST aborted */
-    CS__0new   = 0,		/* starts at BOL, new */
-    CS__new,			/* new */
+    CS__new     =  0,
+    CS__0new,			/* new, at BOL */
     CS__0eb,			/* starts at BOL, empty, break */
     CS__eb,			/* empty, break */
     CS__0cb,			/* starts at BOL, content, break */
@@ -50,22 +50,6 @@ typedef enum {
     CS__cbc			/* content, break, more content (maybe @BOL) */
 } cellstate_t;
 
-const char * const cellstate_s[] = {	/* Should be indexed by cellstate+1 */
-    "CS_invalid",
-    "CS__new",
-    "CS__0new",
-    "CS__0eb",
-    "CS__eb",
-    "CS__0cb",
-    "CS__cb",
-    "CS__0ef",
-    "CS__ef",
-    "CS__0cf",
-    "CS__cf",
-    "CS__ebc",
-    "CS__cbc"
-};
-
 typedef struct _STable_states {
     cellstate_t	prev_state;	/* Contents type of the previous cell */
     cellstate_t	state;		/* Contents type of the worked-on cell */
@@ -125,8 +109,10 @@ typedef struct _STable_rowinfo {
 } STable_rowinfo;
 
 struct _STable_info {
+#ifdef EXP_NESTED_TABLES
 	struct _STable_info *enclosing;	/* The table which contain us */
 	struct _TextAnchor  *enclosing_last_anchor_before_stbl;
+#endif
 	int	startline;	/* lineno where table starts (zero-based) */
 	int	nrows;		/* number of rows */
 	int	ncols;		/* number of rows */
@@ -202,20 +188,45 @@ PRIVATE int Stbl_finishCellInRow PARAMS((
 PRIVATE int Stbl_finishRowInTable PARAMS((
     STable_info *	me));
 
+PRIVATE CONST char * cellstate_s ARGS1(
+	cellstate_t,	state)
+{
+    CONST char *result = "?";
+
+    switch (state) {
+    case CS_invalid:	result = "CS_invalid";	break;
+    case CS__new:	result = "CS__new";	break;
+    case CS__0new:	result = "CS__0new";	break;
+    case CS__0eb:	result = "CS__0eb";	break;
+    case CS__eb:	result = "CS__eb";	break;
+    case CS__0cb:	result = "CS__0cb";	break;
+    case CS__cb:	result = "CS__cb";	break;
+    case CS__0ef:	result = "CS__0ef";	break;
+    case CS__ef:	result = "CS__ef";	break;
+    case CS__0cf:	result = "CS__0cf";	break;
+    case CS__cf:	result = "CS__cf";	break;
+    case CS__ebc:	result = "CS__ebc";	break;
+    case CS__cbc:	result = "CS__cbc";	break;
+    }
+    return result;
+}
 
 PUBLIC struct _STable_info * Stbl_startTABLE ARGS1(
     short,		alignment)
 {
     STable_info *me = typecalloc(STable_info);
 
-    CTRACE((tfp, "TRST:Stbl_startTABLE(align=%d)\n", (int)alignment));
+    CTRACE2(TRACE_TRST,
+	    (tfp, "TRST:Stbl_startTABLE(align=%d)\n", (int)alignment));
     if (me) {
 	me->alignment = alignment;
 	me->rowgroup_align = HT_ALIGN_NONE;
 	me->pending_colgroup_align = HT_ALIGN_NONE;
 	me->s.x_td = -1;
 	me->s.icell_core = -1;
+#ifdef EXP_NESTED_TABLES
 	me->enclosing = 0;
+#endif
     }
     return me;
 }
@@ -231,7 +242,8 @@ PRIVATE void free_rowinfo ARGS1(
 PUBLIC void Stbl_free ARGS1(
     STable_info *,	me)
 {
-    CTRACE((tfp, "TRST:Stbl_free()\n"));
+    CTRACE2(TRACE_TRST,
+	    (tfp, "TRST:Stbl_free()\n"));
     if (me && me->allocated_rows && me->rows) {
 	int i;
 	for (i = 0; i < me->allocated_rows; i++)
@@ -265,11 +277,13 @@ PRIVATE int Stbl_addCellToRow ARGS9(
     cellstate_t newstate;
     int ret;
 
-    CTRACE((tfp, "TRST:Stbl_addCellToRow, line=%d, pos=%d, colspan=%d\n",
-	   lineno, *ppos, colspan));
-    CTRACE((tfp, " ncells=%d, stateLine=%d, pending_len=%d, pstate=%s, state=%s\n",
-	    me->ncells, s->lineno, s->pending_len,
-	    cellstate_s[s->prev_state+1], cellstate_s[s->state+1]));
+    CTRACE2(TRACE_TRST,
+	    (tfp, "TRST:Stbl_addCellToRow, line=%d, pos=%d, colspan=%d\n",
+		   lineno, *ppos, colspan));
+    CTRACE2(TRACE_TRST,
+	    (tfp, " ncells=%d, stateLine=%d, pending_len=%d, pstate=%s, state=%s\n",
+		   me->ncells, s->lineno, s->pending_len,
+		   cellstate_s(s->prev_state), cellstate_s(s->state)));
     if (me->ncells == 0)
 	s->prev_state = CS_invalid;
     else if (s->prev_state == CS_invalid ||
@@ -461,7 +475,7 @@ PRIVATE int Stbl_addCellToRow ARGS9(
 	    }
 	}
 	if (i < me->ncells && me->cells[i].cLine != lineno)
-	    return -1;
+	    goto trace_and_fail;
 	me->Line = lineno;
 #endif
     }
@@ -528,8 +542,9 @@ PRIVATE int Stbl_addCellToRow ARGS9(
 
     ret = me->ncells - 1;
   trace_and_return:
-    CTRACE((tfp, " => prev_state=%s, state=%s, ret=%d\n",
-	    cellstate_s[s->prev_state+1], cellstate_s[s->state+1], ret));
+    CTRACE2(TRACE_TRST,
+	    (tfp, " => prev_state=%s, state=%s, ret=%d\n",
+		  cellstate_s(s->prev_state), cellstate_s(s->state), ret));
     return (ret);
 
   trace_and_fail:
@@ -548,8 +563,9 @@ PRIVATE int Stbl_reserveCellsInRow ARGS3(
     int i;
     int growby = icell + colspan - me->allocated;
 
-    CTRACE((tfp, "TRST:Stbl_reserveCellsInRow(icell=%d, colspan=%d\n",
-	   icell, colspan));
+    CTRACE2(TRACE_TRST,
+	    (tfp, "TRST:Stbl_reserveCellsInRow(icell=%d, colspan=%d\n",
+		  icell, colspan));
     if (growby > 0) {
 	cells = realloc(me->cells,
 			(me->allocated + growby)
@@ -588,8 +604,9 @@ PRIVATE int Stbl_finishCellInRow ARGS5(
     BOOL multiline = NO, empty;
     int ret;
 
-    CTRACE((tfp, "TRST:Stbl_finishCellInRow line=%d pos=%d end_td=%d ncells=%d pnd_len=%d\n",
-	   lineno, pos, (int)end_td, me->ncells, s->pending_len));
+    CTRACE2(TRACE_TRST,
+	    (tfp, "TRST:Stbl_finishCellInRow line=%d pos=%d end_td=%d ncells=%d pnd_len=%d\n",
+		  lineno, pos, (int)end_td, me->ncells, s->pending_len));
 
     if (me->ncells <= 0)
 	return -1;
@@ -597,9 +614,10 @@ PRIVATE int Stbl_finishCellInRow ARGS5(
     multiline = (lineno != lastcell->cLine || lineno != s->lineno);
     empty = multiline ? (pos == 0) : (pos <= s->x_td);
 
-    CTRACE((tfp, " [lines: lastCell=%d state=%d multi=%d] empty=%d (prev)state=(%s) %s\n",
-	   lastcell->cLine, s->lineno, multiline, empty,
-	    cellstate_s[s->prev_state+1], cellstate_s[s->state+1]));
+    CTRACE2(TRACE_TRST,
+	    (tfp, " [lines: lastCell=%d state=%d multi=%d] empty=%d (prev)state=(%s) %s\n",
+		  lastcell->cLine, s->lineno, multiline, empty,
+		  cellstate_s(s->prev_state), cellstate_s(s->state)));
 
     if (multiline) {
 	if (!end_td) {			/* processing line-break */
@@ -999,13 +1017,16 @@ PRIVATE int Stbl_finishCellInRow ARGS5(
 #endif /* MEGA_COMMENTOUT */
     s->state = newstate;
     ret = lastcell->len;
+#ifdef EXP_NESTED_TABLES
     if (ret == -1 && pos == 0)
 	ret = 0; /* XXXX Hack to allow trailing <P> in multiline cells. */
+#endif
 
 /*    lastcell->len = pos - lastcell->pos; */
   trace_and_return:
-    CTRACE((tfp, " => prev_state=%s, state=%s, return=%d\n",
-	    cellstate_s[s->prev_state+1], cellstate_s[s->state+1], ret));
+    CTRACE2(TRACE_TRST,
+	    (tfp, " => prev_state=%s, state=%s, return=%d\n",
+		  cellstate_s(s->prev_state), cellstate_s(s->state), ret));
     return ret;
 }
 
@@ -1024,11 +1045,13 @@ PRIVATE int Stbl_reserveCellsInTable ARGS4(
     STable_rowinfo *rows, *row;
     int growby;
     int i;
+
     if (me->nrows <= 0)
 	return -1;		/* must already have at least one row */
 
-    CTRACE((tfp, "TRST:Stbl_reserveCellsInTable(icell=%d, colspan=%d, rowspan=%d)\n",
-	   icell, colspan, rowspan));
+    CTRACE2(TRACE_TRST,
+	    (tfp, "TRST:Stbl_reserveCellsInTable(icell=%d, colspan=%d, rowspan=%d)\n",
+		  icell, colspan, rowspan));
     if (rowspan == 0) {
 	if (!me->rowspans2eog.cells) {
 	    me->rowspans2eog.cells = typecallocn(STable_cellinfo, icell + colspan);
@@ -1089,7 +1112,8 @@ PRIVATE void Stbl_cancelRowSpans ARGS1(
     STable_info *,	me)
 {
     int i;
-    CTRACE((tfp, "TRST:Stbl_cancelRowSpans()"));
+
+    CTRACE2(TRACE_TRST, (tfp, "TRST:Stbl_cancelRowSpans()"));
     for (i = me->nrows; i < me->allocated_rows; i++) {
 	if (!me->rows[i].ncells) { /* should always be the case */
 	    FREE(me->rows[i].cells);
@@ -1111,8 +1135,9 @@ PUBLIC int Stbl_addRowToTable ARGS3(
     STable_rowinfo *rows, *row;
     STable_states * s = &me->s;
 
-    CTRACE((tfp, "TRST:Stbl_addRowToTable(alignment=%d, lineno=%d)\n",
-	   alignment, lineno));
+    CTRACE2(TRACE_TRST,
+	    (tfp, "TRST:Stbl_addRowToTable(alignment=%d, lineno=%d)\n",
+		  alignment, lineno));
     if (me->nrows > 0 && me->rows[me->nrows-1].ncells > 0) {
 	if (s->pending_len > 0)
 	    me->rows[me->nrows-1].cells[me->rows[me->nrows-1].ncells - 1].len = s->pending_len;
@@ -1206,7 +1231,7 @@ PRIVATE int Stbl_finishRowInTable ARGS1(
     STable_states * s = &me->s;
     int ncells;
 
-    CTRACE((tfp, "TRST:Stbl_finishRowInTable()\n"));
+    CTRACE2(TRACE_TRST, (tfp, "TRST:Stbl_finishRowInTable()\n"));
     if (!me->rows || !me->nrows)
 	return -1;		/* no row started! */
     lastrow = me->rows + (me->nrows - 1);
@@ -1297,6 +1322,7 @@ PRIVATE int get_remaining_colspan ARGS5(
     return colspan;
 }
 
+#ifdef EXP_NESTED_TABLES
 /* Returns -1 on failure, 1 if faking was performed, 0 if not needed. */
 PRIVATE int Stbl_fakeFinishCellInTable ARGS4(
     STable_info *,	me,
@@ -1343,36 +1369,45 @@ PRIVATE int Stbl_fakeFinishCellInTable ARGS4(
 	int end_td = 1;
 	int need_reserved = 0;
 	int prev_reserved_last = -1;
-	STable_rowinfo *prev_row = lastrow;
+	STable_rowinfo *prev_row;
+	int prev_row_n2 = lastrow - me->rows;
 
-	CTRACE((tfp, "TRST:Stbl_fakeFinishCellInTable(lineno=%d, finishing=%d) START FAKING\n",
-		lineno, finishing));
+	CTRACE2(TRACE_TRST,
+		(tfp, "TRST:Stbl_fakeFinishCellInTable(lineno=%d, finishing=%d) START FAKING\n",
+		      lineno, finishing));
 
 	/* Although here we use pos=0, this may commit the previous
 	   cell which had <BR> as a last element.  This may overflow
 	   the screen width, so the additional checks performed in
 	   Stbl_finishCellInTable (comparing to Stbl_finishCellInRow)
 	   are needed. */
-	if (finishing)
+	if (finishing) {
 	    /* Fake </TD> at BOL */
-	    if (Stbl_finishCellInTable(me, end_td, lineno, 0) < 0)
+	    if (Stbl_finishCellInTable(me, end_td, lineno, 0) < 0) {
 		return -1;
+	    }
+	}
 
 	/* Fake </TR> at BOL */
 	/* Stbl_finishCellInTable(lineno, 0, 0);*/ /* Needed? */
 
 	/* Fake <TR> at BOL */
-	if (Stbl_addRowToTable(me, al, lineno) < 0)
+	if (Stbl_addRowToTable(me, al, lineno) < 0) {
 	    return -1;
+	}
 	lastrow = me->rows + (me->nrows - 1);
-	for (i = 0; i < lastrow->allocated; i++)
+	for (i = 0; i < lastrow->allocated; i++) {
 	    if (lastrow->cells[i].alignment == RESERVEDCELL) {
 		need_reserved = 1;
 		break;
 	    }
-	for (i = ncells; i < prev_row->allocated; i++)
+	}
+
+	prev_row = me->rows + prev_row_n2;
+	for (i = ncells; i < prev_row->allocated; i++) {
 	    if (prev_row->cells[i].alignment == RESERVEDCELL)
 		prev_reserved_last = i;
+	}
 	if (need_reserved || prev_reserved_last >= 0) {
 	    /* Oups, we are going to stomp over a line which somebody
 	       cares about already, or the previous line had reserved
@@ -1390,7 +1425,8 @@ PRIVATE int Stbl_fakeFinishCellInTable ARGS4(
 	    if (!rows)
 		return -1; /* ignore silently, no free memory, may be recoverable */
 
-	    CTRACE((tfp, "TRST:Stbl_fakeFinishCellInTable REALLOC ROWSPAN\n"));
+	    CTRACE2(TRACE_TRST,
+		    (tfp, "TRST:Stbl_fakeFinishCellInTable REALLOC ROWSPAN\n"));
 	    me->rows = rows;
 	    lastrow = me->rows + (me->nrows - 1);
 	    prev_row = me->rows + prev_row_n;
@@ -1406,8 +1442,9 @@ PRIVATE int Stbl_fakeFinishCellInTable ARGS4(
 	    if (need_cells) {
 		lastrow->cells = typecallocn(STable_cellinfo, need_cells);
 		/* ignore silently, no free memory, may be recoverable */
-		if (!lastrow->cells)
+		if (!lastrow->cells) {
 		    return -1;
+		}
 		lastrow->allocated = need_cells;
 		memcpy(lastrow->cells, prev_row->cells,
 		       lastrow->allocated * sizeof(STable_cellinfo));
@@ -1425,26 +1462,32 @@ PRIVATE int Stbl_fakeFinishCellInTable ARGS4(
 	}
 
 	/* Fake <TD></TD>...<TD> (and maybe a </TD>) at BOL. */
-	CTRACE((tfp, "TRST:Stbl_fakeFinishCellInTable FAKE %d elts%s\n",
-		ncells, (finishing ? ", last unfinished" : "")));
+	CTRACE2(TRACE_TRST,
+		(tfp, "TRST:Stbl_fakeFinishCellInTable FAKE %d elts%s\n",
+		      ncells, (finishing ? ", last unfinished" : "")));
 	i = 0;
 	while (++i <= ncells) {
 	    /* XXXX A lot of args may be wrong... */
 	    if (Stbl_addCellToTable(me, (i==ncells ? cs : 1), rs, al,
-				    ih, lineno, 0) < 0)
+				    ih, lineno, 0) < 0) {
 		return -1;
+	    }
 	    /* We cannot run out of width here, so it is safe to not
 	       call Stbl_finishCellInTable(), but Stbl_finishCellInRow. */
-	    if (!finishing || (i != ncells))
-		if (Stbl_finishCellInRow(lastrow, s, end_td, lineno, 0) < 0)
+	    if (!finishing || (i != ncells)) {
+		if (Stbl_finishCellInRow(lastrow, s, end_td, lineno, 0) < 0) {
 		    return -1;
+		}
+	    }
 	}
-	CTRACE((tfp, "TRST:Stbl_fakeFinishCellInTable(lineno=%d) FINISH FAKING\n",
-		lineno));
+	CTRACE2(TRACE_TRST,
+		(tfp, "TRST:Stbl_fakeFinishCellInTable(lineno=%d) FINISH FAKING\n",
+		      lineno));
 	return 1;
     }
     return 0;
 }
+#endif
 
 /*
  * Returns -1 on error, otherwise 0.
@@ -1466,18 +1509,19 @@ PUBLIC int Stbl_addCellToTable ARGS7(
     int prevsumpos, advance;
 #endif
 
-    CTRACE((tfp, "TRST:Stbl_addCellToTable(lineno=%d, pos=%d, isheader=%d, cs=%d, rs=%d, al=%d)\n",
-	   lineno, pos, (int)isheader, colspan,rowspan,alignment));
+    CTRACE2(TRACE_TRST,
+	    (tfp, "TRST:Stbl_addCellToTable(lineno=%d, pos=%d, isheader=%d, cs=%d, rs=%d, al=%d)\n",
+		  lineno, pos, (int)isheader, colspan, rowspan, alignment));
     if (!me->rows || !me->nrows)
 	return -1;		/* no row started! */
 				/* ##850_fail_if_fail?? */
-    Stbl_finishCellInTable(me, YES,
-			   lineno, pos);
+    Stbl_finishCellInTable(me, YES, lineno, pos);
     lastrow = me->rows + (me->nrows - 1);
 
+#ifdef EXP_NESTED_TABLES
     /* If the last cell was finished by <BR></TD>, we need to fake an
        appropriate amount of cells */
-    if (!NO_AGRESSIVE_NEWROW && pos == 0 && lastrow->ncells > 0
+    if (!NO_AGGRESSIVE_NEWROW && pos == 0 && lastrow->ncells > 0
 	&& lastrow->cells[lastrow->ncells-1].cLine != lineno) {
 	int rc = Stbl_fakeFinishCellInTable(me, lastrow, lineno, 0);
 
@@ -1486,6 +1530,7 @@ PUBLIC int Stbl_addCellToTable ARGS7(
 	if (rc)
 	    lastrow = me->rows + (me->nrows - 1);
     }
+#endif
     if (colspan == 0) {
 	colspan = get_remaining_colspan(lastrow, me->sumcols, me->ncolinfo,
 					colspan, me->ncols);
@@ -1596,8 +1641,9 @@ PUBLIC int Stbl_finishCellInTable ARGS4(
     int len, xlen, icell;
     int i;
 
-    CTRACE((tfp, "TRST:Stbl_finishCellInTable(lineno=%d, pos=%d, end_td=%d)\n",
-	   lineno, pos, (int)end_td));
+    CTRACE2(TRACE_TRST,
+	    (tfp, "TRST:Stbl_finishCellInTable(lineno=%d, pos=%d, end_td=%d)\n",
+		  lineno, pos, (int)end_td));
     if (me->nrows == 0)
 	return -1;
     lastrow = me->rows + (me->nrows - 1);
@@ -1607,8 +1653,9 @@ PUBLIC int Stbl_finishCellInTable ARGS4(
     if (s->x_td == -1)
 	return end_td ? -1 : 0;
 
+#ifdef EXP_NESTED_TABLES
     /* This check for pos saves us from infinite recursion... */
-    if (!NO_AGRESSIVE_NEWROW && pos) {
+    if (!NO_AGGRESSIVE_NEWROW && pos) {
 	int rc = Stbl_fakeFinishCellInTable(me, lastrow, lineno, 1);
 
 	if (rc) {
@@ -1618,6 +1665,7 @@ PUBLIC int Stbl_finishCellInTable ARGS4(
 	    icell = lastrow->ncells - 1;
 	}
     }
+#endif
     len = Stbl_finishCellInRow(lastrow, s, end_td, lineno, pos);
     if (len == -1)
 	return len;
@@ -1710,7 +1758,7 @@ PUBLIC int Stbl_finishCellInTable ARGS4(
     }
 #endif
 
-#if 0	/* maxlen may already include contribution of a cell in this column */
+#ifndef EXP_NESTED_TABLES /* maxlen may already include contribution of a cell in this column */
     if (me->maxlen + (xlen - len) > MAX_STBL_POS)
 	return -1;
 #endif
@@ -1737,8 +1785,9 @@ PUBLIC int Stbl_addColInfo ARGS4(
     STable_cellinfo *sumcols, *sumcol;
     int i, icolinfo;
 
-    CTRACE((tfp, "TRST:Stbl_addColInfo(cs=%d, al=%d, isgroup=%d)\n",
-	   colspan, alignment, (int)isgroup));
+    CTRACE2(TRACE_TRST,
+	    (tfp, "TRST:Stbl_addColInfo(cs=%d, al=%d, isgroup=%d)\n",
+		  colspan, alignment, (int)isgroup));
     if (isgroup) {
 	if (me->pending_colgroup_next > me->ncolinfo)
 	    me->ncolinfo = me->pending_colgroup_next;
@@ -1798,7 +1847,7 @@ PUBLIC int Stbl_addColInfo ARGS4(
 PUBLIC int Stbl_finishColGroup ARGS1(
     STable_info *,	me)
 {
-    CTRACE((tfp, "TRST:Stbl_finishColGroup()\n"));
+    CTRACE2(TRACE_TRST, (tfp, "TRST:Stbl_finishColGroup()\n"));
     if (me->pending_colgroup_next >= me->ncolinfo) {
 	me->ncolinfo = me->pending_colgroup_next;
 	if (me->ncolinfo > 0)
@@ -1813,7 +1862,7 @@ PUBLIC int Stbl_addRowGroup ARGS2(
     STable_info *,	me,
     short,		alignment)
 {
-    CTRACE((tfp, "TRST:Stbl_addRowGroup()\n"));
+    CTRACE2(TRACE_TRST, (tfp, "TRST:Stbl_addRowGroup()\n"));
     Stbl_cancelRowSpans(me);
     me->rowgroup_align = alignment;
     return 0;			/* that's all! */
@@ -1826,7 +1875,7 @@ PUBLIC int Stbl_finishTABLE ARGS1(
     int i;
     int curpos = 0;
 
-    CTRACE((tfp, "TRST:Stbl_finishTABLE()\n"));
+    CTRACE2(TRACE_TRST, (tfp, "TRST:Stbl_finishTABLE()\n"));
     if (!me || me->nrows <= 0 || me->ncols <= 0) {
 	return -1;
     }
@@ -1945,6 +1994,8 @@ PUBLIC int Stbl_getStartLine ARGS1(
 	return me->startline;
 }
 
+#ifdef EXP_NESTED_TABLES
+
 PUBLIC void Stbl_update_enclosing ARGS3(
     STable_info *,	me,
     int,		max_width,
@@ -1954,24 +2005,25 @@ PUBLIC void Stbl_update_enclosing ARGS3(
 
     if (!me || !me->enclosing || !max_width)
 	return;
-    CTRACE((tfp, "TRST:Stbl_update_enclosing, width=%d, lines=%d...%d.\n",
+    CTRACE2(TRACE_TRST, (tfp, "TRST:Stbl_update_enclosing, width=%d, lines=%d...%d.\n",
 	    max_width, me->startline, last_lineno));
-    for (l = me->startline; l <= last_lineno; l++)
+    for (l = me->startline; l <= last_lineno; l++) {
 	/* Fake <BR> in appropriate positions */
 	if (Stbl_finishCellInTable(me->enclosing, 0, l, max_width) < 0) {
 	    /* It is not handy to let the caller delete me->enclosing,
 	       and it does not buy us anything.  Do it directly. */
 	    STable_info *stbl = me->enclosing;
 
-	    CTRACE((tfp, "TRST:Stbl_update_enclosing: width too large, aborting enclosing\n"));
+	    CTRACE2(TRACE_TRST, (tfp, "TRST:Stbl_update_enclosing: width too large, aborting enclosing\n"));
 	    me->enclosing = 0;
 	    while (stbl) {
 		STable_info *enclosing = stbl->enclosing;
 		Stbl_free(stbl);
 		stbl = enclosing;
 	    }
-	    return;
+	    break;
 	}
+    }
     return;
 }
 
@@ -2001,3 +2053,4 @@ PUBLIC struct _TextAnchor * Stbl_get_last_anchor_before ARGS1(
 	return 0;
     return me->enclosing_last_anchor_before_stbl;
 }
+#endif
diff --git a/src/TRSTable.h b/src/TRSTable.h
index c89427b1..5eb48ce5 100644
--- a/src/TRSTable.h
+++ b/src/TRSTable.h
@@ -24,6 +24,7 @@ extern int Stbl_getFixupPositions PARAMS((
     int *		newpos));
 extern short Stbl_getAlignment PARAMS((STable_info *));
 
+#ifdef EXP_NESTED_TABLES
 extern void Stbl_update_enclosing PARAMS((
     STable_info *	me,
     int			max_width,
@@ -34,5 +35,6 @@ extern void Stbl_set_enclosing PARAMS(( STable_info *me,
 					struct _TextAnchor *last_anchor));
 extern STable_info * Stbl_get_enclosing PARAMS((STable_info *	me));
 extern struct _TextAnchor * Stbl_get_last_anchor_before PARAMS((STable_info *	me));
+#endif
 
 #endif /* TRSTABLE_H */
diff --git a/src/UCAuto.c b/src/UCAuto.c
index 5ed8ece8..e37944ff 100644
--- a/src/UCAuto.c
+++ b/src/UCAuto.c
@@ -23,9 +23,29 @@
 #include <LYGlobalDefs.h>
 #include <LYClean.h>
 #include <LYLeaks.h>
+#include <LYCharSets.h>
 
 #ifdef EXP_CHARTRANS_AUTOSWITCH
 
+#  ifdef CAN_SWITCH_DISPLAY_CHARSET
+char *charset_switch_rules;
+char *charsets_directory;
+int auto_other_display_charset = -1;
+int codepages[2];
+int real_charsets[2] = {-1, -1};	/* Non "auto-" charsets for the cps */
+int switch_display_charsets;
+#  endif
+
+#  ifdef __EMX__
+/* If we "just include" <os2.h>, BOOLEAN conflicts. */
+#  define BOOLEAN OS2_BOOLEAN		/* This file doesn't use it, conflicts */
+#  define INCL_VIO			/* I want some Vio functions.. */
+#  define INCL_DOSPROCESS			/* TIB PIB. */
+#  define INCL_DOSNLS			/* DosQueryCp. */
+#  include <os2.h>			/* Misc stuff.. */
+#  include <os2thunk.h>			/* 32 bit to 16 bit pointer conv */
+#  endif
+
 #ifdef LINUX
 typedef enum {
     Is_Unset, Is_Set, Dunno, Dont_Care
@@ -440,16 +460,218 @@ PUBLIC void UCChangeTerminalCodepage ARGS2(
 #ifdef __EMX__
     int res = 0;
 
-    if (p->codepage > 0) {
-	res = VioSetCp(0, p->codepage, 0);
-	CTRACE((tfp, "UCChangeTerminalCodepage: VioSetCp(%d) returned %d\n", p->codepage, res));
-    }
+    if (newcs < 0)
+	newcs = auto_display_charset;
+    res = Switch_Display_Charset(newcs, 1);
+    CTRACE((tfp, "UCChangeTerminalCodepage: Switch_Display_Charset(%d) returned %d\n", newcs, res));
 #else
     CTRACE((tfp, "UCChangeTerminalCodepage: Called, but not implemented!"));
 #endif
 }
 #endif /* LINUX */
 
+#ifdef CAN_SWITCH_DISPLAY_CHARSET
+
+PUBLIC int Find_Best_Display_Charset ARGS1 (int, ord)
+{
+    CONST char *name = LYCharSet_UC[ord].MIMEname;
+    char *s = charset_switch_rules, *r;
+    char buf[160];
+    static int lowercase;
+    int n = strlen(name), source = 1;
+
+    if (!s || !n)
+	return ord;
+    if (!lowercase++)
+	LYLowerCase(charset_switch_rules);
+    while (1) {
+	while (*s && strchr(" \t,", *s))
+	    s++;			/* Go to start of a name or ':' */
+	if (!*s && source)
+	    return ord;			/* OK to find nothing */
+	if (!*s) {
+	    sprintf(buf, "No destination for '%.80s' in CHARSET_SWITCH_RULES",
+		    name);
+	    HTInfoMsg(buf);
+	    return ord;
+	}
+	if (*s == ':') {
+	    /* Before the replacement name */
+	    while (*s && strchr(" \t:", *s))
+		s++;			/* Go to the replacement */
+	    /* At start of the replacement name */
+	    r = s;
+	    while (*s && !strchr(" \t,:", *s))
+		s++;			/* Skip the replacement */
+	    if (source)
+		continue;
+	    break;
+	}
+	/* At start of the source name */
+	if (source && !strnicmp(name, s, n) && strchr(" \t,", s[n])) {/* Found! */
+	    source = 0;
+	    s += n;
+	    continue;			/* Look for the replacement */
+	}
+	while (*s && !strchr(" \t,:", *s))
+	    s++;			/* Skip the other source names */
+    }
+    /* Here r point to the replacement, s to the end of the replacement. */
+    if (s >= r + sizeof(buf)) {
+	HTInfoMsg("Charset name in CHARSET_SWITCH_RULES too long");
+	return ord;
+    }
+    strncpy(buf, r, s-r);
+    buf[s-r] = '\0';
+    n = UCGetLYhndl_byMIME(buf);
+    if (n < 0) {
+	sprintf(buf, "Unknown charset name '%.*s' in CHARSET_SWITCH_RULES",
+		s-r, r);
+	HTInfoMsg(buf);
+	return ord;
+    }
+    return n;
+}
+
+#  ifdef __EMX__
+/* Switch display for the best fit for LYCharSet_UC[ord].
+   If !REALLY, the switch is tentative only, another switch may happen
+   before the actual display.
+
+   Returns the charset we switched to.  */
+PRIVATE int _Switch_Display_Charset ARGS2 (int, ord, int, really)
+{
+    CONST char *name;
+    unsigned short cp;
+    static int font_loaded_for = -1;
+    int rc, ord1;
+    UCHAR msgbuf[MAXPATHLEN + 80];
+
+    CTRACE((tfp, "_Switch_Display_Charset(cp=%d, really=%d).\n", ord, really));
+    /* Do not trust current_char_set if really, we fake it without really! */
+    if (ord == current_char_set && !really)
+	return ord;
+    if (ord == auto_other_display_charset
+	|| ord == auto_display_charset || ord == font_loaded_for) {
+	if (!really)
+	    return ord; /* Report success, to avoid flicker, switch later */
+    } else	/* Currently supports only koi8-r to cp866 translation */
+	ord = Find_Best_Display_Charset(ord);
+
+    if (ord == real_charsets[0] || ord == real_charsets[1]) {
+	ord1 = (ord == real_charsets[1]
+	       ? auto_other_display_charset : auto_display_charset);
+	if (!really)
+	    return ord; /* Can switch later, report success to avoid flicker */
+    } else
+	ord1 = ord;
+    if (ord == current_char_set && !really)
+	return ord;
+
+    name = LYCharSet_UC[ord1].MIMEname;
+    if (ord1 == auto_other_display_charset || ord1 == auto_display_charset) {
+      retry:
+	rc = VioSetCp(0,codepages[ord1 == auto_other_display_charset],0);
+	if (rc == 0)
+	    goto report;
+      err:
+	sprintf(msgbuf, "Can't change to '%s': err=%#lx=%ld", name, rc, rc);
+	HTInfoMsg(msgbuf);
+	return -1;
+    }
+
+    /* Not a "prepared" codepage.  Need to load the user font. */
+    if (ord1 == font_loaded_for) {	/* The same as the previous font */
+	if ((rc = VioSetCp(0, -1, 0)))	/* -1: User font */
+	    goto err;
+    } else if (charsets_directory) {
+	TIB *tib;			/* Can't load font in a windowed-VIO */
+	PIB *pib;
+	VIOFONTINFO f[2];
+	VIOFONTINFO *font;
+	UCHAR b[1<<17];
+	UCHAR *buf = b;
+	UCHAR fnamebuf[MAXPATHLEN];
+	FILE  *file;
+	APIRET rc;
+	long i, j;
+
+	/* 0 means a FS protected-mode session */
+	if (DosGetInfoBlocks(&tib, &pib) || pib->pib_ultype != 0) {
+	    ord = ord1 = auto_display_charset;
+	    goto retry;
+	}
+	/* Should not cross 64K boundaries: */
+	font = f;
+	if (((((ULONG)(char*)f) + sizeof(*font)) & 0xFFFF) < sizeof(*font))
+	    font++;
+	if (((ULONG)buf) & 0xFFFF)
+	    buf += 0x10000 - (((ULONG)buf) & 0xFFFF);
+	font->cb = sizeof(*font);	/* How large is this structure */
+	font->type=0;			/* Not the BIOS, the loaded font. */
+	font->cbData = 65535;		/* How large is my buffer? */
+	font->pbData = _emx_32to16(buf); /* Wants an 16:16 pointer */
+
+	rc = VioGetFont(font,0);	/* Retrieve data for current font */
+	if (rc) {
+	    sprintf(msgbuf, "Can't fetch current font info: err=%#lx=%ld", rc, rc);
+	    HTInfoMsg(msgbuf);
+	    ord = ord1 = auto_display_charset;
+	    goto retry;
+	}
+	sprintf(fnamebuf, "%s/%dx%d/%s.fnt",
+		charsets_directory, font->cyCell, font->cxCell, name);
+	file = fopen(fnamebuf,"rb");
+	if (!file) {
+	    sprintf(msgbuf, "Can't open font file '%s'", fnamebuf);
+	    HTInfoMsg(msgbuf);
+	    ord = ord1 = auto_display_charset;
+	    goto retry;
+	}
+	i = ftell(file);
+	fseek(file, 0, SEEK_END);
+	if (ftell(file) - i != font->cbData) {
+	    fclose(file);
+	    sprintf(msgbuf, "Mismatch of size of font file '%s'", fnamebuf);
+	    HTAlert(msgbuf);
+	    ord = ord1 = auto_display_charset;
+	    goto retry;
+	}
+	fseek(file, i, SEEK_SET);
+	fread(buf, 1, font->cbData,file);
+	fclose(file);
+	rc = VioSetFont(font,0);	/* Put it all back.. */
+	if (rc) {
+	    sprintf(msgbuf, "Can't set font: err=%#lx=%ld", rc, rc);
+	    HTInfoMsg(msgbuf);
+	    ord = ord1 = auto_display_charset;
+	    goto retry;
+	}
+	font_loaded_for = ord1;
+    }
+  report:
+    CTRACE((tfp, "Display font set to '%s'.\n", name));
+    return ord;
+}
+#  endif /* __EMX__ */
+
+PUBLIC int Switch_Display_Charset ARGS2 (CONST int, ord, CONST int, really)
+{
+    int prev = current_char_set;
+    int res;
+
+    if (!switch_display_charsets && !really)
+	return 0;
+    res = _Switch_Display_Charset(ord, really);
+    if (res < 0 || prev == res)		/* No change */
+	return 0;
+    /* Register the change */
+    current_char_set = res;
+    HTMLUseCharacterSet(current_char_set);
+    return 1;
+}
+#endif /* CAN_SWITCH_DISPLAY_CHARSET */
+
 #else /* EXP_CHARTRANS_AUTOSWITCH not defined: */
 /*
  *  This is the thing that actually gets called from display_page().
diff --git a/src/UCdomap.c b/src/UCdomap.c
index 417b841c..cc725694 100644
--- a/src/UCdomap.c
+++ b/src/UCdomap.c
@@ -75,12 +75,6 @@
 
 #ifdef CAN_AUTODETECT_DISPLAY_CHARSET
 int auto_display_charset = -1;
-#  ifdef __EMX__
-/* If we include <os2.h>, BOOLEAN conflicts.  Just copy the proto: */
-unsigned long DosQueryCp (unsigned long ulLength,
-			  unsigned long* pCodePageList,
-			  unsigned long* pDataLength);
-#  endif
 #endif
 
 /*
@@ -1738,9 +1732,9 @@ PRIVATE CONST char ** UC_setup_LYCharSets_repl ARGS2(
 {
     CONST char **ISO_Latin1 = LYCharSets[0];
     CONST char **p;
-    CONST char **prepl;
+    char **prepl;
     CONST u16 *pp;
-    CONST char **tp;
+    char **tp;
     CONST char *s7;
     CONST char *s8;
     size_t i;
@@ -1751,7 +1745,7 @@ PRIVATE CONST char ** UC_setup_LYCharSets_repl ARGS2(
     /*
      *	Create a temporary table for reverse lookup of latin1 codes:
      */
-    tp = (CONST char **)malloc(96 * sizeof(CONST char *));
+    tp = (char **)malloc(96 * sizeof(char *));
     if (!tp)
 	return NULL;
     for (i = 0; i < 96; i++)
@@ -1796,7 +1790,7 @@ PRIVATE CONST char ** UC_setup_LYCharSets_repl ARGS2(
 	list = UCInfo[UC_charset_in_hndl].replacedesc.entries;
 	while (ct--) {
 	    if ((k = list->unicode) >= 160 && k < 256) {
-		tp[k-160] = list->replace_str;
+		tp[k-160] = (char *)list->replace_str;
 	    }
 	    list++;
 	}
@@ -1805,14 +1799,14 @@ PRIVATE CONST char ** UC_setup_LYCharSets_repl ARGS2(
      *	Now allocate a new table compatible with LYCharSets[]
      *	and with the HTMLDTD for entities.
      *	We don't know yet whether we'll keep it around. */
-    prepl = (CONST char **)malloc(HTML_dtd.number_of_entities * sizeof(char *));
+    prepl = (char **)malloc(HTML_dtd.number_of_entities * sizeof(char *));
     if (!prepl) {
 	FREE(tp);
 	FREE(ti);
 	return 0;
     }
 
-    p = prepl;
+    p = (CONST char **)prepl;
     changed = 0;
     for (i = 0; i < HTML_dtd.number_of_entities; i++, p++) {
 	/*
@@ -1883,7 +1877,7 @@ PRIVATE CONST char ** UC_setup_LYCharSets_repl ARGS2(
 	FREE(prepl);
 	return NULL;
     }
-    return prepl;
+    return (CONST char **)prepl;
 }
 
 /*
@@ -2164,6 +2158,47 @@ PRIVATE void UCcleanup_mem NOARGS
 }
 #endif /* LY_FIND_LEAKS */
 
+#ifdef CAN_AUTODETECT_DISPLAY_CHARSET
+#  ifdef __EMX__
+PRIVATE int CpOrdinal ARGS2 (CONST unsigned long, cp, CONST int, other)
+{
+    char lyName[80];
+    char myMimeName[80];
+    char *mimeName, *mName = NULL, *lName = NULL;
+    int s, i, exists = 0, ret;
+
+    CTRACE((tfp, "CpOrdinal(cp=%ul, other=%d).\n", cp, other));
+    sprintf(myMimeName, "auto%s-cp%lu", (other ? "2" : ""), cp);
+    mimeName = myMimeName + 5 + (other != 0);
+    sprintf(lyName, "AutoDetect%s (cp%lu)",
+	    (other ? "-2" : ""), cp);
+    /* Find slot. */
+    s = -1;
+    for (i = 0; i < UCNumCharsets; i++) {
+	if (!strcmp(UCInfo[i].LYNXname, lyName))
+	    return UCGetLYhndl_byMIME(myMimeName);
+	else if (!strcasecomp(UCInfo[i].MIMEname, mimeName))
+	    s = i;
+    }
+    if (s < 0)
+	return -1;
+    /* Store the "real" charset info */
+    real_charsets[other != 0] = UCGetLYhndl_byMIME(mimeName);
+    /* Duplicate the record. */
+    StrAllocCopy(mName, myMimeName);
+    StrAllocCopy(lName, lyName);
+    UC_Charset_Setup(mName, lName,
+		     UCInfo[s].unicount, UCInfo[s].unitable,
+		     UCInfo[s].num_uni, UCInfo[s].replacedesc,
+		     UCInfo[s].lowest_eight, UCInfo[s].enc,
+		     UCInfo[s].codepage);
+    ret = UCGetLYhndl_byMIME(myMimeName);
+    CTRACE((tfp, "Found %i.\n", ret));
+    return ret;
+}
+#  endif /* __EMX__ */
+#endif /* CAN_AUTODETECT_DISPLAY_CHARSET */
+
 PUBLIC void UCInit NOARGS
 {
 
@@ -2241,34 +2276,21 @@ PUBLIC void UCInit NOARGS
 #  ifdef __EMX__
     {
 	unsigned long lst[3];
-	unsigned long len;
-
-	if (DosQueryCp(sizeof(lst), lst, &len) == 0 && len >= 1) {
-	    static char lyName[80];
-	    static char myMimeName[80];
-	    char *mimeName;
-	    int s, i, exists = 0;
-
-	    sprintf(myMimeName, "auto-cp%lu", lst[0]);
-	    mimeName = myMimeName + 5;
-	    sprintf(lyName, "AutoDetect (cp%lu)", lst[0]);
-	    /* Find slot. */
-	    s = -1;
-	    for (i = 0; i < UCNumCharsets; i++) {
-		    if (!strcmp(UCInfo[i].LYNXname, lyName))
-			exists = 1;
-		    else if (!stricmp(UCInfo[i].MIMEname, mimeName))
-			s = i;
-	    }
-	    if (s >= 0 && !exists) {
-		/* Duplicate the record. */
-		UC_Charset_Setup(myMimeName, lyName,
-				 UCInfo[s].unicount, UCInfo[s].unitable,
-				 UCInfo[s].num_uni, UCInfo[s].replacedesc,
-				 UCInfo[s].lowest_eight, UCInfo[s].enc,
-				 UCInfo[s].codepage);
-		auto_display_charset = UCGetLYhndl_byMIME(myMimeName);
+	unsigned long len, rc;
+
+	rc = DosQueryCp(sizeof(lst), lst, &len);
+	if (rc == 0) {
+	    if (len >= 1)
+		auto_display_charset = CpOrdinal(lst[0], 0);
+#    ifdef CAN_SWITCH_DISPLAY_CHARSET
+	    if (len >= 3) {
+		codepages[0] = lst[0];
+		codepages[1] = (lst[0] == lst[1] ? lst[2] : lst[1]);
+		auto_other_display_charset = CpOrdinal(codepages[1], 1);
 	    }
+#    endif
+	} else {
+	    CTRACE((tfp, "DosQueryCp() returned %#lx=%lu.\n", rc, rc));
 	}
     }
 #  endif
diff --git a/src/Xsystem.c b/src/Xsystem.c
index 84938e0d..56cac70d 100644
--- a/src/Xsystem.c
+++ b/src/Xsystem.c
@@ -1,4 +1,4 @@
-/* @Id: Xsystem.c 1.8 Wed, 25 Oct 2000 09:35:28 -0700 dickey @
+/* @Id: Xsystem.c 1.9 Mon, 26 Feb 2001 18:41:57 -0800 dickey @
  *	like system("cmd") but return with exit code of "cmd"
  *	for Turbo-C/MS-C/LSI-C
  *  This code is in the public domain.
@@ -131,7 +131,7 @@ is_builtin_command(char *s)
         count++;
 #endif
     for (i = 0; i < count; i++) {
-	if (stricmp(s, cmdtab[i]) == 0)
+	if (strcasecomp(s, cmdtab[i]) == 0)
 	    return 1;
 	lc = strlen(cmdtab[i]);
 	if (lc < l && strnicmp(s, cmdtab[i], lc) == 0 && issep2(s[lc]))
@@ -344,7 +344,7 @@ prog_go(PRO * p, int flag)
 	s--;
     }
 
-    if (is_builtin_command(p->cmd) || (extp && stricmp(extp, ".bat") == 0))
+    if (is_builtin_command(p->cmd) || (extp && strcasecomp(extp, ".bat") == 0))
 	return csystem(p, flag);
 
     if (s < p->cmd) {		/* cmd has no PATH nor Drive */