about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/HTML.c49
-rw-r--r--src/LYCharUtils.c35
-rw-r--r--src/LYCurses.c56
-rw-r--r--src/LYCurses.h1
-rw-r--r--src/LYGetFile.c21
-rw-r--r--src/LYGlobalDefs.h10
-rw-r--r--src/LYLocal.c472
-rw-r--r--src/LYMain.c23
-rw-r--r--src/LYMainLoop.c101
-rw-r--r--src/LYOptions.c262
-rw-r--r--src/LYOptions.h6
-rw-r--r--src/LYReadCFG.c26
-rw-r--r--src/LYUpload.c200
-rw-r--r--src/LYrcFile.c53
-rw-r--r--src/Makefile1
-rw-r--r--src/UCAux.c2
-rw-r--r--src/UCdomap.c24
-rw-r--r--src/chrtrans/Makefile2
-rw-r--r--src/chrtrans/build-chrtrans.com2
-rw-r--r--src/chrtrans/cp1251_uni.tbl151
-rw-r--r--src/chrtrans/makefile.in2
-rw-r--r--src/makefile.in1
22 files changed, 1065 insertions, 435 deletions
diff --git a/src/HTML.c b/src/HTML.c
index 2e98ae53..4de030c8 100644
--- a/src/HTML.c
+++ b/src/HTML.c
@@ -6427,34 +6427,51 @@ End_Object:
 	    if (current_char_set)
 	        LYExpandString(&me->textarea.data);
 
-	    cp = strtok(me->textarea.data, "\n");
-	    LYUnEscapeEntities(cp, me->UsePlainSpace, me->HiddenValue);
+	    if ((cp = strtok(me->textarea.data, "\n")) != NULL) {
+		StrAllocCopy(temp, cp);
+		LYUnEscapeEntities(temp,
+				   me->UsePlainSpace, me->HiddenValue);
+	    } else {
+		FREE(temp);
+	    }
 	    for (i = 0; i < me->textarea_rows; i++) {
-		I.value = cp;
-
+		I.value = temp;
                 chars = HText_beginInput(me->text, me->inUnderline, &I);
 	        for (; chars > 0; chars--)
 	    	    HTML_put_character(me, '_');
 	        HText_appendCharacter(me->text, '\r');
-	
-		cp = strtok(NULL, "\n");
-		LYUnEscapeEntities(cp, me->UsePlainSpace, me->HiddenValue);
+		if (cp) {
+		    if ((cp = strtok(NULL, "\n")) != NULL) {
+			StrAllocCopy(temp, cp);
+			LYUnEscapeEntities(temp,
+					   me->UsePlainSpace,
+					   me->HiddenValue);
+		    } else {
+			FREE(temp);
+		    }
+		}
 	    }
 
 	    /*
 	     *  Check for more data lines than the rows attribute.
    	     */
 	    while (cp) {
-		I.value = cp;
-
-                chars = HText_beginInput(me->text, me->inUnderline, &I);
-                for (chars = atoi(me->textarea_cols); chars>0; chars--)
-                    HTML_put_character(me, '_');
-                HText_appendCharacter(me->text, '\r');
-        
-                cp = strtok(NULL, "\n");
-		LYUnEscapeEntities(cp, me->UsePlainSpace, me->HiddenValue);
+		StrAllocCopy(temp, cp);
+		I.value = temp;
+		chars = HText_beginInput(me->text, me->inUnderline, &I);
+		for (chars = atoi(me->textarea_cols); chars > 0; chars--)
+		    HTML_put_character(me, '_');
+		HText_appendCharacter(me->text, '\r');
+		if ((cp = strtok(NULL, "\n")) != NULL) {
+		    StrAllocCopy(temp, cp);
+		    LYUnEscapeEntities(temp,
+				       me->UsePlainSpace,
+				       me->HiddenValue);
+		} else {
+		    FREE(temp);
+		}
             }
+	    FREE(temp);
 
 	    me->UsePlainSpace = FALSE;
 
diff --git a/src/LYCharUtils.c b/src/LYCharUtils.c
index 14b036ce..b7d82c97 100644
--- a/src/LYCharUtils.c
+++ b/src/LYCharUtils.c
@@ -16,16 +16,16 @@
 #include "HTMLGen.h"
 #include "HTParse.h"
 
-#include "LYGlobalDefs.h"
-#include "LYCharUtils.h"
-#include "LYCharSets.h"
-
 #ifdef EXP_CHARTRANS
 #include "UCMap.h"
 #include "UCDefs.h"
 #include "UCAux.h"
 #endif
 
+#include "LYGlobalDefs.h"
+#include "LYCharUtils.h"
+#include "LYCharSets.h"
+
 #include "HTAlert.h"
 #include "HTFont.h"
 #include "HTForms.h"
@@ -36,6 +36,7 @@
 #include "LYMap.h"
 #include "LYBookmark.h"
 #include "LYCurses.h"
+#include "LYCookie.h"
 
 #ifdef VMS
 #include "HTVMSUtils.h"
@@ -56,10 +57,6 @@ extern BOOL HTPassHighCtrlNum;
 extern HTkcode kanji_code;
 extern HTCJKlang HTCJK;
 
-extern void LYSetCookie PARAMS((
-	CONST char *	header,
-	CONST char *	address));
-
 /*
  *  Used for nested lists. - FM
  */
@@ -2007,10 +2004,13 @@ PUBLIC void LYHandleMETA ARGS4(
 		    HTPassEightBitRaw = TRUE;
 		}
 		LYGetChartransInfo(me);
-			} else  /* Fall through to old behavior */
+	    /*
+	     *  Fall through to old behavior.
+	     */
+			} else
 #endif /* EXP_CHARTRANS */
 	    if (!strncmp(cp1, "us-ascii", 8) ||
-		!strncmp(cp1, "iso-8859-1", 10)) {
+		       !strncmp(cp1, "iso-8859-1", 10)) {
 		StrAllocCopy(me->node_anchor->charset, "iso-8859-1");
 		HTCJK = NOCJK;
 
@@ -2259,11 +2259,18 @@ PUBLIC void LYHandleMETA ARGS4(
      */
     } else if (!strcasecomp((http_equiv ? http_equiv : ""), "Set-Cookie")) {
 	/*
-	 *  We're using the Request-URI as the second argument,
-	 *  regardless of whether a Content-Base header or BASE
-	 *  tag are present.
+	 *  This will need to be updated when Set-Cookie/Set-Cookie2
+	 *  handling is finalized.  For now, we'll still assume
+	 *  "historical" cookies in META directives. - FM
 	 */
-	LYSetCookie(content, me->node_anchor->address);
+	url_type = is_url(me->inBASE ?
+		       me->base_href : me->node_anchor->address);
+	if (url_type == HTTP_URL_TYPE || url_type == HTTPS_URL_TYPE) {
+	    LYSetCookie(content,
+	    		NULL,
+			(me->inBASE ?
+		      me->base_href : me->node_anchor->address));
+	}
     }
 
     /*
diff --git a/src/LYCurses.c b/src/LYCurses.c
index e12e9683..bad0ceb6 100644
--- a/src/LYCurses.c
+++ b/src/LYCurses.c
@@ -128,8 +128,6 @@ PUBLIC void lynx_setup_colors NOARGS
     SLtt_set_mono(7, NULL, SLTT_ULINE_MASK | SLTT_BOLD_MASK | SLTT_REV_MASK);
 }
 
-
-
 PRIVATE void sl_suspend ARGS1(
 	int,		sig)
 {
@@ -211,7 +209,7 @@ PRIVATE int LYAttrset ARGS3(WINDOW*,win,int,color,int,mono)
 {
 	if (TRACE)
 		fprintf(stderr, "CSS:LYAttrset (%d, %d)\n", color, mono);
-	if (has_color && LYShowColor && color > -1)
+	if (has_color && LYShowColor >= SHOW_COLOR_ON && color > -1)
 	{
 		wattrset(win,color);
 #if 0
@@ -394,7 +392,7 @@ PRIVATE struct {
  */
 PRIVATE void LYsetWAttr ARGS1(WINDOW *, win)
 {
-    if (lynx_uses_color && LYShowColor) {
+    if (lynx_uses_color && LYShowColor >= SHOW_COLOR_ON) {
 	int code = 0;
 	int attr = A_NORMAL;
 	int offs = 1;
@@ -462,7 +460,7 @@ PRIVATE void lynx_map_color ARGS1(int, n)
 		lynx_color_pairs[n+m+1].fg,
 		lynx_color_pairs[n+m+1].bg);
 	}
-	if (n == 0 && LYShowColor)
+	if (n == 0 && LYShowColor >= SHOW_COLOR_ON)
 	    bkgd(COLOR_PAIR(9));
     }
 }
@@ -488,7 +486,7 @@ PUBLIC int lynx_chg_color ARGS3(
 
 PUBLIC void lynx_set_color ARGS1(int, a)
 {
-    if (lynx_uses_color && LYShowColor) {
+    if (lynx_uses_color && LYShowColor >= SHOW_COLOR_ON) {
 	attrset(lynx_color_cfg[a].attr | COLOR_PAIR(a+1));
     }
 }
@@ -517,11 +515,12 @@ PRIVATE void lynx_init_colors NOARGS
 			lynx_color_pairs[n+m+1].fg,
 			lynx_color_pairs[n+m+1].bg);
 	    }
-	    if (n == 0 && LYShowColor)
+	    if (n == 0 && LYShowColor >= SHOW_COLOR_ON)
 		bkgd(COLOR_PAIR(9));
 	}
-    } else
-	LYShowColor = FALSE;
+    } else if (LYShowColor != SHOW_COLOR_NEVER) {
+	LYShowColor = SHOW_COLOR_OFF;
+    }
 }
 
 PUBLIC void lynx_setup_colors NOARGS
@@ -575,8 +574,34 @@ PUBLIC void start_curses NOARGS
 
     if (slinit == 0) {
 	SLtt_get_terminfo();
-	if (LYShowColor && (Lynx_Color_Flags & SL_LYNX_USE_COLOR))
+	/*
+	 *  Check whether a saved show_color:off override is in effect. - kw
+	 */
+	if (LYrcShowColor == SHOW_COLOR_NEVER) {
+	    SLtt_Use_Ansi_Colors = 0;
+	}
+	/*
+	 *  Check whether we're forcing color on. - FM
+	 */
+	if ((LYShowColor > 1) && (Lynx_Color_Flags & SL_LYNX_USE_COLOR))
 	    SLtt_Use_Ansi_Colors = 1;
+	/*
+	 *  Check whether a -nocolor override is in effect. - kw
+	 */
+	if (Lynx_Color_Flags & SL_LYNX_OVERRIDE_COLOR)
+	    SLtt_Use_Ansi_Colors = 0;
+	/*
+	 *  Make sure our flags are in register. - FM
+	 */
+	if (SLtt_Use_Ansi_Colors == 1) {
+	    if (LYShowColor != SHOW_COLOR_ALWAYS) {
+		LYShowColor = SHOW_COLOR_ON;
+	    }
+	} else {
+	    if (LYShowColor != SHOW_COLOR_NEVER) {
+		LYShowColor = SHOW_COLOR_OFF;
+	    }
+	}
 	size_change(0);
 
 	SLtt_add_color_attribute(4, SLTT_ULINE_MASK);
@@ -585,10 +610,11 @@ PUBLIC void start_curses NOARGS
 	 *  If set, the blink escape sequence will turn on high
 	 *  intensity background (rxvt and maybe Linux console).
 	 */
-	if (LYShowColor && (Lynx_Color_Flags & SL_LYNX_USE_BLINK))
+	if (LYShowColor && (Lynx_Color_Flags & SL_LYNX_USE_BLINK)) {
 	    SLtt_Blink_Mode = 1;
-	else
+	} else {
 	    SLtt_Blink_Mode = 0;
+	}
     }
     slinit = 1;
     Current_Attr = 0;
