about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorThomas E. Dickey <dickey@invisible-island.net>1999-06-11 09:49:26 -0400
committerThomas E. Dickey <dickey@invisible-island.net>1999-06-11 09:49:26 -0400
commitc7bfda903760e4bd0d0d8327560f6dee5e1dc059 (patch)
treef197fd66d2ecff0a5f2b1b7ab75badad13bf7e1e
parentfb0d318386632c15db3b295713bd6b26a328e564 (diff)
downloadlynx-snapshots-c7bfda903760e4bd0d0d8327560f6dee5e1dc059.tar.gz
snapshot of project "lynx", label v2-8-3dev_1
-rw-r--r--CHANGES325
-rw-r--r--INSTALLATION9
-rw-r--r--LYHelp.hin3
-rw-r--r--LYMessages_en.h7
-rw-r--r--WWW/Library/Implementation/HTAccess.c101
-rw-r--r--WWW/Library/Implementation/HTAccess.h3
-rw-r--r--WWW/Library/Implementation/HTMIME.c7
-rw-r--r--WWW/Library/Implementation/HTNews.c15
-rw-r--r--WWW/Library/Implementation/HTRules.c260
-rw-r--r--WWW/Library/Implementation/HTRules.h27
-rw-r--r--WWW/Library/Implementation/HTTCP.c146
-rw-r--r--WWW/Library/Implementation/HTTP.c1
-rw-r--r--WWW/Library/Implementation/HTUtils.h11
-rw-r--r--docs/README.defines44
-rw-r--r--lynx.cfg87
-rw-r--r--lynx.hlp39
-rw-r--r--lynx.man87
-rw-r--r--lynx_help/Lynx_users_guide.html222
-rw-r--r--lynx_help/help_files.txt1
-rw-r--r--lynx_help/keystrokes/alt_edit_help.html20
-rw-r--r--lynx_help/keystrokes/bashlike_edit_help.html211
-rw-r--r--lynx_help/keystrokes/edit_help.html17
-rw-r--r--lynx_help/keystrokes/keystroke_help.html10
-rw-r--r--makefile.in14
-rw-r--r--samples/cernrules.txt466
-rw-r--r--samples/lynx-keymaps31
-rw-r--r--src/GridText.c56
-rw-r--r--src/GridText.h2
-rw-r--r--src/HTAlert.c27
-rw-r--r--src/HTAlert.h8
-rw-r--r--src/HTForms.h7
-rw-r--r--src/HTInit.c3
-rw-r--r--src/HTML.c2
-rw-r--r--src/LYCookie.c6
-rw-r--r--src/LYCurses.c29
-rw-r--r--src/LYEditmap.c541
-rw-r--r--src/LYForms.c273
-rw-r--r--src/LYGetFile.c299
-rw-r--r--src/LYGlobalDefs.h21
-rw-r--r--src/LYHistory.c62
-rw-r--r--src/LYHistory.h2
-rw-r--r--src/LYKeymap.c113
-rw-r--r--src/LYKeymap.h50
-rw-r--r--src/LYMail.c133
-rw-r--r--src/LYMain.c189
-rw-r--r--src/LYMainLoop.c689
-rw-r--r--src/LYMainLoop.h4
-rw-r--r--src/LYOptions.c147
-rw-r--r--src/LYOptions.h3
-rw-r--r--src/LYPrint.c1
-rw-r--r--src/LYReadCFG.c96
-rw-r--r--src/LYShowInfo.c7
-rw-r--r--src/LYSignal.h8
-rw-r--r--src/LYStrings.c646
-rw-r--r--src/LYStrings.h84
-rw-r--r--src/LYUtils.c248
-rw-r--r--src/LYUtils.h3
-rw-r--r--src/UCAuto.c59
-rw-r--r--userdefs.h142
59 files changed, 5114 insertions, 1010 deletions
diff --git a/CHANGES b/CHANGES
index c64f985c..9d5516c9 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,6 +1,331 @@
 Changes since Lynx 2.8 release
 ===============================================================================
 
+1999-06-11 (2.8.3dev.1)
+(This is KW's patch, with minor corrections)
+* Key handling changes:
+  - Extended lynxkeycodes:  a bit flag is used to indicate that the lower bits
+    of the value already are a lynxactioncode and need not be looked up again. 
+    Reduces need for back and forth forward and reverse binding lookups;
+    currently only used in some places.
+  - Extended lynxkeycodes:  several (currently three) bit flags are used to
+    indicate key modifiers.
+  - Added some macros for manipulating and mapping of these codes, see
+    especially LYKeymap.h, LKC_TO_LAC() etc.  Added some comments about the
+    various kinds of codes.
+  - Added several editaction codes and flags for setting key modifier on next
+    key (i.e.  for declaring keys as prefix keys, for the purposes of line
+    editing); for flagging a key for different action if same key is repeated;
+    for exiting input field line editing and passing a specific lynxactioncode
+    on; and for undoing 8-bit C1 -> 7-bit replacement transformation for some
+    chars.  Added code to line-editor implementation to react to these new
+    editactions.  Note that the mapping of lynxkeycode to lynxactioncode
+    outside of line editing, i.e.  KEYMAP in lynx.cfg etc., ignores the
+    modifiers.  The main loop just drops modifier flags or ignores the modified
+    key; modifier flags cannot be used in lynx.cfg KEYMAP 'keystroke' values.
+  - An ESC not recognized as part of an escape sequence can set the appropriate
+    modifier flag in LYgetch(), except for SLANG which normally uses a
+    different LYgetch() implementation.  Interpreting an ESC prefix as modifier
+    is very useful for situations where a held-down Alt key (or some other key)
+    is encoded this way:  linux console, kermit with emacs key mappings,
+    possibly xterm with '*eightBitInput:  false'.  OTOH it doesn't work for all
+    characters or in all situations.
+  - Extended syntax recognized in .lynx-keymaps file (which is only used if
+    compiling with USE_KEYMAPS defined, which in turn depends on slang and
+    ncurses version):
+    (a) Meta-foo can be used to map an escape sequence to a key + modifier.
+    (b) LAC:foo can be used to map an escape sequence directly to a
+        lynxactioncode (actually, to an extended lynxkeycode that
+        encapsulates a lynxactioncode).
+    See examples added to samples/lynx-keymaps.
+  - Extended syntax of KEYMAP option, additional field can override line-editor
+    behavior.  PASS documented in lynx.cfg.
+  - Extended syntax that can be used for specifying key in KEYMAP, some of the
+    forms allowed in .lynx-keymaps file are now additionally recognized, but
+    only if compiling with USE_KEYMAPS defined.  Left undocumented in lynx.cfg
+    (maybe subject to change).
+  - New "Bash-like" Line Editor binding.  Adds several new emacs-like editing
+    functions.  Adds tables for keys with modifiers (actually the same table is
+    currently used for all modifiers, to save some space).  Most notably, ^X is
+    a prefix key to set a modifier flag.  Keys with second function when
+    pressed twice are ^E^E and ^K^K.  ESC is also recognized as setting a
+    modifier flag, in case it gets through without been having been handled in
+    LYgetch().  See new file keystrokes/bashlike_edit_help.html for more info. 
+    The Bash-like Line Editor Bindings are only compiled in if compiled with
+    -DEXP_ALT_BINDINGS / configured with --enable-alt-bindings (but not subject
+    to a new macro).  Implementation code for the new emacs-like functions
+    additionally ifdef'd with ENHANCED_LINEEDIT. 
+  - Avoid dependency on DNARROW key binding when form field line-editing is
+    ended with Enter or Return key.
+  - Take setting of real_c/old_c into consideration after return from form
+    field line-editing.  Previously there were some strange effects: 
+    statusline messages would sometimes not appear when they should, the KEYMAP
+    command would sometimes not work when invoked with ^Vk while in a form
+    field.
+  - Make NOCACHE ('x') work for TEXT_SUBMIT_TYPE form fields (i.e.  forms with
+    a single text input field where Enter automatically submits).  Of course
+    'x' has to be typed as ^Vx while line-editing the field (or NOCACHE mapped
+    to a different key).  Similarly allow DOWNLOAD, and HEAD to work for such
+    fields.  Try to ensure that all permission checks that apply to other form
+    submissions are also done for TEXT_SUBMIT_TYPE fields, this wasn't the case
+    before.
+  - New key actions LPOS_PREV_LINK and LPOS_NEXT_LINK.  They are like PREV_LINK
+    and NEXT_LINK, with the difference that, when moving to a form input or
+    textarea line, the last column position (relative to the field) is
+    remembered.  They are not mapped by default, but mentioned in lynx.cfg.
+  - New key action DWIMHELP.  It should give some context-sensitive help. 
+    Currentely the appropriate Line Editor Binding help page is shown if a form
+    input field is selected, otherwise it defaults to the main HELP page.
+  - New key action DWIMEDIT.  Revert meaning of EDIT back to previous meaning: 
+    always edit document file, not textarea content.  DWIMEDIT acts like
+    EDITTEXTAREA if the current link is a form textarea or input field and
+    AUTOEXTEDIT was defined, and like EDIT otherwise.  Also added slightly
+    different statusline message if form field external editiong cannot be done
+    because editing is disabled:  it shouldn't refer to "The 'e'dit command".
+  - Summary of reasonable ways to invoke external texarea editing (assuming
+    that it is desired to keep the action of 'e' to edit files at least outside
+    of input fields):
+    1) KEYMAP 'e' to DWIMEDIT, invoke ^Ve.  (if AUTOEXTEDIT is defined,
+       which is the case by default.)
+    1a) KEYMAP <some other key> to DWIMEDIT, invoke ^V<some other key>.
+    1b) KEYMAP <some other key> to EDITTEXTAREA, invoke ^V<some other key>.
+    2) KEYMAP a key (function or control, not printable!) to EDITTEXTAREA
+       or DWIMEDIT, using PASS in the KEYMAP line.
+    2a) Find some key whose LineEdit binding is already LYE_FORM_PASS, and
+        KEYMAP it to EDITTEXTAREA or DWIMEDIT.
+    3) compile with EXP_ALT_BINDINGS defined (--enable-alt-bindings),
+       select Bash-like Bindings,
+       invoke ^E^E or ^X^E (or ESC ^E aka M-C-e), or
+       invoke ^Xe (or ESC e aka M-e), or
+    3a) compile with EXP_ALT_BINDINGS defined (--enable-alt-bindings),
+        and without selecting Bash-like Bindings
+        (invoke ESC ^E aka M-C-e or ESC e aka M-e).
+    Bindings in parentheses under 3/3a may not work with slang unless a
+    tweaked .lynx-keymaps file is used.
+* Other changes related to textarea handling:
+  - More appropriate message statusline message if GROWTEXTAREA or INSERTFILE
+    cannot be done because a textarea is not selected:  it shouldn't refer to
+    "external editor".
+  - Check whether an editor is defined before trying to use it for textarea
+    editing.  Generate message if spawning of external textarea editor failed.
+  - Allow INSERTFILE only if file access is not restricted.
+  - Enforce dotfiles restriction and "show dot files" setting for INSERTFILE.
+* Mouse handling changes, mostly only if mouse support comes via ncurses:
+  - Re-enabled changing link by clicking in area *near* a link (but not on the
+    link text), but limit max.  distance to 2 character positions.
+  - Make mouse popup menu disappear when it should, by applying the right magic
+    touchline() in popup_choice().
+  - Lots of small tweaks to remove glitches in mouse handling, among them:  No
+    left scrolling of long input fields on entering with mouse.  Try to ensure
+    statusline is updated after mouse menu.  Make menu actions work as
+    expected.  Avoid acting on mouse events, especially invoking mouse menu, in
+    wrong context (e.g.  while at a prompt), at least in many places.
+  - Clicking on left or right border of mouse menu now only moves selection.
+  - At right end of top/bottom line, where single click causes HISTORY action,
+    double click now causes VLINKS action.
+  - Allow to distinguish between submitting and just positioning into a
+    TEXT_SUBMIT_TYPE input field.  Single click positions, double click
+    submits, 'activate' from menu also submits.
+  - When initializing ncurses mouse, call mousemask() with only those bits set
+    that we may actually be interested in.
+* Changes relevant for handling window size changes:
+  - For ncurses, changed the way how mainloop() notifies the curses library
+    about a window size change.  The approach taken previously, and still used
+    if we are not using ncurses, has more overhead, can unnecessarily switch
+    out of the alternative screen buffer (and back) under xterm, and didn't
+    really make ncurses update the WINDOW structures for the new size in time.
+  - Other tweaks for size change:  make sure curdoc.link is valid after
+    refresh.
+  - Detection of size changes in more situations:  tolerate EOF from GetChar in
+    the (non-SLANG) LYgetch_for() in more cases if errno is EINTR, if this
+    happens check for a size change and generate trace output.  Recognize
+    KEY_RESIZE from ncurses, check for a size change and generate trace output
+    when it occurs.
+  - Added NONRESTARTING_SIGWINCH lynx.cfg option and -nonrestarting_sigwinch
+    flag.  If set, lynx *may* react more immediately to window size changes
+    when running under xterm or similar.  Whether this actually has an effect
+    depends on the implementation of sigaction() and on the behavior of the
+    curses (or similar) library when a read() (or other system call) is
+    interrupted by signals.
+    Depends on '#if HAVE_SIGACTION', which currently has to be defined by hand,
+    for example by 'make SITE_DEFS="-DHAVE_SIGACTION"'.  The command line flag
+    is only available on systems with HAVE_SIGACTION and SIGWINCH.
+  - Tweaks so that lynx in an xterm can survive when the window size is made
+    (probably temporarily) very small, for example 1x1.  Avoid display_page's
+    work if it wouldn't be displayable anyway.  Make display_title handle very
+    small screen widths, at least to the degree that it doesn't crash.
+* Except for VMS or when DOSPATH is defined, set restore_sigpipe_for_children.
+  Fixes Debian bug #33853, maybe not really a bug but let's be nice.
+* Changes in HTTCP.c:
+  - Added a CTRACE_FLUSH before creation of NSL_FORK child process.
+  - Block certain signals during creation of NSL_FORK child process, if
+    sigprocmask() and friends are available.  This should prevent a rare
+    problem where sometimes the child process could be killed before it has a
+    chance to modify its signal handlers, resulting in screen corruption, a
+    seemingly hanging lynx, and/or other problems.  It is assumed that
+    sigprocmask() etc.  are available if HAVE_SIGACTION is true.  It currently
+    has to be defined by hand, for example by 'make
+    SITE_LYDEFS="-DHAVE_SIGACTION"'.
+  - Generate diagnostic messages for some failures of forked lookup.  Depends
+    on HAVE_H_ERRNO.  In particular, try to detect whether the child process
+    failed because of memory problems, and also fake a 'z' in that case to
+    short-circuit a URL guessing cycle.
+  - For most systems, generate more trace output for connection attempts, close
+    to the actual connect() and select() calls to prevent clobbering errno. 
+    See SOCKET_DEBUG_TRACE.  This should help diagnose some obscure
+    system-dependent problems that have occasionally been reported.
+* Added some missing stuff for color handling to forms Option Menu code.
+* Printing to screen sometimes didn't show anything for short texts, if screen
+  output was buffered (and ncurses makes stdout buffered).  Added another
+  fflush(stdout) in send_file_to_screen().
+* Some checks for specific URLs (helpfilepath, lynxlistfile, and lynxjumpfile)
+  in LYGetFile.c were inappropriately case-insensitive for Unix.  The
+  comparison is now case-sensitive except for VMS.  This may need tweaking for
+  DOS and similar systems.
+* Added additional LYNoRefererForThis check in getfile(), the one in mainloop()
+  could be missed for TEXT_SUBMIT_TYPE form fields.  Also moved other check for
+  whether to send Referer header earlier, and made it apply for URL types that
+  might be proxied.
+* LYAddVisitedLink tried to regard documents with the same address but a
+  different title string as different documents, but this was coded wrong. 
+  Removed ineffective comparison, but keep old title string if new title string
+  is empty.
+* Correct long-standing logic error in MAIL_SYSTEM_ERROR_LOGGING handling.
+  Apparently not many people are using it...
+* Fix for traversal code to put the right address into the TRAVERSE_REJECT_FILE
+  if a request fails after popping a document from the history stack (this can
+  only occur if a previous request for the same document had succeeded).  Also
+  don't try to send mail in such a case if MAIL_SYSTEM_ERROR_LOGGING is on. 
+  Also prevent possible history stack underflow if this occurs on return to the
+  first document.
+* According to lynx.cfg, error logging mail may be sent to ALERTMAIL if no
+  document owner is known, but this was not implemented; now it is.  ALERTMAIL
+  is used if it is defined non-empty in userdefs.h.  Of course normally it
+  should be left undefined.
+* Fix for traversal code to reject form fields a bit earlier.  This prevents
+  unnecessary lookups as well as adding of an empty line to the
+  TRAVERSE_REJECT_FILE for each form field encountered.
+* Format -crawl output as was documented in CRAWL.announce:  with this switch,
+  link numbering is always off by default (userdefs.h and lynx.cfg defaults und
+  saved user preference are ignored) unless -number_links is given, and -crawl
+  -traversal format is now consistent with -crawl -dump with respect to link
+  numbering.  As a side effect, -crawl without either -traversal or -dump now
+  also turns link numbering off unless -number_links is used (the meaning of
+  -crawl without either of these was undocumented), so it then acts effectively
+  as a (less powerful) negation of the -number_links switch.
+* For -crawl -dump, the list of links was appended twice.  Fixed.
+* Check URL as well as title before deciding that a document should not be
+  pushed on the history stack because it looks like a generated special page.
+* Made "Don't waste the cache" optimization in historytarget() subject to
+  additional checks, to avoid uncaching of the wrong document in some cases.
+* LYSafeGets() would drop the last line from a file if it was not terminated. 
+  Changed to return the unterminated line like fgets().
+* Clarifications on restrictions.  "download" does not imply "disk_save" while
+  "print" does, this doesn't seem to make much sense but has been the behavior
+  for a long time.
+* Restrictions inside_news, outside_news now apply to reading as well as
+  posting.  The documentation (except for the corresponding comments in
+  userdefs.h) said that they apply to posting, while in fact they were
+  implemented for reading only.  [Does nobody read this stuff???] Also, the
+  implementation only checked the flag for news:  URLs, but not for nntp: 
+  URLs, which doesn't make much sense given that the latter provide an
+  alternative way for most (if not all) purposes of the first.  So now these
+  restrictions apply to news:, nntp:, newspost:, and newsreply:  (but not to
+  snews:, snewspost:, or snewsreply:).
+* Document -restrictions=externals.
+* Some of the restriction stuff not added to VMS lynx.hlp file, since I'm not
+  quite sure whether the corresponding features work there at all.
+* Changed restriction parsing so that "all" and "default" don't get ignored if
+  they appear as one of several items in the same list.
+* Implement listing of current restrictions to stdout with new -restrictions=? 
+  option.  This should appear as the last command line option, otherwise the
+  effect of options appearing later may not be shown.  The '?' may require
+  quoting.
+* Made -restrictions= (without any option flags) act like -restrictions
+  (without equal sign either) as implied by documentation, i.e.  list
+  recognized restriction options.
+* LYRestricted has been greatly abused.  Once upon a time it was a PRIVATE flag
+  in LYMain.c (then called anon_restrictions_set), used only to get the
+  precedence of various command line options right.  Recently it has been
+  misused as a check (and as the only one) whether "anonymous restrictions" are
+  in effect.  This undermines various assumptions:
+  - that -anonymous is basically an aggregate set of restrictions which could
+    be specified individually with -restrictions=.
+  - that individually listed restrictions (-restrictions=...) act as expected,
+    and can be used to restrict various aspects in a useful manner.
+  - that -validate implies the strongest restrictions, except for what is
+    explicitly exempted (i.e. 'g'oto for http/https URLs).
+  Use specific restrictions instead:
+  - new "compileopts_info" for LYNXCOMPILEOPTS:  - for anonymous default see
+    userdefs.h
+  - new "lynxcfg_info" for LYNXCFG: - for anonymous default see userdefs.h
+  - new "lynxcfg_xinfo" for extended LYNXCFG: - for anonymous default see
+    userdefs.h
+  - new invisible "goto_configinfo" for LYNXCOMPILEOPTS: & LYNXCFG: for
+    anonymous default, see userdefs.h
+  - additionally check existing "option_save" for LYNXCFG://reload/ -
+    always restricted by anonymous default
+  ("invisible" means that this restriction cannot be explicitly listed in a
+  -restrictions=...  list, but has a value derived from userdefs.h that is used
+  with -anonymous and -restrictions=default.)
+* Forms options menu can now be used with -validate.
+* Allow following local help file links, even if "file_url" restriction is set,
+  from LYNXKEYMAP, LYNXCOOKIES.  (Possibly more need to be added.)
+* Apparently realm checking (with -realm option) is bypassed for URLs from
+  (some) form submissions (it seems to be intentional, but why?).  Made sure
+  this at least doesn't weaken -validate restrictions.
+* Apply -localhost check in getfile for news URLs that include a hostname,
+  i.e., that begin with with "news://".
+* Add '&' to nonalphanumeric characters forbidden by exec_ok() for lynxexec and
+  lynxprog URLs, but keep allowing it for lynxcgi.  There's not much point in
+  excluding ';' and so on if '&' is acceptable!
+* Tweaked LYNXMESSAGES:  handling slightly:  don't bypass normal getfile
+  handling.
+* Reset LYforce_no_cache flag in mainloop() after failed access, before popping
+  the previous (or, actually, probably currently still displayed) document.
+* Tweak for 'no data' handling:  it isn't always an error, but was sometimes
+  treated as such.  It mostly doesn't make a difference, except for the message
+  printed when the startfile cannot be accessed and for traversal and mail
+  error logging.  This needs to be revised to apply for all protocols.
+* Added new functionality for rules:  Redirect, UseProxy, various others.  See
+  cernrules.txt in samples directory for details.
+* Prevent crashes in HTNews.c with HEAD.
+* Allow HEAD requests for proxied URLs (checking whether any applicable proxy
+  begins with http:  or lynxcgi:), as far as this can be determined based on
+  regular environment settings (i.e.  unaware of proxying by rules).
+* Modified add_item_to_list() so that if the restriction flag is omitted from a
+  DOWNLOADER/UPLOADER/EXTERNAL line in lynx.cfg, it is assumed FALSE.  This
+  modifies the change of 1998-10-17 to be on the safer side, it is more
+  consistent with how PRINTER lines or lines with the colon separator present
+  but the flag value absent are handled, and it only makes a difference when a
+  -restriction command line option or its equivalent is in effect anyway.
+* Deal with unusual cases where telnet and similar protocols are proxied, or
+  possibly changed to a different type of protocol by rules.  Normally such
+  protocols should never be proxied, but there was no protection against it,
+  and lynx could crash.  The approach now taken does not disallow it, but just
+  tries to deal with the situation in a way that avoids crashing; it is
+  conceivable that one may want to direct e.g.  telnet or rlogin URLs to a HTTP
+  page that explains why theses types are not supported.  A similar problem
+  that occurred when e.g.  telnet was forbidden by a rule is also dealt with.
+* Protect start_curses calls in getfile against being executed if
+  dump_output_immediately is in effect.  Maybe access to telnet, rlogin,
+  lynxexec URLs should be completely disabled for this case; skipping the
+  start_curses at least avoids being left with non-restored tty settings after
+  the program exits, is someone attempts to use -dump or -source with such a
+  URL (the -dump or -source flags is then effectively more or less ignored).
+* Tweaks in fix_http_urls, renamed fix_httplike_urls.
+* Moved LYStrerror from LYStrings.{h,c} to HTAlert.{h,c}, so that it can be
+  used in HT*.c files without pulling in yet more LY*.h headers.
+* Reset 'safe' flag in anchor on parsing "Safe: no" and "Safe: false" headers.
+* The top makefile.in had some 'rm -rf' for whole directories $(helpdir) and
+  $(docdir) in install targets that could potentially wipe out unrelated files;
+  added checks to make sure the directories haven't been changed to something
+  not lynx-specific (they are regarded as lynx-specific if the last component
+  is lynx_help and lynx_doc, respectively).
+* Various doc tweaks.
+* Updated README.defines.  Other contributors should please add their stuff
+  there, too.
+
 1999-06-01 (2.8.2rel.1)
 -----------------------
 1999-06-01 (2.8.2pre.11)
diff --git a/INSTALLATION b/INSTALLATION
index 076ae539..d81a8fa3 100644
--- a/INSTALLATION
+++ b/INSTALLATION
@@ -166,9 +166,10 @@ II. Compile instructions -- UNIX
 	to the default bindings.
 
   --disable-config-info			(define NO_CONFIG_INFO)
-  	Use this option to disable the browsable configuration information
-	(screens that show the result of the configuration script, as well
-	as a pointer to the lynx.cfg file).
+  	Use this option to disable extended browsable configuration information
+	(a screen that shows the result of the configuration script, as well
+	as extended lynx.cfg viewing with a pointer to the lynx.cfg file and
+	additional functionality).
 
   --disable-dired			(define DIRED_SUPPORT)
 	Use this option to disable the optional directory-editor.
@@ -234,7 +235,7 @@ II. Compile instructions -- UNIX
 	Do not compile-in code used to connect to "finger" URLs.
 
   --disable-ftp				(define DISABLE_FTP)
-	Do not compile-in code used to connect to "ftp" URLs.
+	Do not compile-in code used to connect to FTP servers.
 
   --disable-forms-options		(define NO_OPTION_FORMS)
 	Disable the forms-based options screen.  (See --disable-menu-options).
diff --git a/LYHelp.hin b/LYHelp.hin
index fabab118..4c583014 100644
--- a/LYHelp.hin
+++ b/LYHelp.hin
@@ -3,9 +3,12 @@
 #ifndef LYHELP_H
 #define LYHELP_H
 
+#define ALT_EDIT_HELP		"keystrokes/@ALT_EDIT_HELP@"
+#define BASHLIKE_EDIT_HELP	"keystrokes/@BASHLIKE_EDIT_HELP@"
 #define COOKIE_JAR_HELP		"@LYNX_USERS_GUIDE@#Cookies"
 #define CURRENT_KEYMAP_HELP	"keystrokes/@KEYSTROKE_HELP@"
 #define DIRED_MENU_HELP		"keystrokes/@DIRED_HELP@"
+#define EDIT_HELP		"keystrokes/@EDIT_HELP@"
 #define DOWNLOAD_OPTIONS_HELP	"@LYNX_USERS_GUIDE@#RemoteSource"
 #define HISTORY_PAGE_HELP	"keystrokes/@HISTORY_HELP@"
 #define LIST_PAGE_HELP		"keystrokes/@FOLLOW_HELP@"
diff --git a/LYMessages_en.h b/LYMessages_en.h
index b2910b24..d357d5d8 100644
--- a/LYMessages_en.h
+++ b/LYMessages_en.h
@@ -60,7 +60,7 @@
 #define FORM_LINK_TEXT_UNM_MSG \
  gettext("UNMODIFIABLE form text field.  Use UP or DOWN arrows or tab to move off.")
 #define FORM_LINK_TEXT_SUBMIT_MESSAGE \
- gettext("(Form field) Enter text.  Use <return> to submit ('x' for no cache).")
+ gettext("(Form field) Enter text.  Use <return> to submit (^Vx for no cache).")
 #define FORM_LINK_TEXT_RESUBMIT_MESSAGE \
  gettext("(Form field) Enter text.  Use <return> to submit, arrows or tab to move off.")
 #define FORM_LINK_TEXT_SUBMIT_UNM_MSG \
@@ -173,12 +173,14 @@
 #define SENDING_COMMENT gettext("Sending your comment:")
 
 /* textarea */
-#define NOT_IN_TEXTAREA gettext("Not in a TEXTAREA; cannot use external editor.")
+#define NOT_IN_TEXTAREA_NOEDIT gettext("Not in a TEXTAREA; cannot use external editor.")
+#define NOT_IN_TEXTAREA gettext("Not in a TEXTAREA; cannot use command.")
 
 
 #define FILE_ACTIONS_DISALLOWED gettext("file: ACTIONs are disallowed!")
 #define FILE_SERVED_LINKS_DISALLOWED \
  gettext("file: URLs via served links are disallowed!")
+#define NOAUTH_TO_ACCESS_FILES gettext("Access to local files denied.")
 #define FILE_BOOKMARKS_DISALLOWED gettext("file: URLs via bookmarks are disallowed!")
 #define SPECIAL_VIA_EXTERNAL_DISALLOWED \
  gettext("This special URL is not allowed in external documents!")
@@ -374,6 +376,7 @@
 #define CONFIRM_COMMENT gettext("Do you wish to send a comment?")
 #define MAIL_DISALLOWED gettext("Mail is disallowed so you cannot send a comment")
 #define EDIT_DISABLED gettext("The 'e'dit command is currently disabled.")
+#define ANYEDIT_DISABLED gettext("External editing is currently disabled.")
 #define NO_STATUS gettext("System error - failure to get status.")
 #define NO_EDITOR gettext("No editor is defined!")
 #define PRINT_DISABLED gettext("The 'p'rint command is currently disabled.")
diff --git a/WWW/Library/Implementation/HTAccess.c b/WWW/Library/Implementation/HTAccess.c
index 008d42b7..11dfc5ae 100644
--- a/WWW/Library/Implementation/HTAccess.c
+++ b/WWW/Library/Implementation/HTAccess.c
@@ -72,6 +72,7 @@ extern HTCJKlang HTCJK;
 PUBLIC char * HTClientHost = NULL; /* Name of remote login host if any */
 PUBLIC FILE * HTlogfile = NULL;    /* File to which to output one-liners */
 PUBLIC BOOL HTSecure = NO;	   /* Disable access for telnet users? */
+PUBLIC BOOL HTPermitRedir = NO;	   /* Always allow redirection in getfile()? */
 
 PUBLIC BOOL using_proxy = NO; /* are we using a proxy gateway? */
 
@@ -315,6 +316,9 @@ PUBLIC BOOL override_proxy ARGS1(
 #ifndef DISABLE_FINGER
 	    else if (!strcmp(acc_method, "finger"))	port = 79;
 #endif
+	    else if (!strcmp(acc_method, "telnet"))	port = 23;
+	    else if (!strcmp(acc_method, "tn3270"))	port = 23;
+	    else if (!strcmp(acc_method, "rlogin"))	port = 513;
 	    FREE(acc_method);
 	}
     }
@@ -379,17 +383,34 @@ PRIVATE int get_physical ARGS2(
     char * acc_method = NULL;	/* Name of access method */
     char * physical = NULL;
     char * Server_addr = NULL;
+    BOOL override_flag = NO;
+
+    /*
+    **	Make sure the using_proxy variable is FALSE.
+    */
+    using_proxy = NO;
 
 #ifndef NO_RULES
     physical = HTTranslate(addr);
     if (!physical) {
+	if (redirecting_url) {
+	    return HT_REDIRECTING;
+	}
 	return HT_FORBIDDEN;
     }
     if (anchor->isISMAPScript == TRUE) {
 	StrAllocCat(physical, "?0,0");
 	CTRACE(tfp, "HTAccess: Appending '?0,0' coordinate pair.\n");
     }
-    HTAnchor_setPhysical(anchor, physical);
+    if (!strncmp(physical, "Proxied=", 8)) {
+	HTAnchor_setPhysical(anchor, physical + 8);
+	using_proxy = YES;
+    } else if (!strncmp(physical, "NoProxy=", 8)) {
+	HTAnchor_setPhysical(anchor, physical + 8);
+	override_flag = YES;
+    } else {
+	HTAnchor_setPhysical(anchor, physical);
+    }
     FREE(physical);			/* free our copy */
 #else
     if (anchor->isISMAPScript == TRUE) {
@@ -410,53 +431,56 @@ PRIVATE int get_physical ARGS2(
     **	Check whether gateway access has been set up for this.
     **
     **	This function can be replaced by the rule system above.
+    **
+    **  If the rule system has already determined that we should
+    **  use a proxy, or that we shouldn't, ignore proxy-related
+    **  settings, don't use no_proxy either.
     */
 #define USE_GATEWAYS
 #ifdef USE_GATEWAYS
-    /*
-    **	Make sure the using_proxy variable is FALSE.
-    */
-    using_proxy = NO;
 
-    if (!strcasecomp(acc_method, "news")) {
-	/*
-	**  News is different, so we need to check the name of the server,
-	**  as well as the default port for selective exclusions.
-	*/
-	char *host = NULL;
-	if ((host = HTParse(addr, "", PARSE_HOST))) {
-	    if (strchr(host, ':') == NULL) {
+    if (!override_flag && !using_proxy) {   /* else ignore no_proxy env var */
+	if (!strcasecomp(acc_method, "news")) {
+	    /*
+	    **  News is different, so we need to check the name of the server,
+	    **  as well as the default port for selective exclusions.
+	    */
+	    char *host = NULL;
+	    if ((host = HTParse(addr, "", PARSE_HOST))) {
+		if (strchr(host, ':') == NULL) {
+		    StrAllocCopy(Server_addr, "news://");
+		    StrAllocCat(Server_addr, host);
+		    StrAllocCat(Server_addr, ":119/");
+		}
+		FREE(host);
+	    } else if (getenv("NNTPSERVER") != NULL) {
 		StrAllocCopy(Server_addr, "news://");
-		StrAllocCat(Server_addr, host);
+		StrAllocCat(Server_addr, (char *)getenv("NNTPSERVER"));
 		StrAllocCat(Server_addr, ":119/");
 	    }
-	    FREE(host);
-	} else if (getenv("NNTPSERVER") != NULL) {
-	    StrAllocCopy(Server_addr, "news://");
-	    StrAllocCat(Server_addr, (char *)getenv("NNTPSERVER"));
-	    StrAllocCat(Server_addr, ":119/");
-	 }
-    } else if (!strcasecomp(acc_method, "wais")) {
-	/*
+	} else if (!strcasecomp(acc_method, "wais")) {
+	    /*
 	**  Wais also needs checking of the default port
 	**  for selective exclusions.
 	*/
-	char *host = NULL;
-	if ((host = HTParse(addr, "", PARSE_HOST))) {
-	    if (!(strchr(host, ':'))) {
-		StrAllocCopy(Server_addr, "wais://");
-		StrAllocCat(Server_addr, host);
-		StrAllocCat(Server_addr, ":210/");
+	    char *host = NULL;
+	    if ((host = HTParse(addr, "", PARSE_HOST))) {
+		if (!(strchr(host, ':'))) {
+		    StrAllocCopy(Server_addr, "wais://");
+		    StrAllocCat(Server_addr, host);
+		    StrAllocCat(Server_addr, ":210/");
+		}
+		FREE(host);
 	    }
-	    FREE(host);
-	}
-	else
+	    else
+		StrAllocCopy(Server_addr, addr);
+	} else {
 	    StrAllocCopy(Server_addr, addr);
-    } else {
-	StrAllocCopy(Server_addr, addr);
+	}
+	override_flag = override_proxy(Server_addr);
     }
 
-    if (!override_proxy(Server_addr)) {
+    if (!override_flag && !using_proxy) {
 	char * gateway_parameter, *gateway, *proxy;
 
 	/*
@@ -641,11 +665,17 @@ PRIVATE int HTLoad ARGS4(
     HTProtocol *p;
     int status = get_physical(addr, anchor);
     if (status == HT_FORBIDDEN) {
+	 /* prevent crash if telnet or similar was forbidden by rule. - kw */
+	LYFixCursesOn("show alert:");
 	return HTLoadError(sink, 500, gettext("Access forbidden by rule"));
+    } else if (status == HT_REDIRECTING) {
+	return status;	/* fake redirection by rule, to redirecting_url */
     }
     if (status < 0)
 	return status;	/* Can't resolve or forbidden */
 
+    /* prevent crash if telnet or similar mapped or proxied by rule. - kw */
+    LYFixCursesOnForAccess(addr, HTAnchor_physical(anchor));
     p = (HTProtocol *)HTAnchor_protocol(anchor);
     anchor->underway = TRUE;		/* Hack to deal with caching */
     status= (*(p->load))(HTAnchor_physical(anchor),
@@ -668,6 +698,8 @@ PUBLIC HTStream *HTSaveStream ARGS1(
     return (*p->saveStream)(anchor);
 }
 
+PUBLIC int redirection_attempts = 0; /* counter in HTLoadDocument */
+
 /*	Load a document - with logging etc		HTLoadDocument()
 **	----------------------------------
 **
@@ -697,7 +729,6 @@ PRIVATE BOOL HTLoadDocument ARGS4(
     CONST char * address_to_load = full_address;
     char *cp;
     BOOL ForcingNoCache = LYforce_no_cache;
-    static int redirection_attempts = 0;
 
     CTRACE (tfp, "HTAccess: loading document %s\n", address_to_load);
 
diff --git a/WWW/Library/Implementation/HTAccess.h b/WWW/Library/Implementation/HTAccess.h
index 2cfd49d5..0c763051 100644
--- a/WWW/Library/Implementation/HTAccess.h
+++ b/WWW/Library/Implementation/HTAccess.h
@@ -13,6 +13,8 @@
 
 extern char * use_this_url_instead;
 
+extern int redirection_attempts;
+
 /*      Definition uses:
 */
 #include <HTAnchor.h>
@@ -76,6 +78,7 @@ extern int HTDiag;                      /* Flag: load source as plain text */
 extern char * HTClientHost;             /* Name or number of telnetting host */
 extern FILE * HTlogfile;                /* File to output one-liners to */
 extern BOOL HTSecure;                   /* Disable security holes? */
+extern BOOL HTPermitRedir;              /* Special flag for getfile() */
 extern HTStream* HTOutputStream;        /* For non-interactive, set this */
 extern HTFormat HTOutputFormat;         /* To convert on load, set this */
 
diff --git a/WWW/Library/Implementation/HTMIME.c b/WWW/Library/Implementation/HTMIME.c
index 65bab4f9..24b42194 100644
--- a/WWW/Library/Implementation/HTMIME.c
+++ b/WWW/Library/Implementation/HTMIME.c
@@ -1558,6 +1558,13 @@ PRIVATE void HTMIME_put_character ARGS2(
 		if (!strcasecomp(me->value, "YES") ||
 		    !strcasecomp(me->value, "TRUE")) {
 		    me->anchor->safe = TRUE;
+		} else if (!strcasecomp(me->value, "NO") ||
+		    !strcasecomp(me->value, "FALSE")) {
+		    /*
+		    **  If server explicitly tells us that it has changed
+		    **  its mind, reset flag in anchor. - kw
+		    */
+		    me->anchor->safe = FALSE;
 		}
 		break;
 	    case miSERVER:
diff --git a/WWW/Library/Implementation/HTNews.c b/WWW/Library/Implementation/HTNews.c
index 5b16ee3c..32f4e3a6 100644
--- a/WWW/Library/Implementation/HTNews.c
+++ b/WWW/Library/Implementation/HTNews.c
@@ -771,8 +771,12 @@ PRIVATE void abort_socket NOARGS
 {
     CTRACE(tfp, "HTNews: EOF on read, closing socket %d\n", s);
     NEWS_NETCLOSE(s);	/* End of file, close socket */
-    PUTS("Network Error: connection lost");
-    PUTC('\n');
+    if (rawtext) {
+	RAW_PUTS("Network Error: connection lost\n");
+    } else {
+	PUTS("Network Error: connection lost");
+	PUTC('\n');
+    }
     s = -1;		/* End of file on response */
 }
 
@@ -1299,7 +1303,7 @@ PRIVATE int read_article ARGS1(
 
     if (rawtext) {
 	/*
-	 *  No tags - kw
+	 *  No tags, and never do a PUTC. - kw
 	 */
 	;
     } else if (diagnostic) {
@@ -1308,14 +1312,15 @@ PRIVATE int read_article ARGS1(
 	**  as XMP formatted text. - FM
 	*/
 	START(HTML_XMP);
+	PUTC('\n');
     } else {
 	/*
 	**  Read in the BODY of the Article
 	**  as PRE formatted text. - FM
 	*/
 	START(HTML_PRE);
+	PUTC('\n');
     }
-    PUTC('\n');
 
     p = line;
     while (!done) {
@@ -2783,7 +2788,7 @@ Send_NNTP_command:
 
 /*
 **  This function clears all authorization information by
-**  invoking the free_HTAAGlobals() function, which normally
+**  invoking the free_NNTP_AuthInfo() function, which normally
 **  is invoked at exit.  It allows a browser command to do
 **  this at any time, for example, if the user is leaving
 **  the terminal for a period of time, but does not want
diff --git a/WWW/Library/Implementation/HTRules.c b/WWW/Library/Implementation/HTRules.c
index 97df34e6..6140765e 100644
--- a/WWW/Library/Implementation/HTRules.c
+++ b/WWW/Library/Implementation/HTRules.c
@@ -15,6 +15,7 @@
 **			Bug Fix: in case of PASS, only one parameter to printf.
 **	19 Sep 93  AL	Added Access Authorization stuff.
 **	 1 Nov 93  AL	Added htbin.
+**	25 May 99  KW	Added redirect for lynx.
 **
 */
 
@@ -35,10 +36,17 @@ typedef struct _rule {
 	HTRuleOp	op;
 	char *		pattern;
 	char *		equiv;
+	char *		condition_op; /* as strings - may be inefficient, */
+	char *		condition;    /* but this is not for a server - kw */
 } rule;
 
 #ifndef NO_RULES
 
+#include <HTTP.h> /* for redirecting_url, indirectly HTPermitRedir - kw */
+#include <LYGlobalDefs.h> /* for LYUserSpecifiedURL - kw */
+#include <LYUtils.h>		/* for LYFixCursesOn - kw */
+#include <HTAlert.h>
+
 /*	Global variables
 **	----------------
 */
@@ -68,15 +76,17 @@ PRIVATE rule * rule_tail = 0;	/* Pointer to last on list */
 **	returns 	0 if success, -1 if error.
 */
 
-PUBLIC int HTAddRule ARGS3(
+PUBLIC int HTAddRule ARGS5(
     HTRuleOp,		op,
     CONST char *,	pattern,
-    CONST char *,	equiv)
+    CONST char *,	equiv,
+    CONST char *,	cond_op,
+    CONST char *,	cond)
 { /* BYTE_ADDRESSING removed and memory check - AS - 1 Sep 93 */
     rule *	temp;
     char *	pPattern;
 
-    temp = (rule *)malloc(sizeof(*temp));
+    temp = (rule *)calloc(1, sizeof(*temp));
     if (temp==NULL)
 	outofmem(__FILE__, "HTAddRule");
     pPattern = (char *)malloc(strlen(pattern)+1);
@@ -91,14 +101,23 @@ PUBLIC int HTAddRule ARGS3(
     } else {
 	temp->equiv = 0;
     }
+    if (cond_op) {
+	StrAllocCopy(temp->condition_op, cond_op);
+	StrAllocCopy(temp->condition, cond);
+    }
     temp->pattern = pPattern;
     temp->op = op;
 
     strcpy(pPattern, pattern);
     if (equiv) {
-	CTRACE(tfp, "Rule: For `%s' op %d `%s'\n", pattern, op, equiv);
+	CTRACE(tfp, "Rule: For `%s' op %d `%s'", pattern, op, equiv);
     } else {
-	CTRACE(tfp, "Rule: For `%s' op %d\n", pattern, op);
+	CTRACE(tfp, "Rule: For `%s' op %d", pattern, op);
+    }
+    if (cond_op) {
+	CTRACE(tfp, "\t%s %s\n", cond_op, cond ? cond : "<null>");
+    } else {
+	CTRACE(tfp, "\n");
     }
 
     if (!rules) {
@@ -137,6 +156,8 @@ void HTClearRules NOARGS
 	rules = temp->next;
 	FREE(temp->pattern);
 	FREE(temp->equiv);
+	FREE(temp->condition_op);
+	FREE(temp->condition);
 	FREE(temp);
     }
 #ifndef PUT_ON_HEAD
@@ -144,7 +165,32 @@ void HTClearRules NOARGS
 #endif
 }
 
-
+PRIVATE BOOL rule_cond_ok ARGS1(
+    rule *,	 r)
+{
+    BOOL result;
+    if (!r->condition_op)
+	return YES;
+    if (strcmp(r->condition_op, "if") && strcmp(r->condition_op, "unless")) {
+	CTRACE(tfp, "....... rule ignored, unrecognized `%s'!\n",
+	       r->condition_op);
+	return NO;
+    }
+    if (!strcmp(r->condition, "redirected"))
+	result = (redirection_attempts > 0);
+    else if (!strcmp(r->condition, "userspec"))
+	result = LYUserSpecifiedURL;
+    else {
+	CTRACE(tfp, "....... rule ignored, unrecognized `%s %s'!\n",
+	       r->condition_op, r->condition ? r->condition : "<null>");
+	return NO;
+    }
+    if (!strcmp(r->condition_op, "if"))
+	return result;
+    else
+	return (!result);
+	
+}
 /*	Translate by rules					HTTranslate()
 **	------------------
 **
@@ -169,6 +215,9 @@ char * HTTranslate ARGS1(
 {
     rule * r;
     char *current = NULL;
+    char *msgtmp = NULL, *pMsg;
+    int proxy_none_flag = 0;
+    int permitredir_flag = 0;
     StrAllocCopy(current, required);
 
     HTAA_clearProtections();	/* Reset from previous call -- AL */
@@ -188,6 +237,9 @@ char * HTTranslate ARGS1(
 	} else				/* Not wildcard */
 	    if (*p != *q) continue;	/* plain mismatch: go to next rule */
 
+	if (!rule_cond_ok(r))	/* check condition, next rule if false - kw */
+	    continue;
+
 	switch (r->op) {		/* Perform operation */
 
 #ifdef ACCESS_AUTH
@@ -225,14 +277,53 @@ char * HTTranslate ARGS1(
 	    break;
 #endif /* ACCESS_AUTH */
 
+	case HT_UserMsg:		/* Produce message immediately */
+	    LYFixCursesOn("show rule message:");
+	    HTUserMsg2((r->equiv ? r->equiv : "Rule: %s"), current);
+	    break;
+	case HT_InfoMsg:		/* Produce messages immediately */
+	case HT_Progress:
+	case HT_Alert:
+	    LYFixCursesOn("show rule message:"); /* and fall through */
+	case HT_AlwaysAlert:
+	    pMsg = r->equiv ? r->equiv :
+		(r->op==HT_AlwaysAlert) ? "%s" : "Rule: %s";
+	    if (strchr(pMsg, '%')) {
+		HTSprintf0(&msgtmp, pMsg, current);
+		pMsg = msgtmp;
+	    }
+	    switch (r->op) {		/* Actually produce message */
+	    case HT_InfoMsg:	HTInfoMsg(pMsg);	break;
+	    case HT_Progress:	HTProgress(pMsg);	break;
+	    case HT_Alert:	HTAlert(pMsg);		break;
+	    case HT_AlwaysAlert: HTAlwaysAlert("Rule alert:", pMsg);	break;
+	    default: break;
+	    }
+	    FREE(msgtmp);
+	    break;
+
+	case HT_PermitRedir:			/* Set special flag */
+		    permitredir_flag = 1;
+		    CTRACE(tfp, "HTRule: Mark for redirection permitted\n");
+		    break;
+
 	case HT_Pass:				/* Authorised */
 		if (!r->equiv) {
+		    if (proxy_none_flag) {
+			char * temp = NULL;
+			StrAllocCopy(temp, "NoProxy=");
+			StrAllocCat(temp, current);
+			FREE(current);
+			current = temp;
+		    }
 		    CTRACE(tfp, "HTRule: Pass `%s'\n", current);
 		    return current;
 		}
 		/* Else fall through ...to map and pass */
 
 	case HT_Map:
+	case HT_Redirect:
+	case HT_RedirectPerm:
 	    if (*p == *q) { /* End of both strings, no wildcard */
 		  CTRACE(tfp, "For `%s' using `%s'\n", current, r->equiv);
 		  StrAllocCopy(current, r->equiv); /* use entire translation */
@@ -264,9 +355,49 @@ char * HTTranslate ARGS1(
 		    } /* If no insertion point exists */
 		}
 		if (r->op == HT_Pass) {
+		    if (proxy_none_flag) {
+			char * temp = NULL;
+			StrAllocCopy(temp, "NoProxy=");
+			StrAllocCat(temp, current);
+			FREE(current);
+			current = temp;
+		    }
 		    CTRACE(tfp, "HTRule: ...and pass `%s'\n",
 				current);
 		    return current;
+		} else if (r->op == HT_Redirect) {
+		    CTRACE(tfp, "HTRule: ...and redirect to `%s'\n",
+				current);
+		    redirecting_url = current;
+		    HTPermitRedir = (permitredir_flag == 1);
+		    return (char *)0;
+		} else if (r->op == HT_RedirectPerm) {
+		    CTRACE(tfp, "HTRule: ...and redirect like 301 to `%s'\n",
+				current);
+		    redirecting_url = current;
+		    permanent_redirection = TRUE;
+		    HTPermitRedir = (permitredir_flag == 1);
+		    return (char *)0;
+		}
+		break;
+
+	case HT_UseProxy:
+		if (r->equiv && 0==strcasecomp(r->equiv, "none")) {
+		    CTRACE(tfp, "For `%s' will not use proxy\n", current);
+		    proxy_none_flag = 1;
+		} else if (proxy_none_flag) {
+		    CTRACE(tfp, "For `%s' proxy server ignored: %s\n",
+			   current,
+			   r->equiv ? r->equiv : "<null>");
+		} else {
+		    char * temp = NULL;
+		    StrAllocCopy(temp, "Proxied=");
+		    StrAllocCat(temp, r->equiv);
+		    StrAllocCat(temp, current);
+		    CTRACE(tfp, "HTRule: proxy server found: %s\n",
+			   r->equiv ? r->equiv : "<null>");
+		    FREE(current);
+		    return temp;
 		}
 		break;
 
@@ -280,6 +411,12 @@ char * HTTranslate ARGS1(
 
     } /* loop over rules */
 
+    if (proxy_none_flag) {
+	char * temp = NULL;
+	StrAllocCopy(temp, "NoProxy=");
+	StrAllocCat(temp, current);
+	return temp;
+    }
 
     return current;
 }
@@ -298,6 +435,7 @@ PUBLIC int  HTSetConfiguration ARGS1(
     char * line = NULL;
     char * pointer = line;
     char *word1, *word2, *word3;
+    char *cond_op=NULL, *cond=NULL;
     float quality, secs, secs_per_byte;
     int maxbytes;
     int status;
@@ -357,13 +495,121 @@ PUBLIC int  HTSetConfiguration ARGS1(
 	op =	0==strcasecomp(word1, "map")  ? HT_Map
 	    :	0==strcasecomp(word1, "pass") ? HT_Pass
 	    :	0==strcasecomp(word1, "fail") ? HT_Fail
+	    :	0==strcasecomp(word1, "redirect") ? HT_Redirect
+	    :	0==strncasecomp(word1, "redirectperm", 12) ? HT_RedirectPerm
+	    :	0==strcasecomp(word1, "redirecttemp") ? HT_Redirect
+	    :	0==strcasecomp(word1, "permitredirection") ? HT_PermitRedir
+	    :	0==strcasecomp(word1, "useproxy") ? HT_UseProxy
+	    :	0==strcasecomp(word1, "alert") ? HT_Alert
+	    :	0==strcasecomp(word1, "alwaysalert") ? HT_AlwaysAlert
+	    :	0==strcasecomp(word1, "progress") ? HT_Progress
+	    :	0==strcasecomp(word1, "usermsg") ? HT_UserMsg
+	    :	0==strcasecomp(word1, "infomsg") ? HT_InfoMsg
 	    :	0==strcasecomp(word1, "defprot") ? HT_DefProt
 	    :	0==strcasecomp(word1, "protect") ? HT_Protect
 	    :						HT_Invalid;
 	if (op==HT_Invalid) {
 	    fprintf(stderr, "HTRule: %s '%s'\n", RULE_INCORRECT, config);
 	} else {
-	    HTAddRule(op, word2, word3);
+	    switch (op) {
+	    case HT_Fail:	/* never a or other 2nd parameter */
+	    case HT_PermitRedir:
+		cond_op = word3;
+		if (cond_op && *cond_op) {
+		    word3 = NULL;
+		    cond = HTNextField(&pointer);
+		}
+		break;
+
+	    case HT_Pass:	/* possibly a URL2 */
+		if (word3 && (!strcasecomp(word3, "if") ||
+			      !strcasecomp(word3, "unless"))) {
+		    cond_op = word3;
+		    word3 = NULL;
+		    cond = HTNextField(&pointer);
+		    break;
+		} /* else fall through */
+
+	    case HT_Map:	/* always a URL2 (or other 2nd parameter) */
+	    case HT_Redirect:
+	    case HT_RedirectPerm:
+	    case HT_UseProxy:
+		cond_op = HTNextField(&pointer);
+		/* check for extra status word in "Redirect" */
+		if (op==HT_Redirect && 0==strcasecomp(word1, "redirect") &&
+		    cond_op &&
+		    strcasecomp(cond_op, "if") &&
+		    strcasecomp(cond_op, "unless")) {
+		    if (0==strcmp(word2, "301") ||
+			0==strcasecomp(word2, "permanent")) {
+			op = HT_RedirectPerm;
+		    } else if (!(0==strcmp(word2, "302") ||
+				 0==strcmp(word2, "303") ||
+				 0==strcasecomp(word2, "temp") ||
+				 0==strcasecomp(word2, "seeother"))) {
+			CTRACE(tfp, "Rule: Ignoring `%s' in Redirect\n", word2);
+		    }
+		    word2 = word3;
+		    word3 = cond_op; /* cond_op isn't condition op after all */
+		    cond_op = HTNextField(&pointer);
+		}
+		if (cond_op && *cond_op)
+		    cond = HTNextField(&pointer);
+		break;
+
+	    case HT_Progress:
+	    case HT_InfoMsg:
+	    case HT_UserMsg:
+	    case HT_Alert:
+	    case HT_AlwaysAlert:
+		cond_op = HTNextField(&pointer);
+		if (cond_op && *cond_op)
+		    cond = HTNextField(&pointer);
+		if (word3) {	/* Fix string with too may %s - kw */
+		    char *cp = word3, *cp1, *cp2;
+		    while ((cp1=strchr(cp, '%'))) {
+			if (cp1[1] == '\0') {
+			    *cp1 = '\0';
+			    break;
+			} else if (cp1[1] == '%') {
+			    cp = cp1 + 2;
+			    continue;
+			} else while ((cp2=strchr(cp1+2, '%'))) {
+			    if (cp2[1] == '\0') {
+				*cp2 = '\0';
+				break;
+			    } else if (cp2[1] == '%') {
+				cp1 = cp2;
+			    } else {
+				*cp2 = '?'; /* replace bad % */
+				cp1 = cp2;
+			    }
+			}
+			break;
+		    }
+		}
+		break;
+
+		default:
+		break;
+	    }
+	    if (cond_op && cond && *cond && !strcasecomp(cond_op, "unless")) {
+		cond_op = "unless";
+	    } else if (cond_op && cond && *cond &&
+		       !strcasecomp(cond_op, "if")) {
+		cond_op = "if";
+	    } else if (cond_op || cond) {
+		fprintf(stderr, "HTRule: %s '%s'\n", RULE_INCORRECT, config);
+		FREE(line);	/* syntax error, condition is a mess - kw */
+		return -2;	/* NB unrecognized cond passes here - kw */
+	    }
+	    if (cond && !strncasecomp(cond, "redirected", strlen(cond))) {
+		cond = "redirected"; /* recognized, canonical case - kw */
+	    } else if (cond && strlen(cond) >= 8 &&
+		!strncasecomp(cond, "userspecified", strlen(cond))) {
+		cond = "userspec"; /* also allow abbreviation - kw */
+	    }
+	    HTAddRule(op, word2, word3, cond_op, cond);
 	}
     }
     FREE(line);
diff --git a/WWW/Library/Implementation/HTRules.h b/WWW/Library/Implementation/HTRules.h
index fce782f8..0974bbae 100644
--- a/WWW/Library/Implementation/HTRules.h
+++ b/WWW/Library/Implementation/HTRules.h
@@ -28,7 +28,16 @@ typedef enum _HTRuleOp {
         HT_Pass,
         HT_Fail,
         HT_DefProt,
-        HT_Protect
+        HT_Protect,
+        HT_Progress,
+        HT_InfoMsg,
+        HT_UserMsg,
+        HT_Alert,
+        HT_AlwaysAlert,
+        HT_Redirect,
+        HT_RedirectPerm,
+        HT_PermitRedir,
+        HT_UseProxy
 } HTRuleOp;
 
 #ifndef NO_RULES
@@ -57,7 +66,14 @@ HTAddRule:  Add rule to the list
   pattern                points to 0-terminated string containing a single "*"
 
   equiv                  points to the equivalent string with * for the place where the
-                         text matched by * goes.
+                         text matched by * goes; or to other 2nd parameter
+                         meaning depends on op).			 
+
+  cond_op,               additional condition for applying rule; cond_op should
+  cond                   be either NULL (no additional condition), or one of
+                         the strings "if" or "unless"; if cond_op is not NULL,
+                         cond should point to a recognized condition keyword
+                         (as a string) such as "userspec", "redirected".
 
   ON EXIT,
 
@@ -68,7 +84,12 @@ HTAddRule:  Add rule to the list
    large.
 
  */
-extern int HTAddRule PARAMS((HTRuleOp op, CONST char * pattern, CONST char * equiv));
+extern int HTAddRule PARAMS((
+    HTRuleOp op,
+    CONST char * pattern,
+    CONST char * equiv,
+    CONST char * cond_op,
+    CONST char * cond));
 
 
 /*
diff --git a/WWW/Library/Implementation/HTTCP.c b/WWW/Library/Implementation/HTTCP.c
index 1a6b2621..fdc6b66a 100644
--- a/WWW/Library/Implementation/HTTCP.c
+++ b/WWW/Library/Implementation/HTTCP.c
@@ -645,7 +645,7 @@ PUBLIC struct hostent * LYGetHostByName ARGS1(
     struct _statuses {
 	size_t rehostentlen;
 	int h_length;
-	int child_errno;  /* maybe not very useful */
+	int child_errno;  /* sometimes useful to pass this on */
 	int child_h_errno;
 	BOOL h_errno_valid;
     } statuses;
@@ -687,7 +687,7 @@ PUBLIC struct hostent * LYGetHostByName ARGS1(
     CTRACE(tfp, "LYGetHostByName: Calling gethostbyname(%s)\n", host);
 #endif /* MVS */
 
-    CTRACE_FLUSH(tfp);  /* so child messages will not mess parent log */
+    CTRACE_FLUSH(tfp);  /* so child messages will not mess up parent log */
 
     lynx_nsl_status = HT_INTERNAL;	/* should be set to something else below */
 
@@ -699,6 +699,10 @@ PUBLIC struct hostent * LYGetHostByName ARGS1(
 	*/
     {
 	int got_rehostent = 0;
+#if HAVE_SIGACTION
+	sigset_t old_sigset;
+	sigset_t new_sigset;
+#endif
 	/*
 	**	Pipe, child pid, status buffers, start time, select()
 	**	control variables.
@@ -727,6 +731,32 @@ PUBLIC struct hostent * LYGetHostByName ARGS1(
 
 	pipe(pfd);
 
+#if HAVE_SIGACTION
+	/*
+	 *  Attempt to prevent a rare situation where the child
+	 *  could execute the Lynx signal handlers because it gets
+	 *  killed before it even has a chance to reset its handlers,
+	 *  resulting in bogus 'Exiting via interrupt' message and
+	 *  screen corruption or worse.
+	 *  Should that continue to be reported, for systems without
+	 *  sigprocmask(), we need to find a different solutions for
+	 *  those. - kw 19990430
+	 */
+	sigemptyset(&new_sigset);
+	sigaddset(&new_sigset, SIGTERM);
+	sigaddset(&new_sigset, SIGINT);
+#ifndef NOSIGHUP
+	sigaddset(&new_sigset, SIGHUP);
+#endif /* NOSIGHUP */
+#ifdef SIGTSTP
+	sigaddset(&new_sigset, SIGTSTP);
+#endif /* SIGTSTP */
+#ifdef SIGWINCH
+	sigaddset(&new_sigset, SIGWINCH);
+#endif /* SIGWINCH */
+	sigprocmask(SIG_BLOCK, &new_sigset, &old_sigset);
+#endif /* HAVE_SIGACTION */
+
 	if ((fpid = fork()) == 0 ) {
 	    struct hostent  *phost;	/* Pointer to host - See netdb.h */
 	    /*
@@ -764,13 +794,26 @@ PUBLIC struct hostent * LYGetHostByName ARGS1(
 	    signal(SIGSEGV, SIG_DFL);
 	    signal(SIGILL, SIG_DFL);
 
+#if HAVE_SIGACTION
+	    /* Restore signal mask to whatever it was before the fork. -kw */
+	    sigprocmask(SIG_SETMASK, &old_sigset, NULL);
+#endif /* HAVE_SIGACTION */
+
 	    /*
 	    **  Child won't use read side.  -BL
 	    */
 	    close(pfd[0]);
+#ifdef HAVE_H_ERRNO
+	    /* to detect cases when it doesn't get set although it should */
+	    h_errno = -2;
+#endif
+	    errno = 0;
 	    phost = gethostbyname(host);
+	    statuses.child_errno = errno;
 	    statuses.child_h_errno = h_errno;
+#ifdef HAVE_H_ERRNO
 	    statuses.h_errno_valid = YES;
+#endif
 #ifdef MVS
 	    CTRACE(tfp, "LYGetHostByName: gethostbyname() returned %d\n", phost);
 #endif /* MVS */
@@ -790,12 +833,17 @@ PUBLIC struct hostent * LYGetHostByName ARGS1(
 		statuses.h_length = 0;
 	    } else {
 		statuses.h_length = ((struct hostent *)rehostent)->h_length;
+#ifdef HAVE_H_ERRNO
+		if (h_errno == -2) /* success, but h_errno unchanged? */
+		    statuses.h_errno_valid = NO;
+#endif
 	    }
 	    /*
 	    **  Send variables indicating status of lookup to parent.
 	    **  That includes rehostentlen, which the parent will use
 	    **  as the size for the second read (if > 0).
 	    */
+	    if (!statuses.child_errno)
 	    statuses.child_errno = errno;
 	    statuses.rehostentlen = rehostentlen;
 	    write(pfd[1], &statuses, sizeof(statuses));
@@ -815,6 +863,14 @@ PUBLIC struct hostent * LYGetHostByName ARGS1(
 	    }
 	}
 
+#if HAVE_SIGACTION
+	/*
+	**  (parent) Restore signal mask to whatever it was
+	**  before the fork. - kw
+	*/
+	sigprocmask(SIG_SETMASK, &old_sigset, NULL);
+#endif /* HAVE_SIGACTION */
+
 	/*
 	**	(parent) Wait until lookup finishes, or interrupt,
 	**	or cycled too many times (just in case) -BL
@@ -871,8 +927,44 @@ PUBLIC struct hostent * LYGetHostByName ARGS1(
 		if (readret == sizeof(statuses)) {
 		    h_errno = statuses.child_h_errno;
 		    errno = statuses.child_errno;
-		    if (statuses.h_errno_valid)
+#ifdef HAVE_H_ERRNO
+		    if (statuses.h_errno_valid) {
 			lynx_nsl_status = HT_H_ERRNO_VALID;
+			/*
+			 *  If something went wrong in the child process
+			 *  other than normal lookup errors, and it appears
+			 *  that we have enough info to know what went wrong,
+			 *  generate diagnostic output.
+			 *  ENOMEM observed on linux in processes constrained
+			 *  with ulimit.  It would be too unkind to abort
+			 *  the session, access to local files or through a
+			 *  proxy may still work. - kw
+			 */
+			if (
+#ifdef NETDB_INTERNAL		/* linux glibc: defined in netdb.h */
+			    (errno && h_errno == NETDB_INTERNAL) ||
+#endif
+			    (errno == ENOMEM &&
+			     statuses.rehostentlen == 0 &&
+			     /* should probably be NETDB_INTERNAL if child
+				memory exhausted, but we may find that
+				h_errno remains unchanged. - kw */
+			     h_errno == -2)) {
+#ifndef MULTINET
+			    HTInetStatus("CHILD gethostbyname");
+#endif
+			    HTAlert(LYStrerror(statuses.child_errno));
+			    if (errno == ENOMEM) {
+				/*
+				 *  Not much point in continuing, right?
+				 *  Fake a 'z', should shorten pointless
+				 *  guessing cycle. - kw
+				 */
+				LYFakeZap(YES);
+			    }
+			}
+		    }
+#endif /* HAVE_H_ERRNO */
 		    if (statuses.rehostentlen > sizeof(struct hostent)) {
 			/*
 			**  Then get the full reorganized hostent.  -BL, kw
@@ -1311,6 +1403,11 @@ PUBLIC CONST char * HTHostName NOARGS
     return hostname;
 }
 
+#ifndef MULTINET		/* SOCKET_ERRNO != errno ? */
+#if !defined(UCX) || !defined(VAXC) /* errno not modifiable ? */
+#define SOCKET_DEBUG_TRACE    /* show errno status after some system calls */
+#endif  /* UCX && VAXC */
+#endif /* MULTINET */
 /*
 **  Interruptable connect as implemented for Mosaic by Marc Andreesen
 **  and hacked in for Lynx years ago by Lou Montulli, and further
@@ -1449,6 +1546,13 @@ PUBLIC int HTDoConnect ARGS4(
 	int ret;
 	int tries=0;
 
+#ifdef SOCKET_DEBUG_TRACE
+	{
+	    int saved_errno = SOCKET_ERRNO;
+	    HTInetStatus("this socket's first connect");
+	    errno = saved_errno;	/* I don't trust HTInetStatus */
+	}
+#endif /* SOCKET_DEBUG_TRACE */
 	ret = 0;
 	while (ret <= 0) {
 	    fd_set writefds;
@@ -1477,6 +1581,13 @@ PUBLIC int HTDoConnect ARGS4(
 #endif /* SOCKS */
 	    ret = select(FD_SETSIZE, NULL, (void *)&writefds, NULL, &timeout);
 
+#ifdef SOCKET_DEBUG_TRACE
+	    if (tries == 1) {
+		int saved_errno = SOCKET_ERRNO;
+		HTInetStatus("this socket's first select");
+		errno = saved_errno;	/* I don't trust HTInetStatus */
+	    }
+#endif /* SOCKET_DEBUG_TRACE */
 	   /*
 	   **  If we suspend, then it is possible that select will be
 	   **  interrupted.  Allow for this possibility. - JED
@@ -1484,6 +1595,13 @@ PUBLIC int HTDoConnect ARGS4(
 	   if ((ret == -1) && (errno == EINTR))
 	     continue;
 
+#ifdef SOCKET_DEBUG_TRACE
+	   if (ret < 0) {
+	       int saved_errno = SOCKET_ERRNO;
+	       HTInetStatus("failed select");
+	       errno = saved_errno;	/* I don't trust HTInetStatus */
+	   }
+#endif /* SOCKET_DEBUG_TRACE */
 	    /*
 	    **	Again according to the Sun and Motorola man pages for connect:
 	    **	   EALREADY	       The socket is non-blocking and a  previ-
@@ -1527,8 +1645,16 @@ PUBLIC int HTDoConnect ARGS4(
 
 		if (status && (SOCKET_ERRNO == EALREADY)) /* new stuff LJM */
 		    ret = 0; /* keep going */
-		else
+		else {
+#ifdef SOCKET_DEBUG_TRACE
+		    if (status < 0) {
+			int saved_errno = SOCKET_ERRNO;
+			HTInetStatus("confirm-ready connect");
+			errno = saved_errno;
+		    }
+#endif /* SOCKET_DEBUG_TRACE */
 		    break;
+		}
 #ifdef SOCKS
 		}
 #endif /* SOCKS */
@@ -1559,6 +1685,11 @@ PUBLIC int HTDoConnect ARGS4(
 		    (SOCKET_ERRNO != 18242) &&
 #endif /* UCX */
 		    (SOCKET_ERRNO != EISCONN)) {
+#ifdef SOCKET_DEBUG_TRACE
+		    int saved_errno = SOCKET_ERRNO;
+		    HTInetStatus("confirm-not-ready connect");
+		    errno = saved_errno;
+#endif /* SOCKET_DEBUG_TRACE */
 		    break;
 		}
 	    }
@@ -1570,6 +1701,13 @@ PUBLIC int HTDoConnect ARGS4(
 	    }
 	}
     }
+#ifdef SOCKET_DEBUG_TRACE
+    else if (status < 0) {
+	    int saved_errno = SOCKET_ERRNO;
+	    HTInetStatus("this socket's first and only connect");
+	    errno = saved_errno;	/* I don't trust HTInetStatus */
+    }
+#endif /* SOCKET_DEBUG_TRACE */
 #endif /* !DJGPP */
     if (status < 0) {
 	/*
diff --git a/WWW/Library/Implementation/HTTP.c b/WWW/Library/Implementation/HTTP.c
index 96067a51..05b3e89c 100644
--- a/WWW/Library/Implementation/HTTP.c
+++ b/WWW/Library/Implementation/HTTP.c
@@ -918,6 +918,7 @@ try_again:
 		 */
 		HTAlert(line_buffer);
 		HTTP_NETCLOSE(s, handle);
+		HTNoDataOK = 1;
 		status = HT_NO_DATA;
 		goto clean_up;
 
diff --git a/WWW/Library/Implementation/HTUtils.h b/WWW/Library/Implementation/HTUtils.h
index dd5be2dd..dd0a51e7 100644
--- a/WWW/Library/Implementation/HTUtils.h
+++ b/WWW/Library/Implementation/HTUtils.h
@@ -265,6 +265,17 @@ Macros for declarations
 
 /*
 
+OFTEN USED INTEGER MACROS
+
+  Min and Max functions
+  
+ */
+#ifndef HTMIN
+#define HTMIN(a,b) ((a) <= (b) ? (a) : (b))
+#define HTMAX(a,b) ((a) >= (b) ? (a) : (b))
+#endif
+/*
+
 Booleans
 
  */
diff --git a/docs/README.defines b/docs/README.defines
index 5ca9c25b..d93b60e6 100644
--- a/docs/README.defines
+++ b/docs/README.defines
@@ -5,10 +5,10 @@ Does not include
 - symbols defined and documented in userdefs.h
 - symbols expected to be set by compiler to indicate system type or
   compiler features
-- some symbols set and used only in connection with the ./configure
+- many symbols set and used only in connection with the ./configure
   mechanism - the full and current list can be found in config.hin
   (as a template) or, after running ./configure, in lynx_cfg.h.
-- symbols and macros defined in the source code
+- most symbols and macros defined in the source code
 
 ***Not complete.***
 
@@ -50,8 +50,8 @@ Network related, specific protocols
                		see comments in makefile.in
 # -DNOPORT         if you must use PASV instead of PORT for FTP
 
-Related to DirEd code - probably one usable for UNIX or similar
----------------------------------------------------------------
+Related to DirEd code - probably only usable for UNIX or similar
+----------------------------------------------------------------
 # -DDIRED_SUPPORT  (see INSTALLATION, Section II-1c)
 # -DOK_GZIP        (see INSTALLATION, Section II-1c)
 # -DOK_OVERRIDE    (see INSTALLATION, Section II-1c)
@@ -61,6 +61,7 @@ Related to DirEd code - probably one usable for UNIX or similar
 # -DOK_ZIP         (see INSTALLATION, Section II-1c)
 # -DARCHIVE_ONLY   (see INSTALLATION, Section II-1c)
 # -DNO_CHANGE_EXECUTE_PERMS (see INSTALLATION, Section II-1c)
+# -DCANT_EDIT_UNWRITABLE_FILES (see LYEdit.c - always in effect for VMS)
 
 Related to formatting of local directory listings
 -------------------------------------------------
@@ -82,8 +83,8 @@ Using curses or ncurses library:
 # -DNO_SIZECHANGE (old) or HAVE_SIZECHANGE (new) whether using code to detect
                    new size after size changes of the terminal (window).
                    for UNIX handled by ./configure, may be set in HTUtils.h
-# -DUSE_SIZECHANGEHACK  enable hack to handle increasing the window size
-			above window size at startup
+# -DUSE_SIZECHANGEHACK  gone (was: enable hack to handle increasing the
+                        window size above window size at startup)
 
 Using slang library:
 # -DUSE_SLANG      (see INSTALLATION, Section II-1c)
@@ -99,15 +100,38 @@ Related to *experimental* (unsupported) character style code
 # -DUSE_HASH       (see INSTALLATION, Section II-1c)  probably needs the above
 # -DLINKEDSTYLES   (see INSTALLATION, Section II-1c)  probably needs the above
 
-Other
------
+Other general
+-------------
 # -DDONT_TRACK_INTERNAL_LINKS - Handle following links to same doc differently.
-# -DEXP_CHARTRANS_AUTOSWITCH also let lynx switch term mode(Linux console only)
+# -DEXP_CHARTRANS_AUTOSWITCH (see INSTALLATION, Section II-1c) 
 # -DIGNORE_CTRL_C  Define if Control-C shouldn't exit lynx.
 # -DLY_FIND_LEAKS  (see INSTALLATION, Section II-1c)
 # -DNO_CPU_LIMIT   Disables Max CPU timeout (includes CLOCKS_PER_SECOND)
 # -DNSL_FORK       For fork-based name server lookups that can be 'z'apped.
 # -DSYSLOG_REQUESTED_URLS
 # 	if you would like logging of client requests via syslog()
-# -DUSE_ZLIB       To use some functions from zlib library if you have it.
+# -DUSE_ZLIB       (see INSTALLATION)
 # -DDECLARE_WAIS_LOGFILES   see comments in makefile.in
+# -DNO_RULES	   Disables code for CERN-style rules files
+# -DHAVE_SIGACTION Can use sigaction() and related functions
+
+Untested
+--------
+# -DNO_EXTENDED_HTMLDTD	Disable some "SortaSGML" code, see SGML.c
+
+B. Symbols defined locally to modify some behavior
+==================================================
+Defined in the source files to which they apply.  Only filenames are listed,
+the files would have to be read and edited anyway to change the definition.
+Normally installers shouldn't have to care about any of these symbols.
+
+SOCKET_DEBUG_TRACE			HTTCP.c
+DEBUG_HOSTENT				HTTCP.c
+DEBUG_HOSTENT_CHILD			HTTCP.c
+DUPLICATE_ANCHOR_NAME_WORKAROUND	HTAnchor.c
+reverse_mailcap				HTInit.c
+EXTENDED_OPTION_LOGIC			LYMain.c
+EXTENDED_STARTFILE_RECALL		LYMain.c
+reverse_mailcap				HTInit.c
+ADVANCED_INFO				LYShowInfo.c
+CHECK_FREE_MEM				GridText.c
diff --git a/lynx.cfg b/lynx.cfg
index cb4ab723..f4c6691e 100644
--- a/lynx.cfg
+++ b/lynx.cfg
@@ -128,8 +128,8 @@ DEFAULT_INDEX_FILE:http://www.ncsa.uiuc.edu/SDG/Software/Mosaic/MetaIndex.html
 # in a similar manner to 'g'oto; alternatively, s/he can enter '?'
 # to view the full JUMPFILE list of short-cuts with associated URLs.
 # There is an example jumps file in the samples subdirectory.
-# If not defined here or in  userdefs.h , the JUMP command will invoke
-# the NO_JUMPFILE statusline message (cp  LYMessages_en.h ).
+# If not defined here or in userdefs.h, the JUMP command will invoke
+# the NO_JUMPFILE statusline message (see  LYMessages_en.h ).
 #
 # To allow '?' to work, include in the JUMPFILE
 # a short-cut to the JUMPFILE itself, e.g.
@@ -618,8 +618,10 @@ DEFAULT_INDEX_FILE:http://www.ncsa.uiuc.edu/SDG/Software/Mosaic/MetaIndex.html
 #
 #SEEK_FRAG_AREA_IN_CUR:TRUE
 
-# Local execution links and scripts are by default completely disabled
-# unless a change is made to the userdefs.h file to enabled them.
+# Local execution links and scripts are by default completely disabled,
+# unless a change is made to the userdefs.h file to enabled them or
+# the configure script is used with the corresponding options
+# (--enable-exec-links and --enable-exec-scripts).
 # See the Lynx source code distribution and the userdefs.h
 # file for more detail on enabling execution links and scripts.
 #
@@ -645,11 +647,11 @@ DEFAULT_INDEX_FILE:http://www.ncsa.uiuc.edu/SDG/Software/Mosaic/MetaIndex.html
 
 # If LOCAL_EXECUTION_LINK_ON_BUT_NOT_REMOTE is TRUE, and no TRUSTED_EXEC
 # rule is defined, it defaults to "file://localhost/" and any lynxexec
-# or lynxprog command will be permitted if it was referenced with a URL
-# beginning with that string.  If you wish to restrict the referencing URLs
-# further, you can extend the string to include a trusted path.  You also can
-# specify a trusted directory for http URLs, which will then be treated as
-# if they were local rather than remote.  For example:
+# or lynxprog command will be permitted if it was referenced from within
+# a document whose URL begins with that string.  If you wish to restrict the
+# referencing URLs further, you can extend the string to include a trusted
+# path.  You also can specify a trusted directory for http URLs, which will
+# then be treated as if they were local rather than remote.  For example:
 #
 #	TRUSTED_EXEC:file://localhost/trusted/
 #	TRUSTED_EXEC:http://www.wfbr.edu/trusted/
@@ -1595,7 +1597,7 @@ MINIMAL_COMMENTS:TRUE
 # Key remapping definitions!
 #
 # You may redefine the keymapping of any function in Lynx by
-# using the KEYMAP variable.  The form of KEYMAP is:
+# using the KEYMAP option.  The form of KEYMAP is:
 #  KEYMAP:<KEYSTROKE>:<LYNX FUNCTION>
 #
 # You must map upper and lowercase keys separately.
@@ -1636,8 +1638,15 @@ MINIMAL_COMMENTS:TRUE
 #
 # Other codes not listed above may be available for additional keys,
 # depending on operating system and libraries used to compile Lynx.
-
-#KEYMAP:0x2F:SOURCE	# Toggle source viewing mode (show HTML source)
+# On some systems, if compiled with recent versions of slang or ncurses
+# if macro USE_KEYMAPS was in effect during compilation), an additional
+# level of key mapping is supported via an external ".lynx-keymaps" file.
+# This file, if found in the home directory at startup, will always be
+# used under those conditions; see lynx-keymaps distributed in the samples
+# subdirectory for furhter explanation.  Note that mapping via
+# .lynx-keymaps, if applicable, is a step that precedes KEYMAP.
+
+#KEYMAP:0x5C:SOURCE	# Toggle source viewing mode (show HTML source)
 #KEYMAP:^R:RELOAD	# Reload the current document and redisplay
 #KEYMAP:q:QUIT		# Ask the user to quit
 #KEYMAP:Q:ABORT		# Quit without verification
@@ -1707,10 +1716,28 @@ MINIMAL_COMMENTS:TRUE
 #KEYMAP:0x00:DO_NOTHING	# Does nothing (ignore this key)
 #KEYMAP:0x10E:DO_NOTHING # Does nothing (ignore this key)
 #
-# In addition, the following functions are not mapped to any keys by default:
+# KEYMAP lines can have an additional field with content PASS.  If present,
+# if the key is pressed in a text input field it is passed by the built-in
+# line-editor to normal KEYMAP handling, i.e. this flag acts like an implied
+# ^V escape.  It overrides any line-editor binding for the key.  For example,
+#
+#KEYMAP:0x108:HELP:PASS  # Function key Help (or F1) - Always default help
+#
+# In addition, the following functions are not directly mapped to any keys
+# by default, although some of them may be mapped in specific line-editor
+# bindings (effective while in text input fields):
 #
 #KEYMAP:???:RIGHT_LINK	# Move to the link to the right
 #KEYMAP:???:LEFT_LINK	# Move to the link to the left
+#KEYMAP:???:LPOS_PREV_LINK # Like PREV_LINK, last column pos if form input
+#KEYMAP:???:LPOS_NEXT_LINK # Like NEXT_LINK, last column pos if form input
+#*** Only useful in form text fields , need PASS or prefixing with ^V: ***
+#KEYMAP:???:DWIMHELP       # Display help page that may depend on context
+#KEYMAP:???:DWIMEDIT       # Use external editor for context-dependent purpose
+#*** Only useful in a form textarea, need PASS or prefixing with ^V: ***
+#KEYMAP:???:EDITTEXTAREA   # use external editor to edit a form textarea
+#KEYMAP:???:GROWTEXTAREA   # Add some blank lines to bottom of textarea
+#KEYMAP:???:INSERTFILE     # Insert file into a textarea (just above cursor)
 
 # If TOGGLE_HELP is mapped, in novice mode the second help menu line
 # can be toggled among NOVICE_LINE_TWO_A, _B, and _C, as defined in
@@ -1893,6 +1920,35 @@ MINIMAL_COMMENTS:TRUE
 #DIRED_MENU:TAG::Remove all tagged files and directories.::LYNXDIRED://REMOVE_TAGGED
 #DIRED_MENU:TAG::Untag all tagged items.::LYNXDIRED://CLEAR_TAGGED
 
+# Some systems only:
+#===================
+# Lynx tries to detect window size changes with a signal handler for
+# SIGWINCH if supported.  If NONRESTARTING_SIGWINCH is set to TRUE,
+# and the sigaction interface is available on the system, the handler
+# is installed as 'non-restarting'.  On some systems (depending on the
+# library used for handling keyboard input, e.g. ncurses), this allows
+# more immediate notification of window size change events.  If the value
+# is set to FALSE, the signal() interface is used; this normally makes
+# the handler 'restarting', with the effect that lynx can react to size
+# changes only after some key is pressed.  The value can also be set to
+# XWINDOWS; this is equivalent to TRUE when the user has the environment
+# variable DISPLAY defined *at program start*, and equivalent to FALSE
+# otherwise.  The non-restarting behavior can also be changed to TRUE
+# or FALSE with -nonrestarting_sigwinch switch, which overrides the
+# value in this file.
+# Note that Lynx never re-parses document text purely as a result of a
+# window size change, so text lines may appear truncated after narrowing
+# the window, until the document is reloaded with ^R or a similar key
+# or until a different text is loaded.
+# The default is FALSE since there is a possibility that non-restarting
+# interrupts may be mis-interpreted as fatal input errors in some
+# configurations (leading to an abrupt program exit), and since this
+# option is useful mostly only for users running Lynx under xterm or a
+# similar X terminal emulator.  On systems where the preconditions don't
+# apply this option is ignored.
+# 
+#NONRESTARTING_SIGWINCH:FALSE
+
 # Unix ONLY:
 #===========
 # If NO_FORCED_CORE_DUMP is set to TRUE, Lynx will not force
@@ -1975,6 +2031,9 @@ MINIMAL_COMMENTS:TRUE
 # for certain externals to be enabled while restricting others.  TRUE means
 # a command will still function while Lynx is restricted.  WB
 #
+# For invoking the command use the EXTERN key.  By default it is mapped
+# to '.' (if the feature is enabled), see the KEYMAP section above.
+#
 # EXTERNAL:ftp:wget %s &:TRUE
 
 # CERN-style rules, EXPERIMENTAL  -  URL-specific rules
@@ -1994,7 +2053,7 @@ MINIMAL_COMMENTS:TRUE
 #	RULE:Fail	gopher:*		     # reject by scheme
 #	RULE:Pass	finger://*@localhost/	     # allow this,
 #	RULE:Fail	finger:*		     # but not others
-#	RULE:Map	http://old.server/*	http://new.server/*
+#	RULE:Redirect	http://old.server/*	http://new.server/*
 
 
 # Pretty source view settings. These settings are in effect when -prettysrc
diff --git a/lynx.hlp b/lynx.hlp
index bc2ca656..c70e7fb7 100644
--- a/lynx.hlp
+++ b/lynx.hlp
@@ -39,7 +39,7 @@
        accept all cookies.
 
   -anonymous
-       used to specify the anonymous account.
+       apply restrictions for anonymous account, see also -restrictions.
 
   -assume_charset=MIMEname
        charset for documents that don't specify it.
@@ -243,7 +243,7 @@
        disable forced pauses for statusline messages.
 
   -noprint
-       disable print functions.
+       disable most print functions.
 
   -noredir
        prevents automatic redirection and prints a message with a
@@ -262,7 +262,7 @@
        force numbering of links.
 
   -partial
-       display partial pages while downloading.
+       display partial pages while loading.
 
   -partial_thres=NUMBER
        number of lines to render before repainting display
@@ -305,7 +305,7 @@
        allows a list of services to be disabled selectively.  The following
        list is printed if no options are specified.
 
-       all - restricts all options.
+       all - restricts all options listed below.
 
        bookmark - disallow changing the location of the bookmark file.
 
@@ -316,19 +316,23 @@
            management is enabled.
 
        default - same as command line option -anonymous.  Disables default
-           services for anonymous users.  Currently set to all restricted
-           except for:  inside_telnet, outside_telnet, inside_news,
-           inside_ftp, outside_ftp, inside_rlogin, outside_rlogin, jump,
-           mail and goto.  Defaults are setable within userdefs.h.
+           services 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.
 
        dired_support - disallow local file management.
 
        disk_save - disallow saving to disk in the download and print
            menus.
 
-       download - disallow downloaders in the download menu.
+       download - disallow some downloaders in the download menu (does
+           not imply disk_save restriction).
 
-       editor - disallow editing.
+       editor - disallow external editing.
 
        exec - disable execution scripts.
 
@@ -343,8 +347,11 @@
        inside_ftp - disallow ftps for people coming from inside your domain
            (utmp required for selectivity).
 
-       inside_news - disallow USENET news posting for people coming from
-           inside our domain (utmp required for selectivity).
+       inside_news - disallow USENET news reading and posting for people
+           coming from inside our domain (utmp required for selectivity).
+           This restriction applies to "news", "nntp", "newspost", and
+           "newsreply" URLs, but not to "snews", "snewspost", or
+           "snewsreply" in case they are supported.
 
        inside_rlogin - disallow rlogins for people coming from inside your
            domain (utmp required for selectivity).
@@ -367,6 +374,9 @@
 
        outside_news - disallow USENET news posting for people coming from
            outside your domain (utmp required for selectivity).
+           This restriction applies to "news", "nntp", "newspost", and
+           "newsreply" URLs, but not to "snews", "snewspost", or
+           "snewsreply" in case they are supported.
 
        outside_rlogin - disallow rlogins for people coming from outside your
            domain (utmp required for selectivity).
@@ -424,7 +434,7 @@
        disable recognition of telnet commands.
 
   -term=TERM
-       tell Lynx what terminal type to assume its talking to.  (This may be
+       tell Lynx what terminal type to assume it's talking to.  (This may be
        useful for remote execution, when, for example, Lynx connects to a
        remote TCP/IP port that starts a script that, in turn, starts another
        Lynx process.)
@@ -433,7 +443,8 @@
        toggles use of a Lynx Trace Log for the current session.
 
   -trace
-       turns on WWW trace mode.
+       turns on Lynx trace mode.  Destination of trace output depends
+       on -tlog.
 
   -traversal
        traverse all http links derived from startfile.  When used with
diff --git a/lynx.man b/lynx.man
index 498d3267..d644885d 100644
--- a/lynx.man
+++ b/lynx.man
@@ -59,12 +59,16 @@ If the argument is only '-', then Lynx expects to receive
 the arguments from stdin.  This is to allow for the
 potentially very long command line that can be associated
 with the -get_data or -post_data arguments (see below).
+It can also be used to avoid having sensitive information
+in the invoking command line (which would be visible to
+other processes on most systems), especially when
+the -auth or -pauth options are used.
 .TP
 .B -accept_all_cookies
 accept all cookies.
 .TP
 .B -anonymous
-used to specify the anonymous account.
+apply restrictions for anonymous account, see also -restrictions.
 .TP
 .B -assume_charset\fR=\fIID\fR:\fIMIMEname
 charset for documents that don't specify it.
@@ -87,7 +91,7 @@ outputs for -source dumps.
 .B -blink
 forces high intensity bg colors for color mode, if available
 and supported by the terminal.
-Lynx needs to be compiled with the slang library for this flag.
+Lynx needs to be compiled with the \fBslang\fR library for this flag.
 .TP
 .B -book
 use the bookmark page as the startfile.  The default or command
@@ -118,7 +122,12 @@ exit on left-arrow in startfile, and disable save to disk.
 forces color mode on, if available.  Default color control sequences
 which work for many terminal types are assumed if the terminal
 capability description does not specify how to handle color.
-Lynx needs to be compiled with the slang library for this flag.
+Lynx needs to be compiled with the \fBslang\fR library for this flag,
+it is equivalent to setting the \fBCOLORTERM\fR environment variable.
+(If color support is instead provided by a color-capable curses
+library like \fBncurses\fR, Lynx relies completely on the terminal
+description to determine whether color mode is possible, and
+this flag is not needed and thus unavailable.)
 A saved show_color=always setting found in a .lynxrc file at
 startup has the same effect.  A saved show_color=always found
 in .lynxrc on startup is overridden by this flag.
@@ -144,13 +153,13 @@ set the display variable for X rexec-ed programs.
 .TP
 .B -dump
 dumps the formatted output of the default document or one
-specified on the command line to standard out.
+specified on the command line to standard output.
 This can be used in the following way:
 .sp
 lynx -dump http://www.crl.com/~subir/lynx.html
 .TP
 .B -editor\fR=\fIEDITOR
-enable edit mode using the specified
+enable external editing, using the specified
 EDITOR. (vi, ed, emacs, etc.)
 .TP
 .B -emacskeys
@@ -273,11 +282,18 @@ disable the link list feature in dumps.
 .B -nolog
 disable mailing of error messages to document owners.
 .TP
+.B -nonrestarting_sigwinch
+This flag is not available on all systems, 
+Lynx needs to be compiled with HAVE_SIGACTION defined.
+If available, this flag \fImay\fR cause Lynx to react
+more immediately to window changes when run within 
+an \fBxterm\fR.
+.TP
 .B -nopause
 disable forced pauses for statusline messages.
 .TP
 .B -noprint
-disable print functions.
+disable most print functions.
 .TP
 .B -noredir
 prevents automatic redirection and prints a message with a
@@ -296,7 +312,7 @@ disable the retrieval status messages.
 force numbering of links.
 .TP
 .B -partial
-display partial pages while downloading.
+display partial pages while loading.
 .TP
 .B partial_thres\fR=\fINUMBER
 number of lines to render before repainting display
@@ -344,7 +360,7 @@ selectively.  The following list is printed
 if no options are specified.
 
 .I all
-- restricts all options.
+- restricts all options listed below.
 
 .I bookmark
 - disallow changing the location of the bookmark
@@ -361,11 +377,16 @@ management is enabled.
 .I default
 - same as command line option -anonymous.
 Disables default services for anonymous users.
-Currently set to all restricted except for:
-inside_telnet, outside_telnet, inside_news,
-inside_ftp, outside_ftp, inside_rlogin,
-outside_rlogin, jump, mail and goto.  Defaults
-are setable within userdefs.h.
+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.
 
 .I dired_support
 - disallow local file management.
@@ -374,11 +395,15 @@ are setable within userdefs.h.
 - disallow saving to disk in the download and
 print menus.
 
+.I dotfiles
+- disallow access to, or creation of, hidden (dot) files.
+
 .I download
-- disallow downloaders in the download menu.
+- disallow some downloaders in the download menu (does not
+imply disk_save restriction).
 
 .I editor
-- disallow editing.
+- disallow external editing.
 
 .I exec
 - disable execution scripts.
@@ -387,6 +412,12 @@ print menus.
 - disallow the user from changing the local
 execution option.
 
+.I externals
+- disallow some "EXTERNAL" configuration lines
+if support for passing URLs to external
+applications (with the EXTERN command) is
+compiled in.
+
 .I file_url
 - disallow using G)oto, served links or bookmarks for
 file: URLs.
@@ -430,8 +461,11 @@ your domain (utmp required for selectivity).
 domain (utmp required for selectivity).
 
 .I outside_news
-- disallow USENET news posting for people coming
+- disallow USENET news reading and posting for people coming
 from outside your domain (utmp required for selectivity).
+This restriction applies to "news", "nntp", "newspost", and
+"newsreply" URLs, but not to "snews", "snewspost",
+or "snewsreply" in case they are supported.
 
 .I outside_rlogin
 - disallow rlogins for people coming from outside
@@ -497,16 +531,18 @@ initialize parser, using Tag Soup DTD rather than SortaSGML.
 disable recognition of telnet commands.
 .TP
 .B -term\fR=\fITERM
-tell Lynx what terminal type to assume its talking to.
+tell Lynx what terminal type to assume it is talking to.
 (This may be useful for remote execution, when, for example,
 Lynx connects to a remote TCP/IP port that starts a script that,
 in turn, starts another Lynx process.)
 .TP
 .B -tlog
-toggles use of a Lynx Trace Log for the current session.
+toggles between using a Lynx Trace Log and stderr for trace output
+from the session.
 .TP
 .B -trace
-turns on WWW trace mode.
+turns on Lynx trace mode.  Destination of trace output depends
+on -tlog.
 .TP
 .B -traversal
 traverse all http links derived from startfile.  When used with
@@ -518,12 +554,17 @@ for more information.
 toggles use of _underline_ format in dumps.
 .TP
 .B -use_mouse
-turn on xterm mouse support.
+turn on mouse support, if available.
 Clicking the left mouse button on a link traverses it.
 Clicking the right mouse button pops back.
-Click in the first line of a page to scroll up.
-Click in the last line of a page to scroll down.
-Lynx must be compiled with ncurses or slang to support this feature.
+Click on the top line to scroll up.
+Click on the bottom line to scroll down.
+The first few positions in the top and bottom line may invoke
+additional functions.
+Lynx must be compiled with \fBncurses\fR or \fBslang\fR to support this feature.
+If \fBncurses\fR is used, clicking the middle mouse button pops up
+a simple menu.  Mouse clicks may only work reliably while Lynx is
+idle waiting for input.
 .TP
 .B -useragent=Name
 set alternate Lynx User-Agent header.
diff --git a/lynx_help/Lynx_users_guide.html b/lynx_help/Lynx_users_guide.html
index 45d82fab..a4750ce5 100644
--- a/lynx_help/Lynx_users_guide.html
+++ b/lynx_help/Lynx_users_guide.html
@@ -351,8 +351,8 @@ may have a local copy of the document source, but it is better to <a
 href="#RemoteSource">Download</a> the source.
 
 <p>NOTE: When saving an HTML document it is important to name the
-document with a <em>.html</em> extension, if you want to read it with
-Lynx again later.
+document with a <em>.html</em> or <em>.htm</em> extension, if you
+want to read it with Lynx again later.
 
 <p>Lynx can allow users to edit documents that reside on the local
 system.  To enable editing, documents must be referenced using a
@@ -565,7 +565,7 @@ parentheses for the option you wish to change (e.g., '<em>E</em>' for Editor
 or '<em>@</em>' for show cursor).  For fields where text must be entered,
 simply enter the text by typing on the keyboard.  The <a
 href="keystrokes/edit_help.html">Line Editor</a> can be used to
-correct mistakes, and <em>Control-U</em> can be used to erase the whole
+correct mistakes, and <em>Control-U</em> can be used to erase the
 line.  When you are done entering a change press the <em>Return</em> key
 to get back to the <em>Command?</em> prompt.
 
@@ -777,7 +777,7 @@ return to Lynx or the '<em>&gt;</em>' command to save the options to a
 	    their configured bindings (normally UP_TWO lines, DOWN_TWO
 	    lines, NEXT_PAGE, and PREV_PAGE, respectively).
 
-	 <p>Note: this has no effect on the line-editor's key bindings.
+	 <p>Note: this has no direct effect on the line-editor's key bindings.
 
    <dt>Show dot files
 	<dd>If display/creation of hidden (dot) files/directories is
@@ -819,9 +819,9 @@ return to Lynx or the '<em>&gt;</em>' command to save the options to a
 	    help for more information.
 
    <dt>Line edit style
-	<dd>This option allows you to set alternate key bindings for the
-	    built-in line editor, if your system administrator has installed
-	    alternates.  Otherwise, Lynx uses the <a
+	<dd>This option allows you to set alternative key bindings for the
+	    built-in line editor, if alternative line-edit bindings have
+	    been compiled in.  Otherwise, Lynx uses the <a
 	    href="keystrokes/edit_help.html">Default Binding</a>.
 
    <dt>List directory style
@@ -1213,7 +1213,7 @@ commands.
 	    sent with method GET, and will be entered into the circular
 	    buffer for goto URLs so that it can be accessed for further
 	    modification via the '<em>g</em>' command.	Note that lower
-	    case 'e' invokes the editor for the current document.
+	    case 'e' invokes the external editor for the current document.
 
    <dt><em>=</em>
 	<dd>The '<em>=</em>' command shows information about the current
@@ -1225,7 +1225,11 @@ commands.
 	    useful for diagnosing bad html.  If you get a <em>Bad HTML</em>
 	    statusline message when loading a document, enter
 	    <em>Control-T</em> and then <em>Control-R</em> to reload the
-	    document in trace mode.  You also can submit the document for
+	    document in trace mode.  You may then examine the
+	    <em>Lynx Trace Log</em> file with the <em>;</em> command
+	    if enabled (see below), watch out especially for lines marked
+	    with a number of asterisks '<tt>*****</tt>'.
+	    You also can submit the document for
 	    validation via links in the online help menu.  If you are able
 	    to diagnose the problem, send a message about it to the
 	    document's author.
@@ -1233,16 +1237,16 @@ commands.
 	<dd>The <em>;</em> command shows the <em>Lynx Trace Log</em>
 	    (<em>Lynx.trace</em> in the home directory) if one has been
 	    started for the current session.  If a log has not been started,
-	    any trace and other stderr messages will be sent to the screen
+	    any trace messages will be sent to the screen
 	    (and will disturb the normal display) unless the system supports
 	    piping and that was used to redirect stderr messages to a file.
 	    The log is started when Lynx trace mode is turned on via the
 	    <em>-trace</em> command line switch, or via the
 	    <em>Control-T</em> toggle, if Lynx has been compiled to log
-	    the trace and other stderr messages.  If not, ability to
-	    create a log can be toggled on with the <em>-tlog</em> switch.
-	    Note that this ability is disabled in anonymous or validation
-	    accounts.
+	    the trace and other stderr messages by default.  If not,
+	    ability to create a log can be toggled on with
+	    the <em>-tlog</em> switch.   Note that this ability is
+	    probably disabled in anonymous or validation accounts.
    <dt><A NAME="*-key"><em>*</em></A>
 	<dd>The '<em>*</em>' command toggles image_links mode on and off.
 	    When on, links will be created for all images, including inlines.
@@ -1309,7 +1313,7 @@ options from a list, and fields for entering text.
 <dd>Buttons are displayed in the same way that Lynx displays links in
     a document.  To "push" the button press the <em>right-arrow</em> or
     <em>Return</em> key.  If it is a form submission button, you also can
-    use the RESUBMIT ('<em>x</em>') or DOWNLOAD ('<em>d</em>') keystroke
+    use the NOCACHE ('<em>x</em>') or DOWNLOAD ('<em>d</em>') keystroke
     commands to "push" the button (see below).
 
 <dt>Checkboxes and Radio buttons
@@ -1362,12 +1366,11 @@ options from a list, and fields for entering text.
     <em>down-arrow</em> or <em>Return</em> keys move you to the preceding,
     or next line of the overall message, as for INPUT fields, and the
     <em>TAB</em> key will move you down beyond the bottom of the TEXTAREA
-    field, or to the first line on the next page if the overall field
-    extends beyond the currently displayed page.<P>
+    field.<P>
 
 <dt>Editing TEXTAREA Fields
 <dd>TEXTAREA fields can be edited using an external editor
-    by entering <em>^ve</em> when in the TEXTAREA.<p>
+    by entering <em>^Ve</em> when in the TEXTAREA.<p>
 
     You can also use two other special TEXTAREA functions
     by adding KEYMAP bindings to your <em>lynx.cfg</em> file, e.g.<p>
@@ -1375,19 +1378,20 @@ options from a list, and fields for entering text.
     &nbsp;&nbsp;KEYMAP:$:GROWTEXTAREA<br>
     &nbsp;&nbsp;KEYMAP:#:INSERTFILE<p>
 
-    With these binding -- you can choose other keys -- ,<br>
-    (in a TEXTAREA only) <em>^v$</em> adds 5 lines to the TEXTAREA
-    and <em>^v#</em> brings up the name of an existing file
+    With these bindings -- you can choose other keys -- ,<br>
+    (in a TEXTAREA only) <em>^V$</em> adds 5 lines to the TEXTAREA
+    and <em>^V#</em> brings up the name of an existing file
     to be inserted into the TEXTAREA (above the cursorline).
     An automatic variation is normally compiled in,
     so that hitting <em>Enter</em> with the cursor on the last line
     adds a new line to the TEXTAREA, with the cursor on it.<p>
 
     Some flavors of UNIX, shells &amp; terminal settings require
-    that you enter <em>^v^ve</em> in order to start the editor,
-    as they also use <em>^v</em> as default command-line quote key
+    that you enter <em>^V^Ve</em> in order to start the external editor,
+    as they also use <em>^V</em> as default command-line quote key
     (called `lnext' in stty man pages and `stty -a' output);
-    to avoid this, you can put `stty lnext undef' in .cshrc
+    to avoid this, you can put `stty lnext undef' in your .cshrc
+    file (or .profile or .bashrc, depending on what shell you use),
     or invoke Lynx with a wrapper script, e.g.<p>
 
     <code>
@@ -1397,7 +1401,8 @@ options from a list, and fields for entering text.
     &nbsp;&nbsp;stty lnext ^V<br>
     &nbsp;&nbsp;exit</code><p>
 
-    NB when NOT in a TEXTAREA, <em>^v</em> is the default command
+    NB when NOT in a TEXTAREA, <em>^V</em> is by default bound
+    to the command
     to switch between SortaSGML and TagSoup HTML parsing
     (i.e., SWITCH_DTD ).
 
@@ -1406,14 +1411,15 @@ options from a list, and fields for entering text.
 In general, you can move around the form using the standard Lynx navigation
 keys.  The <em>up-arrow</em> and <em>down-arrow</em> keys, respectively,
 select the previous or next field, box, or button.  The <em>TAB</em> key
-selects the next field (or next page of a TEXTAREA if it extends onto the
-next page), box, or button.
+selects the next field, box, or button.
 
 <p><em>NOTE:</em> If you have a text input field selected you will not
 have access to most of the Lynx keystroke commands, because they are
 interpreted by the <a href="keystrokes/edit_help.html"
 >Line Editor</a> as either text entries or editing commands.  Select a
-button or box when you want to use Lynx keystrokes.
+button or box when you want to use Lynx keystrokes; or prefix your
+keystroke with <em>^V</em> to temporarily escape from line editing.
+
 
 <p>To <A name="submit"><em>submit</em></a> the form press
 <em>right-arrow</em> or <em>Return</em> when positioned on the form's
@@ -1421,7 +1427,7 @@ submit button.	If you've submitted the form previously during the Lynx
 session, have not changed any of the form content, and the METHOD was
 <em>GET</em>, Lynx will retrieve from its cache what was returned from the
 previous submission.  If you wish to resubmit that form to the server with
-the same content as previously, use the RESUBMIT command ('<em>x</em>') when
+the same content as previously, use the NOCACHE command ('<em>x</em>') when
 positioned on the submit button.  The <em>right-arrow</em> and <em>Return</em>
 keys also will invoke a no-cache resubmission if the reply from a form
 submission included a META element with a no-cache Pragma or Cache-Control
@@ -1653,7 +1659,9 @@ a number of others which have subsequently been proposed.  These
 <em>Meta</em>, <em>URC</em>, <em>Hotlist</em>, <em>Begin</em>,
 <em>First</em>, <em>End</em>, <em>Last</em>, <em>Pointer</em>,
 <em>Translation</em>, <em>Definition</em>, <em>Chapter</em>,
+<em>Section</em>, <em>Subsection</em>, <em>Alternate</em>,
 <em>Documentation</em>, <em>Biblioentry</em>, <em>Bibliography</em>,
+<em>Start</em>, <em>Appendix</em>,
 <em>Bookmark</em> and <em>Banner</em>.	Any LINK elements with those
 tokens as the REL attribute value, and an HREF attribute value in the LINK,
 will invoke creation of a <em>banner</em> at the top of the first page,
@@ -2057,7 +2065,12 @@ where
 		    expects to receive the arguments from stdin.  This is to
 		    allow for the potentially very long command line that can
 		    be associated with the <em>-get_data</em> or
-		    <em>-post_data</em> arguments (see below).	On VMS, it
+		    <em>-post_data</em> arguments (see below).
+		    It can also be used to avoid having sensitive information
+		    in the invoking command line (which would be visible to
+		    other processes on most systems), especially when
+		    the <em>-auth</em> or <em>-pauth</em> options are used.
+		    On VMS, the dash
 		    must be encased in double-quotes (&quot;-&quot;) and the
 		    keyboard input terminated with <em>Control-Z</em> or the
 		    command file input terminated by a line that begins
@@ -2066,12 +2079,14 @@ where
 	     <dt><code>-accept_all_cookies</code>
 		<dd>accept all cookies.
 	     <dt><code>-anonymous</code>
-		<dd>used to specify the anonymous account.
-	     <dt><code>-assume_charset=MIMEname</code>
+		<dd>apply restrictions appropriate for an anonymous
+                    account, see <em>-restrictions</em> below for some
+		    details.
+	     <dt><code>-assume_charset=MIMENAME</code>
 		<dd>charset for documents that don't specify it.
-	     <dt><code>-assume_local_charset=MIMEname</code>
+	     <dt><code>-assume_local_charset=MIMENAME</code>
 		<dd>charset assumed for local files.
-	     <dt><code>-assume_unrec_charset=MIMEname</code>
+	     <dt><code>-assume_unrec_charset=MIMENAME</code>
 		<dd>use this instead of unrecognized charsets.
 	     <dt><code>-auth=ID:PW</code>
 		<dd>set authorization ID and password for protected documents
@@ -2111,6 +2126,11 @@ where
 		       which work for many terminal types are assumed if the terminal
 		       capability description does not specify how to handle color.
 		       Lynx needs to be compiled with the slang library for this flag.
+		       It is equivalent to setting the COLORTERM environment variable.
+		       (If color support is instead provided by a color-capable curses
+		       library like ncurses, Lynx relies completely on the terminal
+		       description to determine whether color mode is possible, and
+		       this flag is not needed and thus unavailable.)
 		       A saved show_color=always setting found in a .lynxrc file at
 		       startup has the same effect.  A saved show_color=always found
 		       in .lynxrc on startup is overridden by this flag.
@@ -2130,7 +2150,7 @@ where
 		    This can be used in the following way:<br>
 		    <em>lynx -dump http://www.w3.org/</em>
 	     <dt><code>-editor=EDITOR</code>
-		<dd>enable edit mode using the specified
+		<dd>enable external editing using the specified
 		    <em>EDITOR</em>. (vi, ed, emacs, etc.)
 	     <dt><code>-emacskeys</code>
 		<dd>enable emacs-like key movement.
@@ -2141,9 +2161,6 @@ where
 	     <dt><code>-error_file=FILENAME</code>
 		<dd>the status code from the HTTP request is placed in this
 		    file.
-	     <dt><code>-locexec</code>
-		<dd>enable local program execution from local files only
-		    (if lynx was compiled with local execution enabled).
 	     <dt><code>-fileversions</code>
 		<dd>include all versions of files in local VMS directory
 		    listings.
@@ -2184,6 +2201,9 @@ where
 		    <em>-crawl</em>.
 	     <dt><code>-localhost</code>
 		<dd>disable URLs that point to remote hosts.
+	     <dt><code>-locexec</code>
+		<dd>enable local program execution from local files only
+		    (if lynx was compiled with local execution enabled).
 	     <dt><code>-mime_header</code>
 		<dd>include mime headers and force source dump.
 	     <dt><code>-minimal</code>
@@ -2214,10 +2234,17 @@ where
 		<dd>disable the link list feature in dumps.
 	     <dt><code>-nolog</code>
 		<dd>disable mailing of error messages to document owners.
+	     <dt><code>-nonrestarting_sigwinch</code>
+		<dd>make window size change handler non-restarting.
+		This flag is not available on all systems,
+		Lynx needs to be compiled with HAVE_SIGACTION defined.
+		If available, this flag <em>may</em> cause Lynx to react
+		more immediately to window changes when run within an
+		xterm.
 	     <dt><code>-nopause</code>
 		<dd>disable forced pauses for statusline messages.
 	     <dt><code>-noprint</code>
-		<dd>disable print functions.
+		<dd>disable most print functions.
 	     <dt><code>-noredir</code>
 		<dd>don't follow URL redirections
 	     <dt><code>-noreferer</code>
@@ -2229,7 +2256,7 @@ where
 	     <dt><code>-number_links</code>
 		<dd>force numbering of links.
 	     <dt><code>-partial</code>
-		<dd>toggles display partial pages while downloading.
+		<dd>toggles displaying of partial pages while downloading.
 	     <dt><code>-pauth=ID:PW</code>
 		<dd>set authorization ID and password for a protected proxy
 		    server at startup.	Be sure to protect any script files
@@ -2268,10 +2295,13 @@ where
 		<dd>allows a list of services to be disabled
 		    selectively and takes the following form:
 		<dd><em>lynx -restrictions=[option][,option][,option]...</em>
-		<dd>This list is printed if no options are specified.
+		<dd>The list of recognized options is printed if none
+		    are specified.
 	       <dl>
+		<dt>?
+			<dd>if used alone, lists restrictions in effect.
 		<dt>all
-			<dd>restricts all options.
+			<dd>restricts all options listed below.
 		<dt>bookmark
 			<dd>disallow changing the location of the bookmark
 			    file.
@@ -2283,26 +2313,62 @@ where
 			    local file management is enabled.
 		<dt>default
 			<dd>same as command line option <em>-anonymous</em>.
-			    Disables default services for anonymous users.
-			    Currently set to all restricted except for:
-			    inside_telnet, outside_telnet, inside_news,
-			    inside_ftp, outside_ftp, inside_rlogin,
-			    outside_rlogin, jump, mail and goto.  Defaults
-			    are settable within userdefs.h.
+			    Set default restrictions for anonymous users.
+			    All specific services listed are always
+			    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.<br>
+			    Note that this is the only option value that
+			    may have the effect of <em>removing</em> some
+			    restrictions, if they have been set by other
+			    options, namely for those services that
+			    <em>are</em> allowed by default according to
+			    userdefs.h.  However, if the separate command
+			    line option form (<em>-anonymous</em>) is used,
+			    Lynx takes care to set the default restrictions
+			    before handling additional <em>-restrictions=</em>
+			    options (even if they precede the
+			    <em>anonymous</em> option), so that this cannot
+			    happen.
 		<dt>dired_support
 			<dd>disallow local file management.
 		<dt>disk_save
 			<dd>disallow saving to disk in the download and print
 			    menus.
+		<dt>dotfiles
+			<dd>disallow access to, or creation of, hidden (dot)
+			    files.
 		<dt>download
-			<dd>disallow downloaders in the download menu.
+			<dd>disallow some downloaders in the download menu.
+			    This does <em>not</em> imply the disk_save
+			    restriction.  It also does not disable the
+			    DOWNLOAD command, and does not prevent
+			    "Download or Cancel" offers when a MIME type
+			    cannot otherwise be handled.  Those are only
+			    disabled if additionally the disk_save
+			    restriction is in effect <em>and</em>
+			    no download methods are defined in a <A
+			    HREF="#lynx.cfg">Lynx configuration
+			    file</A> that are marked as "always ENABLED"
+			    (or, alternatively, if the -validate switch
+			    is used).
 		<dt>editor
-			<dd>disallow editing.
+			<dd>disallow external editing.
 		<dt>exec
 			<dd>disable execution scripts.
 		<dt>exec_frozen
 			<dd>disallow the user from changing the local
 			    execution option.
+		<dt>externals
+			<dd>disallow some "EXTERNAL" configuration lines,
+			    if support for passing URLs to external
+			    applications (with the EXTERN command) is
+			    compiled in.
 		<dt>file_url
 			<dd>disallow using G)oto, served links or bookmarks
 			    for file: URLs.
@@ -2312,8 +2378,12 @@ where
 			<dd>disallow ftps for people coming from inside your
 			    domain.
 		<dt>inside_news
-			<dd>disallow USENET news posting for people coming
-			    from inside you domain.
+			<dd>disallow USENET news reading and posting for
+			    people coming from inside you domain.  This
+			    applies to "news", "nntp", "newspost", and
+			    "newsreply" URLs, but not to "snews", "snewspost",
+			    or "snewsreply" in case they are supported.
+
 		<dt>inside_rlogin
 			<dd>disallow rlogins for people coming from inside
 			    your domain.
@@ -2327,15 +2397,18 @@ where
 		<dt>multibook
 			<dd>disallow multiple bookmarks.
 		<dt>news_post
-			<dd>disallow USENET News posting.
+			<dd>disallow USENET News posting,
 		<dt>options_save
 			<dd>disallow saving options in .lynxrc.
 		<dt>outside_ftp
 			<dd>disallow ftps for people coming from outside your
 			    domain.
 		<dt>outside_news
-			<dd>disallow USENET news posting for people coming
-			    from outside you domain.
+			<dd>disallow USENET news reading and posting for
+			    people coming from outside you domain.  This
+			    applies to "news", "nntp", "newspost", and
+			    "newsreply" URLs, but not to "snews", "snewspost",
+			    or "snewsreply" in case they are supported.
 		<dt>outside_rlogin
 			<dd>disallow rlogins for people coming from outside
 			    your domain.
@@ -2394,23 +2467,26 @@ where
 		    example, Lynx connects to a remote TCP/IP port that starts
 		    a script that, in turn, starts another Lynx process.)
 	     <dt><code>-tlog</code>
-		<dd>toggles use of a <em>Lynx Trace Log</em> for the current
+		<dd>toggles use of a <em>Lynx Trace Log</em> for the
 		    session.  The log is named <em>Lynx.trace</em> and is
 		    created in the home directory when Lynx trace mode is
 		    turned on via the <em>-trace</em> command line switch
-		    (see below), or via the TOGGLE_TRACE (<em>Control-T</em>)
+		    (see below), or via the TRACE_TOGGLE (<em>Control-T</em>)
 		    keystroke command.	Once a log is started for the session,
 		    all trace and other stderr messages are written to the
 		    log.  The contents of the log can be examined during
 		    the session via the TRACE_LOG (normally, '<em>;</em>')
-		    keystroke command.
+		    keystroke command.  If use of a Lynx Trace Log
+		    is turned off, any trace output will go to the standard
+		    error stream.
 	     <dt><code>-trace</code>
 		<dd>turns on Lynx trace mode.  If a Lynx Trace Log
 		    (<em>Lynx.trace</em> in the home directory) has
-		    been started for the current session, all trace and
-		    other stderr messages are written to that log, and
+		    been started for the current session, all trace
+		    messages are written to that log, and
 		    can be examined during the session via the TRACE_LOG
-		    (normally, '<em>;</em>') command.
+		    (normally, '<em>;</em>') command.  If no Trace Log
+		    file is in use, trace messages go to stderr.
 	     <dt><code>-traversal</code>
 		<dd>traverse all http links derived from startfile.  When
 		    used with <em>-crawl</em>, each link that begins with the
@@ -2418,11 +2494,27 @@ where
 		    indexing.  See CRAWL.announce for more information.
 	     <dt><code>-underscore</code>
 		<dd>toggles use of _underline_ format in dumps.
-	     <dt><code>-useragent=Name</code>
-	       <dd>set alternate Lynx User-Agent header.
+	     <dt><code>-useragent=NAME</code>
+	       <dd>set different Lynx User-Agent header.
+	     <dt><code>-use_mouse</code>
+	       <dd>turn on mouse support, if available.
 	     <dt><code>-validate</code>
-		<dd>accept only http URLs (for validation).  Complete
-		    security restrictions also are implemented.
+		<dd>accept only http URLs (meant for validation).
+		<dd>This flag implies security restrictions
+		    generally more severe than <em>-anonymous</em>:
+		    restriction options as for
+		    <em>-restrictions=all</em>, with the notable
+		    exception that goto remains enabled for
+		    http and https URLs; in addition,
+		    the PRINT and DOWNLOAD commands are completely
+		    disabled, and use of a Trace Log file is
+		    forced off.
+		<dd>Any relaxing of restriction that might be implied
+		    by an also present (or implied) <em>-anonymous</em>
+		    flag is overridden, the only way to possibly relax
+		    <em>some</em> of the restrictions to the level
+		    applicable for "anononymous" accounts is with an
+		    explicit <em>-restrictions=default</em>.
 	     <dt><code>-verbose</code>
 		<dd>toggles [LINK], [IMAGE] and [INLINE] comments
 		    with filenames of these images.
diff --git a/lynx_help/help_files.txt b/lynx_help/help_files.txt
index c88cbb61..39214ea0 100644
--- a/lynx_help/help_files.txt
+++ b/lynx_help/help_files.txt
@@ -12,6 +12,7 @@
 #
 ABOUT_LYNX=about_lynx.html
 ALT_EDIT_HELP=alt_edit_help.html
+BASHLIKE_EDIT_HELP=bashlike_edit_help.html
 BOOKMARK_HELP=bookmark_help.html
 COOKIE_HELP=cookie_help.html
 DIRED_HELP=dired_help.html
diff --git a/lynx_help/keystrokes/alt_edit_help.html b/lynx_help/keystrokes/alt_edit_help.html
index bd79c6e8..8b2e65a9 100644
--- a/lynx_help/keystrokes/alt_edit_help.html
+++ b/lynx_help/keystrokes/alt_edit_help.html
@@ -1,24 +1,27 @@
 <!DOCTYPE html public "-//IETF//DTD HTML 3.0//EN">
 <html>
 <head>
-<title>Lynx Line Editor Alternate Key Binding</title>
+<title>Lynx Line Editor Alternative Key Binding</title>
 <link rev="made" href="mailto:lynx-dev@sig.net">
+<link rel="Sibling" title="Default Binding" href="edit_help.html">
+<link rel="Sibling" title="Bash-Like Binding" href="bashlike_edit_help.html">
 </head>
 <body>
-<h1>+++ALTERNATE BINDINGS+++</h1>
+<h1>+++ALTERNATIVE BINDING+++</h1>
 
 Lynx invokes a built-in <em>Line Editor</em> for entering strings in
 response to prompts, in forms, and for email messages if an external editor
-has not been defined.  Administrators can offer additional alternate key
-bindings by adding them in LYEditmap.c before compiling Lynx.  If available,
+has not been defined.  Administrators can offer additional alternative key
+bindings by configuring with --enable-alt-bindings or by adding them in
+LYEditmap.c before compiling Lynx.  If available,
 they may be selected via the 'o'ptions menu, or by editing lineedit_mode in
 the '.lynxrc' file.
 
-<p>Note: setting emacs/vi keys ON has no effect on line-editor bindings.
+<p>Note: setting emacs/vi keys ON has no direct effect on line-editor bindings.
 
-<p>This is the <em>Alternate Bindings</em> keymap:
+<p>This is the <em>Alternative Binding</em> keymap:
 
-<p><pre>
+<pre>
      ENTER  Input complete        -  RETURN
      TAB    Input complete        -  TAB, Do
      ABORT  Input cancelled       -  Ctrl-G, Ctrl-O, (Ctrl-C on some systems)
@@ -47,7 +50,8 @@ the '.lynxrc' file.
      means "to the immediate right of" an I-beam (between characters) type
      cursor.
 
-[2]  Follow Ctrl-V with the key "e" bound to the EDIT function,
+[2]  Follow Ctrl-V with the key "e" bound to the DWIMEDIT function,
+     or with some other key bound to EDITTEXTAREA or DWIMEDIT,
      to edit the form's textarea field using an external editor.
 </pre>
 </body>
diff --git a/lynx_help/keystrokes/bashlike_edit_help.html b/lynx_help/keystrokes/bashlike_edit_help.html
new file mode 100644
index 00000000..b451dc56
--- /dev/null
+++ b/lynx_help/keystrokes/bashlike_edit_help.html
@@ -0,0 +1,211 @@
+<!DOCTYPE html public "-//IETF//DTD HTML 3.0//EN">
+<html>
+<head>
+<title>Lynx Line Editor Bash-Like Key Binding</title>
+<link rev="made" href="mailto:lynx-dev@sig.net">
+<link rel="Sibling" title="Default Binding" href="edit_help.html">
+<link rel="Sibling" title="Alternative Binding" href="alt_edit_help.html">
+</head>
+<body>
+<h1>+++BASH-LIKE BINDING+++</h1>
+
+Lynx invokes a built-in <em>Line Editor</em> for entering strings in
+response to prompts, in forms, and for email messages if an external editor
+has not been defined.  Administrators can offer several sets of key
+bindings by configuring with --enable-alt-bindings or by adding them in
+LYEditmap.c before compiling Lynx.  If available,
+they may be selected via the 'o'ptions menu, or by editing lineedit_mode in
+the '.lynxrc' file.
+
+<p>Note: setting emacs/vi keys ON has no direct effect on line-editor bindings.
+
+<p>This is the <em>Bash-like Binding</em> keymap.</p>
+<h2>Basic commands</h2>
+<pre>
+     ENTER  Input complete        -  Enter, RETURN
+     TAB    Completion [2]/ Next  -  TAB, Do
+     ABORT  Cancel / Undo Change  -  C-g, C-_
+     ERASE  Erase the line        -  M-k, C-x k
+
+     BACK   Cursor back     char  -  Left-Arrow,  C-b
+     FORW   Cursor forward  char  -  Right-Arrow, C-f
+     BACKW  Cursor back     word  -  M-b, C-r
+     FORWW  Cursor forward  word  -  M-f, C-s [5]
+     BOL    Go to begin of  line  -  C-a, Home, Find
+     EOL    Go to end   of  line  -  C-e [4], End,  Select
+
+     DELP   Delete prev     char  -  C-h, Backspace, Rubout
+     DELN   Delete next [1] char  -  C-d, Delete, Remove
+     DELPW  Delete prev     word  -  C-w [3], M-Backspace, M-Delete (?)
+     DELNW  Delete next     word  -  M-d
+     DELBL  Delete to beg of line -  C-u
+     DELEL  Delete to end of line -  C-k [4]
+
+     UPPER  Upper case the line   -  M-u
+     LOWER  Lower case the line   -  M-l
+
+<!-- PASS!  Textarea external edit  - C-e C-e - mentioned in note [3] below
+                                    statusline shows binding where relevant
+     PASS!  Insert file in textarea - C-x i
+     PASS!  Grow textarea           - C-x g
+-->     LKCMD  Invoke cmd prompt     -  C-v [FORM]
+     SWMAP  Switch input keymap   -  C-^ (if compiled in)
+
+</pre>
+Here is a little textarea for practice:<BR>
+<FORM action=""><TEXTAREA name="practice" cols=40 ROWS=5>
+This text cannot be submitted.  Normally lines like
+these would be part of a form that is filled out and
+then submitted.  You can move around here and delete
+or add text as you like, using the Line-Editor keys.
+</TEXTAREA><INPUT TYPE=reset VALUE="[reset content]"></FORM>
+<pre>
+
+Advanced emacs-like commands:
+
+    TPOS    Transpose characters                   -  C-t
+    SETMARK Set mark at current position in line   -  C-@
+    XPMARK  Exchange current position with mark    -  C-x C-x
+    KILLREG Kill region between mark and position  -  C-x C-w [3]
+    YANK    Insert text last killed (with KILLREG) -  C-y
+</pre>
+<h2>Notes</h2>
+<P><tt>
+     <DFN>C-</DFN><strong>key</strong> means Control+<strong><kbd>key</kbd></strong>.  <DFN
+     ><tt>C-x </tt></DFN><strong>key</strong> means first Control+<kbd>x</kbd>, then
+     <strong><kbd>key</kbd></strong>.
+                                                                       <DFN
+                        >M-</DFN>key means Meta+<strong><kbd>key</kbd></strong>, where Meta
+     is a modifier that can be entered in a variety of ways:
+</tt></P><UL>
+<LI>First ESC, then the <strong><kbd>key</kbd></strong>.
+    This doesn't work with all systems or on all connections, and if it
+    does may not work for some keys (because the ESC character is also
+    part of code sequences for "normal" function keys).
+<LI>Alt+<strong><kbd>key</kbd></strong>.
+    This works if the terminal, console, or comm program is set up to
+    interpret Alt as a modifier to send ESC.  The Linux console acts
+    like that by default for most keys;  Kermit can be set up to do it,
+    xterm can be for some keys, and so on.  But the same caveats as for
+    the previous item apply.
+    This Alt mapping may also be possible, independent of the ESC character,
+    for some keys in Lynx for DOS/i386 or for Win32.
+<LI>C-x <strong><kbd>key</kbd></strong>.
+    Actually, currently the same internal table is used for Meta and the
+    C-x prefix.  Therefore all M-<strong><kbd>key</kbd></strong> combinations can
+    also be typed as C-x <strong><kbd>key</kbd></strong>, and vice versa.
+</UL><pre>
+[1] "next" means the character "under" a box or underline style cursor; it
+    means "to the immediate right of" an I-beam (between characters) type
+    cursor.
+[2] For entering strings in response to prompts (that is, when not editing
+    form text fields), some keys have different actions: TAB tries to
+    complete input based on previous response; Up-Arrow and Down-Arrow
+    may offer previous response and next response, respectively, from
+    recall buffer for some prompts.
+[3] C-w can only be used for editing functions if its default KEYMAP
+    to REFRESH is changed.  This can be done in the lynx.cfg file,
+    for example with the line "KEYMAP:^W:DO_NOTHING".  This also aplies
+    for other keys: as long as the key's action is mapped to REFRESH,
+    either with an explicit KEYMAP in lynx.cfg or by default, the
+    key's Line Editor binding is disabled.
+[4] These keys invoke special behavior when pressed twice in a row:
+    C-e C-e calls the external editor for changing the text in a
+    textarea (if available).  C-k C-k will move to the next link,
+    so that all lines in a textarea can be conveniently cleared by
+    repeating C-k.
+[5] Key is likely unavailable for Lynx, because it is interpreted by
+    operating system, comm program, or curses library, or swallowed
+    as part of escape sequence recognition.  Binding is provided for
+    the benefit of those where this doesn't apply.
+[FORM] In form text fields, only.  Ignored by Line Editor elsewhere.
+
+
+More notes
+
+   When a text input field, including a textarea line, is selected,
+   the Line Editor functions get a first grab at the keys entered.
+   If a key has no function defined in the Line Editor binding, it
+   can either be ignored, or passed on for normal key command handling,
+   where modifiers like C-x or Meta currently have no effect (see the
+   <A HREF="LYNXKEYMAP:"
+   >Key Map Page</A> accessible with the key <kbd>K</kbd> for current information).
+
+
+</pre>
+<h2>Additional details on other keys, for the curious
+(very much subject to change)</h2>
+<pre>
+Normal key action when used in form fields, subject to remapping
+with KEYMAP: [FORM (except Up-Arrow, Down-Arrow)]
+            C-l [3], C-o, C-z [5], C-\ [5], C-] [5]
+            C-n [emacskey], C-p [emacskey]
+            Up-Arrow [2], Down-Arrow [2]
+            Page-Up, Page-Down, F1, Back-Tab
+
+Normal key command with Meta modifier ignored when used in form fields,
+subject to remapping with KEYMAP: [FORM (except Up-Arrow, Down-Arrow)]
+            M-C-l [3], M-C-o [!], M-C-z [5], M-C-\ [5], M-C-] [5]
+            M-C-u, M-/, M-n
+            M-Up-Arrow [2][!], M-Down-Arrow [2][!]
+            M-Page-Up [!], M-Page-Down [!], M-Home, M-End
+
+Passed as specific command:
+                     lynx action    duplicates by default
+                     -----------    ---------------------
+            M-C-d    NEXT_LINK      Down-Arrow
+            M-C-e    EDITTEXTAREA   C-e C-e
+            M-C-k    LPOS_NEXT_LINK (none, Down-Arrow suggested)
+            M-e      EDITTEXTAREA   C-e C-e
+            M-g      GROWTEXTAREA   (none, C-v $ suggested?)
+            M-i      INSERTFILE     (none, C-v # suggested?)
+            M-F1     DWIMHELP       (none, F1 suggested)
+            M-Find   WHEREIS        C-v /
+            M-Select NEXT           C-v n
+
+Duplicates function of other key(s):
+                     edit action    duplicates
+                     -----------    ----------
+            M-C-b    BACKW          M-b, C-r
+            M-C-f    FORWW          M-f
+            M-C-n    FORWW          M-f
+            M-C-p    BACKW          M-b, C-r
+            M-C-r    BACKW          M-b, C-r
+            M-a      BOL            C-a, Home, ...
+
+Modifier ignored, and duplicates function of other key(s):
+                     edit action    duplicates
+                     -----------    ----------
+            M-C-a    BOL            C-a, Home, ...
+            M-C-g    ABORT          C-g, ...
+            M-TAB    TAB            C-i [!]
+            M-C-j    ENTER          C-m, C-j, Enter / RETURN
+            M-RETURN ENTER          C-m, C-j, Enter / RETURN
+            M-C-y    YANK           C-y [!]
+            M-C-^    SWMAP          C-^ [!] (if compiled in)
+       M-Right-Arrow FORW           Right-Arrow [!], C-f
+        M-Left-Arrow BACK           Left-Arrow [!],  C-b
+            M-Do     TAB            C-i [!]
+
+Key completely ignored:
+            C-q, Insert
+            M-C-q, M-C-s [5], M-C-t, M-C-v, M-ESC
+            M-C-@, M-C-_, M-Remove, M-Insert [!]
+
+Meta + other (mostly, printable character) keys:
+              Modifier ignored, or sequence swallowed (see [5]).
+            M-@, M-E...M-Z [5], M-\, M-^, M-_ attempt to interpret
+              as 7-bit escape representation for character in 8-bit
+	      control (C1) range if appropriate according to
+	      Display Character Set.
+
+
+[emacskey] Normal key action subject to emacs_keys setting.
+[!] Action of key with Meta modifier follows action of key without
+    Meta.  If you manage to enter the Meta key while Line-Editor
+    Binding is not set to Bash-Like, and the unmodified binding
+    is different from that listed here, M-&lt;<var>key</var>&gt; will act
+    like &lt;<var>key</var>&gt;.
+</pre>
+</body>
+</html>
diff --git a/lynx_help/keystrokes/edit_help.html b/lynx_help/keystrokes/edit_help.html
index 92008a63..e4148fca 100644
--- a/lynx_help/keystrokes/edit_help.html
+++ b/lynx_help/keystrokes/edit_help.html
@@ -9,19 +9,21 @@
 
 Lynx invokes a built-in <em>Line Editor</em> for entering strings in
 response to prompts, in forms, and for email messages if an external editor
-has not been defined.  Administrators can offer alternate key bindings
-by adding them in LYEditmap.c before compiling Lynx.  If available, they may
+has not been defined.  Administrators can offer alternative key bindings
+by configuring with --enable-alt-bindings or by adding them in LYEditmap.c
+before compiling Lynx.  If available, they may
 be selected via the 'o'ptions menu, or by editing lineedit_mode in the
 '.lynxrc' file.
 
-<p>One such alternate key binding, which may be available on your system,
-is the <A HREF="alt_edit_help.html">Alternate Bindings</A> keymap.
+<p>Two such alternative key bindings, which may be available on your system,
+are the <A HREF="alt_edit_help.html">Alternative Binding</A> keymap and the
+<A HREF="bashlike_edit_help.html">Bash-like Binding</A> keymap.
 
 <p>Note: setting emacs/vi keys ON has no effect on line-editor bindings.
 
 <p>This is the <em>Default Binding</em> keymap:
 
-<p><pre>
+<pre>
      ENTER  Input complete        -  RETURN
      TAB    Input complete        -  TAB, Do
      ABORT  Input cancelled       -  Ctrl-G, Ctrl-O, (Ctrl-C on some systems)
@@ -44,13 +46,14 @@ is the <A HREF="alt_edit_help.html">Alternate Bindings</A> keymap.
      LOWER  Lower case the line   -  Ctrl-K
 
      LKCMD  Invoke cmd prompt     -  Ctrl-V (in form text fields, only) [2]
-     SWMAP  Switch input keymap   -  Ctrl-^
+     SWMAP  Switch input keymap   -  Ctrl-^ (if compiled in)
 
 [1] "next" means the character "under" a box or underline style cursor; it
      means "to the immediate right of" an I-beam (between characters) type
      cursor.
 
-[2]  Follow Ctrl-V with the key "e" bound to the EDIT function,
+[2]  Follow Ctrl-V with the key "e" bound to the DWIMEDIT function,
+     or with some other key bound to EDITTEXTAREA or DWIMEDIT,
      to edit the form's textarea field using an external editor.
 </pre>
 </body>
diff --git a/lynx_help/keystrokes/keystroke_help.html b/lynx_help/keystrokes/keystroke_help.html
index aa7a3da1..5cf588a8 100644
--- a/lynx_help/keystrokes/keystroke_help.html
+++ b/lynx_help/keystrokes/keystroke_help.html
@@ -11,7 +11,7 @@
   >MOVEMENT</A>:    Down arrow     - Highlight next topic
                Up arrow       - Highlight previous topic
                Right arrow,   - Jump to highlighted topic
-               Return, Enter
+               Return, Enter       (follow selected link)
                Left arrow     - Return to previous topic
 
   <A HREF="scrolling_help.html"
@@ -32,8 +32,6 @@
   <A HREF="dired_help.html">DIRED</A>:       c	      -	Create a new file
 	       d	      -	Download selected file
 	       e	      - Edit selected file
-	       E	      - Edit the current link's URL (or ACTION) and
-                                use that as a goto URL.
 	       f	      - Show a full menu of options for current file
 	       m	      - Modify the name or location of selected file
 	       r              - Remove selected file
@@ -45,13 +43,15 @@
                c              - Send a comment to the document owner
                d              - Download the current link
 	       e	      - Edit the current file
+	       E	      - Edit the current link's URL (or ACTION) and
+                                use that as a goto URL.
                g              - Goto a user specified <a
 	       			href="../lynx_url_support.html">URL</a> or file
                G              - Edit the current document's URL and use that
                                 as a goto URL.
 	       i 	      - Show an index of documents
 	       j	      - Execute a jump operation
-	       k	      - Show a list of key mappings
+	       k	      - Show list of actual key mappings
 	       l	      - List references (links) in current document
                m              - Return to main screen
                o              - Set your <A HREF="option_help.html">options</A>
@@ -85,7 +85,7 @@
                CTRL-R         - Reload current file and refresh the screen
                CTRL-V         - Switch to <A HREF="option_help.html#tagsoup"
                                 >alternative parsing</A> of HTML documents
-               CTRL-W         - Refresh the screen
+               CTRL-L         - Refresh the screen
                CTRL-U         - Erase input line (<a href="edit_help.html"
 				>more input line commands</a>)
                CTRL-G         - Cancel input or transfer
diff --git a/makefile.in b/makefile.in
index d18c00c2..614b1690 100644
--- a/makefile.in
+++ b/makefile.in
@@ -326,7 +326,7 @@ FIX_SED = tr '=' '%'
 #FIX_SED = cat
 
 install-help : $(DOCDIR) $(HELPDIR)
-	(cd $(HELPDIR) && rm -rf *)
+	(cd $(HELPDIR) && WD=`pwd` && HEAD=`echo $$WD|sed -e 's@/lynx_help$$@@'` && test $$WD != $$HEAD && rm -rf *)
 	@echo Constructing sed-script
 	@ECHO_CC@sed	-e '/^#/d' -e '/^$$/d' \
 		-e 's%\(.*\)=\(.*\@.*\)$$%s=@\1@=\2=g%' \
@@ -414,14 +414,20 @@ install-lss : $(LIBDIR)
 	-mv -f $(LIBDIR)/lynx.lss $(LIBDIR)/lynx.oldlss
 	$(INSTALL_DATA) $(srcdir)/samples/lynx.lss $(LIBDIR)/lynx.lss
 
-uninstall:
+uninstall ::
 @MSG_DIR_MAKE@	cd po && $(MAKE) CC="$(CC)" uninstall
 	-rm -f $(BINDIR)/lynx$x
 	-rm -f $(MANDIR)/lynx.1
 	-rm -f $(LIBDIR)/lynx.cfg
 	-rm -f $(LIBDIR)/lynx.lss
-	-rm -rf $(HELPDIR)
-	-rm -rf $(DOCDIR)
+
+uninstall \
+uninstall-help ::
+	-test -d $(HELPDIR) && WD=`cd $(HELPDIR) && pwd` && HEAD=`echo $$WD|sed -e 's@/lynx_help$$@@'` && test $$WD != $$HEAD && rm -rf $(HELPDIR)
+
+uninstall \
+uninstall-doc ::
+	-test -d $(DOCDIR) && WD=`cd $(DOCDIR) && pwd` && HEAD=`echo $$WD|sed -e 's@/lynx_doc$$@@'` && test $$WD != $$HEAD && rm -rf $(DOCDIR)
 
 $(BINDIR) $(MANDIR) $(LIBDIR) $(HELPDIR) $(DOCDIR) :
 	$(srcdir)/mkdirs.sh $@
diff --git a/samples/cernrules.txt b/samples/cernrules.txt
index 1064e74e..f166e055 100644
--- a/samples/cernrules.txt
+++ b/samples/cernrules.txt
@@ -10,10 +10,29 @@
 #
 # Syntax:
 # =======
+# Summary of common forms:
+#
+#   Fail           URL1
+#   Map            URL1  URL2      [CONDITION]
+#   Pass           URL1  [URL2]    [CONDITION]
+#   Redirect       URL1  URL2      [CONDITION]
+#   RedirectPerm   URL1  URL2      [CONDITION]
+#   UseProxy       URL1  PROXYURL  [CONDITION]
+#   UseProxy       URL1  "none"    [CONDITION]
+#
+#   Alert          URL1  MESSAGE   [CONDITION]
+#   AlwaysAlert    URL1  MESSAGE   [CONDITION]
+#   UserMsg        URL1  MESSAGE   [CONDITION]
+#   InfoMsg        URL1  MESSAGE   [CONDITION]
+#   Progress       URL1  MESSAGE   [CONDITION]
+#
 # As you may have guessed, comments are introduced by a '#' character.
 # Rules have the general form
-#   Operator  Operand1  [Operand2]
-# with words separated by whitespace.
+#   Operator  Operand1  [Operand2]  [CONDITION]
+# with words separated by whitespace.  Words containing space can be quoted
+# with "double quotes".  Although normally this should not be necessary
+# necessary for URLs, it has to be used for MESSAGE Operands in Alert etc.
+# See below for an explanation of the optional CONDITION.
 #
 # Recognized operators are
 #
@@ -21,17 +40,94 @@
 # Reject access to this URL, stop processing further rules.
 #
 #   Map   URL1  URL2
-# Change the URL to URL2, then continue processing.
+# Change the current URL to URL2, then continue processing.
 #
 #   Pass  URL1  [URL2]
 # Accept this URL and stop processing further rules; if URL2
 # is given, apply this as the last mapping.
+# See the next item for reasons why you generally don't want to "pass"
+# a changed URL.
+#
+#   RedirectTemp       URL1  URL2
+#   RedirectPerm       URL1  URL2
+#   Redirect [STATUS]  URL1  URL2
+# Stop processing further rules and redirect to URL2, just as if lynx had
+# received a HTTP redirection with URL2 as the new location.  This means that
+# URL2 is subject to any applicable permission checking, if it passes a new
+# request will be issued (which may result in a new round of rules checking,
+# with a new "current URL") or the new URL might be taken from the cache, and,
+# after successful loading, lynx's idea of what the loaded document's URL is
+# will be fully updated.  All this does not happen if you just "pass" a changed
+# URL (or let it fall through), so this is generally the preferred way for
+# substituting URLs. 
+# If the RedirectPerm variant is used, or if the optional word is supplied and
+# is either "permanent" or "301", act as if lynx had received a permanent
+# redirection (with HTTP status 301).  In most cases this will not make a
+# noticeable difference.  Lynx may cache the location in a special way for 301
+# redirections, so that the redirection is followed immediately the next time
+# the same original URL is accessed, without re-checking of rules.  Therefore
+# the permanent variant should never be used if the desired outcome of rules
+# processing depends on variable conditions (see CONDITIONS below) or on
+# setting a special flag (see next item).
+#
+#   PermitRedirection  URL1
+# Mark following redirection as permitted, and continue processing.  Some
+# redirection locations are normally not allowed, because permitting them in a
+# response from an arbitrary remote server would open a security hole, and
+# others are not allowed if certain restrictions options are in effect.  Among
+# redirection locations normally always forbidden are lynxprog:  and lynxexec: 
+# schemes.  With "default" anonymous restrictions in effect, many URL schemes
+# are disallowed if the user would not be allowed to use them with 'g'oto. 
+# This rule allows to override the permission checking if rules processing ends
+# with a Redirect (including the RedirectPerm or RedirectTemp forms).  It is
+# ignored otherwise, in particular, it does not influence acceptance if rules
+# processing ends with a "Pass" and a real redirection is received in the
+# subsequent HTTP request.  If redirections are chained, it only applies to the
+# redirection that ends the same rules cycle.  Note that the new URL is still
+# subject to other permission checks that are not specific to redirections; but
+# using this rule may still weaken the expected effect of -anonymous,
+# -validate, -realm, and other restriction options, including TRUSTED_EXEC and
+# similar in lynx.cfg, so be careful where you redirect to if restrictions are
+# important!
 #
-# Rules are processed sequentially first to last, a rule applies
-# if the current URL (for the resource the user is trying to access)
-# matches URL1.  case-sensitive (!) string comparison is used, in addition
-# URL1 can contain one '*' which is interpreted as a wildcard matching
-# 0 or more characters.  So if for example
+#   UseProxy  URL1  PROXYURL
+# Stop processing further rules, and force access through the proxy given by
+# PROXYURL.  PROXYURL should have the same form as required for foo_proxy
+# environment variables and lynx.cfg options, i.e., (unless you are trying to
+# do something unusual) "http://some.proxy-server.dom:port/".  This rule
+# overrides any use of a proxy (or external gateway) that might otherwise apply
+# because of environment variables or lynx.cfg options, it also overrides any
+# "no_proxy" settings.
+#
+#   UseProxy  URL1  none
+# Mark request as NOT using any proxy (or external gateway), and continue
+# processing(!).  For a request marked this way, any subsequent UseProxy
+# rule with a PROXYURL will be ignored, and any use of a proxy (or external
+# gateway) that might otherwise apply because of environment variables or
+# lynx.cfg options will be overridden.  Note that the marking will not
+# survive a Redirect rule (since that will result, if successful, in a
+# new request).
+#
+#   Alert         URL1  MESSAGE
+#   AlwaysAlert   URL1  MESSAGE
+#   UserMsg       URL1  MESSAGE
+#   InfoMsg       URL1  MESSAGE
+#   Progress      URL1  MESSAGE
+# These produce various kinds of statusline messages, differing in whether
+# a pause is enforced and in its duration, immediately when the rule is
+# applied.  AlwaysAlert shows the message text even in non-interactive mode
+# (-dump, -source, etc.).  Rule processing continues after the message is
+# shown.  As usual, these rules only apply if URL1 matches.  MESSAGE is
+# the text to be displayed, it can contain one occurrence of "%s" which
+# will be replaced by the current URL, literal '%' characters should be
+# doubled as "%%".
+#
+# Rules are processed sequentially first to last for each request, a rule
+# applies if the current URL matches URL1.  The current URL is initally the
+# URL for the resource the user is trying to access, but may change as the
+# result of applied Map rules.  case-sensitive (!) string comparison is used,
+# in addition URL1 can contain one '*' which is interpreted as a wildcard
+# matching 0 or more characters.  So if for example
 # "http://example.com/dir/doc.html" is requested, it would matches any of
 # the following:
 #   Pass  http:*
@@ -56,14 +152,74 @@
 # not in the machine's native representation for filenames.
 #
 # Anyone with experience configuring the venerable CERN httpd server will
-# recognize the syntax - in fact, the code implementing rules goes back
-# to a common ancestor.  But note the differences: all URLs and URL-
+# recognize some of the syntax - in fact, the code implementing rules goes
+# back to a common ancestor.  But note the differences: all URLs and URL-
 # patterns here have to be given as absolute URLs, even for local files.
-# (Absolute URLs don't imply proxying - you cannot control that from here.)
+# (Absolute URLs don't imply proxying.)
+#
+# CONDITIONS
+# ----------
+# All rules mentioned can be followed by an optional CONDITION, which can
+# be used to further restrict when the rule should be applied (in addition
+# to the match on URL1).  A CONDITION takes one of the forms
+#   "if"     CONDITIONFLAG
+#   "unless" CONDITIONFLAG
+# and currently two condition flags are recognized:
+#   "userspecified"   (or abbreviated "userspec")
+#   "redirected"
+# To explain these, first some terms need to be defined.  A "request"
+# is...
+# 
+# A user action (like following a link, or entering a 'g'oto URL) can either be
+# rejected immediately (for example, because of restrictions in effect, or
+# because of invalid input), or can generate a "request".  For the purpose of
+# this discussion, a "request" is the sequence of processing done by lynx,
+# which might ultimately lead to an actual network request and loading and
+# display of data; a request can also result in rejection (for example, some
+# restrictions are checked at this stage), or in a redirection.  A redirection
+# in turn can be rejected (which makes the request fail), or can automatically
+# generate a new request.  A "request chain" is the sequence of one or more
+# requests triggered by the same user event that are chained together by
+# redirections.
+# For each request, some URL schemes are handled (or rejected) specially, see
+# Limitation 1 below, the others are passed to the generic access code.  Rules
+# processing occurs at the beginning of the generic access code, before a
+# request is dispatched to the scheme-specific protocol module (but after
+# checking whether the request can be satisfied by re-displaying an already
+# cached document).
+# With these definitions, the meaning of the possible CONDITIONFLAGS:
+# 
+#   if redirected
+# The rule applies if the current request results from a redirection;
+# whether that was a real HTTP redirection or one generated by a rule
+# in the previous request makes no difference.  In other words, the
+# condition is true if the current request is not the first one in the
+# request chain.
+#
+#   if userspecified
+# The rule applies if the initial URL of the request chain was specified
+# by the user.  Lynx marks a request as "user specified" for URLs that
+# come from 'g'oto prompts, as well as for following links in a bookmark
+# or Jump file and some other special (lynx-generated) pages that may
+# contain URLs that were typed in by the user.
+# Note that this is not a property of the request, but of the whole request
+# chain (based on where the first request's URL came from).  The current
+# URL may differ from what the user typed
+# - because of initial fixups, including conversion of Guess-URLs and file
+#   paths to full URLs,
+# - because of Map rules applied, and/or
+# - because of a previous redirection.
+# So to make reasonably sure a suspicious or potentially dangerous URL has
+# been entered by the user, i.e. is not a link or external redirection
+# location that cannot be trusted, a combination of "userspecified" and
+# "redirected" flags should be used, for example
+#   Fail URL1 unless userspecified
+#   Fail URL1 if redirected
+#   ...
 #
 # CAVEAT
 # ======
-# First, to squash any false expectations, and example for what NOT TO DO.
+# First, to squash any false expectations, an example for what NOT TO DO.
 # It might be expected that a rule like
 #   Fail  file://localhost/etc/passwd		# <- DON'T RELY ON THIS
 # could be used to prevent access to the file "/etc/passwd".  This might
@@ -105,15 +261,13 @@
 #
 # You could also direct access for a scheme to a brief text explaining
 # why it's not available:
-#   Map news:*   http://localhost/texts/newsserver-is-broken.html
-# (That text shouldn't contain any relative links, they would be
-# broken.)
+#   Redirect news:*   http://localhost/texts/newsserver-is-broken.html
 #
 # 2. Preventing accidental access
 # -------------------------------
 # If there is a page or site you don't want to access for whatever
 # reason (say there's a link to it that crashes Lynx [don't forget to
-# report a bug], or it that starts sending you a 5 Mb file you don't
+# report a bug], or if that starts sending you a 5 Mb file you don't
 # want, or you just don't like the people...), you can prevent yourself
 # from accidentally accessing it:
 #    Fail  http://bad.site.com/*
@@ -126,6 +280,8 @@
 # following kind of rule will alow you to navigate, invisibly accessing
 # the compressed files:
 #   Map file://localhost/somedir/*.html file://localhost/somedir/*.html.gz
+# or, perhaps better:
+#   Redirect file://localhost/somedir/*.html file://localhost/somedir/*.html.gz
 #
 # 4. Use local copies
 # -------------------
@@ -137,6 +293,12 @@
 # Or even combine this with compressing the files:
 #  Map http://remote.com/docs/*.html file://localhost/home/me/docs/*.html.gz
 #
+# Again, replacing the "Map" with "Redirect" is probably better - it will
+# allow you to see the _real_ location on the lynx INFO screen or in the
+# HISTORY list, will avoid duplicates in the cache if the same document is
+# loaded with two different URLs, and may allow you to 'e'dit the local
+# from within lynx if you feel like it.
+#
 # 5. Broken links etc.
 # --------------------
 # A user has moved from http://www.siteA.com/~jdoe to http://siteB.org/john,
@@ -147,10 +309,13 @@
 # which you're tired of seeing.  This will not fix your bookmarks, and
 # it will let you see the outdated URLs for longer (Limitation 3 below),
 # but for a quick fix:
-#   Map   http://www.siteA.com/~jdoe/*      http://siteB.org/john/*
-#   Map   http://www.provider.com/company/* http://www.company.com/*
-# But note that you are likely to create invalid links if not all documents
-# from a site are mapped (Limitation 3).
+#   Redirect   http://www.siteA.com/~jdoe/*      http://siteB.org/john/*
+#   Redirect   http://www.provider.com/company/* http://www.company.com/*
+#
+# You could use "Map" instead of "Redirect", but this would let you see the
+# outdated URLs for longer and even bookmark them, and you are likely to
+# create invalid links if not all documents from a site are mapped
+# (Limitation 3).
 #
 # 6. DNS troubles
 # ---------------
@@ -168,10 +333,202 @@
 #   Map   http://www.w3.org/*    http://www12.w3.org/*
 #
 # Note that this can break access to some name-based virtually hosted sites.
-
-
-# Limitations
-# ===========
+#
+# In this case use of "Map" is probably preferred over "Redirect", as long
+# as the URL on the left side contains the real and preferred hostname or
+# the problem is only temporary.
+#
+# 7. Avoid redirections
+# ---------------------
+# Some sites have a habit to provide links that don't go to the destination
+# directly but always force redirection via some intermediate URL.  The
+# delay imposed by this, especially for users with slower connections and
+# for overloaded servers, can be avoided if the intermediate URLs always
+# follow som simple pattern: we can then anticipate the redirect that will
+# inevitably follow and generate it internally.  For example,
+#   Redirect http://lwn.net/cgi-bin/vr/*    http://*
+#
+# Warning: The page authors may not like this circumvention.  Often the
+# redirection is wanted by them to track access, sometimes in connection
+# with cookies.  Some sites may employ mechanisms that defeat the shortcut.
+# It is your responsibility to decide whether use of this feature is
+# acceptable.  (But note that the same effect can be achieved anyway for
+# any link by editing the URL, e.g. with the ELGOTO ('E') key in Lynx, so
+# a shortcut like this does not create some new kind of intrusion.)
+#
+# 8. Detailed proxy selection
+# ---------------------------
+# Basic use for this one should be obvious, if you have a need for it.
+# It simply allows selecting use (or non-use) of proxies on a more detailed
+# level than the traditional <scheme>_proxy and no_proxy variables, as well
+# as using different proxies for different sites.
+# For example, to request access through an anonymizing proxy for all pages
+# on a "suspicious" site:
+#   UseProxy  http://suspicious.site/*  http://anonymyzing.proxy.dom/
+# (as long as all URLs really have a matching form, not some alternative
+# like <http://suspicious.site:80/> or <http://SuSpIcIoUs.site/>!)
+#
+# To access some site through a local squid proxy, running on the same host
+# as lynx, except for some image types (say because you rarely access images
+# with lynx anyway, and if you do, you don't want them cached by the proxy):
+#   UseProxy  http://some.site/*.gif  none
+#   UseProxy  http://some.site/*.jpg  none
+#   UseProxy  http://some.site/*      http://localhost:3128/
+# Note that order is important here.
+#
+# To exempt a local address from all proxying:
+#   UseProxy  http://local.site/*  none
+#
+# Note however that for some purposes the "no_proxy" setting may be better
+# suited than "UseProxy ... none", because of its different matching logic
+# (see comments in lynx.cfg).
+#
+# 9. Invent your own scheme
+# -------------------------
+# Suppose you want to teach lynx to handle a completely new URL scheme.
+# If what's required for the new scheme is already available in lynx in
+# _some_ way, this may be possible with some inventive use of rules.
+# As an example, let's assume you want to introduce a simple "man:" scheme
+# for showing manual pages, so (for a Unix-like system, at least) "man:lynx"
+# would display the same help information as the "man lynx" command and so
+# on (we ignore section numbers etc. for simplicity here).
+# First, since lynx doesn't know anything about a "man:" scheme, it will
+# normally reject any such URLs at an early stage.  However, a trick exists
+# to bypass that hurdle: define a man_proxy environment variable *outside of
+# lynx, before starting lynx* (it won't work in lynx.cfg), the actual value
+# is unimportant and won't actually be used.  For example, in your shell:
+#   export man_proxy=X
+#
+# If you already have some kind of HTTP-accessible man gateway available,
+# the task then probably just amounts to transforming the URL into the right
+# form.  For one such gateway (in this case, a CGI script running on the
+# local machine), the rule
+#   Redirect man:* http://localhost/cgi-bin/dwww?type=runman&location=*/
+# or, alternatively,
+#   UseProxy man:* none
+#   Map      man:* http://localhost/cgi-bin/dwww?type=runman&location=*/
+# does it, for other setups the right-hand side just has to be modified
+# appropriately.  The "UseProxy" is to make sure the bogus man_proxy gets
+# ignored.
+#
+# If no CGI-like access is available, you might want to invoke your system's
+# man command directly for a man: URL.  Here is some discussion of how this
+# could be done, and why ultimately you may not want to do it; this is also
+# an opportunity to show examples for how some of the rules and conditions
+# can be used that haven't been discussed in detail elsewhere.
+# Lynx provides the lynxexec: (and the similar lynxprog:) scheme for running
+# (nearly) arbitrary commands locally.  At the heart of employing it for
+# man: would be a rule like this:
+#   Redirect          man:*  "lynxexec:/usr/bin/man *"
+# (It is a peculiarity of this scheme that the literal space and quoting
+# are necessary here.  Also note that Map cannot be used here instead of
+# Redirect, since lynxexec, as a special kind of URL, needs to be handled
+# "early" in a request.)
+# Of course, execution of arbitrary commands is a potentially dangerous
+# thing.  lynxexec has to be specifically enabled at compile time and in
+# lynx.cfg (or with command line options), and there are various levels
+# of control, too much to go into here.  It is assumed in the following that
+# lynxexec has been enabled to the degree necessary (allow /usr/bin/man
+# execution) but hopefully not too much.
+# What needs to be prevented is that allowing local execution of the man
+# command might unintentionally open up unwanted execution of other commands,
+# possibly by some trick that could be exploited.  For example, redirecting
+# man:* as above, the URL "man:lynx;rm -r *" could result in the command
+# "man lynx;rm -r *" executed by the system, with obvious disastrous results.
+# (This particular example won't actually work, for several reasons; but
+# for the purpose of discussion let's assume it did, there may be similar
+# ones that do.)
+# Because of such dangers, redirection to a lynxexec: is normally never
+# accepted by lynx.  We need at least a PermitRedirection rule to override
+# this protective limitation:
+#   PermitRedirection man:*
+#   Redirect          man:*  "lynxexec:/usr/bin/man *"
+# But now we have potentially opened up local execution more than is
+# acceptable via the man: scheme, so this needs to be examined.
+# There are two aspects to security here: (1) restricting the user, and (2)
+# protecting the user.  The first could also be phrased as protecting the
+# system from the user; the second as preventing lynx (and the system) from
+# doing things the user doesn't really want.  Aspect (1) is very important
+# for setups providing anonymous guest accounts and similarly restricted
+# environments.  (Otherwise shell access is normally allowed, and trying to
+# protect the system in lynx would be rather pointless.)  As far as access
+# to some URLs is concerned, the difference can be characterized in terms of
+# which sources  of URLs are trusted enough to allow access: for (1), only
+# links occurring in a limited number of documents are trusted enough for
+# some (or all) URLs, user input at 'g'oto prompts and the like is not (if
+# not completely disabled).  For (2) and assuming a user with normal shell
+# privileges, the user may be trusted enough to accept any URL explicitly
+# entered, but URLs from arbitrary external sources are not - someone might
+# try to use them to trick the user (by following an innocent-looking link)
+# or lynx (by following a redirection) into doing something undesirable.
+#
+# In the following we are concerned with (2); it is assumed that providers
+# of anonymous accounts would not want to follow this path, and would have
+# no need for additional schemes that imply local execution anyway.  (For
+# one thing, with the man example they would have to carefully check that
+# users cannot break out of the man command to a local shell prompt.)
+#
+# Getting back to the example, it was already mentioned that lynx does not
+# allow redirections to lynxexec.  In fact this continues to be disallowed
+# for real redirection received from HTTP servers.  But we have introduced
+# a new man: scheme, and the lynx code that does the redirection checking
+# doesn't know anything about special considerations for man: URLs, so
+# an external HTTP server might send a redirection message with "Location:
+# man:<something>", which lynx would allow, and which would in turn be
+# redirected by our rule to "lynxexec:/usr/bin/man <something>".  Unless
+# we are 100% sure that either this can never happen or that the lynxexec
+# URL resulting from this can have no harmful effect, this needs to be
+# prevented.  It can be done by checking for the "redirected" condition,
+# either by putting something like (the first line is of course optional)
+#   Alert  man:*  "Redirection to man: not allowed" if redirected
+#   Fail   man:*                                    if redirected
+# somewhere before the Redirect rule, or, reversing the logic, by adding
+# a condition to the redirection rules, i.e. they become
+#   PermitRedirection man:*                             unless redirected
+#   Redirect          man:*  "lynxexec:/usr/bin/man *"  unless redirected
+# (actually, putting the condition on either one of the rules would be
+# sufficient).  The second variant assumes that the attempted access to
+# man: via redirection will ultimately fail because there is no other way
+# to handle such URLs.
+#
+# The above should take care of rejecting man: URLs from redirections, but
+# what about regular links in HTML (like <A HREF="man:...">)?  As long as
+# it can be assumed that the user will always inspect each and every link
+# before following it, and never follow a link that can have harmful effect,
+# no further restrictions are necessary.  But this is a very big assumption,
+# unrealistic except perhaps in some single-user setups where the user is
+# is identical with the rule writer.  So normally most links have to be
+# regarded as suspect, and only URLs entered by the user can be accepted:
+#   Alert  man:*  "Redirection to man: not allowed" if redirected
+#   Fail   man:*                                    if redirected
+#   Alert  man:*  "Link to man: not allowed"        unless userspecified
+#   Fail   man:*                                    unless userspecified
+#
+# With these restrictions we have limited the ways our new man: scheme can
+# be used rather severely, to the point where its usefulness is questionable.
+# In addition to 'g'oto prompts, it may work in Jump files; also, should
+# links to man:<something> appear in HTML text, the user could retype them
+# manually or use the ELGOTO ('E') command with some trivial editing (like
+# adding a space) to "confirm" the URL.  Even if the precautions outlined
+# above are followed: THIS TEXT DOESN NOT IMPLY ANY PROMISE THAT, BY FOLLOWING
+# THE EXAMPLES, LYNX WILL BE SAFE.  On the other hand, some of the precautions
+# *may* not be necessary: it is possible that careful use of TRUSTED_EXEC
+# options in lynx.cfg could offer enough protection while making the new
+# scheme more useful.
+#
+# If all this seems a bit too scary, that's intentional; it should be noted
+# that these considerations are not in general necessary for "harmless" URL
+# schemes, but appropriate for this "extreme" example.  One last remark
+# regarding the hypothetical man scheme: instead of implementing it through
+# "lynxexec:" or "lynxprog:", it would be somewhat safer to use "lynxcgi:"
+# instead if it is supported.  A simple lynxcgi script would have to write
+# the man page to stdout (either converted to text/html or as plain text,
+# preceded by an appropriate Content-Type header line), and all necessary
+# checking for special shell characters would be done within the script -
+# lynx does not use the system() function to run the script.
+#
+# Other Limitations
+# =================
 # First, see CAVEAT above.  There are other limitations:
 #
 # 1. Applicable URL schemes
@@ -179,11 +536,15 @@
 # Rules processing does not apply to all URL schemes.  Some are
 # handled differently from the generic access code, therefore rules
 # for such URLs will never be "seen".  This limitation applies at
-# least to lynxexec:, lynxprog:, mailto:, and LYNXHIST: URLs.
+# least to lynxexec:, lynxprog:, mailto:, LYNXHIST:, LYNXMESSAGES:,
+# LYNXCFG:, and LYNXCOMPILEOPTS: URLs.  You shouldn't be tempted
+# to try to redirect most of these schemes anyway, but this also
+# makes it impossible to disable them with "Fail" rules.
 #
 # Also, a scheme has to be known to Lynx in order to get as far as
 # applying rules - you cannot just define your own new foobar: scheme
-# and then map it to something here.
+# and then map it to something here, but see Application 9, above,
+# for a workaround.
 #
 # 2. No re-checking
 # -----------------
@@ -193,6 +554,8 @@
 # it allows specific exceptions.  Of course it means that users for
 # whom any restrictions must be enforced cannot have write access to a
 # personal rules file, but that should be obvious anyway!
+# This limitiation does not applies if "Redirect" is used, in that case
+# the new URL will always be re-examined.
 #
 # 3. Mappings are invisible
 # -------------------------
@@ -209,6 +572,10 @@
 # since they are taken to be relative to the "Document URL" (if no BASE tag
 # is present) when the HTML is parsed.
 #
+# This limitation does not apply if "Redirect" is used - the new location
+# will be visible to the user, and will be used by lynx for resolving
+# relative URLs within the document.
+#
 # 4. Interaction with proxying
 # ----------------------------
 # Rules processing is done after most other access checks, but before
@@ -224,3 +591,50 @@
 # don't do that"; in some cases setting the no_proxy variable will help.
 # Example 3 happens to work nicely if there is a http_proxy but no
 # ftp_proxy.
+#
+# This limitation does not come into play if a "UseProxy" rule is applied,
+# in either of its two forms: with a PROXYURL, proxying is fully under
+# the control of the rules author, and with "none", subsequent proxy
+# and gateway checking is completely disabled.  It is therefore a good
+# idea to combine any "Map" and "Pass" rules that might result in passing
+# the changed URL with explicit "UseProxy" rules, if the rules file is
+# expected to be used together with proxying; or else always use "Redirect"
+# instead of simple passing.
+#
+# 5. Case-sensitive matching
+# --------------------------
+# The matching logic is generic string-based.  It doesn't know anything
+# about URL syntax, and so it cannot know in which parts of a URL case
+# matters and where it doesn't.  As a result, all comparisons are case-
+# sensitive.  If (a limited number of) case variations of a URL need
+# to be dealt with, several rules can be used instead of one.
+# In particular, this makes "UseProxy ... none" in some ways more limited
+# than a no_proxy setting.
+#
+# 6. Redirection differences
+# --------------------------
+# For some URLs lynx does never check after a request whether a redirection
+# occurs; that makes the "Redirect" rule useless for such URLs (in addition
+# to those mentioned under limitation 1.).  Some of them are some gopher
+# types, telnet: and similar in most situations, newspost: and similar,
+# lynxcgi:, and some other private types.  Trying to redirect these will
+# make access fail.  You probable don't want to change such URLs anyway,
+# but if you feel you must, try using "Map" and "Pass" instead.
+#
+# The -noredir command line option only applies for real HTTP redirection
+# responses, Redirect rules are still applied.  Also for certain other
+# command line options (-mime_header, -head) and command keys (HEAD) lynx
+# shows the redirection message (or part of it) in case of a real HTTP
+# redirection, instead of following the redirection.  Here, too, a Redirect
+# rule remains effective (there is no redirection message to show, after all).
+#
+# 7. URLs required
+# ----------------
+# Full absolute URLs (modulo possible "*" matching wildcards) are required
+# in rules.  Strings like "www.somewhere.com" or "/some/dir/some.file" or
+# "www.somewhere.com/some/dir/some.file" are not URLs.  Lynx may accept
+# them as user input, as abbreviated forms for URLs; but by the time the
+# rules get checked, those have been converted to full URLs, if they can
+# be recognized.  This also means that rules cannot influence which strings
+# typed at a 'g'oto prompt are recognized for URLs - rules processing kicks
+# in later.
diff --git a/samples/lynx-keymaps b/samples/lynx-keymaps
index ee6039af..1efa2cf3 100644
--- a/samples/lynx-keymaps
+++ b/samples/lynx-keymaps
@@ -107,10 +107,39 @@ setkey "^[[Z"		0x10F
 #	\v		vertical tab
 #	\<number>	octal number, up to 3 digits, e.g., "\033".
 #	\d<number>	decimal number, up to 3 digits, e.g., "\d99"
-#	\x<number>	hexidecimal number, up to 2 digits, e.g., "\xFF"
+#	\x<number>	hexadecimal number, up to 2 digits, e.g., "\xFF"
 #
 # For Unix-systems (which have termcap or terminfo) you may also use symbols
 # that refer to the termcap/terminfo, by referencing the name bracketed by
 # "^(" and ")", e.g.,
 setkey "^(cuu1)"	UPARROW
 setkey "^(up)"		UPARROW
+#
+# The following extension, introduced after lynx2.8.2, allows to force
+# recognition of meta (ESC) prefixes - especially useful with the
+# "Bash-like" lineeditor binding.  Its use is unnecessary in most
+# cases if Lynx was built with ncurses, but is probably necessary for
+# all keys that should recognize ESC as a prefix if Lynx was built with
+# slang.
+#
+#       setkey ESC-SEQUENCE  Meta-LETTER
+#       setkey ESC-SEQUENCE  Meta-KEYSYM
+#       setkey ESC-SEQUENCE  Meta-KEYSYM_NAME
+#
+# for example
+#setkey "\033b"          Meta-b
+#setkey "\033e"          Meta-'e'
+#setkey "\033\033[28~"   Meta-F1
+#
+# The following extension, introduced after lynx2.8.2, allows to map
+# escape sequences directly to key commands (lynxactioncodes).
+#
+#       setkey ESC-SEQUENCE  LAC:LYNX_ACTION
+#
+# where LYNX_ACTION is a key command specified as in lynx.cfg KEYMAP
+# options and on the KEYMAP ('K') screen.  Using this form makes remapping
+# according to user preference with KEYMAP impossible and should thus be
+# used sparingly (in general, use KEYMAP with PASS instead, if the goal is
+# to force recognition of a key in form text fields).  For example:
+#
+#setkey "\033e"          LAC:EDITTEXTAREA
diff --git a/src/GridText.c b/src/GridText.c
index d3d7e2ea..957a8a3d 100644
--- a/src/GridText.c
+++ b/src/GridText.c
@@ -1069,7 +1069,14 @@ PRIVATE void display_title ARGS1(
     /*
      *  Generate the page indicator (percent) string.
      */
-    if ((text->Lines + 1) > (display_lines)) {
+    if (LYcols < 10) {
+	percent[0] = '\0';	/* Null string */
+    } else if ((display_lines) <= 0 && LYlines > 0 &&
+	text->top_of_screen <= 99999 && text->Lines <= 999999) {
+	sprintf(percent, " (l%d of %d)",
+		text->top_of_screen, text->Lines);
+    } else if ((text->Lines + 1) > (display_lines) &&
+	(display_lines) > 0) {
 	/*
 	 *  In a small attempt to correct the number of pages counted....
 	 *    GAB 07-14-94
@@ -1130,7 +1137,8 @@ PRIVATE void display_title ARGS1(
 	 *  account the possibility that multibyte
 	 *  characters might be present. - FM
 	 */
-	title[((LYcols - 2) - strlen(percent))] = '\0';
+	if (LYcols - 2 >= (int)strlen(percent))
+	    title[((LYcols - 2) - strlen(percent))] = '\0';
 	move(0, 1);
     }
     addstr(title);
@@ -1203,6 +1211,12 @@ PRIVATE void display_page ARGS3(
 
     tmp[0] = tmp[1] = tmp[2] = '\0';
     text->page_has_target = NO;
+    if (display_lines <= 0) {
+	/*  No screen space to display anything!
+	 *  returning here makes it more likely we will survive if
+	 *  an xterm is temporarily made very small. - kw */
+	return;
+    }
     last_screen = text->Lines - (display_lines - 2);
     line = text->last_line->prev;
 
@@ -7905,7 +7919,15 @@ PRIVATE int find_best_target_cs ARGS3(
     return (-1);
 }
 
-PUBLIC void HText_SubmitForm ARGS4(
+/*
+ *  HText_SubmitForm - generate submit data from form fields.
+ *  For mailto forms, send the data.
+ *  For other methods, set fields in structure pointed to by doc
+ *  appropriately for next request.
+ *  Returns 1 if *doc set appropriately for next request,
+ *	    0 otherwise. - kw
+ */
+PUBLIC int HText_SubmitForm ARGS4(
 	FormInfo *,	submit_item,
 	document *,	doc,
 	char *,		link_name,
@@ -7941,7 +7963,7 @@ PUBLIC void HText_SubmitForm ARGS4(
 
     CTRACE(tfp, "FIXME:SubmitForm\n");
     if (!HTMainText)
-	return;
+	return 0;
 
     thisform = HTList_objectAt(HTMainText->forms, form_number - 1);
     /*  Sanity check */
@@ -7961,10 +7983,10 @@ PUBLIC void HText_SubmitForm ARGS4(
 	if ((submit_item->submit_method == URL_MAIL_METHOD) &&
 	    strncmp(submit_item->submit_action, "mailto:", 7)) {
 	    HTAlert(BAD_FORM_MAILTO);
-	    return;
+	    return 0;
 	}
     } else {
-	return;
+	return 0;
     }
 
     /*
@@ -8830,7 +8852,7 @@ PUBLIC void HText_SubmitForm ARGS4(
 		 doc->post_content_type);
 	FREE(query);
 	FREE(doc->post_content_type);
-	return;
+	return 0;
     } else {
 	_statusline(SUBMITTING_FORM);
     }
@@ -8840,13 +8862,13 @@ PUBLIC void HText_SubmitForm ARGS4(
 	CTRACE(tfp,"GridText - post_data: %s\n",doc->post_data);
 	StrAllocCopy(doc->address, submit_item->submit_action);
 	FREE(query);
-	return;
+	return 1;
     } else { /* GET_METHOD */
 	StrAllocCopy(doc->address, query);
 	FREE(doc->post_data);
 	FREE(doc->post_content_type);
 	FREE(query);
-	return;
+	return 1;
     }
 }
 
@@ -10069,7 +10091,13 @@ PUBLIC int HText_ExtEditForm ARGS1(
     HTSprintf0 (&tbuf, "%s %s %s", editor, ed_offset, ed_temp);
 #endif
 
-    LYSystem (tbuf);   /* finally the editor is called */
+    if (LYSystem (tbuf)) {   /* finally the editor is called */
+	/*
+	 *  If something went wrong, we should probably return soon;
+	 *  currently we don't, but at least put out a message. - kw
+	 */
+	HTAlwaysAlert(NULL, ERROR_SPAWNING_EDITOR);
+    }
 
 #ifdef UNIX
     /*
@@ -10353,6 +10381,12 @@ PUBLIC int HText_InsertFile ARGS1(
 	CTRACE(tfp, "GridText: file insert cancelled - no filename provided\n");
 	return (0);
     }
+    if (no_dotfiles || !show_dotfiles) {
+	if (*LYPathLeaf(fn) == '.') {
+	    HTUserMsg(FILENAME_CANNOT_BE_DOT);
+	    return (0);
+	}
+    }
 
     /*
      *	Read it into our buffer (abort on 0-length file).
@@ -10790,7 +10824,7 @@ PUBLIC void redraw_lines_of_link ARGS1(
 	lines_back = display_lines - (links[cur].ly-pvtTITLE_HEIGHT);
     }
     todr1 = HTMainText->next_line;
-    while (lines_back--)
+    while (lines_back-- > 0)
 	todr1 = todr1->prev;
     todr2 = (links[cur].hightext2 && links[cur].ly < display_lines) ?
 	    todr1->next : 0;
diff --git a/src/GridText.h b/src/GridText.h
index 1eeba7b2..a26f709a 100644
--- a/src/GridText.h
+++ b/src/GridText.h
@@ -224,7 +224,7 @@ extern int HText_beginInput PARAMS((
 extern void HText_trimHightext PARAMS((
 	HText *		text,
 	BOOLEAN 	final));
-extern void HText_SubmitForm PARAMS((
+extern int HText_SubmitForm PARAMS((
 	FormInfo *	submit_item,
 	document *	doc,
 	char *		link_name,
diff --git a/src/HTAlert.c b/src/HTAlert.c
index a3a902c2..eae16bd7 100644
--- a/src/HTAlert.c
+++ b/src/HTAlert.c
@@ -200,8 +200,8 @@ PUBLIC BOOL HTLastConfirmCancelled NOARGS
 
 #define DFT_CONFIRM ~(YES|NO)
 
-/*	Seek confirmation.				HTConfirm()
-**	------------------
+/*	Seek confirmation with default answer.		HTConfirmDefault()
+**	--------------------------------------
 */
 PUBLIC BOOL HTConfirmDefault ARGS2(CONST char *, Msg, int, Dft)
 {
@@ -223,7 +223,7 @@ PUBLIC BOOL HTConfirmDefault ARGS2(CONST char *, Msg, int, Dft)
 	FREE(msg);
 
 	while (result < 0) {
-	    int c = LYgetch();
+	    int c = LYgetch_for(FOR_SINGLEKEY);
 #ifdef VMS
 	    if (HadVMSInterrupt) {
 		HadVMSInterrupt = FALSE;
@@ -245,6 +245,9 @@ PUBLIC BOOL HTConfirmDefault ARGS2(CONST char *, Msg, int, Dft)
     return (result);
 }
 
+/*	Seek confirmation.				HTConfirm()
+**	------------------
+*/
 PUBLIC BOOL HTConfirm ARGS1(CONST char *, Msg)
 {
     return HTConfirmDefault(Msg, DFT_CONFIRM);
@@ -535,7 +538,7 @@ PUBLIC BOOL HTConfirmCookie ARGS4(
     }
     while (1) {
 	if(!LYAcceptAllCookies) {
-	    ch = LYgetch();
+	    ch = LYgetch_for(FOR_SINGLEKEY);
 	} else {
 	    ch = 'A';
 	}
@@ -671,7 +674,7 @@ PUBLIC int HTConfirmPostRedirect ARGS2(
 	    case 1:
 		_statusline(show_POST_url);
 	}
-	c = LYgetch();
+	c = LYgetch_for(FOR_SINGLEKEY);
 	switch (TOUPPER(c)) {
 	    case 'P':
 		/*
@@ -730,3 +733,17 @@ PUBLIC int HTConfirmPostRedirect ARGS2(
     FREE(url);
     return (result);
 }
+
+/*
+ *  LYstrerror emulates the ANSI strerror() function.
+ */
+#ifdef LYStrerror
+    /* defined as macro in .h file. */
+#else
+PUBLIC char *LYStrerror ARGS1(int, code)
+{
+    static char temp[80];
+    sprintf(temp, "System errno is %d.\r\n", code);
+    return temp;
+}
+#endif /* HAVE_STRERROR */
diff --git a/src/HTAlert.h b/src/HTAlert.h
index f9559036..b2cc1508 100644
--- a/src/HTAlert.h
+++ b/src/HTAlert.h
@@ -145,4 +145,12 @@ extern int HTConfirmPostRedirect PARAMS((
 	CONST char *	Redirecting_url,
 	int		server_status));
 
+
+#ifdef HAVE_STRERROR
+#define LYStrerror strerror
+#else
+extern char *LYStrerror PARAMS((
+	int		code));
+#endif /* HAVE_STRERROR */
+
 #endif /* HTALERT_H */
diff --git a/src/HTForms.h b/src/HTForms.h
index ff7bc962..53cde123 100644
--- a/src/HTForms.h
+++ b/src/HTForms.h
@@ -8,7 +8,9 @@
 /* in LYForms.c */
 extern int change_form_link PARAMS((struct link *form_link,
                                     document *newdoc, BOOLEAN *refresh_screen,
-				    char *link_name, char *link_value));
+				    char *link_name, char *link_value,
+				    BOOLEAN use_last_tfpos,
+				    BOOLEAN immediate_submit));
 
 /* InputFieldData is used to pass the info between
  * HTML.c and Gridtext.c in HText_beginInput()
@@ -134,4 +136,7 @@ typedef struct _PerFormInfo
 #define MIDDLE_ORDER 2
 #define LAST_ORDER   3
 
+/* in LYForms.c */
+extern void show_formlink_statusline PARAMS((CONST FormInfo * form));
+
 #endif /* HTFORMS_H */
diff --git a/src/HTInit.c b/src/HTInit.c
index e08d9b63..d65298d7 100644
--- a/src/HTInit.c
+++ b/src/HTInit.c
@@ -645,6 +645,9 @@ PRIVATE int ExitWithError ARGS1(
     return(-1);
 }
 
+/* Reverse the entries from each mailcap after it has been read, so that
+ * earlier entries have precedence.  Set to 0 to get traditional lynx
+ * behavior, which means that the last match wins. - kw */
 #define reverse_mailcap 1
 
 PRIVATE int HTLoadTypesConfigFile ARGS1(
diff --git a/src/HTML.c b/src/HTML.c
index 2635b106..2f036c9d 100644
--- a/src/HTML.c
+++ b/src/HTML.c
@@ -642,7 +642,7 @@ PUBLIC void HTML_write ARGS3(HTStructured *, me, CONST char*, s, int, l)
    "internal".	The flag is set before we start messing around with the
    string (resolution of relative URLs etc.).  This variable only used
    locally here, don't confuse with LYinternal_flag which is for
-   for overriding non-caching similar to LYoverride_no_cache. - kw */
+   overriding non-caching similar to LYoverride_no_cache. - kw */
 #define CHECK_FOR_INTERN(s) intern_flag = (s && (*s=='#' || *s=='\0')) ? TRUE : FALSE;
 
 /* Last argument to pass to HTAnchor_findChildAndLink() calls,
diff --git a/src/LYCookie.c b/src/LYCookie.c
index 288385da..bd0bab72 100644
--- a/src/LYCookie.c
+++ b/src/LYCookie.c
@@ -2228,6 +2228,7 @@ PRIVATE int LYHandleCookies ARGS4 (
     if (HTList_isEmpty(domain_list)) {
 	HTProgress(COOKIE_JAR_IS_EMPTY);
 	sleep(MessageSecs);
+	HTNoDataOK = 1;
 	return(HT_NO_DATA);
     }
 
@@ -2288,6 +2289,7 @@ PRIVATE int LYHandleCookies ARGS4 (
 			    if (HTConfirm(DELETE_COOKIE_CONFIRMATION) == FALSE)
 			    {
 				FREE(lynxID);
+				HTNoDataOK = 1;
 				return(HT_NO_DATA);
 			    }
 			    HTList_removeObject(de->cookie_list, co);
@@ -2313,6 +2315,7 @@ PRIVATE int LYHandleCookies ARGS4 (
 				HTProgress(COOKIE_EATEN);
 			    }
 			    sleep(MessageSecs);
+			    HTNoDataOK = 1;
 			    break;
 			}
 		    }
@@ -2328,8 +2331,9 @@ PRIVATE int LYHandleCookies ARGS4 (
 		    } else {
 			_statusline(DELETE_COOKIES_SET_ALLOW_OR_CANCEL);
 		    }
+		    HTNoDataOK = 1;
 		    while (1) {
-			ch = LYgetch();
+			ch = LYgetch_for(FOR_SINGLEKEY);
 #ifdef VMS
 			if (HadVMSInterrupt) {
 			    HadVMSInterrupt = FALSE;
diff --git a/src/LYCurses.c b/src/LYCurses.c
index c6c08a2e..666d96b6 100644
--- a/src/LYCurses.c
+++ b/src/LYCurses.c
@@ -688,6 +688,10 @@ PUBLIC void start_curses NOARGS
 #endif /* SLANG_VERSION >= 9935 */
 #endif /* UNIX */
 
+#if !defined(USE_KEYMAPS) && defined(ENHANCED_LINEEDIT) && defined(ESCDELAY)
+	/* way to get ESC that's not part of a recognized sequence through */
+	ESCDELAY = 2000;
+#endif
 	/*
 	 *  Check whether a saved show_color:off override is in effect. - kw
 	 */
@@ -792,8 +796,10 @@ PUBLIC void start_curses NOARGS
 	recent_sizechange = FALSE; /* prevent mainloop drawing 1st doc twice */
 #endif /* SIGWINCH */
 #if defined(USE_KEYMAPS) && defined(NCURSES_VERSION)
-	if (-1 == lynx_initialize_keymaps ())
+	if (-1 == lynx_initialize_keymaps ()) {
+	    endwin();
 	    exit (-1);
+	}
 #endif
 
 	/*
@@ -912,12 +918,8 @@ PUBLIC void lynx_enable_mouse ARGS1(int,state)
 	FlushConsoleInputBuffer(hConIn);
     }
 #else
-    /* Inform ncurses that we're interested in knowing when mouse
-     * button 1 is clicked.  We cannot just specify
-     * BUTTON1_CLICKED | BUTTON3_CLICKED, since ncurses will try hard
-     * to translate other events to single-clicks.
-     * Compensate for small value of maxclick in ncurses.  */
     if (state) {
+	/* Compensate for small value of maxclick in ncurses.  */
 	static int was = 0;
 
 	if (!was) {
@@ -927,7 +929,20 @@ PUBLIC void lynx_enable_mouse ARGS1(int,state)
 	    if (old < 200)		/* Default 166 */
 		mouseinterval(300);
 	}
-	mousemask(ALL_MOUSE_EVENTS, NULL);
+	/* Inform ncurses which mouse events we're interested in.
+	 * We shouldn't need to include BUTTONn_PRESSED and BUTTONn_RELEASED
+	 * events, since ncurses should translate them to click events. - kw
+	 */
+	mousemask(BUTTON_CTRL | BUTTON_ALT
+		  /* | BUTTON1_PRESSED | BUTTON1_RELEASED */
+		  | BUTTON1_CLICKED
+		  | BUTTON1_DOUBLE_CLICKED | BUTTON1_TRIPLE_CLICKED
+		  /* | BUTTON2_PRESSED | BUTTON2_RELEASED */
+		  | BUTTON2_CLICKED
+		  /* | BUTTON3_PRESSED | BUTTON3_RELEASED */
+		  | BUTTON3_CLICKED
+		  | BUTTON3_DOUBLE_CLICKED | BUTTON3_TRIPLE_CLICKED,
+		  NULL);
     } else
 	mousemask(0, NULL);
 #endif /* __BORLANDC__ and __PDCURSES__ */
diff --git a/src/LYEditmap.c b/src/LYEditmap.c
index d7ebebb7..8a947ac4 100644
--- a/src/LYEditmap.c
+++ b/src/LYEditmap.c
@@ -3,8 +3,27 @@
 */
 
 #include <HTUtils.h>
+#include <LYGlobalDefs.h>
 #include <LYStrings.h>
-#include <LYKeymap.h>		/* only for KEYMAP_SIZE - kw */
+#include <LYKeymap.h>	/* KEYMAP_SIZE, LKC_*, LYK_* - kw */
+
+/* * * * *  LynxEditactionCodes  * * * * */
+#ifdef EXP_ALT_BINDINGS
+
+/*  Last valid index for the (lynxkeycode+modifier -> lynxeditactioncode)
+ *  tables.  Currently all three tables are the same. - kw
+ */
+#define LAST_MOD1_LKC	0x111
+#define LAST_MOD2_LKC	0x111
+#define LAST_MOD3_LKC	0x111
+
+/*  Get (lynxkeycode+modifier -> lynxeditactioncode) mapping, intermediate.
+ */
+#define LKC_TO_LEC_M1(c) ((c)>LAST_MOD1_LKC? LYE_UNMOD: Mod1Binding[c])
+#define LKC_TO_LEC_M2(c) ((c)>LAST_MOD2_LKC? LYE_UNMOD: Mod2Binding[c])
+#define LKC_TO_LEC_M3(c) ((c)>LAST_MOD3_LKC? LYE_UNMOD: Mod3Binding[c])
+
+#endif  /* EXP_ALT_BINDINGS */
 
 PUBLIC int current_lineedit = 0;  /* Index into LYLineEditors[]   */
 
@@ -338,7 +357,7 @@ LYE_CHAR,       LYE_CHAR,       LYE_CHAR,       LYE_CHAR,
 LYE_CHAR,       LYE_CHAR,       LYE_CHAR,       LYE_CHAR,
 LYE_CHAR,       LYE_CHAR,       LYE_CHAR,       LYE_CHAR,
 
-/* 100..10E function key definitions in LYStrings.h */
+/* 100..10F function key definitions in LYStrings.h */
 LYE_FORM_PASS,  LYE_FORM_PASS,  LYE_FORW,       LYE_BACK,
 /* UPARROW      DNARROW         RTARROW         LTARROW     */
 
@@ -475,7 +494,414 @@ LYE_NOP,        LYE_NOP,        LYE_NOP,        LYE_NOP,
 /* 290..293 */
 LYE_NOP,        LYE_NOP,        LYE_NOP,        LYE_NOP,
 };
-#endif
+
+/* kw     */ /* Default except: ^B=cursor-backward[+],^F=cursor-forward[+], */
+             /*                 ^K=delete-to-EOL[+][++],^X=Modifier Prefix, */
+             /*                 ^[ (ESC)=Modifier Prefix,                   */
+             /*                 ^R=BACKW,             ^S=FORWW,             */
+             /*                 ^T=transpose-chars,                         */
+             /*                 ^U=delete-to-BOL,     ^W=delete-prev-word,  */
+             /*                 ^@ (NUL)=SETMARK,     ^Y=YANK,              */
+             /*                 ^_=ABORT (undo),                            */
+             /*                 ^P=FORM_PASS,         ^N=FORM_PASS,         */
+             /*                 ^O=FORM_PASS,         ^L=FORM_PASS,         */
+             /*                 ^\=FORM_PASS,         ^]=FORM_PASS,         */
+             /*                 ^Z=FORM_PASS,         F1=FORM_PASS,         */
+             /*                 ^E=EOL[++],           Remove=DELN           */
+             /* [+]: same as BetterEditBinding                              */
+             /* [++]: additionally set double-key modifier                  */
+
+/* Default where BetterEditBinding deviates:          ^^=SWMAP,            */
+             /*                tab=LYE_TAB                                 */
+
+/* Some functions for which the modifier binding is preferred:             */
+             /*         M-bs,M-del=delete-prev-word, M-d=delete-next-word, */
+             /*                M-b=BACKW,            M-f=FORWW,            */
+
+PRIVATE char BashlikeEditBinding[KEYMAP_SIZE-1]={
+
+LYE_SETMARK,    LYE_BOL,        LYE_BACK,       LYE_ABORT,
+/* nul          ^A              ^B              ^C      */
+
+LYE_DELN,       LYE_EOL|LYE_DF, LYE_FORW,       LYE_ABORT,
+/* ^D           ^E              ^F              ^G      */
+
+LYE_DELP,       LYE_TAB,        LYE_ENTER,      LYE_DELEL|LYE_DF,
+/* bs           tab             nl              ^K      */
+
+LYE_FORM_PASS,  LYE_ENTER,      LYE_FORM_PASS,  LYE_FORM_PASS,
+/* ^L           cr              ^N              ^O      */
+
+LYE_FORM_PASS,  LYE_NOP,        LYE_BACKW,      LYE_FORWW,
+/* ^P           XON             ^R              ^S/XOFF */
+
+LYE_TPOS,       LYE_DELBL,      LYE_LKCMD,      LYE_DELPW,
+/* ^T           ^U              ^V              ^W      */
+
+LYE_SETM1,      LYE_YANK,       LYE_FORM_PASS,  LYE_SETM2,
+/* ^X           ^Y              ^Z              ESC     */
+
+LYE_FORM_PASS,  LYE_FORM_PASS,  LYE_SWMAP,      LYE_ABORT,
+/* ^\           ^]              ^^              ^_      */
+
+/* sp .. RUBOUT                                         */
+LYE_CHAR,       LYE_CHAR,       LYE_CHAR,       LYE_CHAR,
+LYE_CHAR,       LYE_CHAR,       LYE_CHAR,       LYE_CHAR,
+LYE_CHAR,       LYE_CHAR,       LYE_CHAR,       LYE_CHAR,
+LYE_CHAR,       LYE_CHAR,       LYE_CHAR,       LYE_CHAR,
+LYE_CHAR,       LYE_CHAR,       LYE_CHAR,       LYE_CHAR,
+LYE_CHAR,       LYE_CHAR,       LYE_CHAR,       LYE_CHAR,
+LYE_CHAR,       LYE_CHAR,       LYE_CHAR,       LYE_CHAR,
+LYE_CHAR,       LYE_CHAR,       LYE_CHAR,       LYE_CHAR,
+LYE_CHAR,       LYE_CHAR,       LYE_CHAR,       LYE_CHAR,
+LYE_CHAR,       LYE_CHAR,       LYE_CHAR,       LYE_CHAR,
+LYE_CHAR,       LYE_CHAR,       LYE_CHAR,       LYE_CHAR,
+LYE_CHAR,       LYE_CHAR,       LYE_CHAR,       LYE_CHAR,
+LYE_CHAR,       LYE_CHAR,       LYE_CHAR,       LYE_CHAR,
+LYE_CHAR,       LYE_CHAR,       LYE_CHAR,       LYE_CHAR,
+LYE_CHAR,       LYE_CHAR,       LYE_CHAR,       LYE_CHAR,
+LYE_CHAR,       LYE_CHAR,       LYE_CHAR,       LYE_CHAR,
+LYE_CHAR,       LYE_CHAR,       LYE_CHAR,       LYE_CHAR,
+LYE_CHAR,       LYE_CHAR,       LYE_CHAR,       LYE_CHAR,
+LYE_CHAR,       LYE_CHAR,       LYE_CHAR,       LYE_CHAR,
+LYE_CHAR,       LYE_CHAR,       LYE_CHAR,       LYE_CHAR,
+LYE_CHAR,       LYE_CHAR,       LYE_CHAR,       LYE_CHAR,
+LYE_CHAR,       LYE_CHAR,       LYE_CHAR,       LYE_CHAR,
+LYE_CHAR,       LYE_CHAR,       LYE_CHAR,       LYE_CHAR,
+LYE_CHAR,       LYE_CHAR,       LYE_CHAR,       LYE_DELP,
+
+/* 80..9F ISO-8859-1 8-bit escape characters. */
+LYE_CHAR,       LYE_CHAR,       LYE_CHAR,       LYE_CHAR,
+LYE_CHAR,       LYE_CHAR,       LYE_CHAR,       LYE_CHAR,
+LYE_CHAR,       LYE_CHAR,       LYE_CHAR,       LYE_CHAR,
+LYE_CHAR,       LYE_CHAR,       LYE_CHAR,       LYE_CHAR,
+LYE_CHAR,       LYE_CHAR,       LYE_CHAR,       LYE_CHAR,
+LYE_CHAR,       LYE_CHAR,       LYE_CHAR,       LYE_AIX,
+/*                                               97 AIX    */
+LYE_CHAR,       LYE_CHAR,       LYE_CHAR,       LYE_CHAR,
+LYE_CHAR,       LYE_CHAR,       LYE_CHAR,       LYE_CHAR,
+
+/* A0..FF (permissible ISO-8859-1) 8-bit characters. */
+LYE_CHAR,       LYE_CHAR,       LYE_CHAR,       LYE_CHAR,
+LYE_CHAR,       LYE_CHAR,       LYE_CHAR,       LYE_CHAR,
+LYE_CHAR,       LYE_CHAR,       LYE_CHAR,       LYE_CHAR,
+LYE_CHAR,       LYE_CHAR,       LYE_CHAR,       LYE_CHAR,
+LYE_CHAR,       LYE_CHAR,       LYE_CHAR,       LYE_CHAR,
+LYE_CHAR,       LYE_CHAR,       LYE_CHAR,       LYE_CHAR,
+LYE_CHAR,       LYE_CHAR,       LYE_CHAR,       LYE_CHAR,
+LYE_CHAR,       LYE_CHAR,       LYE_CHAR,       LYE_CHAR,
+LYE_CHAR,       LYE_CHAR,       LYE_CHAR,       LYE_CHAR,
+LYE_CHAR,       LYE_CHAR,       LYE_CHAR,       LYE_CHAR,
+LYE_CHAR,       LYE_CHAR,       LYE_CHAR,       LYE_CHAR,
+LYE_CHAR,       LYE_CHAR,       LYE_CHAR,       LYE_CHAR,
+LYE_CHAR,       LYE_CHAR,       LYE_CHAR,       LYE_CHAR,
+LYE_CHAR,       LYE_CHAR,       LYE_CHAR,       LYE_CHAR,
+LYE_CHAR,       LYE_CHAR,       LYE_CHAR,       LYE_CHAR,
+LYE_CHAR,       LYE_CHAR,       LYE_CHAR,       LYE_CHAR,
+LYE_CHAR,       LYE_CHAR,       LYE_CHAR,       LYE_CHAR,
+LYE_CHAR,       LYE_CHAR,       LYE_CHAR,       LYE_CHAR,
+LYE_CHAR,       LYE_CHAR,       LYE_CHAR,       LYE_CHAR,
+LYE_CHAR,       LYE_CHAR,       LYE_CHAR,       LYE_CHAR,
+LYE_CHAR,       LYE_CHAR,       LYE_CHAR,       LYE_CHAR,
+LYE_CHAR,       LYE_CHAR,       LYE_CHAR,       LYE_CHAR,
+LYE_CHAR,       LYE_CHAR,       LYE_CHAR,       LYE_CHAR,
+LYE_CHAR,       LYE_CHAR,       LYE_CHAR,       LYE_CHAR,
+
+/* 100..10F function key definitions in LYStrings.h */
+LYE_FORM_PASS,  LYE_FORM_PASS,  LYE_FORW,       LYE_BACK,
+/* UPARROW      DNARROW         RTARROW         LTARROW     */
+
+LYE_FORM_PASS,  LYE_FORM_PASS,  LYE_BOL,        LYE_EOL,
+/* PGDOWN       PGUP            HOME            END         */
+
+#if (defined(_WINDOWS) || defined(__DJGPP__))
+
+LYE_FORM_PASS,  LYE_NOP,        LYE_NOP,        LYE_NOP,
+/* F1 */
+
+#else
+
+LYE_FORM_PASS,  LYE_TAB,        LYE_BOL,        LYE_EOL,
+/* F1           Do key          Find key        Select key  */
+
+#endif /* _WINDOWS || __DJGPP__ */
+
+LYE_NOP,        LYE_DELN,       LYE_NOP,        LYE_FORM_PASS,
+/* Insert key   Remove key      DO_NOTHING      Back tab */
+
+/* 110..18F */
+#if (defined(_WINDOWS) || defined(__DJGPP__)) && defined(USE_SLANG) && !defined(DJGPP_KEYHANDLER)
+
+LYE_DELP,       LYE_ENTER,      LYE_NOP,        LYE_NOP,
+/* Backspace    Enter */
+
+#else
+
+LYE_NOP,        LYE_NOP,        LYE_NOP,        LYE_NOP,
+
+#endif /* USE_SLANG &&(_WINDOWS || __DJGPP) && !DJGPP_KEYHANDLER */
+
+LYE_NOP,        LYE_NOP,        LYE_NOP,        LYE_NOP,
+LYE_NOP,        LYE_NOP,        LYE_NOP,        LYE_NOP,
+/*             MOUSE_KEY  */
+LYE_NOP,        LYE_NOP,        LYE_NOP,        LYE_NOP,
+LYE_NOP,        LYE_NOP,        LYE_NOP,        LYE_NOP,
+LYE_NOP,        LYE_NOP,        LYE_NOP,        LYE_NOP,
+LYE_NOP,        LYE_NOP,        LYE_NOP,        LYE_NOP,
+LYE_NOP,        LYE_NOP,        LYE_NOP,        LYE_NOP,
+LYE_NOP,        LYE_NOP,        LYE_NOP,        LYE_NOP,
+LYE_NOP,        LYE_NOP,        LYE_NOP,        LYE_NOP,
+LYE_NOP,        LYE_NOP,        LYE_NOP,        LYE_NOP,
+LYE_NOP,        LYE_NOP,        LYE_NOP,        LYE_NOP,
+LYE_NOP,        LYE_NOP,        LYE_NOP,        LYE_NOP,
+LYE_NOP,        LYE_NOP,        LYE_NOP,        LYE_NOP,
+LYE_NOP,        LYE_NOP,        LYE_NOP,        LYE_NOP,
+LYE_NOP,        LYE_NOP,        LYE_NOP,        LYE_NOP,
+LYE_NOP,        LYE_NOP,        LYE_NOP,        LYE_NOP,
+LYE_NOP,        LYE_NOP,        LYE_NOP,        LYE_NOP,
+LYE_NOP,        LYE_NOP,        LYE_NOP,        LYE_NOP,
+LYE_NOP,        LYE_NOP,        LYE_NOP,        LYE_NOP,
+LYE_NOP,        LYE_NOP,        LYE_NOP,        LYE_NOP,
+LYE_NOP,        LYE_NOP,        LYE_NOP,        LYE_NOP,
+LYE_NOP,        LYE_NOP,        LYE_NOP,        LYE_NOP,
+LYE_NOP,        LYE_NOP,        LYE_NOP,        LYE_NOP,
+LYE_NOP,        LYE_NOP,        LYE_NOP,        LYE_NOP,
+LYE_NOP,        LYE_NOP,        LYE_NOP,        LYE_NOP,
+LYE_NOP,        LYE_NOP,        LYE_NOP,        LYE_NOP,
+LYE_NOP,        LYE_NOP,        LYE_NOP,        LYE_NOP,
+LYE_NOP,        LYE_NOP,        LYE_NOP,        LYE_NOP,
+LYE_NOP,        LYE_NOP,        LYE_NOP,        LYE_NOP,
+LYE_NOP,        LYE_NOP,        LYE_NOP,        LYE_NOP,
+LYE_NOP,        LYE_NOP,        LYE_NOP,        LYE_NOP,
+/* 190..20F */
+
+LYE_NOP,        LYE_NOP,        LYE_NOP,        LYE_NOP,
+LYE_NOP,        LYE_NOP,        LYE_NOP,        LYE_NOP,
+LYE_NOP,        LYE_NOP,        LYE_NOP,        LYE_NOP,
+LYE_NOP,        LYE_NOP,        LYE_NOP,        LYE_NOP,
+LYE_NOP,        LYE_NOP,        LYE_NOP,        LYE_NOP,
+LYE_NOP,        LYE_NOP,        LYE_NOP,        LYE_NOP,
+LYE_NOP,        LYE_NOP,        LYE_NOP,        LYE_NOP,
+LYE_NOP,        LYE_NOP,        LYE_NOP,        LYE_NOP,
+LYE_NOP,        LYE_NOP,        LYE_NOP,        LYE_NOP,
+LYE_NOP,        LYE_NOP,        LYE_NOP,        LYE_NOP,
+LYE_NOP,        LYE_NOP,        LYE_NOP,        LYE_NOP,
+LYE_NOP,        LYE_NOP,        LYE_NOP,        LYE_NOP,
+LYE_NOP,        LYE_NOP,        LYE_NOP,        LYE_NOP,
+LYE_NOP,        LYE_NOP,        LYE_NOP,        LYE_NOP,
+LYE_NOP,        LYE_NOP,        LYE_NOP,        LYE_NOP,
+LYE_NOP,        LYE_NOP,        LYE_NOP,        LYE_NOP,
+LYE_NOP,        LYE_NOP,        LYE_NOP,        LYE_NOP,
+LYE_NOP,        LYE_NOP,        LYE_NOP,        LYE_NOP,
+LYE_NOP,        LYE_NOP,        LYE_NOP,        LYE_NOP,
+LYE_NOP,        LYE_NOP,        LYE_NOP,        LYE_NOP,
+LYE_NOP,        LYE_NOP,        LYE_NOP,        LYE_NOP,
+LYE_NOP,        LYE_NOP,        LYE_NOP,        LYE_NOP,
+LYE_NOP,        LYE_NOP,        LYE_NOP,        LYE_NOP,
+LYE_NOP,        LYE_NOP,        LYE_NOP,        LYE_NOP,
+LYE_NOP,        LYE_NOP,        LYE_NOP,        LYE_NOP,
+LYE_NOP,        LYE_NOP,        LYE_NOP,        LYE_NOP,
+LYE_NOP,        LYE_NOP,        LYE_NOP,        LYE_NOP,
+LYE_NOP,        LYE_NOP,        LYE_NOP,        LYE_NOP,
+LYE_NOP,        LYE_NOP,        LYE_NOP,        LYE_NOP,
+LYE_NOP,        LYE_NOP,        LYE_NOP,        LYE_NOP,
+LYE_NOP,        LYE_NOP,        LYE_NOP,        LYE_NOP,
+LYE_NOP,        LYE_NOP,        LYE_NOP,        LYE_NOP,
+/* 210..28F */
+
+LYE_NOP,        LYE_NOP,        LYE_NOP,        LYE_NOP,
+LYE_NOP,        LYE_NOP,        LYE_NOP,        LYE_NOP,
+LYE_NOP,        LYE_NOP,        LYE_NOP,        LYE_NOP,
+LYE_NOP,        LYE_NOP,        LYE_NOP,        LYE_NOP,
+LYE_NOP,        LYE_NOP,        LYE_NOP,        LYE_NOP,
+LYE_NOP,        LYE_NOP,        LYE_NOP,        LYE_NOP,
+LYE_NOP,        LYE_NOP,        LYE_NOP,        LYE_NOP,
+LYE_NOP,        LYE_NOP,        LYE_NOP,        LYE_NOP,
+LYE_NOP,        LYE_NOP,        LYE_NOP,        LYE_NOP,
+LYE_NOP,        LYE_NOP,        LYE_NOP,        LYE_NOP,
+LYE_NOP,        LYE_NOP,        LYE_NOP,        LYE_NOP,
+LYE_NOP,        LYE_NOP,        LYE_NOP,        LYE_NOP,
+LYE_NOP,        LYE_NOP,        LYE_NOP,        LYE_NOP,
+LYE_NOP,        LYE_NOP,        LYE_NOP,        LYE_NOP,
+LYE_NOP,        LYE_NOP,        LYE_NOP,        LYE_NOP,
+LYE_NOP,        LYE_NOP,        LYE_NOP,        LYE_NOP,
+LYE_NOP,        LYE_NOP,        LYE_NOP,        LYE_NOP,
+LYE_NOP,        LYE_NOP,        LYE_NOP,        LYE_NOP,
+LYE_NOP,        LYE_NOP,        LYE_NOP,        LYE_NOP,
+LYE_NOP,        LYE_NOP,        LYE_NOP,        LYE_NOP,
+LYE_NOP,        LYE_NOP,        LYE_NOP,        LYE_NOP,
+LYE_NOP,        LYE_NOP,        LYE_NOP,        LYE_NOP,
+LYE_NOP,        LYE_NOP,        LYE_NOP,        LYE_NOP,
+LYE_NOP,        LYE_NOP,        LYE_NOP,        LYE_NOP,
+LYE_NOP,        LYE_NOP,        LYE_NOP,        LYE_NOP,
+LYE_NOP,        LYE_NOP,        LYE_NOP,        LYE_NOP,
+LYE_NOP,        LYE_NOP,        LYE_NOP,        LYE_NOP,
+LYE_NOP,        LYE_NOP,        LYE_NOP,        LYE_NOP,
+LYE_NOP,        LYE_NOP,        LYE_NOP,        LYE_NOP,
+LYE_NOP,        LYE_NOP,        LYE_NOP,        LYE_NOP,
+LYE_NOP,        LYE_NOP,        LYE_NOP,        LYE_NOP,
+LYE_NOP,        LYE_NOP,        LYE_NOP,        LYE_NOP,
+/* 290..293 */
+LYE_NOP,        LYE_NOP,        LYE_NOP,        LYE_NOP,
+};
+
+/*  Oh no, not another one of those tables...
+ *
+ *  If modifier bit is set in a lynxkeycode, it is first looked up
+ *  here.  Note the type different from the previous tables (short
+ *  vs. char), since we want to hold larger values.  OTOH we can
+ *  keep the size shorter, everything beyond the end is effectively
+ *  LYE_UNMOD (ignore modifier) by virtue of the LKC_TO_LEC_M1
+ *  macro.
+ *
+ *  Currently this table isn't specific to the current_lineedit value,
+ *  it is shared by all alternative "Bindings" to save space.
+ *  However, if the modifier flag is set only by a LYE_SETMn
+ *  lynxeditaction, this table can have effect only for those Bindings
+ *  that map a lynxkeycode to LYE_SETMn.  ( This doesn't apply if
+ *  the modifier is already being set in LYgetch(). ) - kw
+ */
+PRIVATE short Mod1Binding[LAST_MOD1_LKC+1]={
+
+LYE_NOP,        LYE_BOL,        LYE_BACKW,      LYE_UNMOD,
+/* nul          ^A              ^B              ^C      */
+
+LYE_FORM_LAC|LYK_NEXT_LINK,
+                LYE_FORM_LAC|LYK_EDIT_TEXTAREA,
+                                LYE_FORWW,      LYE_ABORT,
+/* ^D           ^E              ^F              ^G      */
+
+LYE_DELPW,      LYE_UNMOD,      LYE_ENTER,     LYE_FORM_LAC|LYK_LPOS_NEXT_LINK,
+/* bs           tab             nl              ^K      */
+
+LYE_FORM_PASS,  LYE_ENTER,      LYE_FORWW,      LYE_UNMOD,
+/* ^L           cr              ^N              ^O      */
+
+LYE_BACKW,      LYE_NOP,        LYE_BACKW,      LYE_NOP,
+/* ^P           XON             ^R              ^S/XOFF */
+
+LYE_NOP,        LYE_FORM_PASS,  LYE_NOP,        LYE_KILLREG,
+/* ^T           ^U              ^V              ^W      */
+
+LYE_XPMARK,     LYE_UNMOD,      LYE_FORM_PASS,  LYE_NOP,
+/* ^X           ^Y              ^Z              ESC     */
+
+LYE_FORM_PASS,  LYE_FORM_PASS,  LYE_UNMOD,      LYE_NOP,
+/* ^\           ^]              ^^              ^_      */
+
+/* sp .. ?                                              */
+LYE_UNMOD,      LYE_UNMOD,      LYE_UNMOD,      LYE_UNMOD,
+LYE_UNMOD,      LYE_UNMOD,      LYE_UNMOD,      LYE_UNMOD,
+LYE_UNMOD,      LYE_UNMOD,      LYE_UNMOD,      LYE_UNMOD,
+LYE_UNMOD,      LYE_UNMOD,      LYE_UNMOD,      LYE_FORM_PASS,
+
+LYE_UNMOD,      LYE_UNMOD,      LYE_UNMOD,      LYE_UNMOD,
+LYE_UNMOD,      LYE_UNMOD,      LYE_UNMOD,      LYE_UNMOD,
+LYE_UNMOD,      LYE_UNMOD,      LYE_UNMOD,      LYE_UNMOD,
+LYE_UNMOD,      LYE_UNMOD,      LYE_UNMOD,      LYE_UNMOD,
+
+/* @, A .. Z, [, \, ], ^, _                             */
+LYE_C1CHAR,     LYE_C1CHAR,     LYE_C1CHAR,     LYE_C1CHAR,
+LYE_C1CHAR,     LYE_C1CHAR,     LYE_C1CHAR,     LYE_C1CHAR,
+LYE_C1CHAR,     LYE_C1CHAR,     LYE_C1CHAR,     LYE_C1CHAR,
+LYE_C1CHAR,     LYE_C1CHAR,     LYE_C1CHAR,     LYE_C1CHAR,
+LYE_C1CHAR,     LYE_C1CHAR,     LYE_C1CHAR,     LYE_C1CHAR,
+LYE_C1CHAR,     LYE_C1CHAR,     LYE_C1CHAR,     LYE_C1CHAR,
+LYE_C1CHAR,     LYE_C1CHAR,     LYE_C1CHAR,     LYE_C1CHAR,
+LYE_C1CHAR,     LYE_C1CHAR,     LYE_C1CHAR,     LYE_C1CHAR,
+
+/* `, a .. z, {, |, }, ~, RUBOUT                        */
+LYE_UNMOD,      LYE_BOL,        LYE_BACKW,      LYE_UNMOD,
+LYE_DELNW,      LYE_FORM_LAC|LYK_EDIT_TEXTAREA,
+                                LYE_FORWW,      LYE_FORM_LAC|LYK_GROW_TEXTAREA,
+LYE_CHAR,       LYE_FORM_LAC|LYK_INSERT_FILE,
+                                LYE_CHAR,       LYE_ERASE,
+LYE_LOWER,      LYE_CHAR,       LYE_FORM_PASS,  LYE_UNMOD,
+LYE_CHAR,       LYE_NOP,        LYE_NOP,        LYE_NOP,
+LYE_NOP,        LYE_UPPER,      LYE_NOP,        LYE_NOP,
+LYE_NOP,        LYE_NOP,        LYE_UNMOD,      LYE_UNMOD,
+LYE_UNMOD,      LYE_UNMOD,      LYE_UNMOD,      LYE_DELPW,
+
+/* 80..9F ISO-8859-1 8-bit escape characters. */
+LYE_NOP,        LYE_NOP,        LYE_NOP,        LYE_NOP,
+LYE_NOP,        LYE_NOP,        LYE_NOP,        LYE_NOP,
+LYE_NOP,        LYE_NOP,        LYE_NOP,        LYE_NOP,
+LYE_NOP,        LYE_NOP,        LYE_NOP,        LYE_NOP,
+LYE_NOP,        LYE_NOP,        LYE_NOP,        LYE_NOP,
+LYE_NOP,        LYE_NOP,        LYE_NOP,        LYE_NOP,
+LYE_NOP,        LYE_NOP,        LYE_NOP,        LYE_NOP,
+LYE_NOP,        LYE_NOP,        LYE_NOP,        LYE_NOP,
+
+/* A0..FF (permissible ISO-8859-1) 8-bit characters. */
+LYE_UNMOD,      LYE_UNMOD,      LYE_UNMOD,      LYE_UNMOD,
+LYE_UNMOD,      LYE_UNMOD,      LYE_UNMOD,      LYE_UNMOD,
+LYE_UNMOD,      LYE_UNMOD,      LYE_UNMOD,      LYE_UNMOD,
+LYE_UNMOD,      LYE_UNMOD,      LYE_UNMOD,      LYE_UNMOD,
+LYE_UNMOD,      LYE_UNMOD,      LYE_UNMOD,      LYE_UNMOD,
+LYE_UNMOD,      LYE_UNMOD,      LYE_UNMOD,      LYE_UNMOD,
+LYE_UNMOD,      LYE_UNMOD,      LYE_UNMOD,      LYE_UNMOD,
+LYE_UNMOD,      LYE_UNMOD,      LYE_UNMOD,      LYE_UNMOD,
+LYE_UNMOD,      LYE_UNMOD,      LYE_UNMOD,      LYE_UNMOD,
+LYE_UNMOD,      LYE_UNMOD,      LYE_UNMOD,      LYE_UNMOD,
+LYE_UNMOD,      LYE_UNMOD,      LYE_UNMOD,      LYE_UNMOD,
+LYE_UNMOD,      LYE_UNMOD,      LYE_UNMOD,      LYE_UNMOD,
+LYE_UNMOD,      LYE_UNMOD,      LYE_UNMOD,      LYE_UNMOD,
+LYE_UNMOD,      LYE_UNMOD,      LYE_UNMOD,      LYE_UNMOD,
+LYE_UNMOD,      LYE_UNMOD,      LYE_UNMOD,      LYE_UNMOD,
+LYE_UNMOD,      LYE_UNMOD,      LYE_UNMOD,      LYE_UNMOD,
+LYE_UNMOD,      LYE_UNMOD,      LYE_UNMOD,      LYE_UNMOD,
+LYE_UNMOD,      LYE_UNMOD,      LYE_UNMOD,      LYE_UNMOD,
+LYE_UNMOD,      LYE_UNMOD,      LYE_UNMOD,      LYE_UNMOD,
+LYE_UNMOD,      LYE_UNMOD,      LYE_UNMOD,      LYE_UNMOD,
+LYE_UNMOD,      LYE_UNMOD,      LYE_UNMOD,      LYE_UNMOD,
+LYE_UNMOD,      LYE_UNMOD,      LYE_UNMOD,      LYE_UNMOD,
+LYE_UNMOD,      LYE_UNMOD,      LYE_UNMOD,      LYE_UNMOD,
+LYE_UNMOD,      LYE_UNMOD,      LYE_UNMOD,      LYE_UNMOD,
+
+/* 100..10F function key definitions in LYStrings.h */
+LYE_UNMOD,      LYE_UNMOD,      LYE_UNMOD,      LYE_UNMOD,
+/* UPARROW      DNARROW         RTARROW         LTARROW     */
+
+LYE_UNMOD,      LYE_UNMOD,      LYE_FORM_PASS,  LYE_FORM_PASS,
+/* PGDOWN       PGUP            HOME            END         */
+
+#if (defined(_WINDOWS) || defined(__DJGPP__))
+
+LYE_FORM_LAC|LYK_DWIMHELP,
+                LYE_UNMOD,      LYE_UNMOD,      LYE_UNMOD,
+/* F1 */
+
+#else
+
+LYE_FORM_LAC|LYK_DWIMHELP,
+                LYE_UNMOD,  LYE_FORM_LAC|LYK_WHEREIS, LYE_FORM_LAC|LYK_NEXT,
+/* F1           Do key          Find key        Select key  */
+
+#endif /* _WINDOWS || __DJGPP__ */
+
+LYE_UNMOD,      LYE_NOP,        LYE_UNMOD,      LYE_UNMOD,    
+/* Insert key   Remove key      DO_NOTHING      Back tab */
+
+/* 110..18F */
+#if (defined(_WINDOWS) || defined(__DJGPP__)) && defined(USE_SLANG) && !defined(DJGPP_KEYHANDLER)
+
+LYE_DELPW,      LYE_UNMOD,
+/* Backspace    Enter */
+
+#else
+
+LYE_UNMOD,      LYE_UNMOD,
+
+#endif /* USE_SLANG &&(_WINDOWS || __DJGPP) && !DJGPP_KEYHANDLER */
+};
+
+/*  Two more tables here, but currently they are all the same.
+    In other words, we are cheating to save space, until there
+    is a need for different tables. - kw */
+PRIVATE short *Mod2Binding = Mod1Binding;
+PRIVATE short *Mod3Binding = Mod1Binding;
+
+#endif /* EXP_ALT_BINDINGS */
 
 
 /*
@@ -486,22 +912,129 @@ PUBLIC char * LYLineEditors[]={
         DefaultEditBinding,     /* You can't please everyone, so you ... DW */
 #ifdef EXP_ALT_BINDINGS
 	BetterEditBinding,      /* No, you certainly can't ... /ked 10/27/98*/
+	BashlikeEditBinding,      /* and one more... - kw 1999-02-15 */
 #endif
 };
 
 /*
  * Add the name that the user will see below.
- * The order of LYLineEditors and LyLineditNames MUST be the same
+ * The order of LYLineEditors and LYLineditNames MUST be the same.
  */
 PUBLIC char * LYLineeditNames[]={
 	"Default Binding",
 #ifdef EXP_ALT_BINDINGS
 	"Alternate Bindings",
+	"Bash-like Bindings",
 #endif
 	(char *) 0
 };
 
 /*
+ * Add the URL (relative to helpfilepath) used for context-dependent
+ * help on form field editing.
+ * 
+ * The order must correspond to that of LYLineditNames.
+ */
+PUBLIC CONST char * LYLineeditHelpURLs[]={
+	EDIT_HELP,
+#ifdef EXP_ALT_BINDINGS
+	ALT_EDIT_HELP,
+	BASHLIKE_EDIT_HELP,
+#endif
+	(char *) 0
+};
+
+PUBLIC int EditBinding ARGS1(
+    int,	xlkc)
+{
+    int editaction, xleac = LYE_UNMOD;
+    int c = xlkc & LKC_MASK;
+
+    if (xlkc == -1)
+	return LYE_NOP;	/* maybe LYE_ABORT? or LYE_FORM_LAC|LYK_UNKNOWN? */
+#ifdef NOT_ASCII
+    if (c < 256) {
+	c = TOASCII(c);
+    }
+#endif
+#ifdef EXP_ALT_BINDINGS
+    /*
+     *  Get intermediate code from one of the lynxkeycode+modifier
+     *  tables if applicable, otherwise get the lynxeditactioncode
+     *  directly.
+     *  If we have more than one modifier bits, the first currently
+     *  wins. - kw
+     */
+    if (xlkc & LKC_MOD1) {
+	xleac = LKC_TO_LEC_M1(c);
+    } else if (xlkc & LKC_MOD2) {
+	xleac = LKC_TO_LEC_M2(c);
+    } else if (xlkc & LKC_MOD3) {
+	xleac = LKC_TO_LEC_M3(c);
+    } else {
+	xleac = (unsigned char)LYLineEditors[current_lineedit][c];
+    }
+#endif
+    /*
+     *  If we have an intermediate code that says "same as without
+     *  modifier", look that up now; otherwise we are already done. - kw
+     */
+    if (xleac == LYE_UNMOD) {
+	editaction = LYLineEditors[current_lineedit][c];
+    } else {
+	editaction = xleac;
+    }
+    return editaction;
+}
+
+/*
+ *  Install lec as the lynxeditaction for lynxkeycode xlkc.
+ *  func must be present in the revmap table.
+ *  returns TRUE if the mapping was made, FALSE if not.
+ *  Note that this remapping cannot be undone (as might be desirable
+ *  as a result of re-parsing lynx.cfg), we don't remember the
+ *  original editaction from the Bindings tables anywhere. - kw
+ */
+PUBLIC int LYRemapEditBinding ARGS2(
+    int,	xlkc,
+    int,	lec)
+{
+    int j;
+    int c = xlkc & LKC_MASK;
+    if (xlkc < 0 || (xlkc&LKC_ISLAC) || c >= KEYMAP_SIZE + 1)
+	return FALSE;
+#ifdef EXP_ALT_BINDINGS
+    if (xlkc & LKC_MOD1) {
+	if (c > LAST_MOD1_LKC)
+	    return FALSE;
+	else
+	    Mod1Binding[c] = lec;
+    } else if (xlkc & LKC_MOD2) {
+	if (c > LAST_MOD2_LKC)
+	    return FALSE;
+	else
+	    Mod2Binding[c] = lec;
+    } else if (xlkc & LKC_MOD3) {
+	if (c > LAST_MOD3_LKC)
+	    return FALSE;
+	else
+	    Mod3Binding[c] = lec;
+    } else
+#endif /* EXP_ALT_BINDINGS */
+    {
+#ifndef UCHAR_MAX
+#define UCHAR_MAX 255
+#endif
+	if ((unsigned int)lec > UCHAR_MAX)
+	    return FALSE;	/* cannot do, doesn't fit in a char - kw */
+	for (j = 0; LYLineeditNames[j]; j++) {
+	    LYLineEditors[j][c] = lec;
+	}
+    }
+    return TRUE;
+}
+
+/*
  * Dummy initializer to ensure this module is linked
  * if the external model is common block, and the
  * module is ever placed in a library. - FM
diff --git a/src/LYForms.c b/src/LYForms.c
index 399f61df..36f06b7f 100644
--- a/src/LYForms.c
+++ b/src/LYForms.c
@@ -23,7 +23,8 @@
 extern HTCJKlang HTCJK;
 
 PRIVATE int form_getstr PARAMS((
-	struct link *	form_link));
+	struct link *	form_link,
+	BOOLEAN		use_last_tfpos));
 PRIVATE int popup_options PARAMS((
 	int		cur_selection,
 	OptionType *	list,
@@ -33,14 +34,17 @@ PRIVATE int popup_options PARAMS((
 	int		i_length,
 	int		disabled));
 
-PUBLIC int change_form_link ARGS5(
+PUBLIC int change_form_link ARGS7(
 	struct link *,	form_link,
 	document *,	newdoc,
 	BOOLEAN *,	refresh_screen,
 	char *,		link_name,
-	char *,		link_value)
+	char *,		link_value,
+	BOOLEAN,	use_last_tfpos,
+	BOOLEAN,	immediate_submit)
 {
     FormInfo *form = form_link->form;
+    int newdoc_changed = 0;
     int c = DO_NOTHING;
     int OrigNumValue;
 
@@ -174,7 +178,7 @@ PUBLIC int change_form_link ARGS5(
 	case F_TEXT_TYPE:
 	case F_TEXTAREA_TYPE:
 	case F_PASSWORD_TYPE:
-	    c = form_getstr(form_link);
+	    c = form_getstr(form_link, use_last_tfpos);
 	    if (form->type == F_PASSWORD_TYPE)
 		form_link->hightext = STARS(strlen(form->value));
 	    else
@@ -189,13 +193,36 @@ PUBLIC int change_form_link ARGS5(
 	    break;
 
 	case F_TEXT_SUBMIT_TYPE:
-	    c = form_getstr(form_link);
+	    if (!immediate_submit)
+		c = form_getstr(form_link, use_last_tfpos);
 	    if (form->disabled == YES &&
-		(c == '\r' || c == '\n')) {
+		(c == '\r' || c == '\n' || immediate_submit)) {
+		if (peek_mouse_link() >= 0)
+		    c = lookup_keymap(LYK_ACTIVATE);
+		else
 		c = '\t';
 		break;
 	    }
-	    if (c == '\r' || c == '\n') {
+	    /*
+	     *  If immediate_submit is set, we didn't enter the line editor
+	     *  above, and will now try to call HText_SubmitForm() directly.
+	     *  If immediate_submit is not set, c is the lynxkeycode returned
+	     *  from line editing.   Then if c indicates that a key was pressed
+	     *  that means we should submit, but with some extra considerations
+	     *  (i.e. NOCACHE, DOWNLOAD, different from simple Enter), or if
+	     *  we should act on some *other* link selected with the mouse,
+	     *  we'll just return c and leave it to mainloop() to do the
+	     *  right thing; if everything checks out, it should call this
+	     *  function again, with immediate_submit set.
+	     *  If c indicates that line editing ended with Enter, we still
+	     *  defer to mainloop() for further checking if the submit
+	     *  action URL could require more checks than we do here.
+	     *  call HText_SubmitForm() directly before returning.
+	     *  Only in the remaining cases do we proceed directly. - kw
+	     */
+	    if (immediate_submit ||
+		((c == '\r' || c == '\n' || c == LAC_TO_LKC0(LYK_SUBMIT)) &&
+		 peek_mouse_link() == -1)) {
 		form_link->hightext = form->value;
 		if (!form->submit_action || *form->submit_action == '\0') {
 		    HTUserMsg(NO_FORM_ACTION);
@@ -205,13 +232,20 @@ PUBLIC int change_form_link ARGS5(
 		    HTAlert(FORM_MAILTO_DISALLOWED);
 		    c = DO_NOTHING;
 		    break;
+		} else if (!immediate_submit &&
+			   ((no_file_url &&
+			     !strncasecomp(form->submit_action, "file:", 5)) ||
+			    !strncasecomp(form->submit_action, "lynx", 4))) {
+		    c = LAC_TO_LKC0(LYK_SUBMIT);
+		    break;
 		} else {
 		    if (form->no_cache &&
 			form->submit_method != URL_MAIL_METHOD) {
 			LYforce_no_cache = TRUE;
 			reloading = TRUE;
 		    }
-		    HText_SubmitForm(form, newdoc, link_name, form->value);
+		    newdoc_changed =
+			HText_SubmitForm(form, newdoc, link_name, form->value);
 		}
 		if (form->submit_method == URL_MAIL_METHOD) {
 		    *refresh_screen = TRUE;
@@ -238,7 +272,8 @@ PUBLIC int change_form_link ARGS5(
 		LYforce_no_cache = TRUE;
 		reloading = TRUE;
 	    }
-	    HText_SubmitForm(form, newdoc, link_name, link_value);
+	    newdoc_changed =
+		HText_SubmitForm(form, newdoc, link_name, link_value);
 	    if (form->submit_method == URL_MAIL_METHOD)
 		*refresh_screen = TRUE;
 	    else {
@@ -250,11 +285,37 @@ PUBLIC int change_form_link ARGS5(
 
     }
 
+    if (newdoc_changed) {
+	c = LKC_DONE;
+    } else {
+	/*
+	 *  These flags may have been set in mainloop, anticipating that
+	 *  a request will be submitted.  But if we haven't filled in
+	 *  newdoc, that won't actually be the case, so unset them. - kw
+	 */
+	LYforce_no_cache = FALSE;
+	reloading = FALSE;
+    }
     return(c);
 }
 
-PRIVATE int form_getstr ARGS1(
-	struct link *,	form_link)
+PRIVATE int LastTFPos = -1;	/* remember last text field position */
+
+PRIVATE void LYSetLastTFPos ARGS1(
+    int,	pos)
+{
+    LastTFPos = pos;
+}
+#if 0
+PRIVATE int LYLastTFPos NOARGS
+{
+    return(LastTFPos);
+}
+#endif /* 0 */
+
+PRIVATE int form_getstr ARGS2(
+	struct link *,	form_link,
+	BOOLEAN,	use_last_tfpos)
 {
     FormInfo *form = form_link->form;
     char *value = form->value;
@@ -263,7 +324,8 @@ PRIVATE int form_getstr ARGS1(
     int max_length;
     int startcol, startline;
     BOOL HaveMaxlength = FALSE;
-    int action, repeat, non_first = 0;
+    int action, repeat;
+    int last_xlkc = -1;
 
     EditFieldData MyEdit;
     BOOLEAN Edited = FALSE;		/* Value might be updated? */
@@ -296,6 +358,8 @@ PRIVATE int form_getstr ARGS1(
 	     *  If we can edit it, report that we are using the tail. - FM
 	     */
 	    HTUserMsg(FORM_VALUE_TOO_LONG);
+	    show_formlink_statusline(form);
+#if 0				/* using function above instead */
 	    switch(form->type) {
 		case F_PASSWORD_TYPE:
 		    statusline(FORM_LINK_PASSWORD_MESSAGE);
@@ -318,6 +382,7 @@ PRIVATE int form_getstr ARGS1(
 		default:
 		    break;
 	    }
+#endif /* 0 - using function instead */
 	    move(startline, startcol);
 	}
     }
@@ -328,6 +393,18 @@ PRIVATE int form_getstr ARGS1(
     LYSetupEdit(&MyEdit, value, max_length, (far_col - startcol));
     MyEdit.pad = '_';
     MyEdit.hidden = (form->type == F_PASSWORD_TYPE);
+    if (use_last_tfpos && LastTFPos >= 0 && LastTFPos < MyEdit.strlen) {
+	MyEdit.pos = LastTFPos;
+#ifdef ENHANCED_LINEEDIT
+	if (MyEdit.pos == 0)
+	    MyEdit.mark = MyEdit.strlen;
+#endif
+    }
+    /* Try to prepare for setting position based on the last mouse event */
+    if (peek_mouse_levent()) {
+	if (!use_last_tfpos)
+	    MyEdit.pos = 0;
+    }
     LYRefreshEdit(&MyEdit);
 
     /*
@@ -337,9 +414,6 @@ PRIVATE int form_getstr ARGS1(
 again:
 	repeat = -1;
 	get_mouse_link();		/* Reset mouse_link. */
-	/* Try to set position basing on the last mouse event */
-	if (!non_first++)
-	    peek_mouse_levent();
 
 	ch = LYgetch_for(FOR_INPUT);
 #ifdef VMS
@@ -349,6 +423,8 @@ again:
 	}
 #endif /* VMS */
 #  ifdef NCURSES_MOUSE_VERSION
+	if (ch != -1 && (ch&LKC_ISLAC))	/* already lynxactioncode? */
+	    break;	/* @@@ maybe move these 2 lines outside ifdef -kw */
 	if (ch == MOUSE_KEY) {		/* Need to process ourselves */
 	    MEVENT	event;
 	    int curx, cury;
@@ -362,23 +438,66 @@ again:
 		    repeat = - repeat;
 		} else
 		    ch = RTARROW;
+	    } else {
+		/*  Mouse event passed to us as MOUSE_KEY, and apparently
+		 *  not on this field's line?  Something is not as it
+		 *  should be...
+		 *  A call to statusline() may have happened, possibly from
+		 *  within a mouse menu.  Let's at least make sure here
+		 *  that the cursor position gets restored.  - kw
+		 */
+		MyEdit.dirty = TRUE;
 	    }
-	}
+	    last_xlkc = -1;
+	} else
 #  endif	/* defined NCURSES_MOUSE_VERSION */
+	{
+	    ch |= MyEdit.current_modifiers;
+	    MyEdit.current_modifiers = 0;
+	    if (last_xlkc != -1) {
+		if (ch == last_xlkc)
+		    ch |= LKC_MOD3;
+		last_xlkc = -1;	/* consumed */
+	    }
+	}
 	if (peek_mouse_link() != -1)
 	    break;
+	action = EditBinding(ch);
+	if ((action & LYE_DF) && !(action & LYE_FORM_LAC)) {
+	    last_xlkc = ch;
+	    action &= ~LYE_DF;
+	} else {
+	    last_xlkc = -1;
+	}
+	if (action == LYE_SETM1) {
+	    /*
+	     *  Set flag for modifier 1.
+	     */
+	    MyEdit.current_modifiers |= LKC_MOD1;
+	    continue;
+	}
+	if (action == LYE_SETM2) {
+	    /*
+	     *  Set flag for modifier 2.
+	     */
+	    MyEdit.current_modifiers |= LKC_MOD2;
+	    continue;
+	}
 	/*
 	 *  Filter out global navigation keys that should not be passed
 	 *  to line editor, and LYK_REFRESH.
 	 */
-	action = EditBinding(ch);
 	if (action == LYE_ENTER)
 	    break;
 	if (action == LYE_FORM_PASS)
 	    break;
+	if (action & LYE_FORM_LAC) {
+	    ch = (action & LAC_MASK) | LKC_ISLAC;
+	    break;
+	}
 	if (action == LYE_LKCMD) {
 	    _statusline(ENTER_LYNX_COMMAND);
-	    ch = LYgetch();
+	    ch = LYgetch_for(FOR_PANEL);
 #ifdef VMS
 	    if (HadVMSInterrupt) {
 		HadVMSInterrupt = FALSE;
@@ -397,7 +516,7 @@ again:
 	if (action == LYE_ABORT) {
 	    return(DO_NOTHING);
 	}
-	if (keymap[ch + 1] == LYK_REFRESH)
+	if (LKC_TO_LAC(keymap,ch) == LYK_REFRESH)
 	    break;
 	switch (ch) {
 #ifdef NOTDEFINED	/* The first four are mapped to LYE_FORM_PASS now */
@@ -454,6 +573,7 @@ again:
 		    Edited = TRUE;
 		}
 		LYRefreshEdit(&MyEdit);
+		LYSetLastTFPos(MyEdit.pos);
 	}
     }
 #ifdef NOTDEFINED
@@ -881,7 +1001,7 @@ redraw:
 		break;
 #endif
 	} else {
-	    cmd = keymap[c+1];
+	    cmd = LKC_TO_LAC(keymap,c);
 	}
 #ifdef VMS
 	if (HadVMSInterrupt) {
@@ -1094,6 +1214,7 @@ redraw:
 		break;
 
 	    case LYK_PREV_LINK:
+	    case LYK_LPOS_PREV_LINK:
 	    case LYK_FASTBACKW_LINK:
 	    case LYK_UP_LINK:
 
@@ -1110,6 +1231,7 @@ redraw:
 		break;
 
 	    case LYK_NEXT_LINK:
+	    case LYK_LPOS_NEXT_LINK:
 	    case LYK_FASTFORW_LINK:
 	    case LYK_DOWN_LINK:
 		if (cur_selection < num_options)
@@ -1560,3 +1682,114 @@ restore_popup_statusline:
 
     return(disabled ? orig_selection : cur_selection);
 }
+
+/*
+ *  Display statusline info tailored for the current form field.
+ */
+PUBLIC void show_formlink_statusline ARGS1(
+    CONST FormInfo *,	form)
+{
+    switch(form->type) {
+    case F_PASSWORD_TYPE:
+	if (form->disabled == YES)
+	    statusline(FORM_LINK_PASSWORD_UNM_MSG);
+	else
+	    statusline(FORM_LINK_PASSWORD_MESSAGE);
+	break;
+    case F_OPTION_LIST_TYPE:
+	if (form->disabled == YES)
+	    statusline(FORM_LINK_OPTION_LIST_UNM_MSG);
+	else
+	    statusline(FORM_LINK_OPTION_LIST_MESSAGE);
+	break;
+    case F_CHECKBOX_TYPE:
+	if (form->disabled == YES)
+	    statusline(FORM_LINK_CHECKBOX_UNM_MSG);
+	else
+	    statusline(FORM_LINK_CHECKBOX_MESSAGE);
+	break;
+    case F_RADIO_TYPE:
+	if (form->disabled == YES)
+	    statusline(FORM_LINK_RADIO_UNM_MSG);
+	else
+	    statusline(FORM_LINK_RADIO_MESSAGE);
+	break;
+    case F_TEXT_SUBMIT_TYPE:
+	if (form->disabled == YES) {
+	    statusline(FORM_LINK_TEXT_SUBMIT_UNM_MSG);
+	} else if (form->submit_method ==
+		   URL_MAIL_METHOD) {
+	    if (no_mail)
+		statusline(FORM_LINK_TEXT_SUBMIT_MAILTO_DIS_MSG);
+	    else
+		statusline(FORM_LINK_TEXT_SUBMIT_MAILTO_MSG);
+	} else if (form->no_cache) {
+	    statusline(FORM_LINK_TEXT_RESUBMIT_MESSAGE);
+	} else {
+	    statusline(FORM_LINK_TEXT_SUBMIT_MESSAGE);
+	}
+	break;
+    case F_SUBMIT_TYPE:
+    case F_IMAGE_SUBMIT_TYPE:
+	if (form->disabled == YES) {
+	    statusline(FORM_LINK_SUBMIT_DIS_MSG);
+	} else if (form->submit_method ==
+		   URL_MAIL_METHOD) {
+	    if (no_mail) {
+		statusline(FORM_LINK_SUBMIT_MAILTO_DIS_MSG);
+	    } else {
+		if(user_mode == ADVANCED_MODE) {
+		    char *submit_str = NULL;
+
+		    StrAllocCopy(submit_str, FORM_LINK_SUBMIT_MAILTO_PREFIX);
+		    StrAllocCat(submit_str, form->submit_action);
+		    statusline(submit_str);
+		    FREE(submit_str);
+		} else {
+		    statusline(FORM_LINK_SUBMIT_MAILTO_MSG);
+		}
+	    }
+	} else if (form->no_cache) {
+	    if(user_mode == ADVANCED_MODE) {
+		char *submit_str = NULL;
+
+		StrAllocCopy(submit_str, FORM_LINK_RESUBMIT_PREFIX);
+		StrAllocCat(submit_str, form->submit_action);
+		statusline(submit_str);
+		FREE(submit_str);
+	    } else {
+		statusline(FORM_LINK_RESUBMIT_MESSAGE);
+	    }
+	} else {
+	    if(user_mode == ADVANCED_MODE) {
+		char *submit_str = NULL;
+
+		StrAllocCopy(submit_str, FORM_LINK_SUBMIT_PREFIX);
+		StrAllocCat(submit_str, form->submit_action);
+		statusline(submit_str);
+		FREE(submit_str);
+	    } else {
+		statusline(FORM_LINK_SUBMIT_MESSAGE);
+	    }
+	}
+	break;
+    case F_RESET_TYPE:
+	if (form->disabled == YES)
+	    statusline(FORM_LINK_RESET_DIS_MSG);
+	else
+	    statusline(FORM_LINK_RESET_MESSAGE);
+	break;
+    case F_TEXT_TYPE:
+	if (form->disabled == YES)
+	    statusline(FORM_LINK_TEXT_UNM_MSG);
+	else
+	    statusline(FORM_LINK_TEXT_MESSAGE);
+	break;
+    case F_TEXTAREA_TYPE:
+	if (form->disabled == YES)
+	    statusline(FORM_LINK_TEXT_UNM_MSG);
+	else
+	    statusline(FORM_LINK_TEXTAREA_MESSAGE);
+	break;
+    }
+}
diff --git a/src/LYGetFile.c b/src/LYGetFile.c
index 0850a8ae..2bb09ea3 100644
--- a/src/LYGetFile.c
+++ b/src/LYGetFile.c
@@ -38,12 +38,43 @@
 #endif /* SYSLOG_REQUESTED_URLS */
 #endif /* !VMS */
 
-PRIVATE int fix_http_urls PARAMS((document *doc));
+PRIVATE int fix_httplike_urls PARAMS((document *doc, UrlTypes type));
 extern char * WWW_Download_File;
 #ifdef VMS
 extern BOOLEAN LYDidRename;
 #endif /* VMS */
 
+#ifdef VMS
+#define STRNADDRCOMP strncasecomp
+#else
+#define STRNADDRCOMP strncmp
+#endif /* !VMS */
+
+PUBLIC int HTNoDataOK = 0;
+
+/*
+ *  getfile is the main mechanism to load a new document (or a previously
+ *  laoded one whose rendering is cached in a HText structure) from
+ *  mainloop, nearly everything goes through it.
+ *  It should return one of the values
+ *     NORMAL     - requested document loaded successfully, usually [always?]
+ *                  its rendering is available as HTMainText.  It can be an
+ *                  HTTP error message page or similar, we make no
+ *                  distinction here.
+ *     NOT_FOUND  - requested document cannot be accessed, and the reason
+ *                  is a real error (as may be caused by an invalid link),
+ *                  not just that lynx disallows access because of some
+ *                  permission restrictions, and we have no error page
+ *                  to show for it either.
+ *     NULLFILE   - requested document not loaded into HTMainText, either
+ *                  some interactive protocol was requested (like telnet),
+ *                  or lynx does not allow access, 
+ *  The distinction between NOT_FOUND and NULLFILE is not very crucial,
+ *  but getting it right prevents mainloop from exiting with the wrong
+ *  message if it happens for the first file, and from logging (or not
+ *  logging) errors inappropriately with -traversal, and from sending
+ *  bogus error mail with MAIL_SYSTEM_ERROR_LOGGING:TRUE. - kw
+ */
 PUBLIC BOOLEAN getfile ARGS1(
 	document *,	doc)
 {
@@ -65,6 +96,14 @@ PUBLIC BOOLEAN getfile ARGS1(
 	 */
 	LYFakeZap(NO);
 
+	/*
+	 *  Reset redirection counter to prevent bogus TOO_MANY_REDIRECTIONS
+	 *  in rare situations if the previous cycle got to the limit, but
+	 *  did not fail for that reason because the URL of the final location
+	 *  was handled specially, not via HTLoadAbsolute. - kw
+	 */
+	redirection_attempts = 0;
+
 Try_Redirected_URL:
 	/*
 	 *  Load the WWWDoc struct in case we need to use it.
@@ -77,6 +116,11 @@ Try_Redirected_URL:
 	WWWDoc.safe = doc->safe;
 
 	/*
+	 *  Reset HTPermitRedir, it has done its job if it was set. - kw
+	 */
+	HTPermitRedir = FALSE;
+
+	/*
 	 *  Reset WWW_Download_File just in case.
 	 */
 	FREE(WWW_Download_File);
@@ -86,6 +130,19 @@ Try_Redirected_URL:
 	 */
 	redirect_post_content = FALSE;
 
+	/*
+	 *  This flag is a hack to allow us to pass on the fact
+	 *  that 'no data' may not really be an error although
+	 *  HTLoadAbsolute returned NO.  There should be a better
+	 *  way...  HT_NO_DATA should always mean 'not data but
+	 *  not an error', and be passed on to us as that, but
+	 *  current usage if HT_NO_DATA vs HT_NOT_LOADED has
+	 *  to be reviewed everywhere.
+	 *  Anyway, some protocol module can set it to say
+	 *  'I really mean it', we have to reset it here. - kw
+	 */
+	HTNoDataOK = 0;
+
 	CTRACE(tfp,"getfile: getting %s\n\n",doc->address);
 
 	/*
@@ -148,16 +205,19 @@ Try_Redirected_URL:
 			  url_type == LYNXKEYMAP_URL_TYPE ||
 			  url_type == LYNXIMGMAP_URL_TYPE ||
 			  url_type == LYNXCOOKIE_URL_TYPE ||
-			  0==strncasecomp(WWWDoc.address, helpfilepath,
+			  url_type == LYNXMESSAGES_URL_TYPE ||
+			  (url_type == LYNXOPTIONS_URL_TYPE &&
+			   WWWDoc.post_data) ||
+			  0==STRNADDRCOMP(WWWDoc.address, helpfilepath,
 					  strlen(helpfilepath)) ||
 			  (lynxlistfile != NULL &&
-			   0==strncasecomp(WWWDoc.address, lynxlistfile,
+			   0==STRNADDRCOMP(WWWDoc.address, lynxlistfile,
 					  strlen(lynxlistfile))) ||
 			  (lynxlinksfile != NULL &&
-			   0==strncasecomp(WWWDoc.address, lynxlinksfile,
+			   0==STRNADDRCOMP(WWWDoc.address, lynxlinksfile,
 					  strlen(lynxlinksfile))) ||
 			  (lynxjumpfile != NULL &&
-			   0==strncasecomp(WWWDoc.address, lynxjumpfile,
+			   0==STRNADDRCOMP(WWWDoc.address, lynxjumpfile,
 					  strlen(lynxjumpfile))))) {
 			HTUserMsg(NOT_HTTP_URL_OR_ACTION);
 			return(NULLFILE);
@@ -181,6 +241,7 @@ Try_Redirected_URL:
 			  url_type == LYNXOPTIONS_URL_TYPE ||
 			  url_type == LYNXCFG_URL_TYPE ||
 			  url_type == LYNXCOMPILE_OPTS_URL_TYPE ||
+			  url_type == LYNXMESSAGES_URL_TYPE ||
 			  url_type == LYNXDOWNLOAD_URL_TYPE ||
 			  url_type == MAILTO_URL_TYPE ||
 			  url_type == NEWSPOST_URL_TYPE ||
@@ -193,13 +254,13 @@ Try_Redirected_URL:
 			    url_type == LYNXCGI_URL_TYPE)) ||
 			  (WWWDoc.bookmark != NULL &&
 			   *WWWDoc.bookmark != '\0') ||
-			  0==strncasecomp(WWWDoc.address, helpfilepath,
+			  0==STRNADDRCOMP(WWWDoc.address, helpfilepath,
 					  strlen(helpfilepath)) ||
 			  (lynxlistfile != NULL &&
-			   0==strncasecomp(WWWDoc.address, lynxlistfile,
+			   0==STRNADDRCOMP(WWWDoc.address, lynxlistfile,
 					  strlen(lynxlistfile))) ||
 			  (lynxjumpfile != NULL &&
-			   0==strncasecomp(WWWDoc.address, lynxjumpfile,
+			   0==STRNADDRCOMP(WWWDoc.address, lynxjumpfile,
 					  strlen(lynxjumpfile))))) {
 			HTUserMsg(NOT_IN_STARTING_REALM);
 			return(NULLFILE);
@@ -249,20 +310,22 @@ Try_Redirected_URL:
 		    return(postoptions(doc));
 #endif
 
-		} else if (url_type == LYNXCFG_URL_TYPE) {
+		} else if (url_type == LYNXCFG_URL_TYPE &&
+		    !no_lynxcfg_info) {
+		    /* @@@ maybe we should generate a specific error message
+		       if attempted but restricted. - kw */
 		    /* show/change/reload lynx.cfg settings */
 		    return(lynx_cfg_infopage(doc));
 
 #if defined(HAVE_CONFIG_H) && !defined(NO_CONFIG_INFO)
-		} else if (url_type == LYNXCOMPILE_OPTS_URL_TYPE) {
+		} else if (url_type == LYNXCOMPILE_OPTS_URL_TYPE &&
+		    !no_compileopts_info) {
+		    /* @@@ maybe we should generate a specific error message
+		       if attempted but restricted or not supported. - kw */
 		    /* show compile-time settings */
 		    return(lynx_compile_opts(doc));
 #endif
 
-		} else if (url_type == LYNXMESSAGES_URL_TYPE) {
-		    /* show list of recent statusline messages */
-		    return(LYshow_statusline_messages(doc));
-
 #ifndef DISABLE_NEWS
 		} else if (url_type == NEWSPOST_URL_TYPE ||
 			   url_type == NEWSREPLY_URL_TYPE ||
@@ -272,6 +335,11 @@ Try_Redirected_URL:
 		    if (no_newspost) {
 			HTUserMsg(NEWSPOSTING_DISABLED);
 			return(NULLFILE);
+		    } else if (!news_ok && (
+			url_type == NEWSPOST_URL_TYPE ||
+			url_type == NEWSREPLY_URL_TYPE)) {
+			HTUserMsg(NEWS_DISABLED);
+			return(NULLFILE);
 		    } else {
 			HTLoadAbsolute(&WWWDoc);
 			return(NULLFILE);
@@ -319,7 +387,28 @@ Try_Redirected_URL:
 		    return(NULLFILE);
 #endif /* DIRED_SUPPORT */
 
-		} else if (url_type == LYNXHIST_URL_TYPE) {
+		}
+		if (LYNoRefererHeader == FALSE &&
+		    LYNoRefererForThis == FALSE) {
+		    if (no_filereferer == TRUE &&
+			!strncmp(HTLoadedDocumentURL(), "file:", 5)) {
+			LYNoRefererForThis = TRUE;
+		    }
+		    if (LYNoRefererForThis == FALSE &&
+			(cp = strchr(HTLoadedDocumentURL(), '?')) != NULL &&
+		    strchr(cp, '=') != NULL) {
+			/*
+			 *  Don't send a Referer header if the URL is
+			 *  the reply from a form with method GET, in
+			 *  case the content has personal data (e.g.,
+			 *  a password or credit card number) which
+			 *  would become visible in logs. - FM
+			 */
+			LYNoRefererForThis = TRUE;
+			cp = NULL;
+		    }
+		}
+		if (url_type == LYNXHIST_URL_TYPE) {
 		    /*
 		     *	'doc' will change to the new file
 		     *	if we had a successful LYpop_num(),
@@ -413,8 +502,10 @@ Try_Redirected_URL:
 			    HadVMSInterrupt = FALSE;
 #endif /* VMS */
 			}
-			start_curses();
-			LYAddVisitedLink(doc);
+			if (!dump_output_immediately) {
+			    start_curses();
+			    LYAddVisitedLink(doc);
+			}
 
 		     } else {
 			char *buf = 0;
@@ -473,11 +564,13 @@ Try_Redirected_URL:
 		 *  so check if that's allowed.
 		 */
 		} else if (local_host_only &&
-			   url_type != NEWS_URL_TYPE &&
 			   url_type != LYNXKEYMAP_URL_TYPE &&
 			   url_type != LYNXIMGMAP_URL_TYPE &&
 			   url_type != LYNXCOOKIE_URL_TYPE &&
+			   url_type != LYNXMESSAGES_URL_TYPE &&
 			   url_type != LYNXCGI_URL_TYPE &&
+			   !(url_type == NEWS_URL_TYPE &&
+			     strncmp(doc->address, "news://", 7)) &&
 			   !(LYisLocalHost(doc->address) ||
 			     LYisLocalAlias(doc->address))) {
 		    HTUserMsg(ACCESS_ONLY_LOCALHOST);
@@ -489,39 +582,76 @@ Try_Redirected_URL:
 		} else if (url_type == TELNET_URL_TYPE ||
 			   url_type == TN3270_URL_TYPE ||
 			   url_type == TELNET_GOPHER_URL_TYPE) {
+		    char * proxy;
 		    if (!telnet_ok) {
 			HTUserMsg(TELNET_DISABLED);
+			return(NULLFILE);
 		    } else if (no_telnet_port && strchr(doc->address+7, ':')) {
 			HTUserMsg(TELNET_PORT_SPECS_DISABLED);
+			return(NULLFILE);
+		    /*
+		     *  Detect weird case where interactive protocol would
+		     *  be proxied, and to a non-interactive protocol at that.
+		     */
+		    } else if ((proxy = (char *)getenv(
+			(url_type==TN3270_URL_TYPE) ? "tn3270_proxy" :
+			(url_type==TELNET_GOPHER_URL_TYPE) ? "gopher_proxy" :
+			"telnet_proxy")) != NULL &&
+			       *proxy != '\0' &&
+			       !override_proxy(doc->address) &&
+			       (strncmp(proxy, "telnet:", 7) &&
+				strncmp(proxy, "tn3270:", 7) &&
+				strncmp(proxy, "rlogin:", 7))) {
+			/* Do nothing, fall through to generic code - kw */
 		    } else {
 			stop_curses();
 			HTLoadAbsolute(&WWWDoc);
-			start_curses();
-			fflush(stdout);
-			LYAddVisitedLink(doc);
+			if (!dump_output_immediately) {
+			    start_curses();
+			    fflush(stdout);
+			    LYAddVisitedLink(doc);
+			}
+			return(NULLFILE);
 		    }
-		    return(NULLFILE);
 
 		/*
 		 *  Disable www news access if not news_ok.
 		 */
 #ifndef DISABLE_NEWS
-		} else if (url_type == NEWS_URL_TYPE && !news_ok) {
+		} else if (!news_ok && (
+		    url_type == NEWS_URL_TYPE ||
+		    url_type == NNTP_URL_TYPE)) {
 		    HTUserMsg(NEWS_DISABLED);
 		    return(NULLFILE);
 #endif
 
 		} else if (url_type == RLOGIN_URL_TYPE) {
+		    char * proxy;
 		    if (!rlogin_ok) {
 			HTUserMsg(RLOGIN_DISABLED);
+			return(NULLFILE);
+		    /*
+		     *  Detect weird case where interactive protocol would
+		     *  be proxied, and to a non-interactive protocol at that.
+		     */
+		    } else if ((proxy = (char *)getenv(
+			"rlogin_proxy")) != NULL &&
+			       *proxy != '\0' &&
+			       !override_proxy(doc->address) &&
+			       (strncmp(proxy, "telnet:", 7) &&
+				strncmp(proxy, "tn3270:", 7) &&
+				strncmp(proxy, "rlogin:", 7))) {
+			/* Do nothing, fall through to generic code - kw */
 		    } else {
 			stop_curses();
 			HTLoadAbsolute(&WWWDoc);
 			fflush(stdout);
-			start_curses();
-			LYAddVisitedLink(doc);
+			if (!dump_output_immediately) {
+			    start_curses();
+			    LYAddVisitedLink(doc);
+			}
+			return(NULLFILE);
 		    }
-		    return(NULLFILE);
 
 		/*
 		 *  If its a gopher index type and there isn't a search
@@ -571,7 +701,8 @@ Try_Redirected_URL:
 		    }
 		    return(status);
 
-		} else {
+		}
+		{
 
 		    if (url_type == FTP_URL_TYPE && !ftp_ok) {
 			HTUserMsg(FTP_DISABLED);
@@ -610,7 +741,7 @@ Try_Redirected_URL:
 			url_type == HTTPS_URL_TYPE ||
 			url_type == FTP_URL_TYPE ||
 			url_type == CSO_URL_TYPE)
-			fix_http_urls(doc);
+			fix_httplike_urls(doc, url_type);
 		    WWWDoc.address = doc->address;  /* possible reload */
 #ifdef DIRED_SUPPORT
 		    lynx_edit_mode = FALSE;
@@ -653,8 +784,23 @@ Try_Redirected_URL:
 			}
 			FREE(cp);
 		    }
-		    CTRACE_SLEEP(MessageSecs);
-		    user_message(WWW_WAIT_MESSAGE, doc->address);
+		    if (url_type == LYNXMESSAGES_URL_TYPE) {
+			int rv;
+		    /* show list of recent statusline messages */
+			if ((rv = LYshow_statusline_messages(doc)) != NORMAL) {
+			    return rv;
+			}
+			WWWDoc.address = doc->address;
+			WWWDoc.post_data = doc->post_data;
+			WWWDoc.post_content_type = doc->post_content_type;
+			WWWDoc.bookmark = doc->bookmark;
+			WWWDoc.isHEAD = doc->isHEAD;
+			WWWDoc.safe = doc->safe;
+		    } else {
+
+			CTRACE_SLEEP(MessageSecs);
+			user_message(WWW_WAIT_MESSAGE, doc->address);
+		    }
 		    if (TRACE) {
 #ifdef USE_SLANG
 			if (LYCursesON) {
@@ -664,22 +810,6 @@ Try_Redirected_URL:
 #endif /* USE_SLANG */
 			fprintf(tfp,"\n");
 		    }
-		    if ((LYNoRefererHeader == FALSE &&
-			 LYNoRefererForThis == FALSE) &&
-			(url_type == HTTP_URL_TYPE ||
-			 url_type == HTTPS_URL_TYPE) &&
-			(cp = strchr(HTLoadedDocumentURL(), '?')) != NULL &&
-			strchr(cp, '=') != NULL) {
-			/*
-			 *  Don't send a Referer header if the URL is
-			 *  the reply from a form with method GET, in
-			 *  case the content has personal data (e.g.,
-			 *  a password or credit card number) which
-			 *  would become visible in logs. - FM
-			 */
-			LYNoRefererForThis = TRUE;
-		    }
-		    cp = NULL;
 		    if (!HTLoadAbsolute(&WWWDoc)) {
 			/*
 			 *  Check for redirection.
@@ -716,7 +846,8 @@ Try_Redirected_URL:
 				FREE(temp);
 			    }
 			    url_type = is_url(use_this_url_instead);
-			    if (url_type == LYNXDOWNLOAD_URL_TYPE ||
+			    if (!HTPermitRedir &&
+			       (url_type == LYNXDOWNLOAD_URL_TYPE ||
 				url_type == LYNXEXEC_URL_TYPE ||
 				url_type == LYNXPROG_URL_TYPE ||
 #ifdef DIRED_SUPPORT
@@ -766,7 +897,7 @@ Try_Redirected_URL:
 				(no_goto_tn3270 &&
 				 url_type == TN3270_URL_TYPE) ||
 				(no_goto_wais &&
-				 url_type == WAIS_URL_TYPE)) {
+				 url_type == WAIS_URL_TYPE))) {
 				/*
 				 *  Some schemes are not acceptable from
 				 *  server redirections. - KW & FM
@@ -823,19 +954,21 @@ Try_Redirected_URL:
 			     */
 			    goto Try_Redirected_URL;
 			}
+			if (HTNoDataOK)
+			    return(NULLFILE);
 			return(NOT_FOUND);
 		    }
 
 		    lynx_mode = NORMAL_LYNX_MODE;
 
 		    /*
-		     *	Some URL's don't actually return a document
+		     *	Some URL's don't actually return a document;
 		     *	compare doc->address with the document that is
-		     *	actually loaded and return NULL if not
+		     *	actually loaded and return NULLFILE if not
 		     *	loaded.  If www_search_result is not -1
 		     *	then this is a reference to a named anchor
-		     *	within the same document.  Do NOT return
-		     *	NULL.
+		     *	within the same document; do NOT return
+		     *	NULLFILE in that case.
 		     */
 		    {
 			char *pound;
@@ -1002,7 +1135,11 @@ PUBLIC int follow_link_number ARGS4(
      *	Check if we had a 'p' or 'P' following the number as
      *	a flag for displaying the page with that number. - FM
      */
-    if ( c == 'p' || c == 'P' ) {
+    if (( c == 'p' || c == 'P') && display_lines == 0) {
+	CTRACE(tfp," curline=%d, LYlines=%d, display too small!\n",
+	       curline,LYlines);
+	return(PRINT_ERROR);
+    } else if ( c == 'p' || c == 'P' ) {
 	int nlines = HText_getNumOfLines();
 	int npages = ((nlines + 1) > display_lines) ?
 		(((nlines + 1) + (display_lines - 1))/(display_lines))
@@ -1204,6 +1341,7 @@ PUBLIC BOOLEAN exec_ok ARGS3(
 {
     struct trust *tp;
     CONST char *cp;
+    CONST char *allowed_extra_chars;
     int Type = type;
 
     /*
@@ -1255,13 +1393,12 @@ PUBLIC BOOLEAN exec_ok ARGS3(
     /*
      *	Security: reject on strange character.
      */
+    if (Type == CGI_PATH)
+	allowed_extra_chars = " _-:./@~$&+=\t";
+    else
+	allowed_extra_chars = " _-:./@~$+=\t";
     for (cp = linktext; *cp != '\0'; cp++) {
-	if (!isalnum(*cp) &&
-	    *cp != '_' && *cp != '-' && *cp != ' ' &&
-	    *cp != ':' && *cp != '.' && *cp != '/' &&
-	    *cp != '@' && *cp != '~' && *cp != '$' &&
-	    *cp != '&' && *cp != '+' && *cp != '=' &&
-	    *cp != '\t') {
+	if (!isalnum(*cp) && !strchr(allowed_extra_chars, *cp)) {
 	    char *buf = 0;
 
 	    HTSprintf0(&buf,
@@ -1282,13 +1419,8 @@ check_tp_for_entry:
 	    if (strstr(command,"//") == linktext) {
 		command += 2;
 	    }
-#ifdef VMS
-	    if (strncasecomp(source, tp->src, strlen(tp->src)) == 0 &&
-		strncasecomp(command, tp->path, strlen(tp->path)) == 0)
-#else
-	    if (strncmp(source, tp->src, strlen(tp->src)) == 0 &&
-		strncmp(command, tp->path, strlen(tp->path)) == 0)
-#endif /* VMS */
+	    if (STRNADDRCOMP(source, tp->src, strlen(tp->src)) == 0 &&
+		STRNADDRCOMP(command, tp->path, strlen(tp->path)) == 0)
 		return TRUE;
 	}
 	tp = tp->next;
@@ -1305,15 +1437,24 @@ check_tp_for_entry:
 }
 #endif /* EXEC_LINKS || LYNXCGI_LINKS */
 
-PRIVATE int fix_http_urls ARGS1(
-	document *,	doc)
+PRIVATE int fix_httplike_urls ARGS2(
+	document *,	doc,
+	UrlTypes,	type)
 {
     char *slash;
 
     /*
+     *  If there's a fragment present, our simplistic methods won't
+     *  work.  - kw
+     */
+    if (strchr(doc->address, '#'))
+	return 0;
+
+#ifndef DISABLE_FTP
+    /*
      *	If it's an ftp URL with a trailing slash, trim it off.
      */
-    if (!strncmp(doc->address, "ftp", 3) &&
+    if (type == FTP_URL_TYPE &&
 	LYIsHtmlSep(doc->address[strlen(doc->address)-1])) {
 	char * proxy;
 	char *path = HTParse(doc->address, "", PARSE_PATH|PARSE_PUNCTUATION);
@@ -1339,11 +1480,12 @@ PRIVATE int fix_http_urls ARGS1(
 	/*
 	 *  If we get to here, trim the trailing slash. - FM
 	 */
-	CTRACE(tfp, "fix_http_urls: URL '%s'\n", doc->address);
+	CTRACE(tfp, "fix_httplike_urls: URL '%s'\n", doc->address);
 	LYTrimHtmlSep(doc->address);
-	CTRACE(tfp, "        changed to '%s'\n", doc->address);
+	CTRACE(tfp, "            changed to '%s'\n", doc->address);
 	CTRACE_SLEEP(MessageSecs);
     }
+#endif /* DISABLE_FTP */
 
     /*
      *	If there isn't a slash besides the two at the beginning, append one.
@@ -1352,10 +1494,21 @@ PRIVATE int fix_http_urls ARGS1(
 	if (!LYIsHtmlSep(*(slash-1)) || *(slash-2) != ':') {
 	    return(0);
 	}
+	if ((type == HTTP_URL_TYPE ||
+	     type == HTTPS_URL_TYPE) &&
+	    ((slash-2) - strchr(doc->address, ':'))) {
+	    /*
+	     *  Turns out we were not looking at the right slash after all,
+	     *  there must have been more than one "://" which is valid
+	     *  at least for http URLs (later occurrences can be part of
+	     *  a query string, for example), so leave this alone, too. - kw
+	     */
+	    return(0);
+	}
     }
-    CTRACE(tfp, "fix_http_urls: URL '%s'\n", doc->address);
+    CTRACE(tfp, "fix_httplike_urls: URL '%s'\n", doc->address);
     LYAddHtmlSep(&(doc->address));
-    CTRACE(tfp, "        changed to '%s'\n",doc->address);
+    CTRACE(tfp, "            changed to '%s'\n", doc->address);
     CTRACE_SLEEP(MessageSecs);
 
     return(1);
diff --git a/src/LYGlobalDefs.h b/src/LYGlobalDefs.h
index 8e8d49ba..e1d9e92f 100644
--- a/src/LYGlobalDefs.h
+++ b/src/LYGlobalDefs.h
@@ -14,10 +14,13 @@
 #ifdef HAVE_CONFIG_H
 #include <LYHelp.h>
 #else
+#define ALT_EDIT_HELP		"keystrokes/alt_edit_help.html"
+#define BASHLIKE_EDIT_HELP	"keystrokes/bashlike_edit_help.html"
 #define COOKIE_JAR_HELP		"Lynx_users_guide.html#Cookies"
 #define CURRENT_KEYMAP_HELP	"keystrokes/keystroke_help.html"
 #define DIRED_MENU_HELP		"keystrokes/dired_help.html"
 #define DOWNLOAD_OPTIONS_HELP	"Lynx_users_guide.html#RemoteSource"
+#define EDIT_HELP		"keystrokes/edit_help.html"
 #define HISTORY_PAGE_HELP	"keystrokes/history_help.html"
 #define LIST_PAGE_HELP		"keystrokes/follow_help.html"
 #define LYNXCFG_HELP		"lynx.cfg"
@@ -179,6 +182,9 @@ extern BOOLEAN emacs_keys;        /* TRUE to turn on emacs-like key movement */
 extern int keypad_mode;           /* is set to either NUMBERS_AS_ARROWS *
 				   * or LINKS_ARE_NUMBERED 		*/
 extern BOOLEAN case_sensitive;    /* TRUE to turn on case sensitive search */
+
+extern BOOLEAN had_restrictions_default; /* flags to note whether we have... */
+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;
@@ -220,12 +226,21 @@ 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_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_statusline;
 extern BOOLEAN no_filereferer;
 extern BOOLEAN local_host_only;
@@ -260,7 +275,7 @@ extern int LYCacheSource;
 #define SOURCE_CACHE_MEMORY	2
 #endif
 extern BOOLEAN LYCancelDownload;
-extern BOOLEAN LYRestricted;
+extern BOOLEAN LYRestricted;	/* whether we had -anonymous option */
 extern BOOLEAN LYValidate;
 extern BOOLEAN LYPermitURL;
 extern BOOLEAN enable_scrollback; /* Clear screen before displaying new page */
@@ -369,9 +384,13 @@ extern BOOLEAN LYPreparsedSource;	/* Show source as preparsed?	 */
 extern BOOLEAN LYPrependBaseToSource;
 extern BOOLEAN LYPrependCharsetToSource;
 extern BOOLEAN LYQuitDefaultYes;
+extern BOOLEAN LYNonRestartingSIGWINCH;
 
 #ifndef VMS
 extern BOOLEAN LYNoCore;
+extern BOOLEAN restore_sigpipe_for_children;
 #endif /* !VMS */
 
+extern int HTNoDataOK;		/* HT_NO_DATA-is-ok hack */
+
 #endif /* LYGLOBALDEFS_H */
diff --git a/src/LYHistory.c b/src/LYHistory.c
index 65c3874c..eef57082 100644
--- a/src/LYHistory.c
+++ b/src/LYHistory.c
@@ -113,9 +113,10 @@ PUBLIC void LYAddVisitedLink ARGS1(
     cur = Visited_Links;
     while (NULL != (old = (VisitedLink *)HTList_nextObject(cur))) {
 	if (!strcmp((old->address ? old->address : ""),
-		    (new->address ? new->address : "")) &&
-	    !strcmp((old->title ? new->title : ""),
-		    (new->title ? new->title : ""))) {
+		    (new->address ? new->address : ""))) {
+	    if (!(new->title && *new->title) && old->title) {
+		StrAllocCopy(new->title, old->title);
+	    }
 	    FREE(old->address);
 	    FREE(old->title);
 	    HTList_removeObject(Visited_Links, old);
@@ -130,11 +131,26 @@ PUBLIC void LYAddVisitedLink ARGS1(
 
 /*
  *  Returns true if this is a page that we would push onto the stack if not
- *  forced.
+ *  forced.  If docurl is NULL, only the title is considered; otherwise
+ *  also check the URL whether it is (likely to be) a generated special
+ *  page.
  */
-PUBLIC BOOLEAN LYwouldPush ARGS1(
-	char *,	title)
+PUBLIC BOOLEAN LYwouldPush ARGS2(
+	CONST char *,	title,
+	CONST char *,	docurl)
 {
+    /*
+     *  All non-pushable generated pages have URLs that begin with
+     *  "file://localhost/" and end with HTML_SUFFIX. - kw
+     */
+    if (docurl) {
+	size_t ulen;
+	if (strncmp(docurl, "file://localhost/", 17) != 0 ||
+	    (ulen = strlen(docurl)) <= strlen(HTML_SUFFIX) ||
+	    strcmp(docurl + ulen - strlen(HTML_SUFFIX), HTML_SUFFIX) != 0)
+	    return TRUE;
+    }
+
     return (!strcmp(title, HISTORY_PAGE_TITLE)
 	 || !strcmp(title, PRINT_OPTIONS_TITLE)
 	 || !strcmp(title, DOWNLOAD_OPTIONS_TITLE)
@@ -169,7 +185,7 @@ PUBLIC void LYpush ARGS2(
 	/*
 	 *  Don't push the history, printer, or download lists.
 	 */
-	if (!LYwouldPush(doc->title)) {
+	if (!LYwouldPush(doc->title, doc->address)) {
 	    if (!LYforce_no_cache)
 		LYoverride_no_cache = TRUE;
 	    return;
@@ -469,8 +485,17 @@ PUBLIC BOOLEAN historytarget ARGS1(
     /*
      * Optimization: assume we came from the History Page,
      * so never return back - always a new version next time.
+     * But check first whether HTMainText is really the History
+     * Page document - in some obscure situations this may not be
+     * the case.  If HTMainText seems to be a History Page document,
+     * also check that it really hasn't been pushed. - LP, kw
      */
-    HTuncache_current_document();  /* don't waste the cache */
+    if (HTMainText && nhist > 0 &&
+	!strcmp(HTLoadedDocumentTitle(), HISTORY_PAGE_TITLE) &&
+	!LYwouldPush(HTLoadedDocumentURL(), HTLoadedDocumentTitle()) &&
+	strcmp(HTLoadedDocumentURL(), history[nhist-1].address)) {
+	HTuncache_current_document();  /* don't waste the cache */
+    }
 
     LYpop_num(number, newdoc);
     if (((newdoc->internal_link &&
@@ -653,14 +678,13 @@ PRIVATE void to_stack ARGS1(char *, str)
 
 /*
  *  Status line messages list, LYNXMESSAGES:/ internal page,
- *  called from getfile() cyrcle.
+ *  called from getfile().
  */
 PUBLIC int LYshow_statusline_messages ARGS1(
     document *,			      newdoc)
 {
     static char tempfile[LY_MAXPATH];
     static char *info_url;
-    DocAddress WWWDoc;  /* need on exit */
     FILE *fp0;
     int i;
 
@@ -695,17 +719,15 @@ PUBLIC int LYshow_statusline_messages ARGS1(
     LYCloseTempFP(fp0);
 
 
-    /* exit to getfile() cyrcle */
+    /* exit to getfile() cycle */
     StrAllocCopy(newdoc->address, info_url);
-    WWWDoc.address = newdoc->address;
-    WWWDoc.post_data = newdoc->post_data;
-    WWWDoc.post_content_type = newdoc->post_content_type;
-    WWWDoc.bookmark = newdoc->bookmark;
-    WWWDoc.isHEAD = newdoc->isHEAD;
-    WWWDoc.safe = newdoc->safe;
-
-    if (!HTLoadAbsolute(&WWWDoc))
-	return(NOT_FOUND);
+    FREE(newdoc->post_data);
+    FREE(newdoc->post_content_type);
+    FREE(newdoc->bookmark);
+    newdoc->isHEAD = FALSE;
+
+    /* Leave loading it to getfile - that has the advantage to make
+       this kind of link 'd'ownloadable. - kw */
     return(NORMAL);
 }
 
diff --git a/src/LYHistory.h b/src/LYHistory.h
index 75156806..ad25b250 100644
--- a/src/LYHistory.h
+++ b/src/LYHistory.h
@@ -5,7 +5,7 @@
 #include <LYStructs.h>
 #endif /* LYSTRUCTS_H */
 
-extern BOOLEAN LYwouldPush PARAMS((char *title));
+extern BOOLEAN LYwouldPush PARAMS((CONST char *title, CONST char *docurl));
 extern BOOLEAN historytarget PARAMS((document *newdoc));
 extern int LYShowVisitedLinks PARAMS((char **newfile));
 extern int showhistory PARAMS((char **newfile));
diff --git a/src/LYKeymap.c b/src/LYKeymap.c
index b7dd523a..3999898c 100644
--- a/src/LYKeymap.c
+++ b/src/LYKeymap.c
@@ -5,6 +5,7 @@
 #include <HTAccess.h>
 #include <HTFormat.h>
 #include <HTAlert.h>
+#include <LYStrings.h>		/* for USE_KEYMAP stuff - kw */
 
 #include <LYLeaks.h>
 
@@ -17,7 +18,7 @@
 #ifdef EXP_KEYBOARD_LAYOUT
 PUBLIC int current_layout = 0;  /* Index into LYKbLayouts[]   */
 
-PUBLIC LYKeymap_t * LYKbLayouts[]={
+PUBLIC unsigned short * LYKbLayouts[]={
 	kb_layout_rot13,
 	kb_layout_jcuken,
 	kb_layout_yawerty
@@ -29,7 +30,7 @@ PUBLIC char * LYKbLayoutNames[]={
 	"YAWERTY Cyrillic, for DEC LK201 kbd",
         (char *) 0
 };
-#endif
+#endif /* EXP_KEYBOARD_LAYOUT */
 
 PRIVATE CONST DocAddress keymap_anchor = {"LYNXKEYMAP", NULL, NULL,
 	NULL, FALSE, FALSE};
@@ -39,6 +40,19 @@ struct _HTStream
   HTStreamClass * isa;
 };
 
+/* * *  Tables mapping LynxKeyCodes to LynxActionCodes  * * */
+
+/*
+ *  Lynxkeycodes include all single-byte keys as well as codes
+ *  for function keys and some special purposes.  See LYStrings.h.
+ *  Extended lynxkeycode values can also contain flags for modifiers
+ *  and other purposes, but here only the base values are mapped to
+ *  lynxactioncodes.  They are called `keystrokes' in lynx.cfg.
+ *
+ *  Lynxactioncodes (confusingly, constants are named LYK_foo and
+ *  typed as LYKeymapCode) specify key `functions', see LYKeymap.h.
+ */
+
 /* the character gets 1 added to it before lookup,
  * so that EOF maps to 0
  */
@@ -662,6 +676,8 @@ PRIVATE struct rmap revmap[] = {
 { "END",		"go to the end of the current document" },
 { "PREV_LINK",		"make the previous link current" },
 { "NEXT_LINK",		"make the next link current" },
+{ "LPOS_PREV_LINK",	"make previous link current, same column for input" },
+{ "LPOS_NEXT_LINK",	"make next link current, same column for input" },
 { "FASTBACKW_LINK",	"previous link or text area, only stops on links" },
 { "FASTFORW_LINK",	"next link or text area, only stops on links" },
 { "UP_LINK",		"move up the page to a previous link" },
@@ -671,9 +687,11 @@ PRIVATE struct rmap revmap[] = {
 { "HISTORY",		"display stack of currently-suspended documents" },
 { "PREV_DOC",		"go back to the previous document" },
 { "ACTIVATE",		"go to the document given by the current link" },
+{ "MOUSE_SUBMIT",	"follow current link, submit" }, /* not mapped */
 { "GOTO",		"go to a document given as a URL" },
 { "ECGOTO",		"edit the current document's URL and go to it" },
 { "HELP",		"display help on using the browser" },
+{ "DWIMHELP",		"display help page that may depend on context" },
 { "INDEX",		"display an index of potentially useful documents" },
 { "NOCACHE",		"force submission of form or link with no-cache" },
 { "INTERRUPT",		"interrupt network connection or transmission" },
@@ -713,11 +731,12 @@ PRIVATE struct rmap revmap[] = {
 { "SWITCH_DTD",		"switch between two ways of parsing HTML" },
 { "ELGOTO",		"edit the current link's URL or ACTION and go to it" },
 { "CHANGE_LINK",	"force reset of the current link on the page" },
+{ "DWIMEDIT",		"use external editor for context-dependent purpose" },
 { "EDITTEXTAREA",	"use an external editor to edit a form's textarea" },
 { "GROWTEXTAREA",	"add 5 new blank lines to the bottom of a textarea" },
 { "INSERTFILE",		"insert file into a textarea (just above cursorline)" },
 #ifdef EXP_ADDRLIST_PAGE
-{ "ADDRLIST",		"like LIST command, but always shows the links URL's" },
+{ "ADDRLIST",		"like LIST command, but always shows the links' URLs" },
 #endif
 #ifdef USE_EXTERNALS
 { "EXTERN",		"run external program with url" },
@@ -757,7 +776,7 @@ PRIVATE CONST char *funckey[] = {
   "Back Tab",
   0, 0, 0, 0, 0, 0, 0, 0,
   0, 0, 0, 0, 0,
-  "mouse pseudo key",		/* normally not mapped to keymap[] action? */
+  "mouse pseudo key",		/* normally not mapped to keymap[] action */
 };
 
 PRIVATE char *pretty ARGS1 (int, c)
@@ -828,6 +847,65 @@ PRIVATE void print_binding ARGS2(HTStream *, target, int, i)
     }
 }
 
+/*
+ *  Return lynxactioncode whose name is the string func.
+ *  func must be present in the revmap table.
+ *  returns -1 if not found. - kw
+ */
+PUBLIC int lacname_to_lac ARGS1(
+	CONST char *,	func)
+{
+       int i;
+       struct rmap *mp;
+
+       if (func == NULL || *func == '\0')
+	       return (-1);
+       for (i = 0, mp = revmap; (*mp).name != NULL; mp++, i++) {
+               if (strcmp((*mp).name, func) == 0) {
+                       return i;
+               }
+       }
+       return (-1);
+}
+
+/*
+ *  Return lynxkeycode represented by string src.
+ *  returns -1 if not valid.
+ *  This is simpler than what map_string_to_keysym() does for
+ *  USE_KEYMAP, but compatible with revmap() used for processing
+ *  KEYMAP options in the configuration file. - kw
+ */
+PUBLIC int lkcstring_to_lkc ARGS1(
+	CONST char *,	src)
+{
+       int c = -1;
+
+       if (strlen(src) == 1)
+               c = *src;
+       else if (strlen(src) == 2 && *src == '^')
+               c = src[1] & 037;
+       else if (strlen(src) >= 2 && isdigit(*src)) {
+               if (sscanf(src, "%i", &c) != 1)
+                       return (-1);
+#ifdef USE_KEYMAPS
+       } else {
+	   map_string_to_keysym((char *)src, &c);
+#ifndef USE_SLANG
+	   if (c >= 0) {
+	       if ((c&LKC_MASK) > 255 && !(c & LKC_ISLKC))
+		   return (-1);	/* Don't accept untranslatable curses KEY_* */
+	       else
+		   c &= ~LKC_ISLKC;
+	   }
+#endif
+#endif
+       } 
+       if (c < -1)
+	   return (-1);
+       else
+	   return c;
+}
+
 PRIVATE int LYLoadKeymap ARGS4 (
 	CONST char *, 		arg GCC_UNUSED,
 	HTParentAnchor *,	anAnchor,
@@ -908,21 +986,30 @@ PUBLIC int remap ARGS2(
 {
        int i;
        struct rmap *mp;
-       int c = 0;
+       int c;
 
        if (func == NULL)
 	       return 0;
-       if (strlen(key) == 1)
-               c = *key;
-       else if (strlen(key) == 2 && *key == '^')
-               c = key[1] & 037;
-       else if (strlen(key) >= 2 && isdigit(*key))
-               if (sscanf(key, "%i", &c) != 1)
-                       return 0;
+       c = lkcstring_to_lkc(key);
+       if (c <= -1)
+	   return 0;
+       else if (c >= 0) {
+	   /* Remapping of key actions is supported only for basic
+	    * lynxkeycodes, without modifiers etc.!  If we get somehow
+	    * called for an invalid lynxkeycode, fail or silently
+	    * modifiers. - kw
+	    */
+	   if (c & LKC_ISLAC)
+	       return 0;
+	   if ((c & LKC_MASK) != c)
+	       c &= LKC_MASK;
+       }
+       if (c + 1 >= KEYMAP_SIZE)
+	   return 0;
        for (i = 0, mp = revmap; (*mp).name != NULL; mp++, i++) {
                if (strcmp((*mp).name, func) == 0) {
                        keymap[c+1] = i;
-                       return c;
+                       return (c ? c : LAC_TO_LKC0(i));
                }
        }
        return 0;
diff --git a/src/LYKeymap.h b/src/LYKeymap.h
index c7e3b634..036e4c60 100644
--- a/src/LYKeymap.h
+++ b/src/LYKeymap.h
@@ -9,6 +9,8 @@ extern BOOLEAN LYisNonAlnumKeyname PARAMS((int ch, int key_name));
 extern char *key_for_func PARAMS((int func));
 extern int LYReverseKeymap PARAMS((int key_name));
 extern int lookup_keymap PARAMS((int code));
+extern int lacname_to_lac PARAMS((CONST char *func));
+extern int lkcstring_to_lkc PARAMS((CONST char *src));
 extern int remap PARAMS((char *key, char *func));
 extern void print_keymap PARAMS((char **newfile));
 extern void reset_emacs_keys NOPARAMS;
@@ -30,7 +32,7 @@ extern LYKeymap_t keymap[KEYMAP_SIZE]; /* main keymap matrix */
 
 #ifdef EXP_KEYBOARD_LAYOUT
 extern int current_layout;
-extern LYKeymap_t * LYKbLayouts[];
+extern unsigned short * LYKbLayouts[];
 extern char * LYKbLayoutNames[];
 extern int LYSetKbLayout PARAMS((char *layout_id));
 #endif
@@ -39,6 +41,47 @@ extern int LYSetKbLayout PARAMS((char *layout_id));
 extern LYKeymap_t key_override[];
 #endif
 
+/* * *  LynxKeyCodes  * * */
+#define LKC_MOD1	0x4000	/* a modifier bit - currently for ^x-map */
+#define LKC_MOD2	0x2000	/* another one - currently for esc-map */
+#define LKC_MOD3	0x1000	/* another one - currently for double-map */
+#define LKC_ISLAC	0x0800	/* flag: lynxkeycode already lynxactioncode */
+#define LKC_ISLKC	0x0400	/* flag: already lynxkeycode (not native) */
+		     /* 0x0400  is MOUSE_KEYSYM for slang in LYStrings.c */
+#define LKC_MASK	0x07FF	/* mask for lynxkeycode proper */
+
+#define LKC_DONE	0x07FE	/* special value - operation done, not-a-key */
+
+/* * *  LynxActionCodes  * * */
+#define LAC_MASK	0x00FF	/* mask for lynxactioncode - must cover all
+				   assigned LYK_* values */
+
+
+/*  Convert lynxkeycode to lynxactioncode.  Modifiers are dropped.  */
+#define LKC_TO_LAC(ktab,c) (((c)==-1) ? ktab[0] : \
+			    ((c)&LKC_ISLAC) ? ((c)&LAC_MASK) : \
+			    ktab[((c)&LKC_MASK)+1])
+
+
+/*  Mask lynxactioncode as a lynxkeycode.  */
+#define LAC_TO_LKC0(a) ((a)|LKC_ISLAC)
+
+/*  Convert lynxactioncode to a lynxkeycode, attempting reverse mapping.  */
+#define LAC_TO_LKC(a) ((LYReverseKeymap(a)>=0)?LYReverseKeymap(a):LAC_TO_LKC0(a))
+
+/*  Simplify a lynxkeycode:
+    attempt reverse mapping if a masked lynxactioncode, drop modifiers.  */
+#define LKC_TO_C(c) ((c&LKC_ISLAC)? LAC_TO_LKC(c&LAC_MASK) : (c&LKC_MASK))
+
+#define LKC_HAS_ESC_MOD(c) (c >= 0 && (c&LKC_MOD2))
+
+
+/* *  The defined LynxActionCodes  * */
+
+/*  Variables for holding and passing around lynxactioncodes are
+ *  generally of type int, the types LYKeymap_t and LYKeymapCodes
+ *  are currently only used for the definitions.  That could change. - kw
+ */
 /* The order of this enum must match the 'revmap[]' array in LYKeymap.c */
 typedef enum {
     LYK_UNKNOWN=0
@@ -67,6 +110,8 @@ typedef enum {
   , LYK_END
   , LYK_PREV_LINK
   , LYK_NEXT_LINK
+  , LYK_LPOS_PREV_LINK
+  , LYK_LPOS_NEXT_LINK
   , LYK_FASTBACKW_LINK
   , LYK_FASTFORW_LINK
   , LYK_UP_LINK
@@ -76,9 +121,11 @@ typedef enum {
   , LYK_HISTORY
   , LYK_PREV_DOC
   , LYK_ACTIVATE
+  , LYK_SUBMIT	/* mostly like LYK_ACTIVATE, for mouse use, don't map */
   , LYK_GOTO
   , LYK_ECGOTO
   , LYK_HELP
+  , LYK_DWIMHELP
   , LYK_INDEX
   , LYK_NOCACHE
   , LYK_INTERRUPT
@@ -118,6 +165,7 @@ typedef enum {
   , LYK_SWITCH_DTD
   , LYK_ELGOTO
   , LYK_CHANGE_LINK
+  , LYK_DWIMEDIT
   , LYK_EDIT_TEXTAREA
   , LYK_GROW_TEXTAREA
   , LYK_INSERT_FILE
diff --git a/src/LYMail.c b/src/LYMail.c
index d4d6a812..340f14c9 100644
--- a/src/LYMail.c
+++ b/src/LYMail.c
@@ -596,6 +596,9 @@ PUBLIC void mailmsg ARGS4(
     char *address = NULL;
     char *searchpart = NULL;
     char *cmd = NULL, *cp, *cp0, *cp1;
+#ifdef ALERTMAIL
+    BOOLEAN skip_parsing = FALSE;
+#endif
 #if defined(VMS) || defined(DOSPATH)
     char my_tmpfile[LY_MAXPATH];
     char *command = NULL;
@@ -615,75 +618,105 @@ PUBLIC void mailmsg ARGS4(
     if (!strncasecomp(system_mail, "PMDF SEND", 9)) {
 	isPMDF = TRUE;
     }
-#endif /* VMS */
+#endif /* VMS || DOSPATH */
+
+#ifdef ALERTMAIL
+    if (owner_address == NULL) {
+	owner_address = ALERTMAIL;
+	skip_parsing = TRUE;
+    }
+#endif
 
     if (owner_address == NULL || *owner_address == '\0') {
 	return;
     }
-    if ((cp = (char *)strchr(owner_address,'\n')) != NULL)
+    if ((cp = (char *)strchr(owner_address,'\n')) != NULL) {
+#ifdef ALERTMAIL
+	if (skip_parsing)
+	    return;		/* invalidly defined - ignore - kw */
+#else
 	*cp = '\0';
+#endif
+    }
+    if (!strncasecomp(owner_address, "lynx-dev@", 9)) {
+	/*
+	 *  Silently refuse sending bad link messages to lynx-dev.
+	 */
+	return;
+    }
     StrAllocCopy(address, owner_address);
 
+#ifdef ALERTMAIL
     /*
-     *	Check for a ?searchpart. - FM
+     *  If we are using a fixed address given by ALERTMAIL, it is
+     *  supposed to already be in usable form, without URL-isms like
+     *  ?-searchpart and URL-escaping.  So skip some code. - kw
      */
-    if ((cp = strchr(address, '?')) != NULL) {
-	StrAllocCopy(searchpart, cp);
-	*cp = '\0';
-	cp = (searchpart + 1);
-	if (*cp != '\0') {
-	    /*
-	     *	Seek and handle to=address(es) fields.
-	     *	Appends to address.  We ignore any other
-	     *	headers in the ?searchpart. - FM
-	     */
+    if (!skip_parsing)
+#endif
+    {
+	/*
+	 *	Check for a ?searchpart. - FM
+	 */
+	if ((cp = strchr(address, '?')) != NULL) {
+	    StrAllocCopy(searchpart, cp);
+	    *cp = '\0';
 	    cp = (searchpart + 1);
-	    while (*cp != '\0') {
-		if ((*(cp - 1) == '?' || *(cp - 1) == '&') &&
-		    !strncasecomp(cp, "to=", 3)) {
-		    cp += 3;
-		    if ((cp1 = strchr(cp, '&')) != NULL) {
-			*cp1 = '\0';
-		    }
-		    while (*cp == ',' || isspace((unsigned char)*cp))
-			cp++;
-		    if (*cp) {
-			if (*address) {
-			    StrAllocCat(address, ",");
+	    if (*cp != '\0') {
+		/*
+		 *	Seek and handle to=address(es) fields.
+		 *	Appends to address.  We ignore any other
+		 *	headers in the ?searchpart. - FM
+		 */
+		cp = (searchpart + 1);
+		while (*cp != '\0') {
+		    if ((*(cp - 1) == '?' || *(cp - 1) == '&') &&
+			!strncasecomp(cp, "to=", 3)) {
+			cp += 3;
+			if ((cp1 = strchr(cp, '&')) != NULL) {
+			    *cp1 = '\0';
+			}
+			while (*cp == ',' || isspace((unsigned char)*cp))
+			    cp++;
+			if (*cp) {
+			    if (*address) {
+				StrAllocCat(address, ",");
+			    }
+			    StrAllocCat(address, cp);
+			}
+			if (cp1) {
+			    *cp1 = '&';
+			    cp = cp1;
+			    cp1 = NULL;
+			} else {
+			    break;
 			}
-			StrAllocCat(address, cp);
-		    }
-		    if (cp1) {
-			*cp1 = '&';
-			cp = cp1;
-			cp1 = NULL;
-		    } else {
-			break;
 		    }
+		    cp++;
 		}
-		cp++;
 	    }
 	}
-    }
 
-    /*
-     *	Convert any Explorer semi-colon Internet address
-     *	separators to commas. - FM
-     */
-    cp = address;
-    while ((cp1 = strchr(cp, '@')) != NULL) {
-	cp1++;
-	if ((cp0 = strchr(cp1, ';')) != NULL) {
-	    *cp0 = ',';
-	    cp1 = cp0 + 1;
+	/*
+	 *	Convert any Explorer semi-colon Internet address
+	 *	separators to commas. - FM
+	 */
+	cp = address;
+	while ((cp1 = strchr(cp, '@')) != NULL) {
+	    cp1++;
+	    if ((cp0 = strchr(cp1, ';')) != NULL) {
+		*cp0 = ',';
+		cp1 = cp0 + 1;
+	    }
+	    cp = cp1;
 	}
-	cp = cp1;
+
+	/*
+	 *	Unescape the address field. - FM
+	 */
+	SafeHTUnEscape(address);
     }
 
-    /*
-     *	Unescape the address field. - FM
-     */
-    SafeHTUnEscape(address);
     if (address[(strlen(address) - 1)] == ',')
 	address[(strlen(address) - 1)] = '\0';
     if (*address == '\0') {
diff --git a/src/LYMain.c b/src/LYMain.c
index 9f1f717e..cc85ece3 100644
--- a/src/LYMain.c
+++ b/src/LYMain.c
@@ -7,6 +7,7 @@
 #include <UCMap.h>
 #include <UCDefs.h>
 #include <HTInit.h>
+#include <HTAlert.h>
 #include <LYCurses.h>
 #include <LYStyle.h>
 #include <HTML.h>
@@ -180,7 +181,7 @@ PUBLIC BOOLEAN nolist = FALSE;
 PUBLIC BOOLEAN historical_comments = FALSE;
 PUBLIC BOOLEAN minimal_comments = FALSE;
 PUBLIC BOOLEAN soft_dquotes = FALSE;
-PUBLIC BOOLEAN LYRestricted = FALSE;
+PUBLIC BOOLEAN LYRestricted = FALSE; /* whether we have -anonymous option */
 PUBLIC BOOLEAN LYValidate = FALSE;
 PUBLIC BOOLEAN LYPermitURL = FALSE;
 PUBLIC BOOLEAN child_lynx = FALSE;
@@ -190,6 +191,7 @@ PUBLIC BOOLEAN vi_keys = VI_KEYS_ALWAYS_ON;
 PUBLIC BOOLEAN emacs_keys = EMACS_KEYS_ALWAYS_ON;
 PUBLIC int keypad_mode = DEFAULT_KEYPAD_MODE;
 PUBLIC BOOLEAN case_sensitive = CASE_SENSITIVE_ALWAYS_ON;
+
 PUBLIC BOOLEAN telnet_ok = TRUE;
 #ifndef DISABLE_NEWS
 PUBLIC BOOLEAN news_ok = TRUE;
@@ -197,6 +199,9 @@ PUBLIC BOOLEAN news_ok = TRUE;
 PUBLIC BOOLEAN rlogin_ok = TRUE;
 PUBLIC BOOLEAN ftp_ok = TRUE;
 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
@@ -247,6 +252,7 @@ PUBLIC BOOLEAN no_goto_snews = FALSE;
 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_jump = FALSE;
 PUBLIC BOOLEAN no_file_url = FALSE;
 #ifndef DISABLE_NEWS
@@ -255,6 +261,14 @@ PUBLIC BOOLEAN no_newspost = FALSE;
 PUBLIC BOOLEAN no_mail = FALSE;
 PUBLIC BOOLEAN no_dotfiles = NO_DOT_FILES;
 PUBLIC BOOLEAN no_useragent = FALSE;
+PUBLIC BOOLEAN no_lynxcfg_info = FALSE;
+#ifndef NO_CONFIG_INFO
+PUBLIC BOOLEAN no_lynxcfg_xinfo = FALSE;
+#ifdef HAVE_CONFIG_H
+PUBLIC BOOLEAN no_compileopts_info = FALSE;
+#endif
+#endif
+
 PUBLIC BOOLEAN no_statusline = FALSE;
 PUBLIC BOOLEAN no_filereferer = FALSE;
 PUBLIC BOOLEAN local_host_only = FALSE;
@@ -394,6 +408,8 @@ PUBLIC BOOLEAN debug_display_partial = FALSE; /* Show with MessageSecs delay */
 PUBLIC int partial_threshold = -1;  /* # of lines to be d/l'ed until we repaint */
 #endif
 
+PUBLIC BOOLEAN LYNonRestartingSIGWINCH = FALSE;
+
 /* 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 */
@@ -417,6 +433,12 @@ PRIVATE HTList *LYStdinArgs = NULL;
 #define EXTENDED_OPTION_LOGIC 1
 #endif
 
+#ifndef EXTENDED_STARTFILE_RECALL
+/* if set then additional non-option args (before the last one) will be
+   made available for 'g'oto recall - kw */
+#define EXTENDED_STARTFILE_RECALL 1
+#endif
+
 #if EXTENDED_OPTION_LOGIC
 PRIVATE BOOLEAN no_options_further=FALSE; /* set to TRUE after '--' argument */
 #endif
@@ -427,6 +449,7 @@ PRIVATE void print_help_and_exit PARAMS((int exit_status));
 
 #ifndef VMS
 PUBLIC BOOLEAN LYNoCore = NO_FORCED_CORE_DUMP;
+PUBLIC BOOLEAN restore_sigpipe_for_children = FALSE;
 PRIVATE void FatalProblem PARAMS((int sig));
 #endif /* !VMS */
 
@@ -1148,15 +1171,15 @@ PUBLIC int main ARGS2(
 	strlen((char *)ANONYMOUS_USER) > 0 &&
 #if defined (VMS) || defined (NOUSERS)
 	!strcasecomp(((char *)getenv("USER")==NULL ? " " : getenv("USER")),
-		     ANONYMOUS_USER))
+		     ANONYMOUS_USER)
 #else
 #if HAVE_CUSERID
-	STREQ((char *)cuserid((char *) NULL), ANONYMOUS_USER))
+	STREQ((char *)cuserid((char *) NULL), ANONYMOUS_USER)
 #else
-	STREQ(((char *)getlogin()==NULL ? " " : getlogin()), ANONYMOUS_USER))
+	STREQ(((char *)getlogin()==NULL ? " " : getlogin()), ANONYMOUS_USER)
 #endif /* HAVE_CUSERID */
 #endif /* VMS */
-    {
+	) {
 	parse_restrictions("default");
 	LYRestricted = TRUE;
 	LYUseTraceLog = FALSE;
@@ -1548,6 +1571,14 @@ PUBLIC int main ARGS2(
     if (vi_keys)
 	set_vi_keys();
 
+    if (crawl) {
+	/* No numbered links by default, as documented
+	   in CRAWL.announce. - kw */
+	if (!number_links) {
+	    keypad_mode = NUMBERS_AS_ARROWS;
+	}
+    }
+
     if (number_links && keypad_mode == NUMBERS_AS_ARROWS)
 	keypad_mode = LINKS_ARE_NUMBERED;
     if (keypad_mode == NUMBERS_AS_ARROWS)
@@ -1620,7 +1651,7 @@ PUBLIC int main ARGS2(
 #endif /* NOSIGHUP */
     (void) signal(SIGTERM, cleanup_sig);
 #ifdef SIGWINCH
-    (void) signal(SIGWINCH, size_change);
+	LYExtSignal(SIGWINCH, size_change);
 #endif /* SIGWINCH */
 #ifndef VMS
     if (!TRACE && !dump_output_immediately && !stack_dump) {
@@ -1642,7 +1673,8 @@ PUBLIC int main ARGS2(
 	 *   more.
 	 */
 #ifndef DOSPATH
-	(void) signal(SIGPIPE, SIG_IGN);
+	if (signal(SIGPIPE, SIG_IGN) != SIG_IGN)
+    	     restore_sigpipe_for_children = TRUE;
 #endif /* DOSPATH */
     }
 #endif /* !VMS */
@@ -1782,13 +1814,12 @@ PUBLIC int main ARGS2(
 	 *  Finish setting up and start a
 	 *  NON-INTERACTIVE session. - FM
 	 */
-	if (crawl && !number_links) {
-	    keypad_mode = NUMBERS_AS_ARROWS;
-	} else if (!nolist) {
+	if (!crawl && !nolist) {
 	    if (keypad_mode == NUMBERS_AS_ARROWS) {
 		keypad_mode = LINKS_ARE_NUMBERED;
 	    }
 	}
+
 	if (x_display != NULL && *x_display != '\0') {
 	    LYisConfiguredForX = TRUE;
 	}
@@ -1797,6 +1828,7 @@ PUBLIC int main ARGS2(
 	}
 	status = mainloop();
 	if (!nolist &&
+	    !crawl &&		/* For -crawl it has already been done! */
 	    (keypad_mode == LINKS_ARE_NUMBERED ||
 	     keypad_mode == LINKS_AND_FORM_FIELDS_ARE_NUMBERED))
 	    printlist(stdout,FALSE);
@@ -1869,10 +1901,32 @@ PUBLIC void LYRegisterLynxProtocols NOARGS
  */
 PUBLIC void reload_read_cfg NOARGS
 {
+    /*
+     *  no_option_save is always set for -anonymous and -validate.
+     *  It is better to check for one or several specific restriction
+     *  flags than for 'LYRestricted', which doesn't get set for
+     *  individual restrictions or for -validate!
+     *  However, no_option_save may not be the appropriate one to
+     *  check - in that case, a new no_something should be added
+     *  that gets automatically set for -anonymous and -validate
+     *  (and whether it applies for -anonymous can be made installer-
+     *  configurable in the usual way at the bottom of userdefs.h). - kw
+     *  
+     */
+    if (no_option_save) {
+	/* current logic requires(?) that saving user preferences is
+	   possible.  Additional applicable restrictions are already
+	   checked by caller. - kw */
+	return;
+    }
+#if 0				/* therefore this isn't needed: */
     if (LYRestricted) return;  /* for sure */
-
+#endif
     /* save .lynxrc file in case we change something from Options Menu */
-    if (!save_rc()) return;    /* can not write the very own file :( */
+    if (!save_rc()) {
+	HTAlwaysAlert(NULL, OPTIONS_NOT_SAVED);
+	return;    /* can not write the very own file :( */
+    }
 
     {
 	/* set few safe flags: */
@@ -1922,7 +1976,7 @@ PUBLIC void reload_read_cfg NOARGS
 	 }
 	 if (strcmp(LYCookieFile, LYCookieFile_flag)) {
 	     StrAllocCopy(LYCookieFile, LYCookieFile_flag);
-	     CTRACE(tfp, "cookies file can be changed in next session only, restored.\n")
+	     CTRACE(tfp, "cookies file can be changed in next session only, restored.\n");
 	 }
 #endif
 
@@ -2041,9 +2095,19 @@ static int anonymous_fun ARGS1(
     *  override or replace any additional
     *  restrictions from the command line. - FM
     */
-   if (!LYRestricted)
-      parse_restrictions("default");
-   LYRestricted = TRUE;
+    if (!LYRestricted) {
+	/* This should not happen unless the option parsing logic
+	   is broken. - kw */
+	fprintf(stderr, "Lynx: internal error parsing -anonymous!\n");
+#ifndef VMS
+	if (LYNoCore)		/* not worth a core dump, I think - kw */
+	    FatalProblem(0);
+	else
+	    exit(70);	/* EX_SOFTWARE in sysexits.h */
+#else
+	exit(-1);
+#endif
+    }
    return 0;
 }
 
@@ -2166,8 +2230,10 @@ static int display_fun ARGS1(
 {
     if (next_arg != 0) {
 	LYsetXDisplay(next_arg);
+#if 0		/* LYsetXDisplay already does this as a side effect  - kw */
 	if ((next_arg = LYgetXDisplay()) != 0)
 	    StrAllocCopy(x_display, next_arg);
+#endif
     }
 
     return 0;
@@ -2437,6 +2503,7 @@ static int restrictions_fun ARGS1(
  ""
 ,"   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"
@@ -2445,23 +2512,29 @@ static int restrictions_fun ARGS1(
 ,"                   (but still allow it for directories) when local file"
 ,"                   management is enabled."
 #endif /* DIRED_SUPPORT && OK_PERMIT */
-,"   default         same as commandline option -anonymous.  Disables"
-,"                   default services for anonymous users.  Currently set to,"
-,"                   all restricted except for: inside_telnet, outside_telnet,"
-,"                   inside_news, inside_ftp, outside_ftp, inside_rlogin,"
-,"                   outside_rlogin, goto, jump and mail.  Defaults"
-,"                   are settable within userdefs.h"
+#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."
 #ifdef DIRED_SUPPORT
 ,"   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 downloaders in the download menu"
+,"   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"
+,"   exec_frozen     disallow the user from changing the execution link option"
 #ifdef USE_EXTERNALS
-,"   externals       disable passing URLs to 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"
@@ -2469,37 +2542,40 @@ static int restrictions_fun ARGS1(
 #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 posting 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)"
 #else
 ,"   inside_ftp      disallow ftps for people coming from inside your domain"
-,"   inside_news     disallow USENET news posting 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"
 #endif /* HAVE_UTMP || VMS */
 ,"   jump            disable the 'j' (jump) command"
-,"   mail            disallow mail"
+,"   lynxcfg_info    disable viewing of lynx.cfg configuration file info"
+#ifndef NO_CONFIG_INFO
+,"   lynxcfg_xinfo   disable extended lynx.cfg viewing and reloading"
+#endif
 ,"   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 posting 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)"
 #else
 ,"   outside_ftp     disallow ftps for people coming from outside your domain"
-,"   outside_news    disallow USENET news posting 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"
 #endif /* !HAVE_UTMP || VMS */
@@ -2512,14 +2588,19 @@ static int restrictions_fun ARGS1(
     };
     size_t n;
 
-    if (next_arg != 0) {
-	parse_restrictions(next_arg);
-    } else {
+    if (next_arg == 0 || *next_arg == '\0') {
 	SetOutputMode( O_TEXT );
 	for (n = 0; n < sizeof(Usage)/sizeof(Usage[0]); n++)
 	    printf("%s\n", Usage[n]);
 	SetOutputMode( O_BINARY );
 	exit(0);
+    } else if (*next_arg == '?') {
+	SetOutputMode( O_TEXT );
+	print_restrictions_to_fd(stdout);
+	SetOutputMode( O_BINARY );
+	exit(0);
+    } else {
+	parse_restrictions(next_arg);
     }
     return 0;
 }
@@ -2616,7 +2697,7 @@ static Parse_Args_Type Arg_Table [] =
    ),
    PARSE_FUN(
       "anonymous",	FUNCTION_ARG,	anonymous_fun,
-      "used to specify the anonymous account"
+      "apply restrictions for anonymous account,\nsee also -restrictions"
    ),
    PARSE_FUN(
       "assume_charset", NEED_FUNCTION_ARG, assume_charset_fun,
@@ -2862,13 +2943,19 @@ keys (may be incompatible with some curses packages)"
       "nolog",		UNSET_ARG,		&error_logging,
       "disable mailing of error messages to document owners"
    ),
+#if HAVE_SIGACTION && defined(SIGWINCH)
+   PARSE_SET(
+      "nonrestarting_sigwinch", SET_ARG,	&LYNonRestartingSIGWINCH,
+      "make window size change handler non-restarting"
+   ),
+#endif /* HAVE_SIGACTION */
    PARSE_FUN(
       "nopause",	FUNCTION_ARG,		nopause_fun,
       "disable forced pauses for statusline messages"
    ),
    PARSE_SET(
       "noprint",	SET_ARG,		&no_print,
-      "disable print functions"
+      "disable some print functions, like -restrictions=print"
    ),
    PARSE_SET(
       "noredir",	SET_ARG,		&no_url_redirection,
@@ -2928,7 +3015,7 @@ to visualize how lynx behaves with invalid HTML"
 #endif
    PARSE_SET(
       "print",		UNSET_ARG,		&no_print,
-      "enable print functions (DEFAULT)"
+      "enable print functions (DEFAULT), opposite of -noprint"
    ),
    PARSE_SET(
       "pseudo_inlines", TOGGLE_ARG,		&pseudo_inline_alts,
@@ -3024,7 +3111,7 @@ treated '>' as a co-terminator for double-quotes and tags"
 #if defined(NCURSES_MOUSE_VERSION) || defined(USE_SLANG_MOUSE)
    PARSE_SET(
       "use_mouse",	SET_ARG,		&LYUseMouse,
-      "turn on xterm mouse support"
+      "turn on mouse support"
    ),
 #endif
    PARSE_STR(
@@ -3033,7 +3120,7 @@ treated '>' as a co-terminator for double-quotes and tags"
    ),
    PARSE_SET(
       "validate",	IGNORE_ARG,		0,
-      "accept only http URLs (for validation)"
+      "accept only http URLs (meant for validation)\nimplies more restrictions than -anonymous, but\ngoto is allowed for http and https"
    ),
    PARSE_SET(
       "verbose",	TOGGLE_ARG,		&verbose_img,
@@ -3204,6 +3291,9 @@ PRIVATE void parse_arg ARGS2(
 {
     Parse_Args_Type *p;
     char *arg_name;
+#if EXTENDED_STARTFILE_RECALL
+    static BOOLEAN had_nonoption = FALSE;
+#endif
 
     arg_name = argv[0];
 
@@ -3216,6 +3306,12 @@ PRIVATE void parse_arg ARGS2(
     if (*arg_name != '-' || no_options_further == TRUE )
 #endif
     {
+#if EXTENDED_STARTFILE_RECALL
+	if (had_nonoption && !dump_output_immediately) {
+	    HTAddGotoURL(startfile); /* startfile was set by a previous arg */
+	}
+	had_nonoption = TRUE;
+#endif
 	StrAllocCopy(startfile, arg_name);
 	LYTrimStartfile(startfile);
 	return;
@@ -3381,11 +3477,14 @@ have concise descriptions of the command and/or URL which causes\r\n\
 the problem, the operating system name with version number, the\r\n\
 TCPIP implementation, and any other relevant information.\r\n");
 
-	fprintf(stderr, "\r\n\
+	if (!(sig == 0 && LYNoCore)) {
+	    fprintf(stderr, "\r\n\
 Do NOT mail the core file if one was generated.\r\n");
-
-	fprintf(stderr, "\r\n\
+	}
+	if (sig != 0) {
+	    fprintf(stderr, "\r\n\
 Lynx now exiting with signal:  %d\r\n\r\n", sig);
+	}
 
 	/*
 	 *  Exit and possibly dump core.
diff --git a/src/LYMainLoop.c b/src/LYMainLoop.c
index 8bdc0ae0..f3e5835e 100644
--- a/src/LYMainLoop.c
+++ b/src/LYMainLoop.c
@@ -1,5 +1,6 @@
 #include <HTUtils.h>
 #include <HTAccess.h>
+#include <HTParse.h>
 #include <HTList.h>
 #include <HTML.h>
 #include <HTFTP.h>
@@ -56,15 +57,13 @@
 
 
 PRIVATE void exit_immediately_with_error_message PARAMS((int state, BOOLEAN first_file));
-PRIVATE void print_status_message PARAMS((CONST linkstruct curlink, char **cp));
+PRIVATE void show_main_statusline PARAMS((CONST linkstruct curlink));
 PRIVATE BOOL confirm_post_resub PARAMS((
     CONST char*		address,
     CONST char*		title,
     int			if_imgmap,
     int			if_file));
 PRIVATE int are_different PARAMS((document *doc1, document *doc2));
-PUBLIC void HTGotoURLs_free NOPARAMS;
-PUBLIC void HTAddGotoURL PARAMS((char *url));
 
 #ifndef DONT_TRACK_INTERNAL_LINKS
 PRIVATE int are_phys_different PARAMS((document *doc1, document *doc2));
@@ -173,10 +172,36 @@ PUBLIC BOOLEAN LYOpenTraceLog NOARGS
 	fprintf(tfp, "\t\t%s (%s)\n\n", LYNX_TRACELOG_TITLE, LYNX_VERSION);
 	/*
 	 *  If TRACE is on, indicate whether the
-	 *  anonymous restrictions are set. - FM
+	 *  anonymous restrictions are set. - FM, LP, kw
+	 *  This is only a summary for convenience - it doesn't
+	 *  take the case of individual -restrictions= options
+	 *  into account. - kw
 	 */
-	if (LYRestricted) {
-	    CTRACE(tfp, "Anonymous restrictions are set.\n");
+	if (LYValidate) {
+	    if (LYRestricted && had_restrictions_default) {
+		CTRACE(tfp, "Validate and some anonymous restrictions are set.\n");
+	    } else if (had_restrictions_default) {
+		CTRACE(tfp, "Validate restrictions set, restriction \"default\" was given.\n");
+	    } else if (LYRestricted) {
+		CTRACE(tfp, "Validate restrictions set, additional anonymous restrictions ignored.\n");
+	    } else {
+		CTRACE(tfp, "Validate restrictions are set.\n");
+	    }
+	    /* But none of the above can actually happen, since there should
+	     * never be a Trace Log with -validate.  If it appears in a log
+	     * file something went wrong! */
+	} else if (LYRestricted) {
+	    if (had_restrictions_all) {
+		CTRACE(tfp, "Anonymous restrictions set, restriction \"all\" was given.\n");
+	    } else {
+		CTRACE(tfp, "Anonymous restrictions are set.\n");
+	    }
+	} else if (had_restrictions_all && had_restrictions_default) {
+	    CTRACE(tfp, "Restrictions \"all\" and \"default\" were given.\n");
+	} else if (had_restrictions_default) {
+	    CTRACE(tfp, "Restriction \"default\" was given.\n");
+	} else if (had_restrictions_all) {
+	    CTRACE(tfp, "\"all\" restrictions are set.\n");
 	}
     }
     return TRUE;
@@ -207,16 +232,29 @@ PRIVATE BOOLEAN LYReopenTracelog ARGS1(BOOLEAN *, trace_flag_ptr)
     return TRUE;
 }
 
-PRIVATE void do_change_link ARGS1(
+PRIVATE int do_change_link ARGS1(
 	char *,		prev_target)
 {
     /* Is there a mouse-clicked link waiting? */
     int mouse_tmp = get_mouse_link();
     /* If yes, use it as the link */
     if (mouse_tmp != -1) {
+	if (curdoc.link >= 0 && curdoc.link < nlinks &&
+	    curdoc.link != mouse_tmp) {
 	highlight(OFF, curdoc.link, prev_target);
+	}
+	if (mouse_tmp < 0 || mouse_tmp >= nlinks) {
+	    char *msgtmp = NULL;
+	    HTSprintf0(&msgtmp,
+		       gettext("Internal error: Invalid mouse link %d!"),
+		       mouse_tmp);
+	    HTAlert(msgtmp);
+	    FREE(msgtmp);
+	    return(-1);		/* indicates unexpected error */
+	}
 	curdoc.link = mouse_tmp;
     }
+    return(0);			/* indicates OK */
 }
 
 /*
@@ -238,6 +276,7 @@ int mainloop NOARGS
     char user_input_buffer[1024];
     char *owner_address = NULL;  /* Holds the responsible owner's address     */
     char *ownerS_address = NULL; /* Holds owner's address during source fetch */
+    CONST char *cshelpfile = NULL;
     BOOLEAN first_file = TRUE;
     BOOLEAN popped_doc = FALSE;
     BOOLEAN refresh_screen = FALSE;
@@ -283,11 +322,13 @@ int mainloop NOARGS
     newdoc.post_data = NULL;
     newdoc.post_content_type = NULL;
     newdoc.bookmark = NULL;
+    newdoc.internal_link = FALSE;
     curdoc.address = NULL;
     curdoc.title = NULL;
     curdoc.post_data = NULL;
     curdoc.post_content_type = NULL;
     curdoc.bookmark = NULL;
+    curdoc.internal_link = FALSE;
 #ifdef USE_HASH
     curdoc.style = NULL;
     newdoc.style = NULL;
@@ -305,7 +346,6 @@ initialize:
     StrAllocCopy(newdoc.title, gettext("Entry into main screen"));
     newdoc.isHEAD = FALSE;
     newdoc.safe = FALSE;
-    newdoc.internal_link = FALSE;
     newdoc.line = 1;
     newdoc.link = 0;
 
@@ -600,43 +640,74 @@ try_again:
 		     *	Do any error logging, if appropriate.
 		     */
 		    LYoverride_no_cache = FALSE; /* Was TRUE if popped. - FM */
-		    popped_doc = FALSE;		 /* Was TRUE if popped. - FM */
 		    LYinternal_flag = FALSE;	 /* Reset to default. - kw */
 		    if (trace_mode_flag == TRUE) {
 			WWW_TraceFlag = TRUE;
 			trace_mode_flag = FALSE;
 			fprintf(tfp, "Turning TRACE back on.\n\n");
 		    }
-		    if (error_logging &&
-			first_file && owner_address && !LYCancelledFetch) {
+		    if (!first_file && !LYCancelledFetch) {
 			/*
+			 *  Do error mail sending and/or traversal
+			 *  stuff.  Note that the links[] elements may
+			 *  not be valid at this point, if we did call
+			 *  HTuncache_current_document!   This should
+			 *  not have happened for traversal, but for
+			 *  sending error mail check that HTMainText
+			 *  exists for this reason. - kw
+			 */
+			if (error_logging && nhist > 0 && !popped_doc &&
+			    !LYUserSpecifiedURL &&
+			    HTMainText &&
+			    nlinks > 0 && curdoc.link < nlinks &&
+			    strncmp(newdoc.address ? newdoc.address : "",
+				    "LYNXHIST:", 9) &&
+			    strncmp(newdoc.address ? newdoc.address : "",
+				    "LYNXCOOKIE:", 11)) {
+			    char *mail_owner = NULL;
+			    if (owner_address &&
+				strncasecomp(owner_address, "mailto:", 7)) {
+				mail_owner = owner_address + 7;
+			    }
+			    /*
 			 *  Email a bad link message to the owner of
-			 *  the document (but NOT to lynx-dev). - FM
+			 *  the document, or to ALERTMAIL if defined,
+			 *  but NOT to lynx-dev (it is rejected in
+			 *  mailmsg). - FM, kw
 			 */
-			if (strncasecomp(owner_address, "mailto:", 7)) {
-			    if (strncasecomp((owner_address + 7),
-					     "lynx-dev@", 9)) {
+#ifndef ALERTMAIL
+			    if (mail_owner)
+#endif
 				mailmsg(curdoc.link,
-					(owner_address+7),
+					mail_owner,
 					history[nhist-1].address,
 					history[nhist-1].title);
-			    }
 			}
-		    }
-		    if (traversal && !first_file && !LYCancelledFetch) {
-			FILE *ofp;
+			if (traversal) {
+			    FILE *ofp;
 
-			if ((ofp = LYAppendToTxtFile(TRAVERSE_ERRORS)) == NULL) {
-			    if ((ofp = LYNewTxtFile(TRAVERSE_ERRORS)) == NULL) {
-				perror(NOOPEN_TRAV_ERR_FILE);
-				exit_immediately(-1);
+			    if ((ofp = LYAppendToTxtFile(TRAVERSE_ERRORS)) == NULL) {
+				if ((ofp = LYNewTxtFile(TRAVERSE_ERRORS)) == NULL) {
+				    perror(NOOPEN_TRAV_ERR_FILE);
+				    exit_immediately(-1);
+				}
+			    }
+			    if (nhist > 0) {
+				fprintf(ofp,
+					"%s %s\tin %s\n",
+					popped_doc ?
+					newdoc.address : links[curdoc.link].lname,
+					links[curdoc.link].target,
+					history[nhist-1].address);
+			    } else {
+				fprintf(ofp,
+					"%s %s\t\n",
+					popped_doc ?
+					newdoc.address : links[curdoc.link].lname,
+					links[curdoc.link].target);
 			    }
+			    fclose(ofp);
 			}
-			fprintf(ofp, "%s %s\tin %s\n",
-				     links[curdoc.link].lname,
-				     links[curdoc.link].target,
-				     history[nhist-1].address);
-			fclose(ofp);
 		    }
 
 		    /*
@@ -727,13 +798,23 @@ try_again:
 		    }
 
 		   /*
+		    *  If we're going to pop from history because
+		    *  getfile didn't succeed, reset LYforce_no_cache
+		    *  first.  This would have been done in HTAccess.c
+		    *  if the request got that far, but the URL may
+		    *  have been handled or rejected in getfile without
+		    *  taking care of that. - kw
+		    */
+		    LYforce_no_cache = FALSE;
+		   /*
 		    *  Retrieval of a newdoc just failed, and just
 		    *  going to try_again would pop the next doc
 		    *  from history and try to get it without further
 		    *  questions.  This may not be the right thing to do if
 		    *  we have POST data, so fake a PREV_DOC key if it seems
-		    *  that some prompting should be done.  Dunno about the
-		    *  traversal logic, so I leave that case alone.
+		    *  that some prompting should be done.  This doesn't
+		    *  affect the traversal logic, since with traversal
+		    *  POST data can never occur. - kw
 		    */
 		   if (history[nhist - 1].post_data &&
 		       !history[nhist - 1].safe) {
@@ -933,7 +1014,7 @@ try_again:
 		     */
 #ifdef DISP_PARTIAL
 		    /* Newline = newdoc.line; */
-		    /* - alreary set and probably updated in partial mode */
+		    /* - already set and probably updated in partial mode */
 		    /* incremental rendering stage already closed (but see below) */
 
 		    if (Newline != Newline_partial || display_partial == TRUE) {
@@ -1037,7 +1118,7 @@ try_again:
 	   LYNoRefererForThis = FALSE;	/* always reset on return here */
 	   reloading = FALSE;		/* only set for RELOAD and RESUBMIT */
 	   HEAD_request = FALSE;	/* only set for HEAD requests */
-	   LYPermitURL = FALSE;		/* only set for LYValidate */
+	   LYPermitURL = FALSE;		/* only for LYValidate or check_realm */
 	   ForcePush = FALSE;		/* only set for some PRINT requests. */
 	   LYforce_HTML_mode = FALSE;
 	   popped_doc = FALSE;
@@ -1058,9 +1139,27 @@ try_again:
 	 *  then the window size changed recently.
 	 */
 	if (recent_sizechange) {
+	    /*
+	     *  First we need to make sure the display library - curses, slang,
+	     *  whatever - gets notified about the change, and gets a chance
+	     *  to update external structures appropriately.  Hopefully the
+	     *  stop_curses()/start_curses() sequence achieves this, at least
+	     *  if the display library has a way to get the new screen size
+	     *  from the OS.
+	     *  However, at least for ncurses, the update of the internal
+	     *  structures will come still too late - the changed screen
+	     *  size is detected in doupdate(), which would only be called
+	     *  (indirectly through the HText_pageDisplay below) after the
+	     *  WINDOW structures are already filled based on the old size.
+	     *  So we notify the ncurses library directly here. - kw
+	     */
+#ifdef NCURSES_VERSION		/* FIXME: check for specific version? */
+	    resizeterm(LYlines, LYcols);
+#else
 		stop_curses();
 		start_curses();
 		clear();
+#endif
 		refresh_screen = TRUE; /* to force a redraw */
 		if (HTMainText)	/* to REALLY force it... - kw */
 		    HText_setStale(HTMainText);
@@ -1220,7 +1319,7 @@ try_again:
 	 *  Trying to accomodate HTreparse_document() logic
 	 *  with mainloop events.  Working out of force_load cycle
 	 *  set all the necessary flags here, from case NORMAL
-	 *  (see also LYK_SOURCE, some staff implemented directly there).
+	 *  (see also LYK_SOURCE, some stuff implemented directly there).
 	 */
 	if (from_source_cache) {
 	    from_source_cache = FALSE; /* done */
@@ -1285,7 +1384,10 @@ try_again:
 		    /*
 		     *	We may have popped a doc (possibly in local_dired)
 		     *	which didn't have any links when it was pushed, but
-		     *	does have links now (e.g., a file was created) - KW
+		     *	does have links now (e.g., a file was created).
+		     *  Code below assumes that curdoc.link is valid and
+		     *  that (curdoc.link==-1) only occurs if (nlinks==0)
+		     *  is true. - KW
 		     */
 		    curdoc.link = 0;
 		}
@@ -1322,6 +1424,20 @@ try_again:
 	     */
 	    more = HText_canScrollDown();
 
+	    /*
+	     *  Adjust curdoc.link as above; nlinks may have changed,
+	     *  if the refresh_screen flag was set as a result of
+	     *  a size change.
+	     *  Code below assumes that curdoc.link is valid and
+	     *  that (curdoc.link==-1) only occurs if (nlinks==0)
+	     *  is true. - kw
+	     */
+	    if (curdoc.link >= nlinks) {
+		curdoc.link = nlinks - 1;
+	    } else if (curdoc.link < 0 && nlinks > 0) {
+		curdoc.link = 0;
+	    }
+
 	    if (user_mode == NOVICE_MODE)
 		noviceline(more);  /* print help message */
 	    refresh_screen = FALSE;
@@ -1340,7 +1456,7 @@ try_again:
 	 *  to tell the user other misc info.
 	 */
 	if (!show_help) {
-	   print_status_message(links[curdoc.link], &cp);
+	   show_main_statusline(links[curdoc.link]);
 	} else {
 	   show_help = FALSE;
 	}
@@ -1397,6 +1513,8 @@ try_again:
 		 links[curdoc.link].form->type == F_TEXT_SUBMIT_TYPE ||
 		 links[curdoc.link].form->type == F_PASSWORD_TYPE ||
 		 links[curdoc.link].form->type == F_TEXTAREA_TYPE)) {
+
+		BOOLEAN use_last_tfpos;
 		/*
 		 *  Replace novice lines if in NOVICE_MODE.
 		 */
@@ -1406,12 +1524,33 @@ try_again:
 		    move(LYlines-1,0); clrtoeol();
 		    addstr(FORM_NOVICELINE_TWO);
 		}
-		c = change_form_link(&links[curdoc.link],
+		use_last_tfpos = (real_cmd==LYK_LPOS_PREV_LINK ||
+				  real_cmd==LYK_LPOS_NEXT_LINK);
+		real_c = change_form_link(&links[curdoc.link],
 				     &newdoc, &refresh_screen,
 				     links[curdoc.link].form->name,
-				     links[curdoc.link].form->value);
+					  links[curdoc.link].form->value,
+					  use_last_tfpos, FALSE);
 
-		if (c == '\n' || c == '\r') {
+		c = (real_c==LKC_DONE) ? DO_NOTHING : LKC_TO_C(real_c);
+		if (c != DO_NOTHING &&
+		    peek_mouse_link() != -1 && peek_mouse_link() != -2)
+		    old_c = 0;
+		if (peek_mouse_link() >= 0 &&
+		    LKC_TO_LAC(keymap,real_c) != LYK_CHANGE_LINK) {
+		    do_change_link(prev_target);
+		    if ((c == '\n' || c == '\r') &&
+			links[curdoc.link].type == WWW_FORM_LINK_TYPE &&
+			(links[curdoc.link].form->type == F_TEXT_TYPE ||
+			 links[curdoc.link].form->type == F_TEXT_SUBMIT_TYPE ||
+			 links[curdoc.link].form->type == F_PASSWORD_TYPE ||
+			 links[curdoc.link].form->type == F_TEXTAREA_TYPE)) {
+			c = DO_NOTHING;
+		    }
+		} else
+		    switch (c) {
+		    case '\n':
+		    case '\r':
 #ifdef AUTOGROW
 		    /*
 		     *  If on the bottom line of a TEXTAREA, and the user hit
@@ -1429,6 +1568,8 @@ try_again:
 		     */
 		    if ((links[curdoc.link].type       == WWW_FORM_LINK_TYPE &&
 			 links[curdoc.link].form->type == F_TEXTAREA_TYPE)
+/*			&&
+			 (peek_mouse_link() == -1) */
 			&&
 			 ((curdoc.link == nlinks-1)
 			 ||
@@ -1464,17 +1605,17 @@ try_again:
 		   }
 #endif /* AUTOGROW */
 
-#ifdef FASTTAB
 		    /*
-		     *	Make return act like down-arrow.
+		     *	Make return in input field (if it was returned
+		     *  by change_form_link) act as LYK_NEXT_LINK,
+		     *  independent of what key (if any) is mapped to
+		     *  LYK_NEXT_LINK. - kw
 		     */
-		    c = DNARROW;
-#else
-		    /*
-		     *	Make return act like tab.
-		     */
-		    c = '\t';
-#endif /* FASTTAB */
+		    c = LAC_TO_LKC0(LYK_NEXT_LINK);
+		    break;
+		default:
+		    if (old_c != c && old_c != real_c && c != real_c)
+			real_c = c;
 		}
 	    } else {
 		/*
@@ -1496,6 +1637,19 @@ try_again:
 		    goto new_cmd;
 		}
 #endif /* !VMS */
+		if (LKC_HAS_ESC_MOD(c) && EditBinding(c) != LYE_FORM_PASS) {
+		    /*
+		     *  If ESC + <key> was read (and not recognized as a
+		     *  terminal escape sequence for another key), ignore
+		     *  the ESC modifier and act on <key> only if the line
+		     *  editor binding would have passed the same ESC-modified
+		     *  lynxkeycode back to us if it had been pressed in a
+		     *  text input field.  Otherwise set interesting part
+		     *  so that it will map to 0, to prevent that ESC + <key>
+		     *  acts like <key>, which might be unexpected. - kw
+		     */
+		    c = (c & ~LKC_MASK) | LAC_TO_LKC(0);
+		}
 		if (old_c != real_c) {
 		    old_c = 0;
 		}
@@ -1527,10 +1681,14 @@ new_keyboard_input:
 	     *	"traversal_host" are searched - this keeps the search
 	     *	from crossing to other servers (a feature, not a bug!).
 	     */
-	    rlink_exists = (nlinks > 0 && links[curdoc.link].lname != NULL);
+	    BOOLEAN rlink_rejected = FALSE;
+	    rlink_exists = (nlinks > 0 &&
+			    links[curdoc.link].type != WWW_FORM_LINK_TYPE &&
+			    links[curdoc.link].lname != NULL);
 	    if (rlink_exists) {
+		rlink_rejected = lookup_reject(links[curdoc.link].lname);
 		rlink_allowed =
-		    (!lookup_reject(links[curdoc.link].lname) &&
+		    (!rlink_rejected &&
 		     traversal_host && links[curdoc.link].lname &&
 		     !strncmp(traversal_host,
 			      (strncmp(links[curdoc.link].lname,
@@ -1565,7 +1723,8 @@ new_keyboard_input:
 		    c = RTARROW;
 		}
 	    } else { /* no good right link, so only down and left arrow ok*/
-		if (rlink_exists)
+		if (rlink_exists /* && !rlink_rejected */)
+		    /* uncomment in previous line to avoid duplicates - kw */
 		    add_to_reject_list(links[curdoc.link].lname);
 		if (more_links ||
 		    (curdoc.link > -1 && curdoc.link < nlinks-1))
@@ -1588,11 +1747,11 @@ new_keyboard_input:
 	    } /* right link not NULL or link to another site*/
 	} /* traversal */
 
-	cmd = keymap[c+1];  /* add 1 to map EOF to 0 */
+	cmd = LKC_TO_LAC(keymap,c);  /* adds 1 to map EOF to 0 */
 
 #if defined(DIRED_SUPPORT) && defined(OK_OVERRIDE)
-	if (lynx_edit_mode && key_override[c+1] && !no_dired_support)
-	  cmd = key_override[c+1];
+	if (lynx_edit_mode && !no_dired_support && LKC_TO_LAC(key_override,c))
+	  cmd = LKC_TO_LAC(key_override,c);
 #endif /* DIRED_SUPPORT && OK_OVERRIDE */
 
 	real_cmd = cmd;
@@ -1607,7 +1766,15 @@ new_cmd:  /*
 	switch(cmd) {
 	case 0: /* unmapped character */
 	default:
-	    if (more)
+	    if (curdoc.link >= 0 && curdoc.link < nlinks &&
+		links[curdoc.link].type == WWW_FORM_LINK_TYPE &&
+		(links[curdoc.link].form->type == F_TEXT_TYPE ||
+		 links[curdoc.link].form->type == F_TEXT_SUBMIT_TYPE ||
+		 links[curdoc.link].form->type == F_PASSWORD_TYPE ||
+		 links[curdoc.link].form->type == F_TEXTAREA_TYPE))
+		
+		show_main_statusline(links[curdoc.link]);
+	    else if (more)
 		_statusline(MOREHELP);
 	    else
 		_statusline(HELP);
@@ -2303,6 +2470,7 @@ new_cmd:  /*
 	    break;
 
 	case LYK_PREV_LINK:
+	case LYK_LPOS_PREV_LINK:
 	    if (curdoc.link > 0) {	     /* previous link */
 		/*
 		 *  Unhighlight current link.
@@ -2345,6 +2513,7 @@ new_cmd:  /*
 	    break;
 
 	case LYK_NEXT_LINK:
+	case LYK_LPOS_NEXT_LINK:
 	    if (curdoc.link < nlinks-1) {	/* next link */
 		highlight(OFF, curdoc.link, prev_target);
 #ifdef FASTTAB
@@ -2860,7 +3029,8 @@ new_cmd:  /*
 	    if (nlinks > 0) {
 		if (links[curdoc.link].type == WWW_FORM_LINK_TYPE &&
 		    links[curdoc.link].form->type != F_SUBMIT_TYPE &&
-		    links[curdoc.link].form->type != F_IMAGE_SUBMIT_TYPE) {
+		    links[curdoc.link].form->type != F_IMAGE_SUBMIT_TYPE &&
+		    links[curdoc.link].form->type != F_TEXT_SUBMIT_TYPE) {
 		    if (old_c == real_c)
 			break;
 		    old_c = real_c;
@@ -2873,11 +3043,11 @@ new_cmd:  /*
 	    } /* fall through to LYK_ACTIVATE */
 
 	case LYK_ACTIVATE:			/* follow a link */
-	    {
-	     /* Is there a mouse-clicked link waiting? */
-	     int mouse_tmp = get_mouse_link();
-	     /* If yes, use it as the link */
-	     if (mouse_tmp != -1) curdoc.link = mouse_tmp;
+	case LYK_SUBMIT:	/* follow a link, submit TEXT_SUBMIT input */
+	    if (do_change_link(prev_target) == -1) {
+		LYforce_no_cache = FALSE;
+		reloading = FALSE;
+		continue;	/* mouse stuff was confused, ignore - kw */
 	    }
 	     if (nlinks > 0) {
 		if (links[curdoc.link].type == WWW_FORM_LINK_TYPE) {
@@ -3014,36 +3184,107 @@ new_cmd:  /*
 			    !strncmp(curdoc.address, "file:", 5)) {
 			    LYNoRefererForThis = TRUE;
 			}
-			StrAllocCopy(newdoc.title,
-				     links[curdoc.link].hightext);
+			if (links[curdoc.link].form->submit_method
+				     != URL_MAIL_METHOD) {
+			    StrAllocCopy(newdoc.title,
+					 links[curdoc.link].hightext);
+			}
+		    }
+		    /*
+		     *	Normally we don't get here for text input fields,
+		     *  but it can happen as a result of mouse positioning.
+		     *  In that case the statusline will not have updated
+		     *  info, so update it now. - kw
+		     */
+
+		    if (links[curdoc.link].form->type == F_TEXT_TYPE ||
+			links[curdoc.link].form->type == F_TEXT_SUBMIT_TYPE ||
+			links[curdoc.link].form->type == F_PASSWORD_TYPE ||
+			links[curdoc.link].form->type == F_TEXTAREA_TYPE) {
+			show_formlink_statusline(links[curdoc.link].form);
 		    }
+ 
 		    c = change_form_link(&links[curdoc.link],
 					 &newdoc, &refresh_screen,
 					 links[curdoc.link].form->name,
-					 links[curdoc.link].form->value);
-		    if (HTOutputFormat == HTAtom_for("www/download") &&
+					 links[curdoc.link].form->value,
+					 FALSE,
+					 (real_cmd==LYK_SUBMIT ||
+					  real_cmd==LYK_NOCACHE ||
+					  real_cmd==LYK_DOWNLOAD ||
+					  real_cmd==LYK_HEAD));
+		    if (c != LKC_DONE || refresh_screen) {
+			/*
+			 *  Cannot have been a submit field for which
+			 *  newdoc was filled in. - kw
+			 */
+			if ((links[curdoc.link].form->type == F_SUBMIT_TYPE ||
+			     links[curdoc.link].form->type == F_IMAGE_SUBMIT_TYPE ||
+			     links[curdoc.link].form->type == F_TEXT_SUBMIT_TYPE) &&
+			    links[curdoc.link].form->submit_method
+				     != URL_MAIL_METHOD) {
+			    /*
+			     *  Try to undo change of newdoc.title done above.
+			     */
+			    if (HText_getTitle()) {
+				StrAllocCopy(newdoc.title, HText_getTitle());
+			    } else if (curdoc.title) {
+				StrAllocCopy(newdoc.title, curdoc.title);
+			    }
+			}
+		    } else {
+			if (HTOutputFormat == HTAtom_for("www/download") &&
 			newdoc.post_data != NULL &&
 			newdoc.safe == FALSE) {
-			if ((HText_POSTReplyLoaded(&newdoc) == TRUE) &&
-			    HTConfirm(CONFIRM_POST_RESUBMISSION) == FALSE) {
-			    HTInfoMsg(CANCELLED);
-			    HTOutputFormat = WWW_PRESENT;
-			    LYforce_no_cache = FALSE;
-			    StrAllocCopy(newdoc.address, curdoc.address);
-			    StrAllocCopy(newdoc.title, curdoc.title);
-			    StrAllocCopy(newdoc.post_data, curdoc.post_data);
-			    StrAllocCopy(newdoc.post_content_type,
-					 curdoc.post_content_type);
-			    StrAllocCopy(newdoc.bookmark, curdoc.bookmark);
-			    newdoc.isHEAD = curdoc.isHEAD;
-			    newdoc.safe = curdoc.safe;
-			    newdoc.internal_link = curdoc.internal_link;
-			    break;
+			    if ((HText_POSTReplyLoaded(&newdoc) == TRUE) &&
+				HTConfirm(CONFIRM_POST_RESUBMISSION) == FALSE) {
+				HTInfoMsg(CANCELLED);
+				HTOutputFormat = WWW_PRESENT;
+				LYforce_no_cache = FALSE;
+				StrAllocCopy(newdoc.address, curdoc.address);
+				StrAllocCopy(newdoc.title, curdoc.title);
+				StrAllocCopy(newdoc.post_data, curdoc.post_data);
+				StrAllocCopy(newdoc.post_content_type,
+					     curdoc.post_content_type);
+				StrAllocCopy(newdoc.bookmark, curdoc.bookmark);
+				newdoc.isHEAD = curdoc.isHEAD;
+				newdoc.safe = curdoc.safe;
+				newdoc.internal_link = curdoc.internal_link;
+				break;
+			    }
+			}
+			/*
+			 *  Moved here from earlier to only apply when it
+			 *  should.   Anyway, why should realm checking be
+			 *  overridden for form submissions, this seems to
+			 *  be an unnecessary loophole??  But that's the way
+			 *  it was, maybe there is some reason.
+			 *  However, at least make sure this doesn't weaken
+			 *  restrictions implied by -validate!
+			 *  - kw 1999-05-25
+			 */
+			if (check_realm && !LYValidate) {
+			    LYPermitURL = TRUE;
 			}
 		    }
-		    if (c == 23) {
+		    if (c == LKC_DONE) {
+			c = DO_NOTHING;
+		    } else if (c == 23) {
 			c = DO_NOTHING;
 			refresh_screen = TRUE;
+		    } else
+			switch (LKC_TO_C(c)) {
+			case '\n':
+			case '\r':
+			    /*  Avoid getting stuck with repeatedly calling
+			    **  the second change_form_link() instead of the
+			    **  first for text input fields. - kw
+			    */
+			    if (peek_mouse_link() == -1 ||
+				peek_mouse_link() == curdoc.link)
+				c = DO_NOTHING;
+			default:
+			    break;
 		    }
 		    goto new_keyboard_input;
 		} else {
@@ -3055,7 +3296,12 @@ new_cmd:  /*
 		     */
 		    if (no_file_url &&
 			!strncmp(links[curdoc.link].lname, "file:", 5)) {
-			if (strncmp(curdoc.address, "file:", 5)) {
+			if (strncmp(curdoc.address, "file:", 5) &&
+			    !((!strncmp(curdoc.address, "LYNXKEYMAP:", 11) ||
+			       !strncmp(curdoc.address, "LYNXCOOKIE:", 11)) &&
+			      !strncmp(links[curdoc.link].lname,
+				       helpfilepath,
+				       strlen(helpfilepath)))) {
 			    HTAlert(FILE_SERVED_LINKS_DISALLOWED);
 			    reloading = FALSE;
 			    break;
@@ -3697,12 +3943,15 @@ check_goto_URL:
 		       !strncmp(user_input_buffer, "wais:", 5)) {
 		HTUserMsg(GOTO_WAIS_DISALLOWED);
 
+	    } else if (no_goto_configinfo &&
+		       (!strncmp(user_input_buffer, "LYNXCFG:", 8) ||
+			!strncmp(user_input_buffer, "LYNXCOMPILEOPTS:", 16))) {
+		HTUserMsg(GOTO_SPECIAL_DISALLOWED);
+
 	    } else if (!strncmp(user_input_buffer, "LYNXCOOKIE:", 11) ||
 		       !strncmp(user_input_buffer, "LYNXDIRED:", 10) ||
 		       !strncmp(user_input_buffer, "LYNXDOWNLOAD:", 13) ||
 		       !strncmp(user_input_buffer, "LYNXOPTIONS:", 12) ||
-		       !strncmp(user_input_buffer, "LYNXCFG:", 8) ||
-		       !strncmp(user_input_buffer, "LYNXCOMPILEOPTS:", 16) ||
 		       !strncmp(user_input_buffer, "LYNXPRINT:", 10)) {
 		HTUserMsg(GOTO_SPECIAL_DISALLOWED);
 
@@ -3734,12 +3983,30 @@ check_goto_URL:
 	    }
 	    break;
 
+	case LYK_DWIMHELP:		/* show context-dependent help file */
+	    /*
+	     *  Currently a different help file form the main
+	     *  'helpfile' is shown only if current link is a
+	     *  text input form field. - kw
+	     */
+	    if (curdoc.link >= 0 && curdoc.link < nlinks &&
+		links[curdoc.link].type == WWW_FORM_LINK_TYPE &&
+		(links[curdoc.link].form->type == F_TEXT_TYPE ||
+		 links[curdoc.link].form->type == F_TEXT_SUBMIT_TYPE ||
+		 links[curdoc.link].form->type == F_PASSWORD_TYPE ||
+		 links[curdoc.link].form->type == F_TEXTAREA_TYPE)) {
+		cshelpfile = LYLineeditHelpURL();
+	    }
+	    /* fall through to LYK_HELP */
+
 	case LYK_HELP:			/* show help file */
-	    if (!STREQ(curdoc.address, helpfile)) {
+	    if (cshelpfile == NULL)
+		cshelpfile = helpfile;
+	    if (!STREQ(curdoc.address, cshelpfile)) {
 		/*
 		 *  Set the filename.
 		 */
-		StrAllocCopy(newdoc.address, helpfile);
+		StrAllocCopy(newdoc.address, cshelpfile);
 		/*
 		 *  Make a name for this help file.
 		 */
@@ -3751,6 +4018,7 @@ check_goto_URL:
 		newdoc.safe = FALSE;
 		newdoc.internal_link = FALSE;
 	    }
+	    cshelpfile = NULL;	/* reset pointer - kw */
 	    break;
 
 	case LYK_INDEX:  /* index file */
@@ -3958,6 +4226,9 @@ if (!LYUseFormsOptions) {
 		newdoc.safe = FALSE;
 		newdoc.internal_link = FALSE;
 		LYforce_no_cache = TRUE;
+		/* change to 'if (check_realm && !LYValidate)' and
+		   make change near top of getfile to forbid
+		   using forms options menu with -validate:  - kw */
 		if (LYValidate || check_realm) {
 		    LYPermitURL = TRUE;
 		}
@@ -4302,14 +4573,8 @@ if (!LYUseFormsOptions) {
 	    break;
 #endif /* DIRED_SUPPORT */
 
-	case LYK_EDIT:	/* edit */
-	    if (no_editor) {
-		if (old_c != real_c) {
-		    old_c = real_c;
-		    HTUserMsg(EDIT_DISABLED);
-		}
-		break;
-	    }
+	case LYK_DWIMEDIT:	/* context-dependent edit */
+
 #ifdef AUTOEXTEDIT
 	    /*
 	     *  If we're in a forms TEXTAREA, invoke the editor on *its*
@@ -4338,8 +4603,25 @@ if (!LYUseFormsOptions) {
 		HTUserMsg (CANNOT_EDIT_FIELD);
 		break;
 	    }
+
+	    if (no_editor) {
+		if (old_c != real_c) {
+		    old_c = real_c;
+		    HTUserMsg(ANYEDIT_DISABLED);
+		}
+		break;
+	    } /* fall through */
 #endif /* AUTOEXTEDIT */
 
+	case LYK_EDIT:	/* edit */
+	    if (no_editor) {
+		if (old_c != real_c) {
+		    old_c = real_c;
+		    HTUserMsg(EDIT_DISABLED);
+		}
+		break;
+	    }
+
 #ifdef DIRED_SUPPORT
 	    /*
 	     *	Allow the user to edit the link rather
@@ -4469,6 +4751,8 @@ if (!LYUseFormsOptions) {
 	     */
 	    if (strcmp((curdoc.title ? curdoc.title : ""),
 		       SHOWINFO_TITLE)) {
+		if (do_change_link(prev_target) == -1)
+		    break;	/* mouse stuff was confused, ignore - kw */
 		if (showinfo(&curdoc, HText_getNumOfLines(),
 			     &newdoc, owner_address) < 0)
 		    break;
@@ -4495,7 +4779,14 @@ if (!LYUseFormsOptions) {
 	    if (no_editor) {
 		if (old_c != real_c) {
 		    old_c = real_c;
-		    HTUserMsg(EDIT_DISABLED);
+		    HTUserMsg(ANYEDIT_DISABLED);
+		}
+		break;
+	    }
+	    if (!editor || *editor == '\0') {
+		if (old_c != real_c) {
+		    old_c = real_c;
+		    HTUserMsg(NO_EDITOR);
 		}
 		break;
 	    }
@@ -4529,7 +4820,7 @@ if (!LYUseFormsOptions) {
 
 	    } else {
 
-		HTInfoMsg (NOT_IN_TEXTAREA);
+		HTInfoMsg (NOT_IN_TEXTAREA_NOEDIT);
 	    }
 	    break;
 
@@ -4557,6 +4848,30 @@ if (!LYUseFormsOptions) {
 	    if (links[curdoc.link].type       == WWW_FORM_LINK_TYPE &&
 		links[curdoc.link].form->type == F_TEXTAREA_TYPE)   {
 
+		/*
+		 *  Reject attempts to use this for gaining access to
+		 *  local files when such access is restricted:
+		 *  if no_file_url was set via the file_url restriction,
+		 *  if no_goto_file was set for the anonymous account,
+		 *  or if HTDirAccess was set to HT_DIR_FORBID or
+		 *  HT_DIR_SELECTIVE via the -nobrowse or -selective
+		 *  switches, it is assumed that inserting files or
+		 *  checking for existence of files needs to be denied. - kw
+		 */
+		if (no_file_url || no_goto_file ||
+		    HTDirAccess == HT_DIR_FORBID ||
+		    HTDirAccess == HT_DIR_SELECTIVE) {
+		    if (old_c != real_c) {
+			old_c = real_c;
+			if (no_goto_file)
+			    HTUserMsg(GOTO_FILE_DISALLOWED);
+			else
+			    HTUserMsg(NOAUTH_TO_ACCESS_FILES);
+			HTInfoMsg(FILE_INSERT_CANCELLED);
+		    }
+		    break;
+		}
+		
 		n = HText_InsertFile (&links[curdoc.link]);
 
 		/*
@@ -4939,7 +5254,7 @@ if (!LYUseFormsOptions) {
 			 *  save either that or the link. - FM
 			 */
 			_statusline(BOOK_D_L_OR_CANCEL);
-			c = LYgetch();
+			c = LYgetch_for(FOR_SINGLEKEY);
 			if (TOUPPER(c) == 'D') {
 			    save_bookmark_link(curdoc.address, curdoc.title);
 			    refresh_screen = TRUE; /* MultiBookmark support */
@@ -4975,7 +5290,7 @@ if (!LYUseFormsOptions) {
 			     */
 			    _statusline(BOOK_L_OR_CANCEL);
 			}
-			c = LYgetch();
+			c = LYgetch_for(FOR_SINGLEKEY);
 		    }
 		    if (TOUPPER(c) == 'L') {
 			if (curdoc.post_data != NULL &&
@@ -5015,7 +5330,7 @@ if (!LYUseFormsOptions) {
 		    break;
 		} else {
 		    _statusline(BOOK_D_OR_CANCEL);
-		    c = LYgetch();
+		    c = LYgetch_for(FOR_SINGLEKEY);
 		    if (TOUPPER(c) == 'D') {
 			save_bookmark_link(curdoc.address, curdoc.title);
 			refresh_screen = TRUE; /* MultiBookmark support */
@@ -5118,10 +5433,13 @@ check_add_bookmark_to_self:
 			DOWNLOAD_OPTIONS_TITLE))
 		break;
 
+	    if (do_change_link(prev_target) == -1)
+		continue;	/* mouse stuff was confused, ignore - kw */
 	    if (nlinks > 0) {
 		if (links[curdoc.link].type == WWW_FORM_LINK_TYPE) {
 		    if (links[curdoc.link].form->type == F_SUBMIT_TYPE ||
-			links[curdoc.link].form->type == F_IMAGE_SUBMIT_TYPE) {
+			links[curdoc.link].form->type == F_IMAGE_SUBMIT_TYPE ||
+			links[curdoc.link].form->type == F_TEXT_SUBMIT_TYPE) {
 			if (links[curdoc.link].form->submit_method ==
 				 URL_MAIL_METHOD) {
 			    if (old_c != real_c) {
@@ -5244,6 +5562,7 @@ check_add_bookmark_to_self:
 				    "LYNXPRINT:", 10) ||
 			   !strncmp(links[curdoc.link].lname,
 				    "LYNXOPTIONS:", 12) ||
+     /* @@@ should next two be downloadable? - kw */
 			   !strncmp(links[curdoc.link].lname,
 				    "LYNXCFG:", 8) ||
 			   !strncmp(links[curdoc.link].lname,
@@ -5447,13 +5766,14 @@ check_add_bookmark_to_self:
 	    if (nlinks > 0 &&
 		(links[curdoc.link].type != WWW_FORM_LINK_TYPE ||
 		 links[curdoc.link].form->type == F_SUBMIT_TYPE ||
-		 links[curdoc.link].form->type == F_IMAGE_SUBMIT_TYPE)) {
+		 links[curdoc.link].form->type == F_IMAGE_SUBMIT_TYPE ||
+		 links[curdoc.link].form->type == F_TEXT_SUBMIT_TYPE)) {
 		/*
 		 *  We have links, and the current link is a
 		 *  normal link or a form's submit button. - FM
 		 */
 		_statusline(HEAD_D_L_OR_CANCEL);
-		c = LYgetch();
+		c = LYgetch_for(FOR_SINGLEKEY);
 		if (TOUPPER(c) == 'D') {
 		    char *scheme = strncmp(curdoc.address, "LYNXIMGMAP:", 11) ?
 			curdoc.address : curdoc.address + 11;
@@ -5534,7 +5854,7 @@ check_add_bookmark_to_self:
 		     *	current document, not the form link. - FM
 		     */
 		    _statusline(HEAD_D_OR_CANCEL);
-		    c = LYgetch();
+		    c = LYgetch_for(FOR_SINGLEKEY);
 		} else {
 		    /*
 		     *	No links, so we can just assume that
@@ -5935,21 +6255,21 @@ PRIVATE int are_phys_different ARGS2(
 /*
  *  Utility for freeing the list of goto URLs. - FM
  */
-PUBLIC void HTGotoURLs_free NOARGS
+#ifdef LY_FIND_LEAKS
+PRIVATE void HTGotoURLs_free NOARGS
 {
     char *url;
     HTList *cur = Goto_URLs;
 
-    if (!cur)
-	return;
-
-    while (NULL != (url = (char *)HTList_nextObject(cur))) {
-	FREE(url);
+    if (cur != 0) {
+	while (NULL != (url = (char *)HTList_nextObject(cur))) {
+	    FREE(url);
+	}
+	HTList_delete(Goto_URLs);
+	Goto_URLs = NULL;
     }
-    HTList_delete(Goto_URLs);
-    Goto_URLs = NULL;
-    return;
 }
+#endif
 
 /*
  *  Utility for listing Goto URLs, making any
@@ -5996,9 +6316,8 @@ PUBLIC void HTAddGotoURL ARGS1(
  *  put a message on the screen
  *  to tell the user other misc info.
  */
-PRIVATE void print_status_message ARGS2(
-	CONST linkstruct,	curlink,
-	char **,		cp)
+PRIVATE void show_main_statusline ARGS1(
+    CONST linkstruct,	curlink)
 {
     /*
      *	Make sure form novice lines are replaced.
@@ -6007,16 +6326,16 @@ PRIVATE void print_status_message ARGS2(
 	noviceline(more);
     }
 
-    /*
-     *	If we are in forms mode then explicitly
-     *	tell the user what each kind of link is.
-     */
     if (HTisDocumentSource()) {
 	/*
 	 *  Currently displaying HTML source.
 	 */
 	_statusline(SOURCE_HELP);
 
+    /*
+     *	If we are in forms mode then explicitly
+     *	tell the user what each kind of link is.
+     */
 #ifdef INDICATE_FORMS_MODE_FOR_ALL_LINKS_ON_PAGE
     } else if (lynx_mode == FORMS_LYNX_MODE && nlinks > 0) {
 #else
@@ -6030,109 +6349,7 @@ PRIVATE void print_status_message ARGS2(
 #endif /* NORMAL_NON_FORM_LINK_STATUSLINES_FOR_ALL_USER_MODES */
 #endif /* INDICATE_FORMS_MODE_FOR_ALL_LINKS_ON_PAGE */
 	if (curlink.type == WWW_FORM_LINK_TYPE) {
-	    switch(curlink.form->type) {
-	    case F_PASSWORD_TYPE:
-		if (curlink.form->disabled == YES)
-		    statusline(FORM_LINK_PASSWORD_UNM_MSG);
-		else
-		    statusline(FORM_LINK_PASSWORD_MESSAGE);
-		break;
-	    case F_OPTION_LIST_TYPE:
-		if (curlink.form->disabled == YES)
-		    statusline(FORM_LINK_OPTION_LIST_UNM_MSG);
-		else
-		    statusline(FORM_LINK_OPTION_LIST_MESSAGE);
-		break;
-	    case F_CHECKBOX_TYPE:
-		if (curlink.form->disabled == YES)
-		    statusline(FORM_LINK_CHECKBOX_UNM_MSG);
-		else
-		    statusline(FORM_LINK_CHECKBOX_MESSAGE);
-		break;
-	    case F_RADIO_TYPE:
-		if (curlink.form->disabled == YES)
-		    statusline(FORM_LINK_RADIO_UNM_MSG);
-		else
-		    statusline(FORM_LINK_RADIO_MESSAGE);
-		break;
-	    case F_TEXT_SUBMIT_TYPE:
-		if (curlink.form->disabled == YES) {
-		    statusline(FORM_LINK_TEXT_SUBMIT_UNM_MSG);
-		} else if (curlink.form->submit_method ==
-			 URL_MAIL_METHOD) {
-		    if (no_mail)
-			statusline(FORM_LINK_TEXT_SUBMIT_MAILTO_DIS_MSG);
-		    else
-			statusline(FORM_LINK_TEXT_SUBMIT_MAILTO_MSG);
-		} else if (curlink.form->no_cache) {
-		    statusline(FORM_LINK_TEXT_RESUBMIT_MESSAGE);
-		} else {
-		    statusline(FORM_LINK_TEXT_SUBMIT_MESSAGE);
-		}
-		break;
-	    case F_SUBMIT_TYPE:
-	    case F_IMAGE_SUBMIT_TYPE:
-		if (curlink.form->disabled == YES) {
-		    statusline(FORM_LINK_SUBMIT_DIS_MSG);
-		} else if (curlink.form->submit_method ==
-			 URL_MAIL_METHOD) {
-		    if (no_mail) {
-			statusline(FORM_LINK_SUBMIT_MAILTO_DIS_MSG);
-		    } else {
-			if(user_mode == ADVANCED_MODE) {
-			    char *submit_str = NULL;
-
-			    StrAllocCopy(submit_str, FORM_LINK_SUBMIT_MAILTO_PREFIX);
-			    StrAllocCat(submit_str, curlink.form->submit_action);
-			    statusline(submit_str);
-			    FREE(submit_str);
-			} else {
-			    statusline(FORM_LINK_SUBMIT_MAILTO_MSG);
-			}
-		    }
-		} else if (curlink.form->no_cache) {
-		    if(user_mode == ADVANCED_MODE) {
-			char *submit_str = NULL;
-
-			StrAllocCopy(submit_str, FORM_LINK_RESUBMIT_PREFIX);
-			StrAllocCat(submit_str, curlink.form->submit_action);
-			statusline(submit_str);
-			FREE(submit_str);
-		    } else {
-			statusline(FORM_LINK_RESUBMIT_MESSAGE);
-		    }
-		} else {
-		    if(user_mode == ADVANCED_MODE) {
-			char *submit_str = NULL;
-
-			StrAllocCopy(submit_str, FORM_LINK_SUBMIT_PREFIX);
-			StrAllocCat(submit_str, curlink.form->submit_action);
-			statusline(submit_str);
-			FREE(submit_str);
-		    } else {
-			statusline(FORM_LINK_SUBMIT_MESSAGE);
-		    }
-		}
-		break;
-	    case F_RESET_TYPE:
-		if (curlink.form->disabled == YES)
-		    statusline(FORM_LINK_RESET_DIS_MSG);
-		else
-		    statusline(FORM_LINK_RESET_MESSAGE);
-		break;
-	    case F_TEXT_TYPE:
-		if (curlink.form->disabled == YES)
-		    statusline(FORM_LINK_TEXT_UNM_MSG);
-		else
-		    statusline(FORM_LINK_TEXT_MESSAGE);
-		break;
-	    case F_TEXTAREA_TYPE:
-		if (curlink.form->disabled == YES)
-		    statusline(FORM_LINK_TEXT_UNM_MSG);
-		else
-		    statusline(FORM_LINK_TEXTAREA_MESSAGE);
-		break;
-	    }
+	    show_formlink_statusline(curlink.form);
 	} else {
 	    statusline(NORMAL_LINK_MESSAGE);
 	}
@@ -6151,24 +6368,23 @@ PRIVATE void print_status_message ARGS2(
 	/*
 	 *  Show the URL or, for some internal links, the fragment
 	 */
-	*cp = NULL;
+	char *cp = NULL;
 	if (curlink.type == WWW_INTERN_LINK_TYPE &&
 	    strncmp(curlink.lname, "LYNXIMGMAP:", 11)) {
-	    *cp = strchr(curlink.lname, '#');
+	    cp = strchr(curlink.lname, '#');
 	}
-	if (!(*cp))
-	    *cp = curlink.lname;
+	if (!cp)
+	    cp = curlink.lname;
 	if (more) {
 	    if (is_www_index)
-		_user_message("-more- -index- %s",
-					 *cp);
+		_user_message("-more- -index- %s", cp);
 	    else
-		_user_message("-more- %s",*cp);
+		_user_message("-more- %s", cp);
 	} else {
 	    if (is_www_index)
-		_user_message("-index- %s",*cp);
+		_user_message("-index- %s", cp);
 	    else
-		statusline(*cp);
+		statusline(cp);
 	}
     } else if (is_www_index && more) {
 	char buf[128];
@@ -6192,6 +6408,17 @@ PRIVATE void print_status_message ARGS2(
     move((LYlines - 1), (LYcols - 1));
 }
 
+/*
+ *  Public function for redrawing the statusline appropriate for the
+ *  selected link.  It should only be called at times when curdoc.link,
+ *  nlinks, and the links[] array are valid. - kw
+ */
+PUBLIC void repaint_main_statusline NOARGS
+{
+    if (curdoc.link >= 0 && curdoc.link < nlinks)
+	show_main_statusline(links[curdoc.link]);
+}
+
 
 PRIVATE void exit_immediately_with_error_message ARGS2(
 	int,		state,
diff --git a/src/LYMainLoop.h b/src/LYMainLoop.h
index 4b9b562f..44923639 100644
--- a/src/LYMainLoop.h
+++ b/src/LYMainLoop.h
@@ -10,7 +10,9 @@
 #define AUTOEXTEDIT
 
 extern BOOLEAN LYOpenTraceLog NOPARAMS;
-extern void LYCloseTracelog NOPARAMS;
 extern int mainloop NOPARAMS;
+extern void HTAddGotoURL PARAMS((char *url));
+extern void LYCloseTracelog NOPARAMS;
+extern void repaint_main_statusline NOPARAMS;
 
 #endif /* LYMAINLOOP_H */
diff --git a/src/LYOptions.c b/src/LYOptions.c
index 0884d18a..06c7663f 100644
--- a/src/LYOptions.c
+++ b/src/LYOptions.c
@@ -471,7 +471,7 @@ draw_options:
 	lynx_stop_prompt_color ();
 
 	refresh();
-	response = LYgetch();
+	response = LYgetch_for(FOR_SINGLEKEY);
 	if (term_options || response == 7 || response == 3)
 	    response = 'R';
 	if (LYisNonAlnumKeyname(response, LYK_REFRESH)) {
@@ -631,7 +631,7 @@ draw_options:
 						     (1 + LYMBMAdvanced)),
 						    L_HOME, (C_MULTI - 1),
 						    choices,
-						    3, FALSE);
+						    3, FALSE, FALSE);
 		}
 		if (LYMultiBookmarks == 2) {
 		    LYMultiBookmarks = TRUE;
@@ -757,7 +757,7 @@ draw_options:
 		    HTfileSortMethod = popup_choice(HTfileSortMethod,
 						    L_FTPSTYPE, -1,
 						    choices,
-						    4, FALSE);
+						    4, FALSE, FALSE);
 #if defined(VMS) || defined(USE_SLANG)
 		    move(L_FTPSTYPE, COL_OPTION_VALUES);
 		    clrtoeol();
@@ -862,7 +862,7 @@ draw_options:
 			UCLYhndl_for_unspec = popup_choice(curval,
 							   L_ASSUME_CHARSET, -1,
 							   assume_list,
-							   0, FALSE);
+							   0, FALSE, FALSE);
 #if defined(VMS) || defined(USE_SLANG)
 			move(L_ASSUME_CHARSET, COL_OPTION_VALUES);
 			clrtoeol();
@@ -926,7 +926,7 @@ draw_options:
 		    current_char_set = popup_choice(current_char_set,
 						    L_Charset, -1,
 						    (char **)LYchar_set_names,
-						    0, FALSE);
+						    0, FALSE, FALSE);
 #if defined(VMS) || defined(USE_SLANG)
 		    move(L_Charset, COL_OPTION_VALUES);
 		    clrtoeol();
@@ -1212,7 +1212,7 @@ draw_options:
 			    chosen = popup_choice(LYChosenShowColor,
 						  L_Color,
 						  C_COLOR,
-						  choices, 4, FALSE);
+						  choices, 4, FALSE, FALSE);
 			}
 #if defined(COLOR_CURSES)
 			again = (chosen == 2 && !has_colors());
@@ -1308,7 +1308,7 @@ draw_options:
 		    keypad_mode = popup_choice(keypad_mode,
 					       L_Keypad, -1,
 					       choices,
-					       3, FALSE);
+					       3, FALSE, FALSE);
 #if defined(VMS) || defined(USE_SLANG)
 		    move(L_Keypad, COL_OPTION_VALUES);
 		    clrtoeol();
@@ -1348,7 +1348,7 @@ draw_options:
 		    current_lineedit = popup_choice(current_lineedit,
 						    L_Lineed, -1,
 						    LYLineeditNames,
-						    0, FALSE);
+						    0, FALSE, FALSE);
 #if defined(VMS) || defined(USE_SLANG)
 		    move(L_Lineed, COL_OPTION_VALUES);
 		    clrtoeol();
@@ -1381,7 +1381,7 @@ draw_options:
 		    current_layout = popup_choice(current_layout,
 						    L_Layout, -1,
 						    LYKbLayoutNames,
-						    0, FALSE);
+						    0, FALSE, FALSE);
 #if defined(VMS) || defined(USE_SLANG)
 		    move(L_Layout, COL_OPTION_VALUES);
 		    clrtoeol();
@@ -1425,7 +1425,7 @@ draw_options:
 		    dir_list_style = popup_choice(dir_list_style,
 						  L_Dired, -1,
 						  choices,
-						  3, FALSE);
+						  3, FALSE, FALSE);
 #if defined(VMS) || defined(USE_SLANG)
 		    move(L_Dired, COL_OPTION_VALUES);
 		    clrtoeol();
@@ -1472,7 +1472,7 @@ draw_options:
 		    user_mode = popup_choice(user_mode,
 					     L_User_Mode, -1,
 					     choices,
-					     3, FALSE);
+					     3, FALSE, FALSE);
 		    use_assume_charset = (user_mode >= 2);
 #if defined(VMS) || defined(USE_SLANG)
 		    if (use_assume_charset == old_use_assume_charset) {
@@ -1526,7 +1526,7 @@ draw_options:
 					     L_VERBOSE_IMAGES,
 					     C_VERBOSE_IMAGES,
 					     choices,
-					     2, FALSE);
+					     2, FALSE, FALSE);
 		}
 		FREE(choices[0]);
 		FREE(choices[1]);
@@ -1766,7 +1766,7 @@ PRIVATE int boolean_choice ARGS4(
     while (1) {
 	move(line, col);
 	if (term_options == FALSE) {
-	    response = LYgetch();
+	    response = LYgetch_for(FOR_SINGLEKEY);
 	}
 	if (term_options || response == 7 || response == 3) {
 	     /*
@@ -1785,7 +1785,7 @@ PRIVATE int boolean_choice ARGS4(
 	}
 #endif /* VMS */
 	if ((response != '\n' && response != '\r') &&
-	    (cmd = keymap[response+1]) != LYK_ACTIVATE) {
+	    (cmd = LKC_TO_LAC(keymap,response)) != LYK_ACTIVATE) {
 	    switch (cmd) {
 		case LYK_HOME:
 		    cur_choice = 0;
@@ -1811,6 +1811,7 @@ PRIVATE int boolean_choice ARGS4(
 		case LYK_UP_HALF:
 		case LYK_UP_TWO:
 		case LYK_PREV_LINK:
+		case LYK_LPOS_PREV_LINK:
 		case LYK_FASTBACKW_LINK:
 		case LYK_UP_LINK:
 		case LYK_LEFT_LINK:
@@ -2005,7 +2006,7 @@ draw_bookmark_list:
 	lynx_stop_prompt_color ();
 
 	refresh();
-	response = (def_response ? def_response : LYgetch());
+	response = (def_response ? def_response : LYgetch_for(FOR_SINGLEKEY));
 	def_response = 0;
 
 	/*
@@ -2216,14 +2217,18 @@ PRIVATE int get_popup_choice_number ARGS1(
  *  This function offers the choices for values of an
  *  option via a popup window which functions like
  *  that for selection of options in a form. - FM
+ *
+ *  Also used for mouse popups with ncurses; this is indicated
+ *  by for_mouse.
  */
-PUBLIC int popup_choice ARGS6(
+PUBLIC int popup_choice ARGS7(
 	int,		cur_choice,
 	int,		line,
 	int,		column,
 	char **,	choices,
 	int,		i_length,
-	int,		disabled)
+	int,		disabled,
+	BOOLEAN,	for_mouse)
 {
     int ly = line;
     int lx = (column >= 0 ? column : (COL_OPTION_VALUES - 1));
@@ -2251,6 +2256,7 @@ PUBLIC int popup_choice ARGS6(
     BOOLEAN ReDraw = FALSE;
     int number;
     char buffer[512];
+    char *popup_status_msg = NULL;
 
     /*
      * Initialize the search string buffer. - FM
@@ -2356,6 +2362,16 @@ PUBLIC int popup_choice ARGS6(
 	top = bottom - length - 2;
     }
 
+    if (for_mouse) {
+	/* shift horizontally to lie within screen width, if possible */
+	if (Lnum + (int)width + 4 < LYcols) {
+	    if (lx - 1 + (Lnum + (int)width + 4) > LYcols)
+		lx = LYcols + 1 - (Lnum + width + 4);
+	    else if (lx <= 0)
+		lx = 1;
+	}
+    }
+	
     /*
      *	Set up the overall window, including the boxing characters ('*'),
      *	if it all fits.  Otherwise, set up the widest window possible. - FM
@@ -2389,10 +2405,16 @@ PUBLIC int popup_choice ARGS6(
     move((LYlines - 2), 0);
     clrtoeol();
     if (disabled) {
-	_statusline(CHOICE_LIST_UNM_MSG);
+	StrAllocCopy(popup_status_msg, CHOICE_LIST_UNM_MSG);
+    } else if (!for_mouse) {
+	StrAllocCopy(popup_status_msg, CHOICE_LIST_MESSAGE);
+#ifdef NCURSES_MOUSE_VERSION
     } else {
-	_statusline(CHOICE_LIST_MESSAGE);
+	StrAllocCopy(popup_status_msg, gettext(
+		"Left mouse button or return to select, arrow keys to scroll."));
+#endif
     }
+    _statusline(popup_status_msg);
 
     /*
      *	Set up the window_offset for choices.
@@ -2533,7 +2555,7 @@ redraw:
 		break;
 #endif
 	} else {
-	    cmd = keymap[c+1];
+	    cmd = LKC_TO_LAC(keymap,c);
 	}
 #ifdef VMS
 	if (HadVMSInterrupt) {
@@ -2571,20 +2593,12 @@ redraw:
 		    if (number <= 1) {
 			if (window_offset == 0) {
 			    HTUserMsg(ALREADY_AT_CHOICE_BEGIN);
-			    if (disabled) {
-				_statusline(CHOICE_LIST_UNM_MSG);
-			    } else {
-				_statusline(CHOICE_LIST_MESSAGE);
-			    }
+			    _statusline(popup_status_msg);
 			    break;
 			}
 			window_offset = 0;
 			cur_choice = 0;
-			if (disabled) {
-			    _statusline(CHOICE_LIST_UNM_MSG);
-			} else {
-			    _statusline(CHOICE_LIST_MESSAGE);
-			}
+			_statusline(popup_status_msg);
 			goto redraw;
 		    }
 
@@ -2595,11 +2609,7 @@ redraw:
 		    if (number >= npages) {
 			if (window_offset >= ((num_choices - length) + 1)) {
 			    HTUserMsg(ALREADY_AT_CHOICE_END);
-			    if (disabled) {
-				_statusline(CHOICE_LIST_UNM_MSG);
-			    } else {
-				_statusline(CHOICE_LIST_MESSAGE);
-			    }
+			    _statusline(popup_status_msg);
 			    break;
 			}
 			window_offset = ((npages - 1) * length);
@@ -2608,11 +2618,7 @@ redraw:
 			}
 			if (cur_choice < window_offset)
 			    cur_choice = window_offset;
-			if (disabled) {
-			    _statusline(CHOICE_LIST_UNM_MSG);
-			} else {
-			    _statusline(CHOICE_LIST_MESSAGE);
-			}
+			_statusline(popup_status_msg);
 			goto redraw;
 		    }
 
@@ -2622,19 +2628,11 @@ redraw:
 		    if (((number - 1) * length) == window_offset) {
 			sprintf(buffer, ALREADY_AT_CHOICE_PAGE, number);
 			HTUserMsg(buffer);
-			if (disabled) {
-			    _statusline(CHOICE_LIST_UNM_MSG);
-			} else {
-			    _statusline(CHOICE_LIST_MESSAGE);
-			}
+			_statusline(popup_status_msg);
 			break;
 		    }
 		    cur_choice = window_offset = ((number - 1) * length);
-		    if (disabled) {
-			_statusline(CHOICE_LIST_UNM_MSG);
-		    } else {
-			_statusline(CHOICE_LIST_MESSAGE);
-		    }
+		    _statusline(popup_status_msg);
 		    goto redraw;
 
 		}
@@ -2672,11 +2670,7 @@ redraw:
 			    sprintf(buffer,
 				    CHOICE_ALREADY_CURRENT, (number + 1));
 			    HTUserMsg(buffer);
-			    if (disabled) {
-				_statusline(CHOICE_LIST_UNM_MSG);
-			    } else {
-				_statusline(CHOICE_LIST_MESSAGE);
-			    }
+			    _statusline(popup_status_msg);
 			    break;
 			}
 
@@ -2698,11 +2692,7 @@ redraw:
 				if (window_offset < 0)
 				    window_offset = 0;
 			    }
-			    if (disabled) {
-				_statusline(CHOICE_LIST_UNM_MSG);
-			    } else {
-				_statusline(CHOICE_LIST_MESSAGE);
-			    }
+			    _statusline(popup_status_msg);
 			    goto redraw;
 			}
 
@@ -2716,14 +2706,11 @@ redraw:
 		/*
 		 *  Restore the popup statusline. - FM
 		 */
-		if (disabled) {
-		    _statusline(CHOICE_LIST_UNM_MSG);
-		} else {
-		    _statusline(CHOICE_LIST_MESSAGE);
-		}
+		_statusline(popup_status_msg);
 		break;
 
 	    case LYK_PREV_LINK:
+	    case LYK_LPOS_PREV_LINK:
 	    case LYK_UP_LINK:
 
 		if (cur_choice > 0)
@@ -2739,6 +2726,7 @@ redraw:
 		break;
 
 	    case LYK_NEXT_LINK:
+	    case LYK_LPOS_NEXT_LINK:
 	    case LYK_DOWN_LINK:
 		if (cur_choice < num_choices)
 		    cur_choice++;
@@ -3163,10 +3151,7 @@ restore_popup_statusline:
 		 *  Restore the popup statusline and
 		 *  reset the search variables. - FM
 		 */
-		if (disabled)
-		    _statusline(CHOICE_LIST_UNM_MSG);
-		else
-		    _statusline(CHOICE_LIST_MESSAGE);
+		_statusline(popup_status_msg);
 		*prev_target = '\0';
 		QueryTotal = (search_queries ? HTList_count(search_queries)
 					     : 0);
@@ -3183,12 +3168,17 @@ restore_popup_statusline:
 	    case LYK_PREV_DOC:
 		cur_choice = orig_choice;
 		term_options = TRUE;
-		HTUserMsg(CANCELLED);
+		if (!for_mouse) {
+		    HTUserMsg(CANCELLED);
+		}
 		cmd = LYK_ACTIVATE; /* to exit */
 		break;
 	}
     }
+    FREE(popup_status_msg);
 #ifndef USE_SLANG
+    /* added touchline() - kw 19990513 */
+    touchline(stdscr, top, bottom - top);
     delwin(form_window);
 #ifdef NCURSES
     LYsubwindow(0);
@@ -3199,7 +3189,9 @@ restore_popup_statusline:
 	_statusline("");
 	return(orig_choice);
     } else {
-	_statusline(VALUE_ACCEPTED);
+	if (!for_mouse) {
+	    _statusline(VALUE_ACCEPTED);
+	}
 	return(cur_choice);
     }
 }
@@ -3932,6 +3924,7 @@ PUBLIC int postoptions ARGS1(
     if (save_all) {
 	_statusline(SAVING_OPTIONS);
 	if (save_rc()) {
+	    LYrcShowColor = LYChosenShowColor;
 	    _statusline(OPTIONS_SAVED);
 	} else {
 	    HTAlert(OPTIONS_NOT_SAVED);
@@ -4106,6 +4099,13 @@ PRIVATE int gen_options ARGS1(
 
     LYLocalFileToURL(newfile, tempfile);
 
+    /* This should not be needed, as long as we regenerate the
+       temp file every time with a new name (which just happened
+       above.  If access to the actual file via getfile()
+       (maybe because of some restrictions), mainloop may leave
+       this flag on after popping the previous doc which is then
+       unnecessarily reloaded.  But I changed mainloop to reset
+       the flag. - kw 1999-05-24 */
     LYforce_no_cache = TRUE;
 
     BeginInternalPage(fp0, OPTIONS_TITLE, NULL); /* help link below */
@@ -4217,7 +4217,8 @@ PRIVATE int gen_options ARGS1(
 #if defined(USE_SLANG) || defined(COLOR_CURSES)
     can_do_colors = 1;
 #if defined(COLOR_CURSES)
-    can_do_colors = has_colors();
+    if (LYCursesON)	/* could crash if called before initialization */
+	can_do_colors = has_colors();
 #endif
     PutLabel(fp0, gettext("Show color"));
     MaybeSelect(fp0, !can_do_colors, show_color_string);
@@ -4472,7 +4473,7 @@ PRIVATE int gen_options ARGS1(
 		     NOTEMPTY(LYUserAgent), text_len, "");
     }
 
-    if (!LYRestricted) {
+    if (!no_lynxcfg_info) {
 	fprintf(fp0,
 		"\n  Check your <a href=\"LYNXCFG:\">lynx.cfg</a> here\n");
     }
diff --git a/src/LYOptions.h b/src/LYOptions.h
index 60cb6c6e..d0dc120f 100644
--- a/src/LYOptions.h
+++ b/src/LYOptions.h
@@ -12,7 +12,8 @@ extern  int popup_choice PARAMS((
 	int		column,
 	char ** 	choices,
 	int		i_length,
-	int		disabled));
+	int		disabled,
+	BOOLEAN		for_mouse));
 
 #ifndef NO_OPTION_FORMS
 extern int postoptions PARAMS((document *newdoc));
diff --git a/src/LYPrint.c b/src/LYPrint.c
index 4e4ef9ae..810a1ab7 100644
--- a/src/LYPrint.c
+++ b/src/LYPrint.c
@@ -989,6 +989,7 @@ PRIVATE void send_file_to_screen ARGS3(
 	Lpansi = FALSE;
     } else {
 	fprintf(stdout,"\n\n%s", PRESS_RETURN_TO_FINISH);
+	fflush(stdout);  /* refresh to screen */
 	LYgetch();  /* grab some user input to pause */
 #ifdef VMS
 	HadVMSInterrupt = FALSE;
diff --git a/src/LYReadCFG.c b/src/LYReadCFG.c
index f7142ac6..a8cc016b 100644
--- a/src/LYReadCFG.c
+++ b/src/LYReadCFG.c
@@ -178,8 +178,10 @@ PRIVATE void add_item_to_list ARGS2(
 	remove_backslashes(cur_item->name);
 
 	/*
-	 *  Process TRUE/FALSE field.  If we do not find one, assume it is
-	 *  true.  In any case, we want the command string.
+	 *  Find end of command string and beginning of TRUE/FALSE option
+	 *  field.  If we do not find a colon that ends the command string,
+	 *  leave the always_enabled option flag as FALSE.  In any case,
+	 *  we want the command string.
 	 */
 	if ((next_colon = find_colon(colon+1)) == NULL) {
 	    next_colon = colon + strlen(colon);
@@ -190,7 +192,6 @@ PRIVATE void add_item_to_list ARGS2(
 		outofmem(__FILE__, "read_cfg");
 	    LYstrncpy(cur_item->command, colon+1, (int)(next_colon-(colon+1)));
 	    remove_backslashes(cur_item->command);
-	    cur_item->always_enabled = TRUE;
 	}
 	if (*next_colon++) {
 	    cur_item->always_enabled = is_true(next_colon);
@@ -635,18 +636,60 @@ static int keyboard_layout_fun ARGS1(
 static int keymap_fun ARGS1(
 	char *,		key)
 {
-    char *func;
+    char *func, *efunc;
 
     if ((func = strchr(key, ':')) != NULL)	{
 	*func++ = '\0';
+	efunc = strchr(func, ':');
 	/* Allow comments on the ends of key remapping lines. - DT */
-	if (!remap(key, strtok(func, " \t\n#")))
-	    fprintf(stderr, "%s%s%s%s%s\n",
-		    gettext("key remapping of "),
-		    key, TO_SEGMENT, func,
-		    gettext(" failed"));
-	else if (!strcmp("TOGGLE_HELP", strtok(func, " \t\n#")))
-	    LYUseNoviceLineTwo = FALSE;
+	/* Allow third field for line-editor action. - kw */
+	if (efunc == func) {	/* have 3rd field, but 2nd field empty */
+	    func = NULL;
+	} else if (!remap(key, strtok(func, " \t\n:#"))) {
+	    fprintf(stderr, gettext("key remapping of %s to %s failed\n"),
+		    key, func);
+	} else {
+	    if (func && !strcmp("TOGGLE_HELP", func))
+		LYUseNoviceLineTwo = FALSE;
+	}
+	if (efunc) {
+	    efunc++;
+	    if (efunc == strtok((func ? NULL : efunc), " \t\n:#") && *efunc) {
+		BOOLEAN success = FALSE;
+		int lkc = lkcstring_to_lkc(key);
+		int lec = -1;
+		if (strcasecomp(efunc, "PASS!") == 0) {
+		    if (func) {
+			lec = LYE_FORM_LAC|lacname_to_lac(func);
+			success = LYRemapEditBinding(lkc, lec);
+		    }
+		    if (!success)
+			fprintf(stderr,
+				gettext(
+   "setting of line-editor binding for key %s (0x%x) to 0x%x for %s failed\n"),
+				key, lkc, lec, efunc);
+		    else
+			return 0;
+		}
+		if (!success && strncasecomp(efunc, "PASS", 4) == 0) {
+		    lec = LYE_FORM_PASS;
+		    success = LYRemapEditBinding(lkc, lec);
+		}
+		if (!success) {
+		    if (lec != -1) {
+			fprintf(stderr,
+				gettext(
+   "setting of line-editor binding for key %s (0x%x) to 0x%x for %s failed\n"),
+				key, lkc, lec, efunc);
+		    } else {
+			fprintf(stderr,
+				gettext(
+	   "setting of line-editor binding for key %s (0x%x) for %s failed\n"),
+				key, lkc, efunc);
+		    }
+		}
+	    }
+	}
     }
     return 0;
 }
@@ -854,6 +897,16 @@ static int viewer_fun ARGS1(
     return 0;
 }
 
+static int nonrest_sigwinch_fun ARGS1(
+	char *, 	value)
+{
+    if (!strncasecomp(value, "XWINDOWS", 8)) {
+	LYNonRestartingSIGWINCH = (LYgetXDisplay() != NULL);
+    } else {
+	LYNonRestartingSIGWINCH = is_true(value);
+    }
+    return 0;
+}
 
 #ifdef USE_PSRC
 
@@ -1111,6 +1164,7 @@ static Config_Type Config_Table [] =
      PARSE_SET("no_ismap_if_usemap", CONF_BOOL, &LYNoISMAPifUSEMAP),
      PARSE_ENV("no_proxy", CONF_ENV, 0 ),
      PARSE_SET("no_referer_header", CONF_BOOL, &LYNoRefererHeader),
+     PARSE_SET("nonrestarting_sigwinch", CONF_FUN, nonrest_sigwinch_fun),
      PARSE_FUN("outgoing_mail_charset", CONF_FUN, outgoing_mail_charset_fun),
 #ifdef DISP_PARTIAL
      PARSE_SET("partial", CONF_BOOL, &display_partial_flag),
@@ -1448,7 +1502,7 @@ PRIVATE void do_read_cfg ARGS5(
 	    }
 
 #ifndef NO_CONFIG_INFO
-	    if (fp0 != 0  &&  !LYRestricted) {
+	    if (fp0 != 0  &&  !no_lynxcfg_xinfo) {
 		LYLocalFileToURL(&url, value);
 		StrAllocCopy(cp1, value);
 		if (strchr(value, '&') || strchr(value, '<')) {
@@ -1509,7 +1563,7 @@ PRIVATE void do_read_cfg ARGS5(
 	     * of allowed options in <ul>.  Option names will be uppercased. 
 	     * FIXME:  uppercasing option names can be considered redundant.
 	     */
-	    if (fp0 != 0  &&  !LYRestricted && resultant_set) {
+	    if (fp0 != 0  &&  !no_lynxcfg_xinfo && resultant_set) {
 		char *buf = NULL;
 		unsigned i;
 
@@ -1527,7 +1581,7 @@ PRIVATE void do_read_cfg ARGS5(
 	    do_read_cfg (value, cfg_filename, nesting_level + 1, fp0,resultant_set);
 
 #ifndef NO_CONFIG_INFO
-	    if (fp0 != 0  &&  !LYRestricted) {
+	    if (fp0 != 0  &&  !no_lynxcfg_xinfo) {
 		fprintf(fp0, "    #&lt;end of %s&gt;\n\n", cp1);
 		FREE(url);
 		FREE(cp1);
@@ -1651,7 +1705,7 @@ PUBLIC void read_cfg ARGS4(
 
 /*
  *  Show rendered lynx.cfg data without comments, LYNXCFG:/ internal page.
- *  Called from getfile() cyrcle:
+ *  Called from getfile() cycle:
  *  we create and load the page just in place and return to mainloop().
  */
 PUBLIC int lynx_cfg_infopage ARGS1(
@@ -1671,9 +1725,9 @@ PUBLIC int lynx_cfg_infopage ARGS1(
      * "  <a href=\"LYNXCFG://reload\">RELOAD THE CHANGES</a>\n"
      *--------------------------------------------------*/
 
-    if ((strstr(newdoc->address, "LYNXCFG://reload")) && !LYRestricted) {
+    if (!no_lynxcfg_xinfo && (strstr(newdoc->address, "LYNXCFG://reload"))) {
 	/*
-	 *  Some staff to reload read_cfg(),
+	 *  Some stuff to reload read_cfg(),
 	 *  but also load options menu items and command-line options
 	 *  to make things consistent.	Implemented in LYMain.c
 	 */
@@ -1730,7 +1784,7 @@ PUBLIC int lynx_cfg_infopage ARGS1(
 
 
 #ifndef NO_CONFIG_INFO
-	if (!LYRestricted) {
+	if (!no_lynxcfg_xinfo) {
 #if defined(HAVE_CONFIG_H) || defined(VMS)
 	    if (strcmp(lynx_cfg_file, LYNX_CFG_FILE)) {
 		fprintf(fp0, "<em>%s\n%s",
@@ -1787,7 +1841,7 @@ PUBLIC int lynx_cfg_infopage ARGS1(
 	LYCloseTempFP(fp0);
     }
 
-    /* return to getfile() cyrcle */
+    /* return to getfile() cycle */
     StrAllocCopy(newdoc->address, local_url);
     WWWDoc.address = newdoc->address;
     WWWDoc.post_data = newdoc->post_data;
@@ -1805,7 +1859,7 @@ PUBLIC int lynx_cfg_infopage ARGS1(
 #if defined(HAVE_CONFIG_H) && !defined(NO_CONFIG_INFO)
 /*
  *  Compile-time definitions info, LYNXCOMPILEOPTS:/ internal page,
- *  from getfile() cyrcle.
+ *  from getfile() cycle.
  */
 PUBLIC int lynx_compile_opts ARGS1(
     document *,		       newdoc)
@@ -1848,7 +1902,7 @@ PUBLIC int lynx_compile_opts ARGS1(
 	LYCloseTempFP(fp0);
     }
 
-    /* exit to getfile() cyrcle */
+    /* exit to getfile() cycle */
     StrAllocCopy(newdoc->address, info_url);
     WWWDoc.address = newdoc->address;
     WWWDoc.post_data = newdoc->post_data;
diff --git a/src/LYShowInfo.c b/src/LYShowInfo.c
index 81369a1e..e324623f 100644
--- a/src/LYShowInfo.c
+++ b/src/LYShowInfo.c
@@ -83,14 +83,15 @@ PUBLIC int showinfo ARGS4(
 		 (LYNX_RELEASE ? LYNX_WWW_HOME     : LYNX_WWW_DIST),
 		 (LYNX_RELEASE ? REL_VERSION       : DEV_VERSION) );
 
-    if (!LYRestricted) {
 #if defined(HAVE_CONFIG_H) && !defined(NO_CONFIG_INFO)
+    if (!no_compileopts_info) {
 	fprintf(fp0, " - <a href=\"LYNXCOMPILEOPTS:\">%s</a>\n",
 		COMPILE_OPT_SEGMENT);
-#else
+    } else
+#endif
+    if (!no_lynxcfg_info) {
 	fprintf(fp0, " - <a href=\"LYNXCFG:\">%s lynx.cfg</a>\n",
 		YOUR_SEGMENT);
-#endif
     }
     fprintf(fp0, "</h1>\n");  /* don't forget to close <h1> */
 
diff --git a/src/LYSignal.h b/src/LYSignal.h
index d8b1d106..e0d5ec0a 100644
--- a/src/LYSignal.h
+++ b/src/LYSignal.h
@@ -12,4 +12,12 @@ extern void VMSsignal PARAMS((int sig, void (*func)()));
 #define signal(a,b) VMSsignal(a,b) /* use LYCurses.c routines for interrupts */
 #endif /* VMS */
 
+#if HAVE_SIGACTION
+typedef void LYSigHandlerFunc_t PARAMS((int));
+/* implementation in LYUtils.c */
+extern void LYExtSignal PARAMS((int sig, LYSigHandlerFunc_t * handler));
+#else
+#define LYExtSignal(sig,h) signal(sig, h)
+#endif
+
 #endif /* LYSIGNAL_H */
diff --git a/src/LYStrings.c b/src/LYStrings.c
index 0b493dd7..4e736f4f 100644
--- a/src/LYStrings.c
+++ b/src/LYStrings.c
@@ -14,6 +14,7 @@
 #include <HTString.h>
 #include <LYCharUtils.h>
 #include <HTParse.h>
+#include <LYMainLoop.h>
 
 #ifdef DJGPP_KEYHANDLER
 #include <pc.h>
@@ -66,8 +67,9 @@ static MEVENT levent;
 PUBLIC int peek_mouse_levent NOARGS
 {
 #ifdef NCURSES_MOUSE_VERSION
-    if (have_levent) {
+    if (have_levent > 0) {
 	ungetmouse(&levent);
+	have_levent--;
 	return 1;
     }
 #endif
@@ -148,10 +150,22 @@ PUBLIC int fancy_mouse ARGS3(
 	    cur_selection += delta;
 	    cmd = LYX_TOGGLE;
 #endif
+	} else if (event.x <= getbegx(win) + 1 ||
+		   event.x >= getbegx(win) + getmaxx(win) - 2) {
+	    /* Click on left or right border for positioning without
+	     * immediate action: select, but do nothing else.
+	     * Actually, allow an error of one position inwards. - kw
+	     */
+	    *position += delta;
+	    cmd = -1;
 	} else if (event.bstate & (BUTTON_ALT | BUTTON_SHIFT | BUTTON_CTRL)) {
 	    /* Probably some unrelated activity, such as selecting some text.
 	     * Select, but do nothing else.
 	     */
+	    /* Possibly this is never returned by ncurses, so this case
+	     * may be useless depending on situation (kind of mouse support
+	     * and library versions). - kw
+	     */
 	    *position += delta;
 	    cmd = -1;
 	} else {
@@ -159,8 +173,9 @@ PUBLIC int fancy_mouse ARGS3(
 	    *position += delta;
 #if 0
 	    /* Immediate action looks reasonable since we have no help
-	     * available for individual options.  Moreover, one can position
-	     * active element with shift-click-1.  (;-)
+	     * available for individual options.  Moreover, one should be
+	     * able to position active element with <some modifier>-click-1
+	     * (but see remark above), or with click on left or right border.
 	     */
 	    if (!(event.bstate & (BUTTON1_DOUBLE_CLICKED
 				| BUTTON1_TRIPLE_CLICKED)))
@@ -200,10 +215,11 @@ PRIVATE int XYdist ARGS5(
 ** link.
 **/
 
-PRIVATE int set_clicked_link ARGS3(
+PRIVATE int set_clicked_link ARGS4(
     int,	x,
     int,	y,
-    int,	code)
+    int,	code,
+    int,	clicks)
 {
     int left = 6;
     int right = LYcols-6;
@@ -213,8 +229,8 @@ PRIVATE int set_clicked_link ARGS3(
 
     if (y == (LYlines-1)) {
 	mouse_link = -2;
-	if (x < left) c = LTARROW;
-	else if (x > right) c = '\b';
+	if (x < left)	    c = (code==FOR_PROMPT) ? LTARROW : LTARROW;
+	else if (x > right) c = (code==FOR_PROMPT) ? RTARROW : '\b';
 	else c = PGDOWN;
     } else if (y == 0) {
 	mouse_link = -2;
@@ -222,16 +238,18 @@ PRIVATE int set_clicked_link ARGS3(
 	else if (x > right) c = '\b';
 	else c = PGUP;
     } else {
-	int mouse_err = -1, cur_err;
+	int mouse_err = 3, /* must be closer than this for approx stuff */
+	    cur_err;
 
 	/* Loop over the links and see if we can get a match */
 	for (i = 0; i < nlinks; i++) {
 	    int len, lx = links[i].lx, is_text = 0;
 
 	    if (links[i].type == WWW_FORM_LINK_TYPE
-		/* XXXX What else? */
-		&& (links[i].form->type == F_TEXTAREA_TYPE
-		 || links[i].form->type == F_TEXT_TYPE))
+		&& (links[i].form->type == F_TEXT_TYPE
+		 || links[i].form->type == F_TEXT_SUBMIT_TYPE
+		 || links[i].form->type == F_PASSWORD_TYPE
+		 || links[i].form->type == F_TEXTAREA_TYPE))
 		is_text = 1;
 
 	    if (is_text)
@@ -246,6 +264,22 @@ PRIVATE int set_clicked_link ARGS3(
 		    int cury, curx;
 
 		    LYGetYX(cury,curx);
+		    /* double-click, if we care:
+		       submit text submit fields. - kw */
+		    if (clicks > 1 && is_text &&
+			links[i].form->type == F_TEXT_SUBMIT_TYPE) {
+			if (code != FOR_INPUT
+			    /* submit current input field directly */
+			    || !(cury == y && (curx >= lx) && ((curx - lx) <= len))) {
+			    c = LAC_TO_LKC0(LYK_SUBMIT);
+			    mouse_link = i;
+			} else {
+			    c = LAC_TO_LKC0(LYK_SUBMIT);
+			    mouse_link = -1;
+			}
+			mouse_err = 0;
+			break;
+		    }
 		    if (code != FOR_INPUT
 			/* Do not pick up the current input field */
 			|| !((cury == y && (curx >= lx) && ((curx - lx) <= len)))) {
@@ -283,9 +317,10 @@ PRIVATE int set_clicked_link ARGS3(
 	 * the Enter key).
 	 */
 	if (mouse_link >= 0) {
-	    if (mouse_err == 0)
-		c = lookup_keymap(LYK_ACTIVATE);
-	    else if (mouse_err >= 0)
+	    if (mouse_err == 0) {
+		if (c == -1)
+		    c = lookup_keymap(LYK_ACTIVATE);
+	    } else if (mouse_err >= 0)
 		c = lookup_keymap(LYK_CHANGE_LINK);
 	}
     }
@@ -293,20 +328,6 @@ PRIVATE int set_clicked_link ARGS3(
 }
 
 
-/*
- *  LYstrerror emulates the ANSI strerror() function.
- */
-#ifdef LYStrerror
-    /* defined as macro in .h file. */
-#else
-PUBLIC char *LYStrerror ARGS1(int, code)
-{
-    static char temp[80];
-    sprintf(temp, "System errno is %d.\r\n", code);
-    return temp;
-}
-#endif /* HAVE_STRERROR */
-
 
 /*
  *  LYstrncpy() terminates strings with a null byte.
@@ -522,12 +543,21 @@ PRIVATE int sl_parse_mouse_event ARGS3(int *, x, int *, y, int *, button)
 	return -1;
     }
 
-    *x = SLang_getkey () - 33;
-    *y = SLang_getkey () - 33;
+    *x = SLang_getkey ();
+    if (*x == CH_ESC)		/* Undo 7-bit replace for large x - kw */
+	*x = SLang_getkey () + 64 - 33;
+    else
+	*x -= 33;
+    *y = SLang_getkey ();
+    if (*y == CH_ESC)		/* Undo 7-bit replace for large y - kw */
+	*y = SLang_getkey () + 64 - 33;
+    else
+	*y -= 33;
     return 0;
 }
 
-PRIVATE int sl_read_mouse_event NOARGS
+PRIVATE int sl_read_mouse_event ARGS1(
+    int,	code)
 {
    int mouse_x, mouse_y, button;
 
@@ -535,7 +565,7 @@ PRIVATE int sl_read_mouse_event NOARGS
    if (-1 != sl_parse_mouse_event (&mouse_x, &mouse_y, &button))
      {
 	if (button == 0)  /* left */
-	  return set_clicked_link (mouse_x, mouse_y, FOR_PANEL);
+	  return set_clicked_link (mouse_x, mouse_y, FOR_PANEL, 1);
 
 	if (button == 2)   /* right */
 	  {
@@ -546,7 +576,10 @@ PRIVATE int sl_read_mouse_event NOARGS
 	     return LYReverseKeymap (LYK_PREV_DOC);
 	  }
      }
-   return -1;
+   if (code == FOR_INPUT || code == FOR_PROMPT)
+       return DO_NOTHING;
+   else
+       return -1;
 }
 #endif
 
@@ -566,7 +599,7 @@ PUBLIC void ena_csi ARGS1(
 	SLexpand_escaped_string(dst, first, last)
 static SLKeyMap_List_Type *Keymap_List;
 /* This value should be larger than anything in LYStrings.h */
-#define MOUSE_KEYSYM 0x1000
+#define MOUSE_KEYSYM 0x0400
 #endif
 
 
@@ -609,7 +642,7 @@ static Keysym_String_List Keysym_Strings [] =
     DEFINE_KEY( "SELECT_KEY",	SELECT_KEY,	KEY_SELECT ),
     DEFINE_KEY( "INSERT_KEY",	INSERT_KEY,	KEY_IC ),
     DEFINE_KEY( "REMOVE_KEY",	REMOVE_KEY,	KEY_DC ),
-    DEFINE_KEY( "DO_NOTHING",	DO_NOTHING,	0 ),
+    DEFINE_KEY( "DO_NOTHING",	DO_NOTHING,	DO_NOTHING|LKC_ISLKC ),
     DEFINE_KEY( NULL, 		-1,		ERR )
 };
 
@@ -763,17 +796,52 @@ PRIVATE BOOLEAN unescape_string ARGS2(char*, src, char *, dst)
     return ok;
 }
 
-PRIVATE int map_string_to_keysym ARGS2(char*, str, int*,keysym)
+PUBLIC int map_string_to_keysym ARGS2(char*, str, int*,keysym)
 {
+    int modifier = 0;
     *keysym = -1;
 
+    if (strncasecomp(str, "LAC:", 4) == 0) {
+	*keysym = lacname_to_lac(str + 4);
+	if (*keysym >= 0) {
+	    *keysym = LAC_TO_LKC0(*keysym);
+	    return (*keysym);
+	}
+    }
+    if (strncasecomp(str, "Meta-", 5) == 0) {
+	str += 5;
+	modifier = LKC_MOD2;
+	if (*str) {
+	    size_t len = strlen(str);
+	    if (len == 1)
+		return (*keysym = ((unsigned char)str[0])|modifier);
+	    else if (len == 2 && str[0] == '^' &&
+		     (isalpha(str[1]) ||
+		      (TOASCII(str[1]) >= '@' && TOASCII(str[1]) <= '_')))
+		return (*keysym = FROMASCII((unsigned char)str[1]&0x1f)|modifier);
+	    else if (len == 2 && str[0] == '^' &&
+		     str[1] == '?')
+		return (*keysym = CH_DEL|modifier);
+	    if (*str == '^' || *str == '\\') {
+		char buf[BUFSIZ];
+		expand_substring(buf, str, str + HTMIN(len, 28));
+		if (strlen(buf) <= 1)
+		    return (*keysym = ((unsigned char)buf[0])|modifier);
+	    }
+	}
+    }
     if (*str == SQUOTE) {
 	unescaped_char(str, keysym);
     } else if (isdigit(*str)) {
 	char *tmp;
 	long value = strtol(str, &tmp, 0);
-	if (!isalnum(*tmp))
+	if (!isalnum(*tmp)) {
 	    *keysym = value;
+#ifndef USE_SLANG
+	    if (*keysym > 255)
+		*keysym |= LKC_ISLKC; /* caller should remove this flag - kw */
+#endif	    
+	}
     } else {
 	Keysym_String_List *k;
 
@@ -787,6 +855,8 @@ PRIVATE int map_string_to_keysym ARGS2(char*, str, int*,keysym)
 	}
     }
 
+    if (*keysym >= 0)
+	*keysym |= modifier;
     return (*keysym);
 }
 
@@ -996,7 +1066,7 @@ PUBLIC int lynx_initialize_keymaps NOARGS
 #endif				       /* USE_KEYMAPS */
 
 #ifdef NCURSES_MOUSE_VERSION
-PRIVATE int LYmouse_menu ARGS3(int, x, int, y, int, atlink)
+PRIVATE int LYmouse_menu ARGS4(int, x, int, y, int, atlink, int, code)
 {
     static char *choices[] = {
 	"Quit",
@@ -1059,59 +1129,123 @@ PRIVATE int LYmouse_menu ARGS3(int, x, int, y, int, atlink)
     };
     static int actions_link[] = {
 	LYK_HELP,
-	LYK_REFRESH,
-	LYK_ACTIVATE,
+	LYK_DO_NOTHING,
+	LYK_SUBMIT,
 	LYK_INFO,
 	LYK_DOWNLOAD
     };
-    int c;
+    int c, retlac;
 
     /* Somehow the mouse is over the number instead of being over the
        name, so we decrease x. */
-    c = popup_choice((atlink ? 2 : 9) - 1, y, (x >= 5 ? x-5 : 0),
+    c = popup_choice((atlink ? 2 : 10) - 1, y, (x > 5 ? x-5 : 1),
 		     (atlink ? choices_link : choices),
 		     (atlink
 		      ? (sizeof(actions_link)/sizeof(int))
-		      : (sizeof(actions)/sizeof(int))), FALSE);
+		      : (sizeof(actions)/sizeof(int))), FALSE, TRUE);
+
+    /*
+     *  popup_choice() in LYOptions.c wasn't really meant to be used
+     *  outside of old-style Options menu processing.  One result of
+     *  mis-using it here is that we have to deal with side-effects
+     *  regarding SIGINT signal handler and the term_options global
+     *  variable. - kw
+     */
+    if (term_options) {
+	retlac = LYK_DO_NOTHING;
+	term_options = FALSE;
+    } else {
+	retlac = atlink ? (actions_link[c]) : (actions[c]);
+    }
 
-    return atlink ? (actions_link[c]) : (actions[c]);
+    if (code == FOR_INPUT && mouse_link == -1) {
+	switch (retlac) {
+	    case LYK_ABORT:
+		retlac = LYK_QUIT; /* a bit softer... */
+		/* fall through */
+	    case LYK_MAIN_MENU:
+	    case LYK_PREV_DOC:
+	    case LYK_HOME:
+	    case LYK_PREV_PAGE:
+	    case LYK_UP_HALF:
+	    case LYK_UP_TWO:
+	    case LYK_HISTORY:
+	    case LYK_HELP:
+/*	    case LYK_REFRESH:*/
+	    case LYK_RELOAD:
+	    case LYK_ECGOTO:
+	    case LYK_INFO:
+	    case LYK_WHEREIS:
+	    case LYK_PRINT:
+	    case LYK_DOWN_TWO:
+	    case LYK_DOWN_HALF:
+	    case LYK_NEXT_PAGE:
+	    case LYK_END:
+	    case LYK_VIEW_BOOKMARK:
+ 	    case LYK_COOKIE_JAR:
+	    case LYK_INDEX_SEARCH:
+	    case LYK_OPTIONS:
+		mouse_link = -3; /* so LYgetch_for() passes it on - kw */
+	}
+    }
+    if (retlac == LYK_DO_NOTHING ||
+	retlac == LYK_REFRESH) {
+	mouse_link = -1;	/* mainloop should not change cur link - kw */
+    }
+    if (code == FOR_INPUT && retlac == LYK_DO_NOTHING) {
+	repaint_main_statusline();
+    }
+    return retlac;
 }
 #endif
 
 #if defined(USE_KEYMAPS) && defined(USE_SLANG)
 
+PRIVATE int current_sl_modifier = 0;
+
 /* We cannot guarantee the type for 'GetChar', and should not use a cast. */
 PRIVATE int myGetChar NOARGS
 {
-   return GetChar();
+    int i = GetChar();
+    if (i == 0)			/* trick to get NUL char through - kw */
+	current_sl_modifier = LKC_ISLKC;
+    return i;
 }
 
-PUBLIC int LYgetch NOARGS
+PUBLIC int LYgetch_for ARGS1(
+	int, 	code)
 {
    SLang_Key_Type *key;
    int keysym;
+   current_sl_modifier = 0;
 
    key = SLang_do_key (Keymap_List, myGetChar);
    if ((key == NULL) || (key->type != SLKEY_F_KEYSYM))
-     return DO_NOTHING;
+     return (current_sl_modifier ? 0 : DO_NOTHING);
 
    keysym = key->f.keysym;
 
 #if defined (USE_SLANG_MOUSE)
    if (keysym == MOUSE_KEYSYM)
-     return sl_read_mouse_event ();
+     return sl_read_mouse_event (code);
 #endif
 
-   if ((keysym+1 >= KEYMAP_SIZE) || (keysym < 0))
-     return 0;
+   if (keysym < 0)
+       return 0;
 
-   return keysym;
-}
+   if (keysym&LKC_ISLAC)
+       return (keysym);
 
-PUBLIC int LYgetch_for ARGS1(
-	int, 	code)
-{
-    return LYgetch();
+   current_sl_modifier = 0;
+   if (LKC_HAS_ESC_MOD(keysym)) {
+       current_sl_modifier = LKC_MOD2;
+       keysym &= LKC_MASK;
+   }
+
+   if (keysym+1 >= KEYMAP_SIZE)
+     return 0;
+
+   return (keysym|current_sl_modifier);
 }
 
 #else	/* NOT  defined(USE_KEYMAPS) && defined(USE_SLANG) */
@@ -1121,21 +1255,24 @@ PUBLIC int LYgetch_for ARGS1(
  */
 #define found_CSI(first,second) ((second) == '[' || (first) == 155)
 
-PUBLIC int LYgetch NOARGS
-{
-    return LYgetch_for(FOR_PANEL);
-}
-
 PUBLIC int LYgetch_for ARGS1(
 	int, 	code)
 {
     int a, b, c, d = -1;
+    int current_modifier = 0;
+    BOOLEAN done_esc = FALSE;
 
     have_levent = 0;
 
-#if defined(IGNORE_CTRL_C) || defined(USE_GETCHAR) || !defined(NCURSES)
+#if defined(IGNORE_CTRL_C) || defined(USE_GETCHAR) || !defined(NCURSES) || \
+    (HAVE_KEYPAD && defined(KEY_RESIZE)) || \
+    (defined(NCURSES_MOUSE_VERSION) && !defined(DOSPATH))
 re_read:
-#endif /* IGNORE_CTRL_C || USE_GETCHAR */
+#endif /* IGNORE_CTRL_C || USE_GETCHAR etc. */
+#if !defined(UCX) || !defined(VAXC) /* errno not modifiable ? */
+    if (errno == EINTR)
+	errno = 0;		/* reset - kw */
+#endif  /* UCX && VAXC */
 #ifndef USE_SLANG
     clearerr(stdin); /* needed here for ultrix and SOCKETSHR, but why? - FM */
 #endif /* !USE_SLANG */
@@ -1161,6 +1298,25 @@ re_read:
 #ifdef USE_GETCHAR
     if (c == EOF && errno == EINTR)	/* Ctrl-Z causes EINTR in getchar() */
 	goto re_read;
+#else
+    if (c == EOF && errno == EINTR) {
+
+#if HAVE_SIZECHANGE || defined(USE_SLANG)
+	   CTRACE(tfp, "Got EOF with EINTR, recent_sizechange so far is %d\n",
+		  recent_sizechange);
+	   if (!recent_sizechange) { /* not yet detected by ourselves */
+	       size_change(0);
+	       CTRACE(tfp, "Now recent_sizechange is %d\n", recent_sizechange);
+	   }
+#else /* HAVE_SIZECHANGE || USE_SLANG */
+	   CTRACE(tfp, "Got EOF with EINTR, recent_sizechange is %d\n",
+		  recent_sizechange);
+#endif /* HAVE_SIZECHANGE || USE_SLANG */
+#if !defined(UCX) || !defined(VAXC) /* errno not modifiable ? */
+	errno = 0;		/* reset - kw */
+#endif  /* UCX && VAXC */
+	return(DO_NOTHING);
+    }
 #endif /* USE_GETCHAR */
 
 #ifdef USE_SLANG
@@ -1173,7 +1329,7 @@ re_read:
 #endif /* IGNORE_CTRL_C */
 	return(7); /* use ^G to cancel whatever called us. */
     }
-#else
+#else  /* not USE_SLANG: */
     if (feof(stdin) || ferror(stdin) || c == EOF) {
 	if (recent_sizechange)
 	    return(7); /* use ^G to cancel whatever called us. */
@@ -1195,6 +1351,7 @@ re_read:
 #endif /* USE_SLANG */
 
     if (c == CH_ESC || (csi_is_csi && c == (unsigned char)CH_ESC_PAR)) { /* handle escape sequence  S/390 -- gil -- 2024 */
+	done_esc = TRUE;		/* Flag: we did it, not keypad() */
 	b = GetChar();
 
 	if (b == '[' || b == 'O') {
@@ -1220,7 +1377,7 @@ re_read:
 #ifdef USE_SLANG_MOUSE
 	   if (found_CSI(c,b))
 	     {
-		c = sl_read_mouse_event ();
+		c = sl_read_mouse_event (code);
 	     }
 	   else
 #endif
@@ -1236,6 +1393,8 @@ re_read:
 	case 'k':
 	    if (b == 'O')
 		c = '+';  /* keypad + on my xterminal :) */
+	    else
+		done_esc = FALSE; /* we have another look below - kw */
 	    break;
 	case 'l':
 #ifdef VMS
@@ -1264,6 +1423,8 @@ re_read:
 	case '1':			    /** VTxxx  Find  **/
 	    if (found_CSI(c,b) && (d=GetChar()) == '~')
 		c = FIND_KEY;
+	    else
+		done_esc = FALSE; /* we have another look below - kw */
 	    break;
 	case '2':
 	    if (found_CSI(c,b)) {
@@ -1280,22 +1441,32 @@ re_read:
 		    d = -1;
 		 }
 	    }
+	    else
+		done_esc = FALSE; /* we have another look below - kw */
 	    break;
 	case '3':			     /** VTxxx Delete **/
 	    if (found_CSI(c,b) && (d=GetChar()) == '~')
 		c = REMOVE_KEY;
+	    else
+		done_esc = FALSE; /* we have another look below - kw */
 	    break;
 	case '4':			     /** VTxxx Select **/
 	    if (found_CSI(c,b) && (d=GetChar()) == '~')
 		c = SELECT_KEY;
+	    else
+		done_esc = FALSE; /* we have another look below - kw */
 	    break;
 	case '5':			     /** VTxxx PrevScreen **/
 	    if (found_CSI(c,b) && (d=GetChar()) == '~')
 		c = PGUP;
+	    else
+		done_esc = FALSE; /* we have another look below - kw */
 	    break;
 	case '6':			     /** VTxxx NextScreen **/
 	    if (found_CSI(c,b) && (d=GetChar()) == '~')
 		c = PGDOWN;
+	    else
+		done_esc = FALSE; /* we have another look below - kw */
 	    break;
 	case '[':			     /** Linux F1-F5: ^[[[A etc. **/
 	    if (found_CSI(c,b)) {
@@ -1304,12 +1475,41 @@ re_read:
 		break;
 	    }
 	default:
+	    if (c == CH_ESC && a == b && !found_CSI(c,b)) {
+		current_modifier = LKC_MOD2;
+		c = a;
+		/* We're not yet done if ESC + curses-keysym: */
+		done_esc = ((a & ~0xFF) == 0);
+		break;
+	    }
 	    CTRACE(tfp,"Unknown key sequence: %d:%d:%d\n",c,b,a);
 	    CTRACE_SLEEP(MessageSecs);
 	    break;
 	}
 	if (isdigit(a) && found_CSI(c,b) && d != -1 && d != '~')
 	    d = GetChar();
+	if (!done_esc && (a & ~0xFF) == 0) {
+	    if (a == b && !found_CSI(c,b) && c == CH_ESC) {
+		current_modifier = LKC_MOD2;
+		c = a;
+		done_esc = TRUE;
+	    } else {
+		done_esc = TRUE;
+	    }
+	}
+    }
+#ifdef USE_KEYMAPS
+    if (c >= 0 && (c&LKC_ISLKC)) {
+	c &= ~LKC_ISLKC;
+	done_esc = TRUE; /* already a lynxkeycode, skip keypad switches - kw */
+    }
+    if (c >= 0 && LKC_HAS_ESC_MOD(c)) {
+	current_modifier = LKC_MOD2;
+	c &= LKC_MASK;
+    }
+#endif
+    if (done_esc) {
+	/* don't do keypad() switches below, we already got it - kw */
     }
 #if HAVE_KEYPAD
     else {
@@ -1426,6 +1626,43 @@ re_read:
 	   c = BACKTAB_KEY;	   /* Back tab, often Shift-Tab */
 	   break;
 #endif /* KEY_BTAB */
+#ifdef KEY_RESIZE
+	case KEY_RESIZE:	   /* size change detected by ncurses */
+#if HAVE_SIZECHANGE || defined(USE_SLANG)
+	   /* Make call to detect new size, if that may be implemented.
+	    * The call may set recent_sizechange (except for USE_SLANG),
+	    * which will tell mainloop() to refresh. - kw */
+	   CTRACE(tfp, "Got KEY_RESIZE, recent_sizechange so far is %d\n",
+		  recent_sizechange);
+	   size_change(0);
+	   CTRACE(tfp, "Now recent_sizechange is %d\n", recent_sizechange);
+#else /* HAVE_SIZECHANGE || USE_SLANG */
+	   CTRACE(tfp, "Got KEY_RESIZE, recent_sizechange is %d\n",
+		  recent_sizechange);
+#endif /* HAVE_SIZECHANGE || USE_SLANG */
+	   if (!recent_sizechange) {
+#if 0			/* assumption seems flawed? */
+	       /*  Not detected by us or already processed by us.  It can
+		*  happens that ncurses lags behind us in detecting the
+		*  change, since its own SIGTSTP handler is not installed
+		*  so detecting happened *at the end* of the last refresh.
+		*  Tell it to refresh again... - kw */
+	       refresh();
+#endif
+	       /*
+		*  May be just the delayed effect of mainloop()'s call
+		*  to resizeterm().  Pretend we haven't read anything
+		*  yet, don't return. - kw
+		*/
+	       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;
+#endif /* KEY_RESIZE */
 
 /* The following maps PDCurses keys away from lynx reserved values */
 #if (defined(_WINDOWS) || defined(__DJGPP__)) && !defined(USE_SLANG)
@@ -1452,46 +1689,71 @@ re_read:
 	case KEY_MOUSE:
 	    if (code == FOR_CHOICE) {
 		c = MOUSE_KEY;		/* Will be processed by the caller */
+	    } else if (code == FOR_SINGLEKEY) {
+		MEVENT event;
+		getmouse(&event);	/* Completely ignore event - kw */
+		c = DO_NOTHING;
 	    } else {
 #ifndef DOSPATH
 		MEVENT event;
 		int err;
+		int lac = LYK_UNKNOWN;
 
 		c = -1;
 		mouse_link = -1;
 		err = getmouse(&event);
+		if (err != OK) {
+		    CTRACE(tfp, "Mouse error: no event available!\n");
+		    return(code==FOR_PANEL ? 0 : DO_NOTHING);
+		}
 		levent = event;		/* Allow setting pos in entry fields */
 		if (event.bstate & BUTTON1_CLICKED) {
-		    c = set_clicked_link(event.x, event.y, code);
+		    c = set_clicked_link(event.x, event.y, code, 1);
 		} else if (event.bstate & BUTTON1_DOUBLE_CLICKED) {
-		    c = set_clicked_link(event.x, event.y, code);
+		    c = set_clicked_link(event.x, event.y, code, 2);
 		    if (c == PGDOWN)
 			c = END_KEY;
 		    else if (c == PGUP)
 			c = HOME;
+		    else if (c == RTARROW)
+			c = END_KEY;
+		    else if (c == LTARROW && code == FOR_PROMPT)
+			c = HOME;
 		    else if (c == LTARROW)
 			c = LYReverseKeymap(LYK_MAIN_MENU);
+		    else if (c == '\b' && (code == FOR_PANEL || code == FOR_INPUT))
+			c = LAC_TO_LKC0(LYK_VLINKS);
+		    else if (c == LAC_TO_LKC0(LYK_SUBMIT) && code == FOR_INPUT)
+			lac = LYK_SUBMIT;
 		} else if (event.bstate & BUTTON3_CLICKED) {
-		    c = LYReverseKeymap (LYK_PREV_DOC);
+		    c = LAC_TO_LKC0(LYK_PREV_DOC);
+		} else if (code == FOR_PROMPT) {
+		    /* Completely ignore - don't return anything, to
+		       avoid canceling the prompt - kw */
+		    goto re_read;
 		} else if (event.bstate & BUTTON2_CLICKED) {
 		    int atlink;
 
-		    c = set_clicked_link(event.x, event.y, code);
-		    atlink = c == LYReverseKeymap (LYK_ACTIVATE);
+		    c = set_clicked_link(event.x, event.y, code, 1);
+		    atlink = (c == LYReverseKeymap(LYK_ACTIVATE));
 		    if (!atlink)
 			mouse_link = -1; /* Forget about approx stuff. */
 
-		    c = LYmouse_menu(event.x, event.y, atlink);
-		    if (c == LYK_ACTIVATE && mouse_link == -1) {
+		    lac = LYmouse_menu(event.x, event.y, atlink, code);
+		    if (lac == LYK_SUBMIT && mouse_link == -1)
+			lac = LYK_ACTIVATE;
+		    if (lac == LYK_ACTIVATE && mouse_link == -1) {
 			HTAlert("No link chosen");
-			c = LYK_DO_NOTHING;
-			c = LYK_REFRESH; /* refresh() below does not work... */
+			lac = LYK_REFRESH;
 		    }
-		    c = LYReverseKeymap(c);
+		    c = LAC_TO_LKC(lac);
+#if 0	/* Probably not necessary any more - kw */
 		    lynx_force_repaint();
 		    refresh();
+#endif
 		}
-		if (code == FOR_INPUT && mouse_link == -1) {
+		if (code == FOR_INPUT && mouse_link == -1 &&
+		    lac != LYK_REFRESH && lac != LYK_SUBMIT) {
 		    ungetmouse(&event);	/* Caller will process this. */
 		    getch();		/* ungetmouse puts KEY_MOUSE back */
 		    c = MOUSE_KEY;
@@ -1501,11 +1763,15 @@ re_read:
 		mouse_link = -1;
 		request_mouse_pos();
 		if (BUTTON_STATUS(1) & BUTTON_CLICKED) {
-		    c = set_clicked_link(MOUSE_X_POS, MOUSE_Y_POS, FOR_PANEL);
+		    c = set_clicked_link(MOUSE_X_POS, MOUSE_Y_POS,FOR_PANEL,1);
 		} else if (BUTTON_STATUS(3) & BUTTON_CLICKED) {
-		    c = LYReverseKeymap (LYK_PREV_DOC);
+		    c = LAC_TO_LKC(LYK_PREV_DOC);
 		}
 #endif /* DOSPATH */
+/*		if (c < 0)
+		    c = 0; */
+		if ((c+1) >= KEYMAP_SIZE && (c&LKC_ISLAC))
+		    return(c);
 	    }
 	    break;
 #endif /* NCURSES_MOUSE_VERSION */
@@ -1625,12 +1891,17 @@ re_read:
 	 */
 	return (0);
     } else {
-	return(c);
+	return(c|current_modifier);
     }
 }
 
 #endif	/* NOT  defined(USE_KEYMAPS) && defined(USE_SLANG) */
 
+PUBLIC int LYgetch NOARGS
+{
+    return LYgetch_for(FOR_PANEL);
+}
+
 /*
  * Convert a null-terminated string to lowercase
  */
@@ -1774,6 +2045,13 @@ PUBLIC BOOLEAN LYTrimStartfile ARGS1(
 #define DspWdth  edit->dspwdth
 #define DspStart edit->xpan
 #define Margin	 edit->margin
+#ifdef ENHANCED_LINEEDIT
+#define Mark	 edit->mark
+#endif
+
+#ifdef ENHANCED_LINEEDIT
+PRIVATE char killbuffer[1024] = "\0";
+#endif
 
 PUBLIC void LYSetupEdit ARGS4(
 	EDREC *,	edit,
@@ -1788,12 +2066,16 @@ PUBLIC void LYSetupEdit ARGS4(
     edit->pad	= ' ';
     edit->dirty = TRUE;
     edit->panon = FALSE;
+    edit->current_modifiers = 0;
 
     StrLen  = strlen(old);
     MaxLen  = maxstr;
     DspWdth = maxdsp;
     Margin  = 0;
     Pos = strlen(old);
+#ifdef ENHANCED_LINEEDIT
+    Mark = 0;
+#endif
     DspStart = 0;
 
     if (maxstr > maxdsp) {  /* Need panning? */
@@ -1874,9 +2156,42 @@ PUBLIC int LYEdit1 ARGS4(
 		current_char_set);
 #endif
 	/*
-	 *  ch is printable or ISO-8859-1 escape character.
+	 *  ch is (presumably) printable character.
 	 */
 	if (Pos <= (MaxLen) && StrLen < (MaxLen)) {
+#ifdef ENHANCED_LINEEDIT
+	    if (Mark > Pos)
+		Mark++;
+#endif
+	    for(i = length; i >= Pos; i--)    /* Make room */
+		Buf[i+1] = Buf[i];
+	    Buf[length+1]='\0';
+	    Buf[Pos] = (unsigned char) ch;
+	    Pos++;
+	} else if (maxMessage) {
+	    _statusline(MAXLEN_REACHED_DEL_OR_MOV);
+	}
+	break;
+
+    case LYE_C1CHAR:
+	/*
+	 *  ch is the second part (in most cases, a capital letter) of
+	 *  a 7-bit replacement for a character in the 8-bit C1 control
+	 *  range.
+	 *  This is meant to undo transformations like
+	 *  0x81 -> 0x1b 0x41 (ESC A) etc. done by slang on Unix and
+	 *  possibly some comm programs.  It's an imperfect workaround
+	 *  that doesn't work for all such characters.
+	 */
+	ch &= 0xFF;
+	if (ch + 64 >= LYlowest_eightbit[current_char_set])
+	    ch += 64;
+	
+	if (Pos <= (MaxLen) && StrLen < (MaxLen)) {
+#ifdef ENHANCED_LINEEDIT
+	    if (Mark > Pos)
+		Mark++;
+#endif
 	    for(i = length; i >= Pos; i--)    /* Make room */
 		Buf[i+1] = Buf[i];
 	    Buf[length+1]='\0';
@@ -1913,6 +2228,9 @@ PUBLIC int LYEdit1 ARGS4(
 	 *  Erase the line to start fresh.
 	 */
 	 Buf[0] = '\0';
+#ifdef ENHANCED_LINEEDIT
+	Mark = 0;
+#endif
 	 /* fall through */
 
     case LYE_BOL:
@@ -1994,6 +2312,10 @@ PUBLIC int LYEdit1 ARGS4(
 	 */
 	if (length == 0 || Pos == 0)
 	    break;
+#ifdef ENHANCED_LINEEDIT
+	if (Mark >= Pos)
+	    Mark--;
+#endif
 	Pos--;
 	for (i = Pos; i < length; i++)
 	    Buf[i] = Buf[i+1];
@@ -2017,6 +2339,90 @@ PUBLIC int LYEdit1 ARGS4(
 	    Pos--;
 	break;
 
+#ifdef ENHANCED_LINEEDIT
+    case LYE_TPOS:
+	/*
+	 *  Transpose characters - bash or ksh(emacs not gmacs) style
+	 */
+	if (length <= 1 || Pos == 0)
+	    return(ch);
+	if (Pos == length)
+	    Pos--;
+	if (Mark == Pos || Mark == Pos+1)
+	    Mark = Pos-1;
+	if (Buf[Pos-1] == Buf[Pos]) {
+	    Pos++;
+	    return(0);
+	}
+	i = Buf[Pos-1]; Buf[Pos-1] = Buf[Pos]; Buf[Pos++] = i;
+	break;
+
+    case LYE_SETMARK:
+	/*
+	 *  primitive emacs-like set-mark-command
+	 */
+	Mark = Pos;
+	return(0);
+
+    case LYE_XPMARK:
+	/*
+	 *  emacs-like exchange-point-and-mark
+	 */
+	if (Mark == Pos)
+	    return(0);
+	i = Pos; Pos = Mark; Mark = i;
+	break;
+
+    case LYE_KILLREG:
+	/*
+	 *  primitive emacs-like kill-region
+	 */
+	if (Mark == Pos) {
+	    killbuffer[0] = '\0';
+	    return(0);
+	}
+	if (Mark > Pos)
+	    LYEdit1(edit, 0, LYE_XPMARK, FALSE);
+	{
+	    int reglen = Pos - Mark;
+
+	    LYstrncpy(killbuffer, &Buf[Mark],
+		      HTMIN(reglen, (int)sizeof(killbuffer)-1));
+	    for (i = Mark; Buf[i+reglen]; i++)
+		Buf[i] = Buf[i+reglen];
+	    Buf[i] = Buf[i+reglen]; /* terminate */
+	    Pos = Mark;
+	}
+	break;
+
+    case LYE_YANK:
+	/*
+	 *  primitive emacs-like yank
+	 */
+	if (!killbuffer[0]) {
+	    Mark = Pos;
+	    return(0);
+	}
+	{
+	    int yanklen = strlen(killbuffer);
+
+	    if (Pos+yanklen <= (MaxLen) && StrLen+yanklen <= (MaxLen)) {
+		Mark = Pos;
+
+		for(i = length; i >= Pos; i--)    /* Make room */
+		    Buf[i+yanklen] = Buf[i];
+		Buf[length+1]='\0';
+		for (i = 0; i < yanklen; i++)
+		    Buf[Pos++] = (unsigned char) killbuffer[i];
+
+	    } else if (maxMessage) {
+		_statusline(MAXLEN_REACHED_DEL_OR_MOV);
+	    }
+	}
+	break;
+
+#endif /* ENHANCED_LINEEDIT */
+
     case LYE_UPPER:
 	LYUpperCase(Buf);
 	break;
@@ -2147,6 +2553,7 @@ PUBLIC void LYRefreshEdit ARGS1(
     refresh();
 }
 
+#define CurModif MyEdit.current_modifiers
 
 PUBLIC int LYgetstr ARGS4(
 	char *, 	inputline,
@@ -2156,6 +2563,8 @@ PUBLIC int LYgetstr ARGS4(
 {
     int x, y, MaxStringSize;
     int ch;
+    int xlec;
+    int last_xlkc = -1;
     EditFieldData MyEdit;
     char *res;
 
@@ -2168,13 +2577,13 @@ PUBLIC int LYgetstr ARGS4(
     for (;;) {
 again:
 	LYRefreshEdit(&MyEdit);
-	ch = LYgetch();
+	ch = LYgetch_for(FOR_PROMPT);
 #ifdef VMS
 	if (term_letter || term_options ||
 #ifndef DISABLE_NEWS
-	      term_message
+	      term_message ||
 #endif
-	      || HadVMSInterrupt) {
+	      HadVMSInterrupt) {
 	    HadVMSInterrupt = FALSE;
 	    ch = 7;
 	}
@@ -2191,9 +2600,35 @@ again:
 	    LYAddToCloset(MyEdit.buffer);
 	    return(ch);
 	}
-	if (keymap[ch + 1] == LYK_REFRESH)
+	ch |= CurModif;
+	CurModif = 0;
+	if (last_xlkc != -1) {
+	    if (ch == last_xlkc)
+		ch |= LKC_MOD3;
+	    last_xlkc = -1;	/* consumed */
+	}
+	if (LKC_TO_LAC(keymap,ch) == LYK_REFRESH)
 	    goto again;
-	switch (EditBinding(ch)) {
+	xlec = EditBinding(ch);
+	if ((xlec & LYE_DF) && !(xlec & LYE_FORM_LAC)) {
+	    last_xlkc = ch;
+	    xlec &= ~LYE_DF;
+	} else {
+	    last_xlkc = -1;
+	}
+	switch (xlec) {
+	case LYE_SETM1:
+	    /*
+	     *  Set flag for modifier 1.
+	     */
+	    CurModif |= LKC_MOD1;
+	    break;
+	case LYE_SETM2:
+	    /*
+	     *  Set flag for modifier 2.
+	     */
+	    CurModif |= LKC_MOD2;
+	    break;
 	case LYE_TAB:
 	    ch = '\t';
 	    /* This used to fall through to the next case before
@@ -2254,11 +2689,42 @@ again:
 	    break;
 
 	default:
+	    if (xlec & LYE_FORM_LAC) {
+		/*
+		 *	Used in form_getstr() to end line editing and
+		 *	pass on the lynxkeycode already containing a
+		 *	lynxactioncode.  Here it is just ignored. - kw
+		 */
+		break;
+	    }
+
 	    LYLineEdit(&MyEdit, ch, FALSE);
 	}
     }
 }
 
+PUBLIC CONST char * LYLineeditHelpURL NOARGS
+{
+    static int lasthelp_lineedit = -1;
+    static char helpbuf[LY_MAXPATH] = "\0";
+    static char *phelp = &helpbuf[0];
+    if (lasthelp_lineedit == current_lineedit)
+	return &helpbuf[0];
+    if (lasthelp_lineedit == -1) {
+	LYstrncpy(helpbuf, helpfilepath, sizeof(helpbuf) - 1);
+	phelp += strlen(helpbuf);
+    }
+    if (LYLineeditHelpURLs[current_lineedit] &&
+	strlen(LYLineeditHelpURLs[current_lineedit]) &&
+	(strlen(LYLineeditHelpURLs[current_lineedit]) <=
+	 sizeof(helpbuf) - (phelp - helpbuf))) {
+	LYstrncpy(phelp, LYLineeditHelpURLs[current_lineedit],
+		  sizeof(helpbuf) - (phelp - helpbuf) - 1);
+	lasthelp_lineedit = current_lineedit;
+	return (&helpbuf[0]);
+    }
+    return NULL;
+}
 /*
  *  A replacement for 'strsep()'
  */
@@ -2968,8 +3434,14 @@ PUBLIC char *LYSafeGets ARGS2(
 	if (strchr(buffer, '\n') != 0)
 	    break;
     }
-    if (feof(fp)
-     || ferror(fp)) {
+    if (ferror(fp)) {
+	FREE(result);
+    } else if (feof(fp) && result && *result == '\0') {
+	/*
+	 *  If the file ends in the middle of a line, return the
+	 *  partial line; if another call is made after this, it
+	 *  will return NULL. - kw
+	 */
 	FREE(result);
     }
     if (src != 0)
diff --git a/src/LYStrings.h b/src/LYStrings.h
index d3f4b582..4333b760 100644
--- a/src/LYStrings.h
+++ b/src/LYStrings.h
@@ -13,13 +13,6 @@ extern int peek_mouse_link NOPARAMS;
 extern int peek_mouse_levent NOPARAMS;
 extern int fancy_mouse PARAMS((WINDOW *win, int row, int *position));
 
-#ifdef HAVE_STRERROR
-#define LYStrerror strerror
-#else
-extern char *LYStrerror PARAMS((
-	int		code));
-#endif /* HAVE_STRERROR */
-
 extern char * LYstrncpy PARAMS((
 	char *		dst,
 	CONST char *	src,
@@ -85,6 +78,10 @@ extern char * SNACat PARAMS((
 extern char *LYSafeGets PARAMS((char ** src, FILE * fp));
 
 /* values for LYgetch */
+/* The following are lynxkeycodes, not to be confused with
+   lynxactioncodes (LYK_*) to which they are often mapped.
+   The lynxkeycodes include all single-byte keys as a subset. - kw
+*/
 #define UPARROW		256	/* 0x100 */
 #define DNARROW		257	/* 0x101 */
 #define RTARROW		258	/* 0x102 */
@@ -102,25 +99,54 @@ extern char *LYSafeGets PARAMS((char ** src, FILE * fp));
 #define DO_NOTHING	270	/* 0x10E */
 #define BACKTAB_KEY	271	/* 0x10F */
 #define MOUSE_KEY	0x11d	/* 0x11D */
-/*  *** NOTE: ***
+/*  ***** NOTES: *****
     If you add definitions for new lynxkeycodes to the above list that
     need to be mapped to LYK_* lynxactioncodes -
     - AT LEAST the tables keymap[] and key_override[] in LYKeymap.c
       have to be changed/reviewed, AS WELL AS the lineedit binding
       tables in LYEditmap.c !
     - KEYMAP_SIZE, defined in LYKeymap.h, may need to be changed !
+    - See also table funckey[] in LYKeymap.c for 'pretty' strings
+      for the keys with codes >= 256 (to appear on the 'K'eymap page).
+      New keycodes should probably be assigned consecutively, so their
+      key names can be easily added to funckey[] (but see next point).
+      They should also be documented in lynx.cfg.
+    - The DOS port uses its own native codes for some keys, unless
+      they are remapped by the code in LYgetch().  See *.key files
+      in docs/ directory.  Adding new keys here may conflict with
+      those codes (affecting DOS users), unless/until remapping is
+      added or changed in LYgetch().
+      (N)curses keypad codes (KEY_* from curses.h) can also directly
+      appear as lynxkeycodes and conflict with our assignments, although
+      that shouldn't happen - the useful ones should be recognized in
+      LYgetch().
+    - The actual recognition of raw input keys or escape sequences, and
+      mapping to our lynxkeycodes, take place in LYgetch() and/or its
+      subsidiary functions and/or the curses/slang/etc. libraries.
+    The basic lynxkeycodes can appear combined with various flags in
+    higher-order bits as extended lynxkeycodes; see macros in LYKeymap.h.
+    The range of possible basic values is therefore limited, they have
+    to be less than LKC_ISLKC (even if KEYMAP_SIZE is increased).
 */
 
 
-#  define FOR_PANEL	0
-#  define FOR_CHOICE	1
-#  define FOR_INPUT	2
+#  define FOR_PANEL	0	/* normal screen, also LYgetch default */
+#  define FOR_CHOICE	1	/* mouse menu */
+#  define FOR_INPUT	2	/* form input and textarea field */
+#  define FOR_PROMPT	3	/* string prompt editing */
+#  define FOR_SINGLEKEY	4	/* single key prompt, confirmation */
 
 #define VISIBLE  0
 #define HIDDEN   1
 #define NORECALL 0
 #define RECALL   1
 
+#ifdef EXP_ALT_BINDINGS
+/*  Enable code implementing additional, mostly emacs-like, line-editing
+    functions. - kw */
+#define ENHANCED_LINEEDIT
+#endif
+
 /* EditFieldData preserves state between calls to LYEdit1
  */
 typedef struct _EditFieldData {
@@ -139,6 +165,10 @@ typedef struct _EditFieldData {
         int  xpan;      /* Horizontal scroll offset                  */
         int  pos;       /* Insertion point in string                 */
         int  margin;    /* Number of columns look-ahead/look-back    */
+        int  current_modifiers; /* Modifiers for next input lynxkeycode */
+#ifdef ENHANCED_LINEEDIT
+	int  mark;	/* position of emacs-like mark */
+#endif
 
         char buffer[1024]; /* String buffer                          */
 
@@ -183,8 +213,29 @@ typedef struct _EditFieldData {
 
 #define LYE_SWMAP (LYE_DELEL +1)  /* Switch input keymap   */
 
+#define LYE_TPOS  (LYE_SWMAP +1)  /* 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 */
+
+#define LYE_C1CHAR  (LYE_UNMOD   +1)  /* 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 */
+/* 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! */
+
 #if defined(USE_KEYMAPS)
 extern int lynx_initialize_keymaps NOPARAMS;
+extern int map_string_to_keysym PARAMS((char * src, int *lec));
 #endif
 
 extern void LYLowerCase PARAMS((
@@ -214,7 +265,8 @@ extern void LYSetupEdit PARAMS((
 	int		maxdsp));
 extern void LYRefreshEdit PARAMS((
 	EditFieldData *	edit));
-extern int EditBinding PARAMS((int ch));
+extern int EditBinding PARAMS((int ch));		   /* in LYEditmap.c */
+extern int LYRemapEditBinding PARAMS((int xlkc, int lec)); /* in LYEditmap.c */
 extern int LYEdit1 PARAMS((
 	EditFieldData *	edit,
 	int		ch,
@@ -226,14 +278,20 @@ extern void LYCloseCloset NOPARAMS;
 extern int current_lineedit;
 extern char * LYLineeditNames[];
 extern char * LYLineEditors[];
+extern CONST char * LYLineeditHelpURLs[];
+
+extern CONST char * LYLineeditHelpURL NOPARAMS;
 
+#if 0				/* NOT USED, use function instead - kw */
 /* Push a character through the lineedit machinery */
 #ifdef    NOT_ASCII  /* S/390 -- gil -- 2080 */
 #define EditBinding(c) (LYLineEditors[current_lineedit][(c)<256 ? TOASCII(c) : c])
 #else  /* NOT_ASCII */
 #define EditBinding(c) (LYLineEditors[current_lineedit][c])
 #endif /* NOT_ASCII */
-#define LYLineEdit(e,c,m) LYEdit1(e,c,EditBinding(c),m)
+#endif /* 0 */
+
+#define LYLineEdit(e,c,m) LYEdit1(e,c,EditBinding(c)&~LYE_DF,m)
 
 /* Dummy initializer for LYEditmap.c */
 extern int LYEditmapDeclared NOPARAMS;
diff --git a/src/LYUtils.c b/src/LYUtils.c
index 3ede56ab..f2ecb7fc 100644
--- a/src/LYUtils.c
+++ b/src/LYUtils.c
@@ -2228,10 +2228,11 @@ PUBLIC int HTCheckForInterrupt NOARGS
 	return((int)TRUE);
 
 	/* There is a subset of mainloop() actions available at this stage:
-	** no new getfile() cyrcle possible until the previous finished.
-	** Currently we have scrolling in partial mode and toggling of trace log.
+	** no new getfile() cycle is possible until the previous finished.
+	** Currently we have scrolling in partial mode and toggling of trace
+	** log.
 	*/
-    switch (keymap[c+1])
+    switch (LKC_TO_LAC(keymap,c))
     {
     case LYK_TRACE_TOGGLE :	       /*  Toggle TRACE mode. */
 	WWW_TraceFlag = ! WWW_TraceFlag;
@@ -2245,7 +2246,7 @@ PUBLIC int HTCheckForInterrupt NOARGS
 	/* OK, we got several lines from new document and want to scroll... */
 	{
 	    int res;
-	    switch (keymap[c+1])
+	    switch (LKC_TO_LAC(keymap,c))
 	    {
 	    case LYK_FASTBACKW_LINK :
 		if (Newline_partial <= (display_lines)+1) {
@@ -2746,7 +2747,7 @@ PUBLIC int is_url ARGS1(
 	/*
 	 *  Special Internal Lynx type.
 	 */
-	(void)is_url(&cp[11]);
+	(void)is_url(&cp[11]);	/* forces lower/uppercase of next part */
 	return(LYNXIMGMAP_URL_TYPE);
 
     } else if (compare_type(cp, "LYNXCOOKIE:", 11)) {
@@ -2823,6 +2824,71 @@ PUBLIC int is_url ARGS1(
 }
 
 /*
+ *  Sometimes it is just expected that curses is on when an alert or
+ *  other statusline message needs to be shown and we are not just
+ *  dumping immediately.  Calling this will 'fix' it, but may not
+ *  always be appropriate. - kw
+ */
+PUBLIC void LYFixCursesOn ARGS1(
+    CONST char *,	reason)
+{
+    if (dump_output_immediately || LYCursesON)
+	return;
+    if (reason) {
+	CTRACE(tfp, "Forcing curses on to %s\n", reason);
+    }
+    start_curses();
+}
+
+/*
+ *  Most protocol modules called through HTLoad* expect that curses is on
+ *  unless dump_output_immediately is set, so that statusline messages
+ *  can be shown.  Some protocols expect the opposite, namely telnet and
+ *  friends.  This function should be called after the 'physical' URL
+ *  for accessing addr has been established.  It does the right thing
+ *  to the degree that curses is turned on for known problem cases.
+ *  In any normal circumstances this should never apply, but proxying
+ *  or rule substitution is not prevented for telnet-like URLs, and
+ *  this 'fix' avoids some crashes that can otherwise occur. - kw
+ */
+PUBLIC BOOLEAN LYFixCursesOnForAccess ARGS2(
+    CONST char *,	addr,
+    CONST char *,	physical)
+{
+    /*
+     *  If curses is off when maybe it shouldn't...
+     */
+    if (!dump_output_immediately && !LYCursesON && physical) {
+	char *cp1;
+	/*
+	 *  If requested resource wants to be accessed with curses off, and
+	 *  getfile() would indeed have turned curses off for it...
+	 */
+	if (strstr(addr, "://") != NULL &&
+	    (!strncmp(addr, "telnet:", 7) ||
+	     !strncmp(addr, "rlogin:", 7) ||
+	     !strncmp(addr, "tn3270:", 7) ||
+	     (strncmp(addr, "gopher:", 7) &&
+	      (cp1 = strchr(addr+11,'/')) != NULL &&
+	      (*(cp1+1) == 'T' || *(cp1+1) == '8')))) {
+	    /*
+	     *  If actual access that will be done is ok with curses off,
+	     *  then do nothing special, else force curses on. - kw
+	     */
+	    if (strncmp(physical, "telnet:", 7) &&
+		strncmp(physical, "rlogin:", 7) &&
+		strncmp(physical, "tn3270:", 7)) {
+		start_curses();
+		HTAlert(
+		    gettext("Unexpected access protocol for this URL scheme."));
+		return TRUE;
+	    }
+	}
+    }
+	return FALSE;
+}
+
+/*
  *  Determine whether we allow HEAD and related flags for a URL. - kw
  */
 PUBLIC BOOLEAN LYCanDoHEAD ARGS1(
@@ -2838,29 +2904,64 @@ PUBLIC BOOLEAN LYCanDoHEAD ARGS1(
     /* Make copy for is_url() since caller may not care for case changes */
     StrAllocCopy(temp0, address);
     isurl = is_url(temp0);
-    FREE(temp0);
-    if (!isurl)
+    if (!isurl) {
+	FREE(temp0);
 	return FALSE;
+    }
     if (isurl == LYNXCGI_URL_TYPE) {
+	FREE(temp0);
 #if defined(LYNXCGI_LINKS) && !defined(VMS)
 	return TRUE;
 #else
 	return FALSE;
 #endif
     }
+    /*
+     *  The idea of the following is to allow HEAD for news URLs that
+     *  identify single articles, not those that identify ranges of
+     *  articles or groups or a list of groups. - kw
+     */
     if (isurl == NEWS_URL_TYPE || isurl == NNTP_URL_TYPE) {
 	char *temp = HTParse(address, "", PARSE_PATH);
 	char *cp = strrchr(temp, '/');
 	if (strchr((cp ? cp : temp), '@') != NULL) {
+	    FREE(temp0);
 	    FREE(temp);
 	    return TRUE;
 	}
 	if (cp && isdigit(cp[1]) && strchr(cp, '-') == NULL) {
+	    FREE(temp0);
 	    FREE(temp);
 	    return TRUE;
 	}
 	FREE(temp);
     }
+
+#define ALLOW_PROXY_HEAD
+/*  If defined, also allow head requests for URLs proxied through the
+ *  "http" or "lynxcgi" protocols, which understand HEAD.  Only the
+ *  proxy environment variables are checked, not the HTRules system. - kw
+ */
+#ifdef ALLOW_PROXY_HEAD
+    if (isurl != FILE_URL_TYPE) {
+	char *acc_method = HTParse(temp0, "", PARSE_ACCESS);
+	if (acc_method && *acc_method) {
+	    char *proxy;
+	    StrAllocCat(acc_method, "_proxy");
+	    proxy = (char *)getenv(acc_method);
+	    if (proxy && (!strncmp(proxy, "http:", 5) ||
+			  !strncmp(proxy, "lynxcgi:", 8)) &&
+		!override_proxy(temp0)) {
+		FREE(temp0);
+		FREE(acc_method);
+		return TRUE;
+	    }
+	}
+	FREE(acc_method);
+    }
+#endif /* ALLOW_PROXY_HEAD */
+
+    FREE(temp0);
     return FALSE;
 }
 
@@ -2935,6 +3036,36 @@ PUBLIC BOOLEAN inlocaldomain NOARGS
 #endif /* !HAVE_UTMP */
 }
 
+#if HAVE_SIGACTION
+/*
+ *  An extended alternative for calling signal(), sets some flags for
+ *  signal handler as we want them if that functionality is available.
+ *  (We don't return anything from this function since the return
+ *  value would currently be ignored anyway.) - kw
+ *
+ */
+PUBLIC void LYExtSignal ARGS2(
+    int,			sig,
+    LYSigHandlerFunc_t *,	handler)
+{
+#ifdef SIGWINCH
+    /* add more cases to if(condition) if required... */
+    if (sig == SIGWINCH && LYNonRestartingSIGWINCH) {
+	struct sigaction act;
+	act.sa_handler = handler;
+	sigemptyset(&act.sa_mask);
+	act.sa_flags = 0;
+#ifdef SA_RESTART
+	if (sig != SIGWINCH)
+	    act.sa_flags |= SA_RESTART;
+#endif /* SA_RESTART */
+	sigaction(sig, &act, NULL);
+    } else
+#endif /* defined(SIGWINCH) */
+	signal(sig, handler);
+}
+#endif /* HAVE_SIGACTION */
+
 /**************
 ** This bit of code catches window size change signals
 **/
@@ -3028,7 +3159,7 @@ PUBLIC void size_change ARGS1(
 		old_lines, old_cols, LYlines, LYcols);
     }
 #ifdef SIGWINCH
-    (void)signal (SIGWINCH, size_change);
+    LYExtSignal (SIGWINCH, size_change);
 #endif /* SIGWINCH */
 
     return;
@@ -3471,7 +3602,16 @@ PUBLIC int number2arrows ARGS1(
  *  parse_restrictions takes a string of comma-separated restrictions
  *  and sets the corresponding flags to restrict the facilities available.
  */
+/* The first two are special: we want to record whether "default" or
+ * "all" restrictions were applied, in addition to the detailed effects
+ * of those options. - kw
+ */
+/* skip the special flags when processing "all" and "default": */
+#define N_SPECIAL_RESTRICT_OPTIONS 2
+
 PRIVATE CONST char *restrict_name[] = {
+       "default" ,
+       "all"     ,
        "inside_telnet" ,
        "outside_telnet",
        "telnet_port"   ,
@@ -3512,6 +3652,13 @@ PRIVATE CONST char *restrict_name[] = {
 #ifdef USE_EXTERNALS
        "externals" ,
 #endif
+       "lynxcfg_info" ,
+#ifndef NO_CONFIG_INFO
+       "lynxcfg_xinfo" ,
+#ifdef HAVE_CONFIG_H
+       "compileopts_info",
+#endif
+#endif
        (char *) 0     };
 
 	/* restrict_name and restrict_flag structure order
@@ -3519,6 +3666,8 @@ PRIVATE CONST char *restrict_name[] = {
 	 */
 
 PRIVATE BOOLEAN *restrict_flag[] = {
+       &had_restrictions_default,
+       &had_restrictions_all,
        &no_inside_telnet,
        &no_outside_telnet,
        &no_telnet_port,
@@ -3559,6 +3708,13 @@ PRIVATE BOOLEAN *restrict_flag[] = {
 #ifdef USE_EXTERNALS
        &no_externals ,
 #endif
+       &no_lynxcfg_info ,
+#ifndef NO_CONFIG_INFO
+       &no_lynxcfg_xinfo ,
+#ifdef HAVE_CONFIG_H
+       &no_compileopts_info ,
+#endif
+#endif
        (BOOLEAN *) 0  };
 
 PUBLIC void parse_restrictions ARGS1(
@@ -3568,17 +3724,25 @@ PUBLIC void parse_restrictions ARGS1(
       CONST char *word;
       int i;
 
-      if (STREQ("all", s)) {
-	   /* set all restrictions */
-	  for (i=0; restrict_flag[i]; i++)
-	      *restrict_flag[i] = TRUE;
-	  return;
-      }
+      p = s;
+      while (*p) {
+	  p = LYSkipCBlanks(p);
+	  if (*p == '\0')
+	      break;
+	  word = p;
+	  while (*p != ',' && *p != '\0')
+	      p++;
+
+	  if (STRNEQ(word, "all", p-word)) {
+	      /* set all restrictions */
+	      for (i=N_SPECIAL_RESTRICT_OPTIONS; restrict_flag[i]; i++)
+		  *restrict_flag[i] = TRUE;
+	  }
 
-      if (STREQ("default", s)) {
-	   /* set all restrictions */
-	  for (i=0; restrict_flag[i]; i++)
-	      *restrict_flag[i] = TRUE;
+	  if (STRNEQ(word, "default", p-word)) {
+	      /* set all restrictions */
+	      for (i=N_SPECIAL_RESTRICT_OPTIONS; restrict_flag[i]; i++)
+		  *restrict_flag[i] = TRUE;
 
 	     /* reset these to defaults */
 	     no_inside_telnet = !(CAN_ANONYMOUS_INSIDE_DOMAIN_TELNET);
@@ -3622,20 +3786,18 @@ PUBLIC void parse_restrictions ARGS1(
 		      no_jump = !(CAN_ANONYMOUS_JUMP);
 		      no_mail = !(CAN_ANONYMOUS_MAIL);
 		     no_print = !(CAN_ANONYMOUS_PRINT);
+	      no_lynxcfg_info = !(CAN_ANONYMOUS_VIEW_LYNXCFG_INFO);
+#ifndef NO_CONFIG_INFO
+	     no_lynxcfg_xinfo = !(CAN_ANONYMOUS_VIEW_LYNXCFG_EXTENDED_INFO);
+#ifdef HAVE_CONFIG_H
+	  no_compileopts_info = !(CAN_ANONYMOUS_VIEW_COMPILEOPTS_INFO);
+#endif
+#endif
+	   no_goto_configinfo = !(CAN_ANONYMOUS_GOTO_CONFIGINFO);
 #if defined(EXEC_LINKS) || defined(EXEC_SCRIPTS)
 		      no_exec = LOCAL_EXECUTION_LINKS_ALWAYS_OFF_FOR_ANONYMOUS;
 #endif /* EXEC_LINKS || EXEC_SCRIPTS */
-	  return;
-      }
-
-      p = s;
-      while (*p) {
-	  p = LYSkipCBlanks(p);
-	  if (*p == '\0')
-	      break;
-	  word = p;
-	  while (*p != ',' && *p != '\0')
-	      p++;
+	  }
 
 	  for (i=0; restrict_name[i]; i++) {
 	     if (STRNEQ(word, restrict_name[i], p-word)) {
@@ -3649,6 +3811,26 @@ PUBLIC void parse_restrictions ARGS1(
       return;
 }
 
+PUBLIC void print_restrictions_to_fd ARGS1(
+    FILE *,	fp)
+{
+    int i, count = 0;
+    for (i=0; restrict_name[i]; i++) {
+	if (*restrict_flag[i] == TRUE)
+	    count++;
+    }
+    if (!count) {
+	fprintf(fp, gettext("No restrictions set.\n"));
+	return;
+    }
+    fprintf(fp, gettext("Restrictions set:\n"));
+    for (i=0; restrict_name[i]; i++) {
+	if (*restrict_flag[i] == TRUE) {
+	    fprintf(fp, "   %s\n", restrict_name[i]);
+	}
+    }
+}
+
 #ifdef VMS
 #include <jpidef.h>
 #include <maildef.h>
@@ -4010,7 +4192,7 @@ PUBLIC void LYConvertToURL ARGS2(
 	FREE(cur_dir);
 have_VMS_URL:
 	CTRACE(tfp, "Trying: '%s'\n", *AllocatedString);
-#else /* Unix: */
+#else /* not VMS: */
 #ifdef DOSPATH
 	if (strlen(old_string) == 1 && *old_string == '.') {
 	    /*
@@ -6247,7 +6429,7 @@ PUBLIC void BeginInternalPage ARGS3(
 		 Title);
 
     if ((user_mode == NOVICE_MODE)
-     && LYwouldPush(Title)
+     && LYwouldPush(Title, NULL)
      && (HelpURL != 0)) {
 	fprintf(fp0, "<h1>%s (%s%s%s), <a href=\"%s%s\">help</a></h1>\n",
 		Title, LYNX_NAME, VERSION_SEGMENT, LYNX_VERSION,
@@ -6438,7 +6620,11 @@ PUBLIC int LYSystem ARGS1(
 	}
     }
 #  endif
+    if (restore_sigpipe_for_children)
+	signal(SIGPIPE, SIG_DFL); /* Some commands expect the default */
     code = system(command);
+    if (restore_sigpipe_for_children)
+	signal(SIGPIPE, SIG_IGN); /* Ignore it again - kw */
 #endif
 
 #ifdef __DJGPP__
diff --git a/src/LYUtils.h b/src/LYUtils.h
index 6a507b94..482adc97 100644
--- a/src/LYUtils.h
+++ b/src/LYUtils.h
@@ -83,6 +83,8 @@ extern int LYOpenInternalPage PARAMS((FILE **fp0, char **newfile));
 extern int LYSystem PARAMS((char *command));
 extern int LYValidateOutput PARAMS((char * filename));
 extern int is_url PARAMS((char *filename));
+extern void LYFixCursesOn PARAMS((CONST char* reason));
+extern BOOLEAN LYFixCursesOnForAccess PARAMS((CONST char* addr, CONST char* physical));
 extern int number2arrows PARAMS((int number));
 extern time_t LYmktime PARAMS((char *string, BOOL absolute));
 extern void BeginInternalPage PARAMS((FILE *fp0, char *Title, char *HelpURL));
@@ -117,6 +119,7 @@ extern void free_and_clear PARAMS((char **obj));
 extern void highlight PARAMS((int flag, int cur, char *target));
 extern void noviceline PARAMS((int more_flag));
 extern void parse_restrictions PARAMS((CONST char *s));
+extern void print_restrictions_to_fd PARAMS((FILE *fp));
 extern void remove_backslashes PARAMS((char *buf));
 extern void size_change PARAMS((int sig));
 extern void statusline PARAMS((CONST char *text));
diff --git a/src/UCAuto.c b/src/UCAuto.c
index 12e9f1de..6446341d 100644
--- a/src/UCAuto.c
+++ b/src/UCAuto.c
@@ -117,8 +117,8 @@ PUBLIC void UCChangeTerminalCodepage ARGS2(
     static TGen_state_t lastUtf = Dunno;
     static TGen_state_t lastHasUmap = Dunno;
 
-    static char *old_font;
-    static char *old_umap;
+    static char *old_font = NULL;
+    static char *old_umap = NULL;
 
     CONST char * name;
     TTransT_t TransT = GN_dunno;
@@ -145,26 +145,57 @@ PUBLIC void UCChangeTerminalCodepage ARGS2(
 		    HTSprintf0(&tmpbuf1, "%s %s %s",
 			    SETFONT, old_font, NOOUTPUT);
 		}
+		CTRACE(tfp, "Executing setfont to restore: '%s'\n", tmpbuf1);
 		LYSystem(tmpbuf1);
 		FREE(tmpbuf1);
 	    }
-
-	    remove(old_font);
-	    FREE(old_font);
-	    old_font = 0;
-
-	    remove(old_umap);
-	    FREE(old_umap);
-	    old_umap = 0;
+	}
+	if (newcs < 0 && p == 0) {
+	    if (old_font) {
+		LYRemoveTemp(old_font);
+		FREE(old_font);
+	    }
+	    if (old_umap) {
+		LYRemoveTemp(old_umap);
+		FREE(old_umap);
+	    }
 	}
 	return;
     } else if (lastcs < 0 && old_umap == 0 && old_font == 0) {
+#if 0
 	old_umap = tempnam((char *)0, "umap");
 	old_font = tempnam((char *)0, "font");
-	HTSprintf0(&tmpbuf1, "%s -o %s -ou %s %s",
-		SETFONT, old_font, old_umap, NOOUTPUT);
-	LYSystem(tmpbuf1);
-	FREE(tmpbuf1);
+#endif
+	FILE * fp1;
+	FILE * fp2 = NULL;
+	if ((old_font = calloc(1, LY_MAXPATH)))
+	    old_umap = calloc(1, LY_MAXPATH);
+	if ((fp1 = LYOpenTemp(old_font, ".fnt", "wb")))
+	    fp2 = LYOpenTemp(old_umap, ".uni", "wb");
+	if (fp1 && fp2) {
+	    size_t nlen;
+	    char *rp;
+	    HTSprintf0(&tmpbuf1, "%s -o %s -ou %s %s",
+		       SETFONT, old_font, old_umap, NOOUTPUT);
+	    CTRACE(tfp, "Executing setfont to save: '%s'\n", tmpbuf1);
+	    LYSystem(tmpbuf1);
+	    FREE(tmpbuf1);
+	    LYCloseTempFP(fp1);
+	    LYCloseTempFP(fp2);
+	    if ((nlen = strlen(old_font)) + 1 < LY_MAXPATH &&
+		 (rp = realloc(old_font, nlen + 1)))
+		old_font = rp;
+	    if ((nlen = strlen(old_umap)) + 1 < LY_MAXPATH &&
+		 (rp = realloc(old_umap, nlen + 1)))
+		old_umap = rp;
+	} else {
+	    if (fp1)
+		LYRemoveTemp(old_font);
+	    if (fp2)
+		LYRemoveTemp(old_umap);
+	    FREE(old_font);
+	    FREE(old_umap);
+	}
     }
 
     name = p->MIMEname;
diff --git a/userdefs.h b/userdefs.h
index 3433b4ca..da5c5d02 100644
--- a/userdefs.h
+++ b/userdefs.h
@@ -9,7 +9,7 @@
  * There are four sections to this document:
  *  Section 1.  Things you MUST verify.  Unix platforms use a configure
  *		script to provide sensible default values.  If your site
- *		has special requirements, that may not be sufficient. 
+ *		has special requirements, that may not be sufficient.
  *		For non-Unix platforms (e.g., VMS), there is no
  *		configure script, so the defaults here are more
  *		critical.
@@ -424,8 +424,8 @@
  * STARTFILE is the default starting URL if none is specified
  *   on the command line or via a WWW_HOME environment variable;
  *   Lynx will refuse to start without a starting URL of some kind.
- * STARTFILE can be remote, e.g. http://www.w3.org/default.html ,
- *                or local, e.g. file://localhost/PATH_TO/FILENAME ,
+ * STARTFILE can be remote, e.g., http://www.w3.org/default.html ,
+ *                or local, e.g., file://localhost/PATH_TO/FILENAME ,
  *           where PATH_TO is replaced with the complete path to FILENAME
  *           using Unix shell syntax and including the device on VMS.
  *
@@ -435,7 +435,7 @@
 #define STARTFILE "http://lynx.browser.org/"
 /*
  * As an alternative, you may want to use a local URL.  A good choice for this
- * is the user's home directory: 
+ * is the user's home directory:
  *#define STARTFILE "file://localhost/~/"
  *
  * Your choice of STARTFILE should reflect your site's needs, and be a URL that
@@ -934,7 +934,8 @@
  * Note that this is currently not supported with the chartrans code,
  * or rather it doesn't have an effect if translations for a display
  * character set are taken from one of the *.tbl files in src/chrtrans.
- * One would have to modify the corresponding *.tbl file for this.
+ * One would have to modify the corresponding *.tbl file to change the
+ # 7-bit replacements for these characters.
  */
 #define LY_UMLAUT
 
@@ -997,41 +998,6 @@
 /* #define EXEC_LINKS  */
 /* #define EXEC_SCRIPTS  */
 
-/**********
- * UNIX:
- * =====
- * CGI script support.  Defining LYNXCGI_LINKS allows you to use the
- *
- *   lynxcgi:path
- *
- * URL which allows lynx to access a cgi script directly without the need for
- * a http daemon.  Redirection or mime support is not supported but just about
- * everything else is.  If the path is not an executable file then the URL is
- * rewritten as file://localhost and passed to the file loader.  This means
- * that if your http:html files are currently set up to use relative
- * addressing, you should be able to fire up your main page with lynxcgi:path
- * and everything should work as if you were talking to the http daemon.
- *
- * Note that TRUSTED_LYNXCGI directives must be defined in your lynx.cfg file
- * if you wish to place restrictions on source documents and/or paths for
- * lynxcgi links.
- *
- * The cgi scripts are called with a fork()/execve() sequence so you don't
- * have to worry about people trying to abuse the code. :-)
- *
- *     George Lindholm (George.Lindholm@ubc.ca)
- *
- * VMS:
- * ====
- * The lynxcgi scheme, if enabled, yields an informational message regardless
- * of the path, and use of the freeware OSU DECthreads server as a local
- * script server is recommended instead of lynxcgi URLs.  Uncomment the
- * following line to define LYNXCGI_LINKS, and when running Lynx, enter
- * lynxcgi:advice  as a G)oto URL for more information and links to the
- * OSU server distribution.
- */
-/* #define LYNXCGI_LINKS */
-
 #if defined(EXEC_LINKS) || defined(EXEC_SCRIPTS)
 
 /**********
@@ -1089,6 +1055,41 @@
 
 #endif /*  defined(EXEC_LINKS) || defined(EXEC_SCRIPTS) */
 
+/**********
+ * UNIX:
+ * =====
+ * CGI script support.  Defining LYNXCGI_LINKS allows you to use the
+ *
+ *   lynxcgi:path
+ *
+ * URL which allows lynx to access a cgi script directly without the need for
+ * a http daemon.  Redirection is not supported but just about everything
+ * else is.  If the path is not an executable file then the URL is
+ * rewritten as file://localhost and passed to the file loader.  This means
+ * that if your http:html files are currently set up to use relative
+ * addressing, you should be able to fire up your main page with lynxcgi:path
+ * and everything should work as if you were talking to the http daemon.
+ *
+ * Note that TRUSTED_LYNXCGI directives must be defined in your lynx.cfg file
+ * if you wish to place restrictions on source documents and/or paths for
+ * lynxcgi links.
+ *
+ * The cgi scripts are called with a fork()/execve() sequence so you don't
+ * have to worry about people trying to abuse the code. :-)
+ *
+ *     George Lindholm (George.Lindholm@ubc.ca)
+ *
+ * VMS:
+ * ====
+ * The lynxcgi scheme, if enabled, yields an informational message regardless
+ * of the path, and use of the freeware OSU DECthreads server as a local
+ * script server is recommended instead of lynxcgi URLs.  Uncomment the
+ * following line to define LYNXCGI_LINKS, and when running Lynx, enter
+ * lynxcgi:advice  as a G)oto URL for more information and links to the
+ * OSU server distribution.
+ */
+/* #define LYNXCGI_LINKS */
+
 /*********************************
  *  MAIL_SYSTEM_ERROR_LOGGING will send a message to the owner of
  *  the information if there is one, every time
@@ -1101,6 +1102,16 @@
 #define MAIL_SYSTEM_ERROR_LOGGING   FALSE  /*mail a message for every error?*/
 
 /*********************************
+ *  If a document cannot be accessed, and MAIL_SYSTEM_ERROR_LOGGING
+ *  is on and would send a message to the owner of the information,
+ *  but no owner is known, then the message will be sent to ALERTMAIL
+ *  instead - if it is defined as a non-empty email address.
+ *
+ *  NOTE: This can generate A REAL LOT of mail, be warned!!!
+ */
+/* #define ALERTMAIL "webmaster@localhost" */ /*error recipient if no owner*/
+
+/*********************************
  * If CHECKMAIL is set to TRUE, the user will be informed (via a status line
  * message) about the existence of any unread mail at startup of Lynx, and
  * will get status line messages if subsequent new mail arrives.  If a jumps
@@ -1244,12 +1255,12 @@
  * the version definition with the Project Version on checkout.  Just
  * ignore it. - kw */
 /* $Format: "#define LYNX_VERSION \"$ProjectVersion$\""$ */
-#define LYNX_VERSION "2.8.2rel.1"
+#define LYNX_VERSION "2.8.3dev.1"
 #define LYNX_WWW_HOME "http://lynx.browser.org/"
 #define LYNX_WWW_DIST "http://www.slcc.edu/lynx/current/"
 #define LYNX_RELEASE FALSE
 /* $Format: "#define LYNX_DATE \"$ProjectDate$\""$ */
-#define LYNX_DATE "Tue, 01 Jun 1999 19:30:15 -0600"
+#define LYNX_DATE "Fri, 11 Jun 1999 03:34:08 -0600"
 #define LYNX_DATE_OFF 5		/* truncate the automatically-generated date */
 #define LYNX_DATE_LEN 11	/* truncate the automatically-generated date */
 #define LYNX_RELEASE_DATE "1998"
@@ -1404,7 +1415,10 @@
 
 /*******************************
  * set to FALSE if you don't want users of your anonymous
- * account to be able to read news
+ * account to be able to read news OR post news articles.
+ * These flags apply to "news", "nntp", "newspost", and "newsreply"
+ * URLs, but not to "snews", "snewspost", or "snewsreply"
+ * in case they are supported.
  */
 #define CAN_ANONYMOUS_INSIDE_DOMAIN_READ_NEWS	TRUE
 #define CAN_ANONYMOUS_OUTSIDE_DOMAIN_READ_NEWS	FALSE
@@ -1464,6 +1478,48 @@
  */
 #define CAN_ANONYMOUS_PRINT	FALSE
 
+/*******************************
+ * set to FALSE if users with anonymous restrictions should
+ * not be able to view configuration file (lynx.cfg) info
+ * via special LYNXCFG: links.  (This does not control access
+ * to lynx.cfg as a normal file, e.g., through a "file:" URL,
+ * if other restrictions allow that.)
+ */
+#define CAN_ANONYMOUS_VIEW_LYNXCFG_INFO			TRUE
+
+/*******************************
+ * set to FALSE if users with anonymous restrictions should
+ * not be able to view extended configuration file (lynx.cfg)
+ * info @@@ or perform special config info functions (reloading
+ * at run-time) via special LYNXCFG: links @@@.  This only applies
+ * if the lynxcfg_info" restriction controlled by the previous
+ * item is not in effect and if Lynx has been compiled without
+ * NO_CONFIG_INFO defined (--disable-config-info wasn't used
+ * if Lynx was built with the autoconf configure script).
+ * The extended info may include details on configuration file
+ * names and location and links for reading the files, as well
+ * as information on nesting of included configuration files.
+ */
+#define CAN_ANONYMOUS_VIEW_LYNXCFG_EXTENDED_INFO	TRUE
+
+/*******************************
+ * set to FALSE if users with anonymous restrictions should
+ * not be able to view information on compile time configuration
+ * via special LYNXCOMPILEOPTS: links.  This only applies
+ * if the autoconf configure script was used to build Lynx
+ * AND --disable-config-info wasn't used, otherwise this
+ * special URL scheme isn't recognized anyway.
+ */
+#define CAN_ANONYMOUS_VIEW_COMPILEOPTS_INFO		TRUE
+
+/*******************************
+ * set to FALSE if you don't want users of your anonymous
+ * account to be able to 'g'oto special URLs for showing
+ * configuration info (LYNXCFG: and LYNXCOMPILEOPTS:) if
+ * they are otherwise allowed.
+ */
+#define CAN_ANONYMOUS_GOTO_CONFIGINFO		TRUE
+
 /*****************************
  * Be sure you have read about and set defines above in Sections
  * 1, 2 and 3 that could  affect Lynx in an anonymous account,