@@ -1495,7 +1521,7 @@ PUBLIC void VMSbox ARGS3(
 PUBLIC void lynx_force_repaint NOARGS
 {
 #if defined(COLOR_CURSES)
-    chtype a = (LYShowColor) ? COLOR_PAIR(9) : A_NORMAL;
+    chtype a = (LYShowColor >= SHOW_COLOR_ON) ? COLOR_PAIR(9) : A_NORMAL;
     bkgdset(a | ' ');
     bkgd(a | ' ');
     attrset(a);
@@ -1606,7 +1632,7 @@ PUBLIC void lynx_start_target_color NOARGS
 PUBLIC void lynx_start_status_color NOARGS
 {
 #if USE_COLOR_TABLE && defined(COLOR_CURSES)
-    if (lynx_uses_color && LYShowColor)
+    if (lynx_uses_color && LYShowColor >= SHOW_COLOR_ON)
 	lynx_set_color (2);
     else
 #endif
@@ -1616,7 +1642,7 @@ PUBLIC void lynx_start_status_color NOARGS
 PUBLIC void lynx_stop_status_color NOARGS
 {
 #if USE_COLOR_TABLE && defined(COLOR_CURSES)
-    if (lynx_uses_color && LYShowColor)
+    if (lynx_uses_color && LYShowColor >= SHOW_COLOR_ON)
 	lynx_set_color (0);
     else
 #endif
diff --git a/src/LYCurses.h b/src/LYCurses.h
index 5bccb8b9..4a889faa 100644
--- a/src/LYCurses.h
+++ b/src/LYCurses.h
@@ -161,6 +161,7 @@ extern unsigned int Lynx_Color_Flags;
 
 #define SL_LYNX_USE_COLOR	1
 #define SL_LYNX_USE_BLINK	2
+#define SL_LYNX_OVERRIDE_COLOR	4
 #define start_bold()      	LYaddAttr(1)
 #define start_reverse()   	LYaddAttr(2)
 #define start_underline() 	LYaddAttr(4)
diff --git a/src/LYGetFile.c b/src/LYGetFile.c
index 2faa38cf..ebc708e6 100644
--- a/src/LYGetFile.c
+++ b/src/LYGetFile.c
@@ -93,8 +93,10 @@ PUBLIC BOOLEAN getfile ARGS1(
 	char *cp = NULL;
 	char *temp = NULL;
 	DocAddress WWWDoc;  /* a WWW absolute doc address struct */
+	int redirection_counter = 0;
 
 Try_Redirected_URL:
+	redirection_counter++;
 	/*
 	 *  Load the WWWDoc struct in case we need to use it.
 	 */
@@ -240,6 +242,25 @@ Try_Redirected_URL:
 		    HTAlert(UNSUPPORTED_DATA_URL);
 		    return(NULLFILE);
 
+		} else if (redirection_counter != 1 &&
+			   (url_type == LYNXDOWNLOAD_URL_TYPE ||
+			    url_type == LYNXEXEC_URL_TYPE ||
+			    url_type == LYNXPROG_URL_TYPE ||
+			    url_type == LYNXDIRED_URL_TYPE)) {
+		    /*
+		     *  Some schemes are definitely not acceptable
+		     *  from server redirections. - kw
+		     */
+		    HTAlert(INVALID_URL_SCHEME_IN_REDIRECTION);
+		    if (LYCursesON) {
+			_user_message("Bad URL: %s", doc->address);
+			sleep(AlertSecs);
+		    } else {
+			fprintf(stderr,
+				"Bad Redirection URL: %s", doc->address);
+		    }
+		    return(NULLFILE);
+
 		} else if (url_type == LYNXPRINT_URL_TYPE) {
 		    return(printfile(doc));
 
diff --git a/src/LYGlobalDefs.h b/src/LYGlobalDefs.h
index c8df5cbb..81ffbfa2 100644
--- a/src/LYGlobalDefs.h
+++ b/src/LYGlobalDefs.h
@@ -98,7 +98,15 @@ extern char star_string[MAX_LINE + 1]; /* from GridText.c */
  ((n) >= MAX_LINE ? star_string : &star_string[(MAX_LINE-1)] - (n))
 #define DIRNAMESIZE 256
 
-extern BOOLEAN LYShowColor;	/* Show color or monochrome?	    */
+#define SHOW_COLOR_UNKNOWN	(-1)
+#define SHOW_COLOR_NEVER  0
+#define SHOW_COLOR_OFF	  1
+#define SHOW_COLOR_ON	  2
+#define SHOW_COLOR_ALWAYS 3
+extern int LYShowColor;		/* Show color or monochrome?	    */
+extern int LYChosenShowColor;	/* extended color/monochrome choice */
+extern int LYrcShowColor;	/* ... as read or last written	    */
+
 extern BOOLEAN LYShowCursor;	/* Show the cursor or hide it?	    */
 extern BOOLEAN LYUseDefShoCur;	/* Command line -show_cursor toggle */
 extern BOOLEAN LYCursesON;  /* start_curses()->TRUE, stop_curses()->FALSE */
diff --git a/src/LYLocal.c b/src/LYLocal.c
index 22b66886..3b65287f 100644
--- a/src/LYLocal.c
+++ b/src/LYLocal.c
@@ -1,32 +1,33 @@
-/* Routines to manipulate the local filesystem. */
-/* Written by: Rick Mallett, Carleton University */
-/* Report problems to rmallett@ccs.carleton.ca */
-/* Modified 18-Dec-95 David Trueman (david@cs.dal.ca):
-	Added OK_PERMIT compilation option.
-	Support replacement of compiled-in f)ull menu configuration via
-	  DIRED_MENU definitions in lynx.cfg, so that more than one menu
-	  can be driven by the same executable. */
-/* Modified Oct-96 Klaus Weide (kweide@tezcat.com):
-	Changed to use the library's HTList_* functions and macros for
-	  managing the list of tagged file URLs.
-	Keep track of proper level of URL escaping, so that unusual filenames
-	  which contain #% etc. are handled properly (some HTUnEscapeSome()'s
-	  left in to be conservative, and to document where superfluous
-	  unescaping took place before).
-	Dynamic memory instead of fixed length buffers in a few cases.
-	Other minor changes to make things work as intended. */
-/* Modified Jun-97 Klaus Weide (kweide@tezcat.com) & FM:
-	Modified the code handling DIRED_MENU to do more careful
-	  checking of the selected file.  In addition to "TAG", "FILE", and
-	  "DIR", DIRED_MENU definitions in lynx.cfg now also recognize LINK as
-	  a type.  DIRED_MENU definitions with a type field of "LINK" are only
-	  used if the current selection is a symbolic link ("FILE" and "DIR"
-	  definitions are not used in that case).  The default menu
-	  definitions have been updated to reflect this change, and to avoid
-	  the showing of menu items whose action would always fail - KW
-	Cast all code into the Lynx programming style. - FM */
+/*
+**  Routines to manipulate the local filesystem.
+**  Written by: Rick Mallett, Carleton University
+**  Report problems to rmallett@ccs.carleton.ca
+**  Modified 18-Dec-95 David Trueman (david@cs.dal.ca):
+**	Added OK_PERMIT compilation option.
+**	Support replacement of compiled-in f)ull menu configuration via
+**	  DIRED_MENU definitions in lynx.cfg, so that more than one menu
+**	  can be driven by the same executable.
+**  Modified Oct-96 Klaus Weide (kweide@tezcat.com):
+**	Changed to use the library's HTList_* functions and macros for
+**	  managing the list of tagged file URLs.
+**	Keep track of proper level of URL escaping, so that unusual filenames
+**	  which contain #% etc. are handled properly (some HTUnEscapeSome()'s
+**	  left in to be conservative, and to document where superfluous
+**	  unescaping took place before).
+**	Dynamic memory instead of fixed length buffers in a few cases.
+**	Other minor changes to make things work as intended.
+**  Modified Jun-97 Klaus Weide (kweide@tezcat.com) & FM:
+**	Modified the code handling DIRED_MENU to do more careful
+**	  checking of the selected file.  In addition to "TAG", "FILE", and
+**	  "DIR", DIRED_MENU definitions in lynx.cfg now also recognize LINK as
+**	  a type.  DIRED_MENU definitions with a type field of "LINK" are only
+**	  used if the current selection is a symbolic link ("FILE" and "DIR"
+**	  definitions are not used in that case).  The default menu
+**	  definitions have been updated to reflect this change, and to avoid
+**	  the showing of menu items whose action would always fail - KW
+**	Cast all code into the Lynx programming style. - FM
+*/
 
-#ifdef DIRED_SUPPORT
 #include "HTUtils.h"
 #include "tcp.h"
 #include "HTParse.h"
@@ -42,18 +43,25 @@
 #include "LYLocal.h"
 #include "LYSystem.h"
 
+#ifndef VMS
 #include <sys/wait.h>
 #include <errno.h>
 #include <grp.h>
+#endif /* VMS */
 
 #include "LYLeaks.h"
 
 #define FREE(x) if (x) {free(x); x = NULL;}
 
-PRIVATE int my_spawn PARAMS((
+PUBLIC int LYExecv PARAMS((
 	char *		path,
 	char **		argv,
 	char *		msg));
+
+#ifdef DIRED_SUPPORT
+PUBLIC char LYPermitFileURL[256] = "\0";
+PUBLIC char LYDiredFileURL[256] = "\0";
+
 PRIVATE char *filename PARAMS((
 	char *		prompt,
 	char *		buf,
@@ -263,7 +271,7 @@ PRIVATE BOOLEAN remove_tagged NOARGS
 		args[2] = testpath;
 		args[3] = (char *) 0;
 		sprintf(tmpbuf, "remove %s", testpath);
-		if (my_spawn(RM_PATH, args, tmpbuf) <= 0) {
+		if (LYExecv(RM_PATH, args, tmpbuf) <= 0) {
 		    FREE(testpath);
 		    return ((count == 0) ? -1 : count);
 		}
@@ -376,95 +384,102 @@ PRIVATE BOOLEAN modify_tagged ARGS1(
 		FREE(cp1);
 		return 0;
 	    }
-	  strcpy(tmpbuf, cp1);
-	  FREE(cp1);
-      }
-
-/* if path is relative prefix it with current location */
-
-      if (tmpbuf[0] != '/') {
-	 if (savepath[strlen(savepath)-1] != '/')
-	     StrAllocCat(savepath,"/");
-	 StrAllocCat(savepath,tmpbuf);
-      } else {
-	 StrAllocCopy(savepath,tmpbuf);
-      }
-
-/* stat the target location to determine type and ownership */
-
-      if (stat(savepath,&dir_info) == -1) {
-	 sprintf(tmpbuf,"Unable to get status of '%s'.",savepath);
-	 _statusline(tmpbuf);
-	 sleep(AlertSecs);
-	 FREE(savepath);
-	 return 0;
-      }
-
-/* make sure the source and target locations are not the same place */
-
-      if (dev == dir_info.st_dev && inode == dir_info.st_ino) {
-	 _statusline(
+	    strcpy(tmpbuf, cp1);
+	    FREE(cp1);
+	}
+
+	/*
+	 *  If path is relative, prefix it with current location.
+	 */
+	if (tmpbuf[0] != '/') {
+	    if (savepath[(strlen(savepath) - 1)] != '/')
+		StrAllocCat(savepath,"/");
+	    StrAllocCat(savepath,tmpbuf);
+	} else {
+	    StrAllocCopy(savepath,tmpbuf);
+	}
+
+	/*
+	 *  stat() the target location to determine type and ownership.
+	 */
+	if (stat(savepath, &dir_info) == -1) {
+	    sprintf(tmpbuf,"Unable to get status of '%s'.",savepath);
+	    _statusline(tmpbuf);
+	    sleep(AlertSecs);
+	    FREE(savepath);
+	    return 0;
+	}
+
+	/*
+	 *  Make sure the source and target locations are not the same place.
+	 */
+	if (dev == dir_info.st_dev && inode == dir_info.st_ino) {
+	    _statusline(
 	   "Source and destination are the same location - request ignored!");
-	 sleep(AlertSecs);
-	 FREE(savepath);
-	 return 0;
-      }
-
-/* make sure the target location is a directory which is owned */
-/* by the same uid as the owner of the current location */
-
-      if((dir_info.st_mode & S_IFMT) == S_IFDIR) {
-	 if(dir_info.st_uid == owner) {
-	    count = 0;
-	    tag = tagged;
-
-/* move all tagged items to the target location */
-
-	    while((cp = (char *)HTList_nextObject(tag)) != NULL) {
-	       if(!strncmp(cp,"file://localhost",16))
-		 cp += 16;
-	       else if(!strncmp(cp,"file:",5))
-		 cp += 5;
-	       StrAllocCopy(srcpath, cp);
-	       HTUnEscape(srcpath);
-
-	       sprintf(tmpbuf, "move %s to %s", srcpath, savepath);
-	       args[0] = "mv";
-	       args[1] = srcpath;
-	       args[2] = savepath;
-	       args[3] = (char *) 0;
-	       if (my_spawn(MV_PATH, args, tmpbuf) <= 0) {
-		  if (count == 0)
-		      count = -1;
-		  break;
-	       }
-	       ++count;
-	    }
-	    FREE(srcpath);
+	    sleep(AlertSecs);
 	    FREE(savepath);
-	    clear_tags();
-	    return count;
-	 } else {
-	    _statusline("Destination has different owner! Request denied. ");
+	    return 0;
+	}
+
+	/*
+	 *  Make sure the target location is a directory which is owned
+	 * by the same uid as the owner of the current location.
+	 */
+	if ((dir_info.st_mode & S_IFMT) == S_IFDIR) {
+	    if (dir_info.st_uid == owner) {
+		count = 0;
+		tag = tagged;
+
+		/*
+		 *  Move all tagged items to the target location.
+		 */
+		while ((cp = (char *)HTList_nextObject(tag)) != NULL) {
+		    if (!strncmp(cp, "file://localhost", 16)) {
+			cp += 16;
+		    } else if (!strncmp(cp, "file:", 5)) {
+			cp += 5;
+		    }
+		    StrAllocCopy(srcpath, cp);
+		    HTUnEscape(srcpath);
+
+		    sprintf(tmpbuf, "move %s to %s", srcpath, savepath);
+		    args[0] = "mv";
+		    args[1] = srcpath;
+		    args[2] = savepath;
+		    args[3] = (char *) 0;
+		    if (LYExecv(MV_PATH, args, tmpbuf) <= 0) {
+			if (count == 0)
+			    count = -1;
+			break;
+		    }
+		    ++count;
+		}
+		FREE(srcpath);
+		FREE(savepath);
+		clear_tags();
+		return count;
+	    } else {
+		_statusline(
+			"Destination has different owner! Request denied.");
+		sleep(AlertSecs);
+		FREE(srcpath);
+		FREE(savepath);
+		return 0;
+	    }
+	} else {
+	    _statusline(
+	    	   "Destination is not a valid directory! Request denied.");
 	    sleep(AlertSecs);
-	    FREE(srcpath);
 	    FREE(savepath);
 	    return 0;
-	 }
-      } else {
-	 _statusline("Destination is not a valid directory! Request denied. ");
-	 sleep(AlertSecs);
-	 FREE(savepath);
-	 return 0;
-      }
-   }
-   return 0;
+	}
+    }
+    return 0;
 }
 
 /*
  *  Modify the name of the specified item.
  */
-
 PRIVATE BOOLEAN modify_name ARGS1(
 	char *,		testpath)
 {
@@ -529,7 +544,7 @@ PRIVATE BOOLEAN modify_name ARGS1(
 		    args[1] = savepath;
 		    args[2] = newpath;
 		    args[3] = (char *) 0;
-		    if (my_spawn(MV_PATH, args, tmpbuf) <= 0)
+		    if (LYExecv(MV_PATH, args, tmpbuf) <= 0)
 			return (-1);
 		    return 1; 
 		}
@@ -656,7 +671,7 @@ PRIVATE BOOLEAN modify_location ARGS1(
 	    args[1] = savepath;
 	    args[2] = newpath;
 	    args[3] = (char *) 0;
-	    if (my_spawn(MV_PATH, args, tmpbuf) <= 0)
+	    if (LYExecv(MV_PATH, args, tmpbuf) <= 0)
 		return (-1);
 	    return 1;
 	} else {
@@ -799,7 +814,7 @@ PRIVATE BOOLEAN create_file ARGS1(
 	    args[0] = "touch";
 	    args[1] = testpath;
 	    args[2] = (char *) 0;
-	    if (my_spawn(TOUCH_PATH, args, tmpbuf) <= 0)
+	    if (LYExecv(TOUCH_PATH, args, tmpbuf) <= 0)
 		return (-1);
 	    return 1;
 	} else if ((dir_info.st_mode & S_IFMT) == S_IFDIR) {
@@ -865,7 +880,7 @@ PRIVATE BOOLEAN create_directory ARGS1(
 	    args[0] = "mkdir";
 	    args[1] = testpath;
 	    args[2] = (char *) 0;
-	    if (my_spawn(MKDIR_PATH, args, tmpbuf) <= 0)
+	    if (LYExecv(MKDIR_PATH, args, tmpbuf) <= 0)
 		return (-1);
 	    return 1;
 	} else if ((dir_info.st_mode & S_IFMT) == S_IFDIR) {
@@ -984,7 +999,7 @@ PRIVATE BOOLEAN remove_single ARGS1(
 	args[1] = "-rf";
 	args[2] = testpath;
 	args[3] = (char *) 0;
-	if (my_spawn(RM_PATH, args, tmpbuf) <= 0)
+	if (LYExecv(RM_PATH, args, tmpbuf) <= 0)
 	    return (-1);
 	return 1;
     }
@@ -1058,6 +1073,8 @@ static struct {
 #define S_ISDIR(mode)   ((mode&0xF000) == 0x4000)
 #endif /* !S_ISDIR */
     
+PRIVATE char LYValidPermitFile[256] = "\0";
+
 /*
  *  Handle DIRED permissions.
  */
@@ -1071,7 +1088,7 @@ PRIVATE BOOLEAN permit_location ARGS3(
     sleep(AlertSecs);
     return(0);
 #else
-    static char tempfile[128];
+    static char tempfile[256] = "\0";
     static BOOLEAN first = TRUE;
     char *cp;
     char tmpbuf[LINESIZE];
@@ -1082,7 +1099,6 @@ PRIVATE BOOLEAN permit_location ARGS3(
 	 *  Create form.
 	 */
 	FILE *fp0;
-	char print_filename[256];
 	char * user_filename;
 	struct group * grp;
 	char * group_name;
@@ -1113,10 +1129,17 @@ PRIVATE BOOLEAN permit_location ARGS3(
 	}
 	
 	if (first) {
+	    /*
+	     *  Get an unused tempfile name. - FM
+	     */
 	    tempname(tempfile, NEW_FILE);
-	    first = FALSE;
 	}
 	
+	/*
+	 *  Open the tempfile for writing and set its
+	 *  protection in case this wasn't done via an
+	 *  external umask. - FM
+	 */
 	if ((fp0 = fopen(tempfile, "w")) == NULL) {
 	    _statusline("Unable to open permit options file");
 	    sleep(AlertSecs);
@@ -1124,12 +1147,15 @@ PRIVATE BOOLEAN permit_location ARGS3(
 	}
 	chmod(tempfile, 0600);
 	
-	/*
-	 *  Make the tempfile a URL.
-	 */
-	strcpy(print_filename, "file://localhost");
-	strcat(print_filename, tempfile);
-	StrAllocCopy(*newpath, print_filename);
+	if (first) {
+	    /*
+	     *  Make the tempfile a URL.
+	     */
+	    strcpy(LYPermitFileURL, "file://localhost");
+	    strcat(LYPermitFileURL, tempfile);
+	    first = FALSE;
+	}
+	StrAllocCopy(*newpath, LYPermitFileURL);
 
 	grp = getgrgid(dir_info.st_gid);
 	if (grp == NULL) {
@@ -1138,6 +1164,10 @@ PRIVATE BOOLEAN permit_location ARGS3(
 	    group_name = grp->gr_name;
 	}
 
+	LYstrncpy(LYValidPermitFile,
+		  srcpath,
+		  (sizeof(LYValidPermitFile) - 1));
+
 	fprintf(fp0, "<Html><Head>\n<Title>%s</Title>\n</Head>\n<Body>\n",
 		PERMIT_OPTIONS_TITLE);
 	fprintf(fp0,"<H1>Permissions for %s</H1>\n", user_filename);
@@ -1215,6 +1245,22 @@ form to permit %s %s.\n</Ol>\n</Form>\n",
 	char *args[5];
 	char amode[10];
 	
+	/*
+	 *  Make sure we have a valid set-permission
+	 *  file comparison string loaded via a previous
+	 *  call with srcpath != NULL. - kw
+	 */
+	if (LYValidPermitFile[0] == '\0') {
+	    if (LYCursesON)
+		HTAlert(INVALID_PERMIT_URL);
+	    else
+		fprintf(stderr, "%s\n", INVALID_PERMIT_URL);
+	    if (TRACE)
+		fprintf(stderr, "permit_location: called for <%s>.\n",
+			(destpath ?
+			 destpath : "NULL URL pointer"));
+	    return 0;
+	}
 	cp = destpath;
 	while (*cp != '\0' && *cp != '?') { /* Find filename */
 	    cp++;
@@ -1228,6 +1274,20 @@ form to permit %s %s.\n</Ol>\n</Form>\n",
 	HTUnEscape(destpath);	/* Will now operate only on filename part. */
 	
 	/*
+	 *  Make sure that the file string is the one from
+	 *  the last displayed File Permissions menu. - kw
+	 */
+	if (strcmp(destpath, LYValidPermitFile)) {
+	    if (LYCursesON)
+		HTAlert(INVALID_PERMIT_URL);
+	    else
+		fprintf(stderr, "%s\n", INVALID_PERMIT_URL);
+	    if (TRACE)
+		fprintf(stderr, "permit_location: called for file '%s'.\n",
+			destpath);
+	    return 0;
+	}
+	/*
 	 *  A couple of sanity tests.
 	 */
 	destpath = strip_trailing_slash(destpath);
@@ -1295,7 +1355,7 @@ form to permit %s %s.\n</Ol>\n</Form>\n",
 	args[1] = amode;
 	args[2] = destpath;
 	args[3] = (char *) 0;
-	if (my_spawn(CHMOD_PATH, args, tmpbuf) <= 0) {
+	if (LYExecv(CHMOD_PATH, args, tmpbuf) <= 0) {
 	    return (-1);
 	}
 	LYforce_no_cache = TRUE;	/* Force update of dired listing. */
@@ -1376,6 +1436,10 @@ PUBLIC int local_dired ARGS1(
     char buffer[512];
 
     line_url = doc->address;
+    if (TRACE)
+	fprintf(stderr, "local_dired: called for <%s>.\n",
+		(line_url ?
+		 line_url : "NULL URL pointer"));
     HTUnEscapeSome(line_url, "/");	/* don't mess too much with *doc */
 
     StrAllocCopy(line, line_url);
@@ -1598,7 +1662,7 @@ PUBLIC int dired_options ARGS2(
 	document *,	doc,
 	char **,	newfile)
 {
-    static char tempfile[128];
+    static char tempfile[256];
     static BOOLEAN first = TRUE;
     char path[512], dir[512]; /* much too large */
     char tmpbuf[LINESIZE];
@@ -1620,10 +1684,17 @@ PUBLIC int dired_options ARGS2(
 
 
     if (first) {
+	/*
+	 *  Get an unused tempfile name. - FM
+	 */
         tempname(tempfile, NEW_FILE);
-	first = FALSE;
     }
 
+    /*
+     *  Open the tempfile for writing and set its
+     *  protection in case this wasn't done via an
+     *  external umask. - FM
+     */
     if ((fp0 = fopen(tempfile,"w")) == NULL) {
 	_statusline("Unable to open file management menu file.");
 	sleep(AlertSecs);
@@ -1631,9 +1702,15 @@ PUBLIC int dired_options ARGS2(
     }
     chmod(tempfile, 0600);
     
-    /* make the tempfile a URL */
-    StrAllocCopy(*newfile, "file://localhost");
-    StrAllocCat(*newfile, tempfile);
+    if (first) {
+	/*
+	 *  Make the tempfile a URL.
+ 	 */
+	strcpy(LYDiredFileURL, "file://localhost");
+	strcat(LYDiredFileURL, tempfile);
+	first = FALSE;
+    }
+    StrAllocCopy(*newfile, LYDiredFileURL);
     
     cp = doc->address;
     if (!strncmp(cp, "file://localhost", 16)) {
@@ -1788,72 +1865,6 @@ PUBLIC int dired_options ARGS2(
 }
 
 /*
- *  Execute DIRED command.
- */
-PRIVATE int my_spawn ARGS3(
-	char *,		path,
-	char **,	argv,
-	char *,		msg)
-{
-    int rc;
-    char tmpbuf[512];
-    pid_t pid;
-#if defined(NeXT) || defined(AIX4) || defined(sony_news)
-    union wait wstatus;
-#else
-    int wstatus;
-#endif /* NeXT || AIX4 || sony_news */
-
-    rc = 1;		/* It will work */
-    tmpbuf[0] = '\0';	/* empty buffer for alert messages */
-    stop_curses();
-    pid = fork();	/* fork and execute rm */
-    switch (pid) {
- 	case -1:
-	    sprintf(tmpbuf, "Unable to %s due to system error!", msg);
-	    rc = 0;
-	    break;	/* don't fall thru! - KW */
-	case 0:  /* child */
-	    execv(path, argv);
-	    exit(-1);	/* execv failed, give wait() something to look at */
-	default:  /* parent */
-#if defined(NeXT) || defined(AIX4) || defined(sony_news)
-	    while (wait(&wstatus) != pid)
-		; /* do nothing */
-#else
-	    waitpid(pid, &wstatus, 0); /* wait for child */
-#endif /* NeXT || AIX4 || sony_news */
-	    if (WEXITSTATUS(wstatus) != 0 ||
-		WTERMSIG(wstatus) > 0)  { /* error return */
-		sprintf(tmpbuf, "Probable failure to %s due to system error!",
-				msg);
-		rc = 0;
-	    }
-    }
-#ifdef VMS
-    {
-	extern BOOLEAN HadVMSInterrupt;
-	HadVMSInterrupt = FALSE;
-    }
-#endif /* VMS */
-
-    if (rc == 0) {
-        /*
-	 *  Screen may have message from the failed execv'd command.
-	 *  Give user time to look at it before screen refresh.
-	 */
-	sleep(AlertSecs);
-    }
-    start_curses();
-    if (tmpbuf[0]) {
-	_statusline(tmpbuf);
-	sleep(AlertSecs);
-    }
-
-    return(rc);
-}
-
-/*
  *  Check DIRED filename.
  */
 PRIVATE char *filename ARGS3(
@@ -1964,7 +1975,7 @@ PUBLIC BOOLEAN local_install ARGS3(
 
     if (HTList_isEmpty(tagged)) {
 	args[src] = savepath;
-	if (my_spawn(INSTALL_PATH, args, tmpbuf) <= 0)
+	if (LYExecv(INSTALL_PATH, args, tmpbuf) <= 0)
 	    return (-1);
 	count++;
     } else {
@@ -1974,7 +1985,7 @@ PUBLIC BOOLEAN local_install ARGS3(
 	    if (strncmp("file://localhost", args[src], 16) == 0)
 		 args[src] = (name + 16);
 
-	    if (my_spawn(INSTALL_PATH, args, tmpbuf) <= 0)
+	    if (LYExecv(INSTALL_PATH, args, tmpbuf) <= 0)
 		return ((count == 0) ? -1 : count);
 	    count++;
 	}	
@@ -2171,3 +2182,70 @@ PRIVATE char * render_item ARGS6(
     return buf;
 }
 #endif /* DIRED_SUPPORT */
+
+/*
+ *  Execute DIRED command.
+ */
+PUBLIC int LYExecv ARGS3(
+	char *,		path,
+	char **,	argv,
+	char *,		msg)
+{
+#ifdef VMS
+    if (TRACE) {
+	fprintf(stderr, "LYExecv:  Called inappropriately!\n");
+    }
+    return(0);
+#else
+    int rc;
+    char tmpbuf[512];
+    pid_t pid;
+#if defined(NeXT) || defined(AIX4) || defined(sony_news)
+    union wait wstatus;
+#else
+    int wstatus;
+#endif /* NeXT || AIX4 || sony_news */
+
+    rc = 1;		/* It will work */
+    tmpbuf[0] = '\0';	/* empty buffer for alert messages */
+    stop_curses();
+    pid = fork();	/* fork and execute rm */
+    switch (pid) {
+ 	case -1:
+	    sprintf(tmpbuf, "Unable to %s due to system error!", msg);
+	    rc = 0;
+	    break;	/* don't fall thru! - KW */
+	case 0:  /* child */
+	    execv(path, argv);
+	    exit(-1);	/* execv failed, give wait() something to look at */
+	default:  /* parent */
+#if defined(NeXT) || defined(AIX4) || defined(sony_news)
+	    while (wait(&wstatus) != pid)
+		; /* do nothing */
+#else
+	    waitpid(pid, &wstatus, 0); /* wait for child */
+#endif /* NeXT || AIX4 || sony_news */
+	    if (WEXITSTATUS(wstatus) != 0 ||
+		WTERMSIG(wstatus) > 0)  { /* error return */
+		sprintf(tmpbuf, "Probable failure to %s due to system error!",
+				msg);
+		rc = 0;
+	    }
+    }
+
+    if (rc == 0) {
+        /*
+	 *  Screen may have message from the failed execv'd command.
+	 *  Give user time to look at it before screen refresh.
+	 */
+	sleep(AlertSecs);
+    }
+    start_curses();
+    if (tmpbuf[0]) {
+	_statusline(tmpbuf);
+	sleep(AlertSecs);
+    }
+
+    return(rc);
+#endif /* VMS */
+}
diff --git a/src/LYMain.c b/src/LYMain.c
index 5a4c3378..b939f01d 100644
--- a/src/LYMain.c
+++ b/src/LYMain.c
@@ -154,7 +154,9 @@ PUBLIC lynx_html_item_type *externals = NULL;
 #endif
 PUBLIC lynx_html_item_type *uploaders = NULL;
 PUBLIC int port_syntax = 1;
-PUBLIC BOOLEAN LYShowColor = SHOW_COLOR; /* to show or not to show */
+PUBLIC int LYShowColor = SHOW_COLOR_UNKNOWN; /* to show or not to show */
+PUBLIC int LYChosenShowColor = SHOW_COLOR_UNKNOWN; /* whether to show and save */
+PUBLIC int LYrcShowColor = SHOW_COLOR_UNKNOWN;  /* ... as last read or written */
 PUBLIC BOOLEAN LYShowCursor = SHOW_CURSOR; /* to show or not to show */
 PUBLIC BOOLEAN LYUseDefShoCur = TRUE;	/* Command line -show_cursor toggle */
 PUBLIC BOOLEAN LYforce_no_cache = FALSE;
@@ -355,7 +357,7 @@ PUBLIC FILE LYOrigStderr;			/* Original stderr pointer */
 PUBLIC BOOLEAN LYSeekFragMAPinCur = TRUE;
 PUBLIC BOOLEAN LYSeekFragAREAinCur = TRUE;
 
-PUBLIC BOOLEAN LYStripDotDotURLs = FALSE;	/* Try to fix ../ in some URLs? */
+PUBLIC BOOLEAN LYStripDotDotURLs = TRUE;	/* Try to fix ../ in some URLs? */
 PUBLIC BOOLEAN LYForceSSLCookiesSecure = FALSE;
 
 /* These are declared in cutil.h for current freeWAIS libraries. - FM */
@@ -534,6 +536,7 @@ PUBLIC int main ARGS2(
     terminal = "vt100";
 #endif
 
+    LYShowColor = (SHOW_COLOR ? SHOW_COLOR_ON : SHOW_COLOR_OFF);
     /*
      *  Set up the argument list.
      */
@@ -1329,12 +1332,15 @@ PUBLIC int main ARGS2(
     read_rc();
 
 #ifdef USE_SLANG
-    if (LYShowColor == TRUE &&
+    if (LYShowColor >= SHOW_COLOR_ON &&
 	!(Lynx_Color_Flags & SL_LYNX_USE_COLOR)) {
 	Lynx_Color_Flags |= SL_LYNX_USE_COLOR;
     } else if ((Lynx_Color_Flags & SL_LYNX_USE_COLOR) ||
 	       getenv("COLORTERM") != NULL) {
-	LYShowColor = TRUE;
+	if (LYShowColor != SHOW_COLOR_NEVER &&
+	    LYShowColor != SHOW_COLOR_ALWAYS) {
+	    LYShowColor = SHOW_COLOR_ON;
+	}
     }
 #endif /* USE_SLANG */
 
@@ -1873,7 +1879,9 @@ PRIVATE void parse_arg ARGS3(
 #ifdef USE_SLANG
     } else if (strncmp(argv[0], "-color", 6) == 0) {
         Lynx_Color_Flags |= SL_LYNX_USE_COLOR;
-	LYShowColor = TRUE;
+	if (LYShowColor != SHOW_COLOR_ALWAYS) {
+	    LYShowColor = SHOW_COLOR_ON;
+	}
 #endif /* USE_SLANG */
 
     } else if (strncmp(argv[0], "-crawl", 6) == 0) {
@@ -2180,9 +2188,10 @@ PRIVATE void parse_arg ARGS3(
 	HTDirAccess = HT_DIR_FORBID;
 
     } else if (strncmp(argv[0], "-nocolor", 8) == 0) {
-	LYShowColor = FALSE;
+	LYShowColor = SHOW_COLOR_NEVER;
 #ifdef USE_SLANG
 	Lynx_Color_Flags &= ~SL_LYNX_USE_COLOR;
+	Lynx_Color_Flags |= SL_LYNX_OVERRIDE_COLOR;
 #endif
 
 #if defined(EXEC_LINKS) || defined(EXEC_SCRIPTS)
@@ -2594,7 +2603,7 @@ Output_Help_List:
     printf("    -child           exit on left-arrow in startfile, and disable save to disk\n");
 #ifdef USE_SLANG
     printf("    -color           force color mode on with standard bg colors\n");
-    printf("    -blink           force color mode on with high intensity bg colors\n");
+    printf("    -blink           force high intensity bg colors in color mode\n");
 #endif /* USE_SLANG */
     printf("    -cookies         toggles handling of Set-Cookie headers\n");
     printf("    -crawl           with -traversal, output each page to a file\n");
diff --git a/src/LYMainLoop.c b/src/LYMainLoop.c
index 4f93190f..b8ecfb02 100644
--- a/src/LYMainLoop.c
+++ b/src/LYMainLoop.c
@@ -175,6 +175,9 @@ int mainloop NOARGS
     char *tp;
     char tmpbuf[1024];
     struct stat dir_info;
+    extern char LYPermitFileURL[];
+    extern char LYDiredFileURL[];
+    extern char LYUploadFileURL[];
 #endif /* DIRED_SUPPORT */
 
 /*
@@ -2444,9 +2447,24 @@ new_cmd:  /*
 			if (!strncasecomp(
 				    links[curdoc.link].form->submit_action,
 					  "LYNXCOOKIE:", 11) ||
+#ifdef DIRED_SUPPORT
+#ifdef OK_PERMIT
+			    (!(strncasecomp(
+				    links[curdoc.link].form->submit_action,
+					   "LYNXDIRED:", 10)) &&
+			     (no_dired_support ||
+			      strncasecomp(
+				(links[curdoc.link].form->submit_action + 10),
+					   "//PERMIT_LOCATION", 17) ||
+			      strcmp(curdoc.address, LYPermitFileURL) ||
+			      strcmp((curdoc.title ? curdoc.title : ""),
+				     PERMIT_OPTIONS_TITLE)))  ||
+#else
 			    !strncasecomp(
 				    links[curdoc.link].form->submit_action,
 					  "LYNXDIRED:", 10) ||
+#endif /* OK_PERMIT */
+#endif /* DIRED_SUPPORT */
 			    !strncasecomp(
 				    links[curdoc.link].form->submit_action,
 					  "LYNXDOWNLOAD:", 13) ||
@@ -2469,6 +2487,11 @@ new_cmd:  /*
 				    links[curdoc.link].form->submit_action,
 					  "lynxprog:", 9)) {
 			    HTAlert(SPECIAL_ACTION_DISALLOWED);
+			    if (TRACE) {
+			        fprintf(stderr,
+					"LYMainLoop: Rejected '%s'\n",
+					links[curdoc.link].form->submit_action);
+			    }
 			    HTOutputFormat = WWW_PRESENT;
 			    LYforce_no_cache = FALSE;
 			    break;
@@ -2557,12 +2580,15 @@ new_cmd:  /*
 #ifdef DIRED_SUPPORT
 			(!strncmp(links[curdoc.link].lname,
 				  "LYNXDIRED:", 10) &&
-			 strcmp((curdoc.title ? curdoc.title : ""),
-				DIRED_MENU_TITLE) &&
-			 strcmp((curdoc.title ? curdoc.title : ""),
-				PERMIT_OPTIONS_TITLE) &&
-			 strcmp((curdoc.title ? curdoc.title : ""),
-				UPLOAD_OPTIONS_TITLE)) ||
+			 (strcmp(curdoc.address, LYDiredFileURL) ||
+			  strcmp((curdoc.title ? curdoc.title : ""),
+				DIRED_MENU_TITLE)) &&
+			 (strcmp(curdoc.address, LYPermitFileURL) ||
+			  strcmp((curdoc.title ? curdoc.title : ""),
+				PERMIT_OPTIONS_TITLE)) &&
+			 (strcmp(curdoc.address, LYUploadFileURL) ||
+			  strcmp((curdoc.title ? curdoc.title : ""),
+				UPLOAD_OPTIONS_TITLE))) ||
 #endif /* DIRED_SUPPORT */
 			(!strncmp(links[curdoc.link].lname,
 				 "LYNXDOWNLOAD:", 13) &&
@@ -3211,41 +3237,27 @@ check_goto_URL:
 			 *  Servers properly use it...  Treat like
 			 *  case LYK_RELOAD (see comments there). - KW
 			 */
-			if (HTisDocumentSource()) {
-			    HTOutputFormat = WWW_SOURCE;
-			}
-			HEAD_request = HTLoadedDocumentIsHEAD();
-			HTuncache_current_document();
+			reloading = TRUE;
+		    }
+		    if (lynx_mode == FORMS_LYNX_MODE) {
+			_statusline(RELOADING_FORM);
+			sleep(AlertSecs);
+		    }
+		    if (HTisDocumentSource()) {
+			HTOutputFormat = WWW_SOURCE;
+		    }
+		    HEAD_request = HTLoadedDocumentIsHEAD();
+		    HTuncache_current_document();
 #ifdef NO_ASSUME_SAME_DOC
-			newdoc.line = 1;
-			newdoc.link = 0;
+		    newdoc.line = 1;
+		    newdoc.link = 0;
 #else
-			if (lynx_mode == FORMS_LYNX_MODE) {
-			    _statusline(RELOADING_FORM);
-			    sleep(AlertSecs);
-			}
-			newdoc.line = ((curdoc.line > 0) ?
-					     curdoc.line : 1);
-			newdoc.link = ((curdoc.link > -1) ?
-					      curdoc.link : 0);
+		    newdoc.line = ((curdoc.line > 0) ?
+					 curdoc.line : 1);
+		    newdoc.link = ((curdoc.link > -1) ?
+					  curdoc.link : 0);
 #endif /* NO_ASSUME_SAME_DOC */
-		        FREE(curdoc.address);
-			reloading = TRUE;
-		    } else if (keypad_mode_flag != keypad_mode ||
-			       (user_mode_flag != user_mode &&
-				(user_mode_flag == NOVICE_MODE ||
-				 user_mode == NOVICE_MODE)) ||
-			       (((HTfileSortMethod_flag != HTfileSortMethod) ||
-#ifdef DIRED_SUPPORT
-				 (c != dir_list_style) ||
-#endif /* DIRED_SUPPORT */
-				 (show_dotfiles_flag != show_dotfiles)) &&
-				(!strncmp(curdoc.address, "file:", 5) ||
-				 !strncmp(curdoc.address, "ftp:", 4))) ||
-				LYSelectPopups_flag != LYSelectPopups) {
-		        HTuncache_current_document();
-		        FREE(curdoc.address);
-		    }
+		    FREE(curdoc.address);
 		}
 	    }
 	    keypad_mode_flag = keypad_mode;
@@ -3996,6 +4008,7 @@ check_goto_URL:
 	     *  Don't do if not allowed or already viewing the menu.
 	     */	
 	    if (lynx_edit_mode && !no_dired_support &&
+		strcmp(curdoc.address, LYDiredFileURL) &&
 	        strcmp((curdoc.title ? curdoc.title : ""),
 		       DIRED_MENU_TITLE)) {
 	        dired_options(&curdoc,&newdoc.address);
@@ -4029,10 +4042,13 @@ check_goto_URL:
 	        strcmp((curdoc.title ? curdoc.title : ""),
 		       PRINT_OPTIONS_TITLE) &&
 #ifdef DIRED_SUPPORT
+		strcmp(curdoc.address, LYDiredFileURL) &&
 	        strcmp((curdoc.title ? curdoc.title : ""),
 		       DIRED_MENU_TITLE) &&
+		strcmp(curdoc.address, LYPermitFileURL) &&
 	        strcmp((curdoc.title ? curdoc.title : ""),
 		       PERMIT_OPTIONS_TITLE) &&
+		strcmp(curdoc.address, LYUploadFileURL) &&
 	        strcmp((curdoc.title ? curdoc.title : ""),
 		       UPLOAD_OPTIONS_TITLE) &&
 #endif /* DIRED_SUPPORT */
@@ -4304,7 +4320,8 @@ check_add_bookmark_to_self:
 		    }
 
 #ifdef DIRED_SUPPORT
-		} else if (!strcmp((curdoc.title ? curdoc.title : ""),
+		} else if (!strcmp(curdoc.address, LYUploadFileURL) ||
+			   !strcmp((curdoc.title ? curdoc.title : ""),
 				   UPLOAD_OPTIONS_TITLE)) {
 		    if (old_c != real_c)	{
 			old_c = real_c;
@@ -4312,7 +4329,8 @@ check_add_bookmark_to_self:
 			sleep(MessageSecs);
 		    }
 
-		} else if (!strcmp((curdoc.title ? curdoc.title : ""),
+		} else if (!strcmp(curdoc.address, LYPermitFileURL) ||
+			   !strcmp((curdoc.title ? curdoc.title : ""),
 				   PERMIT_OPTIONS_TITLE)) {
 		    if (old_c != real_c)	{
 			old_c = real_c;
@@ -4426,7 +4444,8 @@ check_add_bookmark_to_self:
 	    /*
 	     *  Don't do if already viewing upload options page.
 	     */
-	    if (!strcmp((curdoc.title ? curdoc.title : ""),
+	    if (!strcmp(curdoc.address, LYUploadFileURL) ||
+		!strcmp((curdoc.title ? curdoc.title : ""),
 	    		UPLOAD_OPTIONS_TITLE))
 	        break;
 
diff --git a/src/LYOptions.c b/src/LYOptions.c
index c142671d..84f2f3a7 100644
--- a/src/LYOptions.c
+++ b/src/LYOptions.c
@@ -69,6 +69,30 @@ PRIVATE void option_statusline ARGS1(
     LYStatusLine = -1;
 }
 
+PRIVATE void option_user_message ARGS2(
+	CONST char *,		message,
+	char *,			argument)
+{
+    /*
+     *  Make sure we have a pointer to a string.
+     */
+    if (message == NULL || argument == NULL)
+	return;
+
+    /*
+     *  Don't print statusline messages if dumping to stdout.
+     */
+    if (dump_output_immediately)
+	return;
+
+    /*
+     *  Use _user_message() set to output on the bottom line.
+     */
+    LYStatusLine = (LYlines - 1);
+    _user_message((char *)message, argument);
+    LYStatusLine = -1;
+}
+
 PUBLIC void options NOARGS
 {
 #ifdef ALLOW_USERS_TO_CHANGE_EXEC_WITHIN_OPTIONS
@@ -117,6 +141,42 @@ PUBLIC void options NOARGS
 
     term_options = FALSE;
     signal(SIGINT, terminate_options);
+    if (no_option_save) {
+	if (LYShowColor == SHOW_COLOR_NEVER) {
+	    LYShowColor = SHOW_COLOR_OFF;
+	} else if (LYShowColor == SHOW_COLOR_ALWAYS) {
+	    LYShowColor = SHOW_COLOR_ON;
+	}
+#if defined(USE_SLANG) || defined(COLOR_CURSES)
+    } else {
+	if (LYChosenShowColor == SHOW_COLOR_UNKNOWN) {
+	    switch (LYrcShowColor) {
+	    case SHOW_COLOR_NEVER:
+		LYChosenShowColor =
+		    (LYShowColor >= SHOW_COLOR_ON) ?
+				     SHOW_COLOR_ON :
+				     SHOW_COLOR_NEVER;
+		break;
+	    case SHOW_COLOR_ALWAYS:
+#if defined(COLOR_CURSES)
+		if (!has_colors())
+		    LYChosenShowColor = SHOW_COLOR_ALWAYS;
+		else
+#endif
+		    LYChosenShowColor =
+			(LYShowColor >= SHOW_COLOR_ON) ?
+		    		     SHOW_COLOR_ALWAYS :
+				     SHOW_COLOR_OFF;
+		break;
+	    default:
+		LYChosenShowColor =
+		    (LYShowColor >= SHOW_COLOR_ON) ?
+				     SHOW_COLOR_ON :
+				     SHOW_COLOR_OFF;
+	    }
+	}
+#endif /* USE_SLANG || COLOR_CURSES */
+    }
 
 draw_options:
     /*
@@ -191,7 +251,29 @@ draw_options:
 #if defined(USE_SLANG) || defined(COLOR_CURSES)
     move(L_COLOR, B_COLOR);
     addstr("show color (&)  : ");
-    addstr(LYShowColor ? "ON " : "OFF");
+    if (no_option_save) {
+	addstr((LYShowColor == SHOW_COLOR_OFF ? "OFF" :
+	   					"ON "));
+    } else {
+	switch (LYChosenShowColor) {
+	case SHOW_COLOR_NEVER:
+		addstr("NEVER     ");
+		break;
+	case SHOW_COLOR_OFF:
+		addstr("OFF");
+		break;
+	case SHOW_COLOR_ON:
+		addstr("ON ");
+		break;
+	case SHOW_COLOR_ALWAYS:
+#if defined(COLOR_CURSES)
+		if (!has_colors())
+		    addstr("Always try");
+		else
+#endif
+		    addstr("ALWAYS    ");
+	}
+    }
 #endif /* USE_SLANG || COLOR_CURSES */
 
     move(L_BOOL_A, B_VIKEYS);
@@ -333,7 +415,13 @@ draw_options:
 			addstr(display_option);
 		    }
 		    clrtoeol();
-		    option_statusline(VALUE_ACCEPTED);
+		    if (ch == -1) {
+			option_statusline(CANCELLED);
+			sleep(InfoSecs);
+			option_statusline("");
+		    } else {
+			option_statusline(VALUE_ACCEPTED);
+		    }
 		}
 		response = ' ';
 		break;
@@ -368,7 +456,13 @@ draw_options:
 		     */
 		    addstr((display && *display) ? display : "NONE");
 		    clrtoeol();
-		    option_statusline(VALUE_ACCEPTED);
+		    if (ch == -1) {
+			option_statusline(CANCELLED);
+			sleep(InfoSecs);
+			option_statusline("");
+		    } else {
+			option_statusline(VALUE_ACCEPTED);
+		    }
 		    response = ' ';
 		    break;
 		} else if (*display_option == '\0') {
@@ -543,7 +637,13 @@ draw_options:
 			addstr(bookmark_page);
 		    }
 		    clrtoeol();
-		    option_statusline(VALUE_ACCEPTED);
+		    if (ch == -1) {
+			option_statusline(CANCELLED);
+			sleep(InfoSecs);
+			option_statusline("");
+		    } else {
+			option_statusline(VALUE_ACCEPTED);
+		    }
 		} else { /* anonymous */
 		    option_statusline(BOOKMARK_CHANGE_DISALLOWED);
 		}
@@ -626,7 +726,13 @@ draw_options:
 		    addstr(display_option);
 		}
 		clrtoeol();
-		option_statusline(VALUE_ACCEPTED);
+		if (ch == -1) {
+		    option_statusline(CANCELLED);
+		    sleep(InfoSecs);
+		    option_statusline("");
+		} else {
+		    option_statusline(VALUE_ACCEPTED);
+		}
 		response = ' ';
 		break;
 
@@ -750,7 +856,13 @@ draw_options:
 		    addstr(display_option);
 		}
 		clrtoeol();
-		option_statusline(VALUE_ACCEPTED);
+		if (ch == -1) {
+		    option_statusline(CANCELLED);
+		    sleep(InfoSecs);
+		    option_statusline("");
+		} else {
+		    option_statusline(VALUE_ACCEPTED);
+		}
 		response = ' ';
 		break;
 
@@ -781,7 +893,13 @@ draw_options:
 		    addstr(display_option);
 		}
 		clrtoeol();
-		option_statusline(VALUE_ACCEPTED);
+		if (ch == -1) {
+		    option_statusline(CANCELLED);
+		    sleep(InfoSecs);
+		    option_statusline("");
+		} else {
+		    option_statusline(VALUE_ACCEPTED);
+		}
 		response = ' ';
 		break;
 
@@ -875,34 +993,119 @@ draw_options:
 
 #if defined(USE_SLANG) || defined(COLOR_CURSES)
 	    case '&':	/* Change show color setting. */
+		if (no_option_save) {
 #if defined(COLOR_CURSES)
-		if (!has_colors()) {
-		    option_statusline(COLOR_TOGGLE_DISABLED);
-		    break;
-		}
+		    if (!has_colors()) {
+			char * terminal = getenv("TERM");
+			if (terminal)
+			    option_user_message(
+				COLOR_TOGGLE_DISABLED_FOR_TERM,
+				terminal);
+			else
+			    option_statusline(COLOR_TOGGLE_DISABLED);
+			sleep(AlertSecs);
+		    }
 #endif
 		/*
 		 *  Copy strings into choice array.
 		 */
-		choices[0] = NULL;
-		StrAllocCopy(choices[0], "OFF");
-		choices[1] = NULL;
-		StrAllocCopy(choices[1], "ON ");
-		choices[2] = NULL;
-		LYShowColor = boolean_choice(LYShowColor,
-					      L_COLOR,
-					      C_COLOR,
-					      choices);
+		    choices[0] = NULL;
+		    StrAllocCopy(choices[0], "OFF");
+		    choices[1] = NULL;
+		    StrAllocCopy(choices[1], "ON ");
+		    choices[2] = NULL;
+		    LYShowColor = boolean_choice((LYShowColor - 1),
+						 L_COLOR,
+						 C_COLOR,
+						 choices);
+		    if (LYShowColor == 0) {
+			LYShowColor = SHOW_COLOR_OFF;
+		    } else {
+			LYShowColor = SHOW_COLOR_ON;
+		    }
+		} else {		/* !no_option_save */
+		    BOOLEAN again = FALSE;
+		    int chosen;
+		/*
+		 *  Copy strings into choice array.
+		 */
+		    choices[0] = NULL;
+		    StrAllocCopy(choices[0], "NEVER     ");
+		    choices[1] = NULL;
+		    StrAllocCopy(choices[1], "OFF       ");
+		    choices[2] = NULL;
+		    StrAllocCopy(choices[2], "ON        ");
+		    choices[3] = NULL;
+#if defined(COLOR_CURSES)
+		    if (!has_colors())
+			StrAllocCopy(choices[3], "Always try");
+		    else
+#endif
+			StrAllocCopy(choices[3], "ALWAYS    ");
+		    choices[4] = NULL;
+		    do {
+			if (!LYSelectPopups) {
+			    chosen = boolean_choice(LYChosenShowColor,
+						    L_COLOR,
+						    C_COLOR,
+						    choices);
+			} else {
+			    chosen = popup_choice(LYChosenShowColor,
+						  L_COLOR,
+						  C_COLOR,
+						  choices, 4, FALSE);
+			}
+#if defined(COLOR_CURSES)
+			again = (chosen == 2 && !has_colors());
+			if (again) {
+			    char * terminal = getenv("TERM");
+			    if (terminal)
+				option_user_message(
+				    COLOR_TOGGLE_DISABLED_FOR_TERM,
+				    terminal);
+			    else
+				option_statusline(COLOR_TOGGLE_DISABLED);
+			    sleep(AlertSecs);
+			}
+#endif
+		    } while (again);
+		    LYChosenShowColor = chosen;
+#if defined(VMS)
+		    if (LYSelectPopups) {
+			move(L_COLOR, C_COLOR);
+			clrtoeol();
+			addstr(choices[LYChosenShowColor]);
+		    }
+#endif /* VMS */
+#if defined(COLOR_CURSES)
+		    if (has_colors())
+#endif
+			LYShowColor = chosen;
+		    FREE(choices[2]);
+		    FREE(choices[3]);
+		}
 		FREE(choices[0]);
 		FREE(choices[1]);
 		if (CurrentShowColor != LYShowColor) {
-		    CurrentShowColor = LYShowColor;
-#ifdef USE_SLANG
-		    SLtt_Use_Ansi_Colors = LYShowColor;
-#endif
 		    lynx_force_repaint();
 		}
+		CurrentShowColor = LYShowColor;
+#ifdef USE_SLANG
+		SLtt_Use_Ansi_Colors = (LYShowColor > 1 ? 1 : 0);
+#endif
 		response = ' ';
+		if (LYSelectPopups && !no_option_save) {
+#if !defined(VMS) || defined(USE_SLANG)
+		    if (term_options) {
+		        term_options = FALSE;
+	            } else {
+		        AddValueAccepted = TRUE;
+		    }
+		    goto draw_options;
+#else
+		    term_options = FALSE;
+#endif /* !VMS || USE_SLANG */
+		}
 		break;
 #endif /* USE_SLANG or COLOR_CURSES */
 
@@ -1137,7 +1340,11 @@ draw_options:
 			addstr(display_option);
 		    }
 		    clrtoeol();
-		    if (LYUserAgent && *LYUserAgent &&
+		    if (ch == -1) {
+			option_statusline(CANCELLED);
+			sleep(InfoSecs);
+			option_statusline("");
+		    } else if (LYUserAgent && *LYUserAgent &&
 			!strstr(LYUserAgent, "Lynx") &&
 			!strstr(LYUserAgent, "lynx")) {
 			option_statusline(UA_COPYRIGHT_WARNING);
@@ -1241,6 +1448,7 @@ draw_options:
 		if (!no_option_save) {
 		    option_statusline(SAVING_OPTIONS);
 		    if (save_rc()) {
+			LYrcShowColor = LYChosenShowColor;
 			option_statusline(OPTIONS_SAVED);
 		    } else {
 			HTAlert(OPTIONS_NOT_SAVED);
@@ -2675,7 +2883,7 @@ check_recall:
 		 *  If we started at the beginning, it can't be present. - FM
 		 */
 		if (cur_choice == 0) {
-		    _user_message(STRING_NOT_FOUND, prev_target_buffer);
+		    option_user_message(STRING_NOT_FOUND, prev_target_buffer);
 		    sleep(MessageSecs);
 		    goto restore_popup_statusline;
 		}
@@ -2718,7 +2926,7 @@ check_recall:
 		/*
 		 *  Didn't find it in the preceding choices either. - FM
 		 */
-		_user_message(STRING_NOT_FOUND, prev_target_buffer);
+		option_user_message(STRING_NOT_FOUND, prev_target_buffer);
 		sleep(MessageSecs);
 
 restore_popup_statusline:
diff --git a/src/LYOptions.h b/src/LYOptions.h
index fc6e63c2..8855563f 100644
--- a/src/LYOptions.h
+++ b/src/LYOptions.h
@@ -24,9 +24,9 @@ extern void edit_bookmarks NOPARAMS;
 #define L_FTPSTYPE	 5
 #define L_MAIL_ADDRESS	 6
 #define L_SSEARCH	 7
-#define L_CHARSET	 8
-#define L_LANGUAGE	 9
-#define L_PREF_CHARSET	10
+#define L_LANGUAGE	 8
+#define L_PREF_CHARSET	 9
+#define L_CHARSET	10
 #define L_RAWMODE	11
 
 #define L_COLOR		L_RAWMODE
diff --git a/src/LYReadCFG.c b/src/LYReadCFG.c
index 7a6f16c2..18f0c1d5 100644
--- a/src/LYReadCFG.c
+++ b/src/LYReadCFG.c
@@ -350,7 +350,7 @@ PRIVATE int check_color ARGS1(
  *  Exit routine for failed COLOR parsing.
  */
 PRIVATE void exit_with_color_syntax ARGS1(
-	char *,	error_line)
+	char *,		error_line)
 {
     unsigned int i;
     fprintf (stderr, "\
@@ -434,6 +434,7 @@ PUBLIC void read_cfg ARGS1(
     char buffer[501];
     char temp[501];
     char *line_feed;
+    char *cp, *cp1;
     int i, j, len;
 
     /*
@@ -462,7 +463,19 @@ PUBLIC void read_cfg ARGS1(
 	    *line_feed = '\0';
 	
 	/*
-	 *  Strip off trailing white space
+	 *  Trim off any trailing comments.
+	 */
+	if ((cp = (char *)strrchr(buffer, ':')) != NULL) {
+	    if ((cp1 = (char *)strchr(cp, '#')) != NULL) {
+		cp1--;
+		if (isspace((unsigned char)*cp1)) {
+		    *cp1 = '\0';
+		}
+	    }
+	}
+
+	/*
+	 *  Strip off trailing white space.
 	 */
 	len = strlen(buffer);
 	while (len && isspace(buffer[len-1])) {
@@ -471,7 +484,7 @@ PUBLIC void read_cfg ARGS1(
 	}
 
 	/*
-	 *  Skip any comment or blank lines.
+	 *  Skip any blank or purely comment lines.
 	 */
 	if (buffer[0] == '\0' || buffer[0] == '#')
 	    continue;
@@ -512,14 +525,16 @@ PUBLIC void read_cfg ARGS1(
 	} else if (!strncasecomp(buffer, "ASSUME_LOCAL_CHARSET:", 21)) {
 	    StrAllocCopy(UCAssume_localMIMEcharset, buffer+21);
 	    for (i = 0; UCAssume_localMIMEcharset[i]; i++)
-	        UCAssume_localMIMEcharset[i] = TOLOWER(UCAssume_localMIMEcharset[i]);
+	        UCAssume_localMIMEcharset[i] =
+			TOLOWER(UCAssume_localMIMEcharset[i]);
 	    UCLYhndl_HTFile_for_unspec =
 		UCGetLYhndl_byMIME(UCAssume_localMIMEcharset);
 
 	} else if (!strncasecomp(buffer, "ASSUME_UNREC_CHARSET:", 21)) {
 	    StrAllocCopy(UCAssume_unrecMIMEcharset, buffer+21);
 	    for (i = 0; UCAssume_unrecMIMEcharset[i]; i++)
-	        UCAssume_unrecMIMEcharset[i] = TOLOWER(UCAssume_unrecMIMEcharset[i]);
+	        UCAssume_unrecMIMEcharset[i] =
+			TOLOWER(UCAssume_unrecMIMEcharset[i]);
 	    UCLYhndl_for_unrec =
 		UCGetLYhndl_byMIME(UCAssume_unrecMIMEcharset);
 #endif /* EXP_CHARTRANS */
@@ -1127,6 +1142,7 @@ PUBLIC void read_cfg ARGS1(
 	    add_trusted(&buffer[13], EXEC_PATH); /* Add exec path */
 	}
 #endif /* EXEC_LINKS */
+
 #ifdef LYNXCGI_LINKS
 	if (!strncasecomp(buffer, "TRUSTED_LYNXCGI:", 16)) {
 	    add_trusted(&buffer[16], CGI_PATH); /* Add CGI path */
diff --git a/src/LYUpload.c b/src/LYUpload.c
index 48c6f19d..2fd3b373 100644
--- a/src/LYUpload.c
+++ b/src/LYUpload.c
@@ -1,16 +1,17 @@
-/* Routines to upload files to the local filesystem */
-/* Created by: Rick Mallett, Carleton University */
-/* Report problems to rmallett@ccs.carleton.ca */
-/* Modified 15-Dec-95 George Lindholm (lindholm@ucs.ubc.ca):
-	Reread the upload menu page every time, in case the "upload" directory
-	  has changed (make the current directory that for the upload process).
-	Prompt for the upload file name if there is no "%s" in the command
-	  string. Most protocols allow the user to specify the file name
-	  from the client side.  Xmodem appears to be the only that can't
-	  figure out the filename from the transfer data so it needs the
-	  information from lynx (or an upload script which prompts for it).
-	  On the other hand, zmodem aborts when you give it a filename on
-	  the command line (great way of bypassing the nodotfile code :=( ).
+/*
+**  Routines to upload files to the local filesystem.
+**  Created by: Rick Mallett, Carleton University
+**  Report problems to rmallett@ccs.carleton.ca
+**  Modified 15-Dec-95 George Lindholm (lindholm@ucs.ubc.ca):
+**	Reread the upload menu page every time, in case the "upload" directory
+**	  has changed (make the current directory that for the upload process).
+**	Prompt for the upload file name if there is no "%s" in the command
+**	  string. Most protocols allow the user to specify the file name
+**	  from the client side.  Xmodem appears to be the only that can't
+**	  figure out the filename from the transfer data so it needs the
+**	  information from lynx (or an upload script which prompts for it).
+**	  On the other hand, zmodem aborts when you give it a filename on
+**	  the command line (great way of bypassing the nodotfile code :=( ).
 */
 
 #include "HTUtils.h"
@@ -33,24 +34,23 @@
 
 #define FREE(x) if (x) {free(x); x = NULL;}
 
+PUBLIC char LYUploadFileURL[256] = "\0";
+
 /*
  *  LYUpload uploads a file to a given location using a 
- *  specified upload method.
- */
-
-/* it parses an incoming link that looks like
- *
- *  LYNXDIRED://UPLOAD=<#>/TO=<STRING>
+ *  specified upload method.  It parses an incoming link
+ *  that looks like:
+ *	LYNXDIRED://UPLOAD=<#>/TO=<STRING>
  */
-
-PUBLIC int LYUpload ARGS1(char *,line) 
+PUBLIC int LYUpload ARGS1(
+	char *,		line) 
 {
     char *method, *directory, *dir;
     int method_number;
     int count;
     char tmpbuf[256];
     char buffer[256];
-    lynx_html_item_type *upload_command=0;
+    lynx_html_item_type *upload_command = 0;
     int c;
     char *cp;
     FILE *fp;
@@ -59,63 +59,69 @@ PUBLIC int LYUpload ARGS1(char *,line)
     extern BOOLEAN HadVMSInterrupt;
 #endif /* VMS */
 
-    /* use configured upload commands */
-
+    /*
+     *  Use configured upload commands.
+     */
     if((directory = (char *)strstr(line, "TO=")) == NULL)
 	goto failed;
-    *(directory-1) = '\0';
+    *(directory - 1) = '\0';
     /* go past "Directory=" */
     directory+=3;
 
     if((method = (char *)strstr(line, "UPLOAD=")) == NULL)
 	goto failed;
-    /* go past "Method=" */
-    method+=7;
+    /*
+     *  Go past "Method=".
+     */
+    method += 7;
     method_number = atoi(method);
 
-    for(count=0, upload_command=uploaders; count < method_number;
+    for (count = 0, upload_command = uploaders; count < method_number;
 	count++, upload_command = upload_command->next)
       ; /* null body */
 
-    /* Parsed out the Method and the Location? */
-    if(upload_command->command == NULL) {
+    /*
+     *  Parsed out the Method and the Location?
+     */
+    if (upload_command->command == NULL) {
 	_statusline("ERROR! - upload command is misconfigured");
 	sleep(AlertSecs);
 	goto failed;
     }
 
-    /* Care about the local name? */
+    /*
+     *  Care about the local name?
+     */
     if (strstr(upload_command->command, "%s")) {
 	/*
-	 * Commands have the form "command %s [etc]"
-	 * where %s is the filename.
+	 *  Commands have the form "command %s [etc]"
+	 *  where %s is the filename.
 	 */
-
 	_statusline("Enter a filename: ");
 retry:
 	*tmpbuf = '\0';
-	if(LYgetstr(tmpbuf, VISIBLE, sizeof(tmpbuf), NORECALL) < 0)
+	if (LYgetstr(tmpbuf, VISIBLE, sizeof(tmpbuf), NORECALL) < 0)
 	    goto cancelled;
 
-	if(*tmpbuf=='\0')
+	if (*tmpbuf == '\0')
 	    goto cancelled;
 
-	if (strstr(tmpbuf,"../") != NULL) {
+	if (strstr(tmpbuf, "../") != NULL) {
 	    _statusline(
-		    "Illegal redirection \"../\" found! Request ignored. ");
+		    "Illegal redirection \"../\" found! Request ignored.");
 	    sleep(AlertSecs);
 	    goto cancelled;
-	} else if(strchr(tmpbuf,'/') != NULL) {
-	    _statusline("Illegal character \"/\" found! Request ignored. ");
+	} else if (strchr(tmpbuf, '/') != NULL) {
+	    _statusline("Illegal character \"/\" found! Request ignored.");
 	    sleep(AlertSecs);
 	    goto cancelled;
 	} else if (tmpbuf[0] == '~') {
 	    _statusline(
-		"Illegal redirection using \"~\" found! Request ignored. ");
+		"Illegal redirection using \"~\" found! Request ignored.");
 	    sleep(AlertSecs);
 	    goto cancelled;
 	}
-	sprintf(buffer,"%s/%s",directory,tmpbuf);
+	sprintf(buffer, "%s/%s", directory, tmpbuf);
 
 	if (no_dotfiles || !show_dotfiles) {
 	    if (*buffer == '.' ||
@@ -130,8 +136,10 @@ retry:
 	    }
 	}
 
-	/* See if it already exists. */
-	if((fp = fopen(buffer,"r")) != NULL) {
+	/*
+	 *  See if it already exists.
+	 */
+	if ((fp = fopen(buffer, "r")) != NULL) {
 	    fclose(fp);
 
 #ifdef VMS
@@ -140,28 +148,29 @@ retry:
 	    _statusline("File exists. Overwrite? (y/n)");
 #endif /* VMS */
 	    c = 0;
-	    while(TOUPPER(c)!='Y' && TOUPPER(c)!='N' && c != 7 && c != 3)
+	    while (TOUPPER(c) != 'Y' && TOUPPER(c) != 'N' && c != 7 && c != 3)
 		c = LYgetch();
 #ifdef VMS
-	    if(HadVMSInterrupt) {
+	    if (HadVMSInterrupt) {
 		HadVMSInterrupt = FALSE;
 		goto cancelled;
 	    }
 #endif /* VMS */
 
-	    if(c == 7 || c == 3) { /* Control-G or Control-C */
+	    if (c == 7 || c == 3) { /* Control-G or Control-C */
 		goto cancelled;
 	    }
 
-	    if(TOUPPER(c) == 'N') {
+	    if (TOUPPER(c) == 'N') {
 		_statusline("Enter a filename: ");
 		goto retry;
 	    }
 	}
 
-	/* see if we can write to it */
-
-	if((fp = fopen(buffer,"w")) != NULL) {
+	/*
+	 *  See if we can write to it.
+	 */
+	if ((fp = fopen(buffer, "w")) != NULL) {
 	    fclose(fp);
 	    remove(buffer);
 	} else {
@@ -170,10 +179,10 @@ retry:
 	}
 
 #ifdef VMS
-	sprintf(tmpbuf,upload_command->command,buffer);
+	sprintf(tmpbuf, upload_command->command, buffer, "", "", "", "", "");
 #else
 	cp = quote_pathname(buffer); /* to prevent spoofing of the shell */
-	sprintf(tmpbuf,upload_command->command,cp);
+	sprintf(tmpbuf, upload_command->command, cp, "", "", "", "", "");
 	FREE(cp);
 #endif /* VMS */
     } else {			/* No substitution, no changes */
@@ -184,8 +193,8 @@ retry:
     sprintf(cmd, "cd %s ; %s", dir, tmpbuf);
     FREE(dir);
     stop_curses();
-    if(TRACE)
-	fprintf(stderr,"command: %s\n",cmd);
+    if (TRACE)
+	fprintf(stderr, "command: %s\n", cmd);
     system(cmd);
     fflush(stdout);
     start_curses();
@@ -195,31 +204,27 @@ retry:
     return 1;
 
 failed:
-
     _statusline("Unable to upload file.");
     sleep(AlertSecs);
     return 0;
 
 cancelled:
-
     _statusline("Cancelling.");
     sleep(InfoSecs);
     return 0;
-
 }
 
 /*
- * LYUpload_options writes out the current upload choices to a file
- * so that the user can select printers in the same way that
- * they select all other links 
- * upload links look like
- *  LYNXDIRED//UPLOAD=<#>/TO=<STRING>
+ *  LYUpload_options writes out the current upload choices to a
+ *  file so that the user can select printers in the same way that
+ *  they select all other links.  Upload links look like:
+ *	LYNXDIRED//UPLOAD=<#>/TO=<STRING>
  */
-
-PUBLIC int LYUpload_options ARGS2 (char **,newfile, char *,directory)
+PUBLIC int LYUpload_options ARGS2(
+	char **,	newfile,
+	char *,		directory)
 {
-    char upload_filename[256];
-    static char tempfile[128];
+    static char tempfile[256];
     static BOOLEAN first = TRUE;
     FILE *fp0;
     lynx_html_item_type *cur_upload;
@@ -228,61 +233,72 @@ PUBLIC int LYUpload_options ARGS2 (char **,newfile, char *,directory)
     char *cp;
 
     if (first) {
+	/*
+	 *  Get an unused tempfile name. - FM
+	 */
         tempname(tempfile, NEW_FILE);
-	first = FALSE;
 #ifdef VMS
     } else {
         remove(tempfile);   /* Remove duplicates on VMS. */
 #endif /* VMS */
     }
 
-    if ((fp0 = fopen(tempfile,"w")) == NULL) {
+    /*
+     *  Open the tempfile for writing and set it's
+     *  protection in case this wasn't done via an
+     *  external umask. - FM
+     */
+    if ((fp0 = fopen(tempfile, "w")) == NULL) {
 	HTAlert(CANNOT_OPEN_TEMP);
 	return(-1);
     }
+    chmod(tempfile, 0600);
 
 #ifdef VMS
     strcpy(curloc, "/sys$login");
 #else
     cp = directory;
-    if (!strncmp(cp,"file://localhost",16))
+    if (!strncmp(cp, "file://localhost", 16))
         cp += 16;
-    else if (!strncmp(cp,"file:",5))
+    else if (!strncmp(cp, "file:", 5))
         cp += 5;
     strcpy(curloc,cp);
     HTUnEscape(curloc);
-    if (curloc[strlen(curloc)-1] == '/')
-        curloc[strlen(curloc)-1] = '\0';
+    if (curloc[strlen(curloc) - 1] == '/')
+        curloc[strlen(curloc) - 1] = '\0';
 #endif /* VMS */
 
-    /* make the file a URL now */
+    if (first) {
+	/*
+	 *  Make the tempfile a URL.
+ 	 */
 #if defined (VMS) || defined (DOSPATH)
-    sprintf(upload_filename,"file://localhost/%s",tempfile);
+	sprintf(LYUploadFileURL, "file://localhost/%s", tempfile);
 #else
-    sprintf(upload_filename,"file://localhost%s",tempfile);
+	sprintf(LYUploadFileURL, "file://localhost%s", tempfile);
 #endif /* VMS */
-    StrAllocCopy(*newfile, upload_filename);
+	first = FALSE;
+    }
+    StrAllocCopy(*newfile, LYUploadFileURL);
 
-    fprintf(fp0,"<head>\n<title>%s</title>\n</head>\n<body>\n",
-    		UPLOAD_OPTIONS_TITLE);
+    fprintf(fp0, "<head>\n<title>%s</title>\n</head>\n<body>\n",
+    		 UPLOAD_OPTIONS_TITLE);
 
-    fprintf(fp0,"<h1>Upload Options (%s Version %s)</h1>\n",
-    				     LYNX_NAME, LYNX_VERSION);
+    fprintf(fp0, "<h1>Upload Options (%s Version %s)</h1>\n",
+    				      LYNX_NAME, LYNX_VERSION);
 
     fputs("You have the following upload choices.<br>\n", fp0);
     fputs("Please select one:<br>\n<pre>\n", fp0);
 
-    if(uploaders != NULL) {
-
-       for(count=0, cur_upload=uploaders; cur_upload != NULL; 
-	   cur_upload = cur_upload->next, count++) {
-
-	  fprintf(fp0, "   <a href=\"LYNXDIRED://UPLOAD=%d/TO=%s\">",
-	  	       count,curloc);
-
-	  fprintf(fp0, (cur_upload->name ? 
-			cur_upload->name : "No Name Given"));
-	  fprintf(fp0, "</a>\n");
+    if (uploaders != NULL) {
+	for (count = 0, cur_upload = uploaders;
+	     cur_upload != NULL; 
+	     cur_upload = cur_upload->next, count++) {
+	    fprintf(fp0, "   <a href=\"LYNXDIRED://UPLOAD=%d/TO=%s\">",
+			 count, curloc);
+	    fprintf(fp0, (cur_upload->name ? 
+			  cur_upload->name : "No Name Given"));
+	    fprintf(fp0, "</a>\n");
 	}
     } else {
 	fprintf(fp0, "\n   \
diff --git a/src/LYrcFile.c b/src/LYrcFile.c
index 3b59fbd9..147cf7c6 100644
--- a/src/LYrcFile.c
+++ b/src/LYrcFile.c
@@ -335,8 +335,7 @@ PUBLIC void read_rc NOPARAMS
 	        show_dotfiles = TRUE;
 	    else
 	        show_dotfiles = FALSE;
-#if 0	/* UNUSED */
-#if defined(USE_SLANG) || defined(COLOR_CURSES)
+
 	/*
 	 *  Show color.
 	 */
@@ -346,13 +345,20 @@ PUBLIC void read_rc NOPARAMS
 	    if ((cp2 = (char * )strchr(cp, '=')) != NULL)
 		cp = cp2 + 1;
 	    while (isspace(*cp))
-		cp++;  /* get rid of spaces */
-	    if (!strncasecomp(cp, "off", 3))
-		LYShowColor = FALSE;
-	    else
-		LYShowColor = TRUE;
+	        cp++;  /* get rid of spaces */
+	    if (!strncasecomp(cp, "always", 6)) {
+		LYrcShowColor = SHOW_COLOR_ALWAYS;
+#if defined(USE_SLANG) || defined(COLOR_CURSES)
+		if (LYShowColor != SHOW_COLOR_NEVER)
+		    LYShowColor = SHOW_COLOR_ALWAYS;
 #endif /* USE_SLANG || COLOR_CURSES */
-#endif /* UNUSED */
+	    } else if (!strncasecomp(cp, "never", 5)) {
+		LYrcShowColor = SHOW_COLOR_NEVER;
+#if defined(COLOR_CURSES)
+		if (LYShowColor == SHOW_COLOR_ON)
+		    LYShowColor = SHOW_COLOR_OFF;
+#endif /* COLOR_CURSES */
+	    }
 
 	/*
 	 *  Select popups.
@@ -669,18 +675,31 @@ PUBLIC int save_rc NOPARAMS
     fprintf(fp, "preferred_charset=%s\n\n",
     		(pref_charset ? pref_charset : ""));
 
-#if defined(USE_SLANG) || defined(COLOR_CURSES)
     /*
      *  Show color.
      */
-    fprintf(fp, "\
-# show_color specifies whether to show colors when available, or assume a\n\
-# monochrome terminal.  A value of \"on\" will force color mode on, while\n\
-# a value of \"off\" will force it off.  The default can be overridden via\n\
-# the -color and -nocolor command line switches or (if built with slang) the\n\
-# COLORTERM environment variable.\n");
-    fprintf(fp, "show_color=%s\n\n", (LYShowColor ? "on" : "off"));
-#endif /* USE_SLANG || COLOR_CURSES */
+    if (LYChosenShowColor != SHOW_COLOR_UNKNOWN) {
+	fprintf(fp, "\
+# show_color specifies how to set the color mode at startup.  A value of\n\
+# \"never\" will force color mode off (treat the terminal as monochrome)\n\
+# at startup even if the terminal appears to be color capable.  A value of\n\
+# \"always\" will force color mode on even if the terminal appears to be\n\
+# monochrome, if this is supported by the library used to build lynx.\n\
+# A value of \"default\" will yield the behavior of assuming\n\
+# a monochrome terminal unless color capability is inferred at startup\n\
+# based on the terminal type, or the -color command line switch is used, or\n\
+# the COLORTERM environment variable is set. The default behavior always is\n\
+# used in anonymous accounts or if the \"option_save\" restriction is set.\n\
+# The effect of the saved value can be overridden via\n\
+# the -color and -nocolor command line switches.\n\
+# The mode set at startup can be changed via the \"show color\" option in\n\
+# the 'o'ptions menu.  If the option settings are saved, the \"on\" and\n\
+# \"off\" \"show color\" settings will be treated as \"default\".\n");
+     fprintf(fp, "show_color=%s\n\n",
+	     ((LYChosenShowColor == SHOW_COLOR_NEVER  ? "never"  :
+	       (LYChosenShowColor == SHOW_COLOR_ALWAYS ? "always" :
+						      "default"))));
+    }
 
     /*
      *  VI keys.
diff --git a/src/Makefile b/src/Makefile
index 112f0521..5c8048cc 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -70,6 +70,7 @@ TABLES= $(CHRTR)iso02_uni.h \
  $(CHRTR)cp850_uni.h \
  $(CHRTR)cp852_uni.h \
  $(CHRTR)cp1250_uni.h \
+ $(CHRTR)cp1251_uni.h \
  $(CHRTR)cp1252_uni.h \
  $(CHRTR)utf8_uni.h \
  $(CHRTR)rfc_suni.h \
diff --git a/src/UCAux.c b/src/UCAux.c
index db88bbcf..a1065489 100644
--- a/src/UCAux.c
+++ b/src/UCAux.c
@@ -69,9 +69,11 @@ PUBLIC BOOL UCCanTranslateFromTo ARGS2(
 	    
 	if (!strcmp(fromname, "koi8-r") || /* from cyrillic */
 	    !strcmp(fromname, "iso-8859-5") ||
+	    !strcmp(fromname, "windows-1251") ||
 	    !strcmp(fromname, "koi-8")) {
 	    if (strcmp(toname, "iso-8859-5") &&
 		strcmp(toname, "koi8-r") &&
+		strcmp(toname, "windows-1251") &&
 		strcmp(toname, "iso-8859-2"))
 		return NO;
 	}
diff --git a/src/UCdomap.c b/src/UCdomap.c
index a443b7f4..fba41b45 100644
--- a/src/UCdomap.c
+++ b/src/UCdomap.c
@@ -47,6 +47,7 @@
 #include "[.chrtrans]cp850_uni.h"
 #include "[.chrtrans]cp852_uni.h"
 #include "[.chrtrans]cp1250_uni.h"
+#include "[.chrtrans]cp1251_uni.h"
 #include "[.chrtrans]cp1252_uni.h"
 #include "[.chrtrans]utf8_uni.h"
 #include "[.chrtrans]rfc_suni.h"
@@ -69,6 +70,7 @@
 #include "chrtrans/cp850_uni.h"
 #include "chrtrans/cp852_uni.h"
 #include "chrtrans/cp1250_uni.h"
+#include "chrtrans/cp1251_uni.h"
 #include "chrtrans/cp1252_uni.h"
 #include "chrtrans/utf8_uni.h"
 #include "chrtrans/rfc_suni.h"
@@ -1263,6 +1265,27 @@ PUBLIC int UCGetLYhndl_byMIME ARGS1(
 	  return UCGetLYhndl_byMIME("iso-2022-cn");
 	} else if (!strcmp(UC_MIMEcharset, "euc-cn")) {
 	  return UCGetLYhndl_byMIME("iso-2022-cn");
+	} else if (!strcmp(UC_MIMEcharset, "windows-1252")) {
+	    /*
+	     *  It's not my fault that Microsoft hasn't registered
+	     *  the name people are using... - kw
+	     */
+	  return UCGetLYhndl_byMIME("iso-8859-1-windows-3.1-latin-1");
+	} else if (!strncmp(UC_MIMEcharset, "ibm", 3)) {
+	    CONST char * cp = UC_MIMEcharset + 3;
+	    char * cptmp = NULL;
+	    if (*cp && isdigit(*cp) &&
+		*(cp++) && isdigit(*cp) &&
+		*(cp++) && isdigit(*cp)) {
+		/*
+		 *  For "ibmNNN<...>", try "cpNNN<...>" if not yet found - kw
+		 */
+		StrAllocCopy(cptmp, UC_MIMEcharset + 1);
+		cptmp[0] = 'c';
+		cptmp[1] = 'p';
+		LYhndl = UCGetLYhndl_byMIME(cptmp);
+		FREE(cptmp);
+	    }
 	} else if (!strcmp(UC_MIMEcharset, "koi-8")) { /* accentsoft bogosity */
 	  return UCGetLYhndl_byMIME("koi8-r");
   }
@@ -1648,6 +1671,7 @@ PUBLIC void UCInit NOARGS
   UC_CHARSET_SETUP_cp850;
   UC_CHARSET_SETUP_cp852;
   UC_CHARSET_SETUP_windows_1250;
+  UC_CHARSET_SETUP_windows_1251;
   UC_CHARSET_SETUP_iso_8859_1_windows_;
   UC_CHARSET_SETUP_unicode_1_1_utf_8;
   UC_CHARSET_SETUP_mnemonic_ascii_0;
diff --git a/src/chrtrans/Makefile b/src/chrtrans/Makefile
index 02f36f4f..af982a90 100644
--- a/src/chrtrans/Makefile
+++ b/src/chrtrans/Makefile
@@ -36,6 +36,7 @@ TABLES= $(CHRTR)iso02_uni.h \
  $(CHRTR)cp850_uni.h \
  $(CHRTR)cp852_uni.h \
  $(CHRTR)cp1250_uni.h \
+ $(CHRTR)cp1251_uni.h \
  $(CHRTR)cp1252_uni.h \
  $(CHRTR)utf8_uni.h \
  $(CHRTR)rfc_suni.h \
@@ -66,6 +67,7 @@ cp437_uni.h: cp437_uni.tbl makeuctb
 cp850_uni.h: cp850_uni.tbl makeuctb
 cp852_uni.h: cp852_uni.tbl makeuctb
 cp1250_uni.h: cp1250_uni.tbl makeuctb
+cp1251_uni.h: cp1251_uni.tbl makeuctb
 cp1252_uni.h: cp1252_uni.tbl makeuctb
 utf8_uni.h: utf8_uni.tbl makeuctb
 mnemonic_suni.h: mnemonic_suni.tbl makeuctb
diff --git a/src/chrtrans/build-chrtrans.com b/src/chrtrans/build-chrtrans.com
index b9a3d515..c2604a9f 100644
--- a/src/chrtrans/build-chrtrans.com
+++ b/src/chrtrans/build-chrtrans.com
@@ -104,6 +104,8 @@ $ define/user sys$output 'CHRwhere'cp852_uni.h
 $ makeuctb cp852_uni.tbl
 $ define/user sys$output 'CHRwhere'cp1250_uni.h
 $ makeuctb cp1250_uni.tbl
+$ define/user sys$output 'CHRwhere'cp1251_uni.h
+$ makeuctb cp1251_uni.tbl
 $ define/user sys$output 'CHRwhere'cp1252_uni.h
 $ makeuctb cp1252_uni.tbl
 $ define/user sys$output 'CHRwhere'utf8_uni.h
diff --git a/src/chrtrans/cp1251_uni.tbl b/src/chrtrans/cp1251_uni.tbl
new file mode 100644
index 00000000..ada70396
--- /dev/null
+++ b/src/chrtrans/cp1251_uni.tbl
@@ -0,0 +1,151 @@
+#The MIME name of this charset.
+Mwindows-1251
+
+#Name as a Display Charset (used on Options screen)
+OWinCyrillic (cp1251)
+
+#
+#    Name:     cp1251_WinCyrillic to Unicode table
+#    Unicode version: 2.0
+#    Table version: 2.00
+#    Table format:  Format A
+#    Date:          04/24/96
+#    Authors:       Lori Brownell <loribr@microsoft.com>
+#                   K.D. Chang    <a-kchang@microsoft.com>
+#    General notes: none
+#
+#    Format: Three tab-separated columns
+#        Column #1 is the cp1251_WinCyrillic code (in hex)
+#        Column #2 is the Unicode (in hex as 0xXXXX)
+#        Column #3 is the Unicode name (follows a comment sign, '#')
+#
+#    The entries are in cp1251_WinCyrillic order
+#
+0x80    U+0402  #CYRILLIC CAPITAL LETTER DJE
+0x81    U+0403  #CYRILLIC CAPITAL LETTER GJE
+0x82    U+201A  #SINGLE LOW-9 QUOTATION MARK
+0x83    U+0453  #CYRILLIC SMALL LETTER GJE
+0x84    U+201E  #DOUBLE LOW-9 QUOTATION MARK
+0x85    U+2026  #HORIZONTAL ELLIPSIS
+0x86    U+2020  #DAGGER
+0x87    U+2021  #DOUBLE DAGGER
+#0x88            #UNDEFINED
+0x89    U+2030  #PER MILLE SIGN
+0x8A    U+0409  #CYRILLIC CAPITAL LETTER LJE
+0x8B    U+2039  #SINGLE LEFT-POINTING ANGLE QUOTATION MARK
+0x8C    U+040A  #CYRILLIC CAPITAL LETTER NJE
+0x8D    U+040C  #CYRILLIC CAPITAL LETTER KJE
+0x8E    U+040B  #CYRILLIC CAPITAL LETTER TSHE
+0x8F    U+040F  #CYRILLIC CAPITAL LETTER DZHE
+0x90    U+0452  #CYRILLIC SMALL LETTER DJE
+0x91    U+2018  #LEFT SINGLE QUOTATION MARK
+0x92    U+2019  #RIGHT SINGLE QUOTATION MARK
+0x93    U+201C  #LEFT DOUBLE QUOTATION MARK
+0x94    U+201D  #RIGHT DOUBLE QUOTATION MARK
+0x95    U+2022  #BULLET
+0x96    U+2013  #EN DASH
+0x97    U+2014  #EM DASH
+#0x98            #UNDEFINED
+0x99    U+2122  #TRADE MARK SIGN
+0x9A    U+0459  #CYRILLIC SMALL LETTER LJE
+0x9B    U+203A  #SINGLE RIGHT-POINTING ANGLE QUOTATION MARK
+0x9C    U+045A  #CYRILLIC SMALL LETTER NJE
+0x9D    U+045C  #CYRILLIC SMALL LETTER KJE
+0x9E    U+045B  #CYRILLIC SMALL LETTER TSHE
+0x9F    U+045F  #CYRILLIC SMALL LETTER DZHE
+0xA0    U+00A0  #NO-BREAK SPACE
+0xA1    U+040E  #CYRILLIC CAPITAL LETTER SHORT U
+0xA2    U+045E  #CYRILLIC SMALL LETTER SHORT U
+0xA3    U+0408  #CYRILLIC CAPITAL LETTER JE
+0xA4    U+00A4  #CURRENCY SIGN
+0xA5    U+0490  #CYRILLIC CAPITAL LETTER GHE WITH UPTURN
+0xA6    U+00A6  #BROKEN BAR
+0xA7    U+00A7  #SECTION SIGN
+0xA8    U+0401  #CYRILLIC CAPITAL LETTER IO
+0xA9    U+00A9  #COPYRIGHT SIGN
+0xAA    U+0404  #CYRILLIC CAPITAL LETTER UKRAINIAN IE
+0xAB    U+00AB  #LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+0xAC    U+00AC  #NOT SIGN
+0xAD    U+00AD  #SOFT HYPHEN
+0xAE    U+00AE  #REGISTERED SIGN
+0xAF    U+0407  #CYRILLIC CAPITAL LETTER YI
+0xB0    U+00B0  #DEGREE SIGN
+0xB1    U+00B1  #PLUS-MINUS SIGN
+0xB2    U+0406  #CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I
+0xB3    U+0456  #CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I
+0xB4    U+0491  #CYRILLIC SMALL LETTER GHE WITH UPTURN
+0xB5    U+00B5  #MICRO SIGN
+0xB6    U+00B6  #PILCROW SIGN
+0xB7    U+00B7  #MIDDLE DOT
+0xB8    U+0451  #CYRILLIC SMALL LETTER IO
+0xB9    U+2116  #NUMERO SIGN
+0xBA    U+0454  #CYRILLIC SMALL LETTER UKRAINIAN IE
+0xBB    U+00BB  #RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+0xBC    U+0458  #CYRILLIC SMALL LETTER JE
+0xBD    U+0405  #CYRILLIC CAPITAL LETTER DZE
+0xBE    U+0455  #CYRILLIC SMALL LETTER DZE
+0xBF    U+0457  #CYRILLIC SMALL LETTER YI
+0xC0    U+0410  #CYRILLIC CAPITAL LETTER A
+0xC1    U+0411  #CYRILLIC CAPITAL LETTER BE
+0xC2    U+0412  #CYRILLIC CAPITAL LETTER VE
+0xC3    U+0413  #CYRILLIC CAPITAL LETTER GHE
+0xC4    U+0414  #CYRILLIC CAPITAL LETTER DE
+0xC5    U+0415  #CYRILLIC CAPITAL LETTER IE
+0xC6    U+0416  #CYRILLIC CAPITAL LETTER ZHE
+0xC7    U+0417  #CYRILLIC CAPITAL LETTER ZE
+0xC8    U+0418  #CYRILLIC CAPITAL LETTER I
+0xC9    U+0419  #CYRILLIC CAPITAL LETTER SHORT I
+0xCA    U+041A  #CYRILLIC CAPITAL LETTER KA
+0xCB    U+041B  #CYRILLIC CAPITAL LETTER EL
+0xCC    U+041C  #CYRILLIC CAPITAL LETTER EM
+0xCD    U+041D  #CYRILLIC CAPITAL LETTER EN
+0xCE    U+041E  #CYRILLIC CAPITAL LETTER O
+0xCF    U+041F  #CYRILLIC CAPITAL LETTER PE
+0xD0    U+0420  #CYRILLIC CAPITAL LETTER ER
+0xD1    U+0421  #CYRILLIC CAPITAL LETTER ES
+0xD2    U+0422  #CYRILLIC CAPITAL LETTER TE
+0xD3    U+0423  #CYRILLIC CAPITAL LETTER U
+0xD4    U+0424  #CYRILLIC CAPITAL LETTER EF
+0xD5    U+0425  #CYRILLIC CAPITAL LETTER HA
+0xD6    U+0426  #CYRILLIC CAPITAL LETTER TSE
+0xD7    U+0427  #CYRILLIC CAPITAL LETTER CHE
+0xD8    U+0428  #CYRILLIC CAPITAL LETTER SHA
+0xD9    U+0429  #CYRILLIC CAPITAL LETTER SHCHA
+0xDA    U+042A  #CYRILLIC CAPITAL LETTER HARD SIGN
+0xDB    U+042B  #CYRILLIC CAPITAL LETTER YERU
+0xDC    U+042C  #CYRILLIC CAPITAL LETTER SOFT SIGN
+0xDD    U+042D  #CYRILLIC CAPITAL LETTER E
+0xDE    U+042E  #CYRILLIC CAPITAL LETTER YU
+0xDF    U+042F  #CYRILLIC CAPITAL LETTER YA
+0xE0    U+0430  #CYRILLIC SMALL LETTER A
+0xE1    U+0431  #CYRILLIC SMALL LETTER BE
+0xE2    U+0432  #CYRILLIC SMALL LETTER VE
+0xE3    U+0433  #CYRILLIC SMALL LETTER GHE
+0xE4    U+0434  #CYRILLIC SMALL LETTER DE
+0xE5    U+0435  #CYRILLIC SMALL LETTER IE
+0xE6    U+0436  #CYRILLIC SMALL LETTER ZHE
+0xE7    U+0437  #CYRILLIC SMALL LETTER ZE
+0xE8    U+0438  #CYRILLIC SMALL LETTER I
+0xE9    U+0439  #CYRILLIC SMALL LETTER SHORT I
+0xEA    U+043A  #CYRILLIC SMALL LETTER KA
+0xEB    U+043B  #CYRILLIC SMALL LETTER EL
+0xEC    U+043C  #CYRILLIC SMALL LETTER EM
+0xED    U+043D  #CYRILLIC SMALL LETTER EN
+0xEE    U+043E  #CYRILLIC SMALL LETTER O
+0xEF    U+043F  #CYRILLIC SMALL LETTER PE
+0xF0    U+0440  #CYRILLIC SMALL LETTER ER
+0xF1    U+0441  #CYRILLIC SMALL LETTER ES
+0xF2    U+0442  #CYRILLIC SMALL LETTER TE
+0xF3    U+0443  #CYRILLIC SMALL LETTER U
+0xF4    U+0444  #CYRILLIC SMALL LETTER EF
+0xF5    U+0445  #CYRILLIC SMALL LETTER HA
+0xF6    U+0446  #CYRILLIC SMALL LETTER TSE
+0xF7    U+0447  #CYRILLIC SMALL LETTER CHE
+0xF8    U+0448  #CYRILLIC SMALL LETTER SHA
+0xF9    U+0449  #CYRILLIC SMALL LETTER SHCHA
+0xFA    U+044A  #CYRILLIC SMALL LETTER HARD SIGN
+0xFB    U+044B  #CYRILLIC SMALL LETTER YERU
+0xFC    U+044C  #CYRILLIC SMALL LETTER SOFT SIGN
+0xFD    U+044D  #CYRILLIC SMALL LETTER E
+0xFE    U+044E  #CYRILLIC SMALL LETTER YU
+0xFF    U+044F  #CYRILLIC SMALL LETTER YA
diff --git a/src/chrtrans/makefile.in b/src/chrtrans/makefile.in
index 246e94ba..e293d1ad 100644
--- a/src/chrtrans/makefile.in
+++ b/src/chrtrans/makefile.in
@@ -48,6 +48,7 @@ TABLES= $(CHRTR)iso02_uni.h \
  $(CHRTR)cp850_uni.h \
  $(CHRTR)cp852_uni.h \
  $(CHRTR)cp1250_uni.h \
+ $(CHRTR)cp1251_uni.h \
  $(CHRTR)cp1252_uni.h \
  $(CHRTR)utf8_uni.h \
  $(CHRTR)rfc_suni.h \
@@ -88,6 +89,7 @@ cp437_uni.h: cp437_uni.tbl makeuctb
 cp850_uni.h: cp850_uni.tbl makeuctb
 cp852_uni.h: cp852_uni.tbl makeuctb
 cp1250_uni.h: cp1250_uni.tbl makeuctb
+cp1251_uni.h: cp1251_uni.tbl makeuctb
 cp1252_uni.h: cp1252_uni.tbl makeuctb
 utf8_uni.h: utf8_uni.tbl makeuctb
 mnemonic_suni.h: mnemonic_suni.tbl makeuctb
diff --git a/src/makefile.in b/src/makefile.in
index 847a724e..f8b4e7af 100644
--- a/src/makefile.in
+++ b/src/makefile.in
@@ -93,6 +93,7 @@ TABLES= $(CHRTR)iso02_uni.h \
  $(CHRTR)cp850_uni.h \
  $(CHRTR)cp852_uni.h \
  $(CHRTR)cp1250_uni.h \
+ $(CHRTR)cp1251_uni.h \
  $(CHRTR)cp1252_uni.h \
  $(CHRTR)utf8_uni.h \
  $(CHRTR)rfc_suni.h \