changeset 90288:7432ca837c8d

Revision: emacs@sv.gnu.org/emacs--unicode--0--patch-9 Merge from emacs--devo--0 Patches applied: * emacs--devo--0 (patch 16-33) - Update from CVS - Install ERC. - Fix ERC compiler warnings. - Use utf-8 encoding in ERC ChangeLogs. - Merge ERC-related Viper hacks into Viper. - Merge from erc--main--0 - Merge from gnus--rel--5.10 * gnus--rel--5.10 (patch 8-13) - Merge from emacs--devo--0 - Update from CVS
author Miles Bader <miles@gnu.org>
date Wed, 01 Feb 2006 10:07:17 +0000
parents 3cd97358d81a (current diff) 04c2548593f7 (diff)
children 72d8a45f6c9f
files ChangeLog Makefile.in admin/ChangeLog admin/FOR-RELEASE configure configure.in etc/ChangeLog etc/NEWS etc/TODO info/dir lisp/ChangeLog lisp/Makefile.in lisp/bs.el lisp/cus-edit.el lisp/ediff-mult.el lisp/emacs-lisp/cl.el lisp/emulation/viper.el lisp/files.el lisp/gnus/ChangeLog lisp/gnus/mailcap.el lisp/gnus/message.el lisp/gnus/mm-uu.el lisp/gnus/nnweb.el lisp/help-fns.el lisp/mail/rmailsum.el lisp/makefile.w32-in lisp/mh-e/ChangeLog lisp/mh-e/mh-alias.el lisp/mh-e/mh-comp.el lisp/mh-e/mh-customize.el lisp/mh-e/mh-e.el lisp/mh-e/mh-exec.el lisp/mh-e/mh-funcs.el lisp/mh-e/mh-identity.el lisp/mh-e/mh-inc.el lisp/mh-e/mh-init.el lisp/mh-e/mh-junk.el lisp/mh-e/mh-mime.el lisp/mh-e/mh-print.el lisp/mh-e/mh-seq.el lisp/mh-e/mh-speed.el lisp/mh-e/mh-utils.el lisp/net/tramp-vc.el lisp/replace.el lisp/simple.el lisp/subr.el lisp/textmodes/flyspell.el lisp/textmodes/ispell.el lisp/textmodes/org.el lisp/thumbs.el lisp/vc-hooks.el lisp/vc-rcs.el lisp/vc-sccs.el lisp/vc.el lisp/wid-edit.el lisp/window.el lispref/ChangeLog lispref/display.texi lispref/frames.texi lispref/lists.texi man/ChangeLog man/Makefile.in man/anti.texi man/basic.texi man/cc-mode.texi man/commands.texi man/display.texi man/emacs.texi man/entering.texi man/faq.texi man/fixit.texi man/help.texi man/killing.texi man/m-x.texi man/makefile.w32-in man/mark.texi man/message.texi man/mini.texi man/msdog.texi man/regs.texi man/screen.texi man/search.texi src/ChangeLog src/alloc.c src/callproc.c src/cmds.c src/data.c src/dired.c src/editfns.c src/frame.c src/gtkutil.c src/keymap.c src/window.c src/xfns.c
diffstat 156 files changed, 45955 insertions(+), 14666 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Thu Jan 26 02:23:05 2006 +0000
+++ b/ChangeLog	Wed Feb 01 10:07:17 2006 +0000
@@ -1,3 +1,26 @@
+2006-01-31  Jan Dj,Ad(Brv  <jan.h.d@swipnet.se>
+
+	* configure.in: Require GTK 2.4 or newer.
+	* configure: Regenerate
+
+2006-01-29  Michael Olson  <mwolson@gnu.org>
+
+	* Makefile.in (install-arch-indep, uninstall): Add ERC.
+	* info/dir (ERC): New entry.
+
+2006-01-29  Eli Zaretskii  <eliz@gnu.org>
+
+	* info/dir: Fix last change.
+
+2006-01-28  Luc Teirlinck  <teirllm@auburn.edu>
+
+	* Makefile.in (install-arch-indep, uninstall): Add rcirc.
+
+2006-01-27  Eli Zaretskii  <eliz@gnu.org>
+
+	* info/dir: Untabify the whole file.
+	(Rcirc): New entry.
+
 2006-01-12  Andreas Schwab  <schwab@suse.de>
 
 	* configure.in: Move AC_AIX and AC_GNU_SOURCE before first compile
--- a/Makefile.in	Thu Jan 26 02:23:05 2006 +0000
+++ b/Makefile.in	Wed Feb 01 10:07:17 2006 +0000
@@ -497,7 +497,7 @@
 	      chmod a+r ${infodir}/dir); \
 	   fi; \
 	   cd ${srcdir}/info ; \
-	   for f in ada-mode* autotype* calc* ccmode* cl* dired-x* ebrowse* ediff* efaq* eintr* elisp* emacs* emacs-mime* emacs-xtra* eshell* eudc* flymake* forms* gnus* idlwave* info* message* mh-e* newsticker* org* pcl-cvs* pgg* reftex* sc* ses* sieve* speedbar* tramp* vip* widget* woman* smtpmail* url*; do \
+	   for f in ada-mode* autotype* calc* ccmode* cl* dired-x* ebrowse* ediff* efaq* eintr* elisp* emacs* emacs-mime* emacs-xtra* eshell* eudc* flymake* forms* gnus* idlwave* info* message* mh-e* newsticker* org* pcl-cvs* pgg* reftex* sc* ses* sieve* speedbar* tramp* vip* widget* woman* smtpmail* url* rcirc* erc*; do \
 	     (cd $${thisdir}; \
 	      ${INSTALL_DATA} ${srcdir}/info/$$f ${infodir}/$$f; \
 	      chmod a+r ${infodir}/$$f); \
@@ -507,7 +507,7 @@
 	thisdir=`/bin/pwd`; \
 	if [ `(cd ${srcdir}/info && /bin/pwd)` != `(cd ${infodir} && /bin/pwd)` ]; \
 	then \
-	  for f in ada-mode autotype calc ccmode cl dired-x ebrowse ediff efaq elisp eintr emacs emacs-mime emacs-xtra eshell eudc flymake forms gnus idlwave info message mh-e newsticker org pcl-cvs pgg reftex sc ses sieve speedbar tramp vip viper widget woman smtpmail url; do \
+	  for f in ada-mode autotype calc ccmode cl dired-x ebrowse ediff efaq elisp eintr emacs emacs-mime emacs-xtra eshell eudc flymake forms gnus idlwave info message mh-e newsticker org pcl-cvs pgg reftex sc ses sieve speedbar tramp vip viper widget woman smtpmail url rcirc erc; do \
 	    (cd $${thisdir}; \
 	     ${INSTALL_INFO} --info-dir=${infodir} ${infodir}/$$f); \
 	  done; \
@@ -573,7 +573,7 @@
 	done
 	(cd ${archlibdir} && rm -f fns-*)
 	-rm -rf ${libexecdir}/emacs/${version}
-	(cd ${infodir} && rm -f cl* ada-mode* autotype* calc* ccmode* ebrowse* efaq* eintr elisp* eshell* eudc* idlwave* message* pcl-cvs* reftex* speedbar* tramp* widget* woman* dired-x* ediff* emacs* emacs-xtra* flymake* forms* gnus* info* mh-e* newsticker* org* sc* ses* vip* smtpmail* url*)
+	(cd ${infodir} && rm -f cl* ada-mode* autotype* calc* ccmode* ebrowse* efaq* eintr elisp* eshell* eudc* idlwave* message* pcl-cvs* reftex* speedbar* tramp* widget* woman* dired-x* ediff* emacs* emacs-xtra* flymake* forms* gnus* info* mh-e* newsticker* org* sc* ses* vip* smtpmail* url* rcirc* erc*)
 	(cd ${man1dir}  && rm -f emacs${manext} emacsclient${manext} etags${manext} ctags${manext})
 	(cd ${bindir}  && rm -f $(EMACSFULL) $(EMACS))
 
--- a/admin/ChangeLog	Thu Jan 26 02:23:05 2006 +0000
+++ b/admin/ChangeLog	Wed Feb 01 10:07:17 2006 +0000
@@ -1,3 +1,7 @@
+2006-01-27  Chong Yidong  <cyd@stupidchicken.com>
+
+	* FOR-RELEASE: string allocation bugs fixed.
+
 2005-12-13  Bill Wohler  <wohler@newt.com>
 
 	* FOR-RELEASE: Ensure MH-E 8.0 has been released.
--- a/admin/FOR-RELEASE	Thu Jan 26 02:23:05 2006 +0000
+++ b/admin/FOR-RELEASE	Wed Feb 01 10:07:17 2006 +0000
@@ -41,19 +41,8 @@
 a bitmap appearence.
 [Assigned to KFS]
 
-* FATAL ERRORS
-
-** Investigate reported crashes in compact_small_strings.
-
-** Investigate reported crashes related to using an
-invalid pointer from string_free_list.
-
 * BUGS
 
-** Roland.Winkler@physik.uni-erlangen.de's Dec 3 bug report for align.el.
-
-** Ronan Keryell's Sep 23 bug about "tramp sudo:: and version control on RCS"
-
 ** TCP server processes do not work on Windows.
 
 TCP/IP server processes created with `make-network-process' consume
--- a/configure	Thu Jan 26 02:23:05 2006 +0000
+++ b/configure	Wed Feb 01 10:07:17 2006 +0000
@@ -10200,8 +10200,8 @@
 echo "$as_me: error: Conflicting options, --with-gtk is incompatible with --with-x-toolkit=${with_x_toolkit}" >&2;}
    { (exit 1); exit 1; }; };
   fi
-  GLIB_REQUIRED=2.0.1
-  GTK_REQUIRED=2.0.1
+  GLIB_REQUIRED=2.4
+  GTK_REQUIRED=2.4
   GTK_MODULES="gtk+-2.0 >= $GTK_REQUIRED glib-2.0 >= $GLIB_REQUIRED"
 
     if test "X${with_pkg_config_prog}" != X; then
--- a/configure.in	Thu Jan 26 02:23:05 2006 +0000
+++ b/configure.in	Wed Feb 01 10:07:17 2006 +0000
@@ -2000,8 +2000,8 @@
   if test "$USE_X_TOOLKIT" != "none" && test "$USE_X_TOOLKIT" != "maybe"; then
     AC_MSG_ERROR([Conflicting options, --with-gtk is incompatible with --with-x-toolkit=${with_x_toolkit}]);
   fi
-  GLIB_REQUIRED=2.0.1
-  GTK_REQUIRED=2.0.1
+  GLIB_REQUIRED=2.4
+  GTK_REQUIRED=2.4
   GTK_MODULES="gtk+-2.0 >= $GTK_REQUIRED glib-2.0 >= $GLIB_REQUIRED"
 
   dnl Check if --with-pkg-config-prog has been given.
--- a/etc/ChangeLog	Thu Jan 26 02:23:05 2006 +0000
+++ b/etc/ChangeLog	Wed Feb 01 10:07:17 2006 +0000
@@ -1,3 +1,11 @@
+2006-01-29  Michael Olson  <mwolson@gnu.org>
+
+	* NEWS: Add entry for ERC.
+
+2006-01-27  Chong Yidong  <cyd@stupidchicken.com>
+
+	* TODO: Make SYNC_INPUT the default.
+
 2006-01-25  Nick Roberts  <nickrob@snap.net.nz>
 
 	* images/gud/pstar.xpm: Make background transparent.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/etc/ERC-NEWS	Wed Feb 01 10:07:17 2006 +0000
@@ -0,0 +1,599 @@
+ERC NEWS                                                       -*- outline -*-
+
+* Changes since ERC 5.0.4
+
+** Improve XEmacs compatibility.
+
+** Namespace changes
+
+*** Now ERC doesn't use global variable space.
+Renamed all variables that didn't start with "erc-".
+
+  o `away' is now `erc-away'
+
+  o `current-nick' is now `erc-server-current-nick'
+
+  o `last-peers' is now `erc-server-last-peers'
+
+  o `last-ping-time' is now `erc-server-last-ping-time'
+
+  o `last-sent-time' is now `erc-server-last-sent-time'
+
+  o `lines-sent' is now `erc-server-lines-sent'
+
+  o `quitting' is now `erc-server-quitting'
+
+*** Remove the `with-erc-channel-buffer' function.
+
+** Bugfixes
+
+*** Don't inadvertently destroy face properties.
+
+*** Load erc scripts in a safer way.
+
+*** Don't insert a timestamp if text at point is invisible.
+
+*** Don't hide messages from those in `erc-fools' by default.
+Color their nicks instead.
+
+*** Use a more foolproof method of encoding and decoding strings
+before sending to a channel.
+
+** Backend changes
+
+*** Renamed some server-specific variables
+
+  o `erc-announced-server-name' is now `erc-server-announced-name'
+
+  o `erc-auto-reconnect' is now `erc-server-auto-reconnect'
+
+  o `erc-connect-function' is now `erc-server-connect-function'
+
+  o `erc-default-coding-system' is now `erc-server-coding-system'
+
+  o `erc-duplicate-timeout' is now `erc-server-duplicate-timeout'
+
+  o `erc-duplicates' is now `erc-server-duplicates'
+
+  o `erc-lag' is now `erc-server-lag'
+
+  o `erc-prevent-duplicates' is now `erc-server-prevent-duplicates'
+
+  o `erc-previous-read' is now `erc-server-filter-data'
+
+  o `erc-process' is now `erc-server-process'
+
+  o `erc-ping-handler' is now `erc-server-send-ping-handler'
+
+  o `erc-ping-interval' is now `erc-server-send-ping-interval'
+
+*** Renamed some functions
+
+  o `erc-connect' is now `erc-server-connect'
+
+  o `erc-process-filter' is now `erc-server-filter-function'
+
+  o `erc-send-command' is now `erc-server-send'
+
+  o `erc-send-single-line' is now `erc-send-input'
+
+  o `erc-setup-periodical-server-ping' is now
+    `erc-server-setup-periodical-server-ping'
+
+  o `erc-split-command is now `erc-split-line'
+
+*** New options
+
+  o erc-server-flood-margin, erc-server-flood-penalty: New options
+    that allow tweaking of flood control.
+
+  o erc-split-line-length: The maximum line length of a single
+    message.
+
+*** New variables
+
+  o erc-server-flood-last-message, erc-server-flood-queue,
+    erc-server-flood-timer: Flood control.
+
+  o erc-server-processing-p: Indicate when we're currently processing
+    a message.
+
+*** Remove some options
+
+  o `erc-flood-limit'
+  o `erc-flood-limit2'
+
+** New customization group `erc-server' for dealing with IRC servers.
+
+** ERC can now be installed by doing `make install' from the command line.
+
+** ERC now has a manual in erc.texi.
+Type `make doc' to generate HTML and Info versions of it.
+
+** ERC no longer depends on cl.el.
+Only the macros in cl-macs.el are used.
+
+** Fix an edge case when quitting as new messages come in.
+
+** Make flood protection toggle-able as on/off, removing the 'strict option.
+
+** If possible, re-use channel buffers when reconnecting to a server.
+
+** Text in ERC buffers is now read-only by default.
+To get the previous behavior, 
+
+** Changes and additions to modules
+
+*** Auto-join (erc-autojoin.el)
+
+**** Recognize the Azzurra server.
+
+*** BBDB (erc-bbdb.el)
+
+**** When the user types /WHOIS, ask for a record to merge to.
+
+**** Store the displayed name of a BitlBee contact.
+The new `erc-bbdb-bitlbee-name-field' option specifies the field to use
+to store this information.
+
+**** Don't prompt for a name on /JOIN or /NICK.
+
+*** Button (erc-button.el)
+
+**** Fix customization of `erc-button-alist'
+
+**** New option `erc-button-nickname-face' determines the face to use
+when coloring ERC nicknames.
+
+*** Channel tracking (erc-track.el)
+
+**** Remove channels from the modified channels list if not currently
+connected.  This should remove residue from the mode line after
+quitting ERC.
+
+**** Recognize buttonized text
+
+*** Highlighting (erc-match.el)
+
+**** Highlight current nickname by default.
+
+**** Added the option of beeping when certain matches occur.
+Add `erc-beep-on-match' to `erc-text-matched-hook' to enable
+beeping.  Set the new variable `erc-beep-match-types' which match
+types that make beeps.
+
+*** Nicklist (erc-nicklist.el)
+
+**** Fix a couple of errors.
+
+**** Make sure a stray mouse click doesn't trigger an error.
+
+**** Insert icons from the /images directory next to nicks.
+This indicates their away status.  The location is customizable via
+the new `erc-nicklist-icons-directory' option.
+
+If you do not want these icons, set `erc-nicklist-use-icons' to nil.
+
+*** Nickserv identification (erc-nickserv.el)
+
+**** Recognize Azzurra and OFTC networks.
+
+*** Old completion (erc-complete.el)
+
+**** Disable by default.
+
+*** Programmable completion (erc-pcomplete.el)
+
+**** Enable by default.
+
+*** Timestamps (erc-stamp.el)
+
+**** On Emacs22, align right timestamps perfectly, even if variable-width
+characters are used.  If we aren't using Emacs22, move text farther
+away from the right margin when variable-width characters are used.
+It is considered better to misalign the stamp by a bit than to go past
+the right margin.
+
+**** Enable by default
+
+** New modules
+
+*** Spell-checking (erc-spelling.el)
+
+**** Use flyspell in ERC.
+
+*** Viper compatibility (erc-viper.el)
+
+**** Helps ERC work correctly in viper-mode.
+
+* Fixes since ERC 5.0.3
+
+** Fix a problem with undo in channels.
+
+* Fixes since ERC 5.0.2
+
+** Fix typo in the `ctcp-request-to' entry of the English catalog.
+
+** Debugging with edegug has been made easier in all of the
+erc-with-* and with-erc* macros.
+
+** Non-ASCII character sets should be better supported when sending
+and processing messages.
+
+** A load failure with erc-autoaway.el and Emacs21 has been fixed.
+
+** A few XEmacs warnings were fixed.
+
+** Changes and additions to modules
+
+*** Backend (erc-backend.el)
+
+**** Move the check for hidden messages into `erc-display-message'
+so there isn't so much replicated code.
+
+**** Add `definition-name' property to constructed symbols so that
+`find-function' and `find-variable' will be able to locate them.
+
+**** Make sure logs are inserted info the correct channel buffers.
+There was previously an error when using `erc-insert-log-on-open' in
+combination with autojoin to multiple channels.
+
+*** Button (erc-button.el)
+
+**** The layering of `erc-button-face' on other faces in ERC buffers
+has been improved.
+
+*** Channel tracking (erc-track.el)
+
+**** Use optimal amount of whitespace around modified channels
+indicator.  Previously, there was an additional unnecessary space.
+
+**** Fix an error that occurred when unchecked buffers existed when
+invoking /QUIT.
+
+* Fixes since ERC 5.0.1
+
+** If a channel key is required for a certain channel, ERC will prompt
+for one if `erc-prompt-for-channel-key' is non-nil.
+
+** ERC doesn't try to reconnect if the network connection is refused
+when using `open-network-stream-nowait' as the `erc-connect-function'.
+
+** Messages from multiple servers will not go to the currently active
+buffer.  The messages from each server will be contained in the most
+recently active channel/server buffer that corresponds with the
+server.
+
+** Some text messages were cleaned up slightly.
+
+** Button faces should no longer "cover" other faces.
+
+** Made some XEmacs compatibility fixes.
+
+** Nicknames containing a backslash are now correctly highlighted as
+current-nick and buttonized as nicks.
+
+** `erc-server-select' doesn't offer networks without servers as a
+choice anymore.
+
+** Non-ASCII character support has been improved.
+
+** Changes and additions to modules
+
+*** Menu (erc-menu.el)
+
+**** You can now save logs and truncate buffers from the menu-bar.
+
+* Fixes since ERC 5.0
+
+** Narrowing in ERC buffers no longer causes formatting errors.
+
+** The BBDB module now loads correctly when customizing `erc-modules'.
+
+** The value of `erc-button-face' is now respected.
+
+** Fixed a bug which caused a read-only error during connection.
+
+** Server buffers are now tracked correctly.
+This means that `erc-track-priority-faces-only', `erc-track-exclude',
+and `erc-track-exclude-types' now work with server buffers.
+
+* Changes since ERC 4.0
+
+** Channel members are now stored as a hash-table.
+`erc-server-users' and `erc-channel-users' are now hash-tables, rather
+than alists.  This significantly increases performance, especially in
+large channels.  Each channel member is stored as an `erc-server-user'
+struct, with additional information about the channels they are on
+stored in an `erc-channel-user' struct.  Code using old alist-style
+channel members needs to be updated to work with hash-tables.
+This new code also removes the need for erc-members.el, which has been
+removed.
+
+** The way ERC deals with input from the server has changed.
+All server response code is now in a new file, erc-backend.el.  There
+should be no real user visible changes.  There are, however, a few
+major changes for implementers, and module writers:
+
+*** The PARSED response that all handlers get called with is
+    no longer a vector, but an `erc-response' struct.
+
+    This means LESS MAGIC NUMBERS in the ERC source code, but a few
+    changes in how you get at parsed responses.
+
+    The sender is accessed via `erc-response.sender'.
+
+    The command is accessed via `erc-response.command'.
+
+    The arguments to the command (everything after the command and
+    before the colon) are accessed via `erc-response.command-args'.
+    This is a /list/ of arguments in the order they appear in the
+    unparsed response.
+
+    The contents of the response is accessed via
+    `erc-response.contents'.
+
+    Should, for some reason, you want to do something with the
+    /unparsed/ response, you can get it via `erc-response.unparsed'.
+
+*** The `erc-server-hook-list' mechanism is gone.
+
+    All server response handlers should be defined with
+    `define-erc-response-handler'.  This defines functions and
+    corresponding hook variables.
+
+    The mapping of server commands to hook variables is no longer
+    done via `erc-event-to-hook', but through an #'equal hashtable,
+    `erc-server-responses'.  In order to find a hook you do:
+
+    (erc-get-hook command)
+
+    See the docstring of `define-erc-response-handler' for more
+    information.
+
+*** ALL hook variables have been renamed.
+
+    In accordance with recommendations in the Emacs Lisp manual,
+    the hook variables are no longer called `erc-server-FOO-hook',
+    but rather `erc-server-FOO-functions'.  This is to indicate
+    that the functions they call take arguments.
+
+    All the modules in ERC have been updated to reflect this change,
+    but external module authors should beware.
+
+** The values of `erc-mode-line-format' and `erc-header-line-format'
+are now defined as strings to be formatted using `format-spec'.
+`erc-mode-line-format' does not replace the whole mode-line anymore,
+only `mode-line-buffer-identification' is set.  This way, personal
+mode-line configurations are not modified and all key bindings work as
+expected.  The process status (connecting, closed) is now shown in
+`mode-line-process'.
+
+** Customization of ERC variables has been made easier.  Variables
+have been split into more groups for better organization.
+
+** New variables
+
+  o `erc-send-whitespace-lines' - Set this to send lines even if they
+    are empty.
+
+  o `erc-manual-set-nick-on-bad-nick-p' - If the nickname you chose is
+    already taken or not allowed, your nick is not changed and you can
+    try again manually if this is non-nil.
+
+  o `erc-mode-line-away-status-format' - You can now set what is shown
+    in the mode-line when you are away.
+
+  o `erc-header-line-uses-help-echo-p' - The header-line now uses the
+    help-echo property. You can set this to nil to disable it.
+
+  o `erc-format-query-as-channel-p' - Set this to nil to have messages
+    in the query buffer formatted like private messages.
+
+  o `erc-show-channel-key-p' - The channel key is now shown with the
+    other channel modes in the header line. Set this to nil if you
+    want it hidden.
+
+  o `erc-prompt-for-channel-key' - Set this if you want to be prompted
+    for the channel key (channel's mode is +k) when you call
+    `erc-join-channel' interactively.
+
+  o `erc-kill-server-buffer-on-quit' - If non-nil, kill the server
+    buffer automatically when you quit.
+
+** New hooks
+
+  o `erc-join-hook' - Called when you join a channel.
+
+  o `erc-kick-hook' - Called when you are kicked from a channel. The
+    channel's buffer is sent as an argument to functions called from
+    this hook.
+
+  o `erc-nick-changed-functions' - Whenever your nickname changes
+    successfully, the functions in this hook are run with the
+    arguments NEW-NICK and OLD-NICK.
+
+** New command /WHOAMI - Do a /WHOIS on your current nickname.
+
+** The key binding for changing channel modes is now C-c C-o.
+
+** Removed variables
+
+  o `erc-echo-notices-in-minibuffer-flag' and
+    `erc-echo-notices-in-current-buffer' - You should use
+    `erc-echo-notice-hook' and `erc-echo-notice-always-hook' instead.
+
+  o `erc-prompt-interactive-input' has been removed (commented out)
+    because nickname completion does not work with it.
+
+  o All INFO buffer-related variables and functions have been removed.
+
+** You can now disable modules by setting `erc-modules' with the
+customization interface.
+
+** Changes and additions to modules
+
+*** Autoaway (erc-autoaway.el)
+
+**** New variable `erc-autoaway-no-auto-back-regexp' - Add text which,
+when you type anything matching it, will not automatically discard
+your away status when `erc-auto-discard-away' is non-nil.
+
+*** Filling (erc-fill.el)
+
+**** New variable `erc-fill-variable-maximum-indentation' - Don't
+indent more than this many characters when indenting a message from a
+user with a long nickname.
+
+*** Goodies (erc-goodies.el)
+
+**** Miscellaneous small modules have been moved from erc.el.
+The functions erc-add-scroll-to-bottom, erc-make-read-only,
+erc-send-distinguish-noncommands, erc-interpret-controls, erc-unmorse,
+erc-smiley, and erc-occur, which were defined in the main erc.el file
+have been moved to erc-goodies.el and have mostly been translated to
+the modules scrolltobottom, readonly, noncommands, irccontrols, smiley
+and unmorse.
+
+**** New variables
+
+  o `erc-input-line-position' - The line number to use with
+    `erc-scroll-to-bottom'.
+
+  o `erc-beep-p' - Beep if there is a \C-g control character in a
+    message.
+
+*** Channel lists (erc-list.el)
+
+**** New variable `erc-chanlist-highlight-face' - A face used for
+highlighting the current line.
+
+*** Highlighting (erc-match.el)
+
+**** `erc-current-nick-highlight-type' has new options: 'keyword and
+'nick-or-keyword.
+
+*** Menu (erc-menu.el)
+
+**** The `IRC' menu is now automatically added to `erc-mode' buffers.
+
+*** Networks (erc-nets.el)
+
+**** The functions for determining current network are in this file.
+There were a couple of functions spread about in different files which
+each had a different way of determining the current network.  The
+methods have been combined, and the big list of known networks
+(`erc-networks-alist') is being put to use.  You can access the
+network's name by calling the new function `erc-network'.  This
+returns the name of the current network as a symbol or 'Unknown if it
+could not determine which network it is.
+
+*** Nicklist (erc-nicklist.el)
+
+**** ERC has a new way of displaying nicknames in a channel.
+The new file erc-nicklist.el defines a new command `erc-nicklist'
+which pops up a small Emacs window showing the nicknames of all
+members of the current channel.  The implementation is not complete
+and is rather proof-of-concept for now.  The result is something a bit
+like erc-speedbar, but not quite as invasive, and doesn't require use
+of a new frame.
+
+*** Internet services / Nickserv (erc-nickserv.el)
+
+**** Network detection is now taken care of by erc-nets.el.
+The function `erc-current-network' is deprecated, use `erc-network'
+instead.  The variable `erc-networks' has been removed, use
+`erc-networks-alist'.  The network symbols used in
+`erc-nickserv-alist' now match those in `erc-networks-alist'.
+
+**** New variable `erc-nickserv-identify-mode' - Choose which method
+to use for automatic identification: you can wait for Nickserv to ask
+you to identify (the default), or send an identify message
+automatically after you change your nickname.
+
+*** Speedbar (erc-speedbar.el)
+
+**** New variable `erc-speedbar-sort-users-type' - Sort users in a
+channel by activity, alphabetically, or not at all.
+
+*** Timestamps (erc-stamp.el)
+
+**** `erc-timestamp-only-if-changed-flag' now works when
+`erc-insert-timestamp-function' is set to 'erc-insert-timestamp-left.
+
+**** New variable `erc-timestamp-intangible' - Set this to nil if
+timestamps should not have the 'intangible property.
+
+*** Channel tracking (erc-track.el)
+
+**** Using faces to indicate channel activity in the modeline now works
+in XEmacs.
+
+**** New variables
+
+  o `erc-track-priority-faces-only' - Ignore changes in a channel
+    unless there is a face from the `erc-track-faces-priority-list' in
+    the message.
+
+  o `erc-track-exclude-server-buffer' - Ignore changes in the server
+    buffer.
+
+  o `erc-track-position-in-mode-line' - Set the position in the
+    mode-line where modified channels are shown (only works in GNU
+    Emacs versions above 21.3).
+
+* Changes since ERC 3.0.cvs.20030119
+
+** The module system has again changed a lot.  You can now customize
+  the variable `erc-modules' and define once and for all which
+  extension modules you want to use.  This unfortunately may require
+  you to change your current erc initialisation code a bit, if you
+  have some existing customsations.  On the other hand, this change
+  makes the configuration of extension modules a lot easier for new
+  users.  In theory, you should be able to configure all aspects of
+  ERC by using the customize interface, you should no longer really
+  need to write Lisp code for trivial customizations.
+
+  By default, the following modules are now loaded: (pcomplete
+  netsplit fill track ring button autojoin)
+
+  Please use M-x customize-variable RET erc-modules RET to change the
+  default if it does not suite your needs.
+
+** THe symbol used in `erc-nickserv-passwords' for debian.org IRC servers
+  (formerly called OpenProjects, now FreeNode) has changed from
+  openprojects to freenode.  You may need to update your configuration
+  for a successful automatic nickserv identification.
+
+* Changes since ERC 2.93.cvs.20020819
+
+** New module erc-dcc:
+
+This finally implements DCC.  It requires server sockets to fully work
+in both directions.  This feature is currently only available in Emacs
+21.3.50 (CVS). Here is a short list of what should work though.
+
+** Compatibility:
+  * Emacs 21.2, DCC get, and accepting DCC chat offers.
+  * XEmacs 21, Only accepting DCC chat offers.
+
+** erc is switching to global-minor-modes for activation of submodules.
+
+This allows you to customize such a mode and get automatic loading of
+the module.  No longer putting a lot of require statments in .emacs.
+At least this is the long-term plan, not all modules are converted
+yet.
+
+** The most important user visible change is that you now need to activate
+erc-completion-mode, to get TAB completion.  The new completion code
+is based on pcomplete.  To get the old code, manually load
+erc-complete and bind TAB to erc-complete in erc-mode-map.
+
+To activate completion on startup, put (erc-completion-mode 1) in your
+.emacs file.
+
+Same applies to timestamps.  You no longer need to (require
+'erc-stamp), you can customize the variable `erc-timestamp-mode', and
+the rest should be automatic.
+
+arch-tag: 2b21b387-6cdc-4192-889c-6743cfffdcb1
--- a/etc/NEWS	Thu Jan 26 02:23:05 2006 +0000
+++ b/etc/NEWS	Wed Feb 01 10:07:17 2006 +0000
@@ -1447,9 +1447,10 @@
 +++
 *** The new command `multi-occur' is just like `occur', except it can
 search multiple buffers.  There is also a new command
-`multi-occur-by-filename-regexp' which allows you to specify the
-buffers to search by their filename.  Internally, Occur mode has been
-rewritten, and now uses font-lock, among other changes.
+`multi-occur-in-matching-buffers' which allows you to specify the
+buffers to search by their filenames or buffer names.  Internally,
+Occur mode has been rewritten, and now uses font-lock, among other
+changes.
 
 ** Grep changes:
 
@@ -1536,8 +1537,8 @@
 ** Xterm support:
 
 ---
-*** Emacs now responds to mouse-clicks on the mode-line, header-line and
-display margin, when run in an xterm.
+*** If you enable Xterm Mouse mode, Emacs will respond to mouse clicks
+on the mode line, header line and display margin, when run in an xterm.
 
 ---
 *** Improved key bindings support when running in an xterm.
@@ -1579,6 +1580,17 @@
 
 * New Modes and Packages in Emacs 22.1
 
+** ERC is now part of the Emacs distribution.
+
+ERC is a powerful, modular, and extensible IRC client for Emacs.
+
+To see what modules are available, type
+M-x customize-option erc-modules RET.
+
+To start an IRC session, type M-x erc-select, and follow the prompts
+for server, port, and nick.
+
+---
 ** Rcirc is now part of the Emacs distribution.
 
 Rcirc is an Internet relay chat (IRC) client.  It supports
--- a/etc/TODO	Thu Jan 26 02:23:05 2006 +0000
+++ b/etc/TODO	Wed Feb 01 10:07:17 2006 +0000
@@ -58,6 +58,8 @@
 
 ** Modify allout.el to use overlays, like outline.el.
 
+** M-! M-n should fetch the buffer-file-name as the default.
+
 * Important features:
 
 ** Provide user-friendly ways to list all available font families,
@@ -442,6 +444,13 @@
    For use by sml-mode, python-mode, tex-mode, scheme-mode, lisp-mode,
    haskell-mode, tuareg-mode, ...
 
+** Make SYNC_INPUT the default.
+   All loops using immediate_quit need to be checked to ensure that
+   C-g can interrupt them, in case of an infinite loop.  Once we
+   switch to using SYNC_INPUT, we can remove the BLOCK_INPUTs in the
+   allocation functions (allocate_string etc.) without worrying about
+   data munging.
+
 * Other known bugs:
 
 ** a two-char comment-starter whose two chars are symbol constituents will
--- a/info/dir	Thu Jan 26 02:23:05 2006 +0000
+++ b/info/dir	Wed Feb 01 10:07:17 2006 +0000
@@ -20,51 +20,54 @@
 
 * Menu:
 
-* Info: (info).		How to use the documentation browsing system.
+* Info: (info).         How to use the documentation browsing system.
 
 Emacs
-* Emacs: (emacs).	The extensible self-documenting text editor.
-* Emacs FAQ: (efaq).	Frequently Asked Questions about Emacs.
+* Emacs: (emacs).       The extensible self-documenting text editor.
+* Emacs FAQ: (efaq).    Frequently Asked Questions about Emacs.
 * Emacs Lisp Introduction: (eintr).
-  			A simple introduction to Emacs Lisp programming.
-* Elisp: (elisp).	The Emacs Lisp Reference Manual.
+                        A simple introduction to Emacs Lisp programming.
+* Elisp: (elisp).       The Emacs Lisp Reference Manual.
 
-* CL: (cl).		Partial Common Lisp support for Emacs Lisp.
+* CL: (cl).             Partial Common Lisp support for Emacs Lisp.
 * Dired-X: (dired-x).   Dired Extra Features.
-* Ediff: (ediff).	A visual interface for comparing and merging programs.
+* Ediff: (ediff).       A visual interface for comparing and merging programs.
 * Emacs-Xtra: (emacs-xtra).    Specialized Emacs features.
-* Org Mode: (org).	Outline-based notes management and organizer.
-* PCL-CVS: (pcl-cvs).	Emacs front-end to CVS.
-* Speedbar: (speedbar).	File/Tag summarizing utility.
+* Org Mode: (org).      Outline-based notes management and organizer.
+* PCL-CVS: (pcl-cvs).   Emacs front-end to CVS.
+* Speedbar: (speedbar). File/Tag summarizing utility.
 
 * Ada mode: (ada-mode). Emacs mode for editing Ada code.
-* CC mode: (ccmode).	Emacs mode for editing C, C++, Objective-C,
-			  Java, Pike, and IDL code.
-* Ebrowse: (ebrowse).	A C++ class browser for Emacs.
+* CC mode: (ccmode).    Emacs mode for editing C, C++, Objective-C,
+                          Java, Pike, and IDL code.
+* Ebrowse: (ebrowse).   A C++ class browser for Emacs.
+* ERC: (erc).           Powerful, modular, and extensible IRC client
+                          for Emacs.
 * Flymake: (flymake).   An on-the-fly syntax checker for Emacs.
-* IDLWAVE: (idlwave).	Major mode and shell for IDL and WAVE/CL files.
+* IDLWAVE: (idlwave).   Major mode and shell for IDL and WAVE/CL files.
 
-* Gnus: (gnus).		The news reader Gnus.
-* Message: (message).	Mail and news composition mode that goes with Gnus.
-* MH-E: (mh-e).		Emacs interface to the MH mail system.
+* Gnus: (gnus).         The news reader Gnus.
+* Message: (message).   Mail and news composition mode that goes with Gnus.
+* MH-E: (mh-e).         Emacs interface to the MH mail system.
 * MIME: (emacs-mime).   Emacs MIME de/composition library.
 * Newsticker: (newsticker).   A News ticker for Emacs.
-* PGG: (pgg).   	Emacs interface to various PGP implementations.
-* SC: (sc).		Supercite lets you cite parts of messages you're
-			  replying to, in flexible ways.
+* PGG: (pgg).           Emacs interface to various PGP implementations.
+* Rcirc: (rcirc).       Internet Relay Chat (IRC) client.
+* SC: (sc).             Supercite lets you cite parts of messages you're
+                          replying to, in flexible ways.
 * SMTP: (smtpmail).     Emacs library for sending mail via SMTP.
 * Sieve: (sieve).       Managing Sieve scripts in Emacs.
 
 * Autotype: (autotype). Convenient features for text that you enter frequently
                           in Emacs.
-* Calc: (calc). 	Advanced desk calculator and mathematical tool.
-* Eshell: (eshell).	A command shell implemented in Emacs Lisp.
-* EUDC: (eudc).		An Emacs client for directory servers (LDAP, PH).
-* Forms: (forms).	Emacs package for editing data bases
-			  by filling in forms.
-* RefTeX: (reftex).	Emacs support for LaTeX cross-references and citations.
+* Calc: (calc).         Advanced desk calculator and mathematical tool.
+* Eshell: (eshell).     A command shell implemented in Emacs Lisp.
+* EUDC: (eudc).         An Emacs client for directory servers (LDAP, PH).
+* Forms: (forms).       Emacs package for editing data bases
+                          by filling in forms.
+* RefTeX: (reftex).     Emacs support for LaTeX cross-references and citations.
 * SES: (ses).           Simple Emacs Spreadsheet
-* Tramp: (tramp).	Transparent Remote (file) Access, Multiple Protocol.
+* Tramp: (tramp).       Transparent Remote (file) Access, Multiple Protocol.
                           Edit remote files via a remote shell (rsh,
                           ssh, telnet).
 * URL: (url).           URL loading package.
@@ -75,4 +78,4 @@
 * VIPER: (viper).       The newest Emacs VI-emulation mode.
                           (also, A VI Plan for Emacs Rescue
                            or the VI PERil.)
-* VIP: (vip).		An older VI-emulation for Emacs.
+* VIP: (vip).           An older VI-emulation for Emacs.
--- a/lisp/ChangeLog	Thu Jan 26 02:23:05 2006 +0000
+++ b/lisp/ChangeLog	Wed Feb 01 10:07:17 2006 +0000
@@ -1,3 +1,189 @@
+2006-01-31  Richard M. Stallman  <rms@gnu.org>
+
+	* replace.el (multi-occur): Doc fix.
+	(multi-occur-in-matching-buffers): Renamed from
+	multi-occur-by-filename-regexp.  Prefix arg says match
+	buffer names instead of file names.
+
+2006-01-31  Juanma Barranquero  <lekktu@gmail.com>
+
+	* bs.el: Allow non-default values of `bs-header-lines-length'.
+	(bs--running-in-xemacs): Remove (not needed anymore).
+	(bs--set-window-height): Simplify by using `fit-window-to-buffer'
+	instead of `shrink-window', thus avoiding having to compute the
+	height of the window.
+	(bs--up): Wrap around even when there's no header.
+	(bs--down): Use `forward-line' instead of `next-line'.
+
+2006-01-30  Chong Yidong  <cyd@stupidchicken.com>
+
+	* image-mode.el (image-toggle-display): Use file name if possible,
+	instead of unnecessarily allocating a (possibly huge) lisp string.
+
+2006-01-30  John Paul Wallington  <jpw@pobox.com>
+
+	* subr.el (toplevel): Define `cl-assertion-failed' condition here
+	because the `assert' macro signals it at runtime.
+
+	* emacs-lisp/cl.el (toplevel): Remove definition of
+	`cl-assertion-failed' condition.
+
+2006-01-30  Nick Roberts  <nickrob@snap.net.nz>
+
+	* thumbs.el (thumbs-marked-list): Make buffer-local and
+	permanent-local.
+	(thumbs-insert-thumb): Make help-echo non-sticky.
+	(thumbs-file-alist): Use eolp as check for (non)-image.
+
+2006-01-30  Juanma Barranquero  <lekktu@gmail.com>
+
+	* ediff-mult.el (ediff-meta-buffer-keymap-setup-hook)
+	(ediff-before-session-group-setup-hooks)
+	(ediff-default-filtering-regexp, ediff-meta-mark-equal-files):
+	Fix typos in docstrings.
+
+	* window.el (bw-dir, bw-eqdir, balance-windows)
+	(split-window-keep-point): Fix typos in docstrings.
+
+	* textmodes/org.el (org-allow-space-in-links, org-closed-string)
+	(org-quote-string, org-calendar-to-agenda-key)
+	(org-agenda-sorting-strategy, org-agenda-use-time-grid)
+	(org-show-following-heading, org-tags-column)
+	(org-use-tag-inheritance, org, org-allow-space-in-links)
+	(org-usenet-links-prefer-google, org-file-apps-defaults-gnu)
+	(org-enable-table-editor, org-calc-default-modes)
+	(org-table-allow-automatic-line-recalculation)
+	(org-export-html-style, org-export-with-fixed-width)
+	(org-export-with-sub-superscripts, org-special-keyword)
+	(org-formula, org-time-grid, org-table-may-need-update)
+	(org-mode, org-goto-ret, org-goto-left, org-goto-right)
+	(org-goto-quit, org-get-indentation, org-end-of-item)
+	(org-move-item-down, org-move-item-up)
+	(org-renumber-ordered-list, org-todo, org-log-done, org-occur)
+	(org-remove-occur-highlights, org-read-date, org-goto-calendar)
+	(org-agenda, org-agenda-day-view, org-agenda-previous-date-line)
+	(org-agenda-log-mode, org-agenda-toggle-diary)
+	(org-agenda-toggle-time-grid, org-agenda-cleanup-fancy-diary)
+	(org-agenda-file-to-end, org-agenda-no-heading-message)
+	(org-agenda-get-closed, org-format-agenda-item)
+	(org-cmp-priority, org-cmp-category, org-cmp-time)
+	(org-agenda-change-all-lines, org-agenda-diary-entry)
+	(org-scan-tags, org-after-todo-state-change-hook, org-tags-view)
+	(org-link-search, org-camel-to-words, org-open-file)
+	(org-remember-handler, org-table-convert-region)
+	(org-table-move-row-down, org-table-move-row-up)
+	(org-table-copy-region, org-table-wrap-region)
+	(org-table-toggle-vline-visibility)
+	(org-table-get-vertical-vector, org-table-modify-formulas)
+	(org-table-get-specials, org-recalc-commands)
+	(org-table-rotate-recalc-marks, org-table-eval-formula)
+	(orgtbl-make-binding, org-in-invisibility-spec-p, org-cycle)
+	(org-level-color-stars-only, org-insert-heading):
+	Fix typos in docstrings.
+	(last-arg): Add defvar.
+
+	* makefile.w32-in (WINS): Add erc.
+	(MH_E_SRC): Update (copied from lisp/Makefile.in).
+
+2006-01-29  Bill Wohler  <wohler@newt.com>
+
+	* Makefile.in (MH_E_SRC): Add mh-compat.el, mh-folder.el,
+	mh-letter.el, mh-limit.el, mh-scan.el, mh-show.el, mh-thread.el,
+	mh-tool-bar.el, mh-xface.el.  Remove mh-customize.el, mh-init.el.
+	(mh-autoloads): Don't use comments on otherwise empty lines.
+
+2006-01-29  Edward O'Connor  <ted@oconnor.cx>
+
+	* emulation/viper.el (viper-major-mode-modifier-list): Add
+	insert-state and vi-state entries for erc-mode.
+	(viper-go-away, viper-set-hooks): Add and remove
+	viper-comint-mode-hook from erc-mode-hook as appropriate.
+
+	* emulation/viper.el (viper-insert-state-mode-list): Add erc-mode.
+
+2006-01-29  Juanma Barranquero  <lekktu@gmail.com>
+
+	* bs.el (bs--format-aux): Implement `middle' alignment as
+	described in the docstring for `bs-attributes-list'.
+	(bs--get-name): Simplify.  Don't pad the buffer name.
+
+2006-01-27  Agustin Martin  <agustin.martin@hispalinux.es>
+
+	* textmodes/ispell.el (ispell-find-aspell-dictionaries): If no
+	English aspell dictionary is installed, use the first entry of
+	ispell-dictionary-alist-1.
+
+2006-01-27  Kevin Rodgers  <ihs_4664@yahoo.com>
+
+	* textmodes/flyspell.el (flyspell-incorrect, flyspell-duplicate):
+	Doc fix.
+
+2006-01-27  Michael Albinus  <michael.albinus@gmx.de>
+
+	* net/tramp-vc.el (vc-user-login-name): Wrap defadvice with a test
+	for `process-file', in order to let it work for older Emacsen too.
+
+2006-01-27  Eli Zaretskii  <eliz@gnu.org>
+
+	* international/latexenc.el: Add a suitable `coding:' tag.
+	(latexenc-find-file-coding-system): Undo last change.
+
+2006-01-27  Arne J,bx(Brgensen  <arne@arnested.dk>
+
+	* international/latexenc.el (latexenc-find-file-coding-system):
+	Make sure latexenc-main-file is a regular file and is readable.
+
+2006-01-27  Andre Spiegel  <spiegel@gnu.org>
+
+	* vc-rcs.el (vc-rcs-fetch-master-state, vc-rcs-consult-headers):
+	Pass FILE to vc-user-login-name.
+
+	* vc-sccs.el (vc-sccs-state): Pass FILE to vc-user-login-name.
+
+2006-01-27  Nick Roberts  <nickrob@snap.net.nz>
+
+	* thumbs.el (thumbs-do-thumbs-insertion): Suppress message when
+	there are no more images to display.
+	(thumbs-mark, thumbs-unmark): Revert change so that they move to
+	the next image.
+
+2006-01-26  Richard M. Stallman  <rms@gnu.org>
+
+	* cus-edit.el (custom-mode): Doc: Use advertised-widget-backward.
+
+	* wid-edit.el (advertised-widget-backward): New alias.
+	(widget-keymap): Use advertised-widget-backward for S-TAB.
+
+	* tumme.el: Correct the keywords.
+	(tumme-dir-max-size): Use defvar.
+	(tumme-setup-dired-keybindings, tumme-dired): Add autoload cookie.
+
+	* simple.el (move-beginning-of-line): Take account of fields.
+	(clone-indirect-buffer-other-window): Take args like
+	clone-indirect-buffer, and work like it.
+
+	* help-fns.el (describe-function): Don't pass `nil' as default.
+
+	* files.el (risky-local-variable-p): Follow var aliases.
+
+	* subr.el (lazy-completion-table): Doc fix.
+
+	* mail/rmailsum.el (rmail-make-summary-line-1): Don't set
+	global binding of `line'.
+
+2006-01-25  Andre Spiegel  <spiegel@gnu.org>
+
+	* vc-hooks.el (vc-user-login-name): Rewritten to handle access via
+	Tramp.
+
+	* vc.el (vc-default-dired-state-info): Pass FILE to
+	vc-user-login-name.
+	(vc-default-update-changelog): Don't use vc-user-login-name, we
+	don't need it here.
+
+	* tramp-vc.el (vc-user-login-name): Comment out defadvice, it is
+	no longer necessary.
+
 2006-01-25  Kenichi Handa  <handa@m17n.org>
 
 	* international/mule.el (decode-char): Avoid the overhead of
@@ -64,8 +250,8 @@
 
 	* thumbs.el (thumbs-extra-images): New variable.  Make it buffer-local
 	and permanent-local.
-	(thumbs-max-image-number): New variable.  Make it
-	(thumbs-do-thumbs-insertion): Use them
+	(thumbs-max-image-number): New variable.
+	(thumbs-do-thumbs-insertion): Use them.
 	(thumbs-per-line): Change default to 4.
 	(thumbs-marked-list): Rename from thumbs-markedL.
 	(thumbs-cleanup-thumbsdir, thumbs-delete-images)
@@ -1949,7 +2135,7 @@
 	(hi-lock-find-patterns, hi-lock-font-lock-hook):
 	Replace hi-lock-buffer-mode with hi-lock-mode.
 
-2005-12-10  Kevin Rodgers  <ihs_4664@ihs.com>
+2005-12-10  Kevin Rodgers  <ihs_4664@yahoo.com>
 
 	* emacs-lisp/lisp.el (lisp-complete-symbol): Regenerate the
 	completion list, even after a partial completion has been
--- a/lisp/Makefile.in	Thu Jan 26 02:23:05 2006 +0000
+++ b/lisp/Makefile.in	Wed Feb 01 10:07:17 2006 +0000
@@ -223,19 +223,23 @@
 # the autoloads for the MH-E entry points, which are already in
 # loaddefs.el.
 MH_E_SRC = $(lisp)/mh-e/mh-acros.el $(lisp)/mh-e/mh-alias.el	\
-	$(lisp)/mh-e/mh-buffers.el $(lisp)/mh-e/mh-comp.el	\
-	$(lisp)/mh-e/mh-customize.el $(lisp)/mh-e/mh-e.el	\
-	$(lisp)/mh-e/mh-funcs.el $(lisp)/mh-e/mh-identity.el	\
-	$(lisp)/mh-e/mh-inc.el $(lisp)/mh-e/mh-init.el		\
-	$(lisp)/mh-e/mh-junk.el $(lisp)/mh-e/mh-mime.el		\
-	$(lisp)/mh-e/mh-print.el $(lisp)/mh-e/mh-search.el	\
-	$(lisp)/mh-e/mh-seq.el $(lisp)/mh-e/mh-speed.el		\
-	$(lisp)/mh-e/mh-utils.el
+	$(lisp)/mh-e/mh-buffers.el $(lisp)/mh-e/mh-compat.el	\
+	$(lisp)/mh-e/mh-comp.el $(lisp)/mh-e/mh-e.el		\
+	$(lisp)/mh-e/mh-folder.el $(lisp)/mh-e/mh-funcs.el	\
+	$(lisp)/mh-e/mh-gnus.el $(lisp)/mh-e/mh-identity.el	\
+	$(lisp)/mh-e/mh-inc.el $(lisp)/mh-e/mh-junk.el		\
+	$(lisp)/mh-e/mh-letter.el $(lisp)/mh-e/mh-limit.el	\
+	$(lisp)/mh-e/mh-mime.el $(lisp)/mh-e/mh-print.el	\
+	$(lisp)/mh-e/mh-scan.el $(lisp)/mh-e/mh-search.el	\
+	$(lisp)/mh-e/mh-seq.el $(lisp)/mh-e/mh-show.el		\
+	$(lisp)/mh-e/mh-speed.el $(lisp)/mh-e/mh-thread.el	\
+	$(lisp)/mh-e/mh-tool-bar.el $(lisp)/mh-e/mh-utils.el	\
+	$(lisp)/mh-e/mh-xface.el
 
 mh-autoloads: $(lisp)/mh-e/mh-loaddefs.el
 $(lisp)/mh-e/mh-loaddefs.el: $(MH_E_SRC)
 	echo ";;; mh-loaddefs.el --- automatically extracted autoloads" > $@
-	echo ";;" >> $@
+	echo "" >> $@
 	echo ";; Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation, Inc." >> $@
 	echo ";; Author: Bill Wohler <wohler@newt.com>" >> $@
 	echo ";; Keywords: mail" >> $@
--- a/lisp/bs.el	Thu Jan 26 02:23:05 2006 +0000
+++ b/lisp/bs.el	Wed Feb 01 10:07:17 2006 +0000
@@ -180,9 +180,6 @@
   :group 'bs-appearance
   :type '(repeat sexp))
 
-(defvar bs--running-in-xemacs (string-match "XEmacs" (emacs-version))
-  "Non-nil when running under XEmacs.")
-
 (defun bs--make-header-match-string ()
   "Return a regexp matching the first line of a Buffer Selection Menu buffer."
   (let ((res "^\\(")
@@ -701,12 +698,7 @@
 (defun bs--set-window-height ()
   "Change the height of the selected window to suit the current buffer list."
   (unless (one-window-p t)
-    (shrink-window (- (window-height (selected-window))
-		      ;; window-height in xemacs includes mode-line
-		      (+ (if bs--running-in-xemacs 3 1)
-			 bs-header-lines-length
-			 (min (length bs-current-list)
-			      bs-max-window-height))))))
+    (fit-window-to-buffer (selected-window) bs-max-window-height)))
 
 (defun bs--current-buffer ()
   "Return buffer on current line.
@@ -1011,13 +1003,11 @@
   "Move cursor vertically up one line.
 If on top of buffer list go to last line."
   (interactive "p")
-  (previous-line 1)
-  (if (<= (count-lines 1 (point)) (1- bs-header-lines-length))
-      (progn
-	(goto-char (point-max))
-	(beginning-of-line)
-	(recenter -1))
-    (beginning-of-line)))
+  (if (> (count-lines 1 (point)) bs-header-lines-length)
+      (forward-line -1)
+    (goto-char (point-max))
+    (beginning-of-line)
+    (recenter -1)))
 
 (defun bs-down (arg)
   "Move cursor vertically down ARG lines in Buffer Selection Menu."
@@ -1029,10 +1019,9 @@
 (defun bs--down ()
   "Move cursor vertically down one line.
 If at end of buffer list go to first line."
-  (let ((last (line-end-position)))
-    (if (eq last (point-max))
-	(goto-line (1+ bs-header-lines-length))
-      (next-line 1))))
+  (if (eq (line-end-position) (point-max))
+      (goto-line (1+ bs-header-lines-length))
+    (forward-line 1)))
 
 (defun bs-visits-non-file (buffer)
   "Return t or nil whether BUFFER visits no file.
@@ -1332,17 +1321,9 @@
 for mouse highlighting.
 START-BUFFER is the buffer where we started buffer selection.
 ALL-BUFFERS is the list of buffer appearing in Buffer Selection Menu."
-  (let ((name (copy-sequence (buffer-name))))
-    (add-text-properties
-     0 (length name)
-     '(mouse-face highlight
-       help-echo
-       "mouse-2: select this buffer, mouse-3: select in other frame")
-     name)
-    (if (< (length name) bs--name-entry-length)
-	(concat name
-		(make-string (- bs--name-entry-length (length name)) ? ))
-      name)))
+  (propertize (buffer-name)
+              'help-echo "mouse-2: select this buffer, mouse-3: select in other frame"
+              'mouse-face 'highlight))
 
 (defun bs--get-mode-name (start-buffer all-buffers)
   "Return the name of mode of current buffer for Buffer Selection Menu.
@@ -1399,12 +1380,12 @@
 (defun bs--format-aux (string align len)
   "Generate a string with STRING with alignment ALIGN and length LEN.
 ALIGN is one of the symbols `left', `middle', or `right'."
-  (let ((length (length string)))
-    (if (>= length len)
-	string
-      (if (eq 'right align)
-	  (concat (make-string (- len length) ? ) string)
-	(concat string (make-string (- len length) ? ))))))
+  (let* ((width (length string))
+         (len (max len width)))
+    (format (format "%%%s%ds" (if (eq align 'right) "" "-") len)
+            (if (eq align 'middle)
+                (concat (make-string (/ (- len width) 2) ?\s) string)
+              string))))
 
 (defun bs--show-header ()
   "Insert header for Buffer Selection Menu in current buffer."
--- a/lisp/cus-edit.el	Thu Jan 26 02:23:05 2006 +0000
+++ b/lisp/cus-edit.el	Wed Feb 01 10:07:17 2006 +0000
@@ -4417,7 +4417,7 @@
 
 \\<widget-keymap>\
 Move to next button, link or editable field.     \\[widget-forward]
-Move to previous button, link or editable field. \\[widget-backward]
+Move to previous button, link or editable field. \\[advertised-widget-backward]
 \\<custom-field-keymap>\
 Complete content of editable text field.   \\[widget-complete]
 \\<custom-mode-map>\
--- a/lisp/ediff-mult.el	Thu Jan 26 02:23:05 2006 +0000
+++ b/lisp/ediff-mult.el	Wed Feb 01 10:07:17 2006 +0000
@@ -176,7 +176,7 @@
 
 (defcustom ediff-default-filtering-regexp nil
   "The default regular expression used as a filename filter in multifile comparisons.
-Should be a sexp. For instance (car ediff-filtering-regexp-history) or nil."
+Should be a sexp.  For instance (car ediff-filtering-regexp-history) or nil."
   :type 'sexp
   :group 'ediff-mult)
 
@@ -219,9 +219,9 @@
 
 (defcustom ediff-before-session-group-setup-hooks nil
   "*Hooks to run before Ediff arranges the window for group-level operations.
-It is used by commands such as ediff-directories.
+It is used by commands such as `ediff-directories'.
 This hook can be used to save the previous window config, which can be restored
-on ediff-quit, ediff-suspend, or ediff-quit-session-group-hook."
+on `ediff-quit', `ediff-suspend', or `ediff-quit-session-group-hook'."
   :type 'hook
   :group 'ediff-hook)
 (defcustom ediff-after-session-group-setup-hook nil
@@ -242,7 +242,7 @@
   :type 'hook
   :group 'ediff-mult)
 (defcustom ediff-meta-buffer-keymap-setup-hook nil
-  "*Hooks run just after setting up the ediff-meta-buffer-map.
+  "*Hooks run just after setting up the `ediff-meta-buffer-map'.
 This keymap controls key bindings in the meta buffer and is a local variable.
 This means that you can set different bindings for different kinds of meta
 buffers."
@@ -363,7 +363,7 @@
 	   (file-directory-p (ediff-get-session-objC-name session-info)) t)))
 
 ;; set up the keymap in the meta buffer
-(defun ediff-setup-meta-map()
+(defun ediff-setup-meta-map ()
   (setq ediff-meta-buffer-map (make-sparse-keymap))
   (suppress-keymap ediff-meta-buffer-map)
   (define-key ediff-meta-buffer-map "q" 'ediff-quit-meta-buffer)
@@ -2332,8 +2332,8 @@
   "Run through the session list and mark identical files.
 This is used only for sessions that involve 2 or 3 files at the same time.
 ACTION is an optional argument that can be ?h, ?m, ?=, to mark for hiding, mark
-for operation, or simply indicate which are equal files. If it is nil, then
-last-command-char is used to decide which action to take."
+for operation, or simply indicate which are equal files.  If it is nil, then
+`last-command-char' is used to decide which action to take."
   (interactive)
   (if (null action)
       (setq action last-command-char))
--- a/lisp/emacs-lisp/cl.el	Thu Jan 26 02:23:05 2006 +0000
+++ b/lisp/emacs-lisp/cl.el	Wed Feb 01 10:07:17 2006 +0000
@@ -580,9 +580,6 @@
 
 ;;; Miscellaneous.
 
-(put 'cl-assertion-failed 'error-conditions '(error))
-(put 'cl-assertion-failed 'error-message "Assertion failed")
-
 (defvar cl-fake-autoloads nil
   "Non-nil means don't make CL functions autoload.")
 
--- a/lisp/emulation/viper.el	Thu Jan 26 02:23:05 2006 +0000
+++ b/lisp/emulation/viper.el	Wed Feb 01 10:07:17 2006 +0000
@@ -458,6 +458,7 @@
   '(internal-ange-ftp-mode
     comint-mode
     inferior-emacs-lisp-mode
+    erc-mode
     eshell-mode
     shell-mode)
   "*A list of major modes that should come up in Vi Insert state."
@@ -494,6 +495,8 @@
     (gnus-summary-mode emacs-state viper-gnus-modifier-map)
     (Info-mode emacs-state viper-slash-and-colon-map)
     (Buffer-menu-mode emacs-state viper-slash-and-colon-map)
+    (erc-mode insert-state viper-comint-mode-modifier-map)
+    (erc-mode vi-state viper-comint-mode-modifier-map)
     )
   "List specifying how to modify the various major modes to enable some Viperisms.
 The list has the structure: ((mode viper-state keymap) (mode viper-state
@@ -768,6 +771,7 @@
   ;; remove all hooks set by viper
   (mapatoms 'viper-remove-hooks)
   (remove-hook 'comint-mode-hook 'viper-comint-mode-hook)
+  (remove-hook 'erc-mode-hook 'viper-comint-mode-hook)
   (remove-hook 'minibuffer-setup-hook 'viper-minibuffer-setup-sentinel)
   (remove-hook 'change-major-mode-hook 'viper-major-mode-change-sentinel)
   (remove-hook 'post-command-hook 'viper-minibuffer-post-command-hook)
@@ -913,6 +917,7 @@
 
   ;; Emacs shell, ange-ftp, and comint-based modes
   (add-hook 'comint-mode-hook 'viper-comint-mode-hook) ; comint
+  (add-hook 'erc-mode-hook 'viper-comint-mode-hook) ; ERC
 
   (add-hook 'eshell-mode-hook
 	    (lambda () (setq viper-auto-indent nil)))
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lisp/erc/.cvsignore	Wed Feb 01 10:07:17 2006 +0000
@@ -0,0 +1,3 @@
+{arch}
+.arch-ids
+*.elc
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lisp/erc/ChangeLog	Wed Feb 01 10:07:17 2006 +0000
@@ -0,0 +1,371 @@
+2006-01-30  Simon Josefsson  <jas@extundo.com>
+
+	* erc.el (erc-open-ssl-stream): Use tls.el.
+
+2006-01-30  Michael Olson  <mwolson@gnu.org>
+
+	* erc-stamp.el (erc-timestamp-right-align-by-pixel): New option
+	that determines whether to use pixel values to align right
+	timestamps.  The default is not to do so, since it only works with
+	Emacs22 on X, and even then some people have trouble.
+	(erc-insert-aligned): Use `erc-timestamp-right-align-by-pixel'.
+
+2006-01-29  Michael Olson  <mwolson@gnu.org>
+
+	* ChangeLog, ChangeLog.2005, ChangeLog.2004, ChangeLog.2003,
+	ChangeLog.2002, ChangeLog.2001: Add "See ChangeLog.NNNN" line for
+	earlier changes.  Use utf-8 encoding.  Fix some accent typos.
+
+	* erc-speedbar.el (erc-speedbar-buttons): Fix reference to free
+	variable.
+	(erc-speedbar-goto-buffer): Fix compiler warning.
+
+	* erc-ibuffer.el: Use `define-ibuffer-filter' instead of
+	`ibuffer-degine-limiter'.  Use `define-ibuffer-column' instead of
+	`ibuffer-define-column'.  Require 'ibuf-ext so that the macros
+	work without compiler warnings.
+
+	* man/erc.texi (Obtaining ERC, Installation): Note that these
+	sections may be skipped if using the version of ERC that comes
+	with Emacs.
+
+2006-01-29  Edward O'Connor  <ted@oconnor.cx>
+
+	* erc-viper.el: Remove. Now that ERC is included in Emacs, these
+	work-arounds live in Viper itself.
+
+2006-01-28  Michael Olson  <mwolson@gnu.org>
+
+	* erc-*.el, erc.texi, NEWS: Add Arch taglines as per Emacs
+	guidelines.
+
+	* erc-*.el: Space out copyright years like the rest of Emacs.  Use
+	the Emacs copyright statement.  Refer to ourselves as ERC rather
+	than "Emacs IRC Client", since there are now several IRC clients
+	for Emacs.
+
+	* erc-compat.el (erc-emacs-build-time): Define as a variable.
+
+	* erc-log.el (erc-log-setup-logging): Use write-file-functions.
+
+	* erc-ibuffer.el: Require 'erc.
+
+	* erc-stamp.el (erc-insert-aligned): Only use the special text
+	property when window-system is X.
+
+	* erc.texi: Adapt for inclusion in Emacs.
+
+2006-01-28  Johan Bockgård  <bojohan@users.sourceforge.net>
+
+	* erc.el (erc-format-message): More `cl' breakage; don't use
+	`oddp'.
+
+2006-01-27  Michael Olson  <mwolson@gnu.org>
+
+	* debian/changelog: Update for new release.
+
+	* debian/control (Description): Update.
+
+	* debian/rules: Concatenate ChangeLog for 2005.
+
+	* Makefile (MISC): Include ChangeLog.2005 and erc.texi.
+	(debrelease, release): Copy images directory.
+
+	* NEWS: Spelling fixes.  Add items for recent changes.
+
+	* erc.el (erc): Move call to erc-update-modules before the call to
+	erc-mode.  This should fix a timestamp display issue.
+	(erc-version-string): Release ERC 5.1.
+
+2006-01-26  Michael Olson  <mwolson@gnu.org>
+
+	* erc-stamp.el (erc-insert-aligned): New function that inserts
+	text in an perfectly-aligned way relative to the right margin.  It
+	only works well with Emacs22.  A sane fallback is provided for
+	other versions of Emacs.
+	(erc-insert-timestamp-right): Use the new function.
+
+2006-01-25  Edward O'Connor  <ted@oconnor.cx>
+
+	* erc.el (erc-modules): Ensure that `erc-button-mode' gets enabled
+	before `erc-match-mode'.
+
+	* erc-match.el (match): Append `erc-match-message' to
+	`erc-insert-modify-hook'.
+
+2006-01-25  Michael Olson  <mwolson@gnu.org>
+
+	* FOR-RELEASE: Mark last release requirement as done.
+
+	* Makefile (realclean, distclean): Remove docs.
+
+	* erc.texi: Take care of all pre-5.1 items.
+
+	* erc-backend.el (erc-server-send, erc-server-send-queue): Wrap
+	`process-send-string' in `condition-case' to avoid an error when
+	quitting ERC.
+
+	* erc-stamp.el (erc-insert-timestamp-right): Try to deal with
+	variable-width characters in the timestamp and on the same line.
+	The latter is a kludge, but it seems to work with most of the
+	input I've thrown at it so far.  It's certainly better than going
+	past the end of line consistently when we have variable-width
+	characters on the same line.  When `erc-timestamp-intangible' is
+	non-nil, add intangible properties to the whitespace as well, so
+	that hitting <end> does what you'd expect.
+
+	* erc.el (erc-flood-protect, erc-toggle-flood-control): Update
+	this to only use boolean values for `erc-flood-protect'.  Update
+	documentation.
+	(erc-cmd-QUIT): Set the active buffer to be the server buffer, so
+	that any QUIT-related messages go there.
+	(erc): Try to be more clever about re-using channel buffers when
+	automatically re-connecting.  Thanks to e1f for noticing.
+
+2006-01-23  Michael Olson  <mwolson@gnu.org>
+
+	* ChangeLog.2005: Remove erroneous line.
+
+	* FOR-RELEASE: Make that the Makefile tweaking is complete.
+	(NEWS): Mark as done.
+
+	* Makefile (MANUAL): New option indicating the name of the manual.
+	(PREFIX, ELISPDIR, INFODIR): New options that specify the
+	directories to install lisp code and info manuals to.  PREFIX is
+	used only by ELISPDIR and INFODIR.
+	(all): Call `lisp' and create the manual.
+	(lisp): Compile lisp code.
+	(%.info, %.html): New rules that make Info files and HTML files,
+	respectively, from a TexInfo source.
+	(doc): Create both the Info and HTML versions of the manual.  This
+	is for the user -- we never call it automatically.
+	(install-info): Install Info files.
+	(install-bin): Install compiled and source Lisp files.
+	(todo): Remove, since it seems pointless.
+
+	* NEWS: Update.
+
+	* README: Add Installation instructions.  Tweak layout.
+
+	* erc.texi: Work on some pre-5.1 items.
+
+	* erc-stamp.el, erc-track.el: Move some functions and options in
+	order to get rid of a few compiler warnings.
+
+	* erc.el (erc-modules): Enable readonly by default.  This will
+	prevent new users from accidentally removing old messages, which
+	could be disconcerting.  Also enable stamp by default, since
+	timestamps are a fairly standard feature among IRC clients.
+
+	* erc-button.el: Munge whitespace.
+
+	* erc-identd.el (erc-identd-start): Instead of throwing an error,
+	just try to use the obsolete function.
+
+2006-01-22  Michael Olson  <mwolson@gnu.org>
+
+	* erc-backend.el (erc-decode-string-from-target): Make sure that
+	we have a string as an argument.  If not, coerce it to the empty
+	string.  Hopefully, this will work painlessly around an edge case
+	related to quitting ERC around the same time a message comes in.
+
+2006-01-22  Johan Bockgård  <bojohan@users.sourceforge.net>
+
+	* erc-track.el: Use `(eval-when-compile (require 'cl))' (for
+	`case'). Doc fixes.
+	(erc-find-parsed-property): Simplify.
+	(erc-track-get-active-buffer): Fix logic. Simplify.
+	(erc-track-switch-buffer): Remove unused variable `dir'. Simplify.
+
+	* erc-speak.el: Doc fixes.
+	(erc-speak-region): `propertize' --> `erc-propertize'.
+
+	* erc-dcc.el (erc-dcc-chat-parse-output): `propertize' -->
+	`erc-propertize'.
+
+	* erc-button.el (erc-button-add-button): Take erc-fill-prefix into
+	account when wrapping URLs.
+
+	* erc-bbdb.el (erc-bbdb-elide-display): Doc fix.
+
+	* erc-backend.el (define-erc-response-handler): Doc fix.
+
+2006-01-22  Michael Olson  <mwolson@gnu.org>
+
+	* erc.el (erc-update-modules): Use `require' instead of `load',
+	but prevent it from causing errors, in order to preserve the
+	previous behavior.
+
+2006-01-21  Michael Olson  <mwolson@gnu.org>
+
+	* FOR-RELEASE (Source): Mark cl task as done.
+
+	* Makefile (erc-auto.el): Call erc-generate-autoloads rather than
+	generate-autoloads.
+	(erc-auto.el, %.elc): Don't show command, just its output.
+
+	* NEWS: Add items from 2005-01-01 to 2005-08-13.
+
+	* debian/copyright (Copyright): Update.
+
+	* erc-auto.in (erc-generate-autoloads): Rename from
+	generate-autoloads.
+
+	* erc.el, erc-autoaway.el, erc-backend.el: Use
+	erc-server-process-alive instead of erc-process-alive.
+
+	* erc.el, erc-backend.el, erc-ezbounce.el, erc-list.el,
+	erc-log.el, erc-match.el, erc-nets.el, erc-netsplit.el,
+	erc-nicklist.el, erc-nickserv.el, erc-notify.el, erc-pcomplete.el:
+	Use (eval-when-compile (require 'cl)), so that compilation doesn't
+	fail.
+
+	* erc-fill.el, erc-truncate.el: Whitespace munging.
+
+	* erc.el: Update copyright notice.  Remove eval-after-load code.
+	(erc-with-buffer): Docfix.
+	(erc-once-with-server-event, erc-once-with-server-event-global)
+	(erc-with-buffer, erc-with-all-buffers-of-server): Use erc-gensym
+	instead of gensym.
+	(erc-banlist-update): Use erc-delete-if instead of delete-if.
+	(erc): Call `erc-update-modules' here.
+
+	* erc-backend.el: Require 'erc-compat to minimize compiler
+	warnings.
+	(erc-decode-parsed-server-response): Docfix.
+	(erc-server-process-alive): Move here from erc.el and rename from
+	`erc-process-alive'.
+	(erc-server-send, erc-remove-channel-users): Make sure process is
+	alive before sending data to it.
+
+	* erc-bbdb.el: Update copyright years.
+	(erc-bbdb-whois): Remove overexuberant comment.
+
+	* erc-button.el: Require erc-fill, since we make liberal use of
+	`erc-fill-column'.
+
+	* erc-compat.el (erc-const-expr-p, erc-list*, erc-assert): New
+	functions, the latter of which provides an `assert' equivalent.
+	(erc-remove-if-not): New function that provides a simple
+	implementation of `remove-if-not'.
+	(erc-gensym): New function that provides a simple implementation
+	of `gensym'.
+	(erc-delete-if): New function that provides a simple
+	implementation of `delete-if'.
+	(erc-member-if): New function that provides a simple
+	implementation of `member-if'.
+	(field-end): Remove this, since it is unused, and later versions
+	of XEmacs have this function already.
+	(erc-function-arglist): Moved here from erc.el.
+	(erc-delete-dups): New compatibility function for dealing with
+	XEmacs.
+	(erc-subseq): New function copied from cl-extra.el.
+
+	* erc-dcc.el: Require pcomplete during compilation to avoid
+	compiler warnings.
+	(erc-unpack-int, erc-dcc-send-filter)
+	(erc-dcc-get-filter): Use erc-assert instead of assert.
+	(pcomplete/erc-mode/DCC): Use erc-remove-if-not instead of
+	remove-if-not.
+
+	* erc-match.el (erc-log-matches): Fix compiler warning.
+
+	* erc-nicklist.el: Update copyright notice.
+	(erc-nicklist-menu): Change use of caadr to (car (cadr ...)).
+	(erc-nicklist-bitlbee-connected-p): Remove.
+	(erc-nicklist-insert-medium-name-or-icon): Accept channel
+	argument.  Use it to determine whether we are on bitlbee.  Now
+	that bitlbee names its channel "&bitlbee", this is trivial.
+	(erc-nicklist-insert-contents): Pass channel as specified above.
+	Don't try to determine whether we are on bitlbee here.
+	(erc-nicklist-channel-users-info): Use erc-remove-if-not instead
+	of remove-if-not.
+	(erc-nicklist-search-for-nick): Use erc-member-if instead of
+	member-if.
+
+	* erc-notify.el (erc-notify-QUIT): Use erc-delete-if with a
+	partially-evaluated lambda expression instead of `delete' and
+	`find'.
+
+	* erc-track.el: Use erc-assert.
+	(erc-track-modified-channels): Remove use of `return'.
+	(erc-track-modified-channels): Use `cadr' instead of `second',
+	since otherwise we would need yet another eval-when-compile line.
+
+2006-01-19  Michael Olson  <mwolson@gnu.org>
+
+	* erc-backend.el (erc-process-sentinel-1): Remove attempt to
+	detect SIGPIPE, since it doesn't work.
+
+2006-01-10  Diane Murray  <disumu@x3y2z1.net>
+
+	* erc-spelling.el: Updated copyright years.
+	(define-erc-module): Enable/disable `flyspell-mode' for all open
+	ERC buffers as well.
+	(erc-spelling-dictionaries): Reworded customize description.
+
+	* erc.el (erc-command-symbol): New function.
+	(erc-extract-command-from-line): Use `erc-command-symbol'.  This
+	fixes a bug where "Symbol's function definition is void:
+	erc-cmd-LIST" would be shown after typing /list at the prompt (the
+	command was interned because erc-menu.el uses it and is enabled by
+	default whereas erc-list.el is not).
+
+	* NEWS: Started a list of renamed variables.
+
+	* erc.el: Reworded the message sent when defining variable
+	aliases.
+	(erc-command-indicator-face): Doc fix.
+	(erc-modules): Enable the match module by default which makes
+	current nickname highlighting on as the default.
+
+	* erc-button.el: Updated copyright years.
+	(erc-button): New face.
+	(erc-button-face): Use `erc-button'.
+	(erc-button-nickname-face): New customizable variable.
+	(erc-button-add-nickname-buttons, erc-button-add-buttons-1): Send
+	new argument to `erc-button-add-button'.
+	(erc-button-add-button): Doc fix.  Added new argument to function
+	definition, NICK-P.  If it's a nickname, use
+	`erc-button-nickname-face', otherwise use `erc-button-face'.  This
+	makes channel tracking and buttons work better together when
+	`erc-button-buttonize-nicks' is enabled, since there is a nickname
+	on just about every line.
+
+	* erc-track.el (erc-track-use-faces): Doc fix.
+	(erc-track-faces-priority-list): Added `erc-button' to list.
+	(erc-track-priority-faces-only): Doc fix.
+
+2006-01-09  Diane Murray  <disumu@x3y2z1.net>
+
+	* erc-button.el (erc-button-url-regexp): Use `concat' so the
+	regexp is not one long line.
+	(erc-button-alist): Fixed so that customizing works correctly.
+	Reorganized.  Removed lambda functions with more than two lines.
+	Doc fix.
+	(erc-button-describe-symbol, erc-button-beats-to-time): New
+	functions.  Moved from `erc-button-alist'.
+
+2006-01-07  Michael Olson  <mwolson@gnu.org>
+
+	* erc-backend.el (erc-process-sentinel-1): Don't try to re-open a
+	process if a SIGPIPE occurs.  This happens when a new message
+	comes in at the same time a /quit is requested.
+	(erc-process-sentinel): Use string-match rather than string= to do
+	these comparisons.  Matching literal newlines makes me nervous.
+
+	* erc-track.el (erc-track-remove-from-mode-line): Handle case
+	where global-mode-string is not a list.  Emacs22 permits this.
+
+
+See ChangeLog.2005 for earlier changes.
+
+    Copyright (C) 2006 Free Software Foundation, Inc.
+  Copying and distribution of this file, with or without modification,
+  are permitted provided the copyright notice and this notice are preserved.
+
+;; Local Variables:
+;; coding: utf-8
+;; End:
+
+;; arch-tag: 865a75f6-2bcb-46df-bf0c-b514dadf688a
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lisp/erc/ChangeLog.2001	Wed Feb 01 10:07:17 2006 +0000
@@ -0,0 +1,1046 @@
+2001-12-18  Mario Lang  <mlang@delysid.org>
+
+	* erc.el 1.176: * Added missing 747 numreply (banned)
+
+2001-12-15  Gergely Nagy  <algernon@debian.org>
+
+	* debian/scripts/install 1.4, debian/rules 1.6:
+	updated to 2.1.cvs.20011215-1
+
+	* debian/changelog 1.12: Debian version 2.1.cvs.20011215-1
+
+2001-12-11  Andreas Fuchs  <asf@void.at>
+
+	* erc.el 1.175:
+	* applied a nicer version of mhp's patch to remove the last prompt from
+	  saved logs
+
+	* erc-replace.el 1.1: * Initial checkin
+
+2001-12-11  Mario Lang  <mlang@delysid.org>
+
+	* erc.el 1.174:
+	* fixed bug triggered when reuse-buffer was enabled (the default).
+	  Another silly port type problem. Maybe we should unify that once and for all sometimes...
+
+2001-12-10  Mario Lang  <mlang@delysid.org>
+
+	* erc.el 1.173: * erc-message-english: New QUIT and s004 entries.
+	* erc-save-buffer-on-part: New variable.
+	* erc-kill-buffer-on-part: New variable.
+	* (erc-server-PART): Use above variables.
+	* (erc-join-channel): Use DEF argument instead of initial input for completing-read.
+
+2001-12-08  Tijs van Bakel  <smoke@wanadoo.nl>
+
+	* erc.el 1.172: added defcustom erc-nick-uniquifier ^ (i prefer _)
+
+2001-12-07  Gergely Nagy  <algernon@debian.org>
+
+	* debian/changelog 1.11: changelog for version 2.1.cvs.20011208-1
+
+2001-12-07  Tijs van Bakel  <smoke@wanadoo.nl>
+
+	* erc.el 1.171:
+	Added erc-scroll-to-bottom as an erc-insert-hook function.  It still bugs a bit, so please test it, thanks
+
+2001-12-07  Mario Lang  <mlang@delysid.org>
+
+	* erc.el 1.170: * Fixed silly bug in erc-server-TOPIC (thanks mhp)
+
+	* erc-speak.el 1.17:
+	* Fix non-greedy matching bug. That one somehow swallowed text
+
+	* erc.el 1.169:
+	Fix Emacs20 problem. For now, we disable erc-track-modified-channels-minor-mode in emacs20
+
+2001-12-07  Andreas Fuchs  <asf@void.at>
+
+	* erc-fill.el 1.5:
+	* Fix another stupid one-off error. This time it really works!
+	 (Until I find the next bug. I guess you can hold your breath) (-:
+
+2001-12-06  Andreas Fuchs  <asf@void.at>
+
+	* erc-fill.el 1.4: * Fixed static filling:
+	** No more \ed (continued on next line) lines anymore
+	** Fixed bug with previous version where longer lines wouldn't get
+	   filled correctly (i.e. at all)
+
+2001-12-06  Gergely Nagy  <algernon@debian.org>
+
+	* debian/changelog 1.10: changelog for 2.1.cvs.20011206-1 added
+
+2001-12-06  Andreas Fuchs  <asf@void.at>
+
+	* erc.el 1.168:
+	* Don't discard away status when identifying to NickServ
+	* Modify `erc-already-logged-in': check for port, too.
+
+	* erc-fill.el 1.3:
+	* Fix stupid loop non-termination error in erc-fill-static when filling
+	  one-line regions.
+	* Make erc-count-lines return meaningful values
+
+2001-12-05  Mario Lang  <mlang@delysid.org>
+
+	* erc.el 1.167:
+	* (erc-process-input): Make ' /command' work for quoting /commands
+
+	* erc-speak.el 1.16: see changelog
+
+	* erc-fill.el 1.2: see erc.el changelog
+
+	* erc.el 1.166:
+	* erc-insert-hook: Changed strategy completely, no start end parameters any more.
+	We narrow-to-region now, thats much cleaner.
+	* rename erc-fill-region to erc-fill and change the autoload
+	** You'll probably need to restart Emacs
+
+2001-12-04  Mario Lang  <mlang@delysid.org>
+
+	* erc.el 1.165:
+	* (erc-send-current-line): Fixed long outstanding bug. XEmacs users with erc-fill-region on erc-insert-hook knew that one a long time.
+
+	* erc.el 1.164: fix order of attack
+
+	* erc.el 1.163: * macroexpanded define-minor-mode for XEmacs
+
+	* erc.el 1.162: First try to make channel tracking mouse sensitive
+
+	* erc.el 1.161: * More erc-message-format conversion.
+	  erc-format-message-english-PART as an example on how to use functions to format message
+	* (erc-format-message): Fallback mechanism to use english catalog if variable is not bound
+
+2001-12-03  Mario Lang  <mlang@delysid.org>
+
+	* erc.el 1.160: * (erc-iswitchb): Rewrite, docfix.
+	Make it use erc-modified-channels as default if available.
+
+	* erc-menu.el 1.2:
+	* Fixage related to erc-track-modified-channels-minor-mode rewrite
+
+	* erc.el 1.159:
+	* erc-track-modified-channels-minor-mode: Use buffer objects instead of erc-default-target return value for internal state keeping.
+
+	* erc.el 1.158: * Made reconnect behave nicer (erc-process-sentinel)
+	* Rewrote erc-modified-channels-tracking completely.
+	  Its now a minor mode (erc-track-modified-channels-minor-mode)
+	  It uses a list as internal representation now, so all silly string-parsing
+	  related bugs should be gone.
+	  Use (erc-track-modified-channels-minor-mode t) now to toggle this functionality.
+	  Dont set the erc-track-modified-channels-minor-mode variable yourself, use the toggle function
+
+2001-11-29  Gergely Nagy  <algernon@debian.org>
+
+	* debian/changelog 1.9: final version
+
+2001-11-29  Mario Lang  <mlang@delysid.org>
+
+	* erc.el 1.157:
+	* (erc-channel-p): Make it work with string and buffer as parameter. buffer.
+	* (erc-format-message): Add a check for functionp. This allows a format-specifier also to be a function name, which gets called with args applied and needs to return the actual format string.
+	* Converted some formats, JOIN, JOIN-you, MODE, ...
+
+2001-11-28  Mario Lang  <mlang@delysid.org>
+
+	* erc.el 1.156:
+	* (erc-prepare-mode-line-format): Added sanity checks to prevent it from having problems with server buffers where the connection failed
+
+	* erc-bbdb.el 1.7:
+	* (erc-bbdb-JOIN): regexp-quote the fingerhost before searching, some people have really strange characters as their user names
+
+	* erc.el 1.155: Remove a stupid debug like (message ...) call
+
+2001-11-28  Gergely Nagy  <algernon@debian.org>
+
+	* debian/changelog 1.8: draft of 2.1.cvs.20011128-1
+
+	* debian/rules 1.5: simplify for the all-in-one erc package
+
+	* debian/control 1.3: integrated erc-speak back into erc
+
+	* debian/maint/conffiles 1.3, debian/maint/conffiles.in 1.2, debian/maint/postinst 1.3, 
+	  debian/maint/postinst.in 1.2, debian/maint/prerm 1.3, debian/maint/prerm.in 1.2, 
+	  debian/scripts/install 1.3, debian/scripts/install.in 1.3, debian/scripts/remove 1.3, 
+	  debian/scripts/remove.in 1.2, debian/scripts/startup.erc-speak 1.2:
+	since erc-speak is gone, resurrect the static files, and update them to support the latest erc
+
+2001-11-28  Mario Lang  <mlang@delysid.org>
+
+	* erc.el 1.154: * (erc-mode): Shouldn't be interactive.
+	* (erc-info-mode): Ditto.
+
+	* erc.el 1.153: * (erc-server-352): Added hopcount parsing.
+	Added call to erc-update-channel-member to fill in channel-members information
+	on /WHO if the channel is joined.
+
+2001-11-27  Mario Lang  <mlang@delysid.org>
+
+	* erc-speedbar.el 1.6: *** empty log message ***
+
+	* erc-speedbar.el 1.5: * (erc-speedbar-expand-user): New function.
+	Used when more information than just the nick name is available about a dude.
+
+	* erc.el 1.152: * Fixed stupid edit,checkin,save cycle error :)
+
+	* erc.el 1.151:
+	* (erc-generate-log-file-name-default): Renamed to -long
+	Doc fix.
+	* (erc-generate-log-file-name-old): Renamed to -long
+	Doc fix.
+	* erc-generate-log-file-name-function: Set default to ...-long
+	Doc fixes
+
+	* erc-speedbar.el 1.4: *** empty log message ***
+
+2001-11-26  Mario Lang  <mlang@delysid.org>
+
+	* erc-speedbar.el 1.3: * Integrated channel names list
+	  what else do we need to replace info buffers???
+	  please test that code and comment on erc-ehlp, thanks
+
+	* erc-speedbar.el 1.2:
+	* Added erc-speedbar-goto-buffer and therefore enable switching to the buffers from speedbar
+
+	* erc-speedbar.el 1.1:
+	I had to check this in, it works !! sort of,, megaalphagammaversion, first version. test, play, submit ideas/patches
+
+2001-11-26  Gergely Nagy  <algernon@debian.org>
+
+	* erc.el 1.150 (erc-mode): moved erc-last-saved-position here
+	moved buffer naming code from here..
+	(erc): ...to here
+	(erc-generate-log-file-name-old): only prepend target if it exists
+
+	made erc-log-insert-log-on-open a defcustom
+
+2001-11-26  Mario Lang  <mlang@delysid.org>
+
+	* erc.el 1.149:
+	* Applied antifuchs/mhp patches, the latest on erc-help, unmodified
+	* New variable: erc-reuse-buffers default to t.
+	* Modified erc-generate-new-buffer-name to use it. it checks if server and port are the same, 
+	  then one can assume thats the same channel/query target again.
+
+2001-11-23  Mario Lang  <mlang@delysid.org>
+
+	* erc-bbdb.el 1.6:
+	* new function erc-BBDB-NICK to handle nickname anotation on a nick-change event of a known record
+
+	* erc.el 1.148: * Remove erc-rename-buffer, its no longer necessary
+	* Remove erc-autoop-*. it was broken, and needed rewrite anyway
+	* write erc-already-logged-in in terms of erc-buffer-list and make the duplicate login check work again
+
+	* erc.el 1.147: * Fixed stupid typo
+
+2001-11-22  Mario Lang  <mlang@delysid.org>
+
+	* erc.el 1.146: * New local variable, erc-announced-server-name
+	* erc-mode-line-format supports a new symbol, target-and/or-server
+	* The mode-line displays the announced server name now (for autojoin later..., 
+	  greets Adam)
+	* New macro, erc-server-hook-list for a nice way to define the defcustoms of the erc-server-*-hook's
+	  Thanks go to the guy from #emacs who helped with that
+	* erc-fill-region is now autoloaded from erc-fill.el
+	  * erc-fill.el implements a new fill method, erc-fill-static
+	    (setq erc-fill-function 'erc-fill-static)
+	* Some other things I forgot right now
+
+	* erc-bbdb.el 1.5: *** empty log message ***
+
+	* erc-fill.el 1.1: Initial version.
+
+	* erc-complete.el 1.4:
+	Applied antifuchs patch to make completion work with (string= erc-prompt "")
+
+	* erc-complete.el 1.3:
+	added function erc-nick-completion-exclude-myself
+	you can set erc-nick-completion to 'erc-nick-completion-exclude-myself to use it
+
+2001-11-21  Mario Lang  <mlang@delysid.org>
+
+	* erc-bbdb.el 1.4:
+	* Changed usage of 'finger-host to bbdb-finger-host-field
+
+	* erc-bbdb.el 1.3:
+	* Changed WHOIS to use finger-host instead of net field.
+	* Added 'visible as option to erc-bbdb-popup-p to only pop-up the bbdb buffer if a join happened in a visible buffer on any visible frame.
+	* Added (regexp-quote ...) for nickname search in erc-bbdb-JOIN
+
+2001-11-20  Mario Lang  <mlang@delysid.org>
+
+	* erc-bbdb.el 1.2: * Added JOIN support
+
+2001-11-19  Mario Lang  <mlang@delysid.org>
+
+	* erc.el 1.145:
+	Initial message catalog code. converted erc-action-format usage to use it
+
+	* erc.el 1.144: * erc-play-sound: Added XEmacs related check
+
+	* erc-bbdb.el 1.1: * Initial version, many thanks to Andreas Fuchs
+
+	* erc.el 1.143: * Fixed silly problem with whois/was handling
+
+	* erc.el 1.142: * Renamed prev-rd to erc-previous-read
+	* Removed erc-next-line-add-newlines and s next-line-add-newlines to nil in defun erc by default
+
+	* erc.el 1.141:
+	fixed xemacs compatibility prob with delete, thanks Adam
+
+2001-11-18  Mario Lang  <mlang@delysid.org>
+
+	* erc.el 1.140: numreplies 301 & 461
+
+2001-11-13  Tijs van Bakel  <smoke@wanadoo.nl>
+
+	* erc.el 1.139:
+	Added code for error reply 421 "Unknown command", to test the new server parsing system.
+	This was really easy!  Thanks ZenIRC guys & delysid :-)
+
+2001-11-13  Mario Lang  <mlang@delysid.org>
+
+	* erc.el 1.138: * Allow connecting to SSL enabled irc servers.
+	   Ugly hack, but it works for now. Be sure to use the numeric irc port 994 so that erc can recognize what you want
+	  good example is
+	irc server: ircs.segfault.net
+	port: 994
+
+	meet me there, I am still delYsid :)
+
+	* erc.el 1.137: * some more numreply handlers
+	* cleanup in erc-process-away-p
+	* new function erc-display-error-notice
+
+	* erc.el 1.136: * numreply 501 and 221
+
+	* erc.el 1.135:
+	removed obsolete old hook variables. Your functions may break, but it is easy to hook them up to the new hooks.
+	erc-part-hook: use erc-server-PART-hook instead
+	erc-kick-hook: use erc-server-KICK-hook instead
+	and so on
+
+	* erc.el 1.134:
+	fixed serious bug which cause privmsgs vanishing when erc-auto-query was set to nil
+
+	* erc.el 1.133: cleaned up erc-process-filter
+
+	* erc.el 1.132: * 401 and 320 numreplies implemented
+
+	* erc.el 1.131: * Removed old/now obsolete code
+
+	* erc.el 1.130: * Fixed bug in erc-server-MODE
+
+2001-11-12  Mario Lang  <mlang@delysid.org>
+
+	* erc.el 1.129: fixed it
+
+	* erc.el 1.128:
+	*** We switched over. New server message parsing/handling is running now. Thansk to the zenirc developers for the great ideas I got from the code!!!!! Go and test it, poke at it, bug me on irc about problems
+
+	* erc.el 1.127: *** empty log message ***
+
+2001-11-12  Tijs van Bakel  <smoke@wanadoo.nl>
+
+	* erc.el 1.125:
+	Fixed bug in erc-get-buffer, now channel names are compared in
+	a case-insensitive way.
+
+2001-11-12  Mario Lang  <mlang@delysid.org>
+
+	* erc.el 1.124: erc-server-353
+
+2001-11-12  Tijs van Bakel  <smoke@wanadoo.nl>
+
+	* erc.el 1.123: Fixed docstring for erc-get-buffer.
+	Added erc-process to a lot of calls to erc-get-buffer, so
+	that only the local process is searched.
+
+2001-11-12  Mario Lang  <mlang@delysid.org>
+
+	* erc.el 1.122: * erc-buffer-filter: do it differently
+
+	* erc.el 1.121: ugly but working fix for mhp's query problem
+
+	* erc.el 1.120: * erc-server-PRIVMSG-or-NOTICE
+	  Now, all the server word replies are finished. Going to numreplies now
+
+	* erc.el 1.119:
+	* debugging fascilities for the transition. C-x 2 C-x o M-x ielm RET erc-server-vectors RET ; to get a list of all server messages currently not handled in the new code. Feel free to pick one and implement it
+
+	* erc.el 1.118: * erc-server-KICK and erc-server-TOPIC. new functions
+	* erc-server-305-or-306 and erc-server-311-or-314
+
+	* erc.el 1.117:
+	* ported PART and QUIT msgs to the new scheme, many to go. but it is a easy task. does someone wanna try and start with numreplies?
+
+	* erc.el 1.116: * erc-server-JOIN
+
+	* erc.el 1.115: * Ported erc-server-INVITE code
+
+	* erc.el 1.114: * erc-server-ERROR and erc-server-MODE
+
+2001-11-11  Mario Lang  <mlang@delysid.org>
+
+	* erc.el 1.113: * zen
+
+	* erc.el 1.112: * New variable erc-connect-function.
+
+	* erc.el 1.111:
+	* New function erc-channel-p and use it where appropriate
+
+	* erc.el 1.110: * Removed the variable erc-buffer-list completely now
+	* Moved erc-dbuf around a bit
+
+	* erc.el 1.109: * Fix silly change in quit/rename msg handling
+
+	* erc.el 1.108: thanks mhp, fixed
+
+	* erc.el 1.107: * Tijs van Bakel's work from 10th Nov. merged in
+	* My additions to that idea merged in too
+	Basicly, this is a major rewrite, if you are scared and want avoid problems,
+	stay at your current version. It seems fairly stable though.
+	That changed? erc-buffer-name handling was completely rewritten,
+	and erc-buffer-list local variable handling removed.
+	Simplifies alot of code. Poke at it. read the diff. report bug/send patches!
+
+	* erc.el 1.106: * Added variable listing when /set is used without args
+
+2001-11-10  Mario Lang  <mlang@delysid.org>
+
+	* erc.el 1.105:
+	* Comment/structure cleanup, removal of unnecessary code
+
+	* erc.el 1.104: only some code beautification
+
+	* erc-imenu.el 1.2:
+	remove add-hook call, thats done in erc.el now for autoloadability
+
+	* erc.el 1.103: * Make erc-imenu autoloadable
+
+	* erc.el 1.102:
+	* The long promised erc-mode-line-format handling rewrite
+	   Poke at it, try it, play with it, report bugs
+
+	* erc.el 1.101:
+	some regex-quote fixes, new function erc-cmd-set, and minor things
+
+2001-11-08  Mario Lang  <mlang@delysid.org>
+
+	* erc.el 1.100:
+	* added second timestamp-format (erc-away-timestamp-format) for marking msgs when being away
+
+	* erc-complete.el 1.2: fixed silly deffun
+
+	* erc.el 1.99: * Rewrote erc-load-irc-script (simplified)
+	* Removed depricated code
+
+	* erc-speak.el 1.15: * reflect changes in erc.el
+
+	* erc.el 1.98:
+	* Moved completion related functions into erc-complete.el
+	  placed an autoload instead into erc.el. That quite cool,
+	  because erc-complete.el only gets loaded when you use
+	  TAB first time in erc.
+
+	* erc-complete.el 1.1: _ Initial checkin
+
+	* erc.el 1.97: * New function: erc-chain-hook-with-args
+	* Changed calls to erc-insert-hook to use it
+
+2001-11-07  Mario Lang  <mlang@delysid.org>
+
+	* erc.el 1.96: * Patch from Fabien Penso
+	  Make completion case insensitive. try it! its cool
+
+	* erc.el 1.95: * Reduction patch 2
+	  This time, we move the input ring handling into erc-ring.el
+	  Remember that you need (require 'erc-ring) in your .emacs to get the input handling as a feature
+	  And remeber, that you dont need it if you dont use input ring :-)
+
+	* erc-ring.el 1.1: * Initial checkin
+
+	* erc.el 1.94: * The great reduction patch :-)
+	  moved relevant function from erc.el to new file erc-menu.el and erc-imenu.el
+
+	* erc-imenu.el 1.1: nitial version
+
+	* erc-menu.el 1.1: * Initial version
+
+	* erc.el 1.93: * wording change suggested by Benjamin Drieu
+
+2001-11-07  Tijs van Bakel  <smoke@wanadoo.nl>
+
+	* erc.el 1.92: Added Emacs version to /SV
+
+2001-11-07  Mario Lang  <mlang@delysid.org>
+
+	* erc.el 1.91: * Hookification patch, read the diff
+
+	* erc.el 1.90: too tired for a changelog :)
+
+2001-11-06  Mario Lang  <mlang@delysid.org>
+
+	* erc.el 1.89:
+	* make erc-cmd-op and erc-cmd-deop take multiple nicknames as argument
+
+2001-11-06  Gergely Nagy  <algernon@debian.org>
+
+	* debian/changelog 1.7: sync
+
+	* debian/rules 1.4: fixed a typo: PKGDIR, not PKIDR
+
+2001-11-06  Mario Lang  <mlang@delysid.org>
+
+	* erc.el 1.88:
+	* Changed timestamping when away to use erc-timestamp-format and append the timestamp instead of prepending it..
+	* minor cleanup, s/(if (not /(unless/ and thelike
+
+2001-11-06  Tijs van Bakel  <smoke@wanadoo.nl>
+
+	* erc.el 1.87: Fixed OP and DEOP commands to return T.
+	Added SV say-version command.
+	Added erc-send-message utility function, but it's not used everywhere yet.
+
+2001-11-05  Mario Lang  <mlang@delysid.org>
+
+	* erc.el 1.86: stupid delYsid, forgot require 'format-spec. good nite
+
+	* erc.el 1.85:
+	* new variable erc-action-format. Some erc-notice-prefix fixes again
+
+	* erc.el 1.84: * erc-minibuffer-privmsg defaults to t
+
+	* erc.el 1.83:
+	* Small fix in relation to the transition to erc-make-notice
+
+2001-11-05  Tijs van Bakel  <smoke@wanadoo.nl>
+
+	* erc.el 1.82:
+	Renamed erc-message-notices to erc-minibuffer-notice, and renamed erc-prevent-minibuffer-privmsg to erc-minibuffer-privmsg, inverting its functionality
+
+	* erc.el 1.81: Added support for channel names starting with & + and !.
+	Also, many changes partially discussed on the mailinglist:
+
+		* erc.el (cl): Add requirement for cl package.
+		(erc-buffer-list): Make this variable global again.
+		(erc-default-face): Fix typo.
+		(erc-timestamp-face): Add face for timestamps.
+		(erc-join-buffer, erc): Add a 'bury option.
+		(erc-send-action): Add timestamp.
+		(erc-command-table): Add /CLEAR, /DEOP, /OP, /Q.
+		(erc-send-current-line): Add timestamp.
+		(erc-send-current-line): Add call to erc-insert-hook.
+		(erc-cmd-clear): New command to clear buffer contents.
+		(erc-cmd-whois): Fix cut'n'paste-o.
+		(erc-cmd-deop): New command to deop a user.
+		(erc-cmd-op): New command to op a user.
+		(erc-make-notice): Moved a lot of duplicate code here.  Perhaps
+		this should also be done for erc-highlight-error.
+		(erc-parse-line-from-server): Now NOTICE will also open a new
+		query, just as PRIVMSG.
+		(erc-parse-line-from-server): Call erc-put-text-property on a
+		channel message/notice first, before concatenating nick and
+		timestamp &c.
+		(erc-message-notices): Add option to display notices in
+		minibuffer.
+		(erc-fill-region): No longer strip spaces in front of incoming
+		messages.
+		(erc-parse-current-line): No longer strip spaces in front of text
+		input by user.
+
+	Hopefully I didn't break too much :(
+
+2001-11-05  Mario Lang  <mlang@delysid.org>
+
+	* erc.el 1.80:
+	* New function erc-nickserv-identify-autodetect for erc-insert-hook. Added by default currently.
+
+	* erc.el 1.79:
+	* Mini-fix in erc-process-num-reply (= n 353): Added @ as prefix character to make certain channels on opn work again nicely
+
+2001-10-31  Gergely Nagy  <algernon@debian.org>
+
+	* debian/changelog 1.6: updated to reflect changes
+
+	* debian/scripts/install.in 1.2:
+	moved #PKGFLAG# before -f batch-byte-compile
+
+2001-10-29  Mario Lang  <mlang@delysid.org>
+
+	* erc.el 1.78:
+	Imenu fixed somehow, added IRC services interactive function for indentify to NickServ. Read the diff
+
+2001-10-26  Gergely Nagy  <algernon@debian.org>
+
+	* debian/changelog 1.5: sigh. -2
+
+2001-10-25  Gergely Nagy  <algernon@debian.org>
+
+	* debian/changelog 1.4: updated to reflect changes
+
+	* debian/rules 1.3: handle conffiles.in too
+
+	* debian/maint/conffiles.in 1.1: new file
+
+	* debian/maint/conffiles 1.2: superceded by conffiles.in
+
+	* debian/scripts/startup 1.2: superceded by startup.erc
+
+2001-10-25  Mario Lang  <mlang@delysid.org>
+
+	* debian/scripts/startup.erc-speak 1.1: * Initial version
+
+	* debian/scripts/startup.erc 1.1: * Added and fixes minimal typo
+
+2001-10-25  Gergely Nagy  <algernon@debian.org>
+
+	* debian/changelog 1.3: updated to reflect changes
+
+	* debian/rules 1.2:
+	modified to be able to build the erc-speak package too
+
+	* debian/control 1.2: added the new erc-speak package
+
+	* debian/README.erc-speak 1.1, debian/maint/postinst.in 1.1, debian/maint/prerm.in 1.1, 
+	  debian/scripts/install.in 1.1, debian/scripts/remove.in 1.1:
+	new file
+
+	* debian/maint/postinst 1.2, debian/maint/prerm 1.2, debian/scripts/install 1.2, 
+	  debian/scripts/remove 1.2:
+	removed, superceded by it's .in counterpart
+
+2001-10-25  Mario Lang  <mlang@delysid.org>
+
+	* erc.el 1.77: * Fixed some defcustom :type 's
+	* Added erc-before-connect hook which gets called with server port and nick.
+	  Use this hook to e.g. setup a tunnel before actually connecting.
+	  something like (when (string= server "localhost") ...)
+
+2001-10-24  Mario Lang  <mlang@delysid.org>
+
+	* erc.el 1.76: * Patch by smoke: fix erc-cmd-* commands and add aliases
+
+2001-10-23  Mario Lang  <mlang@delysid.org>
+
+	* erc-speak.el 1.14:
+	* Added a new personality for channel name announcement, This makes streams of flooded channels much easier to listen to, 
+	  especially if you are on more than one channel simultaniously.
+
+	* erc.el 1.75:
+	* Made the completion postfix customizable through erc-nick-completion-postfix
+
+	* erc-speak.el 1.13, erc.el 1.74:
+	* Added erc-prevent-minibuffer-privmsg
+
+	* erc-speak.el 1.12:
+	* Quickish hack to allow exclusion of timestamps from speaking. see erc-speak-filter-timestamps
+
+2001-10-21  Mario Lang  <mlang@delysid.org>
+
+	* erc-speak.el 1.11:
+	* Removed now really obsolete code. Package size reduced by 50%
+
+	* erc-speak.el 1.10:
+	* Very important fix! Now erc-speak is really complete. Messages dont get cut anymore. Be sure to use auditory icons, 
+	  it's reallllly cool now!!!
+
+	* erc-speak.el 1.9: *** empty log message ***
+
+	* erc-speak.el 1.5: * Major simplification. depends on erc.el,v 1.73
+	* Things removed, read diff
+
+2001-10-21  Gergely Nagy  <algernon@debian.org>
+
+	* debian/changelog 1.2: oops, silly typo
+
+	* debian/changelog 1.1, debian/control 1.1, debian/copyright 1.1, 
+	  debian/maint/conffiles 1.1, debian/maint/postinst 1.1, debian/maint/prerm 1.1, 
+	  debian/rules 1.1, debian/scripts/install 1.1, debian/scripts/remove 1.1, 
+	  debian/scripts/startup 1.1:
+	initial check-in
+
+2001-10-21  Mario Lang  <mlang@delysid.org>
+
+	* erc.el 1.73:
+	* Changed erc-insert-hook to get two arguments, START and END of the region
+	  which got inserted. CAREFUL! This could break stuff, but it makes the hook
+	  much more useable.
+
+	* erc.el 1.72:
+	* Made erc-smiley a new option, currently set to t to showoff this feature. :)
+
+2001-10-20  Mario Lang  <mlang@delysid.org>
+
+	* erc.el 1.71: * Add missing erc-mode-hook variable
+	* Add smiley-support (preliminary test)
+
+2001-10-20  Alex Schroeder  <alex@gnu.org>
+
+	* erc.el 1.70:
+	Replaced all occurences of put-text-property with a call to
+	erc-put-text-property.
+	(erc-put-text-property): New function.
+	(erc-tracking-modified-channels): Moved to the front of the file such
+	that it is already defined when the menu is being defined.
+	(erc-modified-channel-string): Ditto.
+
+2001-10-18  Alex Schroeder  <alex@gnu.org>
+
+	* erc.el 1.69: Removed some commentary.  The wiki page is the place to
+	put such information.
+	(erc-fill-prefix): Doc change.
+	(erc-notice-highlight-type): Doc change, now a user option.
+	(erc-pal-highlight-type): Doc change, now a user option.
+	(erc-fool-highlight-type): New option.
+	(erc-keyword-highlight-type): New option.
+	(erc-dangerous-host-highlight-type): New option.
+	(erc-uncontrol-input-line): Doc change.
+	(erc-interpret-controls-p): Doc change, now a user option.
+	(erc-multiline-input): Doc change.
+	(erc-auto-discard-away): Doc change.
+	(erc-pals): Changed from string to regexp.
+	(erc-fools): New option.
+	(erc-keywords): Renamed from erc-highlight-strings.  WATCH OUT:
+	Not backwards compatible change!
+	(erc-dangerous-hosts): Renamed from erc-host-danger-highlight.
+	WATCH OUT: Not backwards compatible change!
+	(erc-menu-definition): Added menu entries for fools, keywords and
+	dangerous hosts.
+	(erc-mode-map): Changed keybindings from C-c <plain ascii> to
+	various C-c <C-ascii> combinations.
+	(erc-dangerous-host-face): Renamed from erc-host-danger-face.
+	WATCH OUT: Not backwards compatible change!
+	(erc-fool-face): New face.
+	(erc-keyword-face): Renamed from erc-highlight-face.  WATCH OUT:
+	Not backwards compatible change!
+	(erc-parse-line-from-server): Fixed highlighting in the cases
+	where (equal erc-pal-highlight-type 'all), added code to handle
+	erc-fool-highlight-type, erc-dangerous-host-highlight-type
+	(erc-update-modes): Replaced erc-delete-string with delete.
+	(erc-keywords): Renamed from erc-highlight-strings, handle
+	erc-keyword-highlight-type.
+	(erc-delete-string): Removed.
+	(erc-list-match): New function.
+	(erc-pal-p): Use erc-list-match.
+	(erc-fool-p): New function.
+	(erc-keyword-p): New function.
+	(erc-dangerous-host-p): Renamed from erc-host-danger-p, use
+	erc-list-match.
+	(erc-directed-at-fool-p): New function.
+	(erc-add-entry-to-list): New function.
+	(erc-remove-entry-from-list): New function.
+	(erc-add-pal): Use erc-add-entry-to-list.
+	(erc-delete-pal): Use erc-remove-entry-from-list.
+	(erc-add-fool): New function.
+	(erc-delete-fool): New function.
+	(erc-add-keyword): New function.
+	(erc-delete-keyword): New function.
+	(erc-add-dangerous-host): New function.
+	(erc-delete-dangerous-host): New function.
+
+2001-10-07  Mario Lang  <mlang@delysid.org>
+
+	* erc.el 1.68: * irc vs ircd default port fixed
+
+	* erc.el 1.67: * Added topic-change to imenu
+
+	* erc.el 1.66: * More imenu spiffyness
+
+	* erc.el 1.65: * Added imenu support
+
+	* erc.el 1.64:
+	* Fix to /topic to show topic instead of setting it to null :)
+
+2001-10-05  Mario Lang  <mlang@delysid.org>
+
+	* erc.el 1.63: * First version of erc-rename-buffer
+
+	* erc.el 1.62: * more header-line tricks.
+
+	* erc.el 1.61:
+	* Small fix to do erc-update-mode-line-buffer in erc-update-channel-topic
+
+	* erc.el 1.60: * Added erc-header-line-format
+
+2001-10-04  Mario Lang  <mlang@delysid.org>
+
+	* erc.el 1.59: * mini-fix, add msgp to auto-query code
+
+	* erc.el 1.58: * Added command-names to completion (erc-command-table)
+	* New variable erc-auto-query. When set, every arriving message to you
+	will open a query buffer for that sender if not already open.
+	* Compatibility function fo non-existing line-beginning|end-position functions in XEmacs.
+
+2001-10-03  Mario Lang  <mlang@delysid.org>
+
+	* erc.el 1.57:
+	* Removed alot of (progn ...) where they were not necessary
+	* Changed some (if ...) without else part to (when ...)
+	* Some (while ...) to use (dolist ...)
+	* Fix for completion popup generating tracebacks.
+	* New function erc-arrange-session-in-mulptiple-windows
+	* Lots of other stuff, read the diff
+
+2001-10-02  Mario Lang  <mlang@delysid.org>
+
+	* erc.el 1.56: * Added erc-kill-input and keybinding C-c C-u for it
+
+2001-10-01  Mario Lang  <mlang@delysid.org>
+
+	* erc.el 1.55: * Another fix to nick-completion
+	* Additional checks in erc-track-modified-channels
+
+2001-09-26  Mario Lang  <mlang@delysid.org>
+
+	* erc.el 1.54: * Fixed completion (alex)
+	  * Now popup buffer doesnt destroy your window configuration.
+	* Fixed away handling (incomplete)
+
+2001-09-24  Mario Lang  <mlang@delysid.org>
+
+	* erc.el 1.53: Fixed silly quoting-escape error
+
+2001-09-23  Mario Lang  <mlang@delysid.org>
+
+	* erc.el 1.52: * Added auto-op support (unfinished)
+	* Added erc-latest-version.
+	* Added erc-ediff-latest-version.
+
+2001-09-21  Mario Lang  <mlang@delysid.org>
+
+	* erc.el 1.51:
+	* Minor menu additions (invite only mode is now a checkbox)
+
+2001-09-20  Mario Lang  <mlang@delysid.org>
+
+	* erc.el 1.50:
+	* Fix (erc-cmd-names): This should fix C-c C-n too, hoepfully it was the right fix and doesnt break anything else.
+
+	* erc.el 1.49: * Fixes XEmacs easymenu usage (2nd time).
+
+2001-09-19  Mario Lang  <mlang@delysid.org>
+
+	* erc.el 1.48:
+	* (erc-complete-nick): Add ": " only if one completes directly after the erc-prompt, otherwise, add just one space
+
+	* erc.el 1.47:
+	* Changed menu-definition to use easymenu (hopefully this now works under Xemacs)
+	* Fix for custom problem with :must-match on XEmacs (thanks shapr)
+	* Added /COUNTRY command using (what-domain) from package mail-extr (shapr)
+	* Fix for case-sensitivity problem with pals (they are now all downcased)
+	* Different (erc-version) function which now can take prefix argument to insert the version information into the current buffer, 
+	  instead of just displaying it in the minibuffer.
+
+2001-09-10  Mario Lang  <mlang@delysid.org>
+
+	* erc.el 1.46: Updated erc-version-string
+
+	* erc.el 1.45: Version number change and last read-through...
+
+2001-09-04  Mario Lang  <mlang@delysid.org>
+
+	* erc.el 1.44: Added some asterisks
+
+2001-08-24  Mario Lang  <mlang@delysid.org>
+
+	* erc.el 1.43:
+	Fixed hidden channel buffer tracking (sort of), now using switch-to-buffer for advice.
+	This version is unofficially named 2.1prebeta1. Please test it and send
+	fixes to various problems you may encounter so that we can eventually
+	release 2.1 soon.
+
+2001-08-14  Mario Lang  <mlang@delysid.org>
+
+	* erc.el 1.42:
+	Added function erc-bol and keybinding C-c C-a for it (contributed by Benjamin Rutt <brutt@bloomington.in.us)
+
+2001-08-07  Mario Lang  <mlang@delysid.org>
+
+	* erc.el 1.41:
+	Checked in lathis code and modified it slightly. Still unsure about set-window-buffer advice, current attempt doesnt seem to work.
+	Removed (nick -> #channel) from mode-line. (CLOSED) and (AWAY...) should still be displayed when appropriate
+
+2001-08-06  Mario Lang  <mlang@delysid.org>
+
+	* erc.el 1.40:
+	added local-variable channel-list in session-buffers and make /LIST use it.
+	erc-join-channel can now do completion after /LIST was executed
+
+2001-08-05  Mario Lang  <mlang@delysid.org>
+
+	* erc.el 1.39: Tweaked erc-join-channel and erc-part-from-channel
+
+2001-07-27  Mario Lang  <mlang@delysid.org>
+
+	* erc.el 1.38: some more defcustom stuff
+
+	* erc.el 1.37: Patch from Henrik Enberg <henrik@enberg.org>:
+	   Adds variables erc-frame-alist and erc-frame-dedicated-p.
+
+	* erc.el 1.36: fixed erc-part-from-channel
+
+	* erc.el 1.35:
+	fixed match-string problem and added interactive topic setting function.
+
+	* erc.el 1.34: fixed silly string-match bug
+
+	* erc.el 1.33:
+	Added erc-join-channel and erc-part-from-channel (interactive prompts), as well as keybindings. C-c C-j #emacs RET is now enough :)
+
+2001-07-27  Alex Schroeder  <alex@gnu.org>
+
+	* erc.el 1.32 (erc-display-line-buffer): Simplified filling.
+	(erc-fill-region): New function.
+
+2001-07-27  Mario Lang  <mlang@delysid.org>
+
+	* erc.el 1.31: Added redundancy check in output
+
+2001-07-26  Alex Schroeder  <alex@gnu.org>
+
+	* erc.el 1.30 (erc-send-action): Add text-property stuff.
+	(erc-input-action): Removed text-property stuff.
+	(erc-command-table): Corrected command for DESCRIBE.  Still
+	doesn't work though.  No idea what it should do.  Looks like a no op.
+	(erc-cmd-me): Doc change.
+
+2001-07-26  Mario Lang  <mlang@delysid.org>
+
+	* erc.el 1.29:
+	fixed one occurence of a setq with only one argument (XEmacs didnt like that)
+
+	* erc.el 1.28:
+	Added erc-next-line-add-newlines customisation possibility.
+
+	* erc.el 1.27:
+	added erc-fill-prefix for defining your own way of filling and fixed filling somehow
+
+	* erc.el 1.26:
+	fixed small incompatibility in erc-parse-line-from-server at (and (= n 353) regexp
+
+2001-07-25  Mario Lang  <mlang@delysid.org>
+
+	* erc.el 1.25:
+	Added erc-filling and filling code to erc-display-line-buffer.
+
+2001-07-08  Alex Schroeder  <alex@gnu.org>
+
+	* erc.el 1.24 (try-complete-erc-nick): Make the ": " part of the
+	expansion
+
+	* erc.el 1.23: require ring
+
+2001-07-08  Mario Lang  <mlang@delysid.org>
+
+	* erc.el 1.22: *** empty log message ***
+
+2001-07-07  Mario Lang  <mlang@delysid.org>
+
+	* erc.el 1.21: typo
+
+	* erc.el 1.20: ommit
+	:wq
+
+2001-07-06  Alex Schroeder  <alex@gnu.org>
+
+	* erc.el 1.19 (erc-mode): Call erc-input-ring-setup.
+	(erc-send-current-line): Call erc-add-to-input-ring.
+	(erc-input-ring): New variable.  Currently not buffer local.
+	(erc-input-ring-index): New variable.  Currently not buffer local.
+	(erc-input-ring-setup): New function.
+	(erc-add-to-input-ring): New function.
+	(erc-previous-command): New function.
+	(erc-next-command): New function.
+	(erc-mode-map): Uncommented keybindings for erc-next-command and
+	erc-previous-command.
+
+2001-07-05  Alex Schroeder  <alex@gnu.org>
+
+	* erc.el 1.18 (erc-highlight-strings): Removed debug message.
+
+	* erc.el 1.17 (erc-join-buffer): Changed default to 'buffer.
+	(erc-join-info-buffer): Changed default to 'disable.
+	(erc-nick-completion): Changed default to 'all.
+
+2001-07-04  uid31117  <uid31117@confusibombus>
+
+	* erc.el 1.16: Resolved...
+
+2001-07-03  Alex Schroeder  <alex@gnu.org>
+
+	* erc.el 1.15 (erc-highlight-strings): New option and new function.
+	(erc-parse-line-from-server): Use it.
+	Various empty lines removed.  Various doc strings fixed.
+
+	* erc.el 1.14: Removed more empty lines.
+
+	* erc.el 1.13 (erc-member-string): replaced by plain member
+	Otherwise, lots of deleting of empty lines...  I'm not too happy with that
+	but I feel better when the code is "cleaned up".
+
+2001-07-03  Mario Lang  <mlang@delysid.org>
+
+	* erc.el 1.12: Ugly hack, but looks nicer when giving commands
+
+	* erc-speak.el 1.4: ugly hack, but looks nicer now
+
+2001-07-03  Alex Schroeder  <alex@gnu.org>
+
+	* erc.el 1.11 (try-complete-erc-nick): New function.
+	(erc-try-complete-nick): New function.
+	(erc-nick-completion): New option.
+	(erc-complete): Call hippie-expand such that erc-try-complete-nick
+	will be called eventually.  Based on erc-nick-completion
+	try-complete-erc-nick will then complete on the nick at point.
+
+2001-07-02  Mario Lang  <mlang@delysid.org>
+
+	* erc.el 1.10:
+	Insert (erc-current-nick) instead of (erc-display-prompt). good night :)
+
+	* erc.el 1.9:
+	small, but it was anoying, so I just did it (defcustom for erc-join-buffer and erc-join-info-buffer)
+
+2001-06-29  Alex Schroeder  <alex@gnu.org>
+
+	* erc.el 1.8: Use defface to define all faces.
+	Removed some history from the commentary, as well as some other
+	commentary editing.
+
+2001-06-28  Mario Lang  <mlang@delysid.org>
+
+	* erc.el 1.7: hmm, defcustom for erc-user-full-name
+
+	* erc-speak.el 1.3, erc.el 1.6: *** empty log message ***
+
+2001-06-27  Mario Lang  <mlang@delysid.org>
+
+	* erc.el 1.5: typo
+
+	* erc.el 1.4: Some more defcustom
+
+	* erc-speak.el 1.2: nothing, really
+
+2001-06-26  Mario Lang  <mlang@delysid.org>
+
+	* erc.el 1.3: Some defcustom stuff. Still no defgroup though :)
+
+	* erc.el 1.2:
+	Initial change to erc.el (2.0). Mainly list of ideas and features
+	and syntax-table entries.
+
+	* erc-speak.el 1.1.1.1, erc.el 1.1.1.1: Initial Import
+
+	* erc-speak.el 1.1, erc.el 1.1: New file.
+
+    Copyright (C) 2001 Free Software Foundation, Inc.
+  Copying and distribution of this file, with or without modification,
+  are permitted provided the copyright notice and this notice are preserved.
+
+;; Local Variables:
+;; coding: utf-8
+;; End:
+
+;; arch-tag: 306c4b58-f9ae-4f3d-9fd9-db2d743f05a6
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lisp/erc/ChangeLog.2002	Wed Feb 01 10:07:17 2006 +0000
@@ -0,0 +1,2607 @@
+2002-12-31  Francis Litterio  <franl@users.sourceforge.net>
+
+	* erc.el 1.398 (erc-split-command):
+	Removed assignment to free variable "continue".
+	(erc-strip-controls): New function.  Takes a string, returns the string with
+	all IRC color/bold/underline/etc. control codes stripped out.
+	(erc-interpret-controls): If variable erc-interpret-controls-p is nil, now
+	uses erc-strip-controls to strip control codes.
+	(erc-ctcp-reply-ECHO): Changed reference and assignment to free variable "s"
+	into reference/assignment to "msg", which appears to be the original author's
+	intent.
+
+	* erc-list.el 1.8 (erc-chanlist):
+	Changed to use the new erc-once-with-server-event function
+	instead of the old macro of the same name.
+
+	* erc-notify.el 1.10 (erc-notify-timer):
+	Changed to use the new erc-once-with-server-event function
+	instead of the old macro of the same name.  Also fixed a bug were variable
+	erc-last-ison was being read from a non-server buffer (thus giving its default
+	value instead of its per-server value).
+
+	* erc.el 1.397 (erc-once-with-server-event):
+	This is now a function.  It was a macro with a
+	bug (the call to gensym happened at byte-compile-time not macro-call-time).
+	(erc-toggle-debug-irc-protocol): Now [return] is bound to this function in
+	the *erc-protocol* buffer.
+
+2002-12-30  Alex Schroeder  <alex@gnu.org>
+
+	* erc-autoaway.el 1.10 (erc-autoaway-idletimer): Doc,
+	ref. erc-autoaway-use-emacs-idle.
+	(autoaway): Doc, explain different idle definitions.  Reestablish
+	the idletimer only when erc-autoaway-use-emacs-idle is non-nil.
+	(erc-auto-set-away): Doc, ref erc-auto-discard-away.
+	(erc-auto-discard-away): Doc, ref erc-auto-set-away.
+	(erc-autoaway-use-emacs-idle): Doc, ref erc-autoaway-mode, and
+	added a note that this feature is currently broken.
+	(erc-autoaway-reestablish-idletimer): Doc.
+	(erc-autoaway-possibly-set-away): Split test such that
+	erc-time-diff is only computed when necessary, add a comment why
+	erc-process-alive is not necessary.
+	(erc-autoaway-set-away): Test for erc-process-alive.
+
+2002-12-29  Alex Schroeder  <alex@gnu.org>
+
+	* erc-autoaway.el 1.9:
+	Changed the order of defcustoms to avoid errors in the :set property
+	of erc-autoaway-idle-seconds.
+
+2002-12-29  Damien Elmes  <erc@repose.cx>
+
+	* erc-track.el 1.42:
+	* (erc-track-get-active-buffer): remove superflous (+ arg 0)
+
+2002-12-29  Alex Schroeder  <alex@gnu.org>
+
+	* erc-autoaway.el 1.8 (erc-autoaway): Moved the defgroup up to the
+	top, before the define-erc-module call.
+	(autoaway): Extended doc.
+	(erc-autoaway-idle-seconds): Use a :set property to handle
+	erc-autoaway-use-emacs-idle.
+	(erc-auto-set-away): Set default to t.  Added doc strings where
+	necessary, reformatted doc strings such that the first line can
+	stand on its own.  This is important for the output of M-x
+	apropos.
+
+2002-12-28  Jorgen Schaefer  <forcer@users.sourceforge.net>
+
+	* erc-auto.in 1.3:
+	added (provide 'erc-auto), which is required for (require 'erc-auto) :)
+
+	* erc.el 1.396 (erc-display-prompt):
+	Set the face property of the prompt to
+	everything but the last character.
+
+	* erc.el 1.395 (erc-send-current-line):
+	Check wether point is in the input line. If
+	not, just beep and do nothing.
+
+2002-12-28  Alex Schroeder  <alex@gnu.org>
+
+	* erc.el 1.394 (erc-bol):
+	Fixed bug when there is only a prompt, and no property
+	change.
+
+	* erc.el 1.393 (erc-display-prompt): Rewrote using a save-excursion
+	and erc-propertize.  No longer use a field for the prompt, but a
+	plain text property called erc-prompt.
+	(erc-bol): Use the erc-prompt text property instead of a field.
+	Return point instead of t.
+	(erc-parse-current-line): No need to call point here, then, since
+	erc-bol now returns point.
+
+	* Makefile 1.11:
+	make ChangeLog .PHONY, thus forcing it always to be rebuilt.
+
+2002-12-28  Jorgen Schaefer  <forcer@users.sourceforge.net>
+
+	* erc.el 1.392 (erc-log-irc-protocol):
+	Removed check wether get-buffer-create
+	    returned nil. "The value is never nil", says the docstring.
+
+	* erc.el 1.391: Day Of The Small Changes
+
+	(erc-display-prompt): Make the prompt 'front-sticky, which prevents it
+	    from being modified. It *should* also make end-of-line move to the
+	    end of the field (i.e. the end of the prompt) when point is at the
+	    beginning of the prompt, but it doesn't. Dunno why. :(
+
+2002-12-27  Francis Litterio  <franl@users.sourceforge.net>
+
+	* Makefile 1.10:
+	Added "-f" to "rm" command in rule for target "realclean".
+
+	* erc.el 1.390:
+	New function: erc-log-irc-protocol.  Consolidates nearly duplicate code
+	from functions erc-send-command and erc-process-filter into one function.
+
+	* erc.el 1.389 (erc-toggle-debug-irc-protocol):
+	Removed unneeded argument PREFIX and code
+	which referenced it at end of function.
+	(erc-send-command): Now we only append a newline to the logged copy
+	of output protocol text if it doesn't have one.
+
+2002-12-27  Jorgen Schaefer  <forcer@users.sourceforge.net>
+
+	* erc.el 1.388 (erc-toggle-debug-irc-protocol):
+	Display buffer if it's not shown
+	    already, and use view-mode.
+	(erc-toggle-debug-irc-protocol), (erc-send-command),
+	    (erc-process-filter): inhibit-only t to insert into the
+	    *erc-protocol* buffer (view-mode)
+
+2002-12-27  Francis Litterio  <franl@users.sourceforge.net>
+
+	* erc.el 1.387 (erc-mode-map):
+	Removed keybinding for erc-toggle-debug-irc-protocol.
+	(erc-toggle-debug-irc-protocol): Now used erc-make-notice to propertize the
+	face of the enabled/disabled messages in the *erc-protocol* buffer.
+	(erc-send-command): Now outgoing IRC protocol traffic is logged too.
+
+	* erc.el 1.386:
+	Added user-customizable variable erc-debug-irc-protocol.
+	Added function erc-toggle-debug-irc-protocol.
+	(erc-process-filter): Now supports IRC protocol logging.  If variable
+	erc-debug-irc-protocol is non-nil, all IRC protocol traffic is appended
+	to buffer *erc-protocol*, which is created if necessary.
+
+2002-12-27  Jorgen Schaefer  <forcer@users.sourceforge.net>
+
+	* erc.el 1.385 (erc-display-prompt):
+	Don't make the prompt intangible; that didn't
+	    make things that much better for the user, but confused ispell,
+	    which checked the prompt when it should check the first word
+
+2002-12-27  Alex Schroeder  <alex@gnu.org>
+
+	* AUTHORS 1.4: fixed resolve's email add
+
+	* AUTHORS 1.3: added damien
+
+	* erc.el 1.384 (erc-truncate-buffer-on-save):
+	Removed documentation that
+	described behaviour now changed.  It used to say "When nil, no
+	buffer is ever truncated."  This is no longer true; even when
+	buffers are NOT truncated on save, they can be truncated, eg. by
+	adding erc-truncate-buffer to the hook.
+	(erc-logging-enabled): New function.
+	(erc-current-logfile): New function.
+	(erc): Use erc-logging-enabled and erc-current-logfile.
+	(erc-truncate-buffer-to-size): Rewrote it, and made sure to use a
+	(save-restriction (widen) ...) such that the truncation actually
+	runs in the whole buffer, not in the last message only (as
+	erc-insert-post-hook will do!).  This should fix rw's
+	out-of-bounds error.
+	(erc-generate-log-file-name-short): Made all but the BUFFER
+	argument optional.  Doc: Mention
+	erc-generate-log-file-name-function.
+	(erc-generate-log-file-name-long): Doc: Mention
+	erc-generate-log-file-name-function.
+	(erc-save-buffer-in-logs): Use erc-logging-enabled and
+	erc-current-logfile.  Doc: Mention erc-logging-enabbled.
+
+	(erc-encode-string-for-target): Only do the real work when
+	featurep mule; else just return the string unchanged.
+
+2002-12-27  Damien Elmes  <erc@repose.cx>
+
+	* erc.el 1.383:
+	erc-encoding-default: check for (coding-system-p) for older emacs versions
+
+	* erc.el 1.382 (erc-connect): missing ()s added. "don't commit at 2am"
+
+	* erc.el 1.381 (erc-connect):
+	check if (set-process-coding-system) is available before use
+
+2002-12-27  Alex Schroeder  <alex@gnu.org>
+
+	* AUTHORS 1.2: added franl
+
+2002-12-26  Alex Schroeder  <alex@gnu.org>
+
+	* erc-pcomplete.el 1.14 (pcomplete-parse-erc-arguments):
+	Reworked, and fixed a bug that had
+	caused completions to corrupt preceding text under some circumstances.
+
+	* erc.el 1.380 (erc-encoding-default): New.
+	(erc-encode-string-for-target): Use it instead of a hard-coded ctext.
+	(erc-encoding-coding-alist): Doc.
+
+2002-12-26  Francis Litterio  <franl@users.sourceforge.net>
+
+	* erc.el 1.379:
+	Removed fix for bug 658552 recently checked-in, because it doesn't work.
+
+	* erc.el 1.378 (erc-kill-buffer-function):
+	Removed check that connection is up
+	before running erc-kill-server-hook hooks.  Those hooks should use
+	erc-process-alive to avoid interacting with the process.
+
+	* erc.el 1.377:
+	Fixed erc-send-current-line so it no longer assigns the free variable "s", and
+	it doesn't move point to end-of-buffer in non-ERC buffers.  Fixed
+	erc-kill-buffer-function so it doesn't run the erc-kill-server-hook hooks if the
+	server connection is closed.  Fixed bug 658552, which is described in detail at
+	http://sourceforge.net/tracker/index.php?func=detail&aid=658552&group_id=30118&atid=398125
+
+2002-12-26  Alex Schroeder  <alex@gnu.org>
+
+	* erc.el 1.376 (erc-cmd-SMV): Bug, now call erc-version-modules.
+
+	* erc-pcomplete.el 1.13 (erc-pcomplete-version): New.
+
+2002-12-26  Francis Litterio  <franl@users.sourceforge.net>
+
+	* erc-pcomplete.el 1.12:
+	Fix for bug where you could not complete a nick when there was text following
+	the nick.
+
+2002-12-25  Alex Schroeder  <alex@gnu.org>
+
+	* erc.el 1.375 (erc-already-logged-in): Use erc-process-alive.
+	(erc-prepare-mode-line-format): Use erc-process-alive.
+	(erc-process-alive): Check erc-process for boundp and processp.
+
+	* erc.el 1.374 (erc-kill-buffer-function):
+	Do not check wether the process is
+	alive before running the hook, because there might be functions on
+	the hook that need to run even when the process is dead.  And
+	function that wants to check this, should use (erc-process-alive).
+	(erc-process-alive): New function.
+	(erc-kill-server): Use it.
+	(erc-kill-channel): Use it.
+
+	* erc.el 1.373 (erc-kill-buffer-function):
+	Reverted ignore-error change.
+	ignore-error is dangerous because we might miss bugs in functions
+	on erc-kill-server-hook.
+
+	* erc.el 1.372 (erc-kill-buffer-function): Use memq instead of member
+	when checking process-status.  Added doc string with references to
+	the other hooks.
+	(erc-kill-server): Only send the command when the erc-process is
+	still alive.  This prevents the error: "Process
+	erc-irc.openprojects.net-6667 not running" when killing the buffer
+	after having used /QUIT.
+
+2002-12-24  Jorgen Schaefer  <forcer@users.sourceforge.net>
+
+	* erc.el 1.371 (erc-server-ERROR):
+	Show the error reason, not only the originating host.
+
+	* erc.el 1.370 (erc-kill-buffer-function):
+	(ignore-errors ...) in 'erc-kill-server-hook.
+	    When the process for this server does not exist anymore, the hook
+	    will cause an error, effectively preventing the buffer from being
+	    killed.
+
+2002-12-24  Francis Litterio  <franl@users.sourceforge.net>
+
+	* erc-notify.el 1.9:
+	Fixed erc-notify-timer so that it passes the correct nick to
+	the functions on erc-notify-signoff-hook.
+
+2002-12-24  Alex Schroeder  <alex@gnu.org>
+
+	* erc-track.el 1.41: Doc
+
+	* erc-track.el 1.40 (erc-make-mode-line-buffer-name): Removed a
+	superfluous if construct around erc-track-showcount-string.
+	(erc-track-modified-channels): Use 1+.
+	Plus some doc and comment changes.
+
+2002-12-23  Mario Lang  <mlang@delysid.org>
+
+	* erc.el 1.369: Fix (erc-version) string
+
+2002-12-23  Francis Litterio  <franl@users.sourceforge.net>
+
+	* erc.el 1.368:
+	Removed unnecessary assignment to free-variable "p" in erc-downcase.
+
+	* erc.el 1.367:
+	Now /PART reason strings are generated the same way /QUIT reason strings
+	are generated (see variable erc-part-reason).  Also, when a server buffer
+	is killed, a QUIT command is automatically sent to the server.
+
+	* erc.el 1.366:
+	Changed erc-string-no-properties so that it is more efficient.  Now it uses
+	set-text-properties instead of creating and deleting a temporary buffer.
+
+2002-12-21  Jorgen Schaefer  <forcer@users.sourceforge.net>
+
+	* erc.el 1.365:
+	erc-kill-input: added a check to prevent a (ding) and an error when
+	    there's nothing to kill (thanks to Francis Litterio, franl on IRC)
+
+2002-12-21  Mario Lang  <mlang@delysid.org>
+
+	* erc.el 1.364:
+	AWAY notice duplication prevention. erc-prevent-duplicates now set to ("301") by default, and timeout to 60
+
+	* erc.el 1.363: erc-prevent-duplicates: New variable, see docstring
+
+2002-12-20  Jorgen Schaefer  <forcer@users.sourceforge.net>
+
+	* erc-track.el 1.39:
+	erc-track-modified-channels: Use cddr of cell for old-face. cdr of
+	    cell is '(1 . face-name), i have no idea why :)
+
+2002-12-20  Damien Elmes  <erc@repose.cx>
+
+	* erc.el 1.362 (erc-current-nick):
+	check the server buffer is active before using
+
+	Also tabified and cleaned up some trailing whitespace
+
+2002-12-15  Mario Lang  <mlang@delysid.org>
+
+	* erc-track.el 1.38: erc-track-count patch by az
+
+2002-12-14  Damien Elmes  <erc@repose.cx>
+
+	* erc.el 1.361:
+	last-peers: initialise to a cons. thanks to Francis Litterio
+	    <franl@world.std.com> for the patch
+
+	* erc.el 1.360:
+	erc-kill-channel-hook, erc-kill-buffer-hook, (erc-kill-channel):
+	    both hooks now call erc-save-buffer-in-logs, so that query buffers are
+	    saved properly now, and not just channel buffers.
+
+2002-12-13  Alex Schroeder  <alex@gnu.org>
+
+	* erc-track.el 1.37 (erc-unique-channel-names): Fix another #hurd
+	vs. #hurd-bunny bug.
+
+	* erc-match.el 1.17 (match): No longer modify erc-send-modify-hook,
+	since it does not work without a parsed text property, anyway.
+	(erc-keywords): Allow cons cells.
+	(erc-remove-entry-from-list): Deal with cons cells.
+	(erc-keyword-p): Ditto.
+	(erc-match-message): Ditto.
+
+	Moved nil to the beginning of the list, removed :tags for the
+	-type variables:
+	(erc-current-nick-highlight-type): Ditto.
+	(erc-pal-highlight-type): Ditto.
+	(erc-fool-highlight-type): Ditto.
+	(erc-keyword-highlight-type): Ditto.
+	(erc-dangerous-host-highlight-type): Ditto.
+	(erc-log-matches-flag): Moved nil to the beginning.
+
+2002-12-11  Jorgen Schaefer  <forcer@users.sourceforge.net>
+
+	* erc.el 1.359:
+	erc-beg-of-input-line: Don't do (goto-char (beginning-of-line)), since
+	    beginning-of-line always moves point and returns nil. Thanks to
+	    franl on IRC for noting this.
+
+	* erc-stamp.el 1.20:
+	erc-insert-timestamp-left, erc-insert-timestamp-right: Made the
+	    timestamp a 'field named 'erc-timestamp. Now end-of-line and
+	    beginning-of-line will move over the timestamp.
+
+2002-12-10  Damien Elmes  <erc@repose.cx>
+
+	* erc-button.el 1.34 (erc-button-add-button):
+	make the created button rear-nonsticky, to allow
+	cutting and pasting of buttons without worrying about the button properties
+	being inherited by the text typed afterwards.
+
+	* erc.el 1.358: save logfile when killing buffer
+
+2002-12-09  Alex Schroeder  <alex@gnu.org>
+
+	* erc-track.el 1.36 (erc-modified-channels-display): Reworked.
+	(erc-track-face-more-important-p): Removed.
+	(erc-track-find-face): Return only one face.
+	(erc-track-modified-channels): Reworked.
+	(erc-modified-channels-string): Changed from (BUFFER FACE...) to
+	(BUFFER . FACE)
+
+	* erc-stamp.el 1.19 (erc-insert-timestamp-right): Do not assume
+	erc-fill-column is available.
+
+2002-12-09  Jorgen Schaefer  <forcer@users.sourceforge.net>
+
+	* erc.el 1.357:
+	erc-ech-notices-in-minibuffer-flag, erc-minibuffer-notice: Clarified
+	    the difference in the docstrings.
+
+2002-12-08  Jorgen Schaefer  <forcer@users.sourceforge.net>
+
+	* erc.el 1.356: erc-noncommands-list: added erc-cmd-SM and erc-cmd-SMV
+
+2002-12-08  Alex Schroeder  <alex@gnu.org>
+
+	* erc.el 1.355 (erc-cmd-SM): New.
+	(erc-cmd-SMV): New.
+
+	* erc.el 1.354 (erc-modes): New.
+
+2002-12-08  Jorgen Schaefer  <forcer@users.sourceforge.net>
+
+	* erc-compat.el 1.9:
+	field-end: use (not (fboundp 'field-end)) instead of (featurep 'xemacs)
+
+2002-12-08  Alex Schroeder  <alex@gnu.org>
+
+	* erc.el 1.353 (erc-version-modules): New.
+
+2002-12-08  Mario Lang  <mlang@delysid.org>
+
+	* debian/changelog 1.19, debian/control 1.7, debian/scripts/startup.erc 1.3:
+	debian release 3.0.cvs.20021208
+
+2002-12-08  Jorgen Schaefer  <forcer@users.sourceforge.net>
+
+	* erc.el 1.352 (erc-split-command): Do the right thing with CTCPs.
+
+2002-12-08  Mario Lang  <mlang@delysid.org>
+
+	* erc-stamp.el 1.18: Be a bit more functional
+
+2002-12-08  Jorgen Schaefer  <forcer@users.sourceforge.net>
+
+	* erc-compat.el 1.8:
+	XEmacs doesn't seem to have field-end, so we provide our own version here.
+
+2002-12-08  Mario Lang  <mlang@delysid.org>
+
+	* Makefile 1.9: Small fixes to debrelease target
+
+2002-12-08  Jorgen Schaefer  <forcer@users.sourceforge.net>
+
+	* erc.el 1.351:
+	make-obsolete-variable: xemacs doesn't have the WHEN parameter, remove it.
+
+2002-12-07  Jorgen Schaefer  <forcer@users.sourceforge.net>
+
+	* erc-imenu.el 1.5 (erc-create-imenu-index):
+	Use (forward-line 0) instead of
+	  (beginning-of-line) now, sine the latter ignores fields (used in the
+	  prompt).
+
+	* erc.el 1.350:
+	Rewrite of the prompt stuff to use a field named 'erc-prompt:
+
+	erc-prompt: Removed getter and setter functions. The properties were
+	  already set (and overwritten) in erc-display-prompt.
+	(erc-prompt): Add the trailing space here, not all over the code.
+	(erc-display-prompt): Cleaned up a bit. The text-properties now are
+	  valid on the whole prompt. Also, made the prompt 'intangible to
+	  avoid confused users.
+	(erc-bol): Now use the field 'erc-prompt for finding the prompt
+	(erc-parse-current-line): Cleaned up considerably. Uses (erc-bol) now.
+	(erc-load-irc-script-lines): Adjusted for the new (erc-prompt).
+	(erc-save-buffer-in-logs): Adjusted for the new (erc-prompt).
+
+	* erc.el 1.349:
+	erc-uncontrol-input-line: The comment said "Consider it deprecated",
+	so I removed it now.
+	erc-prompt-interactive-input: Marked obsolete as of 1.348
+
+	* erc.el 1.348:
+	erc-smiley, erc-unmorse: Put at the end to separate it from the
+	important parts of erc.el.
+
+2002-12-07  Alex Schroeder  <alex@gnu.org>
+
+	* erc-stamp.el 1.17 (erc-insert-timestamp-right): New algorithm.
+
+2002-12-07  Jorgen Schaefer  <forcer@users.sourceforge.net>
+
+	* erc.el 1.347:
+	last-peers, erc-message: Explained what last-peers is used for.
+
+2002-12-07  Alex Schroeder  <alex@gnu.org>
+
+	* erc-page.el 1.3 (erc-cmd-PAGE): New function.
+	(erc-ctcp-query-PAGE): Use the catalog entry for the message, too.
+	(erc-ctcp-query-PAGE-hook): Added custom type.
+	(erc-page-function): Changed custom type from ... function-item to
+	... function.
+	As well as doc strings.
+
+2002-12-06  Alex Schroeder  <alex@gnu.org>
+
+	* erc-page.el 1.2: provide feature at the end
+
+2002-12-06  Brian P Templeton  <bpt@tunes.org>
+
+	* erc-nickserv.el 1.10:
+	Added austnet in erc-nickserv.el (thanks to Damien Elmes
+	<resolve@repose.cx>)
+
+2002-12-05  Mario Lang  <mlang@delysid.org>
+
+	* erc-complete.el 1.13: Add autoload cookie
+
+	* erc-speak.el 1.24: Small fix to make proper voice-changes
+
+2002-12-05  Alex Schroeder  <alex@gnu.org>
+
+	* erc-lang.el 1.1: New
+
+2002-12-03  Jorgen Schaefer  <forcer@users.sourceforge.net>
+
+	* erc.el 1.346:
+	erc-mode-map: Put back C-c C-p (PART) and C-c C-q (QUIT)
+
+2002-12-02  Jorgen Schaefer  <forcer@users.sourceforge.net>
+
+	* erc.el 1.345:
+	erc-insert-post-hook: Add :options erc-make-read-only, erc-save-buffer-in-logs
+	erc-send-post-hook: Add :options erc-make-read-only
+
+	* erc.el 1.344: erc-insert-hook: Removed ("this hook is obsolescent")
+	erc-insert-post-hook: Added :options '(erc-truncate-buffer)
+
+2002-12-02  Mario Lang  <mlang@delysid.org>
+
+	* erc.el 1.343: Add missing requires
+
+2002-11-29  Jorgen Schaefer  <forcer@users.sourceforge.net>
+
+	* erc.el 1.342 (erc-quit-reason-normal):
+	Remove v before %s so it's "Version ..." not
+	   "vVersion ..."
+
+2002-11-26  Alex Schroeder  <alex@gnu.org>
+
+	* erc-compat.el 1.7 (erc-encode-coding-string): Add second argument
+		coding-system, and for non-mule xemacsen, use a new defun instead
+		of identity.
+
+	* erc.el 1.341:  (define-erc-module): Use the appropriate group.
+	(erc-port): Changed custom type.
+	(erc-insert-hook): Custom group changed to erc-hooks.
+	(erc-after-connect): ditto
+	(erc-before-connect): ditto
+	(erc-disconnected-hook): ditto
+
+	* erc-button.el 1.33 (erc-button): New group, changed all custom groups
+	from erc to erc-button, but left all erc-faces as-is.
+
+	* erc-track.el 1.35 (erc-track): New group, changed all custom groups
+	from erc to erc-track.
+
+2002-11-26  Mario Lang  <mlang@delysid.org>
+
+	* erc-macs.el 1.1:
+	Macros for erc-victim handling.  Primary idea is to use setf and some fancy things to get nice syntax. have a look
+
+2002-11-26  Jorgen Schaefer  <forcer@users.sourceforge.net>
+
+	* erc.el 1.340:
+	pings, erc-cmd-PING, erc-ctcp-reply-PING, catalog entry CTCP-PING:
+	Cleaned up. Removed buffer-local variable pings which stored a list of
+	all sent CTCP PING requests. Now send our full time with the CTCP PING
+	request and interpret the answer.
+
+2002-11-25  Jorgen Schaefer  <forcer@users.sourceforge.net>
+
+	* erc.el 1.339: nick-stk: replaced by the local variable current-nick.
+
+2002-11-25  Alex Schroeder  <alex@gnu.org>
+
+	* erc.el 1.338 (erc-send-command): Use erc-encode-string-for-target.
+	(erc-encode-string-for-target): New.
+
+	* erc-compat.el 1.6 (erc-encode-coding-string): Add second argument
+	coding-system, and for non-mule xemacsen, use a new defun instead
+	of identity.
+
+	* erc-nickserv.el 1.9 (erc-nickserv-version): New.
+
+2002-11-25  Jorgen Schaefer  <forcer@users.sourceforge.net>
+
+	* Makefile 1.8:
+	UNCOMPILED: erc-chess.el depends on chess-network.el, which might not
+	be installed. Don't compile it.
+
+	* erc.el 1.337:
+	erc-mode-map: Added C-a as erc-bol (no reason why it shouldn't be),
+	and removed C-c C-p (part channel) and C-c C-q (quite server) as these
+	are a bit drastic in their consequences and easy to mistype.
+
+2002-11-24  Jorgen Schaefer  <forcer@users.sourceforge.net>
+
+	* erc-track.el 1.34: erc-track-faces-priority-list: Extended list
+
+	* erc.el 1.336:
+	channel-members: Updated docstring: We have a VOICE predicate, too.
+
+	* erc-track.el 1.33 (erc-unique-substrings):
+	Don't shorten a single channel to "#", but
+	always give at least 2 chars (except when there are no two chars).
+
+2002-11-23  Jorgen Schaefer  <forcer@users.sourceforge.net>
+
+	* erc-nickserv.el 1.8:
+	support for BrasNET. Thanks to rw on IRC for the settings.
+
+2002-11-23  Alex Schroeder  <alex@gnu.org>
+
+	* erc.el 1.335: (erc-default-recipients, erc-session-user-full-name)
+		(nick-stk, pings, erc-announced-server-name, erc-connected)
+		(channel-user-limit, last-peers, invitation, away, channel-list)
+		(last-sent-time, last-ping-time, last-ctcp-time, erc-lines-sent)
+		(erc-bytes-sent, quitting, bad-nick, erc-logged-in)
+		(erc-default-nicks): Defvars.
+
+	* erc-compat.el 1.5: Switched tests to iso-8859-1 instead of latin-1.
+
+	* erc-compat.el 1.4 (erc-compat-version): New.
+
+2002-11-22  Alex Schroeder  <alex@gnu.org>
+
+	* erc.el 1.334 (smiley): Smileys are a very small module, now.
+
+2002-11-22  Jorgen Schaefer  <forcer@users.sourceforge.net>
+
+	* erc.el 1.333:
+	erc-event-to-hook, erc-event-to-hook-name: eval-and-compile these,
+	    since we need them in a macro. ERC now compiles again!
+
+	* erc-speak.el 1.23:
+	erc-minibuffer-privmsg: Removed setting this variable to nil, since it
+	    was removed from erc.el.
+
+	* erc.el 1.332 (erc-interactive-input-map): Added docstring.
+	(erc-wash-quit-reason): Extended docstring.
+	(erc-server-ERROR): Added docstring.
+	(erc-server-321): buffer-local variable channel-list probably
+	    shouldn't be renamed erc-channel-list - removed FIXME.
+
+	* erc.el 1.331: small cleanup.
+	("was not used anymore" here means "not used in erc/*.el nor in
+	fsbot", thanks to deego for checking that.)
+
+	erc-minibuffer-privmsg: Removed (was not used anymore)
+	(erc-reformat-command): Removed (was not used anymore)
+	(erc-strip-erc-parsed-property): Removed (was not used anymore)
+	(erc-process-ctcp-response): Removed (replaced by ctcp-query-XXX-hook)
+	(erc-send-paragraph): Removed ("Note that this function is obsolete,
+	    erc-send-current-line handles multiline input.")
+	(erc-input-hook): Removed ("This hook is obsolete. See
+	    `erc-send-pre-hook', `erc-send-modify-hook' and
+	    `erc-send-post-hook' instead.")
+	(erc-message-hook): Removed ("This hook is obsolete. See
+	    `erc-server-PRIVMSG-hook' and `erc-server-NOTICE-hook'.")
+	(erc-cmd-default-channel): Removed ("FIXME: no clue what this is
+	    supposed to do." - it was supposed to prepend the default channel
+	    to a command before sending it. E.g. typing "/FOO now!" would send
+	    the IRC command "FOO #mycurrentchannel now!")
+
+	* erc.el 1.330:
+	erc-ctcp-query-PING: Send the whole argument back, not just the first
+	number. This is required for many clients (e.g. irssi, BitchX, ...)
+	which send their ping times in two different numbers for microsecond
+	accuracy.
+
+2002-11-22  Alex Schroeder  <alex@gnu.org>
+
+	* erc-track.el 1.32 (erc-track-shorten-function): Allow nil.
+
+2002-11-21  Alex Schroeder  <alex@gnu.org>
+
+	* erc-track.el 1.31 (erc-unique-channel-names): Fixed bug that appeared
+	if one target name was a substring of another -- eg. #hurd and
+	#hurd-bunny.  Added appropriate test.
+
+2002-11-20  Jorgen Schaefer  <forcer@users.sourceforge.net>
+
+	* erc-track.el 1.30:
+	erc-unique-channel-names: Don't take a substring of channel that could
+	be longer than the channel, but at most (min (length candidate)
+	(length channel). (thanks to deego for noticing this)
+
+2002-11-19  Mario Lang  <mlang@delysid.org>
+
+	* erc-notify.el 1.8: * (require pcomplete): Only when compiling.
+
+2002-11-19  Jorgen Schaefer  <forcer@users.sourceforge.net>
+
+	* erc-track.el 1.29:
+	erc-track-faces-priority-list: New variable, defines what faces will
+	be shown in the modeline. If set to nil, the old behavior ("all")
+	remains.
+	erc-track-face-more-important-p: new function
+	erc-track-find-face: new function
+
+2002-11-19  Alex Schroeder  <alex@gnu.org>
+
+	* erc-fill.el 1.20 (erc-stamp): Require it.
+
+	* erc-match.el 1.16 (away): devar for the compiler.
+
+	* erc-stamp.el 1.16 (stamp): Moved.
+
+	* erc.el 1.329 (erc-version-string): New version.
+
+	* erc-autoaway.el 1.7 (erc-autoaway-idletimer): Moved to the front of
+	the file.
+
+	* erc-auto.in 1.2: (generated-autoload-file, command-line-args-left):
+	Added defvar without value to silence byte compiler.
+
+	* Makefile 1.7 (realclean): renamed fullclean to realclean.
+	(UNCOMPILED): New list, for erc-bbdb.el, erc-ibuffer.el,
+	erc-speak.el.
+	(SOURCE): Do not compile UNCOMPILED.
+	(release): New target.
+	(ChangeLog): New target.
+	(todo): New target.
+
+	* erc-complete.el 1.12 (erc-match): Require it.
+	(hippie-exp): Require it.
+
+	* erc-ezbounce.el 1.3 (erc): Require it.
+
+	* erc-imenu.el 1.4 (imenu): Require it.
+
+	* erc-nickserv.el 1.7 (erc-networks): Moved up.
+
+	* erc-notify.el 1.7 (pcomplete): Require it.
+
+	* erc-replace.el 1.5 (erc): Require it.
+
+	* erc-sound.el 1.3 (sound): Typo -- define-key in erc-mode-map.
+
+	* erc-speedbar.el 1.10 (dframe): Require it.
+	(speedbar): Require it.
+
+	* erc-track.el 1.28 (erc-default-recipients): devar for the compiler.
+
+	* README 1.1: New file.
+
+2002-11-18  Mario Lang  <mlang@delysid.org>
+
+	* AUTHORS 1.1: File needed for mkChangeLog
+
+	* mkChangeLog 1.1: Original code by mhp
+
+2002-11-18  Alex Schroeder  <alex@gnu.org>
+
+	* erc-button.el 1.32 (erc-button-list): Renamed to erc-list and moved
+	to erc.el.
+
+	* erc.el 1.328 (erc-list): New.
+
+	* erc-track.el 1.27 (erc-make-mode-line-buffer-name): Simplified.
+	(erc-modified-channels-display): Simplified.  Now works with all
+	faces, and fixes the bug that when two faces where used (bold
+	erc-current-nick-face), then no faces was added.
+
+	* erc-track.el 1.26: Lots of new tests.  Moved some defuns around in
+	the file.
+	(erc-all-channel-names): Renamed.
+	(erc-all-buffer-names): New name, now include query buffers as
+	well.
+	(erc-modified-channels-update-inside): New variable.
+	(erc-modified-channels-update): Use it to prevent running display
+	if already inside it.  This prevented debugging of
+	`erc-modified-channels-display'.
+	(erc-make-mode-line-buffer-name): Moved.
+	(erc-track-shorten-names): Don't test using erc-channel-p as that
+	failed with query buffers.
+	(erc-unique-substrings): Move setq i + 1 to the end of the while
+	loop, so that start is used as a default value instead of start +
+	1.
+
+2002-11-18  Jorgen Schaefer  <forcer@users.sourceforge.net>
+
+	* erc-track.el 1.25:
+	erc-unique-substrings: define this before using it in assert
+
+	* erc.el 1.327:
+	with-erc-channel-buffer: Define *before* using this macro. This
+	hopefully fixes a bug noted on IRC.
+
+	* erc-notify.el 1.6:
+	erc-notify-signon-hook, erc-notify-signoff-hook: New hooks. They're
+	even run when their name suggests!
+
+2002-11-18  Alex Schroeder  <alex@gnu.org>
+
+	* erc-list.el 1.7: Typo.
+
+	* erc-speedbar.el 1.9: Whitespace only.
+
+	* erc.el 1.326 (define-erc-module): Avoid defining an alias if name and
+	alias are the same.
+
+	* erc-ibuffer.el 1.17: URL
+
+	* erc-imenu.el 1.3 (erc-imenu-version): New constant.
+
+	* erc-ibuffer.el 1.16 (erc-ibuffer-version): New constant.
+
+	* erc-ibuffer.el 1.15: File header, comments.
+
+	* erc-fill.el 1.19 (erc-fill-version): New constant.
+
+	* erc-ezbounce.el 1.2 (erc-ezb-version): New constant.
+
+	* erc-complete.el 1.11 (erc-complete-version): New constant.
+
+	* erc-chess.el 1.21 (erc-chess-version): New constant.
+
+	* erc-chess.el 1.20: Whitespace only.
+
+	* erc-bbdb.el 1.20 (erc-bbdb-version): Typo.
+
+	* erc-bbdb.el 1.19 (erc-bbdb-version): New constant.
+	Lots of whitespace changes.  Changes to the header.
+
+	* erc-track.el 1.24 (erc-track-shorten-aggressively): Doc.
+	(erc-all-channel-names): New function.
+	(erc-unique-channel-names): New function.
+	(unique-substrings): Renamed.
+	(erc-unique-substrings): New name
+	(unique-substrings-1): Renamed.
+	(erc-unique-substring-1): New name.  Added lots of tests.
+	(erc-track-shorten-names): Call erc-unique-channel-names instead
+
+	* erc-match.el 1.15 (match): Rewrote a as module.
+
+2002-11-17  Alex Schroeder  <alex@gnu.org>
+
+	* erc-netsplit.el 1.6 (erc-netsplit-version): New.
+	(netsplit): Defined as a module, replacing erc-netsplit-initialize
+	and erc-netsplit-destroy.
+
+2002-11-17  Jorgen Schaefer  <forcer@users.sourceforge.net>
+
+	* erc-track.el 1.23 (erc-track-switch-buffer):
+	define-erc-module defines erc-track-mode,
+	not erc-track-modified-channels-mode.
+
+	* erc.el 1.325:
+	Variables erc-play-sound, erc-sound-path, erc-default-sound,
+	erc-play-command, erc-ctcp-query-SOUND-hook and functions
+	erc-cmd-SOUND, erc-ctcp-query-SOUND, erc-play-sound, erc-toggle-sound
+	moved to erc-sound.el
+
+	Variables erc-page-function, erc-ctcp-query-PAGE-hook and function
+	erc-ctcp-query-PAGE moved to erc-page.el
+
+	* erc-page.el 1.1:
+	erc-page.el: New file. CTCP PAGE support for ERC, extracted from erc.el.
+
+	* erc-sound.el 1.2:
+	defin-erc-module: Typo. Autoload should do erc-sound-mode and "erc-sound".
+
+	* erc-sound.el 1.1:
+	erc-sound.el: New file. Contains all the CTCP SOUND stuff from erc.el.
+
+	* erc.el 1.324 (erc-process-ctcp-request):
+	Removed (old-style CTCP handling)
+	(erc-join-autogreet): Removed (was broken anyways)
+
+2002-11-17  Alex Schroeder  <alex@gnu.org>
+
+	* erc-button.el 1.31 (erc-button-version): New constant.
+
+	* erc-button.el 1.30 (button): rewrote as a module.
+
+2002-11-17  Jorgen Schaefer  <forcer@users.sourceforge.net>
+
+	* erc.el 1.323: New functions:
+	(erc-event-to-hook), (erc-event-to-hook-name): Convert an event to the
+	corresponding hook. The latter only returns the name, while the former
+	interns the hook symbol and returns it.
+
+2002-11-17  Alex Schroeder  <alex@gnu.org>
+
+	* erc-replace.el 1.4:
+	Practically total rewrite.  All smiley stuff deleted.
+
+	* erc-track.el 1.22 (track): typo.
+
+	* erc.el 1.322 (define-erc-module): Doc change.
+
+2002-11-17  Jorgen Schaefer  <forcer@users.sourceforge.net>
+
+	* erc-autoaway.el 1.6: Changed to use define-erc-module.
+
+	* erc.el 1.321 (define-erc-module):
+	Make the enable/disable functions interactive.
+
+	* erc.el 1.320 (erc):
+	Don't use switch-to-buffer when we're in the minibuffer,
+	because that does not work. Use display-buffer instead. This leaves
+	two problems: The point does not advance to the end of the buffer for
+	whatever reason, and after leaving the minibuffer, the new window gets
+	buried.
+
+2002-11-17  Alex Schroeder  <alex@gnu.org>
+
+	* erc-stamp.el 1.15 (stamp): Doc change.
+
+	* erc-stamp.el 1.14 (erc-stamp-version): New constant.
+	(stamp): downcase alias name of the mode.
+
+	* erc.el 1.319 (define-erc-module): Added defalias option, renamed
+	parameters again.
+
+	* erc-track.el 1.21: erc-track-modified-channels-mode is now only an
+	alias to erc-track-mode.  Only erc-track-mode is autoloaded.
+	(track): Rewrote call to define-erc-module.
+
+2002-11-16  Mario Lang  <mlang@delysid.org>
+
+	* debian/README.Debian 1.5: * Spelling fix
+
+	* erc-fill.el 1.18: * Fix autoload definition for erc-fill-mode
+
+	* debian/control 1.6, debian/maint/postinst 1.4, debian/maint/prerm 1.4:
+	* Remove /usr/doc -> /usr/share/doc link handling
+
+	* debian/changelog 1.18: * Sync with reality
+
+	* debian/scripts/startup.erc 1.2:
+	* Add /usr/share/emacs/site-lisp/erc/ to load-path
+	* (load "erc-auto")
+
+	* debian/README.Debian 1.4:
+	* Info about the changes since last release updated
+
+	* erc-pcomplete.el 1.11: * Fix emacs/xemacs compatibility
+
+	* debian/scripts/install 1.10: * Dont compile erc-compat, fix ELCDIR
+
+	* debian/control 1.5: * Change maintainer field
+
+	* erc.el 1.318:
+	* (defin-erc-module): Renamed argument mode-name to mname because silly byte-compiler thought we were talking about `mode-name'.
+
+	* Makefile 1.6: * Added debrelease target
+
+	* erc-bbdb.el 1.18, erc-pcomplete.el 1.10, erc-stamp.el 1.13, erc.el 1.317:
+	* (define-erc-module): Added mode-name argument.
+	* Converted erc-bbdb, erc-pcomplete and erc-stamp to new macro.
+	* autoload fixes
+
+	* erc-bbdb.el 1.17:
+	* Create a global-minor-mode (i.e., make it a proper erc-module)
+
+	* erc.el 1.316: * (define-erc-modle): New defmacro
+
+2002-11-16  Jorgen Schaefer  <forcer@users.sourceforge.net>
+
+	* erc-autoaway.el 1.5 (erc-autoaway-idle-seconds):
+	t in docstrings should be non-nil
+
+2002-11-16  Alex Schroeder  <alex@gnu.org>
+
+	* erc-autoaway.el 1.4, erc-button.el 1.29, erc-fill.el 1.17, erc-match.el 1.14, 
+	  erc-menu.el 1.9, erc-ring.el 1.5, erc-track.el 1.20:
+	Cleanup of file headers: copyright years, GPL mumbo-jumbo, commentaries.
+
+	* erc-stamp.el 1.12 (erc-insert-away-timestamp-function):
+	New custom type.
+	(erc-insert-timestamp-function): New custom type.
+
+	* erc-fill.el 1.16 (erc-fill-function): Doc, new custom type.
+	(erc-fill-static): Doc.
+	(erc-fill-enable): New function.
+	(erc-fill-disable): New function.
+	(erc-fill-mode): New function.
+
+	* erc-match.el 1.13 (erc-match-enable): add-hook for both
+	erc-insert-modify-hook and erc-send-modify-hook.
+	(erc-match-disable): remove-hook for both
+	erc-insert-modify-hook and erc-send-modify-hook.
+
+2002-11-15  Jorgen Schaefer  <forcer@users.sourceforge.net>
+
+	* erc-autoaway.el 1.3:
+	- Added a way to use auto-away using emacs idle timers
+	- Renamed erc-set-autoaway to erc-autoaway-possibly-set-away for consistency
+
+2002-11-14  Jorgen Schaefer  <forcer@users.sourceforge.net>
+
+	* erc.el 1.315: erc-mode-map: Removed the C-c C-g binding for erc-grab
+
+	* erc.el 1.314:
+	(erc-server-341) Another instance of the channel/chnl problem i didn't
+	see last time
+
+2002-11-14  Alex Schroeder  <alex@gnu.org>
+
+	* erc-compat.el 1.3 (erc-decode-coding-string): typo
+
+2002-11-14  Jorgen Schaefer  <forcer@users.sourceforge.net>
+
+	* erc.el 1.313 (erc-server-341):
+	variable name should be chnl not channel, as it is
+	used this way in this function, and the other erc-server-[0-9]* use
+	chnl too.
+
+	* erc-autoaway.el 1.2:
+	Set back on all servers, not just the current one, since we're set
+	away on all servers as well.
+
+	* HISTORY 1.2: Fixed typo (ngu.org => gnu.org)
+
+	* erc-autoaway.el 1.1, erc-fill.el 1.15, erc.el 1.312: erc-autoaway.el:
+	* new file
+
+	erc.el:
+	* Removed auto-discard-away facility (now included in erc-autoaway.el)
+	* (erc-away-p): new function
+
+	erc-fill.el:
+	* (erc-fill-variable): Check wether erc-timestamp-format is bound before
+	                       using it (erc-fill.el does not require erc-stamp).
+
+2002-11-10  Alex Schroeder  <alex@gnu.org>
+
+	* TODO 1.4:
+	TODO: moved it to http://www.emacswiki.org/cgi-bin/wiki.pl?ErcTODO
+
+	* erc.el 1.311 (with-erc-channel-buffer): Rudimentary doc string.
+
+2002-11-09  Alex Schroeder  <alex@gnu.org>
+
+	* erc-button.el 1.28 (erc-nick-popup-alist): Made a defcustom.
+
+	* erc-button.el 1.27 (erc-button-disable): New function.
+	(erc-button-enable): New function, replaces the add-hook calls at top-level.
+	(erc-button-mode): New minor mode.
+
+2002-11-08  Alex Schroeder  <alex@gnu.org>
+
+	* erc-button.el 1.26 (erc-button-entry): Use erc-button-syntax-table.
+
+	* erc.el 1.310, erc-stamp.el 1.10: Doc changes.
+
+	* erc-match.el 1.12 (erc-match-mode): New function, replacing the
+	add-hook.
+	(erc-match-enable): New function.
+	(erc-match-disable): New function.
+	(erc-current-nick-highlight-type): Changed from 'nickname to 'nick
+	to make it consistent with the others.
+	(erc-match-message): Ditto.
+
+	* erc-button.el 1.25 (erc-button-syntax-table): New variable.
+	(erc-button-add-buttons): Use it.
+
+2002-11-06  Mario Lang  <mlang@delysid.org>
+
+	* erc.el 1.309:
+	1) (bug) ERC pops up a new buffer and window when being messaged
+	   from an ignored person. fixed
+	2) (misfeature) ERC notices the user in the minibuffer when it
+	   ignores something - this can get very annoying, since the
+	   minibuffer is also visible when not looking at ERC buffers.
+	   Added a customizeable variable for this, the default is nil.
+	3) (wishlist) There is no IGNORE or UNIGNORE command.
+	   Added.
+	4) (wishlist) Some IRC clients, notably irssi, allow the user to
+	   ignore "replies" to ignored people. A reply is defined as a
+	   line starting with "nick:", where nick is the nick of an
+	   ignored person. Added that functionaly.
+	Done by Jorgen Schaefer <forcer@forcix.cx>
+
+2002-11-02  Alex Schroeder  <alex@gnu.org>
+
+	* erc.el 1.308 (erc-connect): set-process-coding-system to raw-text.
+
+2002-11-01  Brian P Templeton  <bpt@tunes.org>
+
+	* erc-pcomplete.el 1.9, erc-stamp.el 1.9, erc-track.el 1.19:
+	Fixed more autoloads
+
+	* erc-compat.el 1.2: Added autoload for erc-define-minor-mode
+
+2002-11-01  Mario Lang  <mlang@delysid.org>
+
+	* erc.el 1.307: * (erc-send-command): will break long messages into
+	a bunch of smaller ones, to prevent them from being truncated by the server.
+	The patch also axes some trailing whitespace. :-) <resolve>
+
+2002-10-31  Alex Schroeder  <alex@gnu.org>
+
+	* erc-pcomplete.el 1.8 (erc-compat): Require.
+	(erc-completion-mode): Use erc-define-minor-mode.
+
+	* erc-track.el 1.18 (erc-compat): Require.
+	(erc-track-modified-channels-mode): Use erc-define-minor-mode.
+
+	* erc-stamp.el 1.8 (erc-compat): Require.
+	(erc-timestamp-mode): Use erc-define-minor-mode.
+
+	* erc-compat.el 1.1: New file with the code for erc-define-minor-mode,
+	erc-encode-coding-string and erc-decode-coding-string.  Essentially
+	all the stuff that cannot be tested for using a simple boundp or
+	fboundp -- eg. because the number of arguments are wrong.
+
+	* erc.el 1.306 (erc-compat): Require.
+	(erc-process-coding-system): Moved to erc-compat.el.
+	(erc-connect): Do not set-process-coding-system.
+	(encode-coding-string): Compatibility code moved to erc-compat.el.
+	(decode-coding-string): Compatibility code moved to erc-compat.el.
+	(erc-encode-coding-string): Compatibility code moved to erc-compat.el.
+	(erc-decode-coding-string): Compatibility code moved to erc-compat.el.
+
+2002-10-27  Alex Schroeder  <alex@gnu.org>
+
+	* erc.el 1.305 (erc-display-line-1): Removed call to
+	erc-decode-coding-string.
+	(erc-parse-line-from-server): Added call to
+	erc-decode-coding-string before anything gets parsed at all.
+	(erc-decode-coding-string): Use undecided coding system.
+
+2002-10-24  Sandra Jean Chua  <sacha@free.net.ph>
+
+	* erc-button.el 1.24, erc.el 1.304:
+	Added LASTLOG command and action for nick-button
+
+2002-10-22  Sandra Jean Chua  <sacha@free.net.ph>
+
+	* erc-pcomplete.el 1.7:
+	Fixed nopruning bug, added /MODE channel (mode) [nicks...] completion - mode not completed yet.
+
+2002-10-16  Sandra Jean Chua  <sacha@free.net.ph>
+
+	* erc-pcomplete.el 1.6:
+	Fixed 'Hi delysid:' bug in SAY completion after realizing that pcomplete on commands already took care of completing the initial nick:
+
+2002-10-15  Mario Lang  <mlang@delysid.org>
+
+	* erc-pcomplete.el 1.5: update from sachac
+
+2002-10-13  Alex Schroeder  <alex@gnu.org>
+
+	* erc.el 1.303 (erc-emacs-time-to-erc-time): Catch when tm is nil.
+
+2002-10-11  Andreas Fuchs  <asf@void.at>
+
+	* erc.el 1.302:
+	* Fixed `erc-scroll-to-bottom' to scroll to the bottom even when
+	  in the middle of a line. Might also fix the Magic ECHAN Bug[tm]. (-:
+
+2002-10-11  Mario Lang  <mlang@delysid.org>
+
+	* erc-nickserv.el 1.6: Fixed erc-networks for the opn->freenode change
+
+2002-10-08  Mario Lang  <mlang@delysid.org>
+
+	* erc-pcomplete.el 1.4:
+	Make erc-completion-mode work interactively with already joined channel buffers
+
+	* erc-chess.el 1.19: Add autoload cookies
+
+	* erc-notify.el 1.5: Add pcomplete support
+
+	* erc.el 1.301:
+	Remove autoload statments, remove autoload cookie from erc-mode and erc-info-mode
+
+	* erc-fill.el 1.14, erc-match.el 1.11: add/remove autoload cookies
+
+2002-10-06  Alex Schroeder  <alex@gnu.org>
+
+	* erc-pcomplete.el 1.3 (erc-completion-mode): New global minor mode
+	with autoload cookie.
+	(erc-pcomplete-enable): Renamed erc-pcomplete-initialize.
+	(erc-pcomplete-disable): New function.
+
+	* erc-complete.el 1.10: Doc changes.
+
+	* erc-stamp.el 1.7 (erc-stamp-enable): Renamed erc-stamp-initialize.
+	(erc-stamp-disable): Renamed erc-stamp-destroy.
+	(erc-timestamp-mode): Use new names.
+
+	* erc.el 1.300: Removed autload for erc-complete and
+	erc-track-modified-channels-mode -- the autoload cookie should do
+	that instead.
+	(erc-input-message): Doc string, removed binding for erc-complete.
+	(erc-mode-map): Removed binding for erc-complete.
+
+2002-10-03  Mario Lang  <mlang@delysid.org>
+
+	* erc-notify.el 1.4:
+	New functions erc-notify-JOIN and erc-notify-QUIT to catch some common cases (warning, untested)
+
+2002-10-01  Alex Schroeder  <alex@gnu.org>
+
+	* erc-stamp.el 1.6 (erc-timestamp-mode): New function.  Removed call
+	to erc-stamp-initialize at the end.
+
+2002-09-25  Brian P Templeton  <bpt@tunes.org>
+
+	* erc.el 1.299:
+	Added customizable `erc-process-coding-system' variable.
+
+2002-09-22  Brian P Templeton  <bpt@tunes.org>
+
+	* erc-fill.el 1.13:
+	`erc-fill-variable' now does the right thing when `erc-hide-timestamps' is non-nil
+
+2002-09-21  Mario Lang  <mlang@delysid.org>
+
+	* erc-fill.el 1.12:
+	patch from Peter Solodov <peter@alcor.concordia.ca>  (note, its slightly broken still
+
+2002-09-05  Mario Lang  <mlang@delysid.org>
+
+	* erc-pcomplete.el 1.2: Added LEAVE as alias for PART
+
+2002-09-04  Mario Lang  <mlang@delysid.org>
+
+	* erc-pcomplete.el 1.1:
+	By sachac (good work!) keep up doing such things
+
+2002-08-31  Mario Lang  <mlang@delysid.org>
+
+	* erc.el 1.298:
+	A fix for Bug#133267: now you can put (erc-save-buffer-in-logs) on erc-insert-post-hook to save *every* incoming message.
+
+2002-08-30  Brian P Templeton  <bpt@tunes.org>
+
+	* erc.el 1.297:
+	Changed default value of erc-common-server-suffixes because of the OPN
+	name change
+
+2002-08-28  Mario Lang  <mlang@delysid.org>
+
+	* erc-stamp.el 1.5: Try to reactivate isearch in xemacs
+
+	* erc-stamp.el 1.4:
+	fixes issues related to comparative emacsology and a silly bug
+
+2002-08-27  Mario Lang  <mlang@delysid.org>
+
+	* erc.el 1.296:
+	New hook erc-send-completed-hook (for robot stuff), changed alexanders email address to reflect reality, little fix to erc-auto-query to get a bit of a speedup
+
+2002-08-22  Mario Lang  <mlang@delysid.org>
+
+	* erc-button.el 1.23:
+	Fixed case-fold-search (thanks sachac), now lambda works in erc-button-alist, added wardwiki+google+symvar+rfc+itime regexps from the wiki
+
+2002-08-19  Mario Lang  <mlang@delysid.org>
+
+	* erc-button.el 1.22:
+	erc-nick-popup-alist: New variable to make erc-nick-popup configurable
+
+2002-08-16  Alex Schroeder  <alex@gnu.org>
+
+	* erc-button.el 1.21 (erc-recompute-nick-regexp): Fixed regexp.
+
+	* erc-button.el 1.20 (erc-button-buttonize-nicks): Changed custom type
+	to integer.
+	(erc-button-add-buttons): Moved button removal code to new
+	function.
+	(erc-button-remove-old-buttons): New function.
+	(erc-button-add-button): Removed use of overlays and used
+	erc-button-add-face instead.
+	(erc-button-add-face): New function to merge faces as text
+	properties.  This should be much faster when lots of buttons
+	appear.
+	(erc-button-list): New helper function.
+
+	* erc.el 1.295 (erc-display-message): Fixed argument list.
+	(erc-display-prompt): Reduced calls to length, use start-open
+	property for XEmacs to prevent a little box of erc-prompt-face at
+	the end of messages other people send.
+	(erc-refresh-channel-members): Fix XEmacs calls to split-string,
+	which may return an empty string at the end of the list.  This
+	would cause hangups in erc-button in re-search-forward loops.
+	(erc-get-channel-mode-from-keypress): Replaced control codes with
+	octal escape sequences.
+
+2002-08-14  Mario Lang  <mlang@delysid.org>
+
+	* erc-button.el 1.19:
+	Try to be compatible to XEmacs regexp-opt. (Im going to quit this job if I find more of those damn differencies
+
+	* debian/README.Debian 1.3, debian/scripts/install 1.9:
+	* Added info to README.Debian
+	* Finished debian/scripts/install
+
+2002-08-13  Mario Lang  <mlang@delysid.org>
+
+	* debian/scripts/install 1.8: First attempt to fix it
+
+	* debian/README.Debian 1.2, debian/changelog 1.17, debian/scripts/install 1.7:
+	changelog: Changed maintainer and added new entry
+	README.Debian: Re-explained the byte-compile issue
+	scripts/install: Exclude erc-bbdb|chess|ibuffer|speedbar from
+	byte-compiling
+
+	* erc-track.el 1.17: Added C-c C-SPC in addition to C-c C-@
+
+	* erc-notify.el 1.3: Little docstring change
+
+2002-08-09  Mario Lang  <mlang@delysid.org>
+
+	* erc-stamp.el 1.3:
+	Change one use of set-text-properties to add-text-properties (tnx Lathi)
+
+2002-08-02  Mario Lang  <mlang@delysid.org>
+
+	* erc-stamp.el 1.2: added erc-timestamp-only-if-changed-flag
+
+2002-07-22  Mario Lang  <mlang@delysid.org>
+
+	* erc.el 1.294:
+	Removed timestamp related code and moved into erc-stampe.l
+
+	* erc-stamp.el 1.1:
+	Timestamping code moved out of erc.el. Additional, now we can timestamp either on the left or on the right side
+
+2002-07-16  Mario Lang  <mlang@delysid.org>
+
+	* erc.el 1.293:
+	* Make ctcp ping return its message in the active buffer, instead of the server buffer
+	* Corrected minimal typo in catalog
+	* Added var and variable as alias for /set
+
+2002-07-08  Mario Lang  <mlang@delysid.org>
+
+	* erc-track.el 1.16:
+	* New function erc-track-switch-buffer (by resolve)
+	  Bound to C-c C-SPC, enjoy!
+
+2002-07-08  Gergely Nagy  <algernon@debian.org>
+
+	* debian/changelog 1.16: New snapshot deb
+
+	* debian/scripts/install 1.6: Rewrote in make.
+	Does not byte-compile erc-speak.el at all, and excludes erc-track.el too, if
+	ran for xemacs.
+
+	* debian/control 1.4: Added dependency on make
+
+	* debian/copyright 1.2: Updated copyright info
+
+	* debian/rules 1.10: Use $(wildcard *.el) instead of a hardcoded list
+
+2002-07-03  Diane Murray  <disumu@x3y2z1.net>
+
+	* erc.el 1.292:
+	erc-iswitchb now works correctly if erc-modified-channels-alist is non-nil
+
+2002-07-01  Diane Murray  <disumu@x3y2z1.net>
+
+	* erc-menu.el 1.8:
+	* changed how we check if we should activate "Track hidden channels" and
+	  whether it should be selected - fixes a bug Xemacs where whole menu bar
+	  does not work if menu is loaded
+
+	* erc-menu.el 1.7:
+	* added "Disconnect from server", only selectable if erc-connected is non-nil
+
+	* topic is allowed to be set by normal users if channel mode is not +t
+
+	* add " ..." after description if arguments needed after selecting menu item
+
+	* only allow selecting of menu points needing a channel if current buffer is
+	  a channel buffer - done by testing if channel-members is non-nil
+
+	* put erc-match functions in new group "Pals, fools and other keywords"
+
+	* erc.el 1.291:
+	* moved definition of erc-show-my-nick to GUI variables section
+
+	* erc-connected variable now defined with defvar
+	  now set in channel and query buffers, was only in server buffer before
+	  upon disconnect, set erc-connected to nil in all the server's buffers
+
+	* added erc-cmd-GQUIT and its alias erc-cmd-GQ - quit all servers at once
+
+	* added interactive function erc-quit-server, bound to C-c C-q
+
+	* added erc-server-WALLOPS
+
+	* added WALLOPS to english catalog, fixed s461 (was showing message twice)
+
+	* typo fixes, spacing change
+
+2002-06-29  Mario Lang  <mlang@delysid.org>
+
+	* erc.el 1.290: Use pp-to-string in /set (without args)
+
+	* erc-netsplit.el 1.5:
+	Make /set anonymous-lign set erc-anonymous-login, also report
+	which var was set to which val.
+
+2002-06-28  Diane Murray  <disumu@x3y2z1.net>
+
+	* erc-menu.el 1.6: added "Customize ERC"
+
+2002-06-25  Mario Lang  <mlang@delysid.org>
+
+	* erc.el 1.289: New variable: erc-use-info-buffers, defaults to nil.
+	  This prevents info-buffers from being created/updated.
+	  Set to t if you use :INFO buffers.
+	  (by rw)
+	Delete (erc-display-prompt) from reconnect to avoid clutter
+
+2002-06-23  Diane Murray  <disumu@x3y2z1.net>
+
+	* erc.el 1.288:
+	erc-get-channel-mode-from-keypress is now bound to C-c C-m
+	erc-insert-mode-command is taken care of by this function as well
+
+2002-06-21  Mario Lang  <mlang@delysid.org>
+
+	* erc-track.el 1.15:
+	Fixed bug where buffer-names suddenly had text-properties.
+
+2002-06-19  Diane Murray  <disumu@x3y2z1.net>
+
+	* Makefile 1.5: changed erc-auto.el to $(SPECIAL) in make fullclean
+
+	* Makefile 1.4: remove erc-auto.el on make fullclean
+
+2002-06-18  Diane Murray  <disumu@x3y2z1.net>
+
+	* erc-match.el 1.10: fixed spelling error
+
+	* erc-track.el 1.14, erc-match.el 1.9: * erc-match.el:
+	  highlight current nickname in its own face (deactivated by default):
+	  - added erc-current-nick-highlight-type, erc-current-nick-face,
+	    erc-current-nick-p
+
+	* erc-track.el:
+	  added support for erc-current-nick-face
+
+2002-06-17  Diane Murray  <disumu@x3y2z1.net>
+
+	* erc.el 1.287: * added beginning suport for 005 numerics:
+	  - added buffer local variable erc-server-parameters
+	  - added erc-server-005, which sets erc-server-parameters if the server has
+	    used this code to show its parameters
+
+2002-06-16  Diane Murray  <disumu@x3y2z1.net>
+
+	* erc.el 1.286:
+	* bugfix: when pasting lines with blank lines in between, remove the blank lines
+	  but send the rest
+
+	* since we know the command, use it when checking what's in erc-hide-list
+	  added check to erc-server-KICK
+
+	* added some blank lines for better readability
+
+2002-06-16  Alex Schroeder  <alex@gnu.org>
+
+	* erc-nickserv.el 1.5 (erc-nickserv-alist): Fixed typo.
+
+2002-06-15  Alex Schroeder  <alex@gnu.org>
+
+	* erc-nickserv.el 1.4 (erc-networks): Added doc string.
+	(erc-nickserv-alist): Added doc string.
+
+2002-06-14  Diane Murray  <disumu@x3y2z1.net>
+
+	* erc-ring.el 1.4:
+	fixed bug so that the prompt and command always get put at the end of the buffer
+
+2002-06-10  Mario Lang  <mlang@delysid.org>
+
+	* erc-nickserv.el 1.3: Added iip support.
+	Added :type for erc-nickserv-passwords custom.
+	Fixed hook usage.
+
+2002-06-07  Diane Murray  <disumu@x3y2z1.net>
+
+	* erc-nickserv.el 1.2: * added GalaxyNet
+
+	* erc-nickserv-alist:
+	  - sorting networks alphabetically
+	  - added two more pieces of information in erc-nickserv-alist:
+	    word to use for identification and whether to use the nickname
+
+	* erc-current-network:
+	  - made regex case insensitive, downcase server to match
+	  - uses the new information
+	  - now uses new variable erc-networks instead of doing checking manually
+
+	* added variable erc-networks
+
+	* fixed some indentation, documentation
+
+2002-06-07  Mario Lang  <mlang@delysid.org>
+
+	* erc.el 1.285: Fix for kill-buffer hook stuff
+
+2002-06-06  Mario Lang  <mlang@delysid.org>
+
+	* erc.el 1.284: Added /squery command
+
+2002-06-06  Diane Murray  <disumu@x3y2z1.net>
+
+	* erc-menu.el 1.5: * made group Channel modes
+	  - moved change mode and invite only mode to here
+	  - added secret, moderated, no external send, topic lock, limit, key
+
+	* check that user is in a channel buffer and user is a channel operator
+	  for all op-related actions
+
+	* "Identify to nickserv" needs erc-nickserv-identify defined
+
+	* added "Show ERC version"
+
+	* erc.el 1.283:
+	* added erc-set-channel-limit, erc-set-channel-key, erc-toggle-channel-mode
+
+	* added erc-get-channel-mode-from-keypress, which is binded to C-c m
+	  sends the next character which is typed to one of the 3 new functions
+	  - did not remove erc-invite-only-mode and it's key binding in case
+	    people are used to it, although it probably should be removed...
+
+	* in erc-server-MODE:
+	  added check if tgt equal to user's nick
+	  removed erc-display-line, only using the erc-display-message
+
+	* added s461 to english catalog
+
+	* fixed bug where Xemacs would not quit if erc-quit-reason was
+	  set to erc-quit-reason-various and assoc-default was not defined
+
+2002-06-04  Andreas Fuchs  <asf@void.at>
+
+	* erc-ezbounce.el 1.1, erc-match.el 1.8:
+	* erc-ezbounce.el: Added. Provides support for ezbouncer; automatic login,
+	                   session management implemented. I've contacted the author
+			   about stuff in EZBounce's logging.
+	* erc-match.el: Fixed a stupid mistake where
+	                "*** Your new nick is <foo>" would trigger an error.
+
+2002-06-04  Diane Murray  <disumu@x3y2z1.net>
+
+	* erc-nickserv.el 1.1, erc.el 1.282: * added erc-nickserv.el
+	* moved nickserv identification variables and functions to the new file
+	  (require 'erc-nickserv) is now necessary for this to work
+
+	* erc.el 1.281:
+	* results of /COUNTRY now formatted as notice; errors are ignored, 
+	  fixing
+	  bug which made prompt disappear
+
+	* added undefined-ctcp error message to english catalog
+
+	* changed some (when (not erc-disable-ctcp-replies) to use unless instead
+	  and some if's without else statments to use when or use
+
+	* CTCP replies now use erc-display-message, formatted as notices
+
+	* added following to english catalog:
+	  - undefined-ctcp
+	  - CTCP-CLIENTINFO, CTCP-ECHO, CTCP-FINGER, CTCP-PAGE, CTCP-PING,
+	    CTCP-SOUND, CTCP-TIME, CTCP-UNKNOWN, CTCP-VERSION
+	  - s303, s305, s306, s353
+
+	* split erc-server-305-or-306 into erc-server-305 and erc-server-306
+
+	* KICK already had buffer set, using it
+
+	* erc.el 1.280:
+	* erc-format-timestamp now only called from erc-display-message and
+	  erc-send-current-line
+
+	* all instances of erc-display-line with erc-highlight-error
+	  changed to use erc-display-message
+
+	* added following error messages to english catalog:
+	  bad-ping-response, bad-syntax, cannot-find-file, cannot-read-file,
+	  ctcp-request, flood-ctcp-off, flood-strict-mode, no-default-channel,
+	  no-target, variable-not-bound
+
+	* added following server related messages to english catalog:
+	  s324, s329, s331, s332, s333, s341, s406, KICK, KICK-you, KICK-by-you, MODE-nick
+
+	* ignoring server codes 315, 369
+
+	* added erc-server-341, erc-server-406
+
+	* channel topic and mode notices displayed in respective channel buffers if they
+	  exist
+
+	* erc-server-KICK: display the message before removing this channel so that we
+	  can track the kick
+
+	* send parsed to erc-ctcp-query-ACTION-hook so that actions can be checked
+	  by erc-match
+
+	* fixed bug where nil was shown if no reason was given by users on /PART
+
+2002-06-03  Diane Murray  <disumu@x3y2z1.net>
+
+	* erc-match.el 1.7:
+	* fixed bug where erc-log-matches produced an error when the value of
+	  (erc-default-target) was not a channel
+	* use erc-format-timestamp, if it's non-nil, for %t in erc-log-match-format
+
+2002-06-01  Diane Murray  <disumu@x3y2z1.net>
+
+	* erc-button.el 1.18:
+	* made action case insensitive in erc-nick-popup and added a more descriptive
+	  error message
+
+2002-05-30  Brian P Templeton  <bpt@tunes.org>
+
+	* erc.el 1.279:
+	Removed multiple calls of `erc-prompt' in `erc-display-prompt'
+
+2002-05-29  Mario Lang  <mlang@delysid.org>
+
+	* erc.el 1.278:
+	First step timestampkiller cleanup. I'm tired, do the rest tomorrow.
+
+	* erc.el 1.277:
+	New functionality: Catch channel/server buffer kills through kill-buffer-hook.
+	Currently, it only does a PART if you kill a channel buffer.
+
+2002-05-28  Mario Lang  <mlang@delysid.org>
+
+	* erc.el 1.276:
+	defvar'ed some buffer-local variables to make elint at least a bit more happy.
+	  Moved comments into docstrings.
+	Changed some instances of member to memq.
+
+	* erc-track.el 1.13, erc.el 1.275:
+	erc.el: (erc-message-type-member): New function, used to test
+	for message type. Require erc-parsed text-property.
+	erc-track.el: erc-track-exclude-types: New variable. Defaults to ("JOIN" "PART") right now for testing, it should eventually set to nil soon again.
+	(erc-track-modified-channels): Use above fun and var to optionally exclude certain message types from channel tracking.
+
+2002-05-28  Diane Murray  <disumu@x3y2z1.net>
+
+	* CREDITS 1.5: added myself, vain as it sounds ;)
+
+2002-05-25  Mario Lang  <mlang@delysid.org>
+
+	* erc.el 1.274: * Some small docstring fixes
+	* (erc-display-line): Now takes also a process object in the buffer argument.
+	  Used for easy sending to the server buffer.
+	* Several places: Just pass proc, not (process-buffer proc)
+
+2002-05-24  Mario Lang  <mlang@delysid.org>
+
+	* erc.el 1.273: Mostly docstring fixes/additions
+
+	* erc-netsplit.el 1.4: Doc fixes, and a new netjoin-done message.
+
+	* erc-fill.el 1.11: Doc fixes, erc-fill custom group, autoloads.
+
+	* erc-netsplit.el 1.3: Fix to erc-netsplit-timer.
+
+	* erc-netsplit.el 1.2: Fixed a silly typo
+
+	* erc-maint.el 1.1: is this really necessary?
+
+	* erc.el 1.272: Added new variable erc-hide-list.
+	It affects erc globally right now, and is used to hide certain IRC type messages like JOIN and PART.
+
+	* Makefile 1.3: Doh, I should really test this before checkin :)
+
+	* Makefile 1.2: Silly cut&paste bug fixed
+
+	* erc-list.el 1.6: Added autoload cookie
+
+	* erc-match.el 1.6: Added missing require erc.
+
+	* erc-notify.el 1.2: Autoload cookies and a -initialize function.
+
+	* erc-chess.el 1.18: Added autoload cookies
+
+	* Makefile 1.1: Finally, we have a Makefile.
+	Primarily used for autoload definition generation right now.
+
+	* erc-auto.in 1.1: First version.
+
+	* erc-track.el 1.12: Added autoload cookie
+
+	* erc-netsplit.el 1.1:
+	New module, used to autodetect and hide netsplits.
+	(Untested, no netsplit happened yet :) )
+
+	* erc-nets.el 1.3: Added some old code I once worked on.
+	Added autoload cookie
+
+2002-05-24  Diane Murray  <disumu@x3y2z1.net>
+
+	* erc-fill.el 1.10:
+	removed reference in documentation to old variable, changed it to the new one
+
+	* erc.el 1.271:
+	* added new function erc-connection-established which is called after receiving
+	  end of MOTD (does nothing if it's been called before)
+
+	* added new hook erc-after-connect which is called from
+	  erc-connection-established with the arguments server (the announced server)
+	  and nick - which other arguments should be sent??
+
+	* added buffer variable erc-connected which is set to t the first time
+	  erc-connection-established is called, set to nil again if we've been
+	  disconnected
+
+	* set initial user mode
+	  - added custom variable erc-user-mode which can be a string or a function
+	    which returns a string
+	  - new function erc-set-initial-user-mode gets called from
+	    erc-connection-established
+
+2002-05-22  Diane Murray  <disumu@x3y2z1.net>
+
+	* erc.el 1.270: fixed bug where prompt was missing after reconnect
+
+2002-05-21  Diane Murray  <disumu@x3y2z1.net>
+
+	* erc.el 1.269:
+	in erc-nickserv-identify: if network is unknown, just use "Nickserv"
+
+	* erc.el 1.268: * fixed some typos
+
+	* timestamping
+	  - ctcp request messages and replies now have timestamp
+	  - timestamps in front of error messages now in timestamp face
+	  - added timestamp to more error messages
+
+	* ctcp reply messages, server ping message updated
+
+	* added variable erc-verbose-server-ping - check this instead of erc-paranoid
+
+	* added whowas on no such nick:
+	  - added variable erc-whowas-on-nosuchnick
+	  - in erc-server-401 do WHOWAS if erc-whowas-on-nosuchnick is non-nil
+
+	* erc.el 1.267: forgot documentaion for erc-nickserv-alist
+
+	* erc.el 1.266: NickServ identification changed and enhanced:
+	- erc-nickserv-identify-autodetect now called from erc-server-NOTICE-hook
+	- now possible to identify automatically without prompt:
+	  - added custom variables erc-prompt-for-nickserv-password and
+	    erc-nickserv-passwords
+	- added erc-nickserv-alist containing the different networks' nickserv details
+	- added function erc-current-network to determine the network symbol
+	- fixed bug where identification on dalnet didn't work, because they now
+	  require NickServ@services.dal.net
+	  now sends to all NickServ with nick@server where possible
+
+2002-05-17  Diane Murray  <disumu@x3y2z1.net>
+
+	* erc-fill.el 1.9:
+	* filling with erc-fill-variable now works with custom defined fill width:
+	  - changed erc-fill-column from defvar to defcustom
+	  - in erc-fill-variable: set fill-column to value of erc-fill-column
+
+	* erc.el 1.265: erc.el:
+	* fixed bug where topic wasn't being set when chanel name was provided
+
+	erc-fill.el:
+	* filling with erc-fill-variable now works with custom defined fill width:
+	  - changed erc-fill-column from defvar to defcustom
+	  - in erc-fill-variable: set fill-column to value of erc-fill-column
+
+2002-05-16  John Wiegley  <johnw@gnu.org>
+
+	* erc.el 1.264: whitespace fix
+
+2002-05-15  Diane Murray  <disumu@x3y2z1.net>
+
+	* erc.el 1.263:
+	* added explanation of empty string working in erc-quit-reason-various-alist
+	* removed the text property from erc-send-message, it caused problems
+	  with /SV (as noticed by gbvb on IRC) and is obviously not needed
+	* when receiving a ctcp query, convert type to uppercase to allow for
+	  "/ctcp nick time" and not just "/ctcp nick TIME"
+	* timestamp in front of server notices now shown in the timestamp face
+
+2002-05-13  Diane Murray  <disumu@x3y2z1.net>
+
+	* erc.el 1.262:
+	- in erc-format-privmessage: `erc-format-timestamp' added to message after
+	  message's text properties are applied so that it doesn't lose its face
+
+	- /quit without reason now works when `erc-quit-reason' is set to
+	  `erc-quit-reason-various' and the empty string "" is defined in
+	  `erc-quit-reason-various-alist'
+
+2002-05-13  Andreas Fuchs  <asf@void.at>
+
+	* erc-bbdb.el 1.16:
+	* Applied Drewies patch to pop-up on nick changes when -popup-type is 'visible
+
+2002-05-12  Andreas Fuchs  <asf@void.at>
+
+	* erc-bbdb.el 1.15, erc.el 1.261:
+	* erc-bbdb.el: pop up the buffer on /whois when erc-bbdb-popup-type is 'visible
+	* erc.el: fix for empty quit reason problem by drewie.
+
+2002-05-12  Mario Lang  <mlang@delysid.org>
+
+	* erc.el 1.260: disumu nick patch
+	- added erc-show-my-nick (default t)
+	  if t, show nickname like <nickname>
+	  if nil, only show a > character before the message
+	- added faces erc-nick-default-face and erc-nick-msg-face
+	  - nicknames (channel, msgs, notices) are now in bold face by default
+	  - the msg face matches the erc-direct-msg-face color
+
+2002-05-10  Alex Schroeder  <alex@gnu.org>
+
+	* erc.el 1.259 (erc-send-pre-hook): Doc change.
+
+	* CREDITS 1.4: Alexander L. Belikoff is confirmed original author.
+
+2002-05-10  Mario Lang  <mlang@delysid.org>
+
+	* erc.el 1.258:
+	timestamp fix by disumutimestamp fix by disumutimestamp fix by disumutimestamp fix by disumutimestamp fix by disumutimestamp fix by disumutimestamp fix by disumutimestamp fix by disumu
+
+2002-05-09  Mario Lang  <mlang@delysid.org>
+
+	* erc.el 1.257: *** empty log message ***
+
+2002-05-06  Mario Lang  <mlang@delysid.org>
+
+	* erc.el 1.256:
+	New var: erc-echo-notices-in-minibuffer-flag. defaults to t.
+
+2002-05-04  John Wiegley  <johnw@gnu.org>
+
+	* TODO 1.3: *** empty log message ***
+
+2002-05-03  Alex Schroeder  <alex@gnu.org>
+
+	* erc.el 1.255: Copyright notice, version string updates.
+
+2002-05-02  Alex Schroeder  <alex@gnu.org>
+
+	* erc.el 1.254: Comment: dme is David Edmondson
+
+2002-05-01  Alex Schroeder  <alex@gnu.org>
+
+	* erc.el 1.253 (erc-warn-about-blank-lines): New option.
+	(erc-send-current-line): Use it.
+	(erc-quit-reason-various-alist): New option.
+	(erc-quit-reason): New option.
+	(erc-quit-reason-normal): New function.
+	(erc-quit-reason-zippy): New function.
+	(erc-quit-reason-various): New function.
+	(erc-cmd-QUIT): Use them.
+
+2002-04-30  Alex Schroeder  <alex@gnu.org>
+
+	* erc.el 1.252: Version 2.92
+
+	* erc.el 1.251 (erc-send-modify-hook): Default value is nil.
+
+2002-04-27  John Wiegley  <johnw@gnu.org>
+
+	* erc.el 1.250:
+	Don't redisplay the prompt if the ERC buffer is no longer alive.
+
+2002-04-26  John Wiegley  <johnw@gnu.org>
+
+	* erc.el 1.249:
+	Don't call `set-buffer' on old-buf unless the buffer is valid.  It's
+	often not when separate frames are being used.
+
+2002-04-23  Mario Lang  <mlang@delysid.org>
+
+	* erc-button.el 1.17: fixed up erc-nick-regexp
+
+2002-04-22  Brian P Templeton  <bpt@tunes.org>
+
+	* erc.el 1.248:
+	`erc-prompt' may now be a function that returns a string (which is
+	used as the prompt). I don't use Customize but I think customization
+	of it may be broken if it's not a string.
+
+	There is a new `erc-prompt' function that returns the prompt as a
+	string (e.g., returning either the result of `(funcall erc-prompt)' or
+	`erc-prompt').
+
+	This allows for dynamic prompts, such as a LispWorks-like prompt, or
+	one containing simply the current channel name. It was requested by
+	Mojo Nichols (nick michols) in #emacs today, 21-Apr-2002; cf. the
+	#emacs logs at <URL:http://www.tunes.org/~nef/logs/emacs/02.04.21.
+
+2002-04-17  Mario Lang  <mlang@delysid.org>
+
+	* erc.el 1.247:
+	fix erc-send-current-line to work on empty lines again (without sending the prompt)
+	Fix C-c C-t to not include the nick/time info
+	(both from antifuchs)
+
+	* erc-complete.el 1.9: Fix for xemacs elt behaviour
+
+2002-04-17  John Wiegley  <johnw@gnu.org>
+
+	* erc-chess.el 1.17:
+	Added a missing arg in a call to erc-chess-handler.
+
+2002-04-15  John Wiegley  <johnw@gnu.org>
+
+	* erc-chess.el 1.16: *** empty log message ***
+
+2002-04-14  John Wiegley  <johnw@gnu.org>
+
+	* erc-chess.el 1.15: *** empty log message ***
+
+2002-04-12  John Wiegley  <johnw@gnu.org>
+
+	* erc-chess.el 1.14: *** empty log message ***
+
+	* erc-chess.el 1.12: bug fixes
+
+	* erc-chess.el 1.11: *** empty log message ***
+
+2002-04-12  Mario Lang  <mlang@delysid.org>
+
+	* erc-chess.el 1.6: change order.
+
+	* erc-chess.el 1.5: more fixing.
+
+	Now, the 'match question works. It sends an accept back.
+	But display popup doesnt work..
+
+	* erc-chess.el 1.4: fixup (still far from working)
+
+2002-04-11  Mario Lang  <mlang@delysid.org>
+
+	* erc.el 1.246:
+	* Added :options entry for erc-mode-hook (erc-add-scroll-to-bottom)
+
+2002-04-11  John Wiegley  <johnw@gnu.org>
+
+	* erc.el 1.245: remove trailing \n from any sent text
+
+	* servers.pl 1.2, erc-bbdb.el 1.14, erc-button.el 1.16, erc-chess.el 1.3, 
+	  erc-complete.el 1.8, erc-fill.el 1.8, erc-ibuffer.el 1.14, erc-list.el 1.5, 
+	  erc-match.el 1.5, erc-menu.el 1.4, erc-nets.el 1.2, erc-replace.el 1.3, 
+	  erc-speak.el 1.22, erc-speedbar.el 1.8, erc-track.el 1.11, erc.el 1.244:
+	clean whitespace
+
+	* erc.el 1.243: Replaced erc-scroll-to-bottom.
+
+2002-04-11  Mario Lang  <mlang@delysid.org>
+
+	* erc-track.el 1.10:
+	try to fix behaviour when used with different frames.
+
+2002-04-09  Mario Lang  <mlang@delysid.org>
+
+	* erc-chess.el 1.2:
+	fixup release, far from ready for real usage, but it appears to work.
+
+	* erc.el 1.242:
+	speed improvments based on elp-instrument-package RET erc- RET results
+
+	* erc-chess.el 1.1: initial version.
+	please test it
+	Get chess.el from johnw's cvs:
+	cvs -d:pserver:anonymous@alice.dynodns.net:/usr/local/cvsroot login
+	cvs -d:pserver:anonymous@alice.dynodns.net:/usr/local/cvsroot co chess
+
+	(as usual, blank password)
+
+	Add the resulting dir to your load-path and reqire erc-chess.
+
+	Usage: Just do /chess nickname
+	The remote end much use erc, as no other irc client I know of supports this ...
+
+	See erc-chess-default-display and maybe set it to chess-images or chess-ics1 if you prefer those over chess-plain.
+	Also, see erc-chess-user-full-name to set the name you use in chess games.
+
+2002-04-04  Mario Lang  <mlang@delysid.org>
+
+	* erc.el 1.241: New hackery latenightwise
+
+	* erc.el 1.240: upupadowndowncase
+
+2002-04-04  Gergely Nagy  <algernon@debian.org>
+
+	* debian/changelog 1.15: Updated for the new snapshot
+
+	* debian/rules 1.9: Install README.Debian into the package
+
+	* debian/README.Debian 1.1: Initial check-in
+
+2002-04-04  Mario Lang  <mlang@delysid.org>
+
+	* erc.el 1.239:
+	Fixed that /me in query buffers ended up in server buffer
+
+	* erc.el 1.238: * Implemented joining +k channels
+
+2002-03-14  Mario Lang  <mlang@delysid.org>
+
+	* erc.el 1.237: New utility function: erc-channel-list
+	minor fix to erc-get-buffer. hopefully that helps shapr
+
+2002-03-12  Mario Lang  <mlang@delysid.org>
+
+	* erc.el 1.236:
+	New /command: /QUOTE for sending directly to the IRC server
+	Removed erc-fill from erc-insert-modify-hook. To activate filling, simply customize that var.
+
+2002-03-09  Brian P Templeton  <bpt@tunes.org>
+
+	* CREDITS 1.3: *** empty log message ***
+
+2002-03-09  Mario Lang  <mlang@delysid.org>
+
+	* erc-complete.el 1.7:
+	New variable: erc-nick-completion-ignore-case. Defaults to t.
+
+	* erc-track.el 1.9:
+	* erc-track-shorten-name-function can now be set to nil to avoid treating of channel names at all.
+
+2002-03-06  Gergely Nagy  <algernon@debian.org>
+
+	* debian/changelog 1.14, debian/rules 1.8: update to new snapshot
+
+2002-03-06  Mario Lang  <mlang@delysid.org>
+
+	* erc.el 1.235:
+	Fixed nasty bug which prevented channel limit from correctly display/handling
+
+	* erc-track.el 1.8: Made shortening code highly customizable.
+	Now, there is the variable erc-track-shorten-function which holds
+	a function which gets called with one argument, CHANNEL-NAMES, which is a list
+	of strings of the channel names.
+	It needs to return a list of strings of the same length with the modified values...
+
+	* erc-track.el 1.7:
+	Added erc-track-shorten-aggressively, default to nil
+	if it is set to t, erc will shorten a bit more.
+	if nil, erc will shorten the name only if it would get shorter than just
+	one char...
+
+	* erc-speak.el 1.21: added iirc to the abbreviation expansion list.
+
+	* erc-track.el 1.6:
+	Added customization variable: erc-track-use-faces. defaults to t.
+
+	* erc-track.el 1.5: *** empty log message ***
+
+	* erc-track.el 1.4:
+	experimental: Added face support to mode-line channel activity tracker.
+	Currently we use the faces used for indicating in the buffer (erc-pal-face for channels with pal acitivity...)
+
+2002-03-05  Mario Lang  <mlang@delysid.org>
+
+	* erc-complete.el 1.6: * added docfixes (thanks ore)
+
+	* erc-track.el 1.3: Fixed channel-name reduction.
+	thanks again alex.
+	Renamed the vars to erc-track-opt-start and erc-track-opt-cutoff.
+
+	* erc.el 1.234: fixed another silly error
+
+	* erc-track.el 1.2: Implemented channel name shortening.
+	Vars erc-track-cutoff says: all channel names longer than this will be shortened.
+	Var erc-track-minimum-channel-length says: dont make names shorten than this.
+	(Thanks go out to kensanata for the nice unique-substrings utility function).
+
+	* erc.el 1.233: silly typo corrected
+
+	* erc.el 1.232:	* erc.el 1.232: * New varialbe: erc-common-server-name-suffixes
+	  This alist can be used to change the server names displayed in mode-line
+	  to a shorter version..
+	* New function: erc-shorten-server-name (uses var above)
+	* Changed erc-prepare-mode-line to use erc-shorten-server-name.
+
+2002-02-25  Mario Lang  <mlang@delysid.org>
+
+	* erc.el 1.231:
+	CTCP handling rewritten. Seems to work. please test and report probs.
+
+2002-02-24  Mario Lang  <mlang@delysid.org>
+
+	* erc.el 1.230:
+	Fixed emacs20 backward compatibility (new defun/alias: erc-propertize)
+
+2002-02-22  Mario Lang  <mlang@delysid.org>
+
+	* erc-button.el 1.15: *** empty log message ***
+
+2002-02-21  Mario Lang  <mlang@delysid.org>
+
+	* erc-button.el 1.14, erc.el 1.229:
+	minor fixup related to read-only prompts and command renaming.
+
+2002-02-21  Andreas Fuchs  <asf@void.at>
+
+	* erc.el 1.228: * modify `erc-remove-text-properties-region' to work.
+	  Could even be a little faster now. (-:
+
+2002-02-21  Mario Lang  <mlang@delysid.org>
+
+	* erc-ring.el 1.3:
+	fixed erc-replace-command to behave right when text is read-only.
+	Also, use erc-insert-marker and (point-max) now.
+
+	* erc.el 1.227: * Made erc-prompt read-only
+	* new function: erc-make-read-only. Can be used on erc-insert-post-hook and erc-send-post-hook to ensure read-only buffer text too
+
+2002-02-19  Mario Lang  <mlang@delysid.org>
+
+	* erc-list.el 1.4: added comment to docstring
+
+	* erc-speak.el 1.20: minor updates, use erc-nick-regexp now
+
+	* erc.el 1.226:
+	ensure that erc-timer-hook is called inside the server-buffer.
+
+2002-02-19  Andreas Fuchs  <asf@void.at>
+
+	* erc-match.el 1.4:
+	* Probably fixed the "number-char-or-marker-p: nil" bug.
+
+2002-02-19  Mario Lang  <mlang@delysid.org>
+
+	* erc-notify.el 1.1: Initial release.
+
+	* erc.el 1.225: added #303 handling
+	moved timer and added an arg (erc-current-time)
+
+	* erc-list.el 1.3, erc.el 1.224:
+	slightly changed the erc-once-with-server-event macro
+
+	* erc-button.el 1.13: erc-button-alist: doc fix and custom type fix
+
+2002-02-18  Mario Lang  <mlang@delysid.org>
+
+	* erc-list.el 1.2, erc.el 1.223: new macro: erc-once-with-server-event
+	erc-list.el: use it
+
+	* erc-match.el 1.3:
+	Minor fix related to hook call method change (-until-seccess now)
+
+	* erc.el 1.222: fixed ctcp behaviour abit (with auto-query on)
+
+	* erc-list.el 1.1: ChanList mode.
+	Load it, and type M-x erc-chanlist RET
+	Demonstrates how the new hook system can be nicely used.
+
+	* erc.el 1.221:
+	new hook: erc-default-server-hook. This one gets called if we dont have anything defined for a certain IRC server message.
+	New function: erc-default-server-handler. (used by above hook).
+	New function: erc-debug-missing-hooks: Used by above hook to save a list of unimplemented server messages.
+	New function: erc-server-buffer, erc-server-buffer-p.
+	Various places: use it.
+	Minor fixup.
+
+	* erc-button.el 1.12: fix regexp to not buttonize ~user@host hostnames
+
+2002-02-17  Mario Lang  <mlang@delysid.org>
+
+	* erc-complete.el 1.5, erc.el 1.220: Eliminated erc-command-table
+	Upcased the command defuns (erc-cmd-join is now erc-cmd-JOIN)
+	Fixed erc-complete to not require erc-command-table.
+	Implemented erc-cmd-HELP
+	  (You have to try that, its tooo coool!)
+	  e.g. /help auto-q
+	fixed autoloads for erc-add-pal and so on to be interactive.
+
+2002-02-17  Andreas Fuchs  <asf@void.at>
+
+	* erc-match.el 1.2:
+	* Fix unfunctional code in `erc-get-parsed-vector-type'.
+
+	* erc-bbdb.el 1.13, erc-button.el 1.11, erc-match.el 1.1, erc.el 1.219:
+	* Be careful: MANY changes ahead. I won't go into too much details.
+
+	* erc.el, new file erc-match.el: split out all pattern-matching code.
+	* erc.el: removed all defcusts for erc-{...}-highlight-props. They are
+	  quite useless, anyway.
+	* moved erc-add-entry-to-list and -remove- over to erc-match. changed
+	  their arg list.
+	* erc.el: add autoloads for erc-{add,delete}-{keyword,pal,fool,dangerous-host}
+	* erc.el: erc-server-PRIVMSG-or-NOTICE:
+	  - remove all the highlighting crap
+	  - add a (when (eq s nil) ...) so that untreated CTCP messages don't
+	    get misdisplayed.
+	* erc.el: erc-mark-message: removed this function, it's useless
+	* erc.el: minor bugfixes.
+
+	* erc-match.el: first checkin. This file now contains all the pattern
+	  matching stuff. there is now another defcust group, erc-match,
+	  containing all match related stuff (erc-keywords, ...)
+	* erc-match.el: added functionality to log matching lines. Quite
+	  customizable, check out the docstring of defun erc-log-matches
+	* erc-match.el: added functionality to make foolish messages
+	  invisible/intangible. This could replace erc-ignore-list
+	  sometime. it's more powerful right now, anyway.
+	* erc-match.el erc-text-matched-hook: new hook. run when Text matches
+	  anything (pal, fool, etc.).
+
+	* erc-button.el: Make nick buttonization customizable.
+	* erc-button.el: Give nick buttonization a lower priority so that it
+	  does not break url buttons.
+
+	* erc-bbdb.el: Add \n to the separators by which we split nicknames.
+
+2002-02-17  Mario Lang  <mlang@delysid.org>
+
+	* TODO 1.2: Added item
+
+2002-02-17  Brian P Templeton  <bpt@tunes.org>
+
+	* CREDITS 1.2, erc.el 1.218: Added invisible timestamp support.
+
+2002-02-16  Gergely Nagy  <algernon@debian.org>
+
+	* debian/changelog 1.13, debian/rules 1.7, debian/scripts/install 1.5:
+	updated to new snapshot
+
+2002-02-16  Mario Lang  <mlang@delysid.org>
+
+	* erc.el 1.217:
+	Fixed channel limit format overflow in mode-line display.
+	(Having to use floats if integers are to large is quite strange, isn't it?)
+
+	* TODO 1.1: TODO list created.
+	Add comments and expand it.
+
+	* erc.el 1.216:
+	Fixed bug in query buffer handling (only happend in mixed-case situations)
+
+	* erc.el 1.215: shapr checkdoc patch #1
+	massive docfixes! yay, keep going!
+
+2002-02-15  Mario Lang  <mlang@delysid.org>
+
+	* erc.el 1.214: various other fixes
+	make s301 a catalog entry
+
+2002-02-15  Andreas Fuchs  <asf@void.at>
+
+	* erc.el 1.213: * erc-server-NICK and erc-server-INVITE: fixed to use
+	  `erc-display-message'. These I missed in the first checkin.  I
+	  didn't say it in the last log message, but please test these.
+
+	* erc-fill.el 1.7, erc.el 1.212:
+	* erc.el: updated many functions to use `erc-display-message'. Now, we
+	  should go for getting highlighting out of
+	  erc-server-PRIVMSG-or-NOTICE. The part I want to attack has been
+	  marked.
+	* erc-fill.el: updated static filling to leave the erc-parsed property alone.
+
+2002-02-15  Mario Lang  <mlang@delysid.org>
+
+	* erc.el 1.211:
+	first step, new function: erc-display-message
+
+	* erc.el 1.210: added numreply 379 and 405.
+
+	* erc.el 1.209: stupid typo fixed
+
+	* erc.el 1.208:
+	Finally renamed erc-frame-dedicated-p to erc-frame-dedicated-flag
+	Removed usage of erc-interpret-controls from info buffer drawing (major speedup)
+	Other speedups based on the results from elp.
+	ERC is now about 300%-500% faster in some situations with very full channels!!!!!
+
+2002-02-14  Andreas Fuchs  <asf@void.at>
+
+	* erc.el 1.207:
+	* erc-downcase now downcases {}|^ with []\~ -- 'stolen' from zenirc.
+	* various checkdoc fixes. Just the upper third of the file, but that
+	  should help a little, too. (-: Again, if you have any writing
+	  skills, take out that dusty keyboard and tap it to the beat of M-x
+	  checkdoc!
+
+2002-02-14  Gergely Nagy  <algernon@debian.org>
+
+	* erc.el 1.206 (erc-format-privmessage):
+	fix it, so timestamp-coloring works again (patch from antifuchs)
+
+2002-02-14  Mario Lang  <mlang@delysid.org>
+
+	* erc.el 1.205: Many fixes based on M-x checkdoc RET.
+	If you have write access, and some english knowledge, help document erc too!
+	M-x checkdoc RET, and follow the instructions.
+
+	* erc-button.el 1.10, erc-ibuffer.el 1.13: minor fixes
+
+	* erc.el 1.204: Use nreverse instead of reverse.
+	Use eq instead of equal where possible.
+	Rewrote erc-get-buffer to not use find-if (find-if does very deep function-call nesting, which isnt good ina  defun which is called so often)
+
+2002-02-13  Mario Lang  <mlang@delysid.org>
+
+	* erc-button.el 1.9, erc.el 1.203:
+	In erc.el, new hook: erc-channel-members-changed-hook.
+	erc-button.el: Now highlight all nicknames. uses regexp-opt.
+
+2002-02-04  Mario Lang  <mlang@delysid.org>
+
+	* erc-nets.el 1.1:
+	Database of irc networks. Use erc-server-select to interactively select one.
+
+	* erc.el 1.202: * erc-format-nick-function: New variable.
+	* (erc-format-nick): The default for above var. Just return the nick.
+	* (erc-format-@nick): Prefix NICK with @ or + if OP or VOICE.
+	* Removed erc-track-modified-channels related code and moved into erc-tracke.l
+	   Its auto-loaded now
+
+	* erc-track.el 1.1: Split code from erc.el
+
+2002-02-01  Mario Lang  <mlang@delysid.org>
+
+	* erc-ibuffer.el 1.12:
+	* erc-target now uses erc-port-to-string
+
+	* servers.pl 1.1:
+	Script to convert mircs servers.ini to a elisp salist kind of thing.
+	(development tool, it doesnt help you much as a user)
+
+	* erc.el 1.201:
+	* erc-display-line-buffer: renamed to erc-display-line-1
+	* erc-port-equal: New function.
+	* erc-normalize-port: Used by erc-port-equal
+	* minor docstring fixes
+
+2002-02-01  Andreas Fuchs  <asf@void.at>
+
+	* erc.el 1.200:
+	* erc-already-logged-in-p: compare ports is more robust now.
+
+	* erc-button.el 1.8: * Add buttonization to erc-send-modify-hook, too
+
+2002-01-31  Mario Lang  <mlang@delysid.org>
+
+	* erc.el 1.199:
+	Use insert-before-markers instead of insert in erc-display-line-buffer
+	This fixed point@column 0 problem and gives us some speedup! yay
+
+	* erc-ibuffer.el 1.11, erc.el 1.198: minor fixes
+
+	* erc.el 1.197:
+	* (erc-line-beginning-position): Renamed to erc-beg-of-input-line.
+	* (erc-line-end-position): Renamed to erc-end-of-input-line.
+	* erc-multiline-input-p: Variable removed.
+
+	* erc.el 1.196:
+	Minor docstring fixes (using M-x checkdoc-current-buffer)
+	  If you find time, and you are native english speaker, do that too!!
+
+	* erc.el 1.195: fixed macro-invokation
+
+2002-01-31  Andreas Fuchs  <asf@void.at>
+
+	* erc.el 1.194: * erc-with-all-buffers-of-server: use erc-list-buffers
+	* erc-process-away, erc-{save,kill}-query-buffers: use it.
+	* erc-cmd-away-all: new command. Set away/back on all servers.
+
+	* erc.el 1.193:
+	* Fix last multiline bug in erc-send-distinguish-noncommands.
+
+2002-01-31  Mario Lang  <mlang@delysid.org>
+
+	* erc-ibuffer.el 1.10, erc.el 1.192: minor fixes
+
+2002-01-30  Mario Lang  <mlang@delysid.org>
+
+	* erc-ibuffer.el 1.9, erc-menu.el 1.3, erc-speak.el 1.19, erc.el 1.191:
+	Renamed erc-track-modified-channels-minor-mode to erc-track-modified-channels-mode (at least, its a bit shorter)
+	Added docstring to erc-server-hooks (through the macro)
+	Minor docfix in obsolete hook
+
+2002-01-30  Andreas Fuchs  <asf@void.at>
+
+	* erc.el 1.190:
+	* erc-send-current-line: fix behaviour where buffer changes.
+	* erc-mark-message: fix stupid face bug. highlighting of pals should work now.
+
+	* erc-ring.el 1.2, erc.el 1.189:
+	* new hooks: erc-send-pre-hook, erc-send-modify-hook, erc-send-post-hook
+	* erc-send-this: new variable
+	* erc-noncommands-list: new constant.
+	* erc-send-distinguish-noncommands: use it. (First filter function for sending! yay!)
+	* erc-send-current-line: nearly completely rewritten.
+	  - now handles multiline input. (yay!)
+	  - now uses the three hooks from above.
+	* erc-process-line: new arg, no-command: don't process this line as a command.
+
+2002-01-30  Mario Lang  <mlang@delysid.org>
+
+	* erc-bbdb.el 1.12, erc-button.el 1.7, erc-speak.el 1.18, erc.el 1.188:
+	hook handling rewrite phase 1.
+
+2002-01-30  Andreas Fuchs  <asf@void.at>
+
+	* erc.el 1.187: * Rework erc-server-PRIVMSG-or-NOTICE
+	* New function: erc-is-message-ctcp-p
+	* New function: erc-format-privmessage
+	* New function: erc-mark-message
+	* erc-server-PRIVMSG-or-NOTICE: use them.
+
+2002-01-30  Mario Lang  <mlang@delysid.org>
+
+	* CREDITS 1.1, HISTORY 1.1:
+	Initial checkin.
+
+2002-01-29  Andreas Fuchs  <asf@void.at>
+
+	* erc.el 1.186: * erc-put-text-properties: make OBJECT optional
+	* erc-put-text-property: same
+	* erc-server-PRIVMSG-or-NOTICE: use them.
+	* Make erc-display-line-buffer: add the "\n" even when the string would be invisible.
+	* same: make the \n invisible, too (:
+
+2002-01-29  Mario Lang  <mlang@delysid.org>
+
+	* erc-ibuffer.el 1.8, erc.el 1.185:
+	Rewrote channel tracking using window-configuration-change-hook instead of defadvices.
+
+2002-01-28  Andreas Fuchs  <asf@void.at>
+
+	* erc-fill.el 1.6, erc.el 1.184:
+	* Macro define-erc-highlight-customization: Ease up defining
+	  erc-{fool,pal,..}-highlight-props defcusts.
+	* defcusts:
+	  - erc-fool-highlight-props
+	  - erc-pal-highlight-props
+	  - erc-dangerous-host-highlight-props
+	  - erc-keyword-highlight-props
+
+	  Customizable to either nil or "Hide message".
+	* erc-string-invisible-p: check for invisible chars in string
+	* erc-display-line-buffer: use it.
+	* erc-put-text-properties: put a list of props into a piece of text.
+	* erc-server-PRIVMSG-or-NOTICE: use it; set appropriate
+	  highlight-props for entire incoming message. This set of changes
+	  allows you to e.g. auto-ignore fools.
+
+2002-01-28  Mario Lang  <mlang@delysid.org>
+
+	* erc-ibuffer.el 1.7:
+	Added highlight detection support to the Mark column.
+	Now p, k, f, and d indicate pal, keyword, fool and dangerous-host related activity.
+
+	* erc.el 1.183:
+	Highlight tracking finished. All necessary info should now be in erc-modified-channels.
+
+	* erc.el 1.182, erc-ibuffer.el 1.6, erc-speedbar.el 1.7:
+	Added highlight tracking to track-modified-channels
+	   no display code yet, the info is just kept in erc-modified-channels
+	Added erc-modified column to ibuffer
+	speedbar update
+
+	* erc-ibuffer.el 1.5: Added erc-members column
+
+	* erc-ibuffer.el 1.4: *** empty log message ***
+
+2002-01-28  Andreas Fuchs  <asf@void.at>
+
+	* erc-bbdb.el 1.11:
+	* Fix a slight typo. The hook function should be called in
+	  erc-server-376-hook (-:
+
+2002-01-28  Mario Lang  <mlang@delysid.org>
+
+	* erc-ibuffer.el 1.3: *** empty log message ***
+
+2002-01-27  Mario Lang  <mlang@delysid.org>
+
+	* erc-ibuffer.el 1.2: Fixup, it sort of works now. Try it
+
+	* erc-ibuffer.el 1.1: Initial version
+
+2002-01-26  Mario Lang  <mlang@delysid.org>
+
+	* erc.el 1.181: *** empty log message ***
+
+2002-01-25  Andreas Fuchs  <asf@void.at>
+
+	* erc-bbdb.el 1.10: * fix two bad things:
+	  - fix the "proc trick": pass proc as an arg through
+	    ...-insinuate-... to ...-show-entry
+	  - hook highlighting into the 376 hook. This one is bound to get
+	    called (-:
+	* We now only append to hooks only.
+	* Highlighting of changing records gets updated automatically.
+
+2002-01-25  Mario Lang  <mlang@delysid.org>
+
+	* erc.el 1.180: *** empty log message ***
+
+2002-01-25  Andreas Fuchs  <asf@void.at>
+
+	* erc-bbdb.el 1.9: * nearly complete rewrite of erc-bbdb:
+	  -  Removed code duplication in erc-bbdb-NICK and -JOIN.
+	  -  Made erc-bbdb-show-entry more general and intelligent.
+	  -  erc-bbdb-insinuate-entry is now erc-bbdb-insinuate-and-show-entry
+	     (note the different arglist!):
+	  -  erc-search-name-and-create now creates "John Doe" users if name
+	     is not specified.
+	  -  No sign of "mail" anywhere anymore. It's all finger-host. (-:
+	  -  erc-bbdb-popup-p is now called erc-bbdb-popup-type.
+	  -  New customize values:
+	     . erc-bbdb-irc-channel-field     channel field name
+	     . erc-bbdb-irc-highlight-field   (see below)
+	     . erc-bbdb-auto-create-on-nick-p auto-create record on join
+
+	* Highlighting based on BBDB is now here! Specify which type of
+	  highlighting a person in the BBDB (whose nick you know) and have
+	  fun! Read help to erc-bbdb-init-highlighting for details. Changes:
+	  -  new function erc-bbdb-init-highlighting: gets called on server
+	     connect.
+	  -  new function erc-bbdb-highlight-record: highlights a person's
+	     nick names.
+
+2002-01-24  Andreas Fuchs  <asf@void.at>
+
+	* erc-button.el 1.6:
+	* Fix the erc-button-alist regexp for EmacsWiki stuff. delYsid's version
+	  is better (-:
+
+	* erc-button.el 1.5: * Added an Ewiki: specifier to the url-regexp.
+	  <nickname> EmacsWiki: EmacsIRCClient tells you <bla>
+	  should highlight "EmacsWiki: EmacsIRCClient" and allow you to
+	  browse to the wiki when the button is activated.
+	* new custom: erc-emacswiki-url.
+	* new function: erc-browse-emacswiki: use it.
+
+2002-01-23  Mario Lang  <mlang@delysid.org>
+
+	* erc-bbdb.el 1.8:
+	erc-bbdb-NICK: Added regexp-quote around fingerhost search.
+
+2002-01-10  Andreas Fuchs  <asf@void.at>
+
+	* erc.el 1.179:
+	* Channel saving/killing on quit from server implemented:
+	 - defcust erc-save-queries-on-quit: Save server's channel buffers on quitting from server
+	 - defcust erc-kill-queries-on-quit: Kill server's channel buffers on quitting from server
+	 - Macro erc-with-all-buffers-of-server: Run a form inside all the server's query buffers
+	 - Functions erc-{kill,save}-query-buffers: use it.
+	* Added indent-tabs-mode: t to Local Variables section.
+
+2002-01-07  Andreas Fuchs  <asf@void.at>
+
+	* erc-replace.el 1.2: * fix stupid documentation errors.
+
+2002-01-07  Mario Lang  <mlang@delysid.org>
+
+	* erc.el 1.178:
+	* (toplevel): Revert previous change. This resulted ina  recursive load...
+	   You have to put (require 'erc-button) into your .emacs for now
+
+2002-01-05  Mario Lang  <mlang@delysid.org>
+
+	* erc.el 1.177:
+	* Added require for erc-button. This is devel. so I need testers :)
+
+	* erc-button.el 1.4: * Added proper file headers (GPL).
+
+2002-01-04  Mario Lang  <mlang@delysid.org>
+
+	* erc-button.el 1.3: * erc-button-alist: Added entry for finger
+
+	* erc-button.el 1.2: * Removed bogus usage of :button-keymap.
+	P
+	   Does anyone know what this was supposed to do anyway?
+
+	* erc-button.el 1.1: * Initial version.
+	* This module allows a way of buttonizing text in IRC buffers.
+	  Default it is used for URLs, but other things could be added.
+	  see if you can find another use, erc-button-alist
+
+See ChangeLog.2001 for earlier changes.
+
+    Copyright (C) 2002 Free Software Foundation, Inc.
+  Copying and distribution of this file, with or without modification,
+  are permitted provided the copyright notice and this notice are preserved.
+
+;; Local Variables:
+;; coding: utf-8
+;; End:
+
+;; arch-tag: a6779d5e-99fa-442b-98cf-90e73eb2c272
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lisp/erc/ChangeLog.2003	Wed Feb 01 10:07:17 2006 +0000
@@ -0,0 +1,2151 @@
+2003-12-30  Francis Litterio  <franl@users.sourceforge.net>
+
+	* erc.el 1.595 (erc-cmd-HELP):
+	Changed to prefer giving help for erc-cmd-* functions over
+	   similarly-named Elisp functions (e.g., erc-cmd-LIST vs. list).
+
+2003-12-28  Francis Litterio  <franl@users.sourceforge.net>
+
+	* erc.el 1.594 (erc-query-buffer-p): Added this function.
+
+2003-12-28  Jorgen Schaefer  <forcer@users.sourceforge.net>
+
+	* erc.el 1.593 (erc-cmd-SV): Use erc-emacs-build-time.
+
+	* erc-compat.el 1.15: erc-emacs-build-time: New variable.
+
+	* erc.el 1.592 (erc-cmd-SAY):
+	Reintroduced the feature where the spaces between
+	"/SAY" and the rest of the line were being sent with the message.
+
+2003-12-28  Francis Litterio  <franl@users.sourceforge.net>
+
+	* erc.el 1.591 (erc-server-buffer-p):
+	Fixed a bug where this function sometimes would return
+	    nil when it should return t.
+
+2003-12-27  Francis Litterio  <franl@users.sourceforge.net>
+
+	* erc.el 1.590 (erc-generate-new-buffer-name):
+	Really fixed a bug where ERC would reuse
+	    a connected server buffer when erc-reuse-buffers is non-nil.
+	(erc-cmd-JOIN): Now we tell the user when he attempts to join the same
+	    channel twice on the same server.
+
+	* erc.el 1.589 (erc-generate-new-buffer-name):
+	Fixed a bug where ERC would reuse a connected server buffer when erc-reuse-buffers is non-nil.
+
+	* erc.el 1.588 (erc-cmd-SAY):
+	Fixed a bug where the spaces between "/SAY" and the rest of the
+	    line were being sent with the message.
+
+	* erc-list.el 1.15: Fixed another typo.
+
+	* erc-list.el 1.14: Fixed a typo.
+
+	* erc-list.el 1.13:
+	Added text to the top of the channel list buffer describing the keybinding for
+	function erc-chanlist-join-channel.
+
+	* erc-list.el 1.12: Minor appearance changes.  No functional change.
+
+	* erc-list.el 1.11:
+	Implemented function erc-chanlist-join-channel.  Added variable
+	erc-chanlist-channel-line-regexp.  Got rid of function
+	erc-chanlist-pre-command-hook.  Changed the logic for how channel lines are
+	highlighted.
+
+2003-12-26  Francis Litterio  <franl@users.sourceforge.net>
+
+	* erc-list.el 1.10:
+	Removed a bunch of unused code.  No semantic change.
+
+	* erc-list.el 1.9: Added lots of functionality.
+
+2003-12-15  Mario Lang  <mlang@delysid.org>
+
+	* erc-track.el 1.58, erc.el 1.587:
+	New custom type erc-message-type, use it in erc-hide-list and erc-track-exclude-types
+
+2003-12-14  Alex Schroeder  <alex@gnu.org>
+
+	* erc-track.el 1.57 (track-when-inactive): New module.
+	(erc-track-visibility): New option.
+	(erc-buffer-activity): New variable.
+	(erc-buffer-activity-timeout): New variable.
+	(erc-user-is-active): New function.
+	(erc-buffer-visible): New function.
+	(erc-modified-channels-update): Replace get-buffer-window call
+	with call to erc-buffer-visible.
+	(erc-track-modified-channels): Ditto.
+
+2003-12-14  Lawrence Mitchell  <wence@gmx.li>
+
+	* erc-track.el 1.56 (erc-modified-channels-update):
+	Force update of modeline.  Makes sure
+	that the tracked channels disappear in other buffers too.
+
+2003-12-06  Lawrence Mitchell  <wence@gmx.li>
+
+	* erc.el 1.586 (define-erc-module):
+	New optional argument LOCAL-P.  If non-nil, then
+	mode will be created as buffer-local rather than a global mode.
+	(erc-cmd-CTCP): Fix indentation from last commit.
+
+	* erc-compat.el 1.14 (erc-define-minor-mode):
+	Deal with :global and :group keywords.
+
+	* erc-nickserv.el 1.13 (erc-current-network):
+	Make server regex more permissive.
+
+	* erc.el 1.585 (erc-cmd-CTCP):
+	Don't add a space to end of command when ARGS are
+	empty.  This fixes a bug whereby requests of the form "VERSION " were
+	being sent, and ignored.
+
+2003-11-27  Lawrence Mitchell  <wence@gmx.li>
+
+	* erc-log.el 1.9: From Adrian Aichner <adrian@xemacs.org>
+	* erc-log.el (erc-log-file-coding-system): Use 'binary
+	coding-system under XEmacs (instead of 'emacs-mule).
+	* erc-log.el (erc-w32-invalid-file-characters): Removed as no
+	longer needed.
+	* erc-log.el (erc-generate-log-file-name-long): Use
+	`convert-standard-filename', which exists in XEmacs too.
+
+2003-11-16  Mario Lang  <mlang@delysid.org>
+
+	* erc-identd.el 1.1: Code provided by johnw, thanks!
+
+2003-11-09  Lawrence Mitchell  <wence@gmx.li>
+
+	* erc.el 1.584 (erc-latest-version): Clean up docstring.
+	Remove requirement for w3, wrap REQUIRE statement in IGNORE-ERRORS.
+	Update viewcvs url to correct location.
+	(erc-ediff-latest-version): Make sure that we find the uncompiled
+	erc.el, error if not.
+
+2003-11-07  Mario Lang  <mlang@delysid.org>
+
+	* erc.el 1.583: Add more info to /sv
+
+2003-11-06  Francis Litterio  <franl@users.sourceforge.net>
+
+	* erc.el 1.582: Added optional argument BUFFER to erc-server-buffer-p.
+
+2003-11-04  Mario Lang  <mlang@delysid.org>
+
+	* AUTHORS 1.6: Add sachac
+
+2003-11-02  Lawrence Mitchell  <wence@gmx.li>
+
+	* erc.el 1.581 (erc-server-366):
+	chnl is 4th element of parsed, not fifth.
+	(erc-channel-end-receiving-names): Pass correct number of arguments
+	to delete-if-not.
+
+	* erc.el 1.580 (erc-update-current-channel-member):
+	 Use erc-downcase when comparing
+	nick entries.  Cleanup indentation.
+
+2003-11-01  Lawrence Mitchell  <wence@gmx.li>
+
+	* erc-sound.el 1.4: Added a (provide 'erc-sound) line.
+
+	* erc.el 1.579 (erc-cmd-NAMES): send to TGT, not CHANNEL.
+
+2003-10-29  Sandra Jean Chua  <sacha@free.net.ph>
+
+	* erc-pcomplete.el 1.21, erc.el 1.578, CREDITS 1.6:
+	Merged Jeremy Maitin-Shepard's patch for time-sensitive nick completion.
+
+2003-10-27  Mario Lang  <mlang@delysid.org>
+
+	* Makefile 1.19, debian/changelog 1.24:
+	New Debian package 4.0.cvs.20031027
+
+2003-10-25  Mario Lang  <mlang@delysid.org>
+
+	* erc.el 1.577: Fix typo tuncate->rruncate
+
+2003-10-24  Mario Lang  <mlang@delysid.org>
+
+	* erc-dcc.el 1.80: From Stephan Stahl <stl@isogmbh.de>:
+	 * (erc-dcc-send-block): Kill buffer if transfer completed correctly.
+
+2003-10-22  Mario Lang  <mlang@delysid.org>
+
+	* erc-track.el 1.55 (erc-track-disable):
+	Do not deactivate all advices for `switch-to-buffer',
+	just disable the erc specific one. (Bug#217022).
+
+2003-10-18  Lawrence Mitchell  <wence@gmx.li>
+
+	* erc-log.el 1.8 (erc-log-file-coding-system): New variable.
+	(erc-save-buffer-in-logs): Use it.
+
+2003-10-17  Mario Lang  <mlang@delysid.org>
+
+	* erc.el 1.576 (erc-interpret-mirc-color): New boolean defcustom
+
+	* erc.el 1.575: Do not use -nowait on darwin (thanks johnw)
+
+2003-10-15  Lawrence Mitchell  <wence@gmx.li>
+
+	* erc.el 1.574 (define-erc-module):
+	Set erc-FOO-mode appropriately in erc-FOO-enable
+	and erc-FOO-disable.
+
+2003-10-12  Jorgen Schaefer  <forcer@users.sourceforge.net>
+
+	* erc-autoaway.el 1.12 (erc-mode):
+	Reset idletime on connect. Fixes an annoying bug which
+	flooded the server with aways on reconnect.
+	(erc-autoway-reset-idletime): Accept optional args so we can hook it
+	onto erc-server-001-hook.
+
+2003-10-10  Mario Lang  <mlang@delysid.org>
+
+	* erc.el 1.573 (erc-hide-list): Add a nice defcustom type
+
+2003-10-08  Mario Lang  <mlang@delysid.org>
+
+	* Makefile 1.18, debian/changelog 1.23, debian/control 1.8:
+	Debian snapshot 20031008
+
+	* erc-speedbar.el 1.11:
+	Patch from Eric M. Ludlam <eric@siege-engine.com>:
+	 - (erc-install-speedbar-variables): Add functions list (needs new speedbar?)
+	 - (erc-speedbar-buttons): Add doc.  Clear the buffer
+	 - (erc-speedbar-sort-channel-members): New function.
+	 - (erc-speedbar-expand-channel): Call new sort function.  Change some visuals.
+	 - (erc-speedbar-insert-user): Change some visuals based on channel data.
+	 - (erc-speedbar-line-text, erc-speedbar-item-info): New functions
+	Add proper elisp file header.
+
+2003-10-02  Lawrence Mitchell  <wence@gmx.li>
+
+	* erc-match.el 1.22 (erc-match-syntax-table): New variable.
+	(erc-match-current-nick-p): Use it.
+
+	* erc.el 1.572 (erc-quit-reason-zippy, erc-part-reason-zippy): Use
+	`erc-replace-regexp-in-string' rather than
+	`replace-regexp-in-string'.
+	(erc-command-indicator-face): New face, used to show commands if
+	`erc-hide-prompt' is nil and `erc-command-indicator' is non-nil.
+	(erc-command-indicator): Clean up doc-string.
+	(erc-display-prompt): New optional argument FACE, use this rather
+	than `erc-prompt-face' to fontify the prompt if non-nil.
+	(erc-send-current-line): Pass in `erc-command-indicator-face' to
+	`erc-display-prompt'.
+
+	* erc-compat.el 1.13 (erc-replace-regexp-in-string): New function.
+	Alias for `replace-regexp-in-string' on Emacs 21.
+	Argument massaging for `replace-in-string' for XEmacs.
+
+2003-09-28  Jorgen Schaefer  <forcer@users.sourceforge.net>
+
+	* erc.el 1.571 (erc-keywords): Removed. Wasn't used by anything.
+
+2003-09-25  Lawrence Mitchell  <wence@gmx.li>
+
+	* erc.el 1.570: ERC-HIDE-PROMPT: add custom group
+	ERC-COMMAND-INDICATOR: new variable.
+	ERC-COMMAND-INDICATOR: new function.
+	ERC-DISPLAY-PROMPT: new argument, PROMPT, used to override default
+	prompt.
+	ERC-SEND-CURRENT-LINE: pass ERC-COMMAND-INDICATOR to ERC-DISPLAY-PROMPT.
+
+2003-09-24  Jorgen Schaefer  <forcer@users.sourceforge.net>
+
+	* erc.el 1.569 (erc-parse-line-from-server):
+	Ignore empty lines as required by RFC.
+
+2003-09-17  Mario Lang  <mlang@delysid.org>
+
+	* erc.el 1.568: Add lag time calculation
+
+2003-09-13  Mario Lang  <mlang@delysid.org>
+
+	* Makefile 1.17, debian/README.Debian 1.7, debian/changelog 1.22:
+	New debian release
+
+	* erc-notify.el 1.22:
+	Call erc-notify-install-message-catalogs on load, not on module init
+
+	* erc.el 1.567 (erc-update-modules):
+	Use `load' instead of `require'.  XEmacs appears
+	to have the NOERROR arg only sometimes... Strange
+
+	* erc.el 1.566: No fboundp if we have a defvar
+
+	* erc.el 1.565: Properly defvar erc-ping-handler
+
+2003-09-11  Damien Elmes  <erc@repose.cx>
+
+	* erc.el 1.564 (erc-setup-periodical-server-ping):
+	check if erc-ping-handler is
+	    bound before referencing it
+
+2003-09-10  Mario Lang  <mlang@delysid.org>
+
+	* erc.el 1.563 (erc-cmd-NICK):
+	Warn about exceeded NICKLEN if we know it.
+
+	* erc.el 1.562: Make erc-server-PONG obey erc-verbose-server-ping.
+	Cancel old `erc-ping-handler' timer when restablishing connection in the same
+	buffer.
+
+	* debian/changelog 1.21, Makefile 1.16: New debian snapshot
+
+	* erc-dcc.el 1.79, erc-xdcc.el 1.6:
+	Use new function erc-dcc-file-to-name to convert spaces to underscores
+
+	* erc-xdcc.el 1.5: Add autoload for erc-xdcc-add-file
+
+2003-09-08  Mario Lang  <mlang@delysid.org>
+
+	* erc-dcc.el 1.78: indent fixes and copyright update
+
+	* erc.el 1.561:
+	erc-send-ping-interval: New defcustom which defaults to 60.
+	Every 60 seconds, we send PING now.
+	This should fix the "connection silently lost" bug.
+	Please test this change extensively, and report problems.
+
+2003-09-07  Alex Schroeder  <alex@gnu.org>
+
+	* erc.el 1.560 (erc-default-coding-system):
+	Test for undecided and utf-8
+	before setting.
+
+2003-09-01  Mario Lang  <mlang@delysid.org>
+
+	* erc.el 1.559 (erc-modules): Add some more symbols to the set
+
+	* erc.el 1.558 (erc-modules):	* erc.el 1.558 (erc-modules): Add :greedy t to the set in 
+
+	* erc-dcc.el 1.77:
+	More autoloads which make dcc autoload upon ctcp dcc query received.
+
+	* erc-dcc.el 1.76 (erc-cmd-DCC): Add Autoload.
+	(pcomplete/erc-mode/DCC): Ditto, makes DCC autoloadable just by using
+	completion.
+	Also only offer "send" if fboundp make-network-process.
+
+	* erc-autojoin.el 1.6: Update copyright
+
+	* erc-autojoin.el 1.5 (erc-autojoin-add):
+	Only add the channel if it is not already there.
+
+	* erc-notify.el 1.21:
+	Use `define-erc-module' instead of old `erc-notify-initialize'.
+	Now defines the global minor mode erc-notify-mode, and should also
+	be controllable via `erc-modules' with symbol `notify'.
+
+	* erc.el 1.557 (erc-modules):
+	Fix paren-in-column-zero bug in docstring.
+	Add a sort of bogus, but still better :type.
+	Add autojoin and netsplit by default.
+	(erc-update-modules): Dont barf with an error if `require' fails.
+	We can still error out if the mode is not defined.
+
+2003-08-31  Andreas Fuchs  <asf@void.at>
+
+	* erc.el 1.556:
+	* make 353 (NAMES reply) output go into the appropriate channel buffer
+	  (if it exists) or into the active erc buffer (if not).
+
+2003-08-29  mtoledo  <mtoledo@confusibombus>
+
+	* erc.el 1.555:
+	Added the variable erc-echo-notices-in-current-buffer to make possible display notices in the current buffer (queries to nickserv/chanserv/memoserv). Defaults to nil so nothing changes from what we have today.
+
+2003-08-29  Mario Lang  <mlang@delysid.org>
+
+	* erc.el 1.554: Fix typo in varname which led to a compiler warning
+
+	* AUTHORS 1.5: Added lawrence
+
+2003-08-27  Mario Lang  <mlang@delysid.org>
+
+	* erc-dcc.el 1.75:
+	Set process and file-coding system to 'binary (for Windows)
+
+	* erc-stamp.el 1.30: Rename custom group erc-timestamp to erc-stamp.
+
+2003-08-07  Lawrence Mitchell  <wence@gmx.li>
+
+	* erc-fill.el 1.23 (erc-fill-disable):
+	Remove erc-fill, not erc-fill-static from
+	erc-insert-modify-hook.
+
+2003-08-05  Francis Litterio  <franl@users.sourceforge.net>
+
+	* erc.el 1.553 (erc-send-current-line):
+	Now we display the prompt for previously entered commands
+	    based on the value of customization variable erc-hide-prompt.  This change is
+	    closely related to revision 1.552 by wencem.
+
+2003-08-04  Lawrence Mitchell  <wence@gmx.li>
+
+	* erc.el 1.552 (erc-send-current-line):
+	If we're sending a command, don't display
+	the prompt.
+
+2003-08-04  Damien Elmes  <erc@repose.cx>
+
+	* erc-track.el 1.54: patch from David Edmondson (dme AT dme DOT org)
+
+	This patch makes button 3 on the erc-track buffer names in the
+	modeline show the selected buffer in another window. It's analogous to
+	button 2 which shows the buffer in the current window.
+
+2003-07-31  Francis Litterio  <franl@users.sourceforge.net>
+
+	* erc.el 1.551 (erc-display-line-1):
+	Fixed bad indentation on one line.  No semantic change.
+
+2003-07-29  Lawrence Mitchell  <wence@gmx.li>
+
+	* erc-match.el 1.21:
+	Quote open paren in docstring of erc-text-matched-hook
+
+	* erc.el 1.550: Anchor match only at beginning in erc-ignored-user-p.
+
+	* erc-button.el 1.47: New variable erc-button-wrap-long-urls.
+	Modified erc-button-add-buttons:
+	  New optional argument REGEXP.
+	  If we're buttonising a URL and erc-button-wrap-long-urls is
+	  non-nil, try and wrap them
+
+	Modified erc-button-add-buttons-1:
+	  Pass regexp to erc-button-add-buttons.
+
+2003-07-28  Francis Litterio  <franl@users.sourceforge.net>
+
+	* erc.el 1.549 (erc-network-name):
+	Improved docstring.  Removed an unnecessary call to erc-server-buffer.
+
+2003-07-28  Mario Lang  <mlang@delysid.org>
+
+	* erc.el 1.548: By lawrence:
+	(erc-ignored-user-p): Use anchored regexp.
+	(smiley): Fix missing quote in `remove-hook' call.
+
+2003-07-26  Francis Litterio  <franl@users.sourceforge.net>
+
+	* erc-nets.el 1.4, erc-nickserv.el 1.12, erc.el 1.547:
+	Changed all references to Openprojects into references to Freenode.
+
+2003-07-25  Francis Litterio  <franl@users.sourceforge.net>
+
+	* erc.el 1.546:
+	Now variable erc-debug-irc-protocol is defvar'ed instead of defcustom'ed.
+	Made the docstring clearer too.
+
+	* erc.el 1.545: Fixed a wrong-type-argument error from window-live-p.
+
+2003-07-15  Damien Elmes  <erc@repose.cx>
+
+	* erc-log.el 1.7 (erc-log-setup-logging):
+	set buffer-file-name to "", as (basic-save-buffer)
+	    will prompt for a buffer name before invoking hooks. the buffer-file-name
+	    will be overridden by (erc-save-buffer-in-logs) anyway - the main danger
+	    of doing this is write-file-contents hooks. Let's see if anyone complains.
+	(erc-save-buffer-in-logs): return t, so that further write hooks are not run
+
+2003-07-09  Damien Elmes  <erc@repose.cx>
+
+	* erc-dcc.el 1.74 (erc-dcc-open-network-stream):
+	-nowait still crashes emacs cvs - disable for now
+
+2003-07-02  Francis Litterio  <franl@users.sourceforge.net>
+
+	* erc.el 1.544 (erc): Minor docstring modification.
+
+2003-07-01  Damien Elmes  <erc@repose.cx>
+
+	* erc-match.el 1.20 (erc-match-current-nick-p):
+	match only on word boundaries
+
+	* erc-log.el 1.6 (erc-log-setup-logging):
+	not sure how this crept in again - make sure we set
+	    buffer-file-name to nil, since otherwise it is not possible to open
+	    previous correspondence in another buffer while a conversation is open
+
+2003-06-28  Francis Litterio  <franl@users.sourceforge.net>
+
+	* erc.el 1.543 (erc-network-name):
+	Now makes some intelligent guesses if the server didn't tell
+	    us the network name.
+
+2003-06-28  Alex Schroeder  <alex@gnu.org>
+
+	* erc.el 1.542 (erc-default-coding-system): Use utf-8 as the default
+	encoding for outgoing stuff and undecided as the default for
+	incoming stuff.
+	(erc-coding-sytem-for-target): New.
+	(erc-encode-string-for-target): Use it.
+	(erc-decode-string-from-target): Use it.  Removed the flet
+	erc-default-target hack and documented the dynamically bound
+	variable `target' instead.
+
+2003-06-25  Francis Litterio  <franl@users.sourceforge.net>
+
+	* erc.el 1.541 (erc-log-irc-protocol):
+	Now we keep point on the bottom line of the window
+	    displaying the *erc-protocol* buffer if it is at the end of the
+	    *erc-protocol* buffer.
+
+	* erc.el 1.540:
+	Added some text to the docstring for variable erc-debug-irc-protocol.
+
+2003-06-23  Francis Litterio  <franl@users.sourceforge.net>
+
+	* erc-dcc.el 1.73 (erc-dcc-auto-mask-p):
+	Fixed a docstring typo that caused a load-time error.
+
+	* erc-dcc.el 1.72 (erc-dcc-auto-mask-p):
+	Changed reference to undefined variable erc-dcc-auto-mask-list
+	    to erc-dcc-auto-masks.
+	Changed default value of variable erc-dcc-auto-masks to nil and added text to its
+	    docstring.
+
+	* erc-notify.el 1.20 (erc-notify-timer and erc-notify-QUIT):
+	Added network name to notify_off message.
+
+	* erc.el 1.539 (erc-network-name):
+	Now returns the name of the IRC server if the network name
+	    cannot be determined.
+
+	* erc-notify.el 1.19 (erc-notify-JOIN and erc-notify-NICK):
+	Added argument ?m to call to erc-display-message.
+
+	* erc-dcc.el 1.71 (erc-dcc-do-LIST-command):
+	Fixed a bug where I assumed (plist-get elt :type)
+	    returns a string -- it really returns a symbol.
+
+	* erc-notify.el 1.18 (erc-notify-timer):
+	Now we include the network name in the notify_on message.
+
+	* erc.el 1.538:
+	New function: erc-network-name.  Returns the name of the network that the
+	    current buffer is associate with.  Not every server sends the 005 messages
+	    that enable the network name to be known.  If the network name is
+	    not known, the string "UNKNOWN" is returned.
+
+	* erc-dcc.el 1.70 (erc-dcc-chat-setup):
+	Added a comment.  Fixed a bug where a DCC CHAT buffer has no
+	    prompt when it first appears.
+
+	* erc-dcc.el 1.69 (erc-dcc-chat-parse-output):
+	Now a DCC chat buffer displays the nick using
+	    erc-nick-default-face just like in a channel buffer.
+
+2003-06-22  Francis Litterio  <franl@users.sourceforge.net>
+
+	* erc.el 1.537 (erc-display-prompt):
+	Fixed incorrect indentation.  No semantic change.
+
+	* erc.el 1.536 (erc-strip-controls):
+	Minor change to regexp that matches IRC color control
+	    codes.  I was seeing usage as follows: ^C07colored text^C^C04other color.
+	    Now we strip a ^C followed by zero, one, or two digits.  Before this change,
+	    we stripped a ^C followed by one or two digits.
+
+	* erc-dcc.el 1.68 (erc-dcc-do-LIST-command):
+	Improved format of output of /DCC LIST.  Now the
+	    "Size" column for a DCC GET includes the percentage of the file that has
+	    been retrieved.
+	(erc-dcc-do-GET-command): Now it works if erc-dcc-default-directory is set.
+
+2003-06-19  Damien Elmes  <erc@repose.cx>
+
+	* erc-log.el 1.5:
+	* added quickstart information to the comments up the top
+
+2003-06-16  Mario Lang  <mlang@delysid.org>
+
+	* erc.el 1.535:
+	Default to open-network-stream on MS Windows. (thanks lawrence)
+
+2003-06-11  Damien Elmes  <erc@repose.cx>
+
+	* erc.el 1.534 (erc-process-input-line):
+	refactor so that wrong-number-of-arguments is
+	    caught when using do-not-parse-args - this lets do-not-parse-args
+	    commands display help messages on incorrect syntax in a uniform manner.
+	    This no longer raises a bad-syntax error - was this a catch-all to stop a
+	    backtrace? Does it belong?
+	(erc-cmd-APPENDTOPIC): the correct way to display help when you want to
+	    accept an abitrary string is to (signal 'wrong-number-of-arguments nil).
+	    This fixes a bug where people could not /at topics with a space in them.
+
+2003-06-09  Damien Elmes  <erc@repose.cx>
+
+	* erc.el 1.533:
+	Re-add the last few changes which weren't merged for some reason.
+
+	* erc.el 1.532 (erc-cmd-APPENDTOPIC): show help when given no arguments
+
+	Patch from MrBump. Fixes problem with erc-set-topic inserting ^C characters
+	into the topic. Also removes dependency on CL.
+
+2003-06-08  Jorgen Schaefer  <forcer@users.sourceforge.net>
+
+	* erc.el 1.531:
+	Added comment to explain (eval-after-load "erc" '(erc-update-modules)).
+
+2003-06-01  Mario Lang  <mlang@delysid.org>
+
+	* erc-pcomplete.el 1.20: Add completion for /unignore
+
+2003-05-31  Alex Schroeder  <alex@gnu.org>
+
+	* erc-compat.el 1.12 (erc-encode-coding-string): The default binding,
+	if encode-coding-string was not available, must be a defun that
+	takes multiple arguments.  Did that.
+
+2003-05-30  Mario Lang  <mlang@delysid.org>
+
+	* erc.el 1.530:
+	Add handlers for 313 and 330 (by arne@rfc2549.org, thanks)
+
+2003-05-30  Damien Elmes  <erc@repose.cx>
+
+	* erc.el 1.529:
+	patch from MrBump to make /mode #foo +b work again (erc-cmd-BANLIST only
+	temporarily changes them now)
+
+2003-05-29  Alex Schroeder  <alex@gnu.org>
+
+	* erc.el 1.528 (erc-select):
+	server is now defaulted with erc-compute-server.
+	A few cosmetic fixes.
+	(erc-default-coding-system): Renamed from erc-encoding-default.
+	(erc-encoding-default): Renamed to erc-default-coding-system.
+	(erc-encoding-coding-alist): Documentation updated to cover regexps.
+	(erc-encode-string-for-target): Now considers keys of
+	erc-encoding-coding-alist to be regexps.  Rely on erc-compat
+	wrt. MULE support.
+	(erc-decode-string-from-target): New function.
+	(erc-send-current-line): eq -> char-equal fix.
+	(erc-server-TOPIC): topic is now decoded with
+	erc-decode-string-from-target.
+	(erc-parse-line-from-server): Line from server is no longer decoded
+	here.
+	(erc-server-PRIVMSG-or-NOTICE): Message from a user is decoded here,
+	sspec -> sender-spec for clarity.  Cosmetic if -> when fix.
+	(erc-server-TOPIC): sspec -> sender-spec
+	(erc-server-WALLOPS): Ditto.
+
+	* erc-compat.el 1.11 (erc-decode-coding-string):
+	Now requires coding-system as an argument.
+
+2003-05-15  Mario Lang  <mlang@delysid.org>
+
+	* erc.el 1.527:
+	erc-part|quit-hook is only run on a part|quit directed to our nick, reflect that in the docstring to avoid confusion
+
+2003-05-01  Andreas Fuchs  <asf@void.at>
+
+	* erc-truncate.el 1.3:
+	* erc-truncate-buffer-to-size: use fboundp. Scheme takes its toll...
+
+2003-05-01  Jorgen Schaefer  <forcer@users.sourceforge.net>
+
+	* erc-truncate.el 1.2: remove require of erc-log
+	(erc-truncate-buffer-to-size): use erc-save-buffer-in-logs when it's
+	there, else, dont.
+
+2003-04-29  Andreas Fuchs  <asf@void.at>
+
+	* erc-log.el 1.4, erc-truncate.el 1.1, erc.el 1.526: erc.el:
+		* erc-cmd-QUIT: Remove references to code in erc-log.el, to
+		  not force autoloading of erc-log.el
+		* erc-server-PART: ditto.
+		* erc-quit-hook: new hook, run when /quit command is
+		  processed.
+		* erc-cmd-QUIT: use it.
+		* erc-part-hook: new hook, run then PART message is
+		  processed.
+		* erc-cmd-PART: use it.
+		* erc-connect-pre-hook: new hook, run before connection to IRC
+		  server is started.
+		* erc: use it.
+		* erc-max-buffer-size: Move truncation variables and functions
+		  to erc-truncate.el
+		* erc-truncate-buffer-on-save: moved to erc-log.el
+		* erc-initialize-log-marker: new function.
+	erc-log.el:
+		* erc-truncate-buffer-on-save: New defcust here; from erc.el
+		* erc-truncate-buffer-on-save: Put it in group `erc-log'
+		* erc-log-channels-directory: Remove trailing slash from
+		  default value.
+		* Add functions to erc-connect-pre-hook, erc-part-hook and
+		  erc-quit-hook to avoid getting autoloaded.
+
+	erc-truncate.el:
+		* Contains the truncation functions and defcusts from erc.el.
+		* define-erc-module clause added; new erc-truncate-mode.
+
+2003-04-29  Jorgen Schaefer  <forcer@users.sourceforge.net>
+
+	* erc.el 1.525 (erc):
+	Check wether erc-save-buffer-in-logs is bound, too
+
+	* erc.el 1.524 (erc):
+	Check wether erc-logging-enabled is bound before using it - not
+	everyone is using erc-log.el!
+
+2003-04-28  Andreas Fuchs  <asf@void.at>
+
+	* erc-log.el 1.3:
+	* while we're at it, remove the (declare (ignore ignore)) statements.
+
+	* erc-log.el 1.2:
+	* add autoload statement for erc-log-mode/etc. Sorry for the delay.
+
+	* erc-log.el 1.1, erc.el 1.523: * erc.el:
+		- move variables and functions to erc-log.el:
+			 defgroup `erc-log'
+	                 defcustom `erc-log-channels-directory'
+			 defcustom `erc-log-insert-log-on-open'
+			 defcustom `erc-generate-log-file-name-function'
+			 defun `erc-save-buffer-in-logs' (autoloads from erc-log.el)
+	 		 defuns `erc-generate-log-file-name-*'
+			 defun `erc-current-logfile'
+			 defun `erc-logging-enabled' (autoloads from erc-log.el)
+		- erc-truncate-buffer-to-size: fix for double-saving bug when
+		  writing out truncated buffer contents. Thanks, lawrence mitchell <wence@gmx.li>!
+		- erc-remove-text-properties-region: Fix case for read-only text.
+		- erc-send-current-line: update insert-marker before calling the hooks.
+		                         also, wrap (erc-display-prompt) so that it doesn't toggle
+					 buffer-modified-p.
+		- erc-interpret-controls: remove /very/ old commented-out function
+		- erc-last-saved-position: make it a marker
+		- erc: use it.
+
+	* erc-log.el: (thanks, lawrence mitchell <wence@gmx.li>!)
+		- Move logging code from erc.el here
+		- define-erc-module log: add; minor mode erc-log-mode is the
+		  same as adding the `erc-save-buffer-in-logs' to
+		  erc-send-post-hook and `erc-insert-post-hook'.
+		- erc-w32-invalid-file-characters: add.
+		- erc-enable-logging: add.
+		- erc-logging-enabled: use it.
+		- erc-logging-enabled: autoload.
+		- erc-save-buffer-in-logs: fix for truncating saved buffer with read-only text.
+		- erc-save-buffer-in-logs: use erc-last-saved-position.
+		- erc-save-buffer-in-logs: fix saving half-written messages on
+		  the prompt when saving the log file. (simply uses
+		  erc-insert-marker as an upper bound for saving).
+
+2003-04-27  Damien Elmes  <erc@repose.cx>
+
+	* erc.el 1.522:	* erc.el 1.522: erc-modules: added 
+
+2003-04-27  Alex Schroeder  <alex@gnu.org>
+
+	* Makefile 1.15 (UNCOMPILED): Added erc-compat.el.
+	(clean): Remove .elc files, too.
+	Patch by Hynek Schlawack <hynek+erc@hys.in-berlin.de>
+
+2003-04-22  Damien Elmes  <erc@repose.cx>
+
+	* erc-button.el 1.46:
+	erc-button-keymap: set the parent keymap to erc-mode-map
+
+2003-04-20  Damien Elmes  <erc@repose.cx>
+
+	* erc.el 1.521:
+	erc-official-location: shouldn't the official location be the base URL of erc?
+
+	* erc.el 1.520:
+	erc-modules: updated the docstring to make the semantics clearer
+
+2003-04-19  Mario Lang  <mlang@delysid.org>
+
+	* erc.el 1.519:
+	Fix problem where % in NOTICE produced errors (from mmc)
+
+2003-04-18  Damien Elmes  <erc@repose.cx>
+
+	* erc.el 1.518 (erc-toggle-debug-irc-protocol):
+	moved a reference to 'buf' inside the let
+	    statement which defines it. it's difficult to tell what the original
+	    intentions were here - at the moment the debug window is displayed when
+	    toggling either way.
+
+	* README 1.3, erc.el 1.517:
+	(erc-update-modules: added a condition in for erc-nickserv -> erc-services
+
+	* erc-pcomplete.el 1.19:
+	- that change to erc-update-modules making it require the modules first means
+	  we don't need any special case handling here, so i reverted the previous
+	  change
+
+	* erc.el 1.516:
+	- don't require 'erc-auto, since windows users don't have access to make.
+	  instead, we handle it in (erc-update-modules)
+
+2003-04-17  Damien Elmes  <erc@repose.cx>
+
+	* README 1.2, Makefile 1.14:
+	Updated Makefile and documentation to reflect the new release
+
+	* erc.el 1.515:
+	- note the previous change also updated the release number to erc 4.0!
+	(erc-connect): fix a bug introduced by the previous release
+
+	* erc.el 1.514:
+	fixed about 20 instances of (message (format ...)) which will break if the
+	format returns a string with %s in it
+
+	* erc.el 1.513: erc-error-face: make it red, not pink
+
+	* erc-pcomplete.el 1.18:
+	since pcomplete is autoloaded via erc-completion-mode, and completion is in
+	erc-modules by default, we remove completion when pcomplete is added
+
+	* erc.el 1.512 (define-erc-module): no need for delete, use delq
+
+	* erc-members.el 1.5 (erc-nick-channels):
+	(erc-person-channels) takes one arg
+	(erc-format-user): again, they all take an arg
+
+	* erc.el 1.511:
+	- require erc-auto when loading, so the default `erc-modules' can be loaded.
+	  this makes erc-auto no longer a convenience but a necessity - all the name
+	  of user friendliness.
+	(define-erc-module): the enable and disable routines now update erc-modules
+	    accordingly
+	erc-modules: new variable controllig the modules which erc has loaded/will
+	    load. when customising, it will automatically enable modules. it won't
+	    automatically disable modules which are removed, yet.
+	(erc-update-modules): enable all modules in `erc-modules'
+
+	* erc-dcc.el 1.67 (erc-dcc-open-network-stream):
+	use the -nowait equiv if available
+	erc-dcc-server-port: removed
+	erc-dcc-port-range: allows a range of values, so you can have more than one
+	    dcc
+	(erc-dcc-server): support erc-dcc-port-range
+	(erc-dcc-chat): use OCHAT for outgoing chat for now. we need to fix the
+	    issues with allowing more than one chat with the same person
+
+	* erc.el 1.510:
+	erc-log-channels: removed; set the directory to start logging
+	(erc-directory-writeable-p): create directory if it doesn't exist, check if
+	    it's writeable
+	(erc-logging-enabled): don't reference erc-log-channels
+
+2003-04-07  Damien Elmes  <erc@repose.cx>
+
+	* erc.el 1.509 (erc):
+	but when inserting the contents of a previous logfile, use the logfile
+	    name, not ""!
+
+	* erc.el 1.508 (erc):
+	set buffer-file-name to "", since we have a custom saving function and
+	    it's not needed. this enables one to open a log file with previous
+	    correspondence, while talking to the person at the same time
+
+2003-03-29  Francis Litterio  <franl@users.sourceforge.net>
+
+	* erc.el 1.507 (erc-prepare-mode-line-format):
+	Now strips all text properties from the target before
+	    putting it in the mode line.  Keeps the mode line looking consistent.
+	(erc-channel-p): Improved docstring.
+
+2003-03-28  Alex Schroeder  <alex@gnu.org>
+
+	* erc.el 1.506 (erc-generate-log-file-name-with-date): New function.
+	(erc-generate-log-file-name-function): Make it available.
+
+2003-03-24  Mario Lang  <mlang@delysid.org>
+
+	* erc.el 1.505:
+	Fix erc-prompt and erc-user-mode custom :type (Closes: #185794)
+
+2003-03-20  Damien Elmes  <erc@repose.cx>
+
+	* erc.el 1.504:
+	erc-server-hook-list: correct documentation of ordering of (proc parsed)
+
+2003-03-16  Alex Schroeder  <alex@gnu.org>
+
+	* erc-track.el 1.53 (erc-modified-channels-string):
+	Make it a risky-local-variable.
+
+2003-03-16  Jorgen Schaefer  <forcer@users.sourceforge.net>
+
+	* erc-track.el 1.52 (erc-track-modified-channels):
+	Use (point-min) if we don't find a
+	parsed-property, so it won't error out with nil...
+
+2003-03-16  Damien Elmes  <erc@repose.cx>
+
+	* erc-track.el 1.51 (erc-track-switch-buffer):
+	removed call to erc-modified-channels-update, as
+	    this is done correctly on buffer switching in both emacs and xemacs now
+
+2003-03-15  Damien Elmes  <erc@repose.cx>
+
+	* erc-track.el 1.50 (erc-find-parsed-property):
+	simplified a little, so it shouldn't return nil anymore
+
+	* erc.el 1.503: erc-send-post-hook: document narrowing which occurs
+
+2003-03-14  Alex Schroeder  <alex@gnu.org>
+
+	* erc-track.el 1.49 (erc-find-parsed-property): New function.
+	(erc-track-modified-channels): Use it instead of relying on
+	point-min.
+
+2003-03-12  Mario Lang  <mlang@delysid.org>
+
+	* erc.el 1.502:
+	Fix erc-set-topic to accept a channel name as first word
+
+2003-03-11  Jorgen Schaefer  <forcer@users.sourceforge.net>
+
+	* erc-dcc.el 1.66:
+	Small patch (<10 lines, also slightly modified by Jorgen Schäfer) from
+	David Spreen <netzwurm@debian.org> to add hostmask-authentication to
+	DCC auto-accept.
+
+	erc-dcc-auto-mask-list: New variable
+	(erc-dcc-handle-ctcp-send): Check erc-dcc-auto-mask-list
+	(erc-dcc-auto-mask-p): New function
+	erc-dcc-send-request: Docstring now mentions erc-dcc-auto-mask-list
+
+2003-03-10  Francis Litterio  <franl@users.sourceforge.net>
+
+	* erc-ring.el 1.11 (erc-clear-input-ring):
+	New function.  Erases the contents of the input ring for
+	   the current ERC buffer.
+
+2003-03-08  Francis Litterio  <franl@users.sourceforge.net>
+
+	* erc.el 1.501:
+	(erc-display-line-1) and (erc-send-current-line): Now these functions reset erc-insert-this
+	    to t as soon as possible after consuming the value of that variable.  See the comments in
+	    the code for the strange symptom this fixes.
+	(erc-bol): Changed to call point-at-eol instead of line-end-position.  This increases XEmacs
+	    portability, since XEmacs doesn't have line-end-position.  Patch suggested by Scott Evans
+	    on the ERC mailing list.
+
+2003-03-04  Damien Elmes  <erc@repose.cx>
+
+	* erc.el 1.500: banlist*: patch from mrbump to avoid using cl packages
+
+2003-03-04  Francis Litterio  <franl@users.sourceforge.net>
+
+	* erc.el 1.499:
+	Changed erc-noncommands-list from a constant to variable, so that users can
+	    add their own erc-cmd-* functions to the list.  Improved the docstring too.
+
+2003-03-02  Francis Litterio  <franl@users.sourceforge.net>
+
+	* erc.el 1.498 (erc-server-353):
+	Now the output of "/NAMES #channel" appears in the currently
+	    active ERC buffer, even if the user is not a member of #channel.
+
+	* erc.el 1.497 (erc-cmd-DEOP):
+	Fixed a syntax error: invalid read syntax ")" caused by my last change.
+
+2003-03-01  Francis Litterio  <franl@users.sourceforge.net>
+
+	* erc.el 1.496 (erc-cmd-DEOP):
+	Fixed a wrong-type-argument error caused by calling split-string
+	    on a list instead of on a string.  Removed the call to split-string entirely,
+	    because it wasn't needed.
+
+	* erc.el 1.495 (erc-cmd-HELP):
+	Changed to use intern-soft instead of intern.  Now "/HELP floob"
+	    doesn't create a void function symbol erc-cmd-FLOOB.
+
+2003-02-25  Damien Elmes  <erc@repose.cx>
+
+	* erc.el 1.494 (erc-cmd-SERVER):
+	remove erroneous references to line, use server instead
+
+2003-02-23  Francis Litterio  <franl@users.sourceforge.net>
+
+	* erc.el 1.493 (erc-toggle-debug-irc-protocol):
+	Fixed a bug where the global value of
+	    kill-buffer-hook was being modified instead of the buffer-local value.
+
+2003-02-22  Francis Litterio  <franl@users.sourceforge.net>
+
+	* erc.el 1.492 (erc-cmd-KICK):
+	Now supports any number of words in the REASON string.  Examples
+	    of the /KICK command are:
+	      /KICK franl You don't belong here
+	      /KICK franl Bye
+	      /KICK franl
+	      /KICK #channel franl Go away now
+	      /KICK #channel franl Bye
+	      /KICK #channel franl
+
+2003-02-16  Jorgen Schaefer  <forcer@users.sourceforge.net>
+
+	* erc-stamp.el 1.29 (erc-insert-timestamp-right):
+	Make the timestamp rear-nonsticky, so
+	C-e works at the beginning of the next line.
+
+2003-02-16  Andreas Fuchs  <asf@void.at>
+
+	* erc-stamp.el 1.28:
+	* s/choose/choice/ in customize options, as kensanata requested.
+
+2003-02-15  Francis Litterio  <franl@users.sourceforge.net>
+
+	* erc.el 1.491 (erc-toggle-debug-irc-protocol):
+	Now if the *erc-protocol* buffer is killed,
+	    logging is turned off.  Prior to this change, the buffer would come back
+	    into existence (generally unbeknownst to the user) after being killed.
+
+2003-02-11  Damien Elmes  <erc@repose.cx>
+
+	* erc.el 1.490 (erc-send-current-line):
+	we can't inhibit everything here when not connected,
+	    as the user will expect commands like /server still to work. the
+	    erc-cmd-handler should recover from errors instead
+
+2003-02-10  Damien Elmes  <erc@repose.cx>
+
+	* erc.el 1.489:
+	* we now run erc-after-connect on 422 (no motd) messages as well as the motd
+	  messages
+	(erc-login): revert the previous change
+
+	* erc.el 1.488 (erc-login): register that we're connected
+
+2003-02-10  Mario Lang  <mlang@delysid.org>
+
+	* erc-members.el 1.4: * Provide erc-members
+	* Fix excessive )
+	* Comment out broken self-tests
+
+2003-02-07  Damien Elmes  <erc@repose.cx>
+
+	* erc.el 1.487 (erc-connect):
+	notify the user we're trying to connect when using asych
+	    connections
+
+	* erc.el 1.486 (erc-connect): support an asyncronous connection
+	(erc-process-sentinel): ditto
+
+	* erc-track.el 1.48:
+	* advise switch-to-buffer in the case of xemacs, since it doesn't have
+	  window-configuration-change-hook
+
+	* erc.el 1.485 (erc-send-current-line):
+	if not connected, refuse to send either a message or
+	    a command
+
+	* erc.el 1.484: (erc-save-buffer-in-logs):
+	    - check for a sensibile region before saving the buffer. if the
+	      connection process is killed early on, there is not a sensible region
+	      to save
+	    - don't set buffer-file-name on save. we don't need it, and it means we
+	      can now find-file a log while an existing query is open with that
+	      user
+
+	* erc.el 1.483 (erc-process-input-line):
+	when displaying the help for a function, if no
+	    documentation exists, don't fall over
+	(erc-cmd-SAY): new function for quoting lines begining with /
+	(erc-server-NICK):
+	    - fix a bug where the "is now known as" message doesn't appear on newly
+	      created /query buffers
+	    - when a user changes their nick, update the query to point to the new
+	      nick
+
+	* erc.el 1.482 (erc-send-current-command):
+	don't reject multi-line commands. since
+	    multiline-p is used as the no-command arg to erc-process-current-line,
+	    multi-line text is never interpreted as a command. i believe this is the
+	    correct behavior - it allows people to post the output of things like df
+	    (sans header). if you want to change this, please provide a rationale
+	    in the changelog
+
+	* erc.el 1.481 (erc-send-current-line):
+	only match the first line when determining if a
+	    multi-line command is allowed
+
+2003-02-07  Jorgen Schaefer  <forcer@users.sourceforge.net>
+
+	* erc-bbdb.el 1.21 (erc-bbdb-highlight-record):
+	Use alternate strings, not character
+	classes to split the nick-field.
+
+2003-02-06  Francis Litterio  <franl@users.sourceforge.net>
+
+	* erc.el 1.479 (erc-process-sentinel):
+	Now we set erc-connected to nil every time we disconnect
+	    from a server, not just when an unexpected disconnect happens.
+
+	* erc.el 1.478 (erc-connected):
+	Removed redundant defvar of this variable.  Improved the
+	    docstring.
+	(erc-login): Changed to send a correct RFC2812 USER message (see section
+	    3.1.3 of RFC2812 for the documentation of the semantics of each argument
+	    of the USER message.
+
+2003-02-02  Damien Elmes  <erc@repose.cx>
+
+	* erc.el 1.477 (erc-cmd-NOTICE): fix from mrbump
+
+2003-01-31  Francis Litterio  <franl@users.sourceforge.net>
+
+	* erc.el 1.476 (erc-cmd-JOIN):
+	Now we only send one JOIN command to the server when a channel
+	    key is provided.
+
+2003-01-30  Francis Litterio  <franl@users.sourceforge.net>
+
+	* erc.el 1.475 (erc-remove-channel-member):
+	Fixed so that it runs erc-channel-members-changed-hook
+	    with the channel buffer current, as is documented in the docstring for variable
+	    erc-channel-members-changed-hook: "The buffer where the change happened is
+	    current while this hook is called."
+
+2003-01-28  Francis Litterio  <franl@users.sourceforge.net>
+
+	* erc.el 1.474:
+	(erc-ignored-user-p),(erc-cmd-IGNORE),(erc-cmd-UNIGNORE): Now nicks are ignored
+	    on a per-server basis.  Now, erc-ignore-list is only valid in server
+	    buffers!  Do not reference it in channel buffers.
+
+	* erc.el 1.473 (erc-cmd-IGNORE):
+	Now says "Ignore list is empty" if it erc-ignore-list is empty
+	    instead of showing an empty list.
+
+2003-01-25  Alex Schroeder  <alex@gnu.org>
+
+	* erc-nickserv.el 1.11 (services): Defined a module
+
+2003-01-25  Jorgen Schaefer  <forcer@users.sourceforge.net>
+
+	* erc.el 1.472 (erc-process-ctcp-query):
+	Display recipient of CTCP query if it's not
+	our current nick.
+
+	* erc.el 1.471 (erc-cmd-WHOIS):
+	Accept an optional second argument SERVER.
+
+2003-01-25  Alex Schroeder  <alex@gnu.org>
+
+	* erc-stamp.el 1.27 (stamp): erc-add-timestamp must always be added
+	with the APPEND parameter -- not only when adding it on the right.
+
+2003-01-24  Alex Schroeder  <alex@gnu.org>
+
+	* erc-members.el 1.3 (erc-channel-members-changed-hook): Obsolete, use
+	erc-members-changed-hook instead.  When it is set, add its content
+	to erc-members-changed-hook.
+	(erc-update-channel-member): Obsolete, use erc-update-member
+	instead.  Defalias to that effect.
+	(erc-remove-channel-member): New and already obsolete.  Use
+	erc-remove-nick-from-channel instead.
+	(erc-update-channel-info-buffer): Obsolete, use ignore instead.
+	Yes, these have to go.
+	(erc-channel-member-to-user-spec): Obsolete, use erc-format-user
+	instead.
+	(erc-format-user): New.
+	(erc-ignored-reply-p): New, use it.
+
+	* erc-members.el 1.2:
+	Further along the way.  Any function from erc.el that uses
+	channel-members should end up in this file, rewritten to use
+	erc-members.
+
+	(erc-person): Call erc-downcase before getting
+	something from the hash.
+	(erc-nick-in-channel): Checking wether erc-process must be used is
+	unnecessary -- this will be done in erc-person.
+	(erc-nick-channels): New.
+	(erc-add-nick-to-channel, erc-update-member): Call erc-downcase
+	before putting something into the hash.
+	(erc-buffer-list-with-nick): New.
+	(erc-format-nick, erc-format-@nick): New, backwards incompatible.
+	Must check for other places that call these!
+	(erc-server-PRIVMSG-or-NOTICE): Use the new version.
+
+	* erc-compat.el 1.10 (view-mode-enter): defalias to view-mode, if
+	view-mode-enter is not fboundp and view-mode is -- as is the case
+	in XEmacs.  We need view-mode-enter in erc-match.el.
+
+2003-01-23  Francis Litterio  <franl@users.sourceforge.net>
+
+	* erc.el 1.470 (erc-default-server-handler):
+	Minor performance improvement: allow the lambda
+	    expression to be byte-compiled.
+
+2003-01-23  Damien Elmes  <erc@repose.cx>
+
+	* erc.el 1.469 (erc-cmd-BANLIST):
+	in the absence of a fill-column, use the screen width
+
+2003-01-22  Damien Elmes  <erc@repose.cx>
+
+	* erc.el 1.468:
+	patch from MrBump to delay fetching the banlist until /bl is run, so we don't
+	fetch it when joining a channel anymore
+
+	* erc-ring.el 1.10:
+	* instead of adjusting hooks when loaded, provide (erc-ring-mode). you'll
+	  need to run (erc-ring-mode 1) now to get the ring
+	* (erc-previous-command), (erc-next-command):
+	    - check if the ring exists and create it if necessary
+	    - don't do anything if the ring is empty
+
+	* erc-pcomplete.el 1.17:
+	Put "how to use" documentation in the comments up the top
+
+2003-01-21  Alex Schroeder  <alex@gnu.org>
+
+	* erc-autojoin.el 1.4 (erc-autojoin-version): New.
+
+	* erc-autojoin.el 1.3 (erc-autojoin-add): Added body.
+	(erc-autojoin-remove): Added body.
+	(erc-autojoin): Provide it.
+
+2003-01-21  Damien Elmes  <erc@repose.cx>
+
+	* erc.el 1.467: erc-cmd-*: removed a bunch of references to force
+
+2003-01-21  Alex Schroeder  <alex@gnu.org>
+
+	* erc-autojoin.el 1.2 (erc-autojoin-channels-alist): More doc.
+
+2003-01-20  Alex Schroeder  <alex@gnu.org>
+
+	* erc-autojoin.el 1.1:
+	new, based on resolve's mail, and the stuff on the wiki
+
+	* erc-members.el 1.1: new
+
+2003-01-19  Mario Lang  <mlang@delysid.org>
+
+	* debian/README.Debian 1.6, debian/changelog 1.20, debian/scripts/install 1.11, 
+	  debian/scripts/startup.erc 1.4, Makefile 1.13:
+	Prepare for 20030119 debian package
+
+	* erc-dcc.el 1.65: <rant>
+	* (erc-decimal-to-ip): Since XEmacs decides that return a completely
+	and utterly wrong number from string-to-number if it is larger than
+	the integer boundary, instead of sanely converting the thing to
+	a float, we now (concat dec ".0").
+	</rant>
+
+	* erc.el 1.466:
+	* (erc-log-irc-protocol): Use erc-propertize, not propertize
+
+2003-01-19  Alex Schroeder  <alex@gnu.org>
+
+	* erc-button.el 1.45 (erc-button-add-buttons): Added regexp-quote for
+	the list case, too.
+
+2003-01-19  Damien Elmes  <erc@repose.cx>
+
+	* erc-dcc.el 1.64 (erc-dcc-member): fix for case where a prop is nil
+
+	* erc-dcc.el 1.63 (erc-dcc-member):
+	fix for xemacs's version of plist-member
+
+2003-01-19  Mario Lang  <mlang@delysid.org>
+
+	* erc-notify.el 1.17: Delete empty strings from the ison-list
+
+	* erc-track.el 1.47:
+	* (erc-track-switch-buffer): Call erc-modified-channels-update here.
+
+	* erc-track.el 1.46: * toplevel: require 'erc-match
+
+	* erc-track.el 1.45: * (erc-track-mode): Make autoload interactive
+
+	* erc-button.el 1.44: * (button): Make the autoload interactive
+
+	* erc.el 1.465:
+	* (erc-mode): Comment out the case-table stuff, breaks xemacs
+	* (erc-downcase): Revert.
+
+	* erc-dcc.el 1.62:
+	* (erc-dcc-handle-ctcp-send): Use erc-decimal-to-ip on the ip we get...
+
+	* erc-speak.el 1.25:
+	Eliminate reference to erc-nick-regexp, which no longer exists
+
+2003-01-19  Alex Schroeder  <alex@gnu.org>
+
+	* erc-stamp.el 1.26 (erc-timestamp-right-column): New, default nil.
+	(erc-insert-timestamp-right): Use it, if non-nil.  Verbose
+	doc string.
+
+2003-01-18  Jorgen Schaefer  <forcer@users.sourceforge.net>
+
+	* erc.el 1.464 (erc-downcase): Use the old behavior in non-CVS Emacs.
+
+	* erc.el 1.463 (erc-cmd-QUIT): Remove &rest. The correct fix follows.
+	(erc-cmd-GQUIT): Pass "" to erc-cmd-QUIT.
+	(erc-mode): Use the case-table only in CVS Emacs. See comment.
+
+	* erc.el 1.462 (erc-cmd-QUIT): make reason optional.
+
+	* erc.el 1.461 (erc-cmd-GQUIT): Fixed typo.
+
+2003-01-17  Mario Lang  <mlang@delysid.org>
+
+	* erc.el 1.460:
+	* (erc-current-logfile): call expand-file-name, so that downcase doesn't mess up ~
+
+	* erc.el 1.459: * (erc-mode): Define a proper case-table.
+	* (erc-downcase): just call downcase for now, lets see if the case-table is portable, if yes, we'll remove all erc-downcase references anyway...
+
+	* erc-button.el 1.43: * (erc-button-add-buttons): regex-quote the nick
+
+2003-01-17  Alex Schroeder  <alex@gnu.org>
+
+	* erc-button.el 1.42 (button): erc-channel-members-changed-hook no
+	longer has erc-recompute-nick-regexp.
+	(erc-button-alist): Use channel-members instead of
+	erc-nick-regexp.
+	(erc-button-add-buttons): Split some code into
+	erc-button-add-buttons-1, and now handle strings, lists, and
+	alists.  Regular expressions in lists and alists are enclosed in
+	< and >.
+	(erc-button-add-buttons-1): New.
+	(erc-nick-regexp): Deleted.
+	(erc-recompute-nick-regexp): Deleted.
+
+	* erc-button.el 1.41: Remove require cl again.
+	(erc-mode-map): No longer bind widget-backward and widget-forward.
+	(erc-button-alist): Explain why byte-compiling makes no sense, and
+	remove all calls to byte-compile.
+	(erc-button-keymap): Define it the standard way, without exposing
+	the list nature of the keymap.
+	(erc-button-marker-list): Deleted.
+	(erc-button-add-buttons): Simplify.  In particular, create the
+	button using the real callback, instead of using the intermediate
+	erc-button-push, and only store the data as described for
+	erc-button-alist.
+	(erc-button-remove-old-buttons): Simplify.  No more list munging.
+	Instead, just remove all the properties that we add in
+	erc-button-add-button.
+	(erc-widget-press-button): Deleted.
+	(erc-button-click-button): New, for mouse clicks.  Moves point to
+	where the mouse is, and calls erc-button-push.
+	(erc-button-push): Instead of matching again, just use the
+	erc-callback and erc-data properties at point to do the right
+	thing.
+	(erc-button-entry): Deleted.
+	(erc-button-next): Use error instead of the beep plus message
+	combo.
+
+2003-01-17  Jorgen Schaefer  <forcer@users.sourceforge.net>
+
+	* erc-autoaway.el 1.11 (erc-autoaway-set-back):
+	Don't pass a force argument to erc-cmd-GAWAY.
+
+	* erc.el 1.458 (erc-cmd-AWAY): Removed usage of the force variable.
+
+2003-01-17  Alex Schroeder  <alex@gnu.org>
+
+	* erc-button.el 1.40 (button):
+	erc-recompute-nick-regexp is no longer added to
+	erc-channel-members-changed-hook unconditionally, but only if
+	erc-button-mode is enabled, and if it is disabled, it is removed
+	again.
+	(erc): Require cl for delete-if.
+	(erc-button-remove-old-buttons): Rewrote using delete-if to
+	prevent exceesive consing.  Having the marker list is still ugly,
+	so another solution needs to be found.
+
+2003-01-17  Jorgen Schaefer  <forcer@users.sourceforge.net>
+
+	* erc.el 1.457 (erc-banlist-store):
+	Don't assume there's always a setter in the banlist reply.
+
+2003-01-17  Alex Schroeder  <alex@gnu.org>
+
+	* erc-button.el 1.39 (erc-button-url-regexp): Changed regexp according
+	to a suggestion by Max Froumentin <mf@w3.org>.
+
+2003-01-17  Mario Lang  <mlang@delysid.org>
+
+	* erc.el 1.456:
+	fix erc-remove-channel-member again to not error out on nil as first arg...
+
+	* erc.el 1.455: * (erc-occur): New function
+
+2003-01-17  Damien Elmes  <erc@repose.cx>
+
+	* erc.el 1.454: erc-banlist-*: return nil so further hooks are called
+
+	* erc.el 1.453 (erc-server-368):
+	supress "end of ban list" messages - use /listbans now
+
+	* erc.el 1.452 (erc-send-current-line):
+	removed the check for leading whitespace again - the
+	    only time we want to prohibit multi-line commands is if / is the first
+	    thing on the line
+	(erc-get-arglist): new defun for reading a function's arglist which should
+	    work with older copies of emacs. we use help-function-arglist if it's
+	    available, though, since that has support for reading subrs, etc
+
+	* erc.el 1.451 (erc-cmd-JOIN): fixed (again)
+
+	* erc.el 1.450: * fixed call to erc-cmd-NICK when connecting
+	* support for listing bans and mass unbanning, again thanks to MrBump
+
+	* erc.el 1.449 (erc-set-topic):
+	patch from MrBump (Mark Triggs, mst@dishvelled.net) to strip
+	    control chars and topic attribution in C-c C-t
+
+2003-01-16  Mario Lang  <mlang@delysid.org>
+
+	* erc.el 1.448:
+	* (erc-remove-channel-member): Do not use delq, modify the list using setcdr like delq does.
+	In theory, this should be way faster since the list doesnt get traverse two times.
+	Measurement didn't show any real difference though :(, this system is flawed for channels with >300 users it seems...
+	Also moved some defcustoms up.
+
+2003-01-16  Brian P Templeton  <bpt@tunes.org>
+
+	* erc.el 1.447: moved misplaced paren
+
+2003-01-16  Damien Elmes  <erc@repose.cx>
+
+	* erc.el 1.446 (erc-cmd-UNIGNORE):
+	reference argument directly - no string matching
+
+	* erc.el 1.445 (erc-extract-command-from-line):
+	hmm, thinko in the canonicalisation. should
+	    be fixed
+
+2003-01-16  Francis Litterio  <franl@users.sourceforge.net>
+
+	* erc.el 1.444 (erc-send-current-line):
+	Changed the regexp used to match /COMMANDs so that leading
+	    whitespace is taken into account.
+
+2003-01-16  Mario Lang  <mlang@delysid.org>
+
+	* erc-dcc.el 1.61: * (erc-dcc-do-SEND-command): Fix it
+
+	* erc-ezbounce.el 1.4, erc-lang.el 1.2: Arglist changes...
+
+	* erc.el 1.443: Various docstring fixes and additions.
+
+	* erc-notify.el 1.16:
+	* (erc-cmd-NOTIFY): Change the function arglist to (&rest args)
+
+	* erc-netsplit.el 1.8: * (erc-cmd-WHOLEFT): Has no args...
+
+2003-01-16  Damien Elmes  <erc@repose.cx>
+
+	* erc-fill.el 1.22:
+	erc-fill-column: default to 78, so things like docstrings don't get wrapped
+	    in an ugly manner
+
+2003-01-16  Mario Lang  <mlang@delysid.org>
+
+	* erc.el 1.442:
+	* (erc-cmd-default): Take a substring, now /mode works again.
+	* (erc-cmd-AWAY): Put do-not-parse-args t
+	* (erc-cmd-GAWAY): Ditto, and fix it.
+	* (erc-cmd-CTCP): Switch to argument system.
+	* (erc-cmd-KICK): Do the same.
+
+2003-01-15  Mario Lang  <mlang@delysid.org>
+
+	* erc-dcc.el 1.60:
+	* (erc-cmd-DCC): Fixed for the new scheme, simplified.
+	* (erc-dcc-do-CHAT-command): Ditto.
+	* (erc-dcc-do-CLOSE-command): Ditto.
+	* (erc-dcc-do-LIST-command): Ditto.
+
+2003-01-15  Damien Elmes  <erc@repose.cx>
+
+	* erc.el 1.441:
+	erc-error-face: setting a background doesn't work so well with multi-line
+	    messages, so we don't. fg colour is negotiable ;-)
+	(erc-cmd-QUERY): fixed, new doco, supress (erc-delete-query) until we fix it
+	(erc-send-current-line): allow multi-line messages provided they don't start
+	    with a slash - there's no need to prohibit them if the slash isn't the
+	    first character
+
+	* erc.el 1.440: * bad-syntax now reports like incorrect-args
+	* bunch of extra cmds fixed, nick, sv etc.
+
+	* erc.el 1.439 (erc-cmd-HELP): fixed
+	(erc-extract-command-from-line): when deterimining canon-defun, make sure we
+	    have a valid symbol
+	(erc-cmd-KICK): fixed
+
+	* erc.el 1.438:
+	* removed duplicate do-no-parse-args properties for the defaliased defuns
+	(erc-process-input-line): show function signature when incorrect args
+	(erc-extract-command-from-line): canonicalise defaliases before extracting
+	    plist
+	(erc-cmd-CLEAR): fixed
+	(erc-cmd-UNIGNORE): fixed again
+
+	* erc.el 1.437 (erc-cmd-SET): fixed
+	(erc-cmd-UNIGNORE): fixed
+	(erc-process-input-line): report when incorrect arguments are provided to a
+	    command, and show the command's docstring
+
+	* erc.el 1.436 (erc-cmd-APPENDTOPIC): fixed
+	(erc-process-input-line): more informative error message than 'bad syntax'
+
+2003-01-15  Mario Lang  <mlang@delysid.org>
+
+	* erc.el 1.435: * (erc-cmd-IGNORE): fixed
+
+	* erc.el 1.434: * (erc-cmd-NAMES): fixed
+
+	* erc.el 1.433:
+	* (erc-cmd-CLEARTOPIC): Simplify, fix doc, make interactive
+
+2003-01-15  Damien Elmes  <erc@repose.cx>
+
+	* erc.el 1.432 (erc-cmd-JOIN):
+	correct invite behavior, and document it.
+
+2003-01-15  Mario Lang  <mlang@delysid.org>
+
+	* erc.el 1.431: * (erc-cmd-PART): Put 'do-not-parse-args t
+
+2003-01-15  Damien Elmes  <erc@repose.cx>
+
+	* erc.el 1.430 (erc-cmd-JOIN): new cmd argument syntax
+	(erc-process-input-line): check if (erc-extract-command-from-line) returned a
+	    list, and apply if that's the case
+
+	* erc.el 1.429:
+	erc-cmd-*: remove optional force and references to `force' in the code
+	(erc-cmd-AMSG): call erc-trim-string, not trim-string
+
+2003-01-15  Mario Lang  <mlang@delysid.org>
+
+	* erc.el 1.428:
+	* (erc-cmd-CLEARTOPIC): LINE is now ARGS and already parsed.
+	Set erc-cmd-TOPIC to 'do-not-parse-args for now.
+	(comment: I think we should have 'first, so that only first word is parsed...
+	 Or we could autodetect erc-channel-p in the parser before that somehow...)
+
+	* erc.el 1.427: * (erc-cmd-OP): LINE is PEOPLE now, and already parsed.
+
+	* erc-notify.el 1.15:
+	* (erc-cmd-NOTIFY): Arg LINE is now ARGS, and already parsed.
+
+2003-01-15  Jorgen Schaefer  <forcer@users.sourceforge.net>
+
+	* erc-stamp.el 1.25 (erc-insert-timestamp-right):
+	Prefer erc-fill-column to window-width,
+	because on wide screens the timestamp could wander off too far to the
+	right.
+
+2003-01-15  Mario Lang  <mlang@delysid.org>
+
+	* erc.el 1.426: This is the "everything is suddenly broken!" release
+	You know, this is CVS, you can still go back, and wait until the transition
+	is finished, but here is patch one, which basicly breaks every command
+	which is typed on the prompt.
+	Hit me, we can still revert, but something needs to be done about this.
+	* (erc-extract-command-from-line): intern-soft the function here.
+	If the function symbol has a property 'do-not-parse-args, operate as before,
+	otherwise, split the arguments prior to calling the command handler.
+	* (erc-process-input-line): Updated to accomodate the change above.
+	* (erc-send-distinguish-noncommands): Ditto.
+	* (erc-cmd-NAMES): Ditto.
+	* (erc-cmd-ME): Put 'do-not-parse-args property.
+
+	* erc-dcc.el 1.59:nick:	* erc-dcc.el 1.59: * erc-dcc-list: Renamed 
+	* (erc-dcc-member). Treat :nick as either a nick!user@host or nick,
+	do appropriate comparisons, simplified.
+	* (erc-dcc-list-add): New functions
+	various callers of (cons (list ...) erc-dcc-list) updated.
+	Other stuff I'm to bored to document now
+
+2003-01-15  Jorgen Schaefer  <forcer@users.sourceforge.net>
+
+	* erc-stamp.el 1.24 (erc-insert-timestamp-right):
+	Removed redundant code that overrid the
+	window-width. Now substracts (length string) from every found
+	indentation positions.
+
+2003-01-14  Mario Lang  <mlang@delysid.org>
+
+	* erc.el 1.425:
+	* (erc-cmd-AMSG): Remove useless call to erc-display-message.
+
+	* erc-dcc.el 1.58:
+	* erc-dcc-chat/send-request: New variables, control how to treat
+	incoming dcc chat or send requests. Can be set to 'ask, which behaves
+	like it did before, 'auto, which accepts automatically, and
+	'ignore, which ignores those type of requests completely.
+	* (erc-cmd-CREQ): New user-level command.
+	* (erc-cmd-SREQ): Ditto.
+
+	* erc.el 1.424: * (erc-cmd-AMSG). New command.
+
+	* erc-xdcc.el 1.4: * (erc-xdcc): delete empty strings from ARGS
+
+	* erc-dcc.el 1.57: * erc-dcc-ipv4-regexp: New constant
+	* (erc-ip-to-decimal): Use it.
+	* erc-dcc-host:valid-regexp erc-dcc-ipv4-regexp:	* erc-dcc-host: :type
+	* (pcomplete/erc-mode/DCC): Add completion for GET and CLOSE.
+	* Some docstring/comment fixes.
+
+	* erc-stamp.el 1.23:
+	* (erc-insert-timestamp-right): Subtract (length string) from
+	POS in any case, otherwise, linewrap occurs.
+
+	* erc-dcc.el 1.56:
+	* Fixed the unibyte-multibyte problem (now a dcc get buffer is (set-buffer-multibyte nil), 
+	  and saves correctly (tried with 21.3.50). Thanks to Eli for suggesting it!
+	* Added :start-time plist property/value to GET handling so that we can calculate elapsed-time.
+	* Some (unwind-protect (progn (set-buffer ...) ...)) constructs replaced with (with-current-buffer ...)
+
+2003-01-13  Mario Lang  <mlang@delysid.org>
+
+	* erc-xdcc.el 1.3:
+	* erc-xdcc-help-text: New variable which makes replies to the originator
+	much more flexible.
+	* erc-xdcc-help-format: Removed.
+	* (erc-xdcc-help): Handle the new variable.
+	* (erc-xdcc): Simplified
+
+	* erc-xdcc.el 1.2: * erc-xdcc-handler-alist: New variable.
+	* (erc-xdcc): Move code for list and send sub-commands into
+	* (erc-xdcc-help): New function.
+	* (erc-xdcc-list): New function.
+	* (erc-xdcc-send): New function.
+
+2003-01-12  Jorgen Schaefer  <forcer@users.sourceforge.net>
+
+	* erc.el 1.423 (erc-server-JOIN):
+	Oops, send MODE command only when *we* joined a channel.
+
+	* erc.el 1.422:
+	Fixing ERCs behavior wrt IRCnet's !channels have a different name for
+	JOIN than in reality (e.g. you can join !forcertest or !!forcertest
+	and really get to !ABCDEforcertest)
+
+	(erc-cmd-JOIN): Removed erc-send-command MODE.
+	(erc-server-JOIN): Ask for MODE now.
+
+2003-01-12  Damien Elmes  <erc@repose.cx>
+
+	* erc-dcc.el 1.55:
+	(erc-dcc-get-filter), (erc-dcc-get-file): store size as a string, not an
+	    integer. check size > 0 for the case where a size wasn't provided, since
+	    string-to-int will return 0 on an empty string
+
+2003-01-12  Mario Lang  <mlang@delysid.org>
+
+	* erc-dcc.el 1.54: * Use RAWFILE arg with find-file-noselect
+	* Fix alist/plist conversion left-over
+	* Add verbose-info about sending blocks.
+
+2003-01-11  Mario Lang  <mlang@delysid.org>
+
+	* erc-dcc.el 1.53: * (pcomplete-erc-mode/DCC): Fixes
+
+	* erc-xdcc.el 1.1: Initial version.
+
+	* erc-pcomplete.el 1.16:
+	* (erc-pcomplete): Fix so that cycle-completion works again.
+	* (pcomplete-parse-erc-arguments): If there is a space after the last word
+	before point, we need to return a "" arg, and it's position.
+
+	* erc-dcc.el 1.52: Fix to pcomplete/erc-mode/DCC
+
+	* erc-dcc.el 1.51: * (pcomplete/erc-mode/DCC): New function
+
+	* erc-dcc.el 1.50: *** empty log message ***
+
+	* erc-dcc.el 1.49: Move code around, just basic changes
+
+2003-01-11  Jorgen Schaefer  <forcer@users.sourceforge.net>
+
+	* erc-stamp.el 1.22 (erc-insert-timestamp-right):
+	Check wether erc-fill-column is
+	available before using it. Else default to fill-column or if
+	everything else fails, the window width of the current window. For the
+	fill-columns, use them directly as the starting position for the
+	timestamp.
+
+2003-01-11  Andreas Fuchs  <asf@void.at>
+
+	* erc-stamp.el 1.21:
+	erc-insert-timestamp-right: use correct window's window-width. If
+	                  buffer is not in a window, use erc-fill-column.
+
+2003-01-11  Mario Lang  <mlang@delysid.org>
+
+	* erc-dcc.el 1.48:	* erc-dcc.el 1.48: * (erc-dcc-do-LIST-command): Fix 
+
+	* erc-dcc.el 1.47:
+	* buffer-local variables erc-dcc-sent-marker and erc-dcc-send-confirmed marker removed
+	  Keep This info in erc-dcc-member :sent and :confirmed plist values
+	* :	* :buffer plist for :type 'SEND removed, since we can get this with (marker-buffer 
+	* erc-dcc-send-connect-hook: New hook, defaults to erc-dcc-send-block and erc-dcc-send-conntected, which now prints a msg...
+
+	* erc-dcc.el 1.46:
+	* (erc-dcc-chat-accept): Renamed from erc-dcc-chat. Callers updated.
+	* (erc-dcc-chat): Renamed from erc-dcc-chat-request.
+	Callers updated, and interactive form added.
+	* (erc-dcc-server-accept): No longer do any type-specific stuff.
+	* (erc-dcc-chat-sentinel): Call erc-dcc-chat-setup if event is "open from "
+	from here, otherwise call erc-dcc-chat-close.
+
+	* (
+
+	* erc-dcc.el 1.45: *** empty log message ***
+
+	* erc-dcc.el 1.43: Moved some functions around.
+	Doc string fixes.
+	"/dcc send nick filename" works now
+
+2003-01-11  Alex Schroeder  <alex@gnu.org>
+
+	* erc.el 1.421 (erc-send-command): Fixed flood protect message.
+
+	* erc-button.el 1.38 (erc-button-syntax-table): Make `-' a legal nick
+	constituent.
+
+2003-01-10  Mario Lang  <mlang@delysid.org>
+
+	* erc-dcc.el 1.42: Some more steps toward dcc send.
+
+2003-01-10  Francis Litterio  <franl@users.sourceforge.net>
+
+	* erc-notify.el 1.14 (erc-notify-timer):
+	Changed to make it IRC-case-insensitive when comparing nicks.
+	(erc-notify-JOIN): Changed to make it IRC-case-insensitive when comparing nicks.
+	(erc-notify-NICK): Changed to make it IRC-case-insensitive when comparing nicks.
+	(erc-notify-QUIT): Changed to make it IRC-case-insensitive when comparing nicks.
+	(erc-cmd-NOTIFY): Now "/notify -l" lists the nicks on your notify list.  Now
+	    when you remove a nick from your notify list, you no longer recieve a spurious
+	    signoff notification for that nick.  Changed to make it IRC-case-insensitive when
+	    comparing nicks.
+
+	* erc.el 1.420 (erc-ison-p):
+	Fixed so it calls erc-member-ignore-case instead of member.
+
+	* erc.el 1.419 (erc-member-ignore-case):
+	New function.  Just like member-ignore-case, but obeys
+	    the IRC protocol case matching rules.
+
+2003-01-10  Damien Elmes  <erc@repose.cx>
+
+	* erc-dcc.el 1.41:
+	(erc-dcc-do-GET-command), (erc-dcc-get-file): use the plist syntax, this
+	    fixes dcc get again
+
+2003-01-10  Jorgen Schaefer  <forcer@users.sourceforge.net>
+
+	* erc.el 1.418: erc-complete-functions: New variable.
+	erc-mode-map: Bind \t to 'erc-complete-word
+	erc-complete-word: New function.
+
+	* erc-pcomplete.el 1.15 (erc-pcomplete-mode):
+	Use new erc-complete-functions
+	(erc-pcomplete): Check that we're in the input line, else return nil.
+
+	* erc-button.el 1.37 (erc-button-mode): Use new erc-complete-functions
+	erc-button-old-tab-command: Removed.
+	(erc-button-next-or-old): Removed
+	(erc-button-next): check that we're not in the input line, else just return nil.
+
+2003-01-10  Mario Lang  <mlang@delysid.org>
+
+	* erc-dcc.el 1.40: cleanup
+
+	* erc-dcc.el 1.39:
+	* (erc-dcc-chat-request): No longer use erc-send-ctcp-message.
+
+	* erc-dcc.el 1.38:
+	* (erc-dcc-no-such-nick): Also call delete-process if we have a peer already
+
+	* erc-dcc.el 1.37:
+	* (erc-dcc-no-such-nick): New function, server event handler for event 401.
+	If we send a CTCP message requesting something dcc related, we set up an
+	entry in erc-dcc-list before sending the request (for the server proc object
+	for listening conns for example).  But if that nick does not exist
+	on that server, we now nicely cleanup erc-dcc-list again.
+
+2003-01-09  Mario Lang  <mlang@delysid.org>
+
+	* erc-dcc.el 1.36: Moved code around a bit, and doc fixes
+
+	* erc-dcc.el 1.35: *** empty log message ***
+
+	* erc-dcc.el 1.34: Rename erc-dcc-plist to erc-dcc-list
+
+2003-01-09  Damien Elmes  <erc@repose.cx>
+
+	* erc-dcc.el 1.33 (erc-dcc-server (erc-dcc-chat-setup):
+	use erc's (erc-setup-buffer) to determine how to
+	    display new DCC windows
+	(erc-dcc-chat-buffer-killed): buffer-local hook for DCC buffers to close the
+	    process
+	(erc-dcc-chat-close): code common to a killed buffer or a disconnection from
+	    the other side
+	(erc-dcc-chat-sentinel): use (erc-dcc-chat-close)
+	(erc-dcc-server-accept): use (erc-log) instead of (message)
+
+	* erc.el 1.417:
+	(erc), (erc-setup-buffer): factor out window generation code so DCC can use
+	    it too
+
+	* erc-dcc.el 1.32:
+	(erc-dcc-do-CLOSE-command), (erc-dcc-do-LIST-command): work with erc-dcc-plist
+
+	* erc-dcc.el 1.31:
+	erc-dcc-alist: became erc-dcc-plist, so we can more easily grab particular
+	    properties
+	dcc catalog: unify use of DCC: and [dcc] (either's fine, but let's be
+	    consistent)
+	(erc-dcc-member): takes an arbitrary list of constraints now
+	(erc-dcc-proc-member): removed, as (erc-dcc-member) can be used for this
+	(erc-dcc-do-CHAT-command): use the catalog to show the user what's going on
+	(erc-dcc-chat-server): removed
+	(erc-dcc-server): takes name sentinel and filter arguments, can be used for
+	    both send and chat now
+
+	.. this release means all send/get support is broken until we fix up the
+	things that still expect to be using an alist. this include /dcc list, /dcc
+	close
+
+2003-01-09  Francis Litterio  <franl@users.sourceforge.net>
+
+	* erc-ring.el 1.9 (erc-previous-command):
+	If you have a partially typed input line and press M-p,
+	    you lose what you typed.  Now we save it so you can come back to it.
+
+2003-01-09  Jorgen Schaefer  <forcer@users.sourceforge.net>
+
+	* erc-ring.el 1.8 (erc-add-to-input-ring): s/nullp/null/
+
+2003-01-09  Damien Elmes  <erc@repose.cx>
+
+	* erc-ring.el 1.7 (erc-add-to-input-ring):
+	set up the ring if it's not already setup
+
+	* erc-dcc.el 1.30 (erc-dcc-member): case insensitive match of nicknames
+	(erc-dcc-do-CHAT-command): echo what we're doing (at least for now)
+
+2003-01-09  Mario Lang  <mlang@delysid.org>
+
+	* erc-dcc.el 1.29: (temporarily) fix erc-process setting...
+
+	* erc-dcc.el 1.28: * (erc-dcc-chat-send-line): Removed
+
+	* erc.el 1.416:
+	Check if target is stringp (we can now also have 'dcc as value...)
+
+	* erc-dcc.el 1.27 (erc-dcc-chat-send-input-line):
+	New function, used for
+	erc-send-input-line-function.
+	Use erc-send-current-line now.
+
+	* erc-dcc.el 1.26: evt to elt...
+
+	* erc-dcc.el 1.25: Remove () from a var (how silly!)
+
+	* erc-dcc.el 1.24: * (erc-dcc-get-host): Use format-network-address.
+	* (erc-dcc-host): Change semantic.  If erc-dcc-host is set, use it.
+	Otherwise, try to figure out the host by calling erc-dcc-get-host.
+	* (erc-dcc-server-port): New variable.
+	* erc-dcc-chat-log: Renamed to erc-dcc-server-accept
+
+	* erc-dcc.el 1.23 (erc-dcc-do-CHAT-command):
+	Change arg of call to erc-dcc-chat-request from elt to nick
+
+2003-01-09  Francis Litterio  <franl@users.sourceforge.net>
+
+	* erc.el 1.415 (erc-send-current-line):
+	Now rejects multi-line commands (i.e., lines that
+	    start with "/" and contain newlines).
+
+2003-01-09  Jorgen Schaefer  <forcer@users.sourceforge.net>
+
+	* erc-button.el 1.36:
+	Functionality to use TAB to jump to the next button:
+
+	(erc-button-next-or-old): New function.
+	(erc-button-next): New function.
+	erc-button-keymap: added erc-button-next
+	erc-button-old-tab-command: New variable.
+	define-erc-module button: Add and remove 'erc-button-next-or-old as
+	appropriate.
+
+2003-01-09  Francis Litterio  <franl@users.sourceforge.net>
+
+	* erc.el 1.414:
+	New variable: erc-auto-reconnect (defaults to t).  If non-nil, ERC will
+	    automatically reconnect to a server after an unexpected disconnection.
+	(erc-process-sentinel): Changed to refer to variable erc-auto-reconnect.
+
+2003-01-08  Mario Lang  <mlang@delysid.org>
+
+	* erc.el 1.413:
+	* erc-send-input-line-function: New variable, used for dispatch...
+
+2003-01-08  Damien Elmes  <erc@repose.cx>
+
+	* erc-dcc.el 1.22 (erc-dcc-chat-sentinel):
+	check event type before killing process
+	(erc-dcc-chat-log): new, handles the setup of dcc chats for incoming
+	    connections
+	(erc-dcc-chat): use (erc-dcc-chat-setup)
+	(erc-dcc-chat-setup): code common to incoming and outgoing DCC chats
+	(erc-dcc-chat-request): request a DCC chat with another user
+	(erc-dcc-proc-member): locate a member in erc-dcc-alist by process
+
+	The very first ERC to ERC DCC chat was held between delysid and resolve today!
+
+2003-01-08  Mario Lang  <mlang@delysid.org>
+
+	* erc-track.el 1.44 (erc-all-buffer-names):
+	Check for erc-dcc-chat-mode too
+
+2003-01-08  Francis Litterio  <franl@users.sourceforge.net>
+
+	* erc-ring.el 1.6, erc.el 1.412 (erc-kill-input):
+	Resets erc-input-ring-index to nil, so that invoking this
+	    command conceptually puts you after your most recent input in the input
+	    history.
+	(erc-previous-command and erc-next-command): Changed so that history movement
+	    is more intuitive.  Also preserves the blank input line that marks the
+	    place after the newest command in the history ring (i.e., you'll see a
+	    blank command once every trip around the ring in either direction).
+
+2003-01-08  Mario Lang  <mlang@delysid.org>
+
+	* erc-dcc.el 1.21 (erc-dcc-chat): Add docstring
+	Add self-test.
+	Fix error if /dcc chat nick doesnt find the nick
+
+2003-01-08  Francis Litterio  <franl@users.sourceforge.net>
+
+	* Makefile 1.12:
+	Changed so that "make" works correctly under Cygwin.  Before this change, the
+	pathname passed to Emacs on the command line under Cygwin had the form
+	"/cygwin/c/...", which prevented emacs from finding the file.  Now the pathname
+	has the form "c:/...".  This works for any drive letter.
+
+2003-01-08  Mario Lang  <mlang@delysid.org>
+
+	* erc-button.el 1.35: reindent some code, and add TODO to comments
+
+	* erc-dcc.el 1.20: *** empty log message ***
+
+	* erc-dcc.el 1.19: Make dcc-chat-ended a notice
+	Remove now bogus comment
+
+2003-01-08  Damien Elmes  <erc@repose.cx>
+
+	* erc-dcc.el 1.18 (erc-pack-int): from erc-packed-int
+	(erc-unpack-int): new
+
+	* erc-dcc.el 1.17 (erc-unpack-str): added
+
+2003-01-08  Mario Lang  <mlang@delysid.org>
+
+	* erc.el 1.411 (erc-server-482):
+	New handler, handles KICK reply if you're not channel-op
+
+	* erc-dcc.el 1.16: Document SEND in erc-dcc-alist.
+	Move sproc, parent-proc and file into erc-dcc-alist
+
+	* erc-dcc.el 1.15: stubs
+
+	* erc-dcc.el 1.14 (erc-dcc-get-host):
+	Change :iface to :local since Kim committed it now to CVS emacs
+
+	* erc-dcc.el 1.13 (erc-dcc-get-host):
+	New function, requires the not-yet-in-CVS-emacs local-address.patch to process.c.
+	Some other minor additions
+
+2003-01-08  Francis Litterio  <franl@users.sourceforge.net>
+
+	* erc.el 1.410 (erc-cmd-IGNORE):
+	Now returns t to prevent "Bad syntax" error.
+	(erc-cmd-UNIGNORE): Now returns t to prevent "Bad syntax" error.
+	(erc-server-PRIVMSG-or-NOTICE): Capitalized first word in message to user.
+
+	* erc.el 1.409 (erc-scroll-to-bottom):
+	Temporarilly bind resize-mini-windows to nil so that
+	    users who have it set to a non-nil value will not suffer from premature
+	    minibuffer shrinkage due to the below recenter call.  I have no idea why
+	    this works, but it solves the problem, and has no negative side effects.
+
+2003-01-07  Jorgen Schaefer  <forcer@users.sourceforge.net>
+
+	* erc-dcc.el 1.12:
+	erc-dcc-ctcp-query-chat-regexp: The IP is not really an IP, but a
+	number (no . allowed there).
+	(erc-dcc-send-ctcp-string): use let* here to avoid cluttering up the
+	match data.
+	Also, use erc-decimal-to-ip to get the IP.
+	(erc-ip-to-decimal): Removed some pasted ERC timestamps
+	(erc-decimal-to-ip): New function.
+	erc-dcc-chat-mode-map: Return map in the initialization.
+
+2003-01-07  Francis Litterio  <franl@users.sourceforge.net>
+
+	* erc-match.el 1.19 (erc-match-fool-p):
+	Changed to call erc-match-directed-at-fool-p instead of
+	     erc-directed-at-fool-p.
+
+2003-01-07  Mario Lang  <mlang@delysid.org>
+
+	* erc-dcc.el 1.11 (erc-cmd-DCC):
+	Change (cond ... (t nil)) to (when ...)
+
+	* erc-dcc.el 1.10: Use erc-current-nick-p
+
+2003-01-07  Jorgen Schaefer  <forcer@users.sourceforge.net>
+
+	* erc.el 1.408:
+	erc-join-buffer: Added 'window-noselect to docstring and :type.
+	erc-auto-query: Added 'window-noselect to :type.
+	(erc): Treat erc-join-buffer being 'window-noselect appropriately.
+
+	* erc.el 1.407 (erc-current-nick-p): New function.
+	(erc-nick-equal-p): New function.
+	(erc-already-logged-in), (erc-server-JOIN), (erc-auto-query),
+	(erc-server-PRIVMSG-or-NOTICE): Use erc-current-nick-p.
+	(erc-update-channel-member): Use erc-nick-equal-p.
+
+	* erc-match.el 1.18 (erc-match-current-nick-p):
+	Renamed from erc-current-nick-p
+	(erc-match-pal-p): Renamed from erc-pal-p
+	(erc-match-fool-p): Renamed from erc-fool-p
+	(erc-match-keyword-p): Renamed from erc-keyword-p
+	(erc-match-dangerous-host-p): Renamed from erc-dangerous-host-p
+	(erc-match-directed-at-fool-p): Renamed from erc-directed-at-fool-p
+	(erc-match-message): Use erc-match-TYPE-p instead of erc-TYPE-p
+
+	* erc.el 1.406:
+	Support for IRCnets' "nick/channel temporarily unavailable"
+
+	(erc-nickname-in-use): New function (mostly copied from erc-server-433).
+	(erc-server-433): Use erc-nickname-in-use
+	(erc-server-437): New function.
+	erc-server-hook-list: Added (437 erc-server-437).
+
+2003-01-07  Mario Lang  <mlang@delysid.org>
+
+	* erc-fill.el 1.21: Add autoload cookie
+
+	* erc-notify.el 1.13:
+	Now also pass SERVER argument to signon/off hooks, and provide a erc-notify-signon/off function for echo-area printing
+
+	* erc-notify.el 1.12 (erc-notiy-QUIT):
+	Change use of delq to delete, delq does not work with strings
+
+2003-01-06  Jorgen Schaefer  <forcer@users.sourceforge.net>
+
+	* erc.el 1.405 (erc-ctcp-query-VERSION):
+	v%s -> %s, so we are no longer vVersion...
+
+2003-01-06  Mario Lang  <mlang@delysid.org>
+
+	* erc.el 1.404: Small change to erc-ison-p, and fixme tag
+
+2003-01-06  Francis Litterio  <franl@users.sourceforge.net>
+
+	* erc.el 1.403 (erc):
+	Fixed bug where variable "away" would be nil in new channel buffers
+	       even if the user is away when joining the channel.
+	(erc-strip-controls): Fixed a bug where erc-strip-controls accidentally
+	       removed all text properties from the string.
+
+2003-01-06  Mario Lang  <mlang@delysid.org>
+
+	* erc-dcc.el 1.9:
+	Some stub functions, some code, nothing really works yet
+
+	* erc.el 1.402 (erc-ison-p): New function
+
+	* erc-dcc.el 1.8: Some functions which will be needed for dcc send
+
+	* erc-dcc.el 1.7 (erc-ip-address-to-decimal):
+	New function, thanks lawrence
+
+	* erc-dcc.el 1.6: Again, simplify code, fix stuff, DCC CHAT works now
+
+	* erc-dcc.el 1.5: Many fixes, chat nearly works now
+
+	* erc-netsplit.el 1.7: Also detect fast netsplit/joins
+
+	* erc-dcc.el 1.4: some more fixes
+
+	* erc-dcc.el 1.3: Fixup stage 1, now dcc get works
+
+	* erc-dcc.el 1.2: make /dcc LIST work
+
+	* erc-dcc.el 1.1:
+	Initial checkin, dont use it!  its really far from complete.  Hackers: help!
+
+	* erc-notify.el 1.11:
+	New function erc-notify-NICK, and added signon/off hooks which were missing
+
+2003-01-05  Jorgen Schaefer  <forcer@users.sourceforge.net>
+
+	* erc.el 1.401 (erc-truncate-buffer-to-size):
+	set inhibit-read-only to t for the
+	deletion. This is usually done by the function calling the hook, but
+	not if it's called interactively. Also, rewrote some weird if/if
+	combination.
+
+	* erc-track.el 1.43 (erc-track-shortennames):
+	Documentation fix (erc-all-buffers is really
+	erc-all-buffer-names)
+
+	These changes make server buffers be tracked as well, as there are
+	quite a few interesting things going on there (e.g. CTCP etc.)
+	(erc-all-buffer-names): Check for (eq major-mode 'erc-mode) instead of
+	erc-default-recipients.
+	(erc-track-modified-channels): Don't require a default target (e.g.,
+	this-channel being non-nil)
+
+2003-01-03  Damien Elmes  <erc@repose.cx>
+
+	* erc.el 1.400:
+	erc-auto-query: can now be set to a symbol to control how new messages should
+	    be popped up (or not popped up, as the case may be)
+	(erc-query): new function which handles the bulk of what (erc-cmd-QUERY) did
+	    previously
+	(erc-cmd-QUERY): use (erc-query)
+	(erc-auto-query): use (erc-query)
+
+	* erc.el 1.399 (erc-current-logfile):
+	Downcase result of log generation function, as IRC is
+	case insensitive. Fixes problems where "/query user" results in a different
+	log file to a query from "User". Avoided adding an extra flag to control this
+	behavior - if you think this was the wrong decision, please correct it and
+	I'll remember it for next time.
+
+See ChangeLog.2002 for earlier changes.
+
+    Copyright (C) 2003 Free Software Foundation, Inc.
+  Copying and distribution of this file, with or without modification,
+  are permitted provided the copyright notice and this notice are preserved.
+
+;; Local Variables:
+;; coding: utf-8
+;; End:
+
+;; arch-tag: 808865e1-3cce-4c5b-9997-95a8b7a9d384
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lisp/erc/ChangeLog.2004	Wed Feb 01 10:07:17 2006 +0000
@@ -0,0 +1,2080 @@
+2004-12-29  Francis Litterio <franl@users.sourceforge.net>
+
+	* erc-goodies.el (erc-interpret-controls-p): Changed docstring to
+	reflect the new meaning if this is set to 'remove.
+	(erc-controls-interpret): Rephrased docstring to be more accurate.
+	(erc-controls-strip): New function that behaves like the
+	recently-removed erc-strip-controls -- it removes all IRC color
+	and highlighting control characters.
+	(erc-controls-highlight): Changed to support the new 'remove value
+	that variable erc-interpret-controls-p might have.
+
+2004-12-28  Francis Litterio <franl@users.sourceforge.net>
+
+	* erc-ibuffer.el, erc-list.el, erc-page.el, erc-speedbar.el:
+	Changed all calls to erc-interpret-controls (which no longer
+	exists) to call erc-controls-interpret (the new name of the same
+	function).
+
+2004-12-28  Francis Litterio <franl@users.sourceforge.net>
+
+	* erc-goodies.el (erc-controls-interpret): Added this function to
+	replace the recently-removed erc-interpret-controls.  Also added
+	a (require 'erc) to solve a byte-compile problem.
+
+2004-12-28  Francis Litterio <franl@users.sourceforge.net>
+
+	* erc.el (erc-controls-interpret): Added this function to replace
+	the recently-removed erc-interpret-controls.
+
+2004-12-27  Jorgen Schaefer <forcer@users.sourceforge.net>
+
+	* erc-truncate.el (erc-truncate-buffer-to-size): Check for
+	logging even better (via lawrence).
+
+2004-12-26  Jorgen Schaefer <forcer@users.sourceforge.net>
+
+	* erc-truncate.el (erc-truncate-buffer-to-size): Much saner
+	logging detection (via lawrence).
+
+2004-12-25  Jorgen Schaefer <forcer@users.sourceforge.net>
+
+	* erc-goodies.el (erc-controls-highlight): Treat single C-c
+	correctly.
+
+2004-12-24  Jorgen Schaefer <forcer@users.sourceforge.net>
+
+	* erc-goodies.el, erc.el: Deleted IRC control character processing
+	and implemented a sane version in erc-goodies.el as a module.
+
+	* erc.el (erc-merge-controls, erc-interpret-controls,
+	erc-decode-controls, erc-strip-controls, erc-make-property-list,
+	erc-prepend-properties): Removed.
+
+	(erc-interpret-controls-p, erc-interpret-mirc-color, erc-bold-face
+	erc-inverse-face, erc-underline-face, fg:erc-color-face0,
+	fg:erc-color-face1, fg:erc-color-face2, fg:erc-color-face3,
+	fg:erc-color-face4, fg:erc-color-face5, fg:erc-color-face6,
+	fg:erc-color-face7, fg:erc-color-face8, fg:erc-color-face9,
+	fg:erc-color-face10, fg:erc-color-face11, fg:erc-color-face2,
+	fg:erc-color-face13, fg:erc-color-face14, fg:erc-color-face15,
+	bg:erc-color-face1, bg:erc-color-face2, bg:erc-color-face3,
+	bg:erc-color-face4, bg:erc-color-face5, bg:erc-color-face6,
+	bg:erc-color-face7, bg:erc-color-face8, bg:erc-color-face9,
+	bg:erc-color-face10, bg:erc-color-face11, bg:erc-color-face2,
+	bg:erc-color-face13, bg:erc-color-face14, bg:erc-color-face15,
+	erc-get-bg-color-face, erc-get-fg-color-face,
+	erc-toggle-interpret-controls): Moved.
+
+	* erc-goodies.el (erc-beep-p, irccontrols, erc-controls-highlight,
+	erc-controls-propertize): New.
+
+2004-12-24  Jorgen Schaefer <forcer@users.sourceforge.net>
+
+	* erc-goodies.el, erc.el: The Small Extraction of Stuff[tm] commit.
+	 Moved some functions from erc.el to erc-goodies.el, and
+	transformed them to erc modules in the process.
+	- imenu autoload stuff moved. I don't know why it is here at all.
+	- Moved: scroll-to-bottom, make-read-only, distinguish-noncommands,
+	smiley,   unmorse, erc-occur (the last isn't a module, but still
+	moved)
+	(erc-input-line-position, erc-add-scroll-to-bottom,
+	erc-scroll-to-bottom, erc-make-read-only, erc-noncommands-list,
+	erc-send-distinguish-noncommands, erc-smiley, erc-unmorse,
+	erc-occur): Moved from erc.el to erc-goodies.el.
+	(smiley): Module moved from erc.el to erc-goodies.el.
+	(scrolltobottom, readonly, noncommands, unmorse): New modules.
+
+2004-12-20  Diane Murray <disumu@x3y2z1.net>
+
+	* erc.el: (erc-format-away-status): Use `a', not `away' - that's
+	why it's there.
+	(erc-update-mode-line-buffer): The values of `mode-line-process'
+	and `mode-line-buffer-identification' are normally lists.
+	Conform.
+
+2004-12-18  Jorgen Schaefer <forcer@users.sourceforge.net>
+
+	* erc.el: (erc-process-ctcp-query, erc-process-ctcp-reply): Display
+	message in the active window, not the server window.
+
+2004-12-16  Edward O'Connor <ted@oconnor.cx>
+
+	* erc-track.el (erc-track-position-in-mode-line): Check for
+	'erc-track-mode variable with boundp. From Adrian Aichner
+	<adrian@xemacs.org>.
+
+2004-12-16  Jorgen Schaefer <forcer@users.sourceforge.net>
+
+	* erc.el (erc-upcase-first-word): New function. The old way used
+	in erc-send-ctcp-message would eat consecutive whitespace etc.
+	(erc-send-ctcp-message, erc-send-ctcp-notice): Use it.
+
+2004-12-15  Edward O'Connor <ted@oconnor.cx>
+
+	* erc.el (erc-send-ctcp-message): Fix braino with my previous
+	patch. It always helps to C-x C-s before `cvs commit'.
+
+2004-12-15  Edward O'Connor <ted@oconnor.cx>
+
+	* erc.el (erc-send-ctcp-message): Only upcase the ctcp command,
+	and not the entire message. Revision 1.707 had broken /me.
+	Shouting is bad! :)
+
+2004-12-14  Diane Murray <disumu@x3y2z1.net>
+
+	* erc-nets.el (erc-networks-alist): Change undernet to Undernet as
+	is used in `erc-server-alist', so that completion works when using
+	`erc-server-select'.  This should fix Debian bug #282003 (erc:
+	cannot connect to Undernet).
+
+2004-12-14  Diane Murray <disumu@x3y2z1.net>
+
+	* erc-backend.el: (def-edebug-spec): Only run this if 'edebug is
+	available.
+
+2004-12-14  Diane Murray <disumu@x3y2z1.net>
+
+	* erc.el: The last change to `erc-mode-line-format' introduced a
+	bug in Xemacs - it can't handle the #(" "...) strings at all.  The
+	following changes fix the bug and simplify the mode-line handling
+	considerably.  (erc-mode-line-format): Now defined as a string
+	which will be formatted using `format-spec' and take the place of
+	`mode-line-buffer-identification' in the mode line.
+	(erc-header-line-format): Now defined as a string to be formatted
+	using `format-spec'.
+	(erc-prepare-mode-line-format): Removed.
+	(erc-format-target, erc-format-target-and/or-server,
+	erc-format-away-status, erc-format-channel-modes): New functions.
+	Basically the old `erc-prepare-mode-line-format' split apart.
+	(erc-update-mode-line-buffer): Set
+	`mode-line-buffer-identification' to the formatted
+	`erc-mode-line-format', set `mode-line-process' to ": CLOSED" if
+	the connection has been terminated, and set `header-line-format'
+	(if it is bound) to the formatted `erc-header-line-format', then
+	do a `force-mode-line-update'.
+
+2004-12-12  Diane Murray <disumu@x3y2z1.net>
+
+	* erc.el (erc-modules): Disable modules removed with `customize'.
+	(erc-update-modules): Try to give a more descriptive error
+	message.
+
+2004-12-12  Diane Murray <disumu@x3y2z1.net>
+
+	* erc-complete.el, erc.el, erc-list.el, erc-nets.el,
+	erc-nicklist.el, erc-pcomplete.el, erc-replace.el, erc-speak.el,
+	erc-truncate.el: (erc-buffers, erc-coding-systems, erc-display,
+	erc-mode-line-and-header, erc-ignore, erc-query,
+	erc-quit-and-part, erc-paranoia, erc-scripts, erc-old-complete,
+	erc-list, erc-networks, erc-nicklist, erc-pcomplete, erc-replace,
+	erc-truncate): New customization groups.  (erc-join-buffer,
+	erc-frame-alist, erc-frame-dedicated-flag, erc-reuse-buffers): Use
+	'erc-buffers as `:group'.  (erc-default-coding-system,
+	erc-encoding-coding-alist): Use 'erc-coding-systems as `:group'.
+	(erc-hide-prompt, erc-show-my-nick, erc-prompt,
+	erc-input-line-position, erc-command-indicator, erc-notice-prefix,
+	erc-notice-highlight-type, erc-interpret-controls-p,
+	erc-interpret-mirc-color, erc-minibuffer-notice,
+	erc-format-nick-function): Use 'erc-display as `:group'.
+	(erc-mode-line-format, erc-header-line-format,
+	erc-header-line-uses-help-echo-p, erc-common-server-suffixes,
+	erc-mode-line-away-status-format): Use 'erc-mode-line-and-header
+	as `:group'.
+	(erc-hide-list, erc-ignore-list, erc-ignore-reply-list,
+	erc-minibuffer-ignored): Use 'erc-ignore as `:group'.
+	(erc-auto-query, erc-query-on-unjoined-chan-privmsg,
+	erc-format-query-as-channel-p): Use 'erc-query as `:group'.
+	(erc-kill-buffer-on-part, erc-kill-queries-on-quit,
+	erc-kill-server-buffer-on-quit, erc-quit-reason-various-alist,
+	erc-part-reason-various-alist, erc-quit-reason, erc-part-reason):
+	Use 'erc-quit-and-part as `:group'.
+	(erc-verbose-server-ping, erc-paranoid, erc-disable-ctcp-replies,
+	erc-anonymous-login, erc-show-channel-key-p): Use 'erc-paranoia as
+	`:group'.
+	(erc-startup-file-list, erc-script-path, erc-script-echo): Use
+	'erc-scripts as `:group'.
+	(erc-nick-completion, erc-nick-completion-ignore-case,
+	erc-nick-completion-postfix): Use 'erc-old-complete as `:group'.
+	(erc-chanlist-progress-message, erc-no-list-networks,
+	erc-chanlist-frame-parameters, erc-chanlist-hide-modeline,
+	erc-chanlist-mode-hook): Use 'erc-list as `:group'.
+	(erc-server-alist, erc-networks-alist): Use 'erc-networks as
+	`:group'.
+	(erc-settings): Use `defvar' instead of `defcustom' since this is
+	only a draft which doesn't work.
+	(erc-nicklist-window-size): Use 'erc-nicklist as `:group'.
+	(erc-pcomplete-nick-postfix,
+	erc-pcomplete-order-nickname-completions): Use 'erc-pcomplete as
+	`:group'.
+	(erc-replace-alist): Use 'erc-replace as `:group'.
+	(erc-speak-filter-timestamp): Use 'erc-speak as `:group'.
+	(erc-max-buffer-size): Use 'erc-truncate as `:group'.
+
+2004-12-12  Jorgen Schaefer <forcer@users.sourceforge.net>
+
+	* erc.el (erc-scroll-to-bottom): Go to the end of the buffer
+	before recentering. This allows editing multiple lines more
+	conveniently in CVS Emacs. This also undos a change by antifuchs
+	who said this goto-char would mess up redisplay. Extensive testing
+	couldn't reproduce that problem.
+
+2004-12-12  Brian Palmer <bpalmer@gmail.com>
+
+	* erc.el (erc-send-ctcp-message): upcase the ctcp message (so that
+	version becomes VERSION, for example).
+	(erc-iswitchb): Make the argument optional in non-interactive
+	invocation, so erc-iswitchb can be substituted directly for
+	iswitchb in code.
+
+2004-12-11  Diane Murray <disumu@x3y2z1.net>
+
+	* erc-track.el (erc-track-position-in-mode-line): Allow for the
+	fact that `erc-track-mode' isn't bound when file is loaded.
+
+2004-12-11  Diane Murray <disumu@x3y2z1.net>
+
+	* erc-track.el (erc-track-position-in-mode-line): New customizable
+	variable.  (erc-track-remove-from-mode-line): New function.
+	Remove `erc-modified-channels-string' from the mode-line.
+	(erc-track-add-to-mode-line): New function.  Add
+	`erc-modified-channels-string' to the mode-line using the value of
+	`erc-track-position-in-mode-line' to determine whether to add it
+	to the beginning or the end of `mode-line-modes' (only available
+	with GNU Emacs versions above 21.3) or to the end of
+	`global-mode-string'.
+	(erc-track-mode, erc-track-when-inactive-mode): Use the new
+	functions.
+
+2004-12-11  Jorgen Schaefer <forcer@users.sourceforge.net>
+
+	* erc.el: (erc-cmd-BANLIST): Use (buffer-name) and not
+	(erc-default-target) for the buffer name - buffer names are case
+	sensitive.
+
+2004-12-11  Brian Palmer <bpalmer@gmail.com>
+
+	* erc.el (erc-message-type): Added the message "MODE" to the known
+	erc-message-type widget, so that (for example) people can tell
+	erc-track-exclude-types to ignore mode changes. The others tag
+	also needed to be made an inline list, so that it's merged with
+	the given constants, instead of being inserted as a list.
+
+2004-12-10  Jorgen Schaefer <forcer@users.sourceforge.net>
+
+	* erc-track.el, erc.el: Update to get ERC look nicely in CVS Emacs.
+
+	* erc.el (erc-mode-line-format): When on CVS emacs, use the new
+	format.
+
+	* erc-track.el (track module): When on CVS emacs, modify
+	mode-line-modes instead of global-mode-string. The latter is way
+	to far too the right.
+
+2004-11-18  Mario Lang <mlang@delysid.org>
+
+	* Makefile, debian/changelog: debian release 20041118-1
+
+2004-11-03  Diane Murray <disumu@x3y2z1.net>
+
+	* erc-button.el (erc-button-buttonize-nicks): Set default value to
+	`t'.  Updated documentation and customization `:type' to reflect
+	usage.
+
+2004-10-29  Johan Bockgard <bojohan@users.sourceforge.net>
+
+	* AUTHORS: Added self.
+
+2004-10-17  Diane Murray <disumu@x3y2z1.net>
+
+	* erc-list.el: Added local variables for this file.
+	(erc-list-version): New.
+	(erc-cmd-LIST): Take &rest rather than &optional arguments, as was
+	done in revision 1.21.  Allow for input when called interactively.
+	(erc-prettify-channel-list, erc-chanlist-toggle-sort-state): Use
+	`unless' instead of when not.
+
+2004-10-17  Diane Murray <disumu@x3y2z1.net>
+
+	* erc-backend.el (erc-handle-unknown-server-response): Fixed so
+	that the contents are only shown once. (MOTD): Display lines in
+	the server buffer if it's the first MOTD sent upon connection.
+	This is to avoid the problem of having the MOTD of one server
+	showing up in another server's buffer if it took a while to get
+	connected.
+	(004): Fixed to show the user modes and channel modes correctly.
+	(303): Now displays the nicknames returned by ISON instead of the
+	user's nickname.
+	(367, 368): Moved up into 300's section of the code.  Added
+	documentation.  Use `multiple-value-bind' to set variables in 367.
+	(391): Fixed so that the server name is shown correctly.
+
+2004-10-17  Diane Murray <disumu@x3y2z1.net>
+
+	* erc.el (erc-process-sentinel): Use CPROC instead of
+	`erc-process' in debug message.  Should fix a bug where an error
+	saying "Buffer *scratch* has no process" would occur when
+	disconnected.
+	(erc-cmd-SV): Check for X toolkit after checking for more specific
+	features.  (erc--kill-server): Set `quitting' to non-nil so that
+	we don't automatically reconnect.
+
+2004-10-05  Jorgen Schaefer <forcer@users.sourceforge.net>
+
+	* erc.el: (erc-ignored-user-p): Don't require regexes to match the
+	beginning.
+
+2004-09-11  Jorgen Schaefer <forcer@users.sourceforge.net>
+
+	* erc.el: group erc: Moved to 'applications (patch by bojohan)
+
+2004-09-08  Jorgen Schaefer <forcer@users.sourceforge.net>
+
+	* erc-button.el: (erc-button-remove-old-buttons): Remove 'keymap
+	not 'local-map.
+
+2004-09-03  Jorgen Schaefer <forcer@users.sourceforge.net>
+
+	* erc-backend.el: JOIN response handler: Typo fix of the last
+	commit.
+
+2004-09-03  Jorgen Schaefer <forcer@users.sourceforge.net>
+
+	* erc-backend.el: JOIN response handler: Run `erc-join-hook'
+	without arguments as specified in the docstring.
+
+2004-08-27  Jorgen Schaefer <forcer@users.sourceforge.net>
+
+	* erc.el (erc-send-current-line): Removed unused variable SENTP.
+
+2004-08-19  Jorgen Schaefer <forcer@users.sourceforge.net>
+
+	* erc.el: ERC-SEND-COMPLETED-HOOK used to be run when the prompt
+	was already displayed. We restore this behavior (thanks to bojohan
+	and TerryP for noticing). We also fix the docstring of
+	ERC-SEND-COMPLETED-HOOK, since the hook is (and used to be) called
+	even if nothing was sent to the server.
+	(erc-send-completed-hook): Fixed docstring.
+	(erc-send-current-line): Add incantation for
+	erc-send-completed-hook.
+	(erc-send-input): Remove incantation for erc-send-completed-hook.
+
+2004-08-18  Jorgen Schaefer <forcer@users.sourceforge.net>
+
+	* erc-backend.el: response-handler 368: Use s368, not s367.
+
+2004-08-17  Jorgen Schaefer <forcer@users.sourceforge.net>
+
+	* erc.el (erc-scroll-to-bottom): Don't scroll when we're not
+	connected anymore.
+
+2004-08-17  Jorgen Schaefer <forcer@users.sourceforge.net>
+
+	* erc-backend.el, erc.el: Handle /mode #emacs b output without
+	errors and such. First, handle unknown format specs gracefully
+	(that is, give a useful error). Then, provide handlers for the
+	banlist replies.
+
+	* erc-backend.el: New handler for 367 and 368. Removed from default
+	handler.
+
+	* erc.el: Provide english catalog for s367 and s368.
+	(erc-format-message): Give an error message when we don't find an
+	entry.
+
+2004-08-17  Jorgen Schaefer <forcer@users.sourceforge.net>
+
+	* erc-fill.el: erc-fill-variable could be confused about really
+	long nicks. We put an upper limit on the length of the fill prefix.
+	(erc-fill-variable): Adjust fill-prefix.
+	erc-fill-variable-maximum-indentation: New variable.
+
+2004-08-17  Francis Litterio <franl@users.sourceforge.net>
+
+	* erc.el (erc-send-input): Fixed a bug where this function
+	referenced variable "input" instead of variable "str".
+
+2004-08-16  Francis Litterio <franl@users.sourceforge.net>
+
+	* erc-list.el (erc-chanlist-highlight-line): Fixed a bug where
+	this function failed to set the correct face for highlighting the
+	current line.
+
+2004-08-14  Jorgen Schaefer <forcer@users.sourceforge.net>
+
+	* erc-fill.el (erc-fill-variable): Don't fuck up when the
+	looking-at didn't work.
+
+2004-08-14  Jorgen Schaefer <forcer@users.sourceforge.net>
+
+	* erc.el (erc-send-single-line): Call the hooks to change the
+	appearance for something only if we actually inserted something,
+	doh.
+	(erc-display-command): Display the prompt outside of the area that
+	set the text properties on.
+
+2004-08-14  Jorgen Schaefer <forcer@users.sourceforge.net>
+
+	* erc.el: Refactored erc-send-current-line. This should fix some
+	dormant bugs, and make the whole thing actually readable. Yay.
+	Some changes in behavior were made. Whitespace at the end of lines
+	sent is not removed anymore, but that shouldn't bother anyone.
+	Additionally, errors in commands or hooks shouldn't prevent the
+	prompt from showing up again now.
+	(erc-parse-current-line): Removed.
+	(erc-send-current-line): Refactored.
+	(erc-send-input): New function.
+	(erc-send-single-line): New function.
+	(erc-display-command): New function.
+	(erc-display-msg): New function.
+	(erc-user-input): New function.
+
+2004-08-13  Jorgen Schaefer <forcer@users.sourceforge.net>
+
+	* erc.el (erc-cmd-SERVER): Use newer keyword call interface to
+	erc-select, and handle the error if it can't resolve the host.
+
+2004-08-11  Jorgen Schaefer <forcer@users.sourceforge.net>
+
+	* erc-backend.el, erc.el: erc-backend.el (404 response handler):
+	New function. We now support "cannot send to channel".
+
+	* erc.el (erc-define-catalog call): Added s404. erc.el
+	(erc-ctcp-ECHO-reply, erc-ctcp-CLIENTINFO-reply,
+	erc-ctcp-FINGER-reply, erc-ctcp-PING-reply, erc-ctcp-TIME-reply,
+	erc-ctcp-VERSION-reply): Display reply in the active window, not
+	the server window.
+
+2004-08-10  Jorgen Schaefer <forcer@users.sourceforge.net>
+
+	* erc.el (erc-with-all-buffers-of-server): Actually make it left
+	to right, doh.
+
+2004-08-10  Jorgen Schaefer <forcer@users.sourceforge.net>
+
+	* erc.el (erc-with-all-buffers-of-server): Evaluate left-to-right
+	so we don't surprise a user.
+
+2004-08-10  Jorgen Schaefer <forcer@users.sourceforge.net>
+
+	* erc.el (erc-process-input-line): Parentophobia! Another
+	paren-fix.
+
+2004-08-10  Jorgen Schaefer <forcer@users.sourceforge.net>
+
+	* erc-backend.el: PRIVMSG NOTICE response handler: Killed one paren
+	too much. Poor paren. Got resurrected.
+
+2004-08-10  Jorgen Schaefer <forcer@users.sourceforge.net>
+
+	* erc-track.el: Make server buffers showing up in the mode line
+	optional. Thanks to Daniel Knapp on the EmacsWiki for this patch.
+
+	erc-track-exclude-server-buffer: New variable.
+	(erc-track-modified-channels): Return a server buffer only if
+	erc-track-exclude-server-buffer is nil.
+
+2004-08-10  Jorgen Schaefer <forcer@users.sourceforge.net>
+
+	* erc.el: (erc-cmd-DESCRIBE): Don't parse arguments.
+
+2004-08-10  Jorgen Schaefer <forcer@users.sourceforge.net>
+
+	* erc-truncate.el: (erc-truncate-buffer-to-size): Use
+	erc-insert-marker, not (point-max), to decide the length of the
+	buffer. A long input line shouldn't make the buffer smaller.
+
+2004-08-10  Jorgen Schaefer <forcer@users.sourceforge.net>
+
+	* erc-macs.el, erc-members.el: The change to hashes for channel
+	members has been made some time ago.  Clean up the various tries to
+	do this in the past.
+
+	erc-macs.el: Removed.  erc-members.el: Removed.
+
+2004-08-10  Jorgen Schaefer <forcer@users.sourceforge.net>
+
+	* erc-backend.el, erc-ibuffer.el, erc-members.el, erc.el: Nothing
+	big changed here. Really. Uhm, maybe the info-buffers are gone or
+	so.  Can't really remember. Don't worry, nothing important is
+	missing.
+
+	erc-speedbar.el looks nice btw, did you know?
+
+	Adjusted various places in erc.el, erc-backend.el, erc-ibuffer.el
+	and erc-members.el - too numerous to list here, sorry.
+
+	* erc.el: erc-use-info-buffers: Removed.  erc-info-mode-map:
+	Removed.
+	(erc-info-mode): Removed.
+	(erc-find-channel-info-buffer): Removed.
+	(erc-update-channel-info-buffer): Removed.
+	(erc-update-channel-info-buffers): Removed.
+
+	* erc-members.el: erc-update-member renamed to
+	erc-update-channel-member for better clarity.
+
+2004-08-10  Jorgen Schaefer <forcer@users.sourceforge.net>
+
+	* erc.el: This change improves the help output on a bogus command
+	invocation. We display the command as it would be typed by the
+	user, not as it is seen by Emacs.
+
+	(erc-get-arglist): Is now called erc-function-arglist, and returns
+	now an arglist without the enclosing parens.
+	(erc-command-name): New function.
+	(erc-process-input-line): Pass the command name, not the function
+	name.
+
+2004-08-10  Jorgen Schaefer <forcer@users.sourceforge.net>
+
+	* erc.el: (erc-process-input-line): Fix bug when the command
+	doesn't have an arglist or no documentation. Thanks bojohan again
+	:)
+
+2004-08-10  Jorgen Schaefer <forcer@users.sourceforge.net>
+
+	* erc-match.el: (erc-add-entry-to-list),
+	(erc-remove-entry-from-list): Update docstring, a TEST argument is
+	not given.
+
+2004-08-10  Jorgen Schaefer <forcer@users.sourceforge.net>
+
+	* erc.el (erc-with-buffer): Really fix this docstring.
+
+2004-08-10  Jorgen Schaefer <forcer@users.sourceforge.net>
+
+	* erc.el (erc-with-buffer): Fix double evaluation in macro, and
+	fix docstring.
+
+2004-08-10  Brian Palmer <bpalmer@gmail.com>
+
+	* erc.el (erc-cmd-JOIN): Use erc-member-ignore-case instead of
+	member-ignore-case.
+
+2004-08-09  Johan Bockgard <bojohan@users.sourceforge.net>
+
+	* erc-backend.el: Define an "Edebug specification" for the
+	`define-erc-response-handler' macro. This means that one can step
+	through response handlers defined by this macro with edebug. Maybe
+	more macros would benefit from this?
+
+2004-08-09  Johan Bockgard <bojohan@users.sourceforge.net>
+
+	* erc-pcomplete.el (pcomplete/erc-mode/CTCP): New function.
+	Completion for the /CTCP command.  (erc-pcomplete-ctcp-commands):
+	New variable. List of ctcp commands.
+
+2004-08-09  Johan Bockgard <bojohan@users.sourceforge.net>
+
+	* erc-list.el: Clean up docstrings.
+	(erc-prettify-channel-list): Extend properties to cover the entire
+	line, including the newline, to make it look
+	better.
+	(erc-chanlist-highlight-line): Ditto.
+	(erc-chanlist-mode-hook): Make it a defcustom.
+
+2004-08-09  Jorgen Schaefer <forcer@users.sourceforge.net>
+
+	* erc.el (erc-compute-full-name): Typo fix, should be full-name,
+	not name.
+
+2004-08-09  Jorgen Schaefer <forcer@users.sourceforge.net>
+
+	* erc.el (erc): Setup the buffer to be shown in a window at the
+	end of this function. This enables 'window-noselect to work
+	properly.
+	(erc, erc-send-current-line): Fix some
+	goto-char/open-line/goto-char to goto-char/insert.
+
+2004-08-08  Jorgen Schaefer <forcer@users.sourceforge.net>
+
+	* erc.el (erc-parse-user): Live with bogus info from bouncers.
+
+2004-07-31  Brian Palmer <bpalmer@gmail.com>
+
+	* erc.el (erc-select): Change the docstring to reflect the new
+	arguments; include the arguments in the docstring for non-cvs
+	emacs. Change the parameters to call erc-compute-* instead of
+	using the erc-* variables directly.
+	(erc-compute-server): Made argument optional.
+	(erc-compute-nick): ditto.
+	(erc-compute-full-name): ditto.  (erc-compute-port): ditto.
+
+2004-07-30  Francis Litterio <franl@users.sourceforge.net>
+
+	* erc.el: (erc-cmd-BANLIST): Fixed a bug where channel-banlist was
+	not reset to nil before fetching an updated banlist from the
+	server.
+
+2004-07-30  Francis Litterio <franl@users.sourceforge.net>
+
+	* erc.el: (erc-cmd-BANLIST): Fixed a bug where the
+	'received-from-server property on variable channel-banlist was not
+	being reset to nil.  This fixes the symptom where one types
+	/BANLIST and sees "No bans for channel: #whatever" when you know
+	there are bans.
+
+2004-07-23  Brian Palmer <bpalmer@gmail.com>
+
+	* erc.el: (erc-select-read-args): Use erc-compute-nick to
+	calculate the default nickname
+
+2004-07-20  Brian Palmer <bpalmer@gmail.com>
+
+	* erc.el: (erc-process-sentinel-1): New function. This is an
+	auxiliary function refactored out of erc-process-sentinel to
+	decide a server buffer's fate (whether it should be killed, and
+	whether erc should attempt to auto-reconnect).  Michael Olson
+	<mwolson@gnu.org> helped with this.
+	(erc-kill-server-buffer-on-quit): New variable. Used in
+	erc-process-sentinel-1 to decide whether to kill a server buffer
+	when the user quit normally.
+	(erc-process-sentinel): Auxiliary function erc-process-sentinel-1
+	split out.  The function body has `with-current-buffer' wrapped
+	around it, to ensure separation of messages if multiple
+	connections were being made.  Use `if' instead of `cond' in places
+	where the decision is binary.  The last (useless, since the server
+	connection is closed) prompt in the server buffer is removed.
+	Color "erc terminated" and "erc finished" messages with
+	erc-error-face.  Mark the buffer unmodified so that, if not killed
+	automatically, the user is not prompted to save it.
+
+2004-07-16  Brian Palmer <bpalmer@gmail.com>
+
+	* erc.el (erc-select-read-args): New function. Prompts the user
+	for arguments to pass to erc-select and erc-select-ssl.
+	(erc-select): Use (erc-select-read-args) when called interactively
+	to get its arguments.  When non-interactively, use keyword
+	arguments.
+	(erc-select-ssl): Ditto.
+	(erc-compute-port): New function. Parallel to erc-compute-server,
+	but comes up with a default value for an IRC server's port.
+
+2004-07-16  Jorgen Schaefer <forcer@users.sourceforge.net>
+
+	* erc-match.el (erc-match-message): Quote the current nickname.
+
+2004-07-12  Brian Palmer <bpalmer@gmail.com>
+
+	* erc-list.el (erc-chanlist-mode): Remove explicit invocation of
+	erc-chanlist-mode-hook, since it's automatically invoked by
+	define-derived-mode
+
+2004-07-03  Jorgen Schaefer <forcer@users.sourceforge.net>
+
+	* erc-match.el (erc-match-current-nick-p): Quote current nick for
+	regexp parsing.
+
+2004-06-27  Johan Bockgard <bojohan@users.sourceforge.net>
+
+	* erc-nickserv.el (erc-nickserv-identify-mode): Fix erroneous
+	parentheses in call to `completing-read'.
+
+2004-06-23  Alex Schroeder <alex@gnu.org>
+
+	* Makefile (release): Depend on autoloads, and copy erc-auto.el
+	into the tarball.
+
+2004-06-14  Francis Litterio <franl@users.sourceforge.net>
+
+	* erc.el (erc-log-irc-protocol): Fixed minor bug where each line
+	received from a server was logged as two lines (one with text and
+	one blank).
+
+2004-06-08  Brian Palmer <bpalmer@gmail.com>
+
+	* erc-list.el (erc-chanlist-frame-parameters): Made customizable.
+	(erc-chanlist-header-face): Changed to use defface with some
+	reasonable defaults instead of make-face, and removed the
+	associated -face variable.
+	(erc-chanlist-odd-line-face): Ditto.
+	(erc-chanlist-even-line-face): Ditto.
+	(erc-chanlist-highlight-face): New variable. Holds a face used for
+	highlighting the current line.
+	(erc-cmd-LIST): Use erc-member-ignore-case instead of
+	member-ignore-case.
+	(erc-chanlist-post-command-hook): Change to move the highlight
+	overlay instead of refontifying the entire buffer.
+	(erc-chanlist-dehighlight-line): Added to detach the highlight
+	overlay from the buffer.
+
+2004-05-31  Jorgen Schaefer <forcer@users.sourceforge.net>
+
+	* erc.el: erc-mode-line-format: Add column numbers.
+
+2004-05-31  Adrian Aichner <adrian@xemacs.org>
+
+	* erc-autojoin.el: Typo fix.
+
+	* erc-dcc.el (erc-dcc-do-GET-command): Use expand-file-name.
+	(erc-dcc-get-file): XEmacs set-buffer-multibyte compatibility.
+
+	* erc-log.el: Append `erc-log-setup-logging' to
+	`erc-connect-pre-hook' so that `erc-initialize-log-marker' is run
+	first (markers are needed by `erc-log-setup-logging').
+	(erc-enable-logging): Docstring fix.
+	(erc-log-setup-logging): Move `erc-log-insert-log-on-open' to (1-
+	(point-max)) when doing `erc-log-insert-log-on-open'.  Modified
+	version of a patch by Lawrence Mitchell.
+	(erc-log-all-but-server-buffers): Do `save-excursion' as well.
+	(erc-current-logfile): Pass buffer name as target
+	argument to `erc-generate-log-file-name-function' if
+	`erc-default-target' is nil.
+	(erc-generate-log-file-name-with-date): Use expand-file-name.
+	(erc-generate-log-file-name-short): Ditto.
+	(erc-save-buffer-in-logs): Do `save-excursion' and test whether
+	erc-last-saved-position is a marker.
+
+	* erc-members.el: Avoid miscompiling macro `erc-log' and
+	`with-erc-channel-buffer' by requiring 'erc at compile time.
+
+	* erc-sound.el: Use expand-file-name.
+
+	* erc.el (erc-debug-log-file): Ditto.
+	(erc-find-file): Ditto.
+
+2004-05-26  Francis Litterio <franl@users.sourceforge.net>
+
+	* erc.el, erc-backend.el (erc-cmd-BANLIST): Added a missing "'"
+	that was preventing /BANLIST from working.  In erc-backend.el,
+	added server repsonse handler for 367 and 368 reponses to get
+	/BANLIST working.
+
+2004-05-26  Francis Litterio <franl@users.sourceforge.net>
+
+	* erc.el: Removed an eval-when-compile that was preventing the
+	byte-compiled version of this file from loading.
+
+2004-05-26  Francis Litterio <franl@users.sourceforge.net>
+
+	* erc.el: Undid part of my last change.  I suspect it was wrong.
+
+2004-05-26  Francis Litterio <franl@users.sourceforge.net>
+
+	* erc.el: Silenced several byte-compiler warnings.
+
+2004-05-26  Francis Litterio <franl@users.sourceforge.net>
+
+	* erc.el (erc-log-irc-protocol): Fixed problem where this function
+	misformatted IRC protocol text if multiple lines were received from
+	the server at one time.
+
+2004-05-25  Francis Litterio <franl@users.sourceforge.net>
+
+	* erc.el (erc-toggle-debug-irc-protocol): Cosmetic changes to the
+	informational text in the *erc-protocol* buffer.
+
+2004-05-24  Francis Litterio <franl@users.sourceforge.net>
+
+	* erc.el (erc-log-irc-protocol, erc-process-filter): Now the lines
+	inserted in the *erc-protocol* buffer are prefixed with the name
+	of the network to/from which the data is going/coming.  This makes
+	reading the *erc-protocol* buffer much easier when connected to
+	multiple networks.
+
+2004-05-23  Jeremy Bertram Maitin-Shepard <jbms@gentoo.org>
+
+	* erc-backend.el: Fixes server message parsing so that command
+	arguments specified after the colon are not treated specially. All
+	arguments are added to the `command-args' field, and the
+	`contents' points to the last element in the `command-args' list.
+	This allows ERC to connect to networks such as Undernet.  Although
+	keeping `contents' allows many of the response handlers to
+	continue to work as-is, many other are probably broken by this
+	patch.
+
+2004-05-20  Lawrence Mitchell <wence@gmx.li>
+
+	* HACKING: Add comment that C-c C-a can be useful if you write
+	ChangeLog entries using Emacs' standard functions.
+
+2004-05-17  Diane Murray <disumu@x3y2z1.net>
+
+	* erc-speedbar.el: Ignore errors when attempting to require dframe
+	(there are a couple implementations of speedbar, one of which uses
+	of dframe).
+	(erc-speedbar-version): New.
+	(erc-speedbar-goto-buffer): Use dframe functions if dframe is
+	available.
+
+2004-05-17  Diane Murray <disumu@x3y2z1.net>
+
+	* erc-autojoin.el: Added local variables for this file.
+	(erc-autojoin-add): The channel name is in `erc-response.contents'.
+
+2004-05-17  Mario Lang <mlang@delysid.org>
+
+	* erc-log.el: Dont autoload a define-key statement, erc-mode-map
+	might not be known yet
+
+2004-05-16  Lawrence Mitchell <wence@gmx.li>
+
+	* erc-backend.el (erc-parse-server-response): Revert to original
+	`erc-parse-line-from-server' version, since new version breaks for
+	a number of edge cases.
+
+2004-05-14  Diane Murray <disumu@x3y2z1.net>
+
+	* erc-backend.el (erc-handle-unknown-server-response): New
+	function.  Added to `erc-default-server-functions'.  Display
+	unknown responses to the user.
+	(221): Don't show nickname in modes list.
+	(254): Fixed to use 's254.
+	(303): Added docstring.
+	(315, 318, 323, 369): Ignored responses grouped together.
+	(391): New.
+	(406, 432): Use ?n, not ?c in `erc-display-message'.
+	(431, 445, 446, 451, 462, 463, 464, 465, 481, 483, 485, 491, 501,
+	502): All error responsess with no arguments grouped together.
+
+2004-05-14  Diane Murray <disumu@x3y2z1.net>
+
+	* erc.el (erc-message-type-member): Use `erc-response.command'.
+	`erc-track-exclude-types' should be respected again.
+	(erc-cmd-TIME): Fixed to work with and without server given as
+	argument.
+	(erc-define-catalog): Added, s391, s431, s445, s446, s451, s462,
+	s463, s464, s465, s483, s484, s485, s491, s501, s502.
+
+2004-05-14  Lawrence Mitchell <wence@gmx.li>
+
+	* HACKING: Typo fix.
+
+2004-05-14  Lawrence Mitchell <wence@gmx.li>
+
+	* Makefile (erc-auto.el): Pass -f flag to rm so that we don't fail
+	if erc-auto.elc doesn't exist.
+
+2004-05-14  Lawrence Mitchell <wence@gmx.li>
+
+	* erc-backend.el (erc-with-buffer): Autoload.
+	(erc-parse-server-response): XEmacs' `replace-match' only replaces
+	subexpressions when operating on buffers, not strings, work around
+	it.
+	(461): Command with invalid arguments is `second', not `third'.
+
+2004-05-14  Diane Murray <disumu@x3y2z1.net>
+
+	* erc-notify.el (erc-notify-NICK): Use `erc-response.contents' to
+	get nickname.
+
+2004-05-13  Lawrence Mitchell <wence@gmx.li>
+
+	* erc-track.el: Indentation fixes.
+	(track-when-inactive): Use `erc-server-FOO-functions', not
+	`erc-server-FOO-hook.
+
+2004-05-13  Lawrence Mitchell <wence@gmx.li>
+
+	* erc-notify.el (notify): Use `erc-server-FOO-functions', not
+	`erc-server-FOO-hook.
+	(erc-notify-timer, erc-notify-JOIN, erc-notify-NICK)
+	(erc-notify-QUIT): Use new accessors for PARSED argument.
+
+2004-05-13  Lawrence Mitchell <wence@gmx.li>
+
+	* erc-nickserv.el (services, erc-nickserv-identify-mode): Use
+	`erc-server-FOO-functions', not `erc-server-FOO-hook.
+	(erc-nickserv-identify-autodetect): Use new accessors for PARSED
+	argument.
+
+2004-05-13  Lawrence Mitchell <wence@gmx.li>
+
+	* erc-netsplit.el (netsplit): Use `erc-server-FOO-functions', not
+	`erc-server-FOO-hook.
+	(erc-netsplit-JOIN, erc-netsplit-MODE, erc-netsplit-QUIT): Use new
+	accessors for PARSED argument.
+
+2004-05-13  Lawrence Mitchell <wence@gmx.li>
+
+	* erc-nets.el: Use `erc-server-FOO-functions', not
+	`erc-server-FOO-hook.
+
+2004-05-13  Lawrence Mitchell <wence@gmx.li>
+
+	* erc-menu.el (erc-menu-definition): Only allow listing of
+	channels if `erc-cmd-LIST' is fboundp.
+
+2004-05-13  Lawrence Mitchell <wence@gmx.li>
+
+	* erc-match.el: Use `erc-server-FOO-functions', not
+	`erc-server-FOO-hook.
+	(erc-get-parsed-vector-nick, erc-get-parsed-vector-type): Use new
+	accessors for PARSED argument.
+
+2004-05-13  Lawrence Mitchell <wence@gmx.li>
+
+	* erc-list.el (erc-chanlist, erc-chanlist-322): Use new accessors
+	for PARSED argument.  Use `erc-server-FOO-functions', not
+	`erc-server-FOO-hook.
+
+2004-05-13  Lawrence Mitchell <wence@gmx.li>
+
+	* erc-ezbounce.el (erc-ezb-notice-autodetect): Use new accessors
+	for PARSED argument.
+	(erc-ezb-initialize): Use `erc-server-FOO-functions', not
+	`erc-server-FOO-hook.
+
+2004-05-13  Lawrence Mitchell <wence@gmx.li>
+
+	* erc-dcc.el: Use `erc-server-FOO-functions', not
+	`erc-server-FOO-hook.
+	(erc-dcc-no-such-nick): Use new accessors for PARSED argument.
+
+2004-05-13  Lawrence Mitchell <wence@gmx.li>
+
+	* erc-bbdb.el (erc-bbdb-whois, erc-bbdb-JOIN, erc-bbdb-NICK): Use
+	new accessors for PARSED argument.
+	(BBDB): Use `erc-server-FOO-functions', not `erc-server-FOO-hook.
+
+2004-05-13  Lawrence Mitchell <wence@gmx.li>
+
+	* erc-autojoin.el (autojoin): Use `erc-server-FOO-functions', not
+	`erc-server-FOO-hook.
+	(erc-autojoin-add, erc-autojoin-remove): Use new accessors for
+	PARSED argument.
+
+2004-05-13  Lawrence Mitchell <wence@gmx.li>
+
+	* erc-autoaway.el (autoaway): Use `erc-server-FOO-functions', not
+	`erc-server-FOO-hook.
+
+2004-05-13  Lawrence Mitchell <wence@gmx.li>
+
+	* erc.el (erc-backend): Require.
+	(erc-disconnected-hook, erc-join-hook, erc-quit-hook)
+	(erc-part-hook, erc-kick-hook): Docstring fix, we now use
+	`erc-server-FOO-functions', rather than `erc-server-FOO-hook'.
+	(erc-event-to-hook-name, erc-event-to-hook): Remove.
+	(erc-once-with-server-event)
+	(erc-once-with-server-event-global): Use `erc-get-hook'
+	(erc-process-filter): Use `erc-parse-server-response'.
+	(erc-cmd-IDLE, erc-cmd-BANLIST, erc-cmd-MASSUNBAN): New accessors
+	for PARSED argument.  Rename all `erc-server-FOO-hook' to
+	`erc-server-FOO-functions'.
+	(erc-server-364-hook, erc-server-365-hook, erc-server-367-hook)
+	(erc-server-368-hook, erc-server-KILL-hook)
+	(erc-server-PONG-hook, erc-server-200-hook, erc-server-201-hook)
+	(erc-server-202-hook, erc-server-203-hook, erc-server-204-hook)
+	(erc-server-205-hook, erc-server-206-hook, erc-server-208-hook)
+	(erc-server-209-hook, erc-server-211-hook, erc-server-212-hook)
+	(erc-server-213-hook, erc-server-214-hook, erc-server-215-hook)
+	(erc-server-216-hook, erc-server-217-hook, erc-server-218-hook)
+	(erc-server-219-hook, erc-server-241-hook, erc-server-242-hook)
+	(erc-server-243-hook, erc-server-244-hook, erc-server-249-hook)
+	(erc-server-261-hook, erc-server-262-hook, erc-server-302-hook)
+	(erc-server-323-hook, erc-server-342-hook, erc-server-351-hook)
+	(erc-server-381-hook, erc-server-382-hook, erc-server-391-hook)
+	(erc-server-392-hook, erc-server-393-hook, erc-server-394-hook)
+	(erc-server-395-hook, erc-server-402-hook, erc-server-404-hook)
+	(erc-server-407-hook, erc-server-409-hook, erc-server-411-hook)
+	(erc-server-413-hook, erc-server-414-hook, erc-server-415-hook)
+	(erc-server-422-hook, erc-server-423-hook, erc-server-424-hook)
+	(erc-server-431-hook, erc-server-436-hook, erc-server-437-hook)
+	(erc-server-441-hook, erc-server-443-hook, erc-server-444-hook)
+	(erc-server-445-hook, erc-server-446-hook, erc-server-451-hook)
+	(erc-server-462-hook, erc-server-463-hook, erc-server-464-hook)
+	(erc-server-465-hook, erc-server-467-hook, erc-server-471-hook)
+	(erc-server-472-hook, erc-server-473-hook, erc-server-483-hook)
+	(erc-server-491-hook, erc-server-502-hook): Remove.
+	(erc-call-hooks, erc-parse-line-from-server): Remove
+	(erc-server-hook-list): Remove.  Remove top-level call too.
+	(erc-server-ERROR, erc-server-INVITE, erc-server-JOIN)
+	(erc-server-KICK, erc-server-MODE, erc-server-NICK)
+	(erc-server-PART, erc-server-PING, erc-server-PONG)
+	(erc-server-PRIVMSG-or-NOTICE, erc-server-QUIT)
+	(erc-server-TOPIC, erc-server-WALLOPS, erc-server-001)
+	(erc-server-004, erc-server-005, erc-server-221, erc-server-252)
+	(erc-server-253, erc-server-254, erc-server-301, erc-server-303)
+	(erc-server-305, erc-server-306, erc-server-311-or-314)
+	(erc-server-312, erc-server-313, erc-server-317, erc-server-319)
+	(erc-server-320, erc-server-321, erc-server-322, erc-server-324)
+	(erc-server-329, erc-server-330, erc-server-331, erc-server-332)
+	(erc-server-333, erc-server-341, erc-server-352, erc-server-353)
+	(erc-server-366, erc-server-MOTD, erc-server-379)
+	(erc-server-401, erc-server-403, erc-server-405, erc-server-406)
+	(erc-server-412, erc-server-421, erc-server-432, erc-server-433)
+	(erc-server-437, erc-server-442, erc-server-461, erc-server-474)
+	(erc-server-475, erc-server-477, erc-server-481, erc-server-482)
+	(erc-server-501): Move to erc-backend.el
+	(erc-auto-query, erc-banlist-store, erc-banlist-finished)
+	(erc-banlist-update, erc-connection-established)
+	(erc-process-ctcp-query, erc-display-server-message): Use new
+	accessors for PARSED argument.
+
+2004-05-13  Lawrence Mitchell <wence@gmx.li>
+
+	* erc-backend.el: (erc-parse-server-response)
+	(erc-handle-parsed-server-response, erc-get-hook)
+	(define-erc-response-handler): New functions.
+	(erc-response): New struct for server responses.
+	(erc-server-responses): New variable.
+	(erc-call-hooks): Move from erc.el and rework.
+	(ERROR, INVITE, JOIN, KICK, MODE, NICK, PART, PING, PONG)
+	(PRIVMSG, NOTICE, QUIT, TOPIC, WALLOPS, 001, MOTD, 376, 004)
+	(252, 253, 254, 250, 301, 303, 305, 306, 311, 312, 313, 315)
+	(317, 318, 319, 320, 321, 322, 324, 329, 330, 331, 332, 333)
+	(341, 352, 353, 366, 369, 379, 401, 403, 405, 406, 412, 421)
+	(432, 433, 437, 442, 461, 474, 477, 481, 482, 501, 323, 221)
+	(002, 003, 371, 372, 374, 375, 422, 251, 255, 256, 257, 258)
+	(259, 265, 266, 377, 378, 314, 475, 364, 365, 367, 368, 381)
+	(382, 391, 392, 393, 394, 395, 200, 201, 202, 203, 204, 205)
+	(206, 208, 209, 211, 212, 213, 214, 215, 216, 217, 218, 219)
+	(241, 242, 243, 244, 249, 261, 262, 302, 342, 351, 402, 404)
+	(407, 409, 411, 413, 414, 415, 423, 424, 431, 436, 441, 443)
+	(444, 445, 446, 451, 462, 463, 464, 465, 467, 471, 472, 473)
+	(483, 491, 502, 005, KILL): Move from erc.el and rework using
+	`define-erc-response-handler' and erc-response struct.
+
+2004-05-12  Diane Murray <disumu@x3y2z1.net>
+
+	* erc.el: A few bug fixes to avoid errors after disconnect,
+	including the "Selecting deleted buffer" bug.
+	(erc-channel-user-op-p, erc-channel-user-voice-p): Make sure NICK
+	is non-nil (`erc-current-nick' can return nil).
+	(erc-server-buffer): Make sure the buffer isn't a #<killed
+	buffer>.
+	(erc-server-buffer-live-p): New function.
+	(erc-display-line, erc-join-channel, erc-prepare-mode-line-format,
+	erc-away-p): Use `erc-server-buffer-live-p' to make sure process
+	buffer exists.
+	(erc-send-current-line): If there is no server buffer, let the
+	user know.
+
+2004-05-12  Diane Murray <disumu@x3y2z1.net>
+
+	* erc.el, erc-log.el: C-c C-l keybinding now defined in
+	erc-log.el.
+	(erc-log-version): New.
+	(erc-cmd-JOIN): Fix applied for bug where /join -invite causes
+	errors when there's no `invitation'.
+
+2004-05-11  Diane Murray <disumu@x3y2z1.net>
+
+	* erc.el: (erc-cmd-JOIN): Make sure `chnl' is non-nil before trying
+	to join anything (chnl is not set if /join -invite is used but
+	there's no `invitation').
+
+2004-05-10  Diane Murray <disumu@x3y2z1.net>
+
+	* erc-log.el: Define C-c C-l keybinding outside of `erc-log-mode',
+	making it available all the time; autoload definition.
+	(erc-log-version): New.
+
+2004-05-09  Diane Murray <disumu@x3y2z1.net>
+
+	* AUTHORS, CREDITS, Makefile, erc-autoaway.el, erc-autojoin.el,
+	erc-button.el, erc-chess.el, erc-dcc.el, erc-ezbounce.el,
+	erc-fill.el, erc-ibuffer.el, erc-imenu.el, erc-lang.el,
+	erc-list.el, erc-log.el, erc-macs.el, erc-match.el, erc-members.el,
+	erc-menu.el, erc-nets.el, erc-netsplit.el, erc-nickserv.el,
+	erc-notify.el, erc-page.el, erc-ring.el, erc-speak.el,
+	erc-speedbar.el, erc-stamp.el, erc-track.el, erc-truncate.el,
+	erc-xdcc.el, erc.el: Applied all relevant bug fixes and code
+	cleanup made between the time of the ERC_4_0_RELEASE tag until now.
+
+2004-05-09  Diane Murray <disumu@x3y2z1.net>
+
+	* erc-menu.el: Updated copyright years.
+
+2004-05-09  Lawrence Mitchell <wence@gmx.li>
+
+	* erc.el (erc-update-channel-info-buffer): Correct bug in sorting
+	of channel users.  Tiny change from Andreas Schwab
+	<schwab@suse.de>.
+
+2004-05-09  Lawrence Mitchell <wence@gmx.li>
+
+	* erc-fill.el (erc-fill-variable): Fix docstring.
+
+2004-05-09  Lawrence Mitchell <wence@gmx.li>
+
+	* erc-button.el (erc-button-add-button): Use 'keymap
+	text-property, rather than 'local-map, since it's cross-emacs
+	compatible.  Pass :mouse-down-action into `widget-convert-button'
+	as 'erc-button-click-button, to make XEmacs happy.  Replace bogus
+	reference to erc-widget-press-button with erc-button-press-button.
+	(erc-button-click-button): New (ignored) first argument, to make
+	XEmacs behave when pressing buttons.
+	(erc-button-press-button): New (ignored) &rest argument.
+
+2004-05-09  Adrian Aichner <adrian@xemacs.org>
+
+	* erc-log.el (erc-conditional-save-buffer): Fix docstring
+	reference to erc-save-queries-on-quit.
+	(erc-conditional-save-queries): Ditto.
+
+2004-05-06  Diane Murray <disumu@x3y2z1.net>
+
+	* erc-speedbar.el: Updated copyright years.  Added local variables
+	for this file; fixed indenting.
+	(erc-speedbar): New group.
+	(erc-speedbar-sort-users-type): New variable.
+	(erc-speedbar-buttons): Handle query buffers (fixes a bug where an
+	error would be thrown if the current buffer was a query).  Ignore
+	unknown buffers.
+	(erc-speedbar-expand-channel): Show limit and key with channel
+	modes. Sort users according to `erc-speedbar-sort-users-type'.
+	(erc-speedbar-insert-user): Fixed bug where only nicks with more
+	info were being listed, and those were shown twice.
+	(erc-speedbar-goto-buffer): Don't use dframe functions, as dframe
+	isn't available with the default speedbar.
+
+2004-05-06  Diane Murray <disumu@x3y2z1.net>
+
+	* erc.el: (erc-sort-channel-users-alphabetically): New function.
+	(erc-server-412, erc-server-432, erc-server-475): New functions.
+	(erc-server-412-hook, erc-server-432-hook, erc-server-475-hook):
+	Use them.
+	(erc-server-401, erc-server-403, erc-server-405)
+	(erc-server-421, erc-server-474, erc-server-481): Use catalog
+	messages.
+	(erc-define-catalog): Added s401, s403, s405, s412, s421, s432,
+	s474, s475, and s481.
+
+2004-05-06  Diane Murray <disumu@x3y2z1.net>
+
+	* erc-nickserv.el: Added documentation to Commentary, Usage.
+	Removed `outline-mode' from file local variables.
+	(erc-services-mode): Use `erc-nickserv-identify-mode' to add
+	hooks.
+	(erc-nickserv-identify-mode): New function.
+	(erc-nickserv-identify-mode): New variable.
+	(erc-prompt-for-nickserv-password, erc-nickserv-passwords):
+	Changed docstring.
+	(erc-nickserv-identify-autodetect): Use
+	`erc-nickserv-call-identify-function'. Docstring change.
+	(erc-nickserv-identify-on-connect,
+	erc-nickserv-identify-on-nick-change,
+	erc-nickserv-call-identify-function): New functions.
+	(erc-nickserv-identify): PASSWORD is not optional.  Autoload
+	function.
+
+2004-05-05  Diane Murray <disumu@x3y2z1.net>
+
+	* erc.el (erc-join-hook, erc-quit-hook, erc-part-hook,
+	erc-kick-hook, erc-connect-pre-hook): Now customizable.
+	(erc-nick-changed-functions): New hook.
+	(erc-server-NICK): Run `erc-nick-changed-functions' with the
+	arguments NEW-NICK and OLD-NICK.
+	(erc-channel-user-voice-p, erc-channel-user-voice-p): Shortened
+	docstring.
+
+2004-05-05  Lawrence Mitchell <wence@gmx.li>
+
+	* HACKING: New section on function/variable naming and coding
+	conventions.
+
+2004-05-05  Lawrence Mitchell <wence@gmx.li>
+
+	* erc.el (erc-wash-quit-reason): Quote regexp special characters
+	in NICK, LOGIN and HOST.
+
+2004-05-04  Diane Murray <disumu@x3y2z1.net>
+
+	* erc.el (erc-server-parameters): Typo fix in docstring.
+	(erc-input-line-position): `:type' is now a choice between integer
+	and nil.  (erc-mode-map): Bind `erc-get-channel-mode-from-keypress'
+	to C-c C-o instead of C-c RET (C-c C-m).  (erc-cmd-GQUIT): Use
+	REASON as argument when calling `erc-cmd-QUIT'.
+
+2004-05-03  Lawrence Mitchell <wence@gmx.li>
+
+	* erc-nicklist.el: Initial version.
+
+2004-04-28  Diane Murray <disumu@x3y2z1.net>
+
+	* erc-menu.el: Added local variables for file, fixed indenting.
+	(erc-menu-version): New variable.
+	(erc-menu-definition): "List channels": New.  "Join channel": Use
+	`erc-connected' as test.  "Start a query": New.  "List channel
+	operators": New.  "Input action": Moved up.  "Set topic": Fixed
+	test so it's only active in channels.  "Leave this channel": Moved
+	down.  "Track hidden channel buffers": Removed.  "Enable/Disable
+	ERC Modules": New.
+
+2004-04-28  Diane Murray <disumu@x3y2z1.net>
+
+	* erc.el (erc-mode-map): Removed binding for
+	`erc-save-buffer-in-logs' (moved to erc-log.el).
+	(erc-cmd-QUERY, erc-cmd-OPS): Now interactive.
+
+2004-04-28  Diane Murray <disumu@x3y2z1.net>
+
+	* erc-log.el: Added local variables for this file.
+	(erc-log-channels-directory): Added directory as a choice in
+	`:type'.
+	(define-erc-module): Define and undefine key binding (C-c
+	C-l) for `erc-save-buffer-in-logs' here.
+
+2004-04-28  Diane Murray <disumu@x3y2z1.net>
+
+	* erc-nets.el: Added local variables for this file.
+	(erc-networks-alist): Fixed `:type' to work better in
+	customization.
+
+2004-04-28  Diane Murray <disumu@x3y2z1.net>
+
+	* erc-match.el: Added local variables for file.  (erc-keywords):
+	Use `list' instead of `cons' in `:type'.  Fixes bug where mismatch
+	was shown in customization.  (erc-current-nick-highlight-type):
+	Escape parentheses in docstring.  Added keyword, nick-or-keyword as
+	options in `:type'.
+
+2004-04-28  Diane Murray <disumu@x3y2z1.net>
+
+	* erc-stamp.el: Added local variables for file.
+	(erc-away-timestamp-format): Allow nil as a choice in `:type'.
+	(erc-timestamp-intangible): Changed `:type' to boolean.
+	(erc-timestamp-right-column): Added `:group' and `:type'.
+
+2004-04-28  Diane Murray <disumu@x3y2z1.net>
+
+	* erc.el (erc-modules): Added bbdb, log, match, sound, and stamp
+	as `:type' options; changed documentation for autojoin, fill,
+	pcomplete, track.  (erc-prompt-for-channel-key): New variable.
+	(erc-join-channel): Only prompt for key if
+	`erc-prompt-for-channel-key' is non-nil.  (erc-format-my-nick): New
+	function.  (erc-send-message, erc-send-current-line): Use it.
+
+2004-04-24  Johan Bockgard <bojohan@users.sourceforge.net>
+
+	* erc-track.el: (erc-track-modified-channels): Fix indentation.
+
+2004-04-24  Johan Bockgard <bojohan@users.sourceforge.net>
+
+	* erc-match.el: (erc-hide-fools): Docstring fix.
+	(erc-log-matches-types-alist): Added `current-nick' to valid
+	choices.
+
+2004-04-20  Diane Murray <disumu@x3y2z1.net>
+
+	* erc-page.el, erc-ezbounce.el, erc-speak.el, erc-match.el,
+	erc-track.el (erc-ezbounce, erc-page, erc-speak): Groups defined.
+	(erc-match, erc-track): `erc' is parent group.
+	(erc-ezb-regexp, erc-ezb-login-alist): Added `:group'.
+
+2004-04-20  Jorgen Schaefer <forcer@users.sourceforge.net>
+
+	* erc-fill.el: Fixed erc-fill-static so it breaks the lines at the
+	right column and respects timestamps. Patch by Simon Siegler
+	<simon@trz-kril.de>
+	(erc-fill-static): Major rewrite and split up into some functions.
+	(erc-count-lines): Removed.
+	(erc-fill-regarding-timestamp): New function.
+	(erc-timestamp-offset): New function.
+	(erc-restore-text-properties): New function.
+	(erc-fill-variable): Respect leftbound timestamp.  This is still
+	broken if someone has both erc-timestamp-only-if-changed-flag set
+	and erc-insert-timestamp-function set to
+	'erc-insert-timestamp-left, but otherwise it works now.
+
+2004-04-20  Diane Murray <disumu@x3y2z1.net>
+
+	* erc.el: (erc-cmd-SV): Show features gtk, mac-carbon, multi-tty.
+	Fixed so that arguments fit the format (build date was not being
+	shown).
+
+2004-04-19  Lawrence Mitchell <wence@gmx.li>
+
+	* erc.el: (erc-update-channel-topic); Error if `channel-topic' is
+	unbound.  Remove %-sign substitution.
+	(erc-update-mode-line-buffer): Escape %-signs in `channel-topic'
+	here.
+
+2004-04-19  Diane Murray <disumu@x3y2z1.net>
+
+	* erc.el: (erc-send-action, erc-ctcp-query-ACTION,
+	erc-ctcp-reply-ECHO-hook): Let `erc-display-message-highlight'
+	propertize the message.
+	(erc-display-message-highlight): Allow for any erc-TYPE-face.
+	(erc-cmd-JOIN): Display error message instead of throwing an error
+	if there's no `invitation'.
+	(erc-cmd-PART): Allow for no reason if channel is provided.  Fixes
+	bug where user would part the current channel with the other
+	channel's name as reason when no reason was given.
+	(erc-server-vectors, erc-debug-missing-hooks): Added docstring.
+	(erc-server-JOIN): Moved `erc-join-hook' to JOIN-you section.
+	`erc-join-hook' called by `run-hook-with-args', sending the ARGS
+	`chnl' and the channel's buffer.  Changed an instance of if
+	without else to when.
+	(erc-server-477): New function.
+	(erc-server-477-hook): Use `erc-server-477'.
+	(erc-define-catalog): Added `no-invitation'.
+
+2004-04-14  Diane Murray <disumu@x3y2z1.net>
+
+	* erc-nickserv.el: Local variables for file added.
+	(erc-nickserv-passwords): Customization: Network symbols updated
+	to reflect `erc-nickserv-alist'.  Allow user to type in network
+	symbol.
+	(erc-nickserv-alist): Now customizable variable.
+
+2004-04-09  Diane Murray <disumu@x3y2z1.net>
+
+	* erc-autoaway.el (erc-autoaway-reset-idletime): Make sure `line'
+	is a string to avoid errors upon startup.
+
+2004-04-06  Diane Murray <disumu@x3y2z1.net>
+
+	* erc-autoaway.el (erc-autoaway-version): New variable.
+	(erc-auto-discard-away): Updated docstring.
+	(erc-autoaway-no-auto-back-regexp): New variable.
+	(erc-autoaway-reset-idletime): Use it.	Hopefully a better solution
+	which allows for aliases to "/away" and any other text that the
+	user wants to ignore when `erc-auto-discard-away' is non-nil.
+
+2004-04-06  Diane Murray <disumu@x3y2z1.net>
+
+	* erc-autoaway.el (erc-autoaway-reset-idletime): Forgot /gaway in
+	regexp.
+
+2004-04-06  Diane Murray <disumu@x3y2z1.net>
+
+	* erc-autoaway.el (erc-autoaway-reset-idletime): If the user sends
+	an "/away" command, don't call `erc-autoaway-set-back', fixes bug
+	where ERC would send "/away" when user was already away and sent an
+	"/away reason".  Changed `l' to `line' for better understanding.
+	(erc-autoaway-set-back): Changed `l' to `line' for better
+	understanding.
+
+2004-04-05  Diane Murray <disumu@x3y2z1.net>
+
+	* erc.el (erc-set-channel-key): Now able to remove key.
+	(erc-set-channel-limit): Now able to remove limit.
+	(erc-get-channel-mode-from-keypress): Fixed docstring.
+
+2004-04-04  Diane Murray <disumu@x3y2z1.net>
+
+	* erc.el (erc-join-channel): Allow for optional channel key.
+	(erc-set-modes): Need to set `channel-key' to nil in case of mode
+	changes during split.
+	(erc-show-channel-key-p): New variable.
+	(erc-prepare-mode-line-format): Only show key if
+	`erc-show-channel-key-p' is non-nil.
+
+2004-04-04  Diane Murray <disumu@x3y2z1.net>
+
+ 	* erc.el (channel-key): New variable.
+	(erc-update-channel-key): New function.
+	(erc-set-modes, erc-parse-modes, erc-update-modes, erc,
+	erc-update-channel-info-buffer): Deal with channel keys.
+	(erc-prepare-mode-line-format): Show channel key in header-line.
+	(erc-server-NICK): Show nick change in server buffer as well.
+	(erc, erc-send-command, erc-banlist-store, erc-banlist-update,
+	erc-load-irc-script-lines,
+	erc-arrange-session-in-multiple-windows, erc-handle-login,
+	erc-find-channel-info-buffer): Changed when not to unless.
+	(erc-server-MODE): Changed if without else to when.
+
+2004-03-27  Adrian Aichner <adrian@xemacs.org>
+
+	* erc.el: (erc-cmd-BANLIST): Use `truncate-string-to-width'
+	instead of `truncate-string' alias.
+	(erc-nickname-in-use): Ditto.
+
+2004-03-27  Francis Litterio <franl@users.sourceforge.net>
+
+	* erc-list.el (erc-cmd-list): Fixed error caused by erc-cmd-LIST
+	passing a non-sequence to erc-chanlist.
+
+2004-03-22  Jeremy Bertram Maitin-Shepard <jbms@gentoo.org>
+
+	* erc.el: Add new hook `erc-join-hook', which is run when we join a
+	channel.
+
+2004-03-22  Jeremy Bertram Maitin-Shepard <jbms@gentoo.org>
+
+	* erc.el: Replaced existing notice user notification system and
+	the configuration options, which consisted of
+	`erc-echo-notices-in-minibuffer-flag' and
+	`erc-echo-notices-in-current-buffer' with two new hooks,
+	`erc-echo-notice-hook' and `erc-echo-notice-always-hook'.
+
+	When user notification is needed, `erc-echo-notice-always-hook' is
+	first run using `run-hook-with-args', then `erc-echo-notice-hook'
+	is run using `run-hook-with-args-until-success'.
+
+	In addition to these hooks, a large number of functions, which are
+	described in the documentation strings of those hooks, were added
+	which can be used to achieve a large variety of different
+	behaviors.
+
+	The current default behavior, which is identical to the existing
+	default behavior, is for `erc-echo-notice-always-hook' to be set to
+	`(erc-echo-notice-in-default-buffer).
+
+2004-03-21  Diane Murray <disumu@x3y2z1.net>
+
+	* erc-track.el: (erc-modified-channels-display): Added a space
+	before opening bracket.
+
+2004-03-21  Diane Murray <disumu@x3y2z1.net>
+
+	* erc.el: (erc-format-query-as-channel-p): New variable.
+	(erc-server-PRIVMSG-or-NOTICE): If `erc-format-query-as-channel-p'
+	is nil, messages in the query buffer are formatted like private
+	messages.
+
+	(erc-server-252-hook, erc-server-253-hook, erc-server-254-hook,
+	erc-server-256-hook, erc-server-257-hook, erc-server-258-hook,
+	erc-server-259-hook, erc-server-371-hook, erc-server-372-hook,
+	erc-server-374-hook, erc-server-374-hook, erc-server-442-hook,
+	erc-server-477-hook): Removed, now defined in
+	`erc-server-hook-list'.
+	(erc-display-server-message): New function.
+	(erc-server-252, erc-server-253, erc-server-254, erc-server-442):
+	New functions.
+	(erc-server-hook-list): Added 250, 256, 257, 258, 259, 265, 266,
+	377, 378, 477 - using `erc-display-server-message'.  251, 255 now
+	use `erc-display-server-message'.  Added 252, 253, 254, 442 -
+	using respective erc-server-* functions.  371, 372, 374, 375 now
+	defined here.
+	(erc-define-catalog): Added s252, s253, s254, s442.
+	(erc-server-001, erc-server-004, erc-server-005): Fixed
+	documentation.
+
+2004-03-20  Diane Murray <disumu@x3y2z1.net>
+
+	* erc-stamp.el: Commentary: Changed `erc-stamp-mode' to
+	`erc-timestamp-mode'.
+	(erc-insert-timestamp-left): Use `erc-timestamp-face' on filler
+	spaces as well.
+
+2004-03-19  Diane Murray <disumu@x3y2z1.net>
+
+	* erc.el (erc-send-action): Use `erc-input-face'.
+	(erc-display-message-highlight): If the requested highlighting
+	type doesn't match, just display the string with no highlighting
+	and warn about it with `erc-log'.. (erc-cmd-JOIN): If user is
+	already on the requested channel, switch to that channel's buffer.
+	(erc-ctcp-query-ACTION): Use `erc-action-face' for nick as well.
+	(erc-header-line-use-help-echo-p): New variable.
+	(erc-update-mode-line-buffer): Use `help-echo' for header-line if
+	`erc-header-line-use-help-echo-p' is non-nil.
+
+2004-03-18  Adrian Aichner <adrian@xemacs.org>
+
+	* erc-nets.el: Use two arguments version of `make-obsolete', if
+	third argument is not supported (for XEmacs).
+
+2004-03-18  Andreas Fuchs <asf@void.at>
+
+	* CREDITS: added CREDITS entry for Adrian Aichner
+
+2004-03-18  Andreas Fuchs <asf@void.at>
+
+	* erc-xdcc.el, erc.el, erc-autoaway.el, erc-autojoin.el,
+	erc-button.el, erc-dcc.el, erc-ezbounce.el, erc-imenu.el,
+	erc-list.el, erc-log.el, erc-match.el, erc-members.el,
+	erc-menu.el, erc-netsplit.el, erc-notify.el, erc-speedbar.el,
+	erc-stamp.el, erc-track.el, erc-truncate.el:
+	(erc-coding-sytem-for-target): Removed.
+	(erc-coding-system-for-target): New.
+	(erc-autoaway-use-emacs-idle): Typo fix.
+	(erc-auto-set-away): Ditto.
+	(erc-auto-discard-away): Ditto.
+	(autojoin): Ditto.
+	(erc-button-alist): Ditto.
+	(erc-dcc-auto-masks): Ditto.
+	(erc-dcc-chat-send-input-line): Ditto.
+	(erc-ezb-get-login): Ditto.
+	(erc-unfill-notice): Ditto.
+	(erc-save-buffer-in-logs): Ditto.
+	(match): Ditto.
+	(erc-log-matches-types-alist): Ditto.
+	(erc-match-directed-at-fool-p): Ditto.
+	(erc-match-message): Ditto.
+	(erc-update-member): Ditto.
+	(erc-ignored-reply-p): Ditto.
+	(erc-menu-definition): Ditto.
+	(erc-netsplit-QUIT): Ditto.
+	(erc-notify-list): Ditto.
+	(erc-speedbar-update-channel): Ditto.
+	(erc-speedbar-item-info): Ditto.
+	(erc-stamp): Ditto.
+	(erc-timestamp-intangible): Ditto.
+	(erc-add-timestamp): Ditto.
+	(erc-timestamp-only-if-changed-flag): Ditto.
+	(erc-show-timestamps): Ditto.
+	(erc-track-priority-faces-only): Ditto.
+	(erc-modified-channels-alist): Ditto.
+	(erc-unique-substrings): Ditto.
+	(erc-find-parsed-property): Ditto.
+	(erc-track-switch-direction): Ditto.
+	(erc-truncate-buffer-to-size): Ditto.
+	(erc-xdcc): Ditto.
+	(erc-auto-reconnect): Ditto.
+	(erc-startup-file-list): Ditto.
+	(erc-once-with-server-event): Ditto.
+	(erc-once-with-server-event-global): Ditto.
+	(erc-mode): Ditto.
+	(erc-generate-new-buffer-name): Ditto.
+	(erc): Ditto.
+	(erc-open-ssl-stream): Ditto.
+	(erc-default-coding-system): Ditto.
+	(erc-encode-string-for-target): Ditto.
+	(erc-decode-string-from-target): Ditto.
+	(erc-scroll-to-bottom): Ditto.
+	(erc-decode-controls): Ditto.
+	(erc-channel-members-changed-hook): Ditto.
+	(erc-put-text-property): Ditto.
+	(erc-add-default-channel): Ditto.
+
+2004-03-17  Diane Murray <disumu@x3y2z1.net>
+
+	* erc.el (erc-process-sentinel): Cancel ping timer upon
+	disconnect.
+	(erc-cmd-PART): Use same regexp as `erc-cmd-QUIT' when no #channel
+	is provided.
+	(erc-nick-uniquifier, erc-manual-set-nick-on-bad-nick-p): `:group'
+	was missing, added.
+	(erc-part-reason-zippy, erc-part-reason-zippy): Removed FIXME
+	comments.  I see no problem allowing typed in reasons.
+
+2004-03-16  Diane Murray <disumu@x3y2z1.net>
+
+	* erc-stamp.el: (erc-insert-timestamp-left): Added support for
+	`erc-timestamp-only-if-changed-flag' and added docstring.
+	(erc-timestamp-only-if-changed-flag): Updated documentation.
+
+2004-03-13  Francis Litterio <franl@users.sourceforge.net>
+
+	* erc-nets.el (erc-network-name): No longer marked as obsolete.
+	Why was this function made obsolete?  There is no other function
+	that performs this task.  Some of us use these functions in our
+	personal ERC configs.
+
+2004-03-12  Lawrence Mitchell <wence@gmx.li>
+
+	* erc.el (erc-buffer-filter): Use `with-current-buffer'.
+	(erc-process-input-line): Append newline to documentation.  Fixes a
+	bug whereby the prompt would be put on the same line as the output.
+	(erc-cmd-GQUIT): Only try and send QUIT if the process is alive.
+
+2004-03-12  Lawrence Mitchell <wence@gmx.li>
+
+	* erc-log.el: Only add top-level hooks if `erc-enable-logging' is
+	non-nil.
+
+2004-03-10  Damien Elmes <erc@repose.cx>
+
+	* erc-nets.el: From Adrian Aichner (adrian /at/ xemacs /dot/ org)
+	* erc-nets.el: XEmacs make-obsolete only takes two arguments.
+
+2004-03-10  Diane Murray <disumu@x3y2z1.net>
+
+	* erc-nets.el (erc-determine-network): Use `erc-session-server' if
+	`erc-announced-server' is nil to avoid error if server does not
+	send 004 (RPL_MYINFO) message.
+
+2004-03-10  Lawrence Mitchell <wence@gmx.li>
+
+	* erc-nets.el (erc-server-alistm erc-settings): Use lowercase
+	"freenode", as in `erc-networks-alist'.
+
+2004-03-10  Lawrence Mitchell <wence@gmx.li>
+
+	* erc-nickserv.el (erc-nickserv-alist): Use lowercase "freenode",
+	as in `erc-networks-alist'.
+
+2004-03-10  Lawrence Mitchell <wence@gmx.li>
+
+	* erc-dcc.el (pcomplete/erc-mode/DCC): Append "send" as a list.
+
+2004-03-10  Francis Litterio <franl@users.sourceforge.net>
+
+	* erc-nets.el (erc-networks-alist): Changed "Freenode" to
+	"freenode".
+
+2004-03-10  Francis Litterio <franl@users.sourceforge.net>
+
+	* erc-list.el (erc-cmd-LIST): Improved the docstring.	Made
+	message to user more accurate	depending on whether a single
+	channel is being listed or not.
+
+2004-03-10  Lawrence Mitchell <wence@gmx.li>
+
+	* erc-nets.el (erc-determine-network): Make matching logic simpler
+	(suggested by Damian Elmes).
+	(erc-current-network, erc-network-name): Add `make-obsolete' form.
+	(erc-set-network-name): Indentation fix.
+	(erc-ports-list): Add docstring.  Rework function body to use
+	`nconc'.
+
+2004-03-09  Diane Murray <disumu@x3y2z1.net>
+
+	* erc-list.el, erc-notify.el: (require 'erc-nets): added
+
+2004-03-08  Diane Murray <disumu@x3y2z1.net>
+
+	* erc.el (erc-network-name): Function definition moved to
+	erc-nets.el.  The functions `erc-determine-network' and
+	`erc-network' in erc-nets.el do what this did before.  Deprecated.
+	Use (erc-network) instead.
+
+2004-03-08  Diane Murray <disumu@x3y2z1.net>
+
+	* erc-nickserv.el: Changed copyright notice.  Now require
+	erc-nets.  erc-nets.el now takes care of network-related functions
+	and variables.
+	(erc-nickserv-alist): Changed network symbols to match those in
+	`erc-networks-alist' in erc-nets.el.
+	(erc-nickserv-identify-autodetect): Use `erc-network'.
+	(erc-nickserv-identify): Use `erc-network'.  Changed wording for
+	interactive use, now shows current nick.
+	(erc-networks): Removed.  Use `erc-networks-alist' as defined in
+	erc-nets.el.
+	(erc-current-network): Function definition moved to erc-nets.el.
+	The functions `erc-determine-network' and `erc-network' in
+	erc-nets.el do what this did before.  Deprecated.  Use
+	(erc-network) instead.
+
+2004-03-08  Diane Murray <disumu@x3y2z1.net>
+
+	* erc-nets.el: Added commentary, `erc-nets-version'.
+	(erc-server-alist): Changed Brasnet to BRASnet.
+	(erc-networks-alist): All networks (except EFnet and IRCnet) now
+	have a MATCHER.  (erc-network): New variable.
+	(erc-determine-network): New function. Determine the network the
+	user is on.  Use the server parameter NETWORK, if provided, else
+	parse the server name and search for a match (regexp and loop by
+	wencem) in `erc-networks-alist'.  Return the name of the network
+	or "Unknown" as a symbol.
+	(erc-network): New function.  Returns value of `erc-network'.  Use
+	this when the current buffer is not the server process buffer.
+	(erc-current-network): Returns the value of `erc-network' as
+	expected by users who used the function as it was defined in
+	erc-nickserv.el.  Deprecated.
+	(erc-network-name): Returns the value of `erc-network' as expected
+	by users who used the function as it was defined in erc.el.
+	Deprecated.
+	(erc-set-network-name): New function.  Added to
+	`erc-server-375-hook' and `erc-server-422-hook'.
+	(erc-unset-network-name): New function.  Added to
+	`erc-disconnected-hook'.
+	(erc-server-select): Small documentation word change.
+
+2004-03-07  Diane Murray <disumu@x3y2z1.net>
+
+	* AUTHORS, CREDITS: disumu info updated
+
+2004-03-06  Lawrence Mitchell <wence@gmx.li>
+
+	* erc-list.el (erc-cmd-LIST): Take &rest rather than &optional
+	arguments.
+	(erc-chanlist): Construct correct LIST command from list of
+	channels.
+
+2004-03-06  Lawrence Mitchell <wence@gmx.li>
+
+	* erc.el (erc-update-mode-line-buffer): Add 'help-echo property to
+	header-line text.  This allows header lines longer than the width
+	of the current window to be seen.
+
+2004-03-06  Jorgen Schaefer <forcer@users.sourceforge.net>
+
+	* erc-match.el (erc-match-directed-at-fool-p): Also check for
+	"FOOL, "
+
+2004-03-06  Jorgen Schaefer <forcer@users.sourceforge.net>
+
+	* erc-match.el (erc-match-message): Only use nick-or-keyword if
+	we're matching our nick.
+
+2004-03-06  Jorgen Schaefer <forcer@users.sourceforge.net>
+
+	* erc-match.el: The highlight type for the current nickname can
+	now also be 'nick-or-keyword, to highlight the nick of the sender
+	if that is available, but fall back to highlighting your nickname
+	in the whole message otherwise.
+	(erc-current-nick-highlight-type): Adapted docstring accordingly.
+	(erc-match-message): Added new condition. Also added some comments
+	to this monster of a function.
+
+2004-03-06  Jorgen Schaefer <forcer@users.sourceforge.net>
+
+	* erc.el (erc-is-valid-nick-p): Don't check for length less or
+	equal to 9.
+
+2004-03-06  Damien Elmes <erc@repose.cx>
+
+	* erc-nickserv.el (erc-current-network): the last change resulted
+	in this function failing when a network identifies itself as
+	anything other than var.netname.com, so for instance
+	'vic.au.austnet.org' fails. This version is only a marginal
+	improvement over the original, but if we want to be more flexible
+	we'll probably have to do the iteration ourselves instead of using
+	assoc.
+
+2004-03-05  Diane Murray <disumu@x3y2z1.net>
+
+	* erc.el: Added erc-server-001 which runs when the server sends
+	its welcome message.  It sets the current-nick to reflect the
+	server's settings. This fixes a bug where nicks that were too long
+	and got truncated by ther server were still set to the old value.
+	(nickname-in-use): If user wants to try again manually, let user
+	know that the nick is taken.  If not, go through erc-default-nicks
+	until none are left, and then try one last time with
+	erc-nick-uniquifier.  If it's still a bad-nick, make the user
+	change nick manually.  When applying uniquifier, use NICKLEN if
+	it's in the server parameters, otherwise use what RFC 2812 says is
+	the max nick length (9 chars).  Added custom variable
+	erc-manual-set-nick-on-bad-nick-p, which is set to nil and
+	erc-nick-change-attempt-count.  Reset erc-default-nicks and
+	erc-nick-change-attempt-count when the nick has been changed
+	successfully.  This fixes the bug where ERC would get caught in a
+	neverending loop of trying to set the same nick if the nick was
+	too long and the uniquified nick was not available.
+
+	* added erc-cmd-WHOAMI
+
+	* added custom variable erc-mode-line-away-status-format, use this
+	instead of   the previous hard-coded setting
+
+	* erc-server-315|318|369-hook defvar lines removed - they're
+	already defined in erc-server-hook-list
+
+2004-03-04  Lawrence Mitchell <wence@gmx.li>
+
+	* HACKING: Initial commit.  Some thoughts on coding standards.
+
+2004-03-03  Diane Murray <disumu@x3y2z1.net>
+
+	* erc-track.el: added the variable erc-track-priority-faces-only
+	which adds the option to ignore changes in a channel unless there
+	are faces from the erc-track-faces-priority-list in the message
+	options are nil, 'all, or a list of channel name strings
+
+2004-03-01  Diane Murray <disumu@x3y2z1.net>
+
+	* erc.el, erc-ibuffer.el, erc-menu.el: Changed erc-is-channel-op
+	and erc-is-channel-voice to erc-channel-user-op-p and
+	erc-channel-user-voice-p to better match erc-channel-user
+	structure (and emacs lisp usage)
+
+2004-03-01  Diane Murray <disumu@x3y2z1.net>
+
+	* erc.el, erc-ibuffer.el, erc-menu.el:
+	erc-track-modified-channels-mode is now erc-track-mode
+
+2004-02-29  Diane Murray <disumu@x3y2z1.net>
+
+	* erc-match.el: Added 'keyword option to
+	erc-current-nick-highlight-type highlights all instances of
+	current-nick in the message ('nickname option in cvs revisions 1.9
+	- 1.11 had same effect)
+
+2004-02-28  Jorgen Schaefer <forcer@users.sourceforge.net>
+
+	* erc-button.el: Add Lisp: prefix for the EmacsWiki Elisp area.
+	(erc-button-alist): Added Lisp: prefix.
+	(erc-emacswiki-lisp-url): New variable.
+	(erc-browse-emacswiki-lisp): New function.
+
+2004-02-27  Lawrence Mitchell <wence@gmx.li>
+
+	* erc.el (erc-get-arglist): Use `substitute-command-keys', rather
+	than hard-coding C-h f for `describe-function'.
+
+2004-02-26  Johan Bockgard <bojohan@users.sourceforge.net>
+
+	* erc-log.el (erc-save-buffer-in-logs): bind `inhibit-read-only'
+	to t around call to `erase-buffer'.
+
+2004-02-23  Edward O'Connor <ted@oconnor.cx>
+
+	* erc-chess.el, erc-dcc.el, erc-ezbounce.el, erc-list.el,
+	erc-macs.el, erc-ring.el, erc-stamp.el, erc.el: Normalized buffer
+	local variable creation.
+
+2004-02-17  Lawrence Mitchell <wence@gmx.li>
+
+	* erc.el (erc-scroll-to-bottom, erc-add-scroll-to-bottom): Mention
+	`erc-input-line-position' in docstring.
+
+2004-02-13  Jorgen Schaefer <forcer@users.sourceforge.net>
+
+	* erc.el (erc-kick-hook): Typo fix.
+
+2004-02-13  Jeremy Bertram Maitin-Shepard <jbms@gentoo.org>
+
+	* erc.el: Added `erc-kick-hook', which is called when the local
+	user is kicked from a channel.  Fixed a bug in `erc-cmd-OPS', such
+	that the command now works.  Added `erc-remove-channel-users', in
+	order to fix a number of significant bugs relating to channel
+	parting.
+
+2004-02-12  Jorgen Schaefer <forcer@users.sourceforge.net>
+
+	* erc.el (erc-display-prompt): Remove last change. This caused a
+	lot of trouble :(
+
+2004-02-12  Jorgen Schaefer <forcer@users.sourceforge.net>
+
+	* erc.el (erc-display-prompt): Also set 'field property, so C-j
+	works on an empty prompt.
+
+2004-02-12  Lawrence Mitchell <wence@gmx.li>
+
+	* erc.el (erc-update-channel-topic): Ensure that `channel-topic'
+	does not contain any bare format controls.
+
+2004-02-10  Jorgen Schaefer <forcer@users.sourceforge.net>
+
+	* erc-stamp.el (erc-timestamp-intangible): New variable (user
+	feature request)
+	(erc-format-timestamp): Use erc-timestamp-intangible.
+
+2004-02-07  Jeremy Bertram Maitin-Shepard <jbms@gentoo.org>
+
+	* erc-button.el: Fixed bug related to nickname buttonizing and text
+	fields due to erc-stamp.
+
+2004-02-07  Jeremy Bertram Maitin-Shepard <jbms@gentoo.org>
+
+	* CREDITS: Added mention of my change of ERC to use hash tables.
+
+2004-02-07  Jeremy Bertram Maitin-Shepard <jbms@gentoo.org>
+
+	* AUTHORS: Added myself to the list.
+
+2004-02-05  Lawrence Mitchell <wence@gmx.li>
+
+	* erc.el: From Jeremy Maitin-Shepard <jbms@attbi.com>:
+	(erc-remove-channel-user): Use `delq' not `delete'.
+	(erc-get-buffer): Pass PROC through to `erc-buffer-filter'.
+	(erc-process-sentinel): Use `erc' rather than `erc-reconnect' for
+	auto-reconnection.
+
+2004-02-02  Lawrence Mitchell <wence@gmx.li>
+
+	* erc.el: (erc-buffer-list-with-nick): Apply `erc-downcase' NICK.
+
+2004-01-30  Alex Schroeder <alex@gnu.org>
+
+	* erc.el: (erc-get-buffer): Use erc-buffer-filter.
+
+2004-01-30  Johan Bockgard <bojohan@users.sourceforge.net>
+
+	* erc.el: From jbms: (erc-get-channel-nickname-list): New function.
+	(erc-get-server-nickname-list): New function.
+	(erc-get-server-nickname-alist): New function.
+	(erc-get-channel-nickname-alist): New function.
+
+2004-01-30  Johan Bockgard <bojohan@users.sourceforge.net>
+
+	* erc-match.el: (erc-add-entry-to-list,
+	erc-remove-entry-from-list): Use `erc-member-ignore-case' to
+	compare entries.
+	(erc-add-pal, erc-add-fool): Fix type bug. Use
+	`erc-get-server-nickname-alist'.
+
+2004-01-29  Johan Bockgard <bojohan@users.sourceforge.net>
+
+	* erc.el: From jbms: Adds xemacs compatibility to hash table
+	channel-members patch.
+
+2004-01-29  Johan Bockgard <bojohan@users.sourceforge.net>
+
+	* erc.el: (erc-update-undo-list): Rewritten. Update
+	buffer-undo-list in place.  Deal with XEmacsesque
+	entries (extents) in the list.
+	(erc-channel-users): Fix unescaped open-paren in left column in
+	docstring.
+
+2004-01-29  Johan Bockgard <bojohan@users.sourceforge.net>
+
+	* erc-ring.el: (erc-replace-current-command): Exclude the prompt
+	from the deleted region and don't redisplay the prompt (because
+	`erc-display-prompt' flushes `buffer-undo-list').
+
+2004-01-29  Johan Bockgard <bojohan@users.sourceforge.net>
+
+	* erc-match.el: (erc-add-entry-to-list): Use `symbol-value' instead
+	of `eval'.
+
+2004-01-28  Jorgen Schaefer <forcer@users.sourceforge.net>
+
+	* erc.el: (erc-kill-buffer-function): maphash was missing an
+	argument.
+
+2004-01-28  Jorgen Schaefer <forcer@users.sourceforge.net>
+
+	* Makefile, erc-autoaway.el, erc-button.el, erc-ibuffer.el,
+	erc-lang.el, erc-list.el, erc-match.el, erc-menu.el, erc-page.el,
+	erc-pcomplete.el, erc-speedbar.el, erc.el: HUGE change by jbms.
+	This makes channel-members a hash, erc-channel-users.
+
+	Modified files: Makefile erc-autoaway.el erc-button.el
+	erc-ibuffer.el erc-lang.el erc-list.el erc-match.el erc-menu.el
+	erc-page.el erc-pcomplete.el erc-speedbar.el erc.el
+
+	The changes are too numerous to document properly. Have fun with
+	the breakage.
+
+2004-01-27  Jorgen Schaefer <forcer@users.sourceforge.net>
+
+	* erc.el: (erc-send-input-line): Add a space to empty lines so the
+	server likes them.
+
+2004-01-25  Jorgen Schaefer <forcer@users.sourceforge.net>
+
+	* erc.el: erc-send-whitespace-lines: New variable.
+	(erc-send-current-line): Use erc-send-whitespace-lines. Also,
+	removed superflous test for empty line in the mapc, since the
+	blank line test should find all. I do like to be able to send an
+	empty line when i want to!
+	(erc-send-current-line): Check for point being in input line
+	before checking for blank lines.
+
+2004-01-21  Lawrence Mitchell <wence@gmx.li>
+
+	* erc.el: (erc-display-line-1): Move `erc-update-undo-list' outside
+	`save-restriction'.  Removing need for temporary variable.
+	(erc-send-current-line): Fix bug introduced by last change, remove
+	complement in blank line regexp.
+
+2004-01-20  Lawrence Mitchell <wence@gmx.li>
+
+	* erc.el: (erc-update-undo-list): Add logic to catch the case when
+	`buffer-undo-list' is t, indentation cleanup.
+	(erc-send-current-line):  Reverse logic for matching blank lines.
+
+2004-01-20  Lawrence Mitchell <wence@gmx.li>
+
+	* erc.el (erc-input-line-position): New variable.  If non-nil,
+	specifies the argument to `recenter' in `erc-scroll-to-bottom'.
+	(erc-scroll-to-bottom): Use it.
+
+2004-01-20  Lawrence Mitchell <wence@gmx.li>
+
+	* erc.el: From Johan Bockgård <bojohan+news@dd.chalmers.se>:
+	(erc-update-undo-list): New function.  Update `buffer-undo-list'
+	so that calling `undo' in an ERC buffer doesn't mess up the
+	existing text.
+	(erc-display-line-1): Use it.
+
+2004-01-19  Lawrence Mitchell <wence@gmx.li>
+
+	* erc.el (erc-beg-of-input-line): Use `forward-line' rather than
+	`beginning-of-line'.  Docstring fix.
+	(erc-end-of-input-line): Docstring fix.
+
+2004-01-13  Jorgen Schaefer <forcer@users.sourceforge.net>
+
+	* erc.el (erc-display-prompt): Remove the undo list after
+	displaying the prompt, so the user can't undo ERC changes, which
+	breaks some stuff anyways. This way the user can still undo his
+	editing, but not ours.
+
+2004-01-12  Jorgen Schaefer <forcer@users.sourceforge.net>
+
+	* erc.el (erc-scroll-to-bottom): Should recenter on the bottom
+	line, not the second-to-last one.
+
+2004-01-12  Lawrence Mitchell <wence@gmx.li>
+
+	* erc.el: (erc-bol): Fix bug introduced in revision 1.601.
+
+2004-01-12  Lawrence Mitchell <wence@gmx.li>
+
+	* erc.el: From Brian Palmer <bpalmer@gmail.com>
+	(erc-cmd-JOIN): Use `erc-member-ignore-case', rather than
+	`member-ignore-case'.
+
+2004-01-12  Jorgen Schaefer <forcer@users.sourceforge.net>
+
+	* erc.el: There was an inconsistency where the values of op and
+	voice in channel-names could be 'on or 'off after an update, t and
+	nil before.  The intended version was to have t or nil, so i fixed
+	it to do so.
+	(channel-names): Updated docstring.
+	(erc-update-current-channel-member): Clarified docstring, fixed so
+	it sets t or nil on an update as well, not only on an add.
+	(erc-cmd-OPS): Updated not to check for 'on (the only function that
+	did this!)
+
+2004-01-12  Lawrence Mitchell <wence@gmx.li>
+
+	* erc.el (erc-part-reason-various-alist,
+	erc-update-mode-line-buffer): Fix docstring
+
+2004-01-11  Lawrence Mitchell <wence@gmx.li>
+
+	* erc.el (erc-update-mode-line): Fix typo.
+
+2004-01-11  Lawrence Mitchell <wence@gmx.li>
+
+	* erc.el (erc-prompt-interactive-input): Removed.
+	(erc-display-prompt): Removed `erc-prompt-interactive-input'
+	option.  (erc-interactive-input-map): Removed.
+
+	Major docstring fixes.
+
+2004-01-07  Francis Litterio <franl@users.sourceforge.net>
+
+	* erc.el (erc-cmd-OPS): Added this function.
+	(erc-cmd-IDLE): Switched from using erc-display-message-highlight
+	to erc-make-notice.
+
+2004-01-07  Francis Litterio <franl@users.sourceforge.net>
+
+	* erc-list.el (erc-cmd-LIST): Switched from using
+	erc-display-message-highlight to erc-make-notice.
+
+2004-01-07  Francis Litterio <franl@users.sourceforge.net>
+
+	* erc.el (erc-once-with-server-event): Added a sentence to the
+	docstring.  Now returns the uninterned symbol that is added to the
+	server hook.
+	(erc-cmd-IDLE): Changed to use erc-once-with-server-event instead
+	of erc-once-with-server-event-global.
+
+2004-01-06  Francis Litterio <franl@users.sourceforge.net>
+
+	* erc-list.el (erc-chanlist-hide-modeline): New variable.
+	(erc-chanlist): Now displays message as a notice.  Also hides the
+	modeline if erc-chanlist-hide-modeline is non-nil.
+
+2004-01-05  Francis Litterio <franl@users.sourceforge.net>
+
+	* erc.el (erc-server-PRIVMSG-or-NOTICE): Now nicks appear as
+	<nick> in query buffers, instead of as *nick*.
+
+2004-01-03  Francis Litterio <franl@users.sourceforge.net>
+
+	* erc.el (erc-once-with-server-event-global): Changed to return
+	the uninterned symbol that it creates.
+	(erc-cmd-LIST): Changed to clean up hooks that don't run.
+
+2004-01-03  Francis Litterio <franl@users.sourceforge.net>
+
+	* erc-pcomplete.el (pcomplete/erc-mode/IDLE): Added to support new
+	/IDLE command.
+
+2004-01-03  Francis Litterio <franl@users.sourceforge.net>
+
+	* erc.el (erc-once-with-server-event-global): New function.  Like
+	erc-once-with-server-event, except it modifies the global value of
+	the event hook.
+	(erc-cmd-IDLE): New function.  Implements the new /IDLE command.
+	Usage: /IDLE NICK (erc-seconds-to-string): New function.  Converts
+	a number of seconds to an Engligh phrase.
+
+2004-01-02  Francis Litterio <franl@users.sourceforge.net>
+
+	* erc-list.el: Added variable erc-chanlist-mode-hook.
+
+See ChangeLog.2003 for earlier changes.
+
+    Copyright (C) 2004 Free Software Foundation, Inc.
+  Copying and distribution of this file, with or without modification,
+  are permitted provided the copyright notice and this notice are preserved.
+
+;; Local Variables:
+;; coding: utf-8
+;; End:
+
+;; arch-tag: cc606d2d-635b-4b36-829b-a50e3c51e2d1
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lisp/erc/ChangeLog.2005	Wed Feb 01 10:07:17 2006 +0000
@@ -0,0 +1,1228 @@
+2005-11-23  Johan Bockgård  <bojohan@users.sourceforge.net>
+
+	* erc.el (erc-cmd-SAY): Strip leading space in input line.
+
+2005-10-29  Michael Olson  <mwolson@gnu.org>
+
+	* FOR-RELEASE: Add stuff that needs to be done before the 5.1
+	release.  Longer-term items can be added to the 5.2 section.
+
+	* Makefile (SITEFLAG): New variable that indicates what variant of
+	"--site-flag" to use.  XEmacs needs "-site-flag".
+	(INSTALLINFO): New variable indicating how we should call
+	install-info when installing documentation.
+	(erc-auto.el, .elc.el): Use $(SITEFLAG).
+
+	* NEWS: Note that last release was 5.0.4.
+
+	* erc.texi: Initial and incomplete draft of ERC documentation.
+	Commence collaborate-documentation-hack-mode :^) .
+
+2005-10-29  Diane Murray  <disumu@x3y2z1.net>
+
+	* erc-ring.el (erc-replace-current-command): Revert last change
+	since it made the prompt disappear when using `erc-next-command'
+	and `erc-previous-command'.
+
+2005-10-28  Michael Olson  <mwolson@gnu.org>
+
+	* erc.el (erc-input-marker): New variable that indicates the
+	position where text from the user begins, after the prompt.
+	(erc-mode-map): Bind <HOME> to erc-bol, just like C-a.
+	(erc): Initialize erc-input-marker.
+	(erc-display-prompt): Even in case where no prompt is desired by
+	the user, clear the undo buffer and set the input marker.
+	(erc-bol, erc-user-input): Simplify by using erc-input-marker.
+
+	* erc-pcomplete.el (pcomplete-parse-erc-arguments): Use
+	erc-insert-marker.
+
+	* erc-ring.el (erc-previous-command)
+	(erc-replace-current-command): Use erc-insert-marker.
+
+	* erc-spelling.el (erc-spelling-init): Make sure that even Emacs21
+	obeys erc-spelling-flyspell-verify.
+	(erc-spelling-flyspell-verify): Use erc-input-marker.  This should
+	make it considerably faster when switching to a buffer that has
+	seen a lot of activity since last viewed.
+
+2005-10-25  Diane Murray  <disumu@x3y2z1.net>
+
+	* erc-backend.el (erc-server-version, 004): Re-added setting of
+	`erc-server-version'.  It doesn't hurt to set, and it could be
+	used in modules or users' settings.
+
+	* NEWS: Added descriptions of some new features.
+
+2005-10-20  Diane Murray  <disumu@x3y2z1.net>
+
+	* erc-match.el (erc-current-nick-highlight-type): Set to `keyword'
+	as default.
+	(erc-beep-match-types): New variable.
+	(erc-text-matched-hook): Doc fix.  Added `erc-beep-on-match' to
+	customization options.
+	(erc-beep-on-match): New function.  If the MATCH-TYPE is found in
+	`erc-beep-match-types', beep.
+
+	* erc-compat.el (erc-make-obsolete, erc-make-obsolete-variable):
+	New functions to deal with the difference in the number of
+	arguments accepted by `make-obsolete' and `make-obsolete-variable'
+	in Emacs and XEmacs.
+
+	* erc.el, erc-nets.el: Use `erc-make-obsolete' and
+	`erc-make-obsolete-variable'.
+
+	* erc-compat.el (erc-make-obsolete, erc-make-obsolete-variable):
+	Handle `wrong-number-of-arguments' error instead of checking for
+	xemacs feature as future versions of XEmacs might accept three
+	arguments.
+
+2005-10-18  Edward O'Connor  <ted@oconnor.cx>
+
+	* erc.el: Tell emacs-lisp-mode how to font-lock define-erc-module
+	docstrings.
+
+2005-10-08  Diane Murray  <disumu@x3y2z1.net>
+
+	* AUTHORS, CREDITS, ChangeLog, ChangeLog.2002, ChangeLog.2004:
+	Updated my email address.
+
+2005-10-06  Michael Olson  <mwolson@gnu.org>
+
+	* erc.el (erc-send-input-line, erc-cmd-KICK, erc-cmd-PART)
+	(erc-cmd-QUIT, erc-cmd-TOPIC, erc-kill-server, erc-kill-channel):
+	Adapt to new TARGET parameter of erc-server-send.
+
+	* erc-backend.el (erc-server-connect): Don't specify encoding for
+	erc-server-process, since we set this each time we send a line to
+	the server.
+	(erc-encode-string-for-target): Remove.
+	(erc-server-send): Allow TARGET to be specified.  This was how it
+	used to be before my more-backend work.  Set encoding of server
+	process just before sending text to it.  Associate encoding with
+	text if we are using the queue.
+	(erc-server-send-queue): Pull encoding from queue.
+	(erc-message, erc-send-ctcp-message, erc-send-ctcp-notice): Adapt
+	to new TARGET parameter of erc-server-send.
+
+2005-10-05  Michael Olson  <mwolson@gnu.org>
+
+	* erc.el (erc-toggle-debug-irc-protocol): Use erc-view-mode-enter
+	rather than view-mode.
+
+	* erc-backend.el (erc-encode-string-for-target): If given a nil or
+	empty string, return "".
+	(erc-server-send-queue): XEmacs fix: Use erc-cancel-timer rather
+	than cancel-timer.
+
+	* erc-compat.el (erc-view-mode-enter): New function that is
+	aliased to the correct way of entering view-mode.
+
+	* erc-match.el (erc-log-matches-make-buffer): Use
+	erc-view-mode-enter rather than view-mode-enter.
+
+2005-10-05  Edward O'Connor  <ted@oconnor.cx>
+
+	* erc-backend.el (erc-encode-string-for-target): If str is nil,
+	pass the empty string to erc-encode-coding-string instead, which
+	allows one to /part and /quit without providing a reason again.
+
+2005-10-03  Michael Olson  <mwolson@gnu.org>
+
+	* erc-backend.el (erc-message, erc-send-ctcp-message)
+	(erc-send-ctcp-notice): Encode string for target before sending.
+
+	* erc.el (erc-cmd-KICK, erc-cmd-PART, erc-cmd-QUIT, erc-cmd-TOPIC)
+	(erc-kill-server, erc-kill-channel): Ditto.
+
+2005-09-05  Johan Bockgård  <bojohan@users.sourceforge.net>
+
+	* erc-page.el (erc-ctcp-query-PAGE): (message text) -> (message
+	"%s" text).
+	(erc-cmd-PAGE): Simplify regexp. Put `do-not-parse-args' t.
+
+2005-09-05  Michael Olson  <mwolson@gnu.org>
+
+	* erc.el (erc-flood-limit, erc-flood-limit2): Remove since they
+	are no longer needed.
+	(erc-send-input): Detect whether we want flood control to be
+	active.  The previous behavior was to always force the message.
+	(erc-toggle-flood-control): Adapt to new flood control method.  No
+	more 'strict.
+	(erc-cmd-SV): Use concat rather than
+	format-time-string.
+	(erc-format-target, erc-format-target-and/or-server): Shorten
+	logic statements.
+
+	* erc-compat.el (erc-emacs-build-time): Use a string
+	representation rather than trying to coerce a time out of a string
+	on XEmacs.
+
+	* erc-identd.el (erc-identd-start): Use make-network-process
+	instead of open-network-stream.  Error out if this is not defined.
+
+	* erc-backend.el (erc-send-line): New command that sends a line
+	using flood control, using a callback for display.  It isn't used
+	yet.
+
+2005-09-04  Michael Olson  <mwolson@gnu.org>
+
+	* erc.el: Add defvaralias and make-obsolete-variable for
+	erc-default-coding-system.
+	(channel-topic, channel-modes, channel-user-limit, channel-key,
+	invitation, away, channel-list, bad-nick): Rename globally to
+	erc-{name-of-variable}.
+
+2005-09-03  Johan Bockgård  <bojohan@users.sourceforge.net>
+
+	* erc.el (erc-message): Simplify regexp.
+	(erc-cmd-DEOP, erc-cmd-OP): Simplify.
+
+2005-08-29  Michael Olson  <mwolson@gnu.org>
+
+	* erc.el: Alias erc-send-command to erc-server-send.  ErBot needs
+	this to work without modification.  Add defvaralias for
+	erc-process.  Make this and the other backwards-compatibility
+	functions and variables be marked obsolete as of ERC 5.1.
+
+	* erc-backend.el: Add autoload for erc-log macro.
+	(erc-server-connect): Set some variables before defining process
+	handlers.  It probably doesn't make any difference.
+
+2005-08-26  Michael Olson  <mwolson@gnu.org>
+
+	* erc.el: Add defvaralias for erc-announced-server-name, since
+	this seems to be widely used.
+
+2005-08-17  Michael Olson  <mwolson@gnu.org>
+
+	* erc.el (erc): Remove unnecessary boundp check.
+
+	* erc-autoaway.el: Fix compiler warning.
+
+	* erc-backend.el (erc-server-version): Since this isn't used by
+	any code, and isn't generally useful, remove it.
+	(erc-server-send-queue): Use erc-current-time rather than
+	float-time.
+	(004): Don't set erc-server-version.
+
+	* erc-dcc.el (erc-dcc-chat-request, erc-dcc-get-parent): Move to
+	fix a compiler warning.
+
+	* erc-ibuffer.el (erc-server): Remove unnecessary boundp check.
+
+	* erc-identd.el (erc-identd-start): Use read-string instead of
+	read-input.
+
+	* erc-imenu.el (erc-unfill-notice): Use a while loop instead of
+	replace-regexp.
+
+	* erc-nicklist.el: Add conditional dependency on erc-bbdb.
+	(erc-nicklist-insert-contents): Tighten some regexps.
+
+	* erc-notify.el (erc-notify-list): Docfix.
+
+	* erc-spelling.el (erc-spelling-dictionaries): Add :type and
+	:group to silence a compiler warning.
+
+2005-08-14  Michael Olson  <mwolson@gnu.org>
+
+	* erc-backend.el (erc-session-server, erc-session-port)
+	(erc-announced-server-name, erc-server-version)
+	(erc-server-parameters): Moved here from erc.el.
+	(erc-server-last-peers): Moved, renamed from last-peers.
+	(erc-server-lag): Moved, renamed from erc-lag.
+	(erc-server-duplicates): Moved, renamed from erc-duplicates.
+	(erc-server-duplicate-timeout): Moved, renamed from
+	erc-duplicate-timeout.
+	(erc-server): New customization group hosting all options from
+	this file.
+	(erc-server-prevent-duplicates): Moved, renamed from
+	erc-prevent-duplicates.
+	(erc-server-duplicate-timeout): Moved, renamed from
+	erc-duplicate-timeout.
+	(erc-server-auto-reconnect, erc-split-line-length)
+	(erc-server-coding-system, erc-encoding-coding-alist)
+	(erc-server-connect-function, erc-server-flood-margin)
+	(erc-server-flood-penalty): Change group to 'erc-server.
+	(erc-server-send-ping-interval): Moved, renamed from
+	erc-ping-interval.
+	(erc-server-ping-handler): Moved, renamed from erc-ping-handler.
+	(erc-server-setup-periodical-server-ping): Moved, renamed from
+	erc-setup-periodical-server-ping.
+	(erc-server-connect): Add to docstring.  Move more initialization
+	here.
+	(erc-server-processing-p): Docfix.
+	(erc-server-connect): Use 'raw-text like in the original version.
+	(erc-server-filter-function): Don't reset process coding system.
+
+	* erc-stamp.el (erc-add-timestamp): If the text at point is
+	invisible, don't insert a timestamp.  Thanks to Pascal
+	J. Bourguignon for the suggestion.
+
+	* erc-match.el (erc-text-matched-hook): Don't hide fools by
+	default, but include it in the available options.
+
+2005-08-13  Michael Olson  <mwolson@gnu.org>
+
+	* erc-*.el: s/erc-send-command/erc-server-send/g.
+	s/erc-process/erc-server-process/g (sort of).  Occasional
+	whitespace and indentation fixes.
+
+	* erc-backend.el: Specify a few local variables for indentation.
+	Take one item off of the TODO list.
+	(erc-server-filter-data): Renamed from erc-previous-read.  From
+	circe.
+	(erc-server-processing-p): New variable that indicates when we're
+	currently processing a message.  From circe.
+	(erc-split-line-length): New option that gives the maximum line
+	length of a single message.  From circe.
+	(erc-default-coding-system): Moved here from erc.el.
+	(erc-split-line): Renamed from erc-split-command and taken from
+	circe.
+	(erc-connect-function, erc-connect, erc-process-sentinel-1)
+	(erc-process-sentinel, erc-flood-exceeded-p, erc-send-command)
+	(erc-message, erc-upcase-first-word, erc-send-ctcp-message)
+	(erc-send-ctcp-notice): Moved here from erc.el.
+	(erc-server-filter-function): Renamed from erc-process-filter.
+	From circe.
+	(erc-server-process): Renamed from `erc-process' and moved here
+	from erc.el.
+	(erc-server-coding-system): Renamed from
+	`erc-default-coding-system'.
+	(erc-encoding-coding-alist): Moved here from erc.el.
+	(erc-server-flood-margin, erc-server-flood-penalty):
+	(erc-server-flood-last-message, erc-server-flood-queue):
+	(erc-server-flood-timer): New options from circe that allow
+	tweaking of flood control.
+	(erc-server-connect-function): Renamed from erc-connect-function.
+	(erc-flood-exceeded-p): Removed.
+	(erc-coding-system-for-target)
+	(erc-encode-string-for-target, erc-decode-string-from-target):
+	Moved here from erc.el
+	(erc-server-send): Renamed from erc-send-command.  Adapted from
+	the circe function by the same name.
+	(erc-server-send-queue): New function from circe that implements
+	handling of a flood queue.
+	(erc-server-current-nick): Renamed from current-nick.
+	(erc-server-quitting): Renamed from `quitting'.
+	(erc-server-last-sent-time): Renamed from `last-sent-time'.
+	(erc-server-last-ping-time): Renamed from `last-ping-time'.
+	(erc-server-lines-sent): Renamed from `lines-sent'.
+	(erc-server-auto-reconnect): Renamed from `erc-auto-reconnect'.
+	(erc-server-coding-system): Docfix.
+	(erc-server-connect): Renamed from `erc-connect'.  Require SERVER
+	and PORT parameters.  Initialize several variables here.  Don't
+	set `erc-insert-marker'.  Use a per-server coding system via
+	erc-server-default-encoding.
+
+	* erc.el (erc-version-string): Changed to indicate we are running
+	the `more-backend' branch.
+	(erc-send-single-line): Implement flood control using
+	erc-split-line.
+	(erc-send-input): Move functionality of erc-send-single-line in
+	here.
+	(erc-send-single-line): Assimilated!
+	(erc-display-command, erc-display-msg): Handle display hooks.
+	(erc-auto-reconnect, current-nick, last-sent-time)
+	(last-ping-time, last-ctcp-time, erc-lines-sent, erc-bytes-sent)
+	(quitting): Moved to erc-backend.el.
+	(erc): Docfix.  Don't initialize quite so many things here.
+
+2005-08-10  Michael Olson  <mwolson@gnu.org>
+
+	* debian/copyright (Copyright): Remove notices for 4 people, since
+	they didn't contribute legally-significant changes, or have had
+	these changes overwritten.
+
+	* erc-log.el: Remove copyright notice.
+
+	* erc.el: Remove 3 copyright notices.
+
+2005-08-09  Michael Olson  <mwolson@gnu.org>
+
+	* debian/changelog: Create 5.0.4-3 package.  This doesn't serve
+	any purpose other than to thank Romain Francoise for some advice.
+
+	* Makefile (debrelease): Allow last upload and extra build options
+	to be specified.
+
+2005-08-08  Michael Olson  <mwolson@gnu.org>
+
+	* debian/changelog: Create 5.0.4-2 package.
+
+	* debian/control (Uploaders): Add Romain Francoise.
+	(Standards-Version): Update to 3.6.2.
+	(Depends): Add `emacsen'.
+
+	* debian/scripts/startup.erc (load-path): Minor whitespace fixup.
+
+	* Makefile (clean): Split target from realclean and make it remove
+	files that aren't packaged in releases.
+	(clean, release): Minor cleanups.
+	(debrelease): Use debuild rather than dpkg-buildpackage since the
+	former calls lintian.  Minor cleanups.
+	(debrelease-mwolson): New target that removes old Debian packages,
+	calls debrelease, and copies the resulting package to my dist dir.
+	(upload): New target that automates the process of uploading an
+	ERC release to sourceforge.
+
+	* erc.el (erc-mode): Use `make-local-variable' instead of
+	`make-variable-buffer-local'.
+
+2005-07-12  Michael Olson  <mwolson@gnu.org>
+
+	* debian/changelog: Build 5.0.4-1.
+
+	* Makefile (release): Prepare zip file in addition to tarball.
+
+	* NEWS: Add item for the undo fix.
+
+2005-07-09  Michael Olson  <mwolson@gnu.org>
+
+	* erc-nicklist.el (erc-nicklist-insert-contents): Check
+	erc-announced-name before erc-session-server.  Make sure that we
+	can never get a stringp (nil) error.
+	(erc-nicklist-call-erc-command): If given no command, do nothing.
+	This fixes an error that used to occur when a stray mouse click
+	was made outside of the popup window, but on the erc-nicklist
+	menu.
+
+	* erc-bbdb.el (erc-bbdb-search-name-and-create): Get rid of the
+	infinite input loop when you want to create a new record.  Replace
+	most of that with a completing read of existing nicks.  If no nick
+	is chosen, create a new John Doe record.  The net effect of this
+	is that the old behavior is re-instated, with the addition of one
+	completing read that happens when you do a /whois.
+
+2005-07-09  Johan Bockgård  <bojohan@users.sourceforge.net>
+
+	* erc.el (erc-process-input-line): Docfix.
+	(erc-update-mode-line-buffer): Use `erc-propertize' instead of
+	`propertize'.
+	(erc-propertize): Move to erc-compat.el.
+
+	* erc-compat.el (erc-propertize): Move here from erc.el. Always
+	return a copy of the string (like `propertize' in GNU Emacs).
+
+	* erc-nicklist.el (erc-nicklist-icons-directory)
+	(erc-nicklist-voiced-position)
+	(erc-nicklist-insert-medium-name-or-icon): Docfix.
+	(erc-nicklist-insert-contents): Simplify.
+	(erc-nicklist-mode-map): Bind RET instead of `return'. Bind
+	`down-mouse-3' instead of `mouse-3'.
+	(erc-nicklist-kbd-cmd-QUERY): Cleanup regexp.
+	(erc-nicklist-channel-users-info): Docfix. Simplify.
+
+2005-07-02  Michael Olson  <mwolson@gnu.org>
+
+	* images: New directory containing the images that are used by
+	erc-nicklist.el.  These are from Gaim, and are thought to be
+	available under the terms of the GPL.
+
+	* erc-bbdb.el: Add local variables section to preserve tabs, since
+	that is the style used throughout this file.  Apply patch from
+	Edgar Gonçalves as follows.
+	(erc-bbdb-bitlbee-name-field): New variable that indicates the
+	field name to use for annotating the "displayed name" of a bitlbee
+	contact.
+	(erc-bbdb-irc-highlight-field): Docfix.
+	(erc-bbdb-search-name-and-create): Prompt the user for the name of
+	a contact if none was found.  Merge the new entries into the
+	specified contact.  If new arg SILENT is non-nil, do not prompt
+	the user for a name or offer to merge the new entry.
+	(erc-bbdb-insinuate-and-show-entry): New arg SILENT is accepted,
+	which is passed on to erc-bbdb-search-name-and-create.
+	(erc-bbdb-whois): Tell erc-bbdb-search-name-and-create to prompt
+	for name if necessary.
+	(erc-bbdb-JOIN, erb-bbdb-NICK): Forbid
+	erc-bbdb-search-name-and-create from prompting for a name.
+
+	* erc-nicklist.el: Add local variables section to preserve tabs,
+	since that is the style used throughout this file.  Apply patch
+	from Edgar Gonçalves as follows.
+	(erc-nicklist-use-icons): New option; if non-nil, display an icon
+	instead of the name of the chat medium.
+	(erc-nicklist-icons-directory): New option indicating the path to
+	the PNG files that are used for chat icons.
+	(erc-nicklist-use-icons): New option indicating whether to put
+	voiced nicks on top, bottom, or not to differentiate them.  The
+	default is to put them on the bottom.
+	(erc-nicklist-bitlbee-connected-p): New variable that indicates
+	whether or not we are currently using bitlbee.  An attempt will be
+	made to auto-detect the proper value.  This is bound in the
+	`erc-nicklist-insert-contents' function.
+	(erc-nicklist-nicklist-images-alist): New variable that maps a
+	host type to its icon.  This is set by `erc-nicklist'.
+	(erc-nicklist-insert-medium-name-or-icon): New function that
+	inserts an icon or string that identifies the current host type.
+	(erc-nicklist-search-for-nick): New function that attempts to find
+	a BBDB record that corresponds with this contact given its
+	finger-host.  If found, return its bitlbee-nick field.
+	(erc-nicklist-insert-contents): New function that inserts the
+	contents of the nick list, including text properties and images.
+	(erc-nicklist): Populate `erc-nicklist-images-alist'.  Move
+	nicklist content generation code to
+	`erc-nicklist-insert-contents'.
+	(erc-nicklist-mode-map): Map C-j to erc-nicklist-kbd-menu and RET
+	to erc-nicklist-kbd-cmd-QUERY.
+	(erc-nicklist-call-erc-command): Make use of
+	`switch-to-buffer-other-window'.
+	(erc-nicklist-cmd-QUERY): New function that opens a query buffer
+	for the given contact.
+	(erc-nicklist-kbd-cmd-QUERY): Ditto; contains most of the code.
+	(erc-nicklist-kbd-menu): New function that shows the nicklist
+	action menu.
+	(erc-nicklist-channel-users-info): Renamed from
+	`erc-nicklist-channel-nicks'.  Implement sorting voiced users.
+
+2005-06-29  Johan Bockgård  <bojohan+sf@dd.chalmers.se>
+
+	* erc-nickserv.el (erc-nickserv-alist): Fix regexp for Azzurra.
+
+2005-06-26  Michael Olson  <mwolson@gnu.org>
+
+	* erc-autojoin.el (erc-autojoin-add, erc-autojoin-remove): Use
+	`erc-session-server' if `erc-announced-server-name' is nil.  This
+	happens when servers don't send a 004 message.
+
+	* erc.el (erc-quit-server): Ditto.
+
+	* erc-ibuffer.el (erc-server, erc-server-name): Ditto.
+
+	* erc-notify.el (erc-notify-JOIN, erc-notify-NICK)
+	(erc-notify-QUIT): Ditto.
+
+2005-06-24  Johan Bockgård  <bojohan+sf@dd.chalmers.se>
+
+	* erc.el (erc-default-coding-system)
+	(erc-handle-user-status-change): Docstring fix.
+	(with-erc-channel-buffer): Removed.
+	(erc-ignored-reply-p): Replace `with-erc-channel-buffer' with
+	`erc-with-buffer'.
+	(erc-display-line-1): Revision 1.730 broke undo. Fix it.
+
+2005-06-23  Michael Olson  <mwolson@gnu.org>
+
+	* CREDITS: Add entries for Luigi Panzeri and Andreas Schwab.
+
+	* erc-nickserv.el (erc-nickserv-alist): Add entries for Azzurra
+	and OFTC.  Thanks to Luigi Panzeri and Andreas Schwab for
+	providing these.
+
+2005-06-16  Michael Olson  <mwolson@gnu.org>
+
+	* CREDITS: Add John Paul Wallington.
+
+	* erc.el: Thanks to John Paul Wallington for the following.
+	(erc-nickname-in-use): Use `string-to-number' instead of
+	`string-to-int'.
+
+	* erc-dcc.el (erc-dcc-handle-ctcp-send)
+	(erc-dcc-handle-ctcp-chat, erc-dcc-get-file)
+	(erc-dcc-chat-accept): Ditto.
+
+	* erc-identd.el (erc-identd-start): Ditto.
+
+2005-06-16  Johan Bockgård  <bojohan+sf@dd.chalmers.se>
+
+	* erc.el (erc-mode-map): Suppress `font-lock-fontify-block' key
+	binding since it destroys face properties.
+
+2005-06-08  Michael Olson  <mwolson@gnu.org>
+
+	* erc.el (erc-cmd-UNIGNORE): Use `erc-member-ignore-case' instead
+	of `member-ignore-case'.  Thanks to bpalmer for the heads up.
+
+2005-06-06  Michael Olson  <mwolson@gnu.org>
+
+	* erc.el (erc-modules): Fix a mistake I made when editing this a
+	few days ago.  Modes should now be disabled properly.
+	(erc-cmd-BANLIST, erc-cmd-MASSUNBAN): Remove unnecessary call to
+	`format'.  Thanks to Andreas Schwab for reporting this.
+
+	* debian/changelog: Close "README file missing" bug.
+
+	* debian/rules (binary-erc): Install README file.
+
+2005-06-03  Michael Olson  <mwolson@gnu.org>
+
+	* erc.el (erc-with-buffer): Set `lisp-indent-function' so Emacs
+	Lisp mode knows how to indent erc-with-buffer blocks.
+	(with-erc-channel-buffer): Ditto.
+	(erc-with-all-buffers-of-server): Ditto.
+	(erc-modules): Use pcomplete by default, not completion, since
+	erc-complete.el is deprecated.  Use `fboundp' instead of
+	`symbol-value' to check for existence of a function before calling
+	it.  This was causing an error when untoggling the `completion'
+	option and trying to save via the customize interface.
+
+	* erc-track.el (erc-modified-channels-update): If a buffer is not
+	currently connected, remove it from the modified channels list.
+	This should fix the problem where residue was left on the mode
+	line after quitting ERC.
+
+	* erc-list.el (erc-prettify-channel-list): Docfix; thanks to John
+	Paul Wallington for reporting this.
+
+2005-05-31  Michael Olson  <mwolson@gnu.org>
+
+	* debian/changelog: First draft of entries for the 5.0.3 release.
+
+	* debian/README.Debian: Note that ERC will now install correctly
+	on versions of Emacs or XEmacs that do not have the `format-spec'
+	library.  Correct some grammar and prune the content a bit.
+
+	* debian/scripts/install (emacs20): Remove line since we no longer
+	need to deal with format-spec.el.
+
+	* NEWS: Add entries for the upcoming 5.0.3 release.
+
+	* erc.el: Don't require format-spec since this is provided in
+	erc-compat.el now.
+	(erc-process-sentinel, erc-setup-periodical-server-ping): Use
+	`erc-cancel-timer' instead of `cancel-timer'.
+	(erc-version-string): Update to 5.0.3.
+
+	* erc-autoaway.el (autoaway, erc-autoaway-reestablish-idletimer):
+	Use `erc-cancel-timer' instead of `cancel-timer'.
+
+	* erc-compat.el (format-spec, format-spec-make): If we cannot load
+	the `format-spec' library, provide versions of these functions.
+	This should keep problems from surfacing with Emacs21 Debian
+	builds.
+	(erc-cancel-timer): New function created to take the place of
+	`cancel-timer' since XEmacs calls it something else.
+
+	* erc-track.el (erc-modified-channels-update): Accept any number
+	of arguments, which are ignored.  This allows it to be run from
+	`erc-disconnected-hook' without extra bother.
+	(track): Add `erc-modified-channels-update' to
+	`erc-disconnected-hook' so that the indicators are removed
+	correctly in some edge cases.
+	(erc-modified-channels-display): Make sure that we never pass nil
+	to the function in `erc-track-shorten-function'.  This happens
+	when we have deleted buffers in `erc-modified-channels-alist'.
+	Also, make sure that the buffer has a non-nil short-name before
+	adding it to the string list.  This should fix some XEmacs
+	warnings when running /quit with unchecked buffers, as well as get
+	rid of a stray buffer problem (or so it is hoped).
+
+2005-05-31  Johan Bockgård  <bojohan+sf@dd.chalmers.se>
+
+	* erc-replace.el, erc-speak.el: Clean up comment formatting.
+
+	* erc-ring.el (ring, erc-input-ring-index, erc-clear-input-ring):
+	Clean up docstring formatting.
+
+2005-05-30  Johan Bockgård  <bojohan+sf@dd.chalmers.se>
+
+	* erc.el (erc-cmd-BANLIST, erc-cmd-MASSUNBAN): Delete superfluous
+	arg to `format'.
+	(erc-load-irc-script): Use `insert-file-contents' instead of
+	`insert-file'. Simplify.
+
+2005-05-29  Michael Olson  <mwolson@gnu.org>
+
+	* erc.el (erc-version-string): Move this up so that it is
+	evaluated before the `require' statements.  Not a major change.
+
+2005-04-27  Johan Bockgård  <bojohan+sf@dd.chalmers.se>
+
+	* erc.el (erc-complete-word): Simplify.
+
+2005-04-27  Michael Olson  <mwolson@gnu.org>
+
+	* Makefile (debrelease): Use a slightly different approach when
+	removing CVS and Arch cruft.
+
+	* debian/changelog: Update for 5.0.2-1 package.
+
+2005-04-25  Michael Olson  <mwolson@gnu.org>
+
+	* erc-autoaway.el (erc-autoaway-reestablish-idletimer): Move code
+	block higher in file to fix a load failure when using Emacs21.
+	Thanks to Daniel Brockman for the report and fix.
+
+2005-04-24  Adrian Aichner  <adrian@xemacs.org>
+
+	* erc-backend.el (JOIN): save-excursion so that
+	`erc-current-logfile' inserts into the correct channel buffers
+	when using erc-log-insert-log-on-open in combination with autojoin
+	to multiple channels.
+
+2005-04-17  Adrian Aichner  <adrian@xemacs.org>
+
+	* erc-log.el: Remove stray whitespace.
+	* erc.el: Ditto.
+
+2005-04-09  Aidan Kehoe  <kehoea@parhasard.net>
+
+	* erc.el: autoload erc-select-read-args, which, because it parses
+	erc-select's args, can be called before erc.el is loaded. 
+
+2005-04-07  Edward O'Connor  <ted@oconnor.cx>
+	
+	* erc-viper.el: Remove final newlines from previously-existing ERC
+	buffers. (Minor bug fix.)
+
+2005-04-06  Michael Olson  <mwolson@gnu.org>
+
+	* Makefile (debrelease): Ignore errors from deleting Arch and CVS
+	metadata.
+
+2005-04-05  Michael Olson  <mwolson@gnu.org>
+
+	* ChangeLog, CREDITS, AUTHORS: Correct name and email address of
+	Marcelo Toledo.
+
+2005-04-04  Michael Olson  <mwolson@gnu.org>
+
+	* erc.el (erc-modules): Add entry for spelling module.
+
+	* erc-spelling.el: Add autoload line.
+
+	* erc-backend.el: Apply latest non-ascii patch from Kai Fan.
+	(erc-decode-parsed-server-response): Search
+	erc-response.command-args for channel name.  Decode the
+	erc-response struct using this channel name as key according to
+	the `erc-encoding-coding-alist'.
+
+	* erc-track.el: Apply patch from Henrik Enberg.
+	(erc-modified-channels-object): Use optimal amount of whitespace
+	around modified channels indicator.
+
+2005-04-02  Johan Bockgård  <bojohan+sf@dd.chalmers.se>
+
+	* erc.el (define-erc-module, erc-with-buffer)
+	(erc-with-all-buffers-of-server, with-erc-channel-buffer): Add
+	edebug-form-spec.
+
+	* erc-compat (erc-define-minor-mode): Ditto.
+
+2005-03-29  Jorgen Schaefer  <forcer@forcix.cx>
+
+	* erc-spelling.el: New file.
+
+2005-03-24  Johan Bockgård  <bojohan+sf@dd.chalmers.se>
+
+	* erc-backend.el (define-erc-response-handler): Add
+	`definition-name' property to constructed symbols so that
+	find-function and find-variable will find them.
+
+2005-03-21  Michael Olson  <mwolson@gnu.org>
+
+	* erc-dcc.el, erc-goodies.el, erc-list.el, erc-notify.el,
+	erc-ring.el, erc.el: Copyright assignment occurred.
+
+	* debian/scripts/install: Make a shell wrapper around the original
+	Makefile and inline the Makefile.  The problem is that Debian
+	passes all the Emacs variants at once, rotating them at every
+	invocation of the install script, which happens once per variant.
+	This caused each installation to happen N-1 times more often than
+	it should have.  As a result, we need to only deal with the first
+	argument.
+	(ELFILES): Only add format-spec.el if we are compiling for
+	emacs21.  Don't filter out erc-compat.el.
+	(SITEFLAG): New variable that indicates that the "nosite" option
+	should look like.
+	(.DEFAULT): Use $(FLAVOUR) instead of $@ for clarity.
+
+	* debian/rules: Install NEWS file and compress it.
+
+	* debian/maint/postinst: Be more cautious about configuration
+	step.
+
+	* debian/copyright (Copyright): Another assignment came in.
+
+	* debian/control (Standards-Version): Update to a newer version as
+	recommended by lintian.
+
+	* debian/changelog: Changes made for the Debian package.
+
+	* debian/README.Debian: Keep only the General Notes section.
+
+	* NEWS: Move old history items here from debian/README.Debian.
+
+	* Makefile (SNAPSHOTDATE): Deprecate this option since we hope to
+	release more often.
+
+2005-03-20  Jorgen Schaefer  <forcer@users.sourceforge.net>
+
+	* erc.el (erc-define-catalog, `ctcp-request-to'): Fix typo (%: ->
+	%t:).
+
+2005-03-01  Michael Olson  <mwolson@gnu.org>
+
+	* erc-log.el (erc-save-buffer-in-logs): Replace tabs with spaces
+	in code indentation.
+
+2005-02-28  Michael Olson  <mwolson@gnu.org>
+
+	* erc.el (erc-display-message): Apply corrected patch from Henrik
+	Enberg.
+
+2005-02-27  Michael Olson  <mwolson@gnu.org>
+
+	* erc.el (erc-display-message): Apply patch from Henrik Enberg.
+	Check here to see if a message should be hidden, rather than
+	relying on code in each individual command.
+	(erc-version-string): Add "(CVS)" to the version string for
+	clarity.
+
+	* erc-backend.el (JOIN, KICK, MODE, NICK, PART, QUIT, TOPIC):
+	Don't check `erc-hide-list' here.
+
+	* erc-list.el, erc-match.el, erc.el, debian/copyright: Update
+	copyright information as a few more people have assignments
+	registered.
+
+2005-02-06  Michael Olson  <mwolson@gnu.org>
+
+	* erc-backend.el: Apply patch from Kai Fan for non-ASCII character
+	support.
+	(erc-parse-server-response): Add call to
+	`erc-decode-parsed-server-response'.
+	(erc-decode-parsed-server-response): New function that decodes a
+	pre-parsed server response before it can be handled.
+	(PRIVMSG): Comment out call to `erc-decode-string-from-target'.
+	(TOPIC): Ditto.
+
+2005-02-01  Jorgen Schaefer  <forcer@users.sourceforge.net>
+
+	* erc.el (erc-process-sentinel-1): Don't reconnect on connection
+	refused. This error is reported differently when using
+	open-network-stream-nowait.
+
+2005-01-26  Diane Murray  <disumu@x3y2z1.net>
+
+	* erc.el (erc-cmd-APPENDTOPIC, erc-set-topic): The control
+	character in `channel-topic' was changed to \C-o - replaced \C-c
+	with \C-o so that these functions work as expected again.
+	(erc-get-channel-mode-from-keypress): Doc fix.
+
+2005-01-25  Diane Murray  <disumu@x3y2z1.net>
+
+	* erc.el, erc-button.el, erc-compat.el, erc-goodies.el,
+	erc-match.el, erc-nets.el, ChangeLog, NEWS: Merged bug fixes made
+	on release_5_0_branch since 5.0.1 release.
+
+2005-01-24  Johan Bockgård  <bojohan+sf@dd.chalmers.se>
+
+	* erc.el (erc-input-action): Quote `erc-action-history-list' so
+	that input history actually works.
+	(erc-process-ctcp-query): Fix and simplify logic.
+	(erc-get-channel-mode-from-keypress): Use `C-' string syntax.
+	(erc-load-irc-script-lines): Use `erc-command-indicator' instead
+	of `erc-prompt'.
+
+2005-01-23  Edward O'Connor  <ted@oconnor.cx>
+	
+	* erc-viper.el: Ensure that `viper-comint-mode-hook' runs in
+	buffers whose `erc-mode-hook' has already run when this file is
+	loaded.
+	Explicitly `require' erc.el.
+
+2005-01-22  Edward O'Connor  <ted@oconnor.cx>
+	
+	* erc.el (erc-mode): Remove frobbing of `require-final-newline'.
+
+	* erc-log.el (erc-save-buffer-in-logs): Remove frobbing of
+	`require-final-newline'.
+
+	* erc-viper.el: New file. This is where all ERC/Viper
+	compatiibilty code should live. When and if ERC is bundled with
+	Emacs, some of the hacks in this file should be merged into Viper
+	itself.
+
+2005-01-21  Edward O'Connor  <ted@oconnor.cx>
+	
+	* erc.el (erc-mode): Set `require-final-newline' to nil in ERC
+	buffers. This prevents a Viper misfeature whereby extraneous
+	newlines are inserted into the ERC buffer when switching between
+	viper states.
+
+	* erc-log.el (erc-save-buffer-in-logs): Bind `require-final-newline'
+	to t when calling `write-region' to ensure that further log
+	entries start on fresh lines.
+	
+2005-01-21  Diane Murray  <disumu@x3y2z1.net>
+
+	* erc-button.el (erc-button-add-face): Reverted my change to the
+	order faces since it had the unwanted effect of putting the button
+	face after all others.
+	(erc-button-face-has-priority): Removed this variable as it is not
+	necessary anymore - it was used to compensate for the above
+	mentioned change.
+
+	* NEWS: Added the latest fixes.
+
+2005-01-20  Diane Murray  <disumu@x3y2z1.net>
+
+	* erc-button.el, erc-match.el:
+	(erc-button-syntax-table, erc-match-syntax-table): Added \ as a
+	legal character for nicknames.
+
+	* erc-nets.el (erc-server-select): Fixed so that only networks
+	with servers found in `erc-server-alist' are available as choices.
+
+	* erc.el, erc-compat.el, erc-goodies.el:
+	(erc-replace-match-subexpression-in-string): New function.  Needed
+	because `replace-match' in XEmacs doesn't replace regular
+	expression subexpressions in strings, only in buffers.
+	(erc-seconds-to-string, erc-controls-interpret): Use the new
+	function.
+
+	* erc-button.el (erc-button-add-button): Use the `:button-face'
+	key combined with an `erc-mode' local `widget-button-face' set to
+	nil to get the widget overlay face suppressed in XEmacs.
+
+2005-01-19  Francis Litterio  <franl@world.std.com>
+
+	* erc-button.el (erc-button-add-face): The face added by this
+	function is more important than the existing text's face, so we
+	now prepend erc-button-face to the list of existing faces when
+	adding a button.  To instead append erc-button-face to existing
+	faces, set variable `erc-button-face-has-priority' to nil.
+	(erc-button-face-has-priority): New variable to control how
+	erc-button-add-face adds erc-button-face to existing faces.
+	(erc-button-press-button): Silenced a byte-compiler warning about
+	too few arguments in a call to `error'.
+
+2005-01-19  Diane Murray  <disumu@x3y2z1.net>
+
+	* NEWS: Added list of 5.0.1 fixes.
+
+2005-01-19  Michael Olson  <mwolson@gnu.org>
+
+	* AUTHORS: Move to format that cscvs can understand.  As an added
+	perk, entries line up nicer.
+
+	* erc.el, erc-fill.el, erc-pcomplete.el, debian/copyright: Merge a
+	few more copyright lines thanks to Alex Schroeder's BBDB file.
+
+	* Makefile: Change version to correspond with our new scheme.
+
+2005-01-18  Diane Murray  <disumu@x3y2z1.net>
+
+	* erc-list.el (erc-chanlist-channel-line-regexp): Now matches
+	private channels, the channels `#' and `&', and channels with
+	names including non-ascii characters.
+	(erc-chanlist-join-channel): Don't attempt to join private
+	channels since the channel name is unknown.
+
+	* erc-goodies.el (erc-make-read-only): Add `rear-nonsticky'
+	property to avoid `Text is read-only' errors during connection.
+	`front-nonsticky' does not exist, changed to `front-sticky'.
+	(erc-controls-interpret, erc-controls-strip): Just work on the
+	string, don't open a temporary buffer.
+	(erc-controls-propertize): Now accepts optional argument STR.
+
+2005-01-17  Michael Olson  <mwolson@gnu.org>
+
+	* Makefile: Version is 5.01, but only in the Makefile.  It has not
+	been released yet.
+
+	* erc-auto.in, erc-autojoin.el, erc-bbdb.el, erc-button.el,
+	erc-chess.el, erc-complete.el, erc-dcc.el, erc-fill.el,
+	erc-goodies.el, erc-ibuffer.el, erc-identd.el, erc-imenu.el,
+	erc-list.el, erc-match.el, erc-menu.el, erc-nets.el,
+	erc-netsplit.el, erc-nickserv.el, erc-notify.el, erc-pcomplete.el,
+	erc-ring.el, erc-speak.el, erc-speedbar.el, erc-stamp.el,
+	erc-track.el, erc-xdcc.el, erc.el, debian/copyright: Update
+	copyright notices.  If anyone has signed papers for Emacs in
+	general, merge them with the FSF's entry.
+
+2005-01-16  Diane Murray  <disumu@x3y2z1.net>
+
+	* erc.el (erc): `erc-set-active-buffer' was being called before
+	`erc-process' was set, so that channels weren't being marked
+	active correctly upon join; fixed.
+
+2005-01-15  Johan Bockgård  <bojohan+sf@dd.chalmers.se>
+
+	* erc-backend.el (def-edebug-spec): This macro caused problems (in
+	XEmacs). Use its expansion directly.
+
+2005-01-15  Diane Murray  <disumu@x3y2z1.net>
+
+	* erc-button.el (erc-button-add-button): Reverted previous change
+	since `:suppress-face' doesn't seem to be checked for a certain
+	face.
+	(erc-button-add-face): FACE is now appended to the `old' face.
+	This should fix the problem of faces being "covered" by
+	`erc-button-face'.
+
+2005-01-14  Diane Murray  <disumu@x3y2z1.net>
+
+	* erc.el, erc-backend.el (erc-cmd-OPS, erc-cmd-COUNTRY,
+	erc-cmd-NICK, erc-process-ctcp-query, ERROR, PONG, 311, 312, 313,
+	314, 317, 319, 320, 321, 322, 330, 352): Use catalog entries
+	instead of hard-coded text messages.
+	(english): Added new catalog entries `country', `country-unknown',
+	`ctcp-empty', `ctcp-request-to', `ctcp-too-many', `nick-too-long',
+	`ops', `ops-none', `ERROR', `PONG', `s311', `s312', `s313',
+	`s314', `s317', `s317-on-since', `s319', `s320', `s321', `s322',
+	`s330', and `s352'.
+	(erc-send-current-line): Use `erc-set-active-buffer' (change was
+	lost in previous bug fix).
+
+2005-01-14  Francis Litterio  <franl@world.std.com>
+
+	* erc-button.el (erc-button-add-button): Fixed a bug where the
+	overlay created by widget-convert-button has a `face' property
+	that hides the `face' property set on the underlying button text.
+
+	* erc-goodies.el: Docstring fix.
+
+	* erc-button.el: Improved docstring for variable erc-button-face.
+
+2005-01-13  Diane Murray  <disumu@x3y2z1.net>
+
+	* erc-menu.el (erc-menu-definition): "Topic set by channel
+	operator": Small word change.  "Identify to NickServ...": Check
+	that we're connected to the server.  Added "Save buffer in log"
+	and "Truncate buffer".
+
+2005-01-13  Lawrence Mitchell  <wence@gmx.li>
+
+	* erc.el (erc-display-line-1): Widen before we try to insert
+	anything, this makes sure input isn't broken when the buffer is
+	narrowed by the user.
+	(erc-beg-of-input-line): Simplify, just return the position of
+	`erc-insert-marker' or error if does not exist.
+	(erc-send-current-line): Widen before trying to send anything.
+
+2005-01-13  Diane Murray  <disumu@x3y2z1.net>
+
+	* erc.el, erc-backend.el, erc-list.el:
+	(erc-update-mode-line-buffer): Strip controls characters from
+	`channel-topic' since we add our own control character to it.
+	(TOPIC, 332): Use \C-o instead of \C-c to force an end of IRC
+	control characters as it also ends bold, underline, and inverse -
+	\C-c only ends colors.
+	(erc-chanlist-322): Strip control characters from channel and
+	topic.  No need to interpret controls when we're applying overlays
+	to the lines.
+
+	* erc.el, erc-backend.el, erc-button.el, erc-netsplit.el,
+	erc-nicklist.el: Fixed so that each server has an active buffer.
+	(erc-active-buffer): Now a buffer-local variable.
+	(erc-active-buffer, erc-set-active-buffer): New functions.
+	(erc-display-line, erc-echo-notice-in-active-non-server-buffer,
+	erc-process-away, MODE): Call `erc-active-buffer' to get the
+	active buffer for the current server.
+	(erc, erc-process-sentinel-1, erc-grab-region, erc-input-action,
+	erc-send-current-line, erc-invite-only-mode,
+	erc-toggle-channel-mode, erc-channel-names, MODE, erc-nick-popup,
+	erc-nicklist-call-erc-command): Use `erc-set-active-buffer' to set
+	the active buffer for the current server.
+	(erc-cmd-WHOLEFT): Use 'active as BUFFER in `erc-display-message'.
+
+	* erc-track.el (erc-track-modified-channels): Server buffers are
+	now treated the same as channels and queries.  This means that
+	`erc-track-priority-faces-only', `erc-track-exclude', and
+	`erc-track-exclude-types' now work with server buffers.
+
+2005-01-12  Diane Murray  <disumu@x3y2z1.net>
+
+	* erc-backend.el (475): Prompt for the channel's key if
+	`erc-prompt-for-channel-key' is non-nil.  Send a new JOIN message
+	with the key if a key is provided.
+
+	* erc.el (erc-command-indicator): Fixed customization choices so
+	that there's no `mismatch' message when nil is the value.
+
+2005-01-11  Michael Olson  <mwolson@gnu.org>
+
+	* erc-bbdb.el (bbdb): Lowercase the name of the module.  This
+	fixes a bug which caused an error to occur when trying to enable
+	the module using the customization interface.
+
+2005-01-08  Edward O'Connor  <ted@oconnor.cx>
+
+	* erc-track.el: Support using faces to indicate channel activity
+	in the modeline under XEmacs.
+	(erc-modified-channels-object): New function.
+	(erc-modified-channels-display): Use it.
+	`erc-modified-channels-string' renamed to
+	`erc-modified-channels-object' (because it's no longer a string on
+	XEmacs). The new function `erc-modified-channels-object' is used
+	to generate updated values for the same-named variable.
+
+2005-01-08  Diane Murray <disumu@x3y2z1.net>
+
+	* ChangeLog.2002: Changed instances of my sourceforge username and
+	email address to real name and email.
+
+	* erc.el (erc-modules): Changed customization tag descriptions, so
+	that they all start with a verb; added new modules to choices.
+
+2005-01-08  Mario Lang  <mlang@delysid.org>
+
+	* debian/rules: Introduce new variable DOCDIR to simplify stuff a
+	bit.
+
+2005-01-08  Michael Olson  <mwolson@gnu.org>
+
+	* AUTHORS, ChangeLog.2004: Change bpalmer's email address as
+	requested.
+
+	* CREDITS: Add everyone who is mentioned in the ChangeLogs.
+
+	* debian/copyright (Copyright): Add last few people.  This can now
+	be considered a complete list, as far as CVS entries are
+	concerned.  If people have assigned copyright to the FSF, merge
+	them with the entry for the FSF.
+
+	* debian/README.Debian: Add entry for XEmacs-related change in
+	`erc-track.el'.
+
+	* erc.el (erc-cmd-MODE): New command that changes or displays the
+	mode for a channel or user.  The functionality was present before
+	this change, but there was no documentation for it.
+
+	* erc-auto.in, erc-*.el: Fully investigate copyright headers and
+	change them appropriately.  If a file has been pulled off of
+	erc.el at one time, keep track of copyright from the time of
+	separation, but not before.  If a file has been derived from a
+	work outside of erc, keep copyright statements in place.
+
+	* Makefile (VERSION): Change to 5.0! :^) Congrats on all the great
+	work.  I'll wait until hober commits his XEmacs compatibility
+	patch to erc-track.el, and then release.
+	(distclean): Alias for `realclean' target.
+
+2005-01-07  Michael Olson  <mwolson@gnu.org>
+
+	* AUTHORS: Add Marcelo Toledo, who has CVS access to this project.
+
+	* ChangeLog.2004: Add my name to my one contribution to erc last
+	year.
+
+	* CREDITS: Add people that were discovered while scouring
+	ChangeLogs.
+
+	* debian/copyright: Add everyone from `AUTHORS' to Upstream
+	Authors.  Anyone who has contributed 15 or more lines of
+	code (according to ChangeLogs) is listed in Copyright section.
+	Accurate years are included.
+
+	* debian/README.Debian: Paste content of NEWS and reformat
+	slightly.
+
+	* debian/rules: Concatenate the ChangeLogs during the Debian
+	install process and then gzip them.
+
+	* Makefile (MISC): Add ChangeLog.yyyy files to list.
+	(ChangeLog): Remove rule since we do not dynamically generate the
+	ChangeLog anymore.
+
+	* MkChangeLog: Removed since we do not use it to generate the
+	ChangeLog anymore.  cvs2cl does a much better job anyway.
+
+	* NEWS: Use 3rd level heading instead of bullets for lists that
+	contain descriptions.
+
+2005-01-07  Diane Murray <disumu@x3y2z1.net>
+
+	* erc-list.el: Require 'sort.
+	(erc-chanlist): Disable undo in the channel list buffer.
+
+	* erc.el, erc-menu.el: The `IRC' menu is now automatically added
+	to the menu-bar.  Add the call to `easy-menu-add' to
+	`erc-mode-hook' when running in XEmacs (without this the menu
+	doesn't appear).
+
+	* NEWS: Added the information from
+	http://emacswiki.org/cgi-bin/wiki/ErcCvsFeatures and the newer
+	changes which weren't yet documented on that page.
+
+2005-01-06  Hoan Ton-That  <hoan@ton-that.org>
+
+	* erc-log.el (erc-current-logfile): Only downcase the logfile
+	name, not the whole filename.  Also expand relative to
+	`erc-log-channels-directory'.
+	(erc-generate-log-file-name-with-date)
+	(erc-generate-log-file-name-short)
+	(erc-generate-log-file-name-long): Don't expand filename, done in
+	`erc-current-logfile'.
+
+2005-01-06  Lawrence Mitchell  <wence@gmx.li>
+
+	* NEWS: New file, details user visible changes from version to
+	version.
+
+	* HACKING (NEWS entries): Mention NEWS file, and what its purpose
+	is.
+
+2005-01-05  Michael Olson  <mwolson@gnu.org>
+
+	* FOR-RELEASE: New file containing the list of release-critical
+	tasks.  Feel free to add to it.
+
+	* debian/rules (binary-erc): Add ChangeLog files.
+
+2005-01-04  Michael Olson  <mwolson@gnu.org>
+
+	* ChangeLog.2001, ChangeLog.2002, ChangeLog.2003, ChangeLog.2004:
+	ChangeLog entries from previous years.
+
+	* ChangeLog: New file containing ChangeLog entries for the current
+	year.  Please update this file manually whenever a change is
+	committed.  This is a new policy.
+
+	* AUTHORS: Add myself to list.  Some entries were space-delimited
+	instead of TAB-delimited, and since the latter seemed to be the
+	default, make the other entries conform.
+
+	* HACKING (ChangeLog Entries): Update section to reflect new
+	policy toward ChangeLog entries, which is that they should be
+	manually updated whenever a change is committed.
+
+2005-01-04  Diane Murray <disumu@x3y2z1.net>
+
+	* erc.el (erc-connection-established, erc-login): Update the
+	mode-line.
+	(erc-update-mode-line-buffer): If `erc-current-nick' returns nil,
+	use an empty string for ?n character in format spec.  Set
+	`mode-line-process' to ":connecting" while the connection is being
+	established.
+
+2005-01-04  Lawrence Mitchell <wence@gmx.li>
+
+	* AUTHORS: Update list of authors.
+
+2005-01-02  Diane Murray <disumu@x3y2z1.net>
+
+	* erc-goodies.el (erc-control-characters): New customization
+	group.
+	(erc-interpret-controls-p): Small fix, addition to
+	documentation. Updated customization to allow 'remove as a value.
+	Use 'erc-control-characters as `:group'.
+	(erc-interpret-mirc-color): Use 'erc-control-characters as
+	`:group'.
+	(erc-beep-p): Updated documentation.  Use 'erc-control-characters
+	as `:group'.
+	(define-erc-module irccontrols): Add `erc-controls-highlight' to
+	`erc-insert-modify-hook' and `erc-send-modify-hook' since it
+	changes the text's appearance.
+	(erc-controls-remove-regexp, erc-controls-interpret-regexp): New
+	variables.
+	(erc-controls-highlight): Fixed so that highlighting works even if
+	there is no following control character.  Fixed mirc color
+	highlighting; now respecting `erc-interpret-mirc-color'.  Fixed a
+	bug where emacs would get stuck in a loop when \C-g was in a
+	message and `erc-beep-p' was set to nil (default setting).
+
+See ChangeLog.2004 for earlier changes.
+
+    Copyright (C) 2005 Free Software Foundation, Inc.
+  Copying and distribution of this file, with or without modification,
+  are permitted provided the copyright notice and this notice are preserved.
+
+;; Local Variables:
+;; coding: utf-8
+;; End:
+
+;; arch-tag: 70f1733a-3e2f-43c2-91c3-d9ace93f82ba
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lisp/erc/erc-autoaway.el	Wed Feb 01 10:07:17 2006 +0000
@@ -0,0 +1,207 @@
+;;; erc-autoaway.el --- Provides autoaway for ERC
+
+;; Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+
+;; Author: Jorgen Schaefer <forcer@forcix.cx>
+;; URL: http://www.emacswiki.org/cgi-bin/wiki.pl?ErcAutoAway
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
+
+;;; Commentary:
+
+;; TODO:
+;; - Legacy names: erc-auto-discard-away, erc-auto-set-away
+
+;;; Code:
+
+(require 'erc)
+
+(defgroup erc-autoaway nil
+  "Set yourself automatically away after some idletime and set
+yourself back when you type something."
+  :group 'erc)
+
+(defvar erc-autoaway-idletimer nil
+  "The Emacs idletimer.
+This is only used when `erc-autoaway-use-emacs-idle' is non-nil.")
+
+(defcustom erc-autoaway-use-emacs-idle nil
+  "*If non-nil, the idle time refers to idletime in Emacs.
+If nil, the idle time refers to idletime on IRC only.
+The time itself is specified by `erc-autoaway-idle-seconds'.
+See `erc-autoaway-mode' for more information on the various
+definitions of being idle.
+
+Note that using Emacs idletime is currently broken for most versions,
+since process activity (as happens all the time on IRC) makes Emacs
+non-idle.  Emacs idle-time and user idle-time are just not the same."
+  :group 'erc-autoaway
+  :type 'boolean)
+
+;;;###autoload (autoload 'erc-autoaway-mode "erc-autoaway")
+(define-erc-module autoaway nil
+  "In ERC autoaway mode, you can be set away automatically.
+If `erc-auto-set-away' is set, then you will be set away after
+the number of seconds specified in `erc-autoaway-idle-seconds'.
+
+There are several kinds of being idle:
+
+IRC idle time measures how long since you last sent something (see
+`erc-autoaway-last-sent-time').  This is the default.
+
+Emacs idle time measures how long Emacs has been idle.  This is
+currently not useful, since Emacs is non-idle when it handles
+ping-pong with IRC servers.  See `erc-autoaway-use-emacs-idle' for
+more information.
+
+User idle time measures how long you have not been sending any
+commands to Emacs, or to your system.  Emacs currently provides no way
+to measure user idle time.
+
+If `erc-auto-discard-away' is set, then typing anything, will
+set you no longer away.
+
+Related variables: `erc-public-away-p' and `erc-away-nickname'."
+  ;; Enable:
+  ((add-hook 'erc-send-completed-hook 'erc-autoaway-reset-idletime)
+   (add-hook 'erc-server-001-functions 'erc-autoaway-reset-idletime)
+   (add-hook 'erc-timer-hook 'erc-autoaway-possibly-set-away)
+   (when erc-autoaway-use-emacs-idle
+     (erc-autoaway-reestablish-idletimer)))
+  ;; Disable:
+  ((remove-hook 'erc-send-completed-hook 'erc-autoaway-reset-idletime)
+   (remove-hook 'erc-server-001-functions 'erc-autoaway-reset-idletime)
+   (remove-hook 'erc-timer-hook 'erc-autoaway-possibly-set-away)
+   (when erc-autoaway-idletimer
+     (erc-cancel-timer erc-autoaway-idletimer)
+     (setq erc-autoaway-idletimer nil))))
+
+(defcustom erc-auto-set-away t
+  "*If non-nil, set away after `erc-autoaway-idle-seconds' seconds of idling.
+ERC autoaway mode can set you away when you idle, and set you no
+longer away when you type something.  This variable controls whether
+you will be set away when you idle.  See `erc-auto-discard-away' for
+the other half."
+  :group 'erc-autoaway
+  :type 'boolean)
+
+(defcustom erc-auto-discard-away t
+  "*If non-nil, sending anything when away automatically discards away state.
+ERC autoaway mode can set you away when you idle, and set you no
+longer away when you type something.  This variable controls whether
+you will be set no longer away when you type something.  See
+`erc-auto-set-away' for the other half.
+See also `erc-autoaway-no-auto-discard-regexp'."
+  :group 'erc-autoaway
+  :type 'boolean)
+
+(defcustom erc-autoaway-no-auto-discard-regexp "^/g?away.*$"
+  "*Input that matches this will not automatically discard away status.
+See `erc-auto-discard-away'."
+  :group 'erc-autoaway
+  :type 'regexp)
+
+(eval-when-compile (defvar erc-autoaway-idle-seconds))
+
+(defun erc-autoaway-reestablish-idletimer ()
+  "Reestablish the emacs idletimer.
+You have to call this function each time you change
+`erc-autoaway-idle-seconds', if `erc-autoaway-use-emacs-idle' is set."
+  (interactive)
+  (when erc-autoaway-idletimer
+    (erc-cancel-timer erc-autoaway-idletimer))
+  (setq erc-autoaway-idletimer
+	(run-with-idle-timer erc-autoaway-idle-seconds
+			     t
+			     'erc-autoaway-set-away
+			     erc-autoaway-idle-seconds)))
+
+(defcustom erc-autoaway-idle-seconds 1800
+  "*Number of seconds after which ERC will set you automatically away.
+If you are changing this variable using lisp instead of customizing it,
+you have to run `erc-autoaway-reestablish-idletimer' afterwards."
+  :group 'erc-autoaway
+  :set (lambda (sym val)
+	 (set-default sym val)
+	 (when erc-autoaway-use-emacs-idle
+	   (erc-autoaway-reestablish-idletimer)))
+  :type 'number)
+
+(defcustom erc-autoaway-message
+  "I'm gone (autoaway after %i seconds of idletime)"
+  "*Message ERC will use when he sets you automatically away.
+It is used as a `format' string with the argument of the idletime in
+seconds."
+  :group 'erc-autoaway
+  :type 'string)
+
+(defvar erc-autoaway-last-sent-time (erc-current-time)
+  "The last time the user sent something.")
+
+(defun erc-autoaway-reset-idletime (line &rest stuff)
+  "Reset the stored idletime for the user.
+This is one global variable since a user talking on one net can talk
+on another net too."
+  (when (and erc-auto-discard-away
+	     (stringp line)
+	     (not (string-match erc-autoaway-no-auto-discard-regexp line)))
+    (erc-autoaway-set-back line))
+  (setq erc-autoaway-last-sent-time (erc-current-time)))
+
+(defun erc-autoaway-set-back (line)
+  "Discard the away state globally."
+  (when (erc-away-p)
+    (setq erc-autoaway-last-sent-time (erc-current-time))
+    (erc-cmd-GAWAY "")))
+
+(defun erc-autoaway-possibly-set-away (current-time)
+  "Set autoaway when `erc-auto-set-away' is true and the idletime is
+exceeds `erc-autoaway-idle-seconds'."
+  ;; A test for (erc-server-process-alive) is not necessary, because
+  ;; this function is called from `erc-timer-hook', which is called
+  ;; whenever the server sends something to the client.
+  (when (and erc-auto-set-away
+	     (not (erc-away-p)))
+    (let ((idle-time (erc-time-diff erc-autoaway-last-sent-time
+				    current-time)))
+      (when (>= idle-time erc-autoaway-idle-seconds)
+	(erc-display-message
+	 nil 'notice nil
+	 (format "Setting automatically away after %i seconds of idle-time"
+		 idle-time))
+	(erc-autoaway-set-away idle-time)))))
+
+(defun erc-autoaway-set-away (idle-time)
+  "Set the away state globally."
+  ;; Note that the idle timer runs, even when Emacs is inactive.  In
+  ;; order to prevent flooding when we connect, we test for an
+  ;; existing process.
+  (when (and (erc-server-process-alive)
+	     (not (erc-away-p)))
+    (erc-cmd-GAWAY (format erc-autoaway-message idle-time))))
+
+(provide 'erc-autoaway)
+
+;;; erc-autoaway.el ends here
+;;
+;; Local Variables:
+;; indent-tabs-mode: t
+;; tab-width: 8
+;; End:
+
+;; arch-tag: 16fc241e-8358-4b56-9fe2-116bdd0ba3bc
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lisp/erc/erc-autojoin.el	Wed Feb 01 10:07:17 2006 +0000
@@ -0,0 +1,139 @@
+;;; erc-autojoin.el --- autojoin channels on connect and reconnects
+
+;; Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+
+;; Author: Alex Schroeder <alex@gnu.org>
+;; Keywords: irc
+;; URL: http://www.emacswiki.org/cgi-bin/wiki.pl?ErcAutoJoin
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
+
+;;; Commentary:
+
+;; This allows us to customize an `erc-autojoin-channels-alist'.  As
+;; we /JOIN and /PART channels, this alist is updated to reflect our
+;; current setup, so that when we reconnect, we rejoin the same
+;; channels.  The alist can be customized, so that the customized
+;; value will be used when we reconnect in our next Emacs session.
+
+;;; Code:
+
+(require 'erc)
+;;; Minor Mode
+
+(defgroup erc-autojoin nil
+  "Enable autojoining."
+  :group 'erc)
+
+;;;###autoload (autoload 'erc-autojoin-mode "erc-autojoin" nil t)
+(define-erc-module autojoin nil
+  "Makes ERC autojoin on connects and reconnects."
+  ((add-hook 'erc-after-connect 'erc-autojoin-channels)
+   (add-hook 'erc-server-JOIN-functions 'erc-autojoin-add)
+   (add-hook 'erc-server-PART-functions 'erc-autojoin-remove))
+  ((remove-hook 'erc-after-connect 'erc-autojoin-channels)
+   (remove-hook 'erc-server-JOIN-functions 'erc-autojoin-add)
+   (remove-hook 'erc-server-PART-functions 'erc-autojoin-remove)))
+
+(defcustom erc-autojoin-channels-alist nil
+  "Alist of channels to autojoin on IRC networks.
+Every element in the alist has the form (SERVER . CHANNELS).
+SERVER is a regexp matching the server, and channels is the
+list of channels to join.
+
+Customize this variable to set the value for your first connect.
+Once you are connected and join and part channels, this alist
+keeps track of what channels you are on, and will join them
+again when you get disconnected.  When you restart Emacs, however,
+those changes are lost, and the customization you saved the last
+time is used again."
+  :group 'erc-autojoin
+  :type '(repeat (cons :tag "Server"
+		       (regexp :tag "Name")
+		       (repeat :tag "Channels"
+			       (string :tag "Name")))))
+
+(defcustom erc-autojoin-domain-only t
+  "Truncate host name to the domain name when joining a server.
+If non-nil, and a channel on the server a.b.c is joined, then
+only b.c is used as the server for `erc-autojoin-channels-alist'.
+This is important for networks that redirect you to other
+servers, presumably in the same domain."
+  :group 'erc-autojoin
+  :type 'boolean)
+
+(defun erc-autojoin-channels (server nick)
+  "Autojoin channels in `erc-autojoin-channels-alist'."
+  (dolist (l erc-autojoin-channels-alist)
+    (when (string-match (car l) server)
+      (dolist (chan (cdr l))
+	(erc-server-send (concat "join " chan))))))
+
+(defun erc-autojoin-add (proc parsed)
+  "Add the channel being joined to `erc-autojoin-channels-alist'."
+  (let* ((chnl (erc-response.contents parsed))
+	 (nick (car (erc-parse-user (erc-response.sender parsed))))
+	 (server (with-current-buffer (process-buffer proc)
+		   (or erc-server-announced-name erc-session-server))))
+    (when (erc-current-nick-p nick)
+      (when (and erc-autojoin-domain-only
+		 (string-match "[^.]+\\.\\([^.]+\\.[^.]+\\)$" server))
+	(setq server (match-string 1 server)))
+      (let ((elem (assoc server erc-autojoin-channels-alist)))
+	(if elem
+	    (unless (member chnl (cdr elem))
+	      (setcdr elem (cons chnl (cdr elem))))
+	  (setq erc-autojoin-channels-alist
+		(cons (list server chnl)
+		      erc-autojoin-channels-alist))))))
+  ;; We must return nil to tell ERC to continue running the other
+  ;; functions.
+  nil)
+
+;; (erc-parse-user "kensanata!~user@dclient217-162-233-228.hispeed.ch")
+
+(defun erc-autojoin-remove (proc parsed)
+  "Remove the channel being left from `erc-autojoin-channels-alist'."
+  (let* ((chnl (car (erc-response.command-args parsed)))
+	 (nick (car (erc-parse-user (erc-response.sender parsed))))
+	 (server (with-current-buffer (process-buffer proc)
+		   (or erc-server-announced-name erc-session-server))))
+    (when (erc-current-nick-p nick)
+      (when (and erc-autojoin-domain-only
+		 (string-match "[^.]+\\.\\([^.]+\\.[^.]+\\)$" server))
+	(setq server (match-string 1 server)))
+      (let ((elem (assoc server erc-autojoin-channels-alist)))
+	(when elem
+	  (setcdr elem (delete chnl (cdr elem)))
+	  (unless (cdr elem)
+	    (setq erc-autojoin-channels-alist
+		  (delete elem erc-autojoin-channels-alist)))))))
+  ;; We must return nil to tell ERC to continue running the other
+  ;; functions.
+  nil)
+
+(provide 'erc-autojoin)
+
+;;; erc-autojoin.el ends here
+;;
+;; Local Variables:
+;; indent-tabs-mode: t
+;; tab-width: 8
+;; End:
+
+;; arch-tag: d62d8b15-8e31-49d6-8a73-12f11e717414
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lisp/erc/erc-backend.el	Wed Feb 01 10:07:17 2006 +0000
@@ -0,0 +1,1786 @@
+;;; erc-backend.el --- Backend network communication for ERC
+
+;; Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc.
+
+;; Filename: erc-backend.el
+;; Author: Lawrence Mitchell <wence@gmx.li>
+;; Created: 2004-05-7
+;; Keywords: IRC chat client internet
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
+
+;;; Commentary:
+
+;; This file defines backend network communication handlers for ERC.
+;;
+;; How things work:
+;;
+;; You define a new handler with `define-erc-response-handler'.  This
+;; defines a function, a corresponding hook variable, and populates a
+;; global hash table `erc-server-responses' with a map from response
+;; to hook variable.  See the function documentation for more
+;; information.
+;;
+;; Upon receiving a line from the server, `erc-parse-server-response'
+;; is called on it.
+;;
+;; A line generally looks like:
+;;
+;; LINE := ':' SENDER ' ' COMMAND ' ' (COMMAND-ARGS ' ')* ':' CONTENTS
+;; SENDER := Not ':' | ' '
+;; COMMAND := Not ':' | ' '
+;; COMMAND-ARGS := Not ':' | ' '
+;;
+;; This gets parsed and stuffed into an `erc-response' struct.  You
+;; can access the fields of the struct with:
+;;
+;; COMMAND --- `erc-response.command'
+;; COMMAND-ARGS --- `erc-response.command-args'
+;; CONTENTS --- `erc-response.contents'
+;; SENDER --- `erc-response.sender'
+;; LINE --- `erc-response.unparsed'
+;;
+;; WARNING, WARNING!!
+;; It's probably not a good idea to destructively modify the list
+;; of command-args in your handlers, since other functions down the
+;; line may well need to access the arguments too.
+;;
+;; That is, unless you're /absolutely/ sure that your handler doesn't
+;; invoke some other function that needs to use COMMAND-ARGS, don't do
+;; something like
+;;
+;; (while (erc-response.command-args parsed)
+;;   (let ((a (pop (erc-response.command-args parsed))))
+;;     ...))
+;;
+;; The parsed response is handed over to
+;; `erc-handle-parsed-server-response', which checks whether it should
+;; carry out duplicate suppression, and then runs `erc-call-hooks'.
+;; `erc-call-hooks' retrieves the relevant hook variable from
+;; `erc-server-responses' and runs it.
+;;
+;; Most handlers then destructure the parsed response in some way
+;; (depending on what the handler is, the arguments have different
+;; meanings), and generally display something, usually using
+;; `erc-display-message'.
+
+;;; TODO:
+
+;; o Generalise the display-line code so that we can use it to
+;;   display the stuff we send, as well as the stuff we receive.
+;;   Then, move all display-related code into another backend-like
+;;   file, erc-display.el, say.
+;;
+;; o Clean up the handlers using new display code (has to be written
+;;   first).
+
+;;; History:
+
+;; 2004/05/10 -- Handler bodies taken out of erc.el and ported to new
+;;               interface.
+
+;; 2005-08-13 -- Moved sending commands from erc.el.
+
+;;; Code:
+
+(require 'erc-compat)
+(eval-when-compile (require 'cl))
+(autoload 'erc-with-buffer "erc" nil nil 'macro)
+(autoload 'erc-log "erc" nil nil 'macro)
+
+;;;; Variables and options
+
+(defvar erc-server-responses (make-hash-table :test #'equal)
+  "Hashtable mapping server responses to their handler hooks.")
+
+(defstruct (erc-response (:conc-name erc-response.))
+  (unparsed "" :type string)
+  (sender "" :type string)
+  (command "" :type string)
+  (command-args '() :type list)
+  (contents "" :type string))
+
+;;; User data
+
+(defvar erc-server-current-nick nil
+  "Nickname on the current server.
+Use `erc-current-nick' to access this.")
+(make-variable-buffer-local 'erc-server-current-nick)
+
+;;; Server attributes
+
+(defvar erc-server-process nil
+  "The process object of the corresponding server connection.")
+(make-variable-buffer-local 'erc-server-process)
+
+(defvar erc-session-server nil
+  "The server name used to connect to for this session.")
+(make-variable-buffer-local 'erc-session-server)
+
+(defvar erc-session-port nil
+  "The port used to connect to.")
+(make-variable-buffer-local 'erc-session-port)
+
+(defvar erc-server-announced-name nil
+  "The name the server announced to use.")
+(make-variable-buffer-local 'erc-server-announced-name)
+
+(defvar erc-server-version nil
+  "The name and version of the server's ircd.")
+(make-variable-buffer-local 'erc-server-version)
+
+(defvar erc-server-parameters nil
+  "Alist listing the supported server parameters.
+
+This is only set if the server sends 005 messages saying what is
+supported on the server.
+
+Entries are of the form:
+  (PARAMETER . VALUE)
+or
+  (PARAMETER) if no value is provided.
+
+Some examples of possible parameters sent by servers:
+CHANMODES=b,k,l,imnpst - list of supported channel modes
+CHANNELLEN=50 - maximum length of channel names
+CHANTYPES=#&!+ - supported channel prefixes
+CHARMAPPING=rfc1459 - character mapping used for nickname and channels
+KICKLEN=160 - maximum allowed kick message length
+MAXBANS=30 - maximum number of bans per channel
+MAXCHANNELS=10 - maximum number of channels allowed to join
+NETWORK=EFnet -  the network identifier
+NICKLEN=9 - maximum allowed length of nicknames
+PREFIX=(ov)@+ - list of channel modes and the user prefixes if user has mode
+RFC2812 - server supports RFC 2812 features
+SILENCE=10 - supports the SILENCE command, maximum allowed number of entries
+TOPICLEN=160 - maximum allowed topic length
+WALLCHOPS - supports sending messages to all operators in a channel")
+(make-variable-buffer-local 'erc-server-parameters)
+
+;;; Server and connection state
+
+(defvar erc-server-connected nil
+  "Non-nil if the `current-buffer' is associated with an open IRC connection.
+This variable is buffer-local.")
+(make-variable-buffer-local 'erc-server-connected)
+
+(defvar erc-server-quitting nil
+  "Non-nil if the user requests a quit.")
+(make-variable-buffer-local 'erc-server-quitting)
+
+(defvar erc-server-lines-sent nil
+  "Line counter.")
+(make-variable-buffer-local 'erc-server-lines-sent)
+
+(defvar erc-server-last-peers '(nil . nil)
+  "Last peers used, both sender and receiver.
+Those are used for /MSG destination shortcuts.")
+(make-variable-buffer-local 'erc-server-last-peers)
+
+(defvar erc-server-last-sent-time nil
+  "Time the message was sent.
+This is useful for flood protection.")
+(make-variable-buffer-local 'erc-server-last-sent-time)
+
+(defvar erc-server-last-ping-time nil
+  "Time the last ping was sent.
+This is useful for flood protection.")
+(make-variable-buffer-local 'erc-server-last-ping-time)
+
+(defvar erc-server-lag nil
+  "Calculated server lag time in seconds.
+This variable is only set in a server buffer.")
+(make-variable-buffer-local 'erc-server-lag)
+
+(defvar erc-server-filter-data nil
+  "The data that arrived from the server
+but has not been processed yet.")
+(make-variable-buffer-local 'erc-server-filter-data)
+
+(defvar erc-server-duplicates (make-hash-table :test 'equal)
+  "Internal variable used to track duplicate messages.")
+(make-variable-buffer-local 'erc-server-duplicates)
+
+;; From Circe
+(defvar erc-server-processing-p nil
+  "Non-nil when we're currently processing a message.
+
+When ERC receives a private message, it sets up a new buffer for
+this query.  These in turn, though, do start flyspell. This
+involves starting an external process, in which case Emacs will
+wait - and when it waits, it does accept other stuff from, say,
+network exceptions.  So, if someone sends you two messages
+quickly after each other, ispell is started for the first, but
+might take long enough for the second message to be processed
+first.")
+(make-variable-buffer-local 'erc-server-processing-p)
+
+(defvar erc-server-flood-last-message 0
+  "When we sent the last message.
+See `erc-server-flood-margin' for an explanation of the flood
+protection algorithm.")
+(make-variable-buffer-local 'erc-server-flood-last-message)
+
+(defvar erc-server-flood-queue nil
+  "The queue of messages waiting to be sent to the server.
+See `erc-server-flood-margin' for an explanation of the flood
+protection algorithm.")
+(make-variable-buffer-local 'erc-server-flood-queue)
+
+(defvar erc-server-flood-timer nil
+  "The timer to resume sending.")
+(make-variable-buffer-local 'erc-server-flood-timer)
+
+;;; IRC protocol and misc options
+
+(defgroup erc-server nil
+  "Parameters for dealing with IRC servers."
+  :group 'erc)
+
+(defcustom erc-server-auto-reconnect t
+  "Non-nil means that ERC will attempt to reestablish broken connections.
+
+Reconnection will happen automatically for any unexpected disconnection."
+  :group 'erc-server
+  :type 'boolean)
+
+(defcustom erc-split-line-length 440
+  "*The maximum length of a single message.
+If a message exceeds this size, it is broken into multiple ones.
+
+IRC allows for lines up to 512 bytes. Two of them are CR LF.
+And a typical message looks like this:
+
+  :nicky!uhuser@host212223.dialin.fnordisp.net PRIVMSG #lazybastards :Hello!
+
+You can limit here the maximum length of the \"Hello!\" part.
+Good luck."
+  :type 'integer
+  :group 'erc-server)
+
+(defcustom erc-server-coding-system (if (and (fboundp 'coding-system-p)
+                                             (coding-system-p 'undecided)
+                                             (coding-system-p 'utf-8))
+                                        '(utf-8 . undecided)
+                                      nil)
+  "The default coding system for incoming and outgoing text.
+This is either a coding system, a cons, a function, or nil.
+
+If a cons, the encoding system for outgoing text is in the car
+and the decoding system for incoming text is in the cdr. The most
+interesting use for this is to put `undecided' in the cdr. If a
+function, it is called with no arguments and should return a
+coding system or a cons as described above. Note that you can use
+the dynamically bound variable `target' to get the current
+target. See `erc-coding-system-for-target'.
+
+If you need to send non-ASCII text to people not using a client that
+does decoding on its own, you must tell ERC what encoding to use.
+Emacs cannot guess it, since it does not know what the people on the
+other end of the line are using."
+  :group 'erc-server
+  :type '(choice (const :tag "None" nil)
+                 coding-system
+                 (cons (coding-system :tag "encoding" :value utf-8)
+                       (coding-system :tag "decoding" :value undecided))
+                 function))
+
+(defcustom erc-encoding-coding-alist nil
+  "Alist of target regexp and coding-system pairs to use.
+This overrides `erc-server-coding-system' depending on the
+current target as returned by `erc-default-target'.
+
+Example: If you know that the channel #linux-ru uses the coding-system
+`cyrillic-koi8', then add '(\"#linux-ru\" . cyrillic-koi8) to the
+alist."
+  :group 'erc-server
+  :type '(repeat (cons (string :tag "Target")
+                       coding-system)))
+
+(defcustom erc-server-connect-function
+  (if (and (fboundp 'open-network-stream-nowait)
+           ;; CVS Emacs claims to define open-network-stream-nowait on
+           ;; windows, however, it does, in fact, not work.
+           (not (memq system-type '(windows-nt cygwin ms-dos darwin))))
+      'open-network-stream-nowait
+    'open-network-stream)
+  "Function used to initiate a connection.
+It should take same arguments as `open-network-stream' does."
+  :group 'erc-server
+  :type 'function)
+
+(defcustom erc-server-prevent-duplicates '("301")
+  "*Either nil or a list of strings.
+Each string is a IRC message type, like PRIVMSG or NOTICE.
+All Message types in that list of subjected to duplicate prevention."
+  :type '(choice (const nil) (list string))
+  :group 'erc-server)
+
+(defcustom erc-server-duplicate-timeout 60
+  "*The time allowed in seconds between duplicate messages.
+
+If two identical messages arrive within this value of one another, the second
+isn't displayed."
+  :type 'integer
+  :group 'erc-server)
+
+;;; Flood-related
+
+;; Most of this is courtesy of Jorgen Schaefer and Circe
+;; (http://www.nongnu.org/circe)
+
+(defcustom erc-server-flood-margin 10
+  "*A margin on how much excess data we send.
+The flood protection algorithm of ERC works like the one
+detailed in RFC 2813, section 5.8 \"Flood control of clients\".
+
+  * If `erc-server-flood-last-message' is less than the current
+    time, set it equal.
+  * While `erc-server-flood-last-message' is less than
+    `erc-server-flood-margin' seconds ahead of the current
+    time, send a message, and increase
+    `erc-server-flood-last-message' by
+    `erc-server-flood-penalty' for each message."
+  :type 'integer
+  :group 'erc-server)
+
+(defcustom erc-server-flood-penalty 3
+  "How much we penalize a message.
+See `erc-server-flood-margin' for an explanation of the flood
+protection algorithm."
+  :type 'integer
+  :group 'erc-server)
+
+;; Ping handling
+
+(defcustom erc-server-send-ping-interval 90
+  "*Interval of sending pings to the server, in seconds.
+If this is set to nil, pinging the server is disabled."
+  :group 'erc-server
+  :type '(choice (const nil) (integer :tag "Seconds")))
+
+(defvar erc-server-ping-handler nil
+  "This variable holds the periodic ping timer.")
+(make-variable-buffer-local 'erc-server-ping-handler)
+
+;;;; Helper functions
+
+;; From Circe
+(defun erc-split-line (longline)
+  "Return a list of lines which are not too long for IRC.
+The length is specified in `erc-split-line-length'.
+
+Currently this is called by `erc-send-input'."
+  (if (< (length longline)
+         erc-split-line-length)
+      (list longline)
+    (with-temp-buffer
+      (insert longline)
+      (let ((fill-column erc-split-line-length))
+        (fill-region (point-min) (point-max)
+                     nil t))
+      (split-string (buffer-string) "\n"))))
+
+;; Used by CTCP functions
+(defun erc-upcase-first-word (str)
+  "Upcase the first word in STR."
+  (with-temp-buffer
+    (insert str)
+    (goto-char (point-min))
+    (upcase-word 1)
+    (buffer-string)))
+
+(defun erc-server-setup-periodical-server-ping (&rest ignore)
+  "Set up a timer to periodically ping the current server."
+  (and erc-server-ping-handler (erc-cancel-timer erc-server-ping-handler))
+  (when erc-server-send-ping-interval
+    (setq erc-server-ping-handler
+          (run-with-timer
+           4 erc-server-send-ping-interval
+           (lambda (buf)
+             (when (buffer-live-p buf)
+               (with-current-buffer buf
+                 (erc-server-send
+                  (format "PING %.0f"
+                          (erc-current-time))))))
+           (current-buffer)))))
+
+(defun erc-server-process-alive ()
+  "Return non-nil when `erc-server-process' is open or running."
+  (and (boundp 'erc-server-process)
+       (processp erc-server-process)
+       (memq (process-status erc-server-process) '(run open))))
+
+;;;; Connecting to a server
+
+(defun erc-server-connect (server port)
+  "Perform the connection and login.
+We will store server variables in the current buffer."
+  (let ((msg (erc-format-message 'connect ?S server ?p port)))
+    (message "%s" msg)
+    (setq erc-server-process
+          (funcall erc-server-connect-function
+                   (format "erc-%s-%s" server port)
+                   (current-buffer) server port))
+    (message "%s...done" msg))
+  ;; Misc server variables
+  (setq erc-server-quitting nil)
+  (setq erc-server-last-sent-time (erc-current-time))
+  (setq erc-server-last-ping-time (erc-current-time))
+  (setq erc-server-lines-sent 0)
+  ;; last peers (sender and receiver)
+  (setq erc-server-last-peers '(nil . nil))
+  ;; process handlers
+  (set-process-sentinel erc-server-process 'erc-process-sentinel)
+  (set-process-filter erc-server-process 'erc-server-filter-function)
+  ;; we do our own encoding and decoding
+  (when (fboundp 'set-process-coding-system)
+    (set-process-coding-system erc-server-process 'raw-text))
+  (set-marker (process-mark erc-server-process) (point))
+  (erc-log "\n\n\n********************************************\n")
+  (message (erc-format-message 'login ?n (erc-current-nick)))
+  ;; wait with script loading until we receive a confirmation (first
+  ;; MOTD line)
+  (if (eq erc-server-connect-function 'open-network-stream-nowait)
+      ;; it's a bit unclear otherwise that it's attempting to establish a
+      ;; connection
+      (erc-display-message nil nil (current-buffer)
+                           "Opening connection..\n")
+    (erc-login)))
+
+(defun erc-server-filter-function (process string)
+  "The process filter for the ERC server."
+  (with-current-buffer (process-buffer process)
+    ;; If you think this is written in a weird way - please refer to the
+    ;; docstring of `erc-server-processing-p'
+    (if erc-server-processing-p
+        (setq erc-server-filter-data
+              (if erc-server-filter-data
+                  (concat erc-server-filter-data string)
+                string))
+      ;; This will be true even if another process is spawned!
+      (let ((erc-server-processing-p t))
+        (setq erc-server-filter-data (if erc-server-filter-data
+                                           (concat erc-server-filter-data
+                                                   string)
+                                         string))
+        (while (and erc-server-filter-data
+                    (string-match "[\n\r]+" erc-server-filter-data))
+          (let ((line (substring erc-server-filter-data
+                                 0 (match-beginning 0))))
+            (setq erc-server-filter-data
+                  (if (= (match-end 0)
+                         (length erc-server-filter-data))
+                      nil
+                    (substring erc-server-filter-data
+                               (match-end 0))))
+            (erc-parse-server-response process line)))))))
+
+(defun erc-process-sentinel-1 (event)
+  "This will be called when erc-process-sentinel has decided that we
+are going to quit.  Determine whether user has quit or whether erc has
+been terminated.  Conditionally try to reconnect and take appropriate
+action."
+  (if erc-server-quitting
+      ;; normal quit
+      (progn
+        (let ((string "\n\n*** ERC finished ***\n")
+              (inhibit-read-only t))
+          (erc-put-text-property 0 (length string)
+                                 'face 'erc-error-face string)
+          (insert string))
+        (when erc-kill-server-buffer-on-quit
+          (set-buffer-modified-p nil)
+          (kill-buffer (current-buffer))))
+    ;; unexpected disconnect
+    (erc-display-message nil 'error (current-buffer)
+                         (if erc-server-auto-reconnect
+                             'disconnected
+                           'disconnected-noreconnect))
+    (erc-update-mode-line)
+    (erc-set-active-buffer (current-buffer))
+    (setq erc-server-last-sent-time 0)
+    (setq erc-server-lines-sent 0)
+    (if (and erc-server-auto-reconnect
+             (not (string-match "^deleted" event))
+             ;; open-network-stream-nowait error for connection refused
+             (not (string-match "^failed with code 111" event)))
+        ;; Yuck, this should perhaps funcall
+        ;; erc-server-reconnect-function with no args
+        (erc erc-session-server erc-session-port erc-server-current-nick
+             erc-session-user-full-name t erc-session-password)
+      ;; terminate, do not reconnect
+      (let ((string (concat "\n\n*** ERC terminated: " event
+                            "\n"))
+            (inhibit-read-only t))
+        (erc-put-text-property 0 (length string)
+                               'face 'erc-error-face string)
+        (insert string)))))
+
+(defun erc-process-sentinel (cproc event)
+  "Sentinel function for ERC process."
+  (with-current-buffer (process-buffer cproc)
+    (erc-log (format
+              "SENTINEL: proc: %S	 status: %S  event: %S (quitting: %S)"
+              cproc (process-status cproc) event erc-server-quitting))
+    (if (string-match "^open" event)
+        ;; newly opened connection (no wait)
+        (erc-login)
+      ;; assume event is 'failed
+      (let ((buf (process-buffer cproc)))
+        (erc-with-all-buffers-of-server cproc nil
+                                        (setq erc-server-connected nil))
+        (when erc-server-ping-handler
+          (progn (erc-cancel-timer erc-server-ping-handler)
+                 (setq erc-server-ping-handler nil)))
+        (run-hook-with-args 'erc-disconnected-hook
+                            (erc-current-nick) (system-name) "")
+        ;; Remove the prompt
+        (forward-line 0)
+        (erc-remove-text-properties-region (point) (point-max))
+        (delete-region (point) (point-max))
+        ;; Decide what to do with the buffer
+        ;; Restart if disconnected
+        (erc-process-sentinel-1 event)
+        ;; Make sure we don't write to the buffer if it has been
+        ;; killed
+        (when (buffer-live-p buf)
+          (erc-update-mode-line)
+          (set-buffer-modified-p nil))))))
+
+;;;; Sending messages
+
+(defun erc-coding-system-for-target (target)
+  "Return the coding system or cons cell appropriate for TARGET.
+This is determined via `erc-encoding-coding-alist' or
+`erc-server-coding-system'."
+  (or (cdr (assoc target erc-encoding-coding-alist))
+      (and (functionp erc-server-coding-system)
+           (funcall erc-server-coding-system))
+      erc-server-coding-system))
+
+(defun erc-decode-string-from-target (str target)
+  "Decode STR as appropriate for TARGET.
+This is indicated by `erc-encoding-coding-alist', defaulting to the value of
+`erc-server-coding-system'."
+  (unless (stringp str)
+    (setq str ""))
+  (let ((coding (erc-coding-system-for-target target)))
+    (when (consp coding)
+      (setq coding (cdr coding)))
+    (erc-decode-coding-string str coding)))
+
+;; proposed name, not used by anything yet
+(defun erc-send-line (text display-fn)
+  "Send TEXT to the current server.  Wrapping and flood control apply.
+Use DISPLAY-FN to show the results."
+  (mapc (lambda (line)
+          (erc-server-send line)
+          (funcall display-fn))
+        (erc-split-line text)))
+
+;; From Circe, with modifications
+(defun erc-server-send (string &optional forcep target)
+  "Send STRING to the current server.
+If FORCEP is non-nil, no flood protection is done - the string is
+sent directly. This might cause the messages to arrive in a wrong
+order.
+
+If TARGET is specified, look up encoding information for that
+channel in `erc-encoding-coding-alist' or
+`erc-server-coding-system'.
+
+See `erc-server-flood-margin' for an explanation of the flood
+protection algorithm."
+  (erc-log (concat "erc-server-send: " string "(" (buffer-name) ")"))
+  (setq erc-server-last-sent-time (erc-current-time))
+  (let ((buf (erc-server-buffer))
+        (encoding (erc-coding-system-for-target
+                   (or target (erc-default-target)))))
+    (when (consp encoding)
+      (setq encoding (car encoding)))
+    (if (and buf
+             (erc-server-process-alive))
+        (with-current-buffer buf
+          (let ((str (concat string "\r\n")))
+            (if forcep
+                (progn
+                  (setq erc-server-flood-last-message
+                        (+ erc-server-flood-penalty
+                           erc-server-flood-last-message))
+                  (erc-log-irc-protocol str 'outbound)
+                  (condition-case err
+                      (progn
+                        ;; Set encoding just before sending the string
+                        (when (fboundp 'set-process-coding-system)
+                          (set-process-coding-system erc-server-process
+                                                     'raw-text encoding))
+                        (process-send-string erc-server-process str))
+                    ;; See `erc-server-send-queue' for full
+                    ;; explanation of why we need this condition-case
+                    (error nil)))
+              (setq erc-server-flood-queue
+                    (append erc-server-flood-queue
+                            (list (cons str encoding))))
+              (erc-server-send-queue (current-buffer))))
+          t)
+      (message "ERC: No process running")
+      nil)))
+
+;; From Circe
+(defun erc-server-send-queue (buffer)
+  "Send messages in `erc-server-flood-queue'.
+See `erc-server-flood-margin' for an explanation of the flood
+protection algorithm."
+  (with-current-buffer buffer
+    (let ((now (erc-current-time)))
+      (when erc-server-flood-timer
+        (erc-cancel-timer erc-server-flood-timer)
+        (setq erc-server-flood-timer nil))
+      (when (< erc-server-flood-last-message
+               now)
+        (setq erc-server-flood-last-message now))
+      (while (and erc-server-flood-queue
+                  (< erc-server-flood-last-message
+                     (+ now erc-server-flood-margin)))
+        (let ((msg (caar erc-server-flood-queue))
+              (encoding (cdar erc-server-flood-queue)))
+          (setq erc-server-flood-queue (cdr erc-server-flood-queue)
+                erc-server-flood-last-message
+                (+ erc-server-flood-last-message
+                   erc-server-flood-penalty))
+          (erc-log-irc-protocol msg 'outbound)
+          (erc-log (concat "erc-server-send-queue: "
+                           msg "(" (buffer-name buffer) ")"))
+          (when (erc-server-process-alive)
+            (condition-case err
+                ;; Set encoding just before sending the string
+                (progn
+                  (when (fboundp 'set-process-coding-system)
+                    (set-process-coding-system erc-server-process
+                                               'raw-text encoding))
+                  (process-send-string erc-server-process msg))
+              ;; Sometimes the send can occur while the process is
+              ;; being killed, which results in a weird SIGPIPE error.
+              ;; Catch this and ignore it.
+              (error nil)))))
+      (when erc-server-flood-queue
+        (setq erc-server-flood-timer
+              (run-at-time 2 nil #'erc-server-send-queue buffer))))))
+
+(defun erc-message (message-command line &optional force)
+  "Send LINE to the server as a privmsg or a notice.
+MESSAGE-COMMAND should be either \"PRIVMSG\" or \"NOTICE\".
+If the target is \",\", the last person you've got a message from will
+be used. If the target is \".\", the last person you've sent a message
+to will be used."
+  (cond
+   ((string-match "^\\s-*\\(\\S-+\\) ?\\(.*\\)" line)
+    (let ((tgt (match-string 1 line))
+          (s (match-string 2 line)))
+      (erc-log (format "cmd: MSG(%s): [%s] %s" message-command tgt s))
+      (cond
+       ((string= tgt ",")
+        (if (car erc-server-last-peers)
+            (setq tgt (car erc-server-last-peers))
+          (setq tgt nil)))
+       ((string= tgt ".")
+        (if (cdr erc-server-last-peers)
+            (setq tgt (cdr erc-server-last-peers))
+          (setq tgt nil))))
+      (cond
+       (tgt
+        (setcdr erc-server-last-peers tgt)
+        (erc-server-send (format "%s %s :%s" message-command tgt s)
+                         force))
+       (t
+        (erc-display-message nil 'error (current-buffer) 'no-target))))
+    t)
+   (t nil)))
+
+;;; CTCP
+
+(defun erc-send-ctcp-message (tgt l &optional force)
+  "Send CTCP message L to TGT.
+
+If TGT is nil the message is not sent.
+The command must contain neither a prefix nor a trailing `\\n'.
+
+See also `erc-server-send'."
+  (let ((l (erc-upcase-first-word l)))
+    (cond
+     (tgt
+      (erc-log (format "erc-send-CTCP-message: [%s] %s" tgt l))
+      (erc-server-send (format "PRIVMSG %s :\C-a%s\C-a" tgt l)
+                       force)))))
+
+(defun erc-send-ctcp-notice (tgt l &optional force)
+  "Send CTCP notice L to TGT.
+
+If TGT is nil the message is not sent.
+The command must contain neither a prefix nor a trailing `\\n'.
+
+See also `erc-server-send'."
+  (let ((l (erc-upcase-first-word l)))
+    (cond
+     (tgt
+      (erc-log (format "erc-send-CTCP-notice: [%s] %s" tgt l))
+      (erc-server-send (format "NOTICE %s :\C-a%s\C-a" tgt l)
+                       force)))))
+
+;;;; Handling responses
+
+(defun erc-parse-server-response (proc string)
+  "Parse and act upon a complete line from an IRC server.
+PROC is the process (connection) from which STRING was received.
+PROCs `process-buffer' is `current-buffer' when this function is called."
+  (unless (string= string "") ;; Ignore empty strings
+    (save-match-data
+      (let ((posn (if (eq (aref string 0) ?:)
+                      (string-match " " string)
+                    0))
+            (msg (make-erc-response :unparsed string)))
+
+        (setf (erc-response.sender msg)
+              (if (eq posn 0)
+                  erc-session-server
+                (substring string 1 posn)))
+
+        (setf (erc-response.command msg)
+              (let* ((bposn (string-match "[^ ]" string posn))
+                     (eposn (string-match " " string bposn)))
+                (setq posn (and eposn
+                                (string-match "[^ ]" string eposn)))
+                (substring string bposn eposn)))
+
+        (while (and posn
+                    (not (eq (aref string posn) ?:)))
+          (push (let* ((bposn posn)
+                       (eposn (string-match " " string bposn)))
+                  (setq posn (and eposn
+                                  (string-match "[^ ]" string eposn)))
+                  (substring string bposn eposn))
+                (erc-response.command-args msg)))
+        (when posn
+      (let ((str (substring string (1+ posn))))
+        (push str (erc-response.command-args msg))))
+
+    (setf (erc-response.contents msg)
+          (first (erc-response.command-args msg)))
+
+    (setf (erc-response.command-args msg)
+          (nreverse (erc-response.command-args msg)))
+
+    (erc-decode-parsed-server-response msg)
+
+    (erc-handle-parsed-server-response proc msg)))))
+
+(defun erc-decode-parsed-server-response (parsed-response)
+  "Decode a pre-parsed PARSED-RESPONSE before it can be handled.
+
+If there is a channel name in `erc-response.command-args', decode
+`erc-response' according to this channel name and
+`erc-encoding-coding-alist', or use `erc-server-coding-system'
+for decoding."
+  (let ((args (erc-response.command-args parsed-response))
+        (decode-target nil)
+        (decoded-args ()))
+    (dolist (arg args nil)
+      (when (string-match "^[#&].*" arg)
+        (setq decode-target arg)))
+    (when (stringp decode-target)
+      (setq decode-target (erc-decode-string-from-target decode-target nil)))
+    (setf (erc-response.unparsed parsed-response)
+          (erc-decode-string-from-target
+           (erc-response.unparsed parsed-response)
+           decode-target))
+    (setf (erc-response.sender parsed-response)
+          (erc-decode-string-from-target
+           (erc-response.sender parsed-response)
+           decode-target))
+    (setf (erc-response.command parsed-response)
+          (erc-decode-string-from-target
+           (erc-response.command parsed-response)
+           decode-target))
+    (dolist (arg (nreverse args) nil)
+      (push (erc-decode-string-from-target arg decode-target)
+            decoded-args))
+    (setf (erc-response.command-args parsed-response) decoded-args)
+    (setf (erc-response.contents parsed-response)
+          (erc-decode-string-from-target
+           (erc-response.contents parsed-response)
+           decode-target))))
+
+(defun erc-handle-parsed-server-response (process parsed-response)
+  "Handle a pre-parsed PARSED-RESPONSE from PROCESS.
+
+Hands off to helper functions via `erc-call-hooks'."
+  (if (member (erc-response.command parsed-response)
+              erc-server-prevent-duplicates)
+      (let ((m (erc-response.unparsed parsed-response)))
+        ;; duplicate supression
+        (if (< (or (gethash m erc-server-duplicates) 0)
+               (- (erc-current-time) erc-server-duplicate-timeout))
+            (erc-call-hooks process parsed-response))
+        (puthash m (erc-current-time) erc-server-duplicates))
+    ;; Hand off to the relevant handler.
+    (erc-call-hooks process parsed-response)))
+
+(defun erc-get-hook (command)
+  "Return the hook variable associated with COMMAND.
+
+See also `erc-server-responses'."
+  (gethash (format (if (numberp command) "%03i" "%s") command)
+           erc-server-responses))
+
+(defun erc-call-hooks (process message)
+  "Call hooks associated with MESSAGE in PROCESS.
+
+Finds hooks by looking in the `erc-server-responses' hashtable."
+  (let ((hook (or (erc-get-hook (erc-response.command message))
+                  'erc-default-server-functions)))
+    (run-hook-with-args-until-success hook process message)
+    (with-current-buffer (erc-server-buffer)
+      (run-hook-with-args 'erc-timer-hook (erc-current-time)))))
+
+(add-hook 'erc-default-server-functions 'erc-handle-unknown-server-response)
+
+(defun erc-handle-unknown-server-response (proc parsed)
+  "Display unknown server response's message."
+  (let ((line (concat (erc-response.sender parsed)
+                      " "
+                      (erc-response.command parsed)
+                      " "
+                      (mapconcat 'identity (erc-response.command-args parsed)
+                                 " "))))
+    (erc-display-message parsed 'notice proc line)))
+
+
+(put 'define-erc-response-handler 'edebug-form-spec
+     '(&define :name erc-response-handler
+               (name &rest name)
+               &optional sexp sexp def-body))
+
+(defmacro* define-erc-response-handler ((name &rest aliases)
+                                        &optional extra-fn-doc extra-var-doc
+                                        &rest fn-body)
+  "Define an ERC handler hook/function pair.
+NAME is the response name as sent by the server (see the IRC RFC for
+meanings).
+
+This creates:
+ - a hook variable `erc-server-NAME-functions' initialised to `erc-server-NAME'.
+ - a function `erc-server-NAME' with body FN-BODY.
+
+If ALIASES is non-nil, each alias in ALIASES is `defalias'ed to
+`erc-server-NAME'.
+Alias hook variables are created as `erc-server-ALIAS-functions' and
+initialised to the same default value as `erc-server-NAME-functions'.
+
+FN-BODY is the body of `erc-server-NAME' it may refer to the two
+function arguments PROC and PARSED.
+
+If EXTRA-FN-DOC is non-nil, it is inserted at the beginning of the
+defined function's docstring.
+
+If EXTRA-VAR-DOC is non-nil, it is inserted at the beginning of the
+defined variable's docstring.
+
+As an example:
+
+  (define-erc-response-handler (311 WHOIS WI)
+    \"Some non-generic function documentation.\"
+    \"Some non-generic variable documentation.\"
+    (do-stuff-with-whois proc parsed))
+
+Would expand to:
+
+  (prog2
+      (defvar erc-server-311-functions 'erc-server-311
+        \"Some non-generic variable documentation.
+
+  Hook called upon receiving a 311 server response.
+  Each function is called with two arguments, the process associated
+  with the response and the parsed response.
+  See also `erc-server-311'.\")
+
+      (defun erc-server-311 (proc parsed)
+        \"Some non-generic function documentation.
+
+  Handler for a 311 server response.
+  PROC is the server process which returned the response.
+  PARSED is the actual response as an `erc-response' struct.
+  If you want to add responses don't modify this function, but rather
+  add things to `erc-server-311-functions' instead.\"
+        (do-stuff-with-whois proc parsed))
+
+    (puthash \"311\" 'erc-server-311-functions erc-server-responses)
+    (puthash \"WHOIS\" 'erc-server-WHOIS-functions erc-server-responses)
+    (puthash \"WI\" 'erc-server-WI-functions erc-server-responses)
+
+    (defalias 'erc-server-WHOIS 'erc-server-311)
+    (defvar erc-server-WHOIS-functions 'erc-server-311
+      \"Some non-generic variable documentation.
+
+  Hook called upon receiving a WHOIS server response.
+  Each function is called with two arguments, the process associated
+  with the response and the parsed response.
+  See also `erc-server-311'.\")
+
+    (defalias 'erc-server-WI 'erc-server-311)
+    (defvar erc-server-WI-functions 'erc-server-311
+      \"Some non-generic variable documentation.
+
+  Hook called upon receiving a WI server response.
+  Each function is called with two arguments, the process associated
+  with the response and the parsed response.
+  See also `erc-server-311'.\"))
+
+\(fn (NAME &rest ALIASES) &optional EXTRA-FN-DOC EXTRA-VAR-DOC &rest FN-BODY)"
+  (if (numberp name) (setq name (intern (format "%03i" name))))
+  (setq aliases (mapcar (lambda (a)
+                          (if (numberp a)
+                              (format "%03i" a)
+                            a))
+                        aliases))
+  (let* ((hook-name (intern (format "erc-server-%s-functions" name)))
+         (fn-name (intern (format "erc-server-%s" name)))
+         (hook-doc (format "%sHook called upon receiving a %%s server response.
+Each function is called with two arguments, the process associated
+with the response and the parsed response.
+See also `%s'."
+                           (if extra-var-doc
+                               (concat extra-var-doc "\n\n")
+                             "")
+                           fn-name))
+         (fn-doc (format "%sHandler for a %s server response.
+PROC is the server process which returned the response.
+PARSED is the actual response as an `erc-response' struct.
+If you want to add responses don't modify this function, but rather
+add things to `%s' instead."
+                         (if extra-fn-doc
+                             (concat extra-fn-doc "\n\n")
+                           "")
+                         name hook-name))
+         (fn-alternates
+          (loop for alias in aliases
+                collect (intern (format "erc-server-%s" alias))))
+         (var-alternates
+          (loop for alias in aliases
+                collect (intern (format "erc-server-%s-functions" alias)))))
+    `(prog2
+         ;; Normal hook variable.
+         (defvar ,hook-name ',fn-name ,(format hook-doc name))
+         ;; Handler function
+         (defun ,fn-name (proc parsed)
+           ,fn-doc
+           ,@fn-body)
+
+       ;; Make find-function and find-variable find them
+       (put ',fn-name 'definition-name ',name)
+       (put ',hook-name 'definition-name ',name)
+
+       ;; Hashtable map of responses to hook variables
+       ,@(loop for response in (cons name aliases)
+               for var in (cons hook-name var-alternates)
+               collect `(puthash ,(format "%s" response) ',var
+                                 erc-server-responses))
+       ;; Alternates.
+       ;; Functions are defaliased, hook variables are defvared so we
+       ;; can add hooks to one alias, but not another.
+       ,@(loop for fn in fn-alternates
+               for var in var-alternates
+               for a in aliases
+               nconc (list `(defalias ',fn ',fn-name)
+                           `(defvar ,var ',fn-name ,(format hook-doc a))
+                           `(put ',var 'definition-name ',hook-name))))))
+
+(define-erc-response-handler (ERROR)
+  "Handle an ERROR command from the server." nil
+  (erc-display-message
+   parsed 'error nil 'ERROR
+   ?s (erc-response.sender parsed) ?c (erc-response.contents parsed)))
+
+(define-erc-response-handler (INVITE)
+  "Handle invitation messages."
+  nil
+  (let ((target (first (erc-response.command-args parsed)))
+        (chnl (erc-response.contents parsed)))
+    (multiple-value-bind (nick login host)
+        (erc-parse-user (erc-response.sender parsed))
+      (setq erc-invitation chnl)
+      (when (string= target (erc-current-nick))
+        (erc-display-message
+         parsed 'notice 'active
+         'INVITE ?n nick ?u login ?h host ?c chnl)))))
+
+
+(define-erc-response-handler (JOIN)
+  "Handle join messages."
+  nil
+  (let ((chnl (erc-response.contents parsed))
+        (buffer nil))
+    (multiple-value-bind (nick login host)
+        (erc-parse-user (erc-response.sender parsed))
+      ;; strip the stupid combined JOIN facility (IRC 2.9)
+      (if (string-match "^\\(.*\\)?\^g.*$" chnl)
+          (setq chnl (match-string 1 chnl)))
+      (save-excursion
+        (let* ((str (cond
+                     ;; If I have joined a channel
+                     ((erc-current-nick-p nick)
+                      (setq buffer (erc erc-session-server erc-session-port
+                                        nick erc-session-user-full-name
+                                        nil nil
+                                        erc-default-recipients chnl
+                                        erc-server-process))
+                      (when buffer
+                        (set-buffer buffer)
+                        (erc-add-default-channel chnl)
+                        (erc-server-send (format "MODE %s" chnl)))
+                      (erc-with-buffer (chnl proc)
+                        (erc-channel-begin-receiving-names))
+                      (erc-update-mode-line)
+                      (run-hooks 'erc-join-hook)
+                      (erc-make-notice
+                       (erc-format-message 'JOIN-you ?c chnl)))
+                     (t
+                      (setq buffer (erc-get-buffer chnl proc))
+                      (erc-make-notice
+                       (erc-format-message
+                        'JOIN ?n nick ?u login ?h host ?c chnl))))))
+          (when buffer (set-buffer buffer))
+          (erc-update-channel-member chnl nick nick t nil nil host login)
+          ;; on join, we want to stay in the new channel buffer
+          ;;(set-buffer ob)
+          (erc-display-message parsed nil buffer str))))))
+
+(define-erc-response-handler (KICK)
+  "Handle kick messages received from the server." nil
+  (let* ((ch (first (erc-response.command-args parsed)))
+         (tgt (second (erc-response.command-args parsed)))
+         (reason (erc-trim-string (erc-response.contents parsed)))
+         (buffer (erc-get-buffer ch proc)))
+    (multiple-value-bind (nick login host)
+        (erc-parse-user (erc-response.sender parsed))
+      (erc-remove-channel-member buffer tgt)
+      (cond
+       ((string= tgt (erc-current-nick))
+        (erc-display-message
+         parsed 'notice buffer
+         'KICK-you ?n nick ?u login ?h host ?c ch ?r reason)
+        (run-hook-with-args 'erc-kick-hook buffer)
+        (erc-with-buffer
+            (buffer)
+          (erc-remove-channel-users))
+        (erc-delete-default-channel ch buffer)
+        (erc-update-mode-line buffer))
+       ((string= nick (erc-current-nick))
+        (erc-display-message
+         parsed 'notice buffer
+         'KICK-by-you ?k tgt ?c ch ?r reason))
+       (t (erc-display-message
+             parsed 'notice buffer
+             'KICK ?k tgt ?n nick ?u login ?h host ?c ch ?r reason))))))
+
+(define-erc-response-handler (MODE)
+  "Handle server mode changes." nil
+  (let ((tgt (first (erc-response.command-args parsed)))
+        (mode (mapconcat 'identity (cdr (erc-response.command-args parsed))
+                         " ")))
+    (multiple-value-bind (nick login host)
+        (erc-parse-user (erc-response.sender parsed))
+      (erc-log (format "MODE: %s -> %s: %s" nick tgt mode))
+      ;; dirty hack
+      (let ((buf (cond ((erc-channel-p tgt)
+                        (erc-get-buffer tgt proc))
+                       ((string= tgt (erc-current-nick)) nil)
+                       ((erc-active-buffer) (erc-active-buffer))
+                       (t (erc-get-buffer tgt)))))
+        (with-current-buffer (or buf
+                                 (current-buffer))
+          (erc-update-modes tgt mode nick host login))
+          (if (or (string= login "") (string= host ""))
+              (erc-display-message parsed 'notice buf
+                                   'MODE-nick ?n nick
+                                   ?t tgt ?m mode)
+            (erc-display-message parsed 'notice buf
+                                 'MODE ?n nick ?u login
+                                 ?h host ?t tgt ?m mode)))
+      (erc-banlist-update proc parsed))))
+
+(define-erc-response-handler (NICK)
+  "Handle nick change messages." nil
+  (let ((nn (erc-response.contents parsed))
+        bufs)
+    (multiple-value-bind (nick login host)
+        (erc-parse-user (erc-response.sender parsed))
+      (setq bufs (erc-buffer-list-with-nick nick proc))
+      (erc-log (format "NICK: %s -> %s" nick nn))
+      ;; if we had a query with this user, make sure future messages will be
+      ;; sent to the correct nick. also add to bufs, since the user will want
+      ;; to see the nick change in the query, and if it's a newly begun query,
+      ;; erc-channel-users won't contain it
+      (erc-buffer-filter
+       (lambda ()
+         (when (equal (erc-default-target) nick)
+           (setq erc-default-recipients
+                 (cons nn (cdr erc-default-recipients)))
+           (rename-buffer nn)
+           (erc-update-mode-line)
+           (add-to-list 'bufs (current-buffer)))))
+      (erc-update-user-nick nick nn host nil nil login)
+      (cond
+       ((string= nick (erc-current-nick))
+        (add-to-list 'bufs (erc-server-buffer))
+        (erc-set-current-nick nn)
+        (erc-update-mode-line)
+        (setq erc-nick-change-attempt-count 0)
+        (setq erc-default-nicks (if (consp erc-nick) erc-nick (list erc-nick)))
+        (erc-display-message
+         parsed 'notice bufs
+         'NICK-you ?n nick ?N nn)
+        (run-hook-with-args 'erc-nick-changed-functions nn nick))
+       (t
+        (erc-handle-user-status-change 'nick (list nick login host) (list nn))
+        (erc-display-message parsed 'notice bufs 'NICK ?n nick
+                             ?u login ?h host ?N nn))))))
+
+(define-erc-response-handler (PART)
+  "Handle part messages." nil
+  (let* ((chnl (first (erc-response.command-args parsed)))
+         (reason (erc-trim-string (erc-response.contents parsed)))
+         (buffer (erc-get-buffer chnl proc)))
+    (multiple-value-bind (nick login host)
+        (erc-parse-user (erc-response.sender parsed))
+      (erc-remove-channel-member buffer nick)
+      (erc-display-message parsed 'notice buffer
+                           'PART ?n nick ?u login
+                           ?h host ?c chnl ?r (or reason ""))
+      (when (string= nick (erc-current-nick))
+        (run-hook-with-args 'erc-part-hook buffer)
+        (erc-with-buffer
+            (buffer)
+          (erc-remove-channel-users))
+        (erc-delete-default-channel chnl buffer)
+        (erc-update-mode-line buffer)
+        (when erc-kill-buffer-on-part
+          (kill-buffer buffer))))))
+
+(define-erc-response-handler (PING)
+  "Handle ping messages." nil
+  (let ((pinger (first (erc-response.command-args parsed))))
+    (erc-log (format "PING: %s" pinger))
+    ;; ping response to the server MUST be forced, or you can lose big
+    (erc-server-send (format "PONG :%s" pinger) t)
+    (when erc-verbose-server-ping
+      (erc-display-message
+       parsed 'error proc
+       'PING ?s (erc-time-diff erc-server-last-ping-time (erc-current-time))))
+    (setq erc-server-last-ping-time (erc-current-time))))
+
+(define-erc-response-handler (PONG)
+  "Handle pong messages." nil
+  (let ((time (string-to-number (erc-response.contents parsed))))
+    (when (> time 0)
+      (setq erc-server-lag (erc-time-diff time (erc-current-time)))
+      (when erc-verbose-server-ping
+        (erc-display-message
+         parsed 'notice proc 'PONG
+         ?h (first (erc-response.command-args parsed)) ?i erc-server-lag
+         ?s (if (/= erc-server-lag 1) "s" "")))
+      (erc-update-mode-line))))
+
+(define-erc-response-handler (PRIVMSG NOTICE)
+  nil nil
+  (let ((sender-spec (erc-response.sender parsed))
+        (cmd (erc-response.command parsed))
+        (tgt (car (erc-response.command-args parsed)))
+        (msg (erc-response.contents parsed)))
+    (if (or (erc-ignored-user-p sender-spec)
+            (erc-ignored-reply-p msg tgt proc))
+        (when erc-minibuffer-ignored
+          (message "Ignored %s from %s to %s" cmd sender-spec tgt))
+      (let* ((sndr (erc-parse-user sender-spec))
+             (nick (nth 0 sndr))
+             (login (nth 1 sndr))
+             (host (nth 2 sndr))
+             (msgp (string= cmd "PRIVMSG"))
+             (noticep (string= cmd "NOTICE"))
+             ;; S.B. downcase *both* tgt and current nick
+             (privp (erc-current-nick-p tgt))
+             s buffer
+             fnick)
+        (setf (erc-response.contents parsed) msg)
+        (setq buffer (erc-get-buffer (if privp nick tgt) proc))
+        (when buffer
+          (with-current-buffer buffer
+            ;; update the chat partner info.  Add to the list if private
+            ;; message.	 We will accumulate private identities indefinitely
+            ;; at this point.
+            (erc-update-channel-member (if privp nick tgt) nick nick
+                                       privp nil nil host login nil nil t)
+            (let ((cdata (erc-get-channel-user nick)))
+              (setq fnick (funcall erc-format-nick-function
+                                   (car cdata) (cdr cdata))))))
+        (cond
+         ((erc-is-message-ctcp-p msg)
+          (setq s (if msgp
+                      (erc-process-ctcp-query proc parsed nick login host)
+                    (erc-process-ctcp-reply proc parsed nick login host
+                                            (match-string 1 msg)))))
+         (t
+          (setcar erc-server-last-peers nick)
+          (setq s (erc-format-privmessage
+                   (or fnick nick) msg
+                   ;; If buffer is a query buffer,
+                   ;; format the nick as for a channel.
+                   (and (not (and buffer
+                                  (erc-query-buffer-p buffer)
+                                  erc-format-query-as-channel-p))
+                        privp)
+                   msgp))))
+        (when s
+          (if (and noticep privp)
+              (progn
+                (run-hook-with-args 'erc-echo-notice-always-hook
+                                    s parsed buffer nick)
+                (run-hook-with-args-until-success
+                 'erc-echo-notice-hook s parsed buffer nick))
+            (erc-display-message parsed nil buffer s)))
+        (when (string= cmd "PRIVMSG")
+          (erc-auto-query proc parsed))))))
+
+;; FIXME: need clean way of specifiying extra hooks in
+;; define-erc-response-handler.
+(add-hook 'erc-server-PRIVMSG-functions 'erc-auto-query)
+
+(define-erc-response-handler (QUIT)
+  nil nil
+  (let ((reason (erc-response.contents parsed))
+        bufs)
+    (multiple-value-bind (nick login host)
+        (erc-parse-user (erc-response.sender parsed))
+      (setq bufs (erc-buffer-list-with-nick nick proc))
+      (erc-remove-user nick)
+      (setq reason (erc-wash-quit-reason reason nick login host))
+      (erc-display-message parsed 'notice bufs
+                           'QUIT ?n nick ?u login
+                           ?h host ?r reason))))
+
+(define-erc-response-handler (TOPIC)
+  nil nil
+  (let* ((ch (first (erc-response.command-args parsed)))
+         (topic (erc-trim-string (erc-response.contents parsed)))
+         (time (format-time-string "%T %m/%d/%y" (current-time))))
+    (multiple-value-bind (nick login host)
+        (erc-parse-user (erc-response.sender parsed))
+      (erc-update-channel-member ch nick nick nil nil nil host login)
+      (erc-update-channel-topic ch (format "%s\C-o (%s, %s)" topic nick time))
+      (erc-display-message parsed 'notice (erc-get-buffer ch proc)
+                           'TOPIC ?n nick ?u login ?h host
+                           ?c ch ?T topic))))
+
+(define-erc-response-handler (WALLOPS)
+  nil nil
+  (let ((message (erc-response.contents parsed)))
+    (multiple-value-bind (nick login host)
+        (erc-parse-user (erc-response.sender parsed))
+      (erc-display-message
+       parsed 'notice nil
+       'WALLOPS ?n nick ?m message))))
+
+(define-erc-response-handler (001)
+  "Set `erc-server-current-nick' to reflect server settings and display the welcome message."
+  nil
+  (erc-set-current-nick (first (erc-response.command-args parsed)))
+  (erc-update-mode-line)                ; needed here?
+  (setq erc-nick-change-attempt-count 0)
+  (setq erc-default-nicks (if (consp erc-nick) erc-nick (list erc-nick)))
+  (erc-display-message
+   parsed 'notice 'active (erc-response.contents parsed)))
+
+(define-erc-response-handler (MOTD 002 003 371 372 374 375)
+  "Display the server's message of the day." nil
+  (erc-handle-login)
+  (erc-display-message
+   parsed 'notice (if erc-server-connected 'active proc)
+   (erc-response.contents parsed)))
+
+(define-erc-response-handler (376 422)
+  nil nil
+  (erc-server-MOTD proc parsed)
+  (erc-connection-established proc parsed))
+
+(define-erc-response-handler (004)
+  nil nil
+  (multiple-value-bind (server-name server-version)
+      (cdr (erc-response.command-args parsed))
+    (setq erc-server-version server-version)
+    (setq erc-server-announced-name server-name)
+    (erc-update-mode-line-buffer (process-buffer proc))
+    (erc-display-message
+     parsed 'notice proc
+     's004 ?s server-name ?v server-version
+     ?U (fourth (erc-response.command-args parsed))
+     ?C (fifth (erc-response.command-args parsed)))))
+
+(define-erc-response-handler (005)
+  "Set the variable `erc-server-parameters' and display the received message.
+
+According to RFC 2812, suggests alternate servers on the network.
+Many servers, however, use this code to show which parameters they have set,
+for example, the network identifier, maximum allowed topic length, whether
+certain commands are accepted and more.	 See documentation for
+`erc-server-parameters' for more information on the parameters sent.
+
+A server may send more than one 005 message."
+  nil
+  (let ((line (mapconcat 'identity
+                         (setf (erc-response.command-args parsed)
+                               (cdr (erc-response.command-args parsed)))
+                         " ")))
+    (while (erc-response.command-args parsed)
+      (let ((section (pop (erc-response.command-args parsed))))
+        ;; fill erc-server-parameters
+        (when (string-match "^\\([A-Z]+\\)\=\\(.*\\)$\\|^\\([A-Z]+\\)$"
+                            section)
+          (add-to-list 'erc-server-parameters
+                       `(,(or (match-string 1 section)
+                              (match-string 3 section))
+                         .
+                         ,(match-string 2 section))))))
+    (erc-display-message parsed 'notice proc line)))
+
+(define-erc-response-handler (221)
+  nil nil
+  (let* ((nick (first (erc-response.command-args parsed)))
+         (modes (mapconcat 'identity
+                           (cdr (erc-response.command-args parsed)) " ")))
+    (erc-set-modes nick modes)
+    (erc-display-message parsed 'notice 'active 's221 ?n nick ?m modes)))
+
+(define-erc-response-handler (252)
+  "Display the number of IRC operators online." nil
+  (erc-display-message parsed 'notice 'active 's252
+                       ?i (second (erc-response.command-args parsed))))
+
+(define-erc-response-handler (253)
+  "Display the number of unknown connections." nil
+  (erc-display-message parsed 'notice 'active 's253
+                       ?i (second (erc-response.command-args parsed))))
+
+(define-erc-response-handler (254)
+  "Display the number of channels formed." nil
+  (erc-display-message parsed 'notice 'active 's254
+                       ?i (second (erc-response.command-args parsed))))
+
+(define-erc-response-handler (250 251 255 256 257 258 259 265 266 377 378)
+  "Generic display of server messages as notices.
+
+See `erc-display-server-message'." nil
+  (erc-display-server-message proc parsed))
+
+(define-erc-response-handler (301)
+  "AWAY notice." nil
+  (erc-display-message parsed 'notice 'active 's301
+                       ?n (second (erc-response.command-args parsed))
+                       ?r (erc-response.contents parsed)))
+
+(define-erc-response-handler (303)
+  "ISON reply" nil
+  (erc-display-message parsed 'notice 'active 's303
+                       ?n (second (erc-response.command-args parsed))))
+
+(define-erc-response-handler (305)
+  "Return from AWAYness." nil
+  (erc-process-away proc nil)
+  (erc-display-message parsed 'notice 'active
+                       's305 ?m (erc-response.contents parsed)))
+
+(define-erc-response-handler (306)
+  "Set AWAYness." nil
+  (erc-process-away proc t)
+  (erc-display-message parsed 'notice 'active
+                       's306 ?m (erc-response.contents parsed)))
+
+(define-erc-response-handler (311 314)
+  "WHOIS/WHOWAS notices." nil
+  (let ((fname (erc-response.contents parsed))
+        (catalog-entry (intern (format "s%s" (erc-response.command parsed)))))
+    (multiple-value-bind (nick user host)
+        (cdr (erc-response.command-args parsed))
+      (erc-update-user-nick nick nick host nil fname user)
+      (erc-display-message
+       parsed 'notice 'active catalog-entry
+       ?n nick ?f fname ?u user ?h host))))
+
+(define-erc-response-handler (312)
+  nil nil
+  (multiple-value-bind (nick server-host)
+      (cdr (erc-response.command-args parsed))
+    (erc-display-message
+     parsed 'notice 'active 's312
+     ?n nick ?s server-host ?c (erc-response.contents parsed))))
+
+(define-erc-response-handler (313)
+  "IRC Operator response in WHOIS." nil
+  (erc-display-message
+   parsed 'notice 'active 's313
+   ?n (second (erc-response.command-args parsed))))
+
+(define-erc-response-handler (315 318 323 369)
+  ;; 315 - End of WHO
+  ;; 318 - End of WHOIS list
+  ;; 323 - End of channel LIST
+  ;; 369 - End of WHOWAS
+  nil nil
+  (ignore proc parsed))
+
+(define-erc-response-handler (317)
+  "IDLE notice." nil
+  (multiple-value-bind (nick seconds-idle on-since time)
+      (cdr (erc-response.command-args parsed))
+    (setq time (when on-since
+                 (format-time-string "%T %Y/%m/%d"
+                                     (erc-string-to-emacs-time on-since))))
+    (erc-update-user-nick nick nick nil nil nil
+                          (and time (format "on since %s" time)))
+    (if time
+        (erc-display-message
+         parsed 'notice 'active 's317-on-since
+         ?n nick ?i (erc-sec-to-time (string-to-number seconds-idle)) ?t time)
+      (erc-display-message
+       parsed 'notice 'active 's317
+       ?n nick ?i (erc-sec-to-time (string-to-number seconds-idle))))))
+
+(define-erc-response-handler (319)
+  nil nil
+  (erc-display-message
+   parsed 'notice 'active 's319
+   ?n (second (erc-response.command-args parsed))
+   ?c (erc-response.contents parsed)))
+
+(define-erc-response-handler (320)
+  "Identified user in WHOIS." nil
+  (erc-display-message
+   parsed 'notice 'active 's320
+   ?n (second (erc-response.command-args parsed))))
+
+(define-erc-response-handler (321)
+  "LIST header." nil
+  (setq erc-channel-list nil)
+  (erc-display-message parsed 'notice 'active 's321))
+
+(define-erc-response-handler (322)
+  "LIST notice." nil
+  (let ((topic (erc-response.contents parsed)))
+    (multiple-value-bind (channel num-users)
+        (cdr (erc-response.command-args parsed))
+      (add-to-list 'erc-channel-list (list channel))
+      (erc-update-channel-topic channel topic)
+      (erc-display-message
+       parsed 'notice 'active 's322
+       ?c channel ?u num-users ?t (or topic "")))))
+
+(define-erc-response-handler (324)
+  "Channel or nick modes." nil
+  (let ((channel (second (erc-response.command-args parsed)))
+        (modes (mapconcat 'identity (cddr (erc-response.command-args parsed))
+                          " ")))
+    (erc-set-modes channel modes)
+    (erc-display-message
+     parsed 'notice (erc-get-buffer channel proc)
+     's324 ?c channel ?m modes)))
+
+(define-erc-response-handler (329)
+  "Channel creation date." nil
+  (let ((channel (second (erc-response.command-args parsed)))
+        (time (erc-string-to-emacs-time
+               (third (erc-response.command-args parsed)))))
+    (erc-display-message
+     parsed 'notice (erc-get-buffer channel proc)
+     's329 ?c channel ?t (format-time-string "%A %Y/%m/%d %X" time))))
+
+(define-erc-response-handler (330)
+  nil nil
+  ;; FIXME: I don't know what the magic numbers mean.  Mummy, make
+  ;; the magic numbers go away.
+  ;; No seriously, I have no clue about the format of this command,
+  ;; and don't sit on Quakenet, so can't test.  Originally we had:
+  ;; nick == (aref parsed 3)
+  ;; authaccount == (aref parsed 4)
+  ;; authmsg == (aref parsed 5)
+  ;; The guesses below are, well, just that. -- Lawrence 2004/05/10
+  (let ((nick (second (erc-response.command-args parsed)))
+        (authaccount (third (erc-response.command-args parsed)))
+        (authmsg (erc-response.contents parsed)))
+    (erc-display-message parsed 'notice 'active 's330
+                         ?n nick ?a authmsg ?i authaccount)))
+
+(define-erc-response-handler (331)
+  "Channel topic." nil
+  (let ((channel (second (erc-response.command-args parsed)))
+        (topic (erc-response.contents parsed)))
+    ;; FIXME: why don't we do anything with the topic? -- Lawrence 2004/05/10
+    (erc-display-message parsed 'notice (erc-get-buffer channel proc)
+                         's331 ?c channel)))
+
+(define-erc-response-handler (332)
+  "TOPIC notice." nil
+  (let ((channel (second (erc-response.command-args parsed)))
+        (topic (erc-response.contents parsed)))
+    (erc-update-channel-topic channel topic)
+    (erc-display-message parsed 'notice (erc-get-buffer channel proc)
+                         's332 ?c channel ?T topic)))
+
+(define-erc-response-handler (333)
+  ;; Who set the topic, and when
+  nil nil
+  (multiple-value-bind (channel nick time)
+      (cdr (erc-response.command-args parsed))
+    (setq time (format-time-string "%T %Y/%m/%d"
+                                   (erc-string-to-emacs-time time)))
+    (erc-update-channel-topic channel
+                              (format "\C-o (%s, %s)" nick time)
+                              'append)
+    (erc-display-message parsed 'notice (erc-get-buffer channel proc)
+                         's333 ?c channel ?n nick ?t time)))
+
+(define-erc-response-handler (341)
+  "Let user know when an INVITE attempt has been sent successfully."
+  nil
+  (multiple-value-bind (nick channel)
+      (cdr (erc-response.command-args parsed))
+    (erc-display-message parsed 'notice (erc-get-buffer channel proc)
+                         's341 ?n nick ?c channel)))
+
+(define-erc-response-handler (352)
+  "WHO notice." nil
+  (multiple-value-bind (channel user host server nick away-flag)
+      (cdr (erc-response.command-args parsed))
+    (let ((full-name (erc-response.contents parsed))
+          hopcount)
+      (when (string-match "\\(^[0-9]+ \\)\\(.*\\)$" full-name)
+        (setq hopcount (match-string 1 full-name))
+        (setq full-name (match-string 2 full-name)))
+      (erc-update-channel-member channel nick nick nil nil nil host
+                                 user full-name)
+      (erc-display-message parsed 'notice 'active 's352
+                           ?c channel ?n nick ?a away-flag
+                           ?u user ?h host ?f full-name))))
+
+(define-erc-response-handler (353)
+  "NAMES notice." nil
+  (let ((channel (third (erc-response.command-args parsed)))
+        (users (erc-response.contents parsed)))
+    (erc-with-buffer (channel proc)
+      (erc-channel-receive-names users))
+    (erc-display-message parsed 'notice (or (erc-get-buffer channel proc)
+                                            'active)
+                         's353 ?c channel ?u users)))
+
+(define-erc-response-handler (366)
+  "End of NAMES." nil
+  (erc-with-buffer ((second (erc-response.command-args parsed)) proc)
+    (erc-channel-end-receiving-names)))
+
+(define-erc-response-handler (367)
+  "Channel ban list entries" nil
+  (multiple-value-bind (channel banmask setter time)
+      (cdr (erc-response.command-args parsed))
+    (erc-display-message parsed 'notice 'active 's367
+                         ?c channel
+                         ?b banmask
+                         ?s setter
+                         ?t time)))
+
+(define-erc-response-handler (368)
+  "End of channel ban list" nil
+  (let ((channel (second (erc-response.command-args parsed))))
+    (erc-display-message parsed 'notice 'active 's368
+                         ?c channel)))
+
+(define-erc-response-handler (379)
+  "Forwarding to another channel." nil
+  ;; FIXME: Yet more magic numbers in original code, I'm guessing this
+  ;; command takes two arguments, and doesn't have any "contents". --
+  ;; Lawrence 2004/05/10
+  (multiple-value-bind (from to)
+      (cdr (erc-response.command-args parsed))
+    (erc-display-message parsed 'notice 'active
+                         's379 ?c from ?f to)))
+
+(define-erc-response-handler (391)
+  "Server's time string" nil
+  (erc-display-message
+   parsed 'notice 'active
+   's391 ?s (second (erc-response.command-args parsed))
+   ?t (third (erc-response.command-args parsed))))
+
+(define-erc-response-handler (401)
+  "No such nick/channel." nil
+  (let ((nick/channel (second (erc-response.command-args parsed))))
+    (when erc-whowas-on-nosuchnick
+      (erc-log (format "cmd: WHOWAS: %s" nick/channel))
+      (erc-server-send (format "WHOWAS %s 1" nick/channel)))
+    (erc-display-message parsed '(notice error) 'active
+                         's401 ?n nick/channel)))
+
+(define-erc-response-handler (403)
+  "No such channel." nil
+  (erc-display-message parsed '(notice error) 'active
+                       's403 ?c (second (erc-response.command-args parsed))))
+
+(define-erc-response-handler (404)
+  "Cannot send to channel." nil
+  (erc-display-message parsed '(notice error) 'active
+                       's404 ?c (second (erc-response.command-args parsed))))
+
+
+(define-erc-response-handler (405)
+  ;; Can't join that many channels.
+  nil nil
+  (erc-display-message parsed '(notice error) 'active
+                       's405 ?c (second (erc-response.command-args parsed))))
+
+(define-erc-response-handler (406)
+  ;; No such nick
+  nil nil
+  (erc-display-message parsed '(notice error) 'active
+                       's406 ?n (second (erc-response.command-args parsed))))
+
+(define-erc-response-handler (412)
+  ;; No text to send
+  nil nil
+  (erc-display-message parsed '(notice error) 'active 's412))
+
+(define-erc-response-handler (421)
+  ;; Unknown command
+  nil nil
+  (erc-display-message parsed '(notice error) 'active 's421
+                       ?c (second (erc-response.command-args parsed))))
+
+(define-erc-response-handler (432)
+  ;; Bad nick.
+  nil nil
+  (erc-display-message parsed '(notice error) 'active 's432
+                       ?n (second (erc-response.command-args parsed))))
+
+(define-erc-response-handler (433)
+  ;; Login-time "nick in use"
+  nil nil
+  (erc-nickname-in-use (second (erc-response.command-args parsed))
+                       "already in use"))
+
+(define-erc-response-handler (437)
+  ;; Nick temporarily unavailable (IRCnet)
+  nil nil
+  (let ((nick/channel (second (erc-response.command-args parsed))))
+    (unless (erc-channel-p nick/channel)
+      (erc-nickname-in-use nick/channel "temporarily unavailable"))))
+
+(define-erc-response-handler (442)
+  ;; Not on channel
+  nil nil
+  (erc-display-message parsed '(notice error) 'active 's442
+                       ?c (second (erc-response.command-args parsed))))
+
+(define-erc-response-handler (461)
+  ;; Not enough params for command.
+  nil nil
+  (erc-display-message parsed '(notice error)  'active 's461
+                       ?c (second (erc-response.command-args parsed))
+                       ?m (erc-response.contents parsed)))
+
+(define-erc-response-handler (474)
+  "Banned from channel errors" nil
+  (erc-display-message parsed '(notice error) nil
+                       (intern (format "s%s"
+                                       (erc-response.command parsed)))
+                       ?c (second (erc-response.command-args parsed))))
+
+(define-erc-response-handler (475)
+  "Channel key needed." nil
+  (erc-display-message parsed '(notice error) nil 's475
+                       ?c (second (erc-response.command-args parsed)))
+  (when erc-prompt-for-channel-key
+    (let ((channel (second (erc-response.command-args parsed)))
+          (key (read-from-minibuffer
+                (format "Channel %s is mode +k.  Enter key (RET to cancel): "
+                        (second (erc-response.command-args parsed))))))
+      (when (and key (> (length key) 0))
+          (erc-cmd-JOIN channel key)))))
+
+(define-erc-response-handler (477)
+  nil nil
+  (let ((channel (second (erc-response.command-args parsed)))
+        (message (erc-response.contents parsed)))
+    (erc-display-message parsed 'notice (erc-get-buffer channel proc)
+                         (format "%s: %s" channel message))))
+
+(define-erc-response-handler (482)
+  nil nil
+  (let ((channel (second (erc-response.command-args parsed)))
+        (message (erc-response.contents parsed)))
+    (erc-display-message parsed '(error notice) 'active 's482
+                         ?c channel ?m message)))
+
+(define-erc-response-handler (431 445 446 451 462 463 464 465 481 483 484 485
+                                  491 501 502)
+  ;; 431 - No nickname given
+  ;; 445 - SUMMON has been disabled
+  ;; 446 - USERS has been disabled
+  ;; 451 - You have not registered
+  ;; 462 - Unauthorized command (already registered)
+  ;; 463 - Your host isn't among the privileged
+  ;; 464 - Password incorrect
+  ;; 465 - You are banned from this server
+  ;; 481 - Need IRCop privileges
+  ;; 483 - You can't kill a server!
+  ;; 484 - Your connection is restricted!
+  ;; 485 - You're not the original channel operator
+  ;; 491 - No O-lines for your host
+  ;; 501 - Unknown MODE flag
+  ;; 502 - Cannot change mode for other users
+  nil nil
+  (erc-display-error-notice
+   parsed
+   (intern (format "s%s" (erc-response.command parsed)))))
+
+;; FIXME: These are yet to be implemented, they're just stubs for now
+;; -- Lawrence 2004/05/12
+
+;; response numbers left here for reference
+
+;; (define-erc-response-handler (323 364 365 381 382 392 393 394 395
+;;                               200 201 202 203 204 205 206 208 209 211 212 213
+;;                               214 215 216 217 218 219 241 242 243 244 249 261
+;;                               262 302 342 351 402 407 409 411 413 414 415
+;;                               423 424 436 441 443 444 467 471 472 473 KILL)
+;;   nil nil
+;;   (ignore proc parsed))
+
+(provide 'erc-backend)
+
+;;; erc-backend.el ends here
+;; Local Variables:
+;; indent-tabs-mode: nil
+;; End:
+
+;; arch-tag: a64e6bb7-a780-4efd-8f98-083b18c7c84a
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lisp/erc/erc-button.el	Wed Feb 01 10:07:17 2006 +0000
@@ -0,0 +1,504 @@
+;; erc-button.el --- A way of buttonizing certain things in ERC buffers
+
+;; Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
+;;   2006 Free Software Foundation, Inc.
+
+;; Author: Mario Lang <mlang@delysid.org>
+;; Keywords: irc, button, url, regexp
+;; URL: http://www.emacswiki.org/cgi-bin/wiki.pl?ErcButton
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
+
+;;; Commentary:
+
+;; Heavily borrowed from gnus-art.el. Thanks to the original authors.
+;; This buttonizes nicks and other stuff to make it all clickable.
+;; To enable, add to your ~/.emacs:
+;; (require 'erc-button)
+;; (erc-button-mode 1)
+;;
+;; Todo:
+;; * Rewrite all this to do the same, but use button.el from GNU Emacs
+;; if it's available for xemacs too.  Why? button.el is much faster,
+;; and much more elegant, and solves the problem we get with large buffers
+;; and a large erc-button-marker-list.
+
+
+;;; Code:
+
+(require 'erc)
+(require 'wid-edit)
+(require 'erc-fill)
+
+;;; Minor Mode
+
+(defgroup erc-button nil
+  "Define how text can be turned into clickable buttons."
+  :group 'erc)
+
+;;;###autoload (autoload 'erc-button-mode "erc-button" nil t)
+(define-erc-module button nil
+  "This mode buttonizes all messages according to `erc-button-alist'."
+  ((add-hook 'erc-insert-modify-hook 'erc-button-add-buttons 'append)
+   (add-hook 'erc-send-modify-hook 'erc-button-add-buttons 'append)
+   (add-hook 'erc-complete-functions 'erc-button-next))
+  ((remove-hook 'erc-insert-modify-hook 'erc-button-add-buttons)
+   (remove-hook 'erc-send-modify-hook 'erc-button-add-buttons)
+   (remove-hook 'erc-complete-functions 'erc-button-next)))
+
+;; Make XEmacs use `erc-button-face'.
+(when (featurep 'xemacs)
+  (add-hook 'erc-mode-hook
+            (lambda () (set (make-local-variable 'widget-button-face) nil))))
+
+;;; Variables
+
+(defface erc-button '((t (:bold t)))
+  "ERC button face."
+  :group 'erc-faces)
+
+(defcustom erc-button-face 'erc-button
+  "Face used for highlighting buttons in ERC buffers.
+
+A button is a piece of text that you can activate by pressing
+`RET' or `mouse-2' above it. See also `erc-button-keymap'."
+  :type 'face
+  :group 'erc-faces)
+
+(defcustom erc-button-nickname-face 'erc-nick-default-face
+  "Face used for ERC nickname buttons."
+  :type 'face
+  :group 'erc-faces)
+
+(defcustom erc-button-mouse-face 'highlight
+  "Face used for mouse highlighting in ERC buffers.
+
+Buttons will be displayed in this face when the mouse cursor is
+above them."
+  :type 'face
+  :group 'erc-faces)
+
+(defcustom erc-button-url-regexp
+  (concat "\\(www\\.\\|\\(s?https?\\|"
+          "ftp\\|file\\|gopher\\|news\\|telnet\\|wais\\|mailto\\):\\)"
+          "\\(//[-a-zA-Z0-9_.]+:[0-9]*\\)?"
+          "[-a-zA-Z0-9_=!?#$@~`%&*+\\/:;.,]+[-a-zA-Z0-9_=#$@~`%&*+\\/]")
+  "Regular expression that matches URLs."
+  :group 'erc-button
+  :type 'regexp)
+
+(defcustom erc-button-wrap-long-urls nil
+  "If non-nil, \"long\" URLs matching `erc-button-url-regexp' will be wrapped.
+
+If this variable is a number, consider URLs longer than its value to
+be \"long\".  If t, URLs will be considered \"long\" if they are
+longer than `erc-fill-column'."
+  :group 'erc-button
+  :type '(choice integer boolean))
+
+(defcustom erc-button-buttonize-nicks t
+  "Flag indicating whether nicks should be buttonized or not."
+  :group 'erc-button
+  :type 'boolean)
+
+(defcustom erc-button-rfc-url "http://www.faqs.org/rfcs/rfc%s.html"
+  "*URL used to browse rfc references.
+%s is replaced by the number."
+  :group 'erc-button
+  :type 'string)
+
+(defcustom erc-button-google-url "http://www.google.com/search?q=%s"
+  "*URL used to browse Google search references.
+%s is replaced by the search string."
+  :group 'erc-button
+  :type 'string)
+
+(defcustom erc-button-alist
+  ;; Since the callback is only executed when the user is clicking on
+  ;; a button, it makes no sense to optimize performance by
+  ;; bytecompiling lambdas in this alist.  On the other hand, it makes
+  ;; things hard to maintain.
+  '(('nicknames 0 erc-button-buttonize-nicks erc-nick-popup 0)
+    (erc-button-url-regexp 0 t browse-url 0)
+    ("<URL: *\\([^<> ]+\\) *>" 0 t browse-url 1)
+    ("(\\(\\([^~\n \t@][^\n \t@]*\\)@\\([a-zA-Z0-9.:-]+\\)\\)" 1 t finger 2 3)
+    ;; emacs internal
+    ("[`]\\([a-zA-Z][-a-zA-Z_0-9]+\\)[']" 1 t erc-button-describe-symbol 1)
+    ;; pseudo links
+    ("\\bInfo:[\"]\\([^\"]+\\)[\"]" 0 t Info-goto-node 1)
+    ("\\b\\(Ward\\|Wiki\\|WardsWiki\\|TheWiki\\):\\([A-Z][a-z]+\\([A-Z][a-z]+\\)+\\)"
+     0 t (lambda (page)
+           (browse-url (concat "http://c2.com/cgi-bin/wiki?" page)))
+     2)
+    ("EmacsWiki:\\([A-Z][a-z]+\\([A-Z][a-z]+\\)+\\)" 0 t erc-browse-emacswiki 1)
+    ("Lisp:\\([a-zA-Z.+-]+\\)" 0 t erc-browse-emacswiki-lisp 1)
+    ("\\bGoogle:\\([^ \t\n\r\f]+\\)"
+     0 t (lambda (keywords)
+           (browse-url (format erc-button-google-url keywords)))
+     1)
+    ("\\brfc[#: ]?\\([0-9]+\\)"
+     0 t (lambda (num)
+           (browse-url (format erc-button-rfc-url num)))
+     1)
+    ;; other
+    ("\\s-\\(@\\([0-9][0-9][0-9]\\)\\)" 1 t erc-button-beats-to-time 2))
+  "*Alist of regexps matching buttons in ERC buffers.
+Each entry has the form (REGEXP BUTTON FORM CALLBACK PAR...), where
+
+REGEXP is the string matching text around the button or a symbol
+  indicating a variable holding that string, or a list of
+  strings, or an alist with the strings in the car.  Note that
+  entries in lists or alists are considered to be nicks or other
+  complete words.  Therefore they are enclosed in \\< and \\>
+  while searching.  REGEXP can also be the quoted symbol
+  'nicknames, which matches the nickname of any user on the
+  current server.
+
+BUTTON is the number of the regexp grouping actually matching the
+  button,  This is ignored if REGEXP is 'nicknames.
+
+FORM is a lisp expression which must eval to true for the button to
+  be added,
+
+CALLBACK is the function to call when the user push this button.
+  CALLBACK can also be a symbol.  Its variable value will be used
+  as the callback function.
+
+PAR is a number of a regexp grouping whose text will be passed to
+  CALLBACK.  There can be several PAR arguments.  If REGEXP is
+  'nicknames, these are ignored, and CALLBACK will be called with
+  the nickname matched as the argument."
+  :group 'erc-button
+  :type '(repeat
+          (list :tag "Button"
+                (choice :tag "Matches"
+                        regexp
+                        (variable :tag "Variable containing regexp")
+                        (const :tag "Nicknames" 'nicknames))
+                (integer :tag "Number of the regexp section that matches")
+                (choice :tag "When to buttonize"
+                        (const :tag "Always" t)
+                        (sexp :tag "Only when this evaluates to non-nil"))
+                (function :tag "Function to call when button is pressed")
+                (repeat :tag "Sections of regexp to send to the function"
+                        :inline t
+                        (integer :tag "Regexp section number")))))
+
+(defcustom erc-emacswiki-url "http://www.emacswiki.org/cgi-bin/wiki.pl?"
+  "*URL of the EmacsWiki Homepage."
+  :group 'erc-button
+  :type 'string)
+
+(defcustom erc-emacswiki-lisp-url "http://www.emacswiki.org/elisp/"
+  "*URL of the EmacsWiki ELisp area."
+  :group 'erc-button
+  :type 'string)
+
+(defvar erc-button-keymap
+  (let ((map (make-sparse-keymap)))
+    (define-key map (kbd "RET") 'erc-button-press-button)
+    (if (featurep 'xemacs)
+        (define-key map (kbd "<button2>") 'erc-button-click-button)
+      (define-key map (kbd "<mouse-2>") 'erc-button-click-button))
+    (define-key map (kbd "TAB") 'erc-button-next)
+    (set-keymap-parent map erc-mode-map)
+    map)
+  "Local keymap for ERC buttons.")
+
+(defvar erc-button-syntax-table
+  (let ((table (make-syntax-table)))
+    (modify-syntax-entry ?\( "w" table)
+    (modify-syntax-entry ?\) "w" table)
+    (modify-syntax-entry ?\[ "w" table)
+    (modify-syntax-entry ?\] "w" table)
+    (modify-syntax-entry ?\{ "w" table)
+    (modify-syntax-entry ?\} "w" table)
+    (modify-syntax-entry ?` "w" table)
+    (modify-syntax-entry ?' "w" table)
+    (modify-syntax-entry ?^ "w" table)
+    (modify-syntax-entry ?- "w" table)
+    (modify-syntax-entry ?_ "w" table)
+    (modify-syntax-entry ?| "w" table)
+    (modify-syntax-entry ?\\ "w" table)
+    table)
+  "Syntax table used when buttonizing messages.
+This syntax table should make all the legal nick characters word
+constituents.")
+
+(defun erc-button-add-buttons ()
+  "Find external references in the current buffer and make buttons of them.
+\"External references\" are things like URLs, as
+specified by `erc-button-alist'."
+  (interactive)
+  (save-excursion
+    (with-syntax-table erc-button-syntax-table
+      (let ((buffer-read-only nil)
+            (inhibit-point-motion-hooks t)
+            (inhibit-field-text-motion t)
+            (alist erc-button-alist)
+            entry regexp data)
+        (erc-button-remove-old-buttons)
+        (dolist (entry alist)
+          (if (equal (car entry) (quote (quote nicknames)))
+              (erc-button-add-nickname-buttons entry)
+            (progn
+              (setq regexp (or (and (stringp (car entry)) (car entry))
+                               (and (boundp (car entry))
+                                    (symbol-value (car entry)))))
+              (cond ((stringp regexp)
+                     (erc-button-add-buttons-1 regexp entry))
+                    ((and (listp regexp) (stringp (car regexp)))
+                     (dolist (r regexp)
+                       (erc-button-add-buttons-1
+                        (concat "\\<" (regexp-quote r) "\\>")
+                        entry)))
+                    ((and (listp regexp) (listp (car regexp))
+                          (stringp (caar regexp)))
+                     (dolist (elem regexp)
+                       (erc-button-add-buttons-1
+                        (concat "\\<" (regexp-quote (car elem)) "\\>")
+                        entry)))))))))))
+
+(defun erc-button-add-nickname-buttons (entry)
+  "Search through the buffer for nicknames, and add buttons."
+  (let ((form (nth 2 entry))
+        (fun (nth 3 entry))
+        bounds word)
+    (when (or (eq t form)
+              (eval form))
+      (goto-char (point-min))
+      (while (forward-word 1)
+        (setq bounds (bounds-of-thing-at-point 'word))
+        (setq word (buffer-substring-no-properties
+                    (car bounds) (cdr bounds)))
+        (if (erc-get-server-user word)
+            (erc-button-add-button (car bounds) (cdr bounds)
+                                   fun t (list word)))))))
+
+(defun erc-button-add-buttons-1 (regexp entry)
+  "Search through the buffer for matches to ENTRY and add buttons."
+  (goto-char (point-min))
+  (while (re-search-forward regexp nil t)
+    (let ((start (match-beginning (nth 1 entry)))
+          (end (match-end (nth 1 entry)))
+          (form (nth 2 entry))
+          (fun (nth 3 entry))
+          (data (mapcar 'match-string (nthcdr 4 entry))))
+      (when (or (eq t form)
+                (eval form))
+        (erc-button-add-button start end fun nil data regexp)))))
+
+(defun erc-button-remove-old-buttons ()
+  "Remove all existing buttons.
+This is called with narrowing in effect, just before the text is
+buttonized again.  Removing a button means to remove all the properties
+that `erc-button-add-button' adds, except for the face."
+  (remove-text-properties
+   (point-min) (point-max)
+   '(erc-callback nil
+                  erc-data nil
+                  mouse-face nil
+                  keymap nil)))
+
+(defun erc-button-add-button (from to fun nick-p &optional data regexp)
+  "Create a button between FROM and TO with callback FUN and data DATA.
+NICK-P specifies if this is a nickname button.
+REGEXP is the regular expression which matched for this button."
+  ;; Really nasty hack to <URL: > ise urls, and line-wrap them if
+  ;; they're going to be wider than `erc-fill-column'.
+  ;; This could be a lot cleaner, but it works for me -- lawrence.
+  (let (fill-column)
+    (when (and erc-button-wrap-long-urls
+               (string= regexp erc-button-url-regexp)
+               (> (- to from)
+                  (setq fill-column (- (if (numberp erc-button-wrap-long-urls)
+                                           erc-button-wrap-long-urls
+                                         erc-fill-column)
+                                       (length erc-fill-prefix)))))
+      (setq to (prog1 (point-marker) (insert ">"))
+            from (prog2 (goto-char from) (point-marker) (insert "<URL: ")))
+      (let ((pos (copy-marker from)))
+        (while (> (- to pos) fill-column)
+          (goto-char (+ pos fill-column))
+          (insert "\n" erc-fill-prefix) ; This ought to figure out
+                                        ; what type of filling we're
+                                        ; doing, and indent accordingly.
+          (move-marker pos (point))))))
+  (if nick-p
+      (when erc-button-nickname-face
+        (erc-button-add-face from to erc-button-nickname-face))
+    (when erc-button-face
+      (erc-button-add-face from to erc-button-face)))
+  (add-text-properties
+   from to
+   (nconc (and erc-button-mouse-face
+               (list 'mouse-face erc-button-mouse-face))
+          (list 'erc-callback fun)
+          (list 'keymap erc-button-keymap)
+          (list 'rear-nonsticky t)
+          (and data (list 'erc-data data))))
+  (widget-convert-button 'link from to :action 'erc-button-press-button
+                         :suppress-face t
+                         ;; Make XEmacs use our faces.
+                         :button-face (if nick-p
+                                          erc-button-nickname-face
+                                        erc-button-face)
+                         ;; Make XEmacs behave with mouse-clicks, for
+                         ;; some reason, widget stuff overrides the
+                         ;; 'keymap text-property.
+                         :mouse-down-action 'erc-button-click-button))
+
+(defun erc-button-add-face (from to face)
+  "Add FACE to the region between FROM and TO."
+  ;; If we just use `add-text-property', then this will overwrite any
+  ;; face text property already used for the button.  It will not be
+  ;; merged correctly.  If we use overlays, then redisplay will be
+  ;; very slow with lots of buttons.  This is why we manually merge
+  ;; face text properties.
+  (let ((old (erc-list (get-text-property from 'face)))
+        (pos from)
+        (end (next-single-property-change from 'face nil to))
+        new)
+    ;; old is the face at pos, in list form.  It is nil if there is no
+    ;; face at pos.  If nil, the new face is FACE.  If not nil, the
+    ;; new face is a list containing FACE and the old stuff.  end is
+    ;; where this face changes.
+    (while (< pos to)
+      (setq new (if old (cons face old) face))
+      (put-text-property pos end 'face new)
+      (setq pos end
+            old (erc-list (get-text-property pos 'face))
+            end (next-single-property-change pos 'face nil to)))))
+
+;; widget-button-click calls with two args, we ignore the first.
+;; Since Emacs runs this directly, rather than with
+;; widget-button-click, we need to fake an extra arg in the
+;; interactive spec.
+(defun erc-button-click-button (ignore event)
+  "Call `erc-button-press-button'."
+  (interactive "P\ne")
+  (save-excursion
+    (mouse-set-point event)
+    (erc-button-press-button)))
+
+;; XEmacs calls this via widget-button-press with a bunch of arguments
+;; which we don't care about.
+(defun erc-button-press-button (&rest ignore)
+  "Check text at point for a callback function.
+If the text at point has a `erc-callback' property,
+call it with the value of the `erc-data' text property."
+  (interactive)
+  (let* ((data (get-text-property (point) 'erc-data))
+         (fun (get-text-property (point) 'erc-callback)))
+    (unless fun
+      (message "No button at point"))
+    (when (and fun (symbolp fun) (not (fboundp fun)))
+      (error "Function %S is not bound" fun))
+    (apply fun data)))
+
+(defun erc-button-next ()
+  "Go to the next button in this buffer."
+  (interactive)
+  (let ((here (point)))
+    (when (< here (erc-beg-of-input-line))
+      (while (and (get-text-property here 'erc-callback)
+                  (not (= here (point-max))))
+        (setq here (1+ here)))
+      (while (and (not (get-text-property here 'erc-callback))
+                  (not (= here (point-max))))
+        (setq here (1+ here)))
+      (if (< here (point-max))
+          (goto-char here)
+        (error "No next button"))
+      t)))
+
+(defun erc-browse-emacswiki (thing)
+  "Browse to thing in the emacs-wiki."
+  (browse-url (concat erc-emacswiki-url thing)))
+
+(defun erc-browse-emacswiki-lisp (thing)
+  "Browse to THING in the emacs-wiki elisp area."
+  (browse-url (concat erc-emacswiki-lisp-url thing)))
+
+;;; Nickname buttons:
+
+(defcustom erc-nick-popup-alist
+  '(("DeOp"  . (erc-cmd-DEOP nick))
+    ("Kick"  . (erc-cmd-KICK (concat nick " "
+                                     (read-from-minibuffer
+                                      (concat "Kick " nick ", reason: ")))))
+    ("Msg"   . (erc-cmd-MSG (concat nick " "
+                                    (read-from-minibuffer
+                                     (concat "Message to " nick ": ")))))
+    ("Op"    . (erc-cmd-OP nick))
+    ("Query" . (erc-cmd-QUERY nick))
+    ("Whois" . (erc-cmd-WHOIS nick))
+    ("Lastlog" . (erc-cmd-LASTLOG nick)))
+  "*An alist of possible actions to take on a nickname.
+An entry looks like (\"Action\" . SEXP) where SEXP is evaluated with
+the variable `nick' bound to the nick in question.
+
+Examples:
+ (\"DebianDB\" .
+  (shell-command
+   (format
+    \"ldapsearch -x -P 2 -h db.debian.org -b dc=debian,dc=org ircnick=%s\"
+    nick)))"
+  :group 'erc-button
+  :type '(repeat (cons (string :tag "Op")
+                       sexp)))
+
+(defun erc-nick-popup (nick)
+  (let* ((completion-ignore-case t)
+         (action (completing-read (concat "What action to take on '" nick "'? ")
+                                  erc-nick-popup-alist))
+         (code (cdr (assoc action erc-nick-popup-alist))))
+    (when code
+      (erc-set-active-buffer (current-buffer))
+      (eval code))))
+
+;;; Callback functions
+(defun erc-button-describe-symbol (symbol-name)
+  "Describe SYMBOL-NAME.
+Use `describe-function' for functions, `describe-variable' for variables,
+and `apropos' for other symbols."
+  (let ((symbol (intern-soft symbol-name)))
+    (cond ((and symbol (fboundp symbol))
+           (describe-function symbol))
+          ((and symbol (boundp symbol))
+           (describe-variable symbol))
+          (t (apropos symbol-name)))))
+
+(defun erc-button-beats-to-time (beats)
+  "Display BEATS in a readable time format."
+  (let* ((seconds (- (* (string-to-number beats) 86.4)
+                     3600
+                     (- (car (current-time-zone)))))
+         (hours (mod (floor seconds 3600) 24))
+         (minutes (mod (round seconds 60) 60)))
+    (message (format "@%s is %d:%02d local time"
+                     beats hours minutes))))
+
+(provide 'erc-button)
+
+;;; erc-button.el ends here
+;; Local Variables:
+;; indent-tabs-mode: nil
+;; End:
+
+;; arch-tag: 7d23bed4-2f30-4273-a03f-d7a274c605c4
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lisp/erc/erc-compat.el	Wed Feb 01 10:07:17 2006 +0000
@@ -0,0 +1,207 @@
+;;; erc-compat.el --- ERC compatibility code for XEmacs
+
+;; Copyright (C) 2002, 2003, 2005, 2006 Free Software Foundation, Inc.
+
+;; Author: Alex Schroeder <alex@gnu.org>
+;; URL: http://www.emacswiki.org/cgi-bin/wiki.pl?EmacsIRCClient
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
+
+;;; Commentary:
+
+;; This mostly defines stuff that cannot be worked around easily.
+
+;;; Code:
+
+(require 'format-spec)
+
+;;;###autoload (autoload 'erc-define-minor-mode "erc-compat")
+(defalias 'erc-define-minor-mode 'define-minor-mode)
+(put 'erc-define-minor-mode 'edebug-form-spec 'define-minor-mode)
+
+(defun erc-decode-coding-string (s coding-system)
+  "Decode S using CODING-SYSTEM."
+  (decode-coding-string s coding-system t))
+
+(defun erc-encode-coding-string (s coding-system)
+  "Encode S using CODING-SYSTEM.
+Return the same string, if the encoding operation is trivial.
+See `erc-encoding-coding-alist'."
+  (encode-coding-string s coding-system t))
+
+(defalias 'erc-propertize 'propertize)
+(defalias 'erc-view-mode-enter 'view-mode-enter)
+(defalias 'erc-function-arglist 'help-function-arglist)
+(defalias 'erc-delete-dups 'delete-dups)
+(defalias 'erc-replace-regexp-in-string 'replace-regexp-in-string)
+
+(defvar erc-emacs-build-time
+  (if (stringp emacs-build-time)
+      emacs-build-time
+    (format-time-string "%Y-%m-%d" emacs-build-time))
+  "Time at which Emacs was dumped out.")
+
+;; XEmacs' `replace-match' does not replace matching subexpressions in strings.
+(defun erc-replace-match-subexpression-in-string
+  (newtext string match subexp start &optional fixedcase literal)
+  "Replace the subexpression SUBEXP of the last match in STRING with NEWTEXT.
+MATCH is the text which matched the subexpression (see `match-string').
+START is the beginning position of the last match (see `match-beginning').
+See `replace-match' for explanations of FIXEDCASE and LITERAL."
+  (cond ((featurep 'xemacs)
+	 (string-match match string start)
+	 (replace-match newtext fixedcase literal string))
+	(t (replace-match newtext fixedcase literal string subexp))))
+
+(defalias 'erc-cancel-timer 'cancel-timer)
+(defalias 'erc-make-obsolete 'make-obsolete)
+(defalias 'erc-make-obsolete-variable 'make-obsolete-variable)
+
+;; Provde an equivalent of `assert', based on the code from cl-macs.el
+(defun erc-const-expr-p (x)
+  (cond ((consp x)
+	 (or (eq (car x) 'quote)
+	     (and (memq (car x) '(function function*))
+		  (or (symbolp (nth 1 x))
+		      (and (eq (and (consp (nth 1 x))
+				    (car (nth 1 x))) 'lambda) 'func)))))
+	((symbolp x) (and (memq x '(nil t)) t))
+	(t t)))
+
+(put 'erc-assertion-failed 'error-conditions '(error))
+(put 'erc-assertion-failed 'error-message "Assertion failed")
+
+(defun erc-list* (arg &rest rest)
+  "Return a new list with specified args as elements, cons'd to last arg.
+Thus, `(list* A B C D)' is equivalent to `(nconc (list A B C) D)', or to
+`(cons A (cons B (cons C D)))'."
+  (cond ((not rest) arg)
+	((not (cdr rest)) (cons arg (car rest)))
+	(t (let* ((n (length rest))
+		  (copy (copy-sequence rest))
+		  (last (nthcdr (- n 2) copy)))
+	     (setcdr last (car (cdr last)))
+	     (cons arg copy)))))
+
+(defmacro erc-assert (form &optional show-args string &rest args)
+  "Verify that FORM returns non-nil; signal an error if not.
+Second arg SHOW-ARGS means to include arguments of FORM in message.
+Other args STRING and ARGS... are arguments to be passed to `error'.
+They are not evaluated unless the assertion fails.  If STRING is
+omitted, a default message listing FORM itself is used."
+  (let ((sargs
+	 (and show-args
+	      (delq nil (mapcar
+			 (function
+			  (lambda (x)
+			    (and (not (erc-const-expr-p x)) x)))
+			 (cdr form))))))
+    (list 'progn
+	  (list 'or form
+		(if string
+		    (erc-list* 'error string (append sargs args))
+		  (list 'signal '(quote erc-assertion-failed)
+			(erc-list* 'list (list 'quote form) sargs))))
+	  nil)))
+
+;; Provide a simpler replacement for `member-if'
+(defun erc-member-if (predicate list)
+  "Find the first item satisfying PREDICATE in LIST.
+Return the sublist of LIST whose car matches."
+  (let ((ptr list))
+    (catch 'found
+      (while ptr
+	(when (funcall predicate (car ptr))
+	  (throw 'found ptr))
+	(setq ptr (cdr ptr))))))
+
+;; Provide a simpler replacement for `delete-if'
+(defun erc-delete-if (predicate seq)
+  "Remove all items satisfying PREDICATE in SEQ.
+This is a destructive function: it reuses the storage of SEQ
+whenever possible."
+  ;; remove from car
+  (while (when (funcall predicate (car seq))
+	   (setq seq (cdr seq))))
+  ;; remove from cdr
+  (let ((ptr seq)
+	(next (cdr seq)))
+    (while next
+      (when (funcall predicate (car next))
+	(setcdr ptr (if (consp next)
+			(cdr next)
+		      nil)))
+      (setq ptr (cdr ptr))
+      (setq next (cdr ptr))))
+  seq)
+
+;; Provide a simpler replacement for `remove-if-not'
+(defun erc-remove-if-not (predicate seq)
+  "Remove all items not satisfying PREDICATE in SEQ.
+This is a non-destructive function; it makes a copy of SEQ to
+avoid corrupting the original SEQ."
+  (let (newseq)
+    (dolist (el seq)
+      (when (funcall predicate el)
+	(setq newseq (cons el newseq))))
+    (nreverse newseq)))
+
+;; Provide a simpler replacement for `gensym'.
+(defvar *erc-sym-counter* 0)
+(defun erc-gensym ()
+  "Generate a new uninterned symbol."
+  (let ((num (prog1 *erc-sym-counter*
+	       (setq *erc-sym-counter* (1+ *erc-sym-counter*)))))
+    (make-symbol (format "*erc-sym-%d*" num))))
+
+;; Copied from cl-extra.el
+(defun erc-subseq (seq start &optional end)
+  "Return the subsequence of SEQ from START to END.
+If END is omitted, it defaults to the length of the sequence.
+If START or END is negative, it counts from the end."
+  (if (stringp seq) (substring seq start end)
+    (let (len)
+      (and end (< end 0) (setq end (+ end (setq len (length seq)))))
+      (if (< start 0) (setq start (+ start (or len (setq len (length seq))))))
+      (cond ((listp seq)
+	     (if (> start 0) (setq seq (nthcdr start seq)))
+	     (if end
+		 (let ((res nil))
+		   (while (>= (setq end (1- end)) start)
+		     (push (pop seq) res))
+		   (nreverse res))
+	       (copy-sequence seq)))
+	    (t
+	     (or end (setq end (or len (length seq))))
+	     (let ((res (make-vector (max (- end start) 0) nil))
+		   (i 0))
+	       (while (< start end)
+		 (aset res i (aref seq start))
+		 (setq i (1+ i) start (1+ start)))
+	       res))))))
+
+(provide 'erc-compat)
+
+;;; erc-compat.el ends here
+;;
+;; Local Variables:
+;; indent-tabs-mode: t
+;; tab-width: 8
+;; End:
+
+;; arch-tag: 8948ffe0-aff8-4ad8-a196-368ebbfd58ff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lisp/erc/erc-complete.el	Wed Feb 01 10:07:17 2006 +0000
@@ -0,0 +1,222 @@
+;;; erc-complete.el --- Provides Nick name completion for ERC
+
+;; Copyright (C) 2001, 2002, 2004 Free Software Foundation, Inc.
+
+;; Author: Alex Schroeder <alex@gnu.org>
+;; URL: http://www.emacswiki.org/cgi-bin/wiki.pl?ErcCompletion
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
+
+;;; Commentary:
+
+;; This file is obsolete.  Use completion from erc-pcomplete instead.
+;; This file is based on hippie-expand, while the new file is based on
+;; pcomplete.  There is no autoload cookie in this file.  If you want
+;; to use the code in this file, add the following to your ~/.emacs:
+
+;; (autoload 'erc-complete "erc-complete" "Complete nick at point." t)
+
+;;; Code:
+
+(require 'erc)
+(require 'erc-match); for erc-pals
+(require 'hippie-exp); for the hippie expand stuff
+
+;;;###autoload
+(defun erc-complete ()
+  "Complete nick at point.
+See `erc-try-complete-nick' for more technical info.
+This function is obsolete, use `erc-pcomplete' instead."
+  (interactive)
+  (let ((hippie-expand-try-functions-list '(erc-try-complete-nick)))
+    (hippie-expand nil)))
+
+(defgroup erc-old-complete nil
+  "Nick completion.  Obsolete, use erc-pcomplete instead."
+  :group 'erc)
+
+(defcustom erc-nick-completion 'all
+  "Determine how the list of nicks is determined during nick completion.
+See `erc-complete-nick' for information on how to activate this.
+
+pals:   Use `erc-pals'.
+all:    All channel members.
+
+You may also provide your own function that returns a list of completions.
+One example is `erc-nick-completion-exclude-myself',
+or you may use an arbitrary lisp expression."
+  :type '(choice (const :tag "List of pals" pals)
+		 (const :tag "All channel members" all)
+		 (const :tag "All channel members except yourself"
+			erc-nick-completion-exclude-myself)
+		 (repeat :tag "List" (string :tag "Nick"))
+		 function
+		 sexp)
+  :group 'erc-old-complete)
+
+(defcustom erc-nick-completion-ignore-case t
+  "*Non-nil means don't consider case significant in nick completion.
+Case will be automatically corrected when non-nil.
+For instance if you type \"dely TAB\" the word completes and changes to
+\"delYsid\"."
+  :group 'erc-old-complete
+  :type 'boolean)
+
+(defun erc-nick-completion-exclude-myself ()
+  "Get a list of all the channel members except you.
+
+This function returns a list of all the members in the channel, except
+your own nick.  This way if you're named foo and someone is called foobar,
+typing \"f o TAB\" will directly give you foobar.  Use this with
+`erc-nick-completion'."
+  (delete
+   (erc-current-nick)
+   (mapcar (function car) (erc-get-channel-user-list))))
+
+(defcustom erc-nick-completion-postfix ": "
+  "*When `erc-complete' is used in the first word after the prompt,
+add this string when a unique expansion was found."
+  :group 'erc-old-complete
+  :type 'string)
+
+(defun erc-command-list ()
+  "Returns a list of strings of the defined user commands."
+  (let ((case-fold-search nil))
+    (mapcar (lambda (x)
+	      (concat "/" (downcase (substring (symbol-name x) 8))))
+	    (apropos-internal "erc-cmd-[A-Z]+"))))
+
+(defun erc-try-complete-nick (old)
+  "Complete nick at point.
+This is a function to put on `hippie-expand-try-functions-list'.
+Then use \\[hippie-expand] to expand nicks.
+The type of completion depends on `erc-nick-completion'."
+  (cond ((eq erc-nick-completion 'pals)
+	 (try-complete-erc-nick old erc-pals))
+	((eq erc-nick-completion 'all)
+	 (try-complete-erc-nick old (append
+				     (mapcar (function car)
+					     (erc-get-channel-user-list))
+				     (erc-command-list))))
+	((functionp erc-nick-completion)
+	 (try-complete-erc-nick old (funcall erc-nick-completion)))
+	(t
+	 (try-complete-erc-nick old erc-nick-completion))))
+
+(defvar try-complete-erc-nick-window-configuration nil
+  "The window configuration for `try-complete-erc-nick'.
+When called the first time, a window config is stored here,
+and when completion is done, the window config is restored
+from here.  See `try-complete-erc-nick-restore' and
+`try-complete-erc-nick'.")
+
+(defun try-complete-erc-nick-restore ()
+  "Restore window configuration."
+  (if (not try-complete-erc-nick-window-configuration)
+      (when (get-buffer "*Completions*")
+	(delete-windows-on "*Completions*"))
+    (set-window-configuration
+     try-complete-erc-nick-window-configuration)
+    (setq try-complete-erc-nick-window-configuration nil)))
+
+(defun try-complete-erc-nick (old completions)
+  "Try to complete current word depending on `erc-try-complete-nick'.
+The argument OLD has to be nil the first call of this function, and t
+for subsequent calls (for further possible completions of the same
+string).  It returns t if a new completion is found, nil otherwise.  The
+second argument COMPLETIONS is a list of completions to use.  Actually,
+it is only used when OLD is nil.  It will be copied to `he-expand-list'
+on the first call.  After that, it is no longer used.
+Window configurations are stored in
+`try-complete-erc-nick-window-configuration'."
+  (let (expansion
+	final
+	(alist (if (consp (car completions))
+		   completions
+		 (mapcar (lambda (s)
+			   (if (and (erc-complete-at-prompt)
+				    (and (not (= (length s) 0))
+					 (not (eq (elt s 0) ?/))))
+			       (list (concat s erc-nick-completion-postfix))
+			     (list (concat s " "))))
+			 completions))) ; make alist if required
+	(completion-ignore-case erc-nick-completion-ignore-case))
+    (he-init-string (he-dabbrev-beg) (point))
+    ;; If there is a string to complete, complete it using alist.
+    ;; expansion is the possible expansion, or t.  If expansion is t
+    ;; or if expansion is the "real" thing, we are finished (final is
+    ;; t).  Take care -- expansion can also be nil!
+    (unless (string= he-search-string "")
+      (setq expansion (try-completion he-search-string alist)
+	    final (or (eq t expansion)
+		      (and expansion
+			   (eq t (try-completion expansion alist))))))
+    (cond ((not expansion)
+	   ;; There is no expansion at all.
+	   (try-complete-erc-nick-restore)
+	   (he-reset-string)
+	   nil)
+	  ((eq t expansion)
+	   ;; The user already has the correct expansion.
+	   (try-complete-erc-nick-restore)
+	   (he-reset-string)
+	   t)
+	  ((and old (string= expansion he-search-string))
+	   ;; This is the second time around and nothing changed,
+	   ;; ie. the user tried to expand something incomplete
+	   ;; without making a choice -- hitting TAB twice, for
+	   ;; example.
+	   (try-complete-erc-nick-restore)
+	   (he-reset-string)
+	   nil)
+	  (final
+	   ;; The user has found the correct expansion.
+	   (try-complete-erc-nick-restore)
+	   (he-substitute-string expansion)
+	   t)
+	  (t
+	   ;; We found something but we are not finished.  Show a
+	   ;; completions buffer.  Substitute what we found and return
+	   ;; t.
+	   (setq try-complete-erc-nick-window-configuration
+		 (current-window-configuration))
+	   (with-output-to-temp-buffer "*Completions*"
+	     (display-completion-list (all-completions he-search-string alist)))
+	   (he-substitute-string expansion)
+	   t))))
+
+(defun erc-at-beginning-of-line-p (point &optional bol-func)
+  (save-excursion
+    (funcall (or bol-func
+		 'erc-bol))
+    (equal point (point))))
+
+(defun erc-complete-at-prompt ()
+  "Returns t if point is directly after `erc-prompt' when doing completion."
+  (erc-at-beginning-of-line-p (he-dabbrev-beg)))
+
+(provide 'erc-complete)
+
+;;; erc-complete.el ends here
+;;
+;; Local Variables:
+;; indent-tabs-mode: t
+;; tab-width: 8
+;; End:
+
+;; arch-tag: 3be13ee8-8fdb-41ab-83c2-6582c757b91e
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lisp/erc/erc-dcc.el	Wed Feb 01 10:07:17 2006 +0000
@@ -0,0 +1,1135 @@
+;;; erc-dcc.el --- CTCP DCC module for ERC
+
+;; Copyright (C) 1993, 1994, 1995, 1998, 2002, 2003, 2004
+;;   Free Software Foundation, Inc.
+
+;; Author: Ben A. Mesander <ben@gnu.ai.mit.edu>
+;;         Noah Friedman <friedman@prep.ai.mit.edu>
+;;         Per Persson <pp@sno.pp.se>
+;; Maintainer: mlang@delysid.org
+;; Keywords: comm, processes
+;; Created: 1994-01-23
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
+
+;;; Commentary:
+
+;; This file provides Direct Client-to-Client support for the Emacs IRC Client.
+;;
+;; The original code was taken from zenirc-dcc.el, heavily mangled and
+;; rewritten to support the way how ERC operates.  Server socket support
+;; was added for DCC CHAT and SEND afterwards.  Thanks
+;; to the original authors for their work.
+;;
+;; To use this file, put
+;;  (require 'erc-dcc)
+;; in your .emacs.
+;;
+;; Provided commands
+;;  /dcc chat nick - Either accept pending chat offer from nick, or offer
+;;                   DCC chat to nick
+;;  /dcc close type [nick] - Close DCC connection (SEND/GET/CHAT) with nick
+;;  /dcc get nick [file] - Accept DCC offer from nick
+;;  /dcc list - List all DCC offers/connections
+;;  /dcc send nick file - Offer DCC SEND to nick
+;;
+;; Please note that offering DCC connections (offering chats and sending
+;; files) is only supported with Emacs 21.3.50 (CVS).
+
+;;; Code:
+
+(require 'erc)
+(eval-when-compile
+ (require 'pcomplete))
+
+(defgroup erc-dcc nil
+  "DCC stands for Direct Client Communication, where you and your
+friend's client programs connect directly to each other,
+bypassing IRC servers and their occasional \"lag\" or \"split\"
+problems.  Like /MSG, the DCC chat is completely private.
+
+Using DCC get and send, you can transfer files directly from and to other
+IRC users."
+  :group 'erc)
+
+(defcustom erc-verbose-dcc t
+  "*If non-nil, be verbose about DCC activity reporting."
+  :group 'erc-dcc
+  :type 'boolean)
+
+(defvar erc-dcc-list nil
+  "List of DCC connections. Looks like:
+  ((:nick \"nick!user@host\" :type GET :peer proc :parent proc :size size :file file)
+   (:nick \"nick!user@host\" :type CHAT :peer proc :parent proc)
+   (:nick \"nick\" :type SEND :peer server-proc :parent parent-proc :file
+   file :sent <marker> :confirmed <marker>))
+
+ :nick - a user or userhost for the peer. combine with :parent to reach them
+
+ :type - the type of DCC connection - SEND for outgoing files, GET for
+         incoming, and CHAT for both directions. To tell which end started
+         the DCC chat, look at :peer
+
+ :peer - the other end of the DCC connection. In the case of outgoing DCCs,
+         this represents a server process until a connection is established
+
+ :parent - the server process where the dcc connection was established.
+           Note that this can be nil or an invalid process since a DCC
+           connection is in general independent from a particular server
+           connection after it was established.
+
+ :file - for outgoing sends, the full path to the file. for incoming sends,
+         the suggested filename or vetted filename
+
+ :size - size of the file, may be nil on incoming DCCs")
+
+(defun erc-dcc-list-add (type nick peer parent &rest args)
+  "Add a new entry of type TYPE to `erc-dcc-list' and return it."
+  (car
+   (setq erc-dcc-list
+         (cons
+          (append (list :nick nick :type type :peer peer :parent parent) args)
+          erc-dcc-list))))
+
+;; This function takes all the usual args as open-network-stream, plus one
+;; more: the entry data from erc-dcc-list for this particular process.
+(defvar erc-dcc-connect-function 'erc-dcc-open-network-stream)
+
+(defun erc-dcc-open-network-stream (procname buffer addr port entry)
+  (if nil;  (fboundp 'open-network-stream-nowait)  ;; this currently crashes
+                                                   ;; cvs emacs
+      (open-network-stream-nowait procname buffer addr port)
+    (open-network-stream procname buffer addr port)))
+
+(erc-define-catalog
+ 'english
+ '((dcc-chat-discarded
+    . "DCC: previous chat request from %n (%u@%h) discarded")
+   (dcc-chat-ended . "DCC: chat with %n ended %t: %e")
+   (dcc-chat-no-request . "DCC: chat request from %n not found")
+   (dcc-chat-offered . "DCC: chat offered by %n (%u@%h:%p)")
+   (dcc-chat-offer . "DCC: offering chat to %n")
+   (dcc-chat-accept . "DCC: accepting chat from %n")
+   (dcc-chat-privmsg . "=%n= %m")
+   (dcc-closed . "DCC: Closed %T from %n")
+   (dcc-command-undefined
+    . "DCC: %c undefined subcommand. GET, CHAT and LIST are defined.")
+   (dcc-ctcp-errmsg . "DCC: `%s' is not a DCC subcommand known to this client")
+   (dcc-ctcp-unknown . "DCC: unknown dcc command `%q' from %n (%u@%h)")
+   (dcc-get-bytes-received . "DCC: %f: %b bytes received")
+   (dcc-get-complete
+    . "DCC: file %f transfer complete (%s bytes in %t seconds)")
+   (dcc-get-cmd-aborted . "DCC: Aborted getting %f from %n")
+   (dcc-get-file-too-long
+    . "DCC: %f: File longer than sender claimed; aborting transfer")
+   (dcc-get-notfound . "DCC: %n hasn't offered %f for DCC transfer")
+   (dcc-list-head . "DCC: From      Type  Active  Size          Filename")
+   (dcc-list-line . "DCC: --------  ----  ------  ------------  --------")
+   (dcc-list-item . "DCC: %-8n  %-4t  %-6a  %-12s  %f")
+   (dcc-list-end  . "DCC: End of list.")
+   (dcc-malformed . "DCC: error: %n (%u@%h) sent malformed request: %q")
+   (dcc-privileged-port
+    . "DCC: possibly bogus request: %p is a privileged port.")
+   (dcc-request-bogus . "DCC: bogus dcc `%r' from %n (%u@%h)")
+   (dcc-send-finished . "DCC: SEND of %f to %n finished (size %s)")
+   (dcc-send-offered . "DCC: file %f offered by %n (%u@%h) (size %s)")
+   (dcc-send-offer . "DCC: offering %f to %n")))
+
+;;; Misc macros and utility functions
+
+(defun erc-dcc-member (&rest args)
+  "Return the first matching entry in `erc-dcc-list' which satisfies the
+constraints given as a plist in ARGS. Returns nil on no match.
+
+The property :nick is treated specially, if it contains a '!' character,
+it is treated as a nick!user@host string, and compared with the :nick property
+value of the individual elements using string-equal. Otherwise it is
+compared with `erc-nick-equal-p' which is IRC case-insensitive."
+  (let ((list erc-dcc-list)
+        result test)
+    ;; for each element in erc-dcc-list
+    (while (and list (not result))
+      (let ((elt (car list))
+            (prem args)
+            (cont t))
+        ;; loop through the constraints
+        (while (and prem cont)
+          (let ((prop (car prem))
+                (val (cadr prem)))
+            (setq prem (cddr prem)
+                  ;; plist-member is a predicate in xemacs
+                  test (and (plist-member elt prop)
+                            (plist-get elt prop)))
+            ;; if the property exists and is equal, we continue, else, try the
+            ;; next element of the list
+            (or (and (eq prop :nick) (string-match "!" val)
+                     test (string-equal test val))
+                (and (eq prop :nick)
+                     test val
+                     (erc-nick-equal-p
+                      (erc-extract-nick test)
+                      (erc-extract-nick val)))
+                ;; not a nick
+                (eq test val)
+                (setq cont nil))))
+        (if cont
+            (setq result elt)
+          (setq list (cdr list)))))
+    result))
+
+;; msa wrote this nifty little frob to convert an n-byte integer to a packed
+;; string.
+(defun erc-pack-int (value count)
+  (if (> count 0)
+      (concat (erc-pack-int (/ value 256) (1- count))
+              (char-to-string (% value 256)))
+    ""))
+
+(defun erc-unpack-int (str)
+  "Unpack a 1-4 character packed string into an integer."
+  (let ((len (length str))
+        (num 0)
+        (count 0))
+    (erc-assert (<= len 4)) ;; this isn't going to fit in elisp bounds
+    (while (< count len)
+      (setq num (+ num (lsh (aref str (- len count 1)) (* 8 count))))
+      (setq count (1+ count)))
+    num))
+
+(defconst erc-dcc-ipv4-regexp
+  (concat "^"
+          (mapconcat #'identity (make-list 4 "\\([0-9]\\{1,3\\}\\)") "\\.")
+          "$"))
+
+(defun erc-ip-to-decimal (ip)
+  "Convert IP address to its decimal representation.
+Argument IP is the address as a string.  The result is also a string."
+  (interactive "sIP Address: ")
+  (if (not (string-match erc-dcc-ipv4-regexp ip))
+      (error "Not an IP address")
+    (let* ((ips (mapcar
+                 (lambda (str)
+                   (let ((n (string-to-number str)))
+                     (if (and (>= n 0) (< n 256))
+                         n
+                       (error "%d out of range" n))))
+                 (split-string ip "\\.")))
+           (res (+ (* (car ips) 16777216.0)
+                   (* (nth 1 ips) 65536.0)
+                   (* (nth 2 ips) 256.0)
+                   (nth 3 ips))))
+      (if (interactive-p)
+          (message "%s is %.0f" ip res)
+        (format "%.0f" res)))))
+
+(defun erc-decimal-to-ip (dec)
+  "Convert a decimal representation DEC to an IP address.
+The result is also a string."
+  (when (stringp dec)
+    (setq dec (string-to-number (concat dec ".0"))))
+  (let* ((first (floor (/ dec 16777216.0)))
+         (first-rest (- dec (* first 16777216.0)))
+         (second (floor (/ first-rest 65536.0)))
+         (second-rest (- first-rest (* second 65536.0)))
+         (third (floor (/ second-rest 256.0)))
+         (third-rest (- second-rest (* third 256.0)))
+         (fourth (floor third-rest)))
+    (format "%s.%s.%s.%s" first second third fourth)))
+
+;;; Server code
+
+(defcustom erc-dcc-host nil
+  "*IP address to use for outgoing DCC offers.
+Should be set to a string or nil, if nil, automatic detection of the
+host interface to use will be attempted."
+  :group 'erc-dcc
+  :type (list 'choice (list 'const :tag "Auto-detect" nil)
+              (list 'string :tag "IP-address"
+                    :valid-regexp erc-dcc-ipv4-regexp)))
+
+(defcustom erc-dcc-send-request 'ask
+  "*How to treat incoming DCC Send requests.
+'ask - Report the Send request, and wait for the user to manually accept it
+       You might want to set `erc-dcc-auto-masks' for this.
+'auto - Automatically accept the request and begin downloading the file
+'ignore - Ignore incoming DCC Send requests completely."
+  :group 'erc-dcc
+  :type '(choice (const ask) (const auto) (const ignore)))
+
+(defun erc-dcc-get-host (proc)
+  "Returns the local IP address used for an open PROCess."
+  (format-network-address (process-contact proc :local) t))
+
+(defun erc-dcc-host ()
+  "Determine the IP address we are using.
+If variable `erc-dcc-host' is non-nil, use it.  Otherwise call
+`erc-dcc-get-host' on the erc-server-process."
+  (or erc-dcc-host (erc-dcc-get-host erc-server-process)
+      (error "Unable to determine local address")))
+
+(defcustom erc-dcc-port-range nil
+  "If nil, any available user port is used for outgoing DCC connections.
+If set to a cons, it specifies a range of ports to use in the form (min . max)"
+  :group 'erc-dcc
+  :type '(choice
+          (const :tag "Any port" nil)
+          (cons :tag "Port range"
+                (integer :tag "Lower port")
+                (integer :tag "Upper port"))))
+
+(defcustom erc-dcc-auto-masks nil
+  "List of regexps matching user identifiers whose DCC send offers should be
+accepted automatically.  A user identifier has the form \"nick!login@host\".
+For instance, to accept all incoming DCC send offers automatically, add the
+string \".*!.*@.*\" to this list."
+  :group 'erc-dcc
+  :type '(repeat regexp))
+
+(defun erc-dcc-server (name filter sentinel)
+  "Start listening on a port for an incoming DCC connection. Returns the newly
+created subprocess, or nil."
+  (let ((port (or (and erc-dcc-port-range (car erc-dcc-port-range)) t))
+        (upper (and erc-dcc-port-range (cdr erc-dcc-port-range)))
+        process)
+    (while (not process)
+      (condition-case err
+            (setq process
+                  (make-network-process :name name
+                                        :buffer nil
+                                        :host (erc-dcc-host)
+                                        :service port
+                                        :nowait t
+                                        :noquery nil
+                                        :filter filter
+                                        :sentinel sentinel
+                                        :log #'erc-dcc-server-accept
+                                        :server t))
+        (file-error
+         (unless (and (string= "Cannot bind server socket" (cadr err))
+                      (string= "address already in use" (caddr err)))
+           (signal (car err) (cdr err)))
+         (setq port (1+ port))
+         (unless (< port upper)
+           (error "No available ports in erc-dcc-port-range")))))
+    process))
+
+(defun erc-dcc-server-accept (server client message)
+  "Log an accepted DCC offer, then terminate the listening process and set up
+the accepted connection."
+  (erc-log (format "(erc-dcc-server-accept): server %s client %s message %s"
+           server client message))
+  (when (and (string-match "^accept from " message)
+             (processp server) (processp client))
+    (let ((elt (erc-dcc-member :peer server)))
+      ;; change the entry in erc-dcc-list from the listening process to the
+      ;; accepted process
+      (setq elt (plist-put elt :peer client))
+      ;; delete the listening process, as we've accepted the connection
+      (delete-process server))))
+
+;;; Interactive command handling
+
+(defcustom erc-dcc-get-default-directory nil
+  "*Default directory for incoming DCC file transfers.
+If this is nil, then the current value of `default-directory' is used."
+  :group 'erc-dcc
+  :type '(choice (const nil :tag "Default directory") directory))
+
+;;;###autoload
+(defun erc-cmd-DCC (cmd &rest args)
+  "Parser for /dcc command.
+This figures out the dcc subcommand and calls the appropriate routine to
+handle it.  The function dispatched should be named \"erc-dcc-do-FOO-command\",
+where FOO is one of CLOSE, GET, SEND, LIST, CHAT, etc."
+  (when cmd
+    (let ((fn (intern-soft (concat "erc-dcc-do-" (upcase cmd) "-command"))))
+      (if fn
+          (apply fn erc-server-process args)
+        (erc-display-message
+         nil 'notice 'active
+         'dcc-command-undefined ?c cmd)
+        (apropos "erc-dcc-do-.*-command")
+        t))))
+
+;;;###autoload
+(defun pcomplete/erc-mode/DCC ()
+  "Provides completion for the /DCC command."
+  (pcomplete-here (append '("chat" "close" "get" "list")
+                          (when (fboundp 'make-network-process) '("send"))))
+  (pcomplete-here
+   (case (intern (downcase (pcomplete-arg 1)))
+     (chat (mapcar (lambda (elt) (plist-get elt :nick))
+                   (erc-remove-if-not
+                    #'(lambda (elt)
+                        (eq (plist-get elt :type) 'CHAT))
+                    erc-dcc-list)))
+     (close (remove-duplicates
+             (mapcar (lambda (elt) (symbol-name (plist-get elt :type)))
+                     erc-dcc-list) :test 'string=))
+     (get (mapcar #'erc-dcc-nick
+                  (erc-remove-if-not
+                   #'(lambda (elt)
+                       (eq (plist-get elt :type) 'GET))
+                   erc-dcc-list)))
+     (send (pcomplete-erc-all-nicks))))
+  (pcomplete-here
+   (case (intern (downcase (pcomplete-arg 2)))
+     (get (mapcar (lambda (elt) (plist-get elt :file))
+                  (erc-remove-if-not
+                   #'(lambda (elt)
+                       (and (eq (plist-get elt :type) 'GET)
+                            (erc-nick-equal-p (erc-extract-nick
+                                               (plist-get elt :nick))
+                                              (pcomplete-arg 1))))
+                   erc-dcc-list)))
+     (close (mapcar #'erc-dcc-nick
+                    (erc-remove-if-not
+                     #'(lambda (elt)
+                         (eq (plist-get elt :type)
+                             (intern (upcase (pcomplete-arg 1)))))
+                     erc-dcc-list)))
+     (send (pcomplete-entries)))))
+
+(defun erc-dcc-do-CHAT-command (proc &optional nick)
+  (when nick
+    (let ((elt (erc-dcc-member :nick nick :type 'CHAT :parent proc)))
+      (if (and elt (not (processp (plist-get elt :peer))))
+          ;; accept an existing chat offer
+          ;; FIXME: perhaps /dcc accept like other clients?
+          (progn (erc-dcc-chat-accept elt erc-server-process)
+                 (erc-display-message
+                  nil 'notice 'active
+                  'dcc-chat-accept ?n nick)
+                 t)
+        (erc-dcc-chat nick erc-server-process)
+        (erc-display-message
+         nil 'notice 'active
+         'dcc-chat-offer ?n nick)
+        t))))
+
+(defun erc-dcc-do-CLOSE-command (proc &optional type nick)
+  "/dcc close type nick
+type and nick are optional."
+  ;; FIXME, should also work if only nick is specified
+  (when (string-match (concat "^\\s-*\\(\\S-+\\)? *\\("
+                              erc-valid-nick-regexp "\\)?\\s-*$") line)
+    (let ((type (when (match-string 1 line)
+                  (intern (upcase (match-string 1 line)))))
+          (nick (match-string 2 line))
+          (ret t))
+      (while ret
+        (if nick
+            (setq ret (erc-dcc-member :type type :nick nick))
+          (setq ret (erc-dcc-member :type type)))
+        (when ret
+          ;; found a match - delete process if it exists.
+          (and (processp (plist-get ret :peer))
+               (delete-process (plist-get ret :peer)))
+          (setq erc-dcc-list (delq ret erc-dcc-list))
+          (erc-display-message
+           nil 'notice 'active
+           'dcc-closed
+           ?T (plist-get ret :type)
+           ?n (erc-extract-nick (plist-get ret :nick))))))
+      t))
+
+(defun erc-dcc-do-GET-command (proc nick &optional file)
+  (let* ((elt (erc-dcc-member :nick nick :type 'GET))
+         (filename (or file (plist-get elt :file) "unknown")))
+    (if elt
+        (let* ((file (read-file-name
+                      (format "Local filename (default %s): "
+                              (file-name-nondirectory filename))
+                      (or erc-dcc-get-default-directory
+                          default-directory)
+                      (expand-file-name (file-name-nondirectory filename)
+                                        (or erc-dcc-get-default-directory
+                                            default-directory)))))
+          (cond ((file-exists-p file)
+                 (if (yes-or-no-p (format "File %s exists.  Overwrite? "
+                                          file))
+                     (erc-dcc-get-file elt file proc)
+                   (erc-display-message
+                    nil '(notice error) proc
+                    'dcc-get-cmd-aborted
+                    ?n nick ?f filename)))
+                (t
+                 (erc-dcc-get-file elt file proc))))
+      (erc-display-message
+       nil '(notice error) 'active
+       'dcc-get-notfound ?n nick ?f filename))))
+
+(defun erc-dcc-do-LIST-command (proc)
+  "This is the handler for the /dcc list command.
+It lists the current state of `erc-dcc-list' in an easy to read manner."
+  (let ((alist erc-dcc-list)
+        size elt)
+    (erc-display-message
+     nil 'notice 'active
+     'dcc-list-head)
+    (erc-display-message
+     nil 'notice 'active
+     'dcc-list-line)
+    (while alist
+      (setq elt (car alist)
+            alist (cdr alist))
+
+      (setq size (or (and (plist-member elt :size)
+                          (plist-get elt :size))
+                     ""))
+      (setq size
+            (cond ((null size) "")
+                 ((numberp size) (number-to-string size))
+                 ((string= size "") "unknown")))
+      (erc-display-message
+       nil 'notice 'active
+       'dcc-list-item
+       ?n (erc-dcc-nick elt)
+       ?t (plist-get elt :type)
+       ?a (if (processp (plist-get elt :peer))
+              (process-status (plist-get elt :peer))
+            "no")
+       ?s (concat size
+                  (if (and (eq 'GET (plist-get elt :type))
+                           (plist-member elt :file)
+                           (buffer-live-p (get-buffer (plist-get elt :file)))
+                           (plist-member elt :size))
+                      (concat " (" (number-to-string
+                                    (* 100
+                                       (/ (buffer-size
+                                           (get-buffer (plist-get elt :file)))
+                                          (plist-get elt :size))))
+                              "%)")))
+       ?f (or (and (plist-member elt :file) (plist-get elt :file)) "")))
+    (erc-display-message
+     nil 'notice 'active
+     'dcc-list-end)
+    t))
+
+(defun erc-dcc-do-SEND-command (proc nick file)
+  "Offer FILE to NICK by sending a ctcp dcc send message."
+  (if (file-exists-p file)
+      (progn
+        (erc-display-message
+         nil 'notice 'active
+         'dcc-send-offer ?n nick ?f file)
+        (erc-dcc-send-file nick file) t)
+    (erc-display-message nil '(notice error) proc "File not found") t))
+
+;;; Server message handling (i.e. messages from remote users)
+
+;;;###autoload
+(defvar erc-ctcp-query-DCC-hook '(erc-ctcp-query-DCC)
+  "Hook variable for CTCP DCC queries")
+
+(defvar erc-dcc-query-handler-alist
+  '(("SEND" . erc-dcc-handle-ctcp-send)
+    ("CHAT" . erc-dcc-handle-ctcp-chat)))
+
+;;;###autoload
+(defun erc-ctcp-query-DCC (proc nick login host to query)
+  "The function called when a CTCP DCC request is detected by the client.
+It examines the DCC subcommand, and calls the appropriate routine for
+that subcommand."
+  (let* ((cmd (cadr (split-string query " ")))
+         (handler (cdr (assoc cmd erc-dcc-query-handler-alist))))
+    (if handler
+        (funcall handler proc query nick login host to)
+      ;; FIXME: Send a ctcp error notice to the remote end?
+      (erc-display-message
+       nil '(notice error) proc
+       'dcc-ctcp-unknown
+       ?q query ?n nick ?u login ?h host))))
+
+(defconst erc-dcc-ctcp-query-send-regexp
+  "^DCC SEND \\([^ ]+\\) \\([0-9]+\\) \\([0-9]+\\) *\\([0-9]*\\)")
+
+(defun erc-dcc-handle-ctcp-send (proc query nick login host to)
+  "This is called if a CTCP DCC SEND subcommand is sent to the client.
+It extracts the information about the dcc request and adds it to
+`erc-dcc-list'."
+  (unless (eq erc-dcc-send-request 'ignore)
+    (cond
+     ((not (erc-current-nick-p to))
+      ;; DCC SEND requests must be sent to you, and you alone.
+      (erc-display-message
+       nil 'notice proc
+       'dcc-request-bogus
+       ?r "SEND" ?n nick ?u login ?h host))
+     ((string-match erc-dcc-ctcp-query-send-regexp query)
+      (let ((filename (match-string 1 query))
+            (ip       (erc-decimal-to-ip (match-string 2 query)))
+            (port     (match-string 3 query))
+            (size     (match-string 4 query)))
+        ;; FIXME: a warning really should also be sent
+        ;; if the ip address != the host the dcc sender is on.
+        (erc-display-message
+         nil 'notice proc
+         'dcc-send-offered
+         ?f filename ?n nick ?u login ?h host
+         ?s (if (string= size "") "unknown" size))
+        (and (< (string-to-number port) 1025)
+             (erc-display-message
+              nil 'notice proc
+              'dcc-privileged-port
+              ?p port))
+        (erc-dcc-list-add
+         'GET (format "%s!%s@%s" nick login host)
+         nil proc
+         :ip ip :port port :file filename
+         :size (string-to-number size))
+        (if (and (eq erc-dcc-send-request 'auto)
+                 (erc-dcc-auto-mask-p (format "\"%s!%s@%s\"" nick login host)))
+            (erc-dcc-get-file (car erc-dcc-list) filename proc))))
+     (t
+      (erc-display-message
+       nil 'notice proc
+       'dcc-malformed
+       ?n nick ?u login ?h host ?q query)))))
+
+(defun erc-dcc-auto-mask-p (spec)
+  "Takes a full SPEC of a user in the form \"nick!login@host\" and
+matches against all the regexp's in `erc-dcc-auto-masks'. If any
+match, returns that regexp and nil otherwise."
+  (let ((lst erc-dcc-auto-masks))
+    (while (and lst
+                (not (string-match (car lst) spec)))
+      (setq lst (cdr lst)))
+    (and lst (car lst))))
+
+(defconst erc-dcc-ctcp-query-chat-regexp
+  "^DCC CHAT +chat +\\([0-9]+\\) +\\([0-9]+\\)")
+
+(defcustom erc-dcc-chat-request 'ask
+  "*How to treat incoming DCC Chat requests.
+'ask - Report the Chat request, and wait for the user to manually accept it
+'auto - Automatically accept the request and open a new chat window
+'ignore - Ignore incoming DCC chat requests completely."
+  :group 'erc-dcc
+  :type '(choice (const ask) (const auto) (const ignore)))
+
+(defun erc-dcc-handle-ctcp-chat (proc query nick login host to)
+  (unless (eq erc-dcc-chat-request 'ignore)
+    (cond
+     (;; DCC CHAT requests must be sent to you, and you alone.
+      (not (erc-current-nick-p to))
+      (erc-display-message
+       nil '(notice error) proc
+       'dcc-request-bogus ?r "CHAT" ?n nick ?u login ?h host))
+     ((string-match erc-dcc-ctcp-query-chat-regexp query)
+      ;; We need to use let* here, since erc-dcc-member might clutter
+      ;; the match value.
+      (let* ((ip   (erc-decimal-to-ip (match-string 1 query)))
+             (port (match-string 2 query))
+             (elt  (erc-dcc-member :nick nick :type 'CHAT)))
+        ;; FIXME: A warning really should also be sent if the ip
+        ;; address != the host the dcc sender is on.
+        (erc-display-message
+         nil 'notice proc
+         'dcc-chat-offered
+         ?n nick ?u login ?h host ?p port)
+        (and (< (string-to-number port) 1025)
+             (erc-display-message
+              nil 'notice proc
+              'dcc-privileged-port ?p port))
+        (cond (elt
+               ;; XXX: why are we updating ip/port on the existing connection?
+               (setq elt (plist-put (plist-put elt :port port) :ip ip))
+               (erc-display-message
+                nil 'notice proc
+                'dcc-chat-discarded ?n nick ?u login ?h host))
+              (t
+               (erc-dcc-list-add
+                'CHAT (format "%s!%s@%s" nick login host)
+                nil proc
+                :ip ip :port port)))
+        (if (eq erc-dcc-chat-request 'auto)
+            (erc-dcc-chat-accept (erc-dcc-member :nick nick :type 'CHAT)
+                                 proc))))
+     (t
+      (erc-display-message
+       nil '(notice error) proc
+       'dcc-malformed ?n nick ?u login ?h host ?q query)))))
+
+
+(defvar erc-dcc-entry-data nil
+  "Holds the `erc-dcc-list' entry for this DCC connection.")
+(make-variable-buffer-local 'erc-dcc-entry-data)
+
+;;; SEND handling
+
+(defcustom erc-dcc-block-size 1024
+  "*Block size to use for DCC SEND sessions."
+  :group 'erc-dcc
+  :type 'integer)
+
+(defcustom erc-dcc-pump-bytes nil
+  "*If set to an integer, keep sending until that number of bytes are
+unconfirmed."
+  :group 'erc-dcc
+  :type '(choice (const nil) integer))
+
+(defsubst erc-dcc-get-parent (proc)
+  (plist-get (erc-dcc-member :peer proc) :parent))
+
+(defun erc-dcc-send-block (proc)
+  "Send one block of data.
+PROC is the process-object of the DCC connection.  Returns the number of
+bytes sent."
+  (let* ((elt (erc-dcc-member :peer proc))
+         (confirmed-marker (plist-get elt :sent))
+         (sent-marker (plist-get elt :sent)))
+    (with-current-buffer (process-buffer proc)
+      (when erc-verbose-dcc
+        (erc-display-message
+         nil 'notice (erc-dcc-get-parent proc)
+         (format "DCC: Confirmed %d, sent %d, sending block now"
+                 (- confirmed-marker (point-min))
+               (- sent-marker (point-min)))))
+      (let* ((end (min (+ sent-marker erc-dcc-block-size)
+                       (point-max)))
+             (string (buffer-substring-no-properties sent-marker end)))
+        (when (< sent-marker end)
+          (set-marker sent-marker end)
+          (process-send-string proc string))
+        (length string)))))
+
+(defun erc-dcc-send-filter (proc string)
+  (erc-assert (= (% (length string) 4) 0))
+  (let* ((size (erc-unpack-int (substring string (- (length string) 4))))
+         (elt (erc-dcc-member :peer proc))
+         (parent (plist-get elt :parent))
+         (sent-marker (plist-get elt :sent))
+         (confirmed-marker (plist-get elt :confirmed)))
+    (with-current-buffer (process-buffer proc)
+      (set-marker confirmed-marker (+ (point-min) size))
+      (cond
+       ((and (= confirmed-marker sent-marker)
+             (= confirmed-marker (point-max)))
+        (erc-display-message
+         nil 'notice parent
+         'dcc-send-finished
+         ?n (plist-get elt :nick)
+         ?f buffer-file-name
+         ?s (number-to-string (- sent-marker (point-min))))
+        (setq erc-dcc-list (delete elt erc-dcc-list))
+        (set-buffer-modified-p nil)
+        (kill-buffer (current-buffer))
+        (delete-process proc))
+       ((<= confirmed-marker sent-marker)
+        (while (and (< (- sent-marker confirmed-marker)
+                       (or erc-dcc-pump-bytes
+                           erc-dcc-block-size))
+                    (> (erc-dcc-send-block proc) 0))))
+       ((> confirmed-marker sent-marker)
+        (erc-display-message
+         nil 'notice parent
+         (format "DCC: Client confirmed too much!"))
+        (delete-process proc))))))
+
+(defcustom erc-dcc-send-connect-hook
+  '((lambda (proc)
+      (erc-display-message
+       nil 'notice (erc-dcc-get-parent proc)
+       (format "DCC: SEND connect from %s"
+               (format-network-address (process-contact proc :remote)))))
+    erc-dcc-send-block)
+  "*Hook run whenever the remote end of a DCC SEND offer connected to your
+listening port."
+  :group 'erc-dcc
+  :type 'hook)
+
+(defun erc-dcc-nick (plist)
+  "Extract the nickname portion of the :nick property value in PLIST."
+  (erc-extract-nick (plist-get plist :nick)))
+
+(defun erc-dcc-send-sentinel (proc event)
+  (let* ((elt (erc-dcc-member :peer proc))
+         (buf (marker-buffer (plist-get elt :sent))))
+    (cond
+     ((string-match "^open from " event)
+      (when elt
+        (with-current-buffer buf
+          (set-process-buffer proc buf)
+          (setq erc-dcc-entry-data elt))
+        (run-hook-with-args 'erc-dcc-send-connect-hook proc))))))
+
+(defun erc-dcc-find-file (file)
+  (with-current-buffer (generate-new-buffer (file-name-nondirectory file))
+    (insert-file-contents-literally file)
+    (setq buffer-file-name file)
+    (current-buffer)))
+
+(defun erc-dcc-file-to-name (file)
+  (with-temp-buffer
+    (insert (file-name-nondirectory file))
+    (subst-char-in-region (point-min) (point-max) ?  ?_ t)
+    (buffer-string)))
+
+(defun erc-dcc-send-file (nick file &optional pproc)
+  "Open a socket for incoming connections, and send a CTCP send request to the
+other client."
+  (interactive "sNick: \nfFile: ")
+  (when (null pproc) (if (processp erc-server-process)
+                         (setq pproc erc-server-process)
+                       (error "Can not find parent process")))
+  (if (featurep 'make-network-process)
+      (let* ((buffer (erc-dcc-find-file file))
+             (size (buffer-size buffer))
+             (start (with-current-buffer buffer
+                      (set-marker (make-marker) (point-min))))
+             (sproc (erc-dcc-server "dcc-send"
+                                    'erc-dcc-send-filter
+                                    'erc-dcc-send-sentinel))
+             (contact (process-contact sproc)))
+        (erc-dcc-list-add
+         'SEND nick sproc pproc
+         :file file :size size
+         :sent start :confirmed (copy-marker start))
+        (process-send-string
+         pproc (format "PRIVMSG %s :\C-aDCC SEND %s %s %d %d\C-a\n"
+                       nick (erc-dcc-file-to-name file)
+                       (erc-ip-to-decimal (nth 0 contact))
+                       (nth 1 contact)
+                       size)))
+    (error "`make-network-process' not supported by your emacs.")))
+
+;;; GET handling
+
+(defvar erc-dcc-byte-count nil)
+(make-variable-buffer-local 'erc-dcc-byte-count)
+
+(defun erc-dcc-get-file (entry file parent-proc)
+  "This function does the work of setting up a transfer from the remote client
+to the local one over a tcp connection. This involves setting up a process
+filter and a process sentinel, and making the connection."
+  (let* ((buffer (generate-new-buffer (file-name-nondirectory file)))
+         proc)
+    (with-current-buffer buffer
+      (fundamental-mode)
+      ;; This is necessary to have the buffer saved as-is in GNU
+      ;; Emacs.
+      ;; XEmacs change: We don't have `set-buffer-multibyte', setting
+      ;; coding system to 'binary below takes care of us.
+      (when (fboundp 'set-buffer-multibyte)
+        (set-buffer-multibyte nil))
+
+      (setq mode-line-process '(":%s")
+            buffer-file-type t
+            buffer-read-only t)
+      (set-visited-file-name file)
+
+      (setq erc-server-process parent-proc
+            erc-dcc-entry-data entry)
+      (setq erc-dcc-byte-count 0)
+      (setq proc
+            (funcall erc-dcc-connect-function
+                     "dcc-get" buffer
+                     (plist-get entry :ip)
+                     (string-to-number (plist-get entry :port))
+                     entry))
+      (set-process-buffer proc buffer)
+      ;; The following two lines make saving as-is work under Windows
+      (set-process-coding-system proc 'binary 'binary)
+      (set-buffer-file-coding-system 'binary t)
+
+      (set-process-filter proc 'erc-dcc-get-filter)
+      (set-process-sentinel proc 'erc-dcc-get-sentinel)
+      (setq entry (plist-put entry :start-time (erc-current-time)))
+      (setq entry (plist-put entry :peer proc)))))
+
+(defun erc-dcc-get-filter (proc str)
+  "This is the process filter for transfers from other clients to this one.
+It reads incoming bytes from the network and stores them in the DCC
+buffer, and sends back the replies after each block of data per the DCC
+protocol spec.  Well not really.  We write back a reply after each read,
+rather than every 1024 byte block, but nobody seems to care."
+  (with-current-buffer (process-buffer proc)
+    (setq buffer-read-only nil) ;; FIXME
+    (goto-char (point-max))
+    (insert (string-make-unibyte str))
+
+    (setq erc-dcc-byte-count (+ (length str) erc-dcc-byte-count))
+    (erc-assert (= erc-dcc-byte-count (1- (point-max))))
+    (and erc-verbose-dcc
+         (erc-display-message
+          nil 'notice erc-server-process
+          'dcc-get-bytes-received
+          ?f (file-name-nondirectory buffer-file-name)
+          ?b (number-to-string erc-dcc-byte-count)))
+    (cond
+     ((and (> (plist-get erc-dcc-entry-data :size) 0)
+           (> erc-dcc-byte-count (plist-get erc-dcc-entry-data :size)))
+      (erc-display-message
+       nil '(error notice) 'active
+       'dcc-get-file-too-long
+       ?f (file-name-nondirectory buffer-file-name))
+      (delete-process proc))
+     (t
+      (process-send-string
+       proc (erc-pack-int erc-dcc-byte-count 4))))))
+
+
+(defun erc-dcc-get-sentinel (proc event)
+  "This is the process sentinel for CTCP DCC SEND connections.
+It shuts down the connection and notifies the user that the
+transfer is complete."
+  ;; FIXME, we should look at EVENT, and also check size.
+  (with-current-buffer (process-buffer proc)
+    (delete-process proc)
+    (setq buffer-read-only nil)
+    (setq erc-dcc-list (delete erc-dcc-entry-data erc-dcc-list))
+    (erc-display-message
+     nil 'notice erc-server-process
+     'dcc-get-complete
+     ?f (file-name-nondirectory buffer-file-name)
+     ?s (number-to-string (buffer-size))
+     ?t (format "%.0f"
+                (erc-time-diff (plist-get erc-dcc-entry-data :start-time)
+                               (erc-current-time))))
+    (save-buffer))
+  (kill-buffer (process-buffer proc))
+  (delete-process proc))
+
+;;; CHAT handling
+
+(defcustom erc-dcc-chat-buffer-name-format "DCC-CHAT-%s"
+  "*Format to use for DCC Chat buffer names."
+  :group 'erc-dcc
+  :type 'string)
+
+(defcustom erc-dcc-chat-mode-hook nil
+  "*Hook calls when `erc-dcc-chat-mode' finished setting up the buffer."
+  :group 'erc-dcc
+  :type 'hook)
+
+(defcustom erc-dcc-chat-connect-hook nil
+  ""
+  :group 'erc-dcc
+  :type 'hook)
+
+(defcustom erc-dcc-chat-exit-hook nil
+  ""
+  :group 'erc-dcc
+  :type 'hook)
+
+(defun erc-cmd-CREQ (line &optional force)
+  "Set or get the DCC chat request flag.
+Possible values are: ask, auto, ignore."
+  (when (string-match "^\\s-*\\(auto\\|ask\\|ignore\\)?$" line)
+    (let ((cmd (match-string 1 line)))
+      (if (stringp cmd)
+          (erc-display-message
+           nil 'notice 'active
+           (format "Set DCC Chat requests to %S"
+                   (setq erc-dcc-chat-request (intern cmd))))
+        (erc-display-message nil 'notice 'active
+                             (format "DCC Chat requests are set to %S"
+                                     erc-dcc-chat-request)))
+      t)))
+
+(defun erc-cmd-SREQ (line &optional force)
+  "Set or get the DCC send request flag.
+Possible values are: ask, auto, ignore."
+  (when (string-match "^\\s-*\\(auto\\|ask\\|ignore\\)?$" line)
+    (let ((cmd (match-string 1 line)))
+      (if (stringp cmd)
+          (erc-display-message
+           nil 'notice 'active
+           (format "Set DCC Send requests to %S"
+                   (setq erc-dcc-send-request (intern cmd))))
+        (erc-display-message nil 'notice 'active
+                             (format "DCC Send requests are set to %S"
+                                     erc-dcc-send-request)))
+      t)))
+
+(defun pcomplete/erc-mode/CREQ ()
+  (pcomplete-here '("auto" "ask" "ignore")))
+(defalias 'pcomplete/erc-mode/SREQ 'pcomplete/erc-mode/CREQ)
+
+(defvar erc-dcc-chat-filter-hook '(erc-dcc-chat-parse-output)
+  "*Hook to run after doing parsing (and possible insertion) of DCC messages.")
+
+(defvar erc-dcc-chat-mode-map
+  (let ((map (make-sparse-keymap)))
+    (define-key map (kbd "RET") 'erc-send-current-line)
+    (define-key map "\t" 'erc-complete-word)
+    map)
+  "Keymap for `erc-dcc-mode'.")
+
+(defun erc-dcc-chat-mode ()
+  "Major mode for wasting time via DCC chat."
+  (interactive)
+  (kill-all-local-variables)
+  (setq mode-line-process '(":%s")
+        mode-name "DCC-Chat"
+        major-mode 'erc-dcc-chat-mode
+        erc-send-input-line-function 'erc-dcc-chat-send-input-line
+        erc-default-recipients '(dcc))
+  (use-local-map erc-dcc-chat-mode-map)
+  (run-hooks 'erc-dcc-chat-mode-hook))
+
+(defun erc-dcc-chat-send-input-line (recipient line &optional force)
+  "Send LINE to the remote end.
+Argument RECIPIENT should always be the symbol dcc, and force
+is ignored."
+  ;; FIXME: We need to get rid of all force arguments one day!
+  (if (eq recipient 'dcc)
+      (process-send-string
+       (get-buffer-process (current-buffer)) line)
+    (error "erc-dcc-chat-send-input-line in %s" (current-buffer))))
+
+(defun erc-dcc-chat (nick &optional pproc)
+  "Open a socket for incoming connections, and send a chat request to the
+other client."
+  (interactive "sNick: ")
+  (when (null pproc) (if (processp erc-server-process)
+                         (setq pproc erc-server-process)
+                       (error "Can not find parent process")))
+  (let* ((sproc (erc-dcc-server "dcc-chat-out"
+                                'erc-dcc-chat-filter
+                                'erc-dcc-chat-sentinel))
+         (contact (process-contact sproc)))
+    (erc-dcc-list-add 'OCHAT nick sproc pproc)
+    (process-send-string pproc
+     (format "PRIVMSG %s :\C-aDCC CHAT chat %s %d\C-a\n"
+             nick
+             (erc-ip-to-decimal (nth 0 contact)) (nth 1 contact)))))
+
+(defvar erc-dcc-from)
+(make-variable-buffer-local 'erc-dcc-from)
+
+(defvar erc-dcc-unprocessed-output)
+(make-variable-buffer-local 'erc-dcc-unprocessed-output)
+
+(defun erc-dcc-chat-setup (entry)
+  "Setup a DCC chat buffer, returning the buffer."
+  (let* ((nick (erc-extract-nick (plist-get entry :nick)))
+         (buffer (generate-new-buffer
+                  (format erc-dcc-chat-buffer-name-format nick)))
+         (proc (plist-get entry :peer))
+         (parent-proc (plist-get entry :parent)))
+    (erc-setup-buffer buffer)
+    ;; buffer is now the current buffer.
+    (erc-dcc-chat-mode)
+    (setq erc-server-process parent-proc)
+    (setq erc-dcc-from nick)
+    (setq erc-dcc-entry-data entry)
+    (setq erc-dcc-unprocessed-output "")
+    (setq erc-insert-marker (set-marker (make-marker) (point-max)))
+    (erc-display-prompt buffer (point-max))
+    (set-process-buffer proc buffer)
+    (add-hook 'kill-buffer-hook 'erc-dcc-chat-buffer-killed nil t)
+    (run-hook-with-args 'erc-dcc-chat-connect-hook proc)
+    buffer))
+
+(defun erc-dcc-chat-accept (entry parent-proc)
+  "Accept an incoming DCC connection and open a DCC window"
+  (let* ((nick (erc-extract-nick (plist-get entry :nick)))
+         buffer proc)
+    (setq proc
+          (funcall erc-dcc-connect-function
+                   "dcc-chat" nil
+                   (plist-get entry :ip)
+                   (string-to-number (plist-get entry :port))
+                   entry))
+    ;; XXX: connected, should we kill the ip/port properties?
+    (setq entry (plist-put entry :peer proc))
+    (setq entry (plist-put entry :parent parent-proc))
+    (set-process-filter proc 'erc-dcc-chat-filter)
+    (set-process-sentinel proc 'erc-dcc-chat-sentinel)
+    (setq buffer (erc-dcc-chat-setup entry))))
+
+(defun erc-dcc-chat-filter (proc str)
+  (let ((orig-buffer (current-buffer)))
+    (unwind-protect
+        (progn
+          (set-buffer (process-buffer proc))
+          (setq erc-dcc-unprocessed-output
+                (concat erc-dcc-unprocessed-output str))
+          (run-hook-with-args 'erc-dcc-chat-filter-hook proc
+                           erc-dcc-unprocessed-output))
+      (set-buffer orig-buffer))))
+
+(defun erc-dcc-chat-parse-output (proc str)
+  (save-match-data
+    (let ((posn 0)
+          line)
+      (while (string-match "\n" str posn)
+        (setq line (substring str posn (match-beginning 0)))
+        (setq posn (match-end 0))
+        (erc-display-message
+         nil nil proc
+         'dcc-chat-privmsg ?n (erc-propertize erc-dcc-from 'face
+                                              'erc-nick-default-face) ?m line))
+      (setq erc-dcc-unprocessed-output (substring str posn)))))
+
+(defun erc-dcc-chat-buffer-killed ()
+  (erc-dcc-chat-close "killed buffer"))
+
+(defun erc-dcc-chat-close (&optional event)
+  "Close a DCC chat, removing any associated processes and tidying up
+`erc-dcc-list'"
+  (let ((proc (plist-get erc-dcc-entry-data :peer))
+        (evt (or event "")))
+    (when proc
+      (setq erc-dcc-list (delq erc-dcc-entry-data erc-dcc-list))
+      (run-hook-with-args 'erc-dcc-chat-exit-hook proc)
+      (delete-process proc)
+      (erc-display-message
+       nil 'notice erc-server-process
+       'dcc-chat-ended ?n erc-dcc-from ?t (current-time-string) ?e evt)
+      (setq erc-dcc-entry-data (plist-put erc-dcc-entry-data :peer nil)))))
+
+(defun erc-dcc-chat-sentinel (proc event)
+  (let ((buf (current-buffer))
+        (elt (erc-dcc-member :peer proc)))
+    ;; the sentinel is also notified when the connection is opened, so don't
+    ;; immediately kill it again
+    ;(message "buf %s elt %S evt %S" buf elt event)
+    (unwind-protect
+        (if (string-match "^open from" event)
+            (erc-dcc-chat-setup elt)
+          (erc-dcc-chat-close event))
+      (set-buffer buf))))
+
+(defun erc-dcc-no-such-nick (proc parsed)
+  "Detect and handle no-such-nick replies from the IRC server."
+  (let* ((elt (erc-dcc-member :nick (second (erc-response.command-args parsed))
+                              :parent proc))
+         (peer (plist-get elt :peer)))
+    (when (or (and (processp peer) (not (eq (process-status peer) 'open)))
+              elt)
+      ;; Since we already created an entry before sending the CTCP
+      ;; message, we now remove it, if it doesn't point to a process
+      ;; which is already open.
+      (setq erc-dcc-list (delq elt erc-dcc-list))
+      (if (processp peer) (delete-process peer)))
+    nil))
+
+(add-hook 'erc-server-401-functions 'erc-dcc-no-such-nick)
+
+(provide 'erc-dcc)
+
+;;; erc-dcc.el ends here
+;;
+;; Local Variables:
+;; indent-tabs-mode: nil
+;; End:
+
+;; arch-tag: cda5a6b3-c510-4dbe-b699-84cccfa04edb
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lisp/erc/erc-ezbounce.el	Wed Feb 01 10:07:17 2006 +0000
@@ -0,0 +1,180 @@
+;;; erc-ezbounce.el ---  Handle EZBounce bouncer commands
+
+;; Copyright (C) 2002, 2004 Free Software Foundation, Inc.
+
+;; Author: Andreas Fuchs <asf@void.at>
+;; Keywords: comm
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
+
+;;; Commentary:
+
+;;; Code:
+
+(require 'erc)
+(eval-when-compile (require 'cl))
+
+(defgroup erc-ezbounce nil
+  "Interface to the EZBounce IRC bouncer (a virtual IRC server)"
+  :group 'erc)
+
+(defcustom erc-ezb-regexp "^ezbounce!srv$"
+  "Regexp used by the EZBouncer to identify itself to the user."
+  :group 'erc-ezbounce
+  :type 'string)
+
+(defcustom erc-ezb-login-alist '()
+  "Alist of logins suitable for the server we're connecting to.
+
+The alist's format is as follows:
+
+ (((server . port) . (username . password))
+  ((server . port) . (username . password))
+  ...)"
+  :group 'erc-ezbounce
+  :type '(repeat
+	  (cons (cons :tag "Server"
+		     string
+		     string)
+		(cons :tag "Login"
+		      string
+		      string))))
+
+(defvar erc-ezb-action-alist '(("^\\[awaiting login/pass command\\]$" . erc-ezb-identify)
+			       ("^\\[use /quote CONN <server> to connect\\]$"    . erc-ezb-select)
+			       ("^ID +IRC NICK +TO +TIME$" . erc-ezb-init-session-list)
+			       ("^$"                       . erc-ezb-end-of-session-list)
+			       (".*"                       . erc-ezb-add-session))
+  "Alist of actions to take on NOTICEs from EZBounce.")
+
+
+(defvar erc-ezb-session-list '()
+  "List of detached EZBounce sessions.")
+(make-variable-buffer-local 'erc-ezb-session-list)
+
+(defvar erc-ezb-inside-session-listing nil
+  "Indicate whether current notices are expected to be EZB session listings.")
+
+;;;###autoload
+(defun erc-cmd-ezb (line &optional force)
+  "Send EZB commands to the EZBouncer verbatim."
+  (erc-server-send (concat "EZB " line)))
+(put 'erc-cmd-EZB 'do-not-parse-args t)
+
+;;;###autoload
+(defun erc-ezb-get-login (server port)
+  "Return an appropriate EZBounce login for SERVER and PORT.
+Look up entries in `erc-ezb-login-alist'. If the username or password
+in the alist is `nil', prompt for the appropriate values."
+  (let ((login (cdr (assoc (cons server port) erc-ezb-login-alist))))
+    (when login
+      (let ((username (car login))
+	    (password (cdr login)))
+	(when (null username)
+	  (setq username (read-from-minibuffer (format "EZBounce user name for %s:%s: " server port))))
+	(when (null password)
+	  (setq password (read-passwd (format "EZBounce password for %s:%s: " server port))))
+	(cons username password)))))
+
+;;;###autoload
+(defun erc-ezb-lookup-action (message)
+  (let ((function-alist erc-ezb-action-alist)
+	found)
+    (while (and (not found)
+		function-alist)
+      (let ((regexp (caar function-alist))
+	    (function (cdar function-alist)))
+	(when (string-match regexp message)
+	  (setq found function))
+	(setq function-alist (cdr function-alist))))
+    found))
+
+;;;###autoload
+(defun erc-ezb-notice-autodetect (proc parsed)
+  "React on an EZBounce NOTICE request."
+  (let* ((sender (erc-response.sender parsed))
+	 (message (erc-response.contents parsed))
+	 (function (erc-ezb-lookup-action message)))
+    (when (and (string-match erc-ezb-regexp sender)
+	       function)
+      (funcall function message)))
+  nil)
+
+;;;###autoload
+(defun erc-ezb-identify (message)
+  "Identify to the EZBouncer server."
+  (let ((login (erc-ezb-get-login erc-session-server (erc-port-to-string erc-session-port))))
+    (unless (null login)
+      (let ((username (car login))
+	    (pass (cdr login)))
+	(erc-server-send (concat "LOGIN " username " " pass))))))
+
+;;;###autoload
+(defun erc-ezb-init-session-list (message)
+  "Reset the EZBounce session list to NIL."
+  (setq erc-ezb-session-list nil)
+  (setq erc-ezb-inside-session-listing t))
+
+;;;###autoload
+(defun erc-ezb-end-of-session-list (message)
+  "Indicate the end of the EZBounce session listing."
+  (setq erc-ezb-inside-session-listing nil))
+  
+;;;###autoload
+(defun erc-ezb-add-session (message)
+  "Add an EZBounce session to the session list."
+  (when (and erc-ezb-inside-session-listing
+	     (string-match "^\\([^ ]+\\) +\\([^ ]+\\) +\\([^ ]+\\) +\\([^ ]+\\)$" message))
+    (let ((id (match-string 1 message))
+	  (nick (match-string 2 message))
+	  (to   (match-string 3 message)))
+      (add-to-list 'erc-ezb-session-list (list id nick to)))))
+
+;;;###autoload
+(defun erc-ezb-select (message)
+  "Select an IRC server to use by EZBounce, in ERC style."
+  (unless (and erc-ezb-session-list
+	       (erc-ezb-select-session))
+    (let* ((server (read-from-minibuffer
+		    "IRC server: " "" nil nil 'erc-server-history-list))
+	   (port
+	    (erc-string-to-port
+	     (read-from-minibuffer "IRC port: "
+				   (erc-port-to-string "6667")))))
+      (erc-server-send (format "CONN %s %s" server port)))))
+    
+
+;;;###autoload
+(defun erc-ezb-select-session ()
+  "Select a detached EZBounce session."
+  (let ((session (completing-read "Existing Session (RET to enter a new one): "
+			       erc-ezb-session-list)))
+    (if (string= session "")
+	nil
+      (erc-server-send (format "REATTACH %s" session)))))
+
+
+;;;###autoload
+(defun erc-ezb-initialize ()
+  "Add EZBouncer convenience functions to ERC."
+  (add-hook 'erc-server-NOTICE-functions 'erc-ezb-notice-autodetect))
+	
+(provide 'erc-ezbounce)
+
+;; arch-tag: e972aa7b-a9f4-4d16-a489-074ec7a1002e
+;;; erc-ezbounce.el ends here
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lisp/erc/erc-fill.el	Wed Feb 01 10:07:17 2006 +0000
@@ -0,0 +1,197 @@
+;;; erc-fill.el --- Filling IRC messages in various ways
+
+;; Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+
+;; Author: Andreas Fuchs <asf@void.at>
+;;         Mario Lang <mlang@delysid.org>
+;; URL: http://www.emacswiki.org/cgi-bin/wiki.pl?ErcFilling
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
+
+;;; Commentary:
+
+;; This package implements filling of messages sent and received.  Use
+;; `erc-fill-mode' to switch it on.  Customize `erc-fill-function' to
+;; change the style.
+
+;;; Code:
+
+(require 'erc)
+(require 'erc-stamp); for the timestamp stuff
+
+(defgroup erc-fill nil
+  "Filling means to reformat long lines in different ways."
+  :group 'erc)
+
+;;;###autoload (autoload 'erc-fill-mode "erc-fill" nil t)
+(erc-define-minor-mode erc-fill-mode
+  "Toggle ERC fill mode.
+With numeric arg, turn ERC fill mode on if and only if arg is
+positive.  In ERC fill mode, messages in the channel buffers are
+filled."
+  nil nil nil
+  :global t :group 'erc-fill
+  (if erc-fill-mode
+      (erc-fill-enable)
+    (erc-fill-disable)))
+
+(defun erc-fill-enable ()
+  "Setup hooks for `erc-fill-mode'."
+  (interactive)
+  (add-hook 'erc-insert-modify-hook 'erc-fill)
+  (add-hook 'erc-send-modify-hook 'erc-fill))
+
+(defun erc-fill-disable ()
+  "Cleanup hooks, disable `erc-fill-mode'."
+  (interactive)
+  (remove-hook 'erc-insert-modify-hook 'erc-fill)
+  (remove-hook 'erc-send-modify-hook 'erc-fill))
+
+(defcustom erc-fill-prefix nil
+  "Values used as `fill-prefix' for `erc-fill-variable'.
+nil means fill with space, a string means fill with this string."
+  :group 'erc-fill
+  :type '(choice (const nil) string))
+
+(defcustom erc-fill-function 'erc-fill-variable
+  "Function to use for filling messages.
+
+Variable Filling with an `erc-fill-prefix' of nil:
+
+<shortnick> this is a very very very long message with no
+	    meaning at all
+
+Variable Filling with an `erc-fill-prefix' of four spaces:
+
+<shortnick> this is a very very very long message with no
+    meaning at all
+
+Static Filling with `erc-fill-static-center' of 27:
+
+		<shortnick> foo bar baz
+	 <a-very-long-nick> foo bar baz quuuuux
+		<shortnick> this is a very very very long message with no
+			    meaning at all
+
+These two styles are implemented using `erc-fill-variable' and
+`erc-fill-static'.  You can, of course, define your own filling
+function.  Narrowing to the region in question is in effect while your
+function is called."
+  :group 'erc-fill
+  :type '(choice (const :tag "Variable Filling" erc-fill-variable)
+                 (const :tag "Static Filling" erc-fill-static)
+                 function))
+
+(defcustom erc-fill-static-center 27
+  "Column around which all statically filled messages will be
+centered.  This column denotes the point where the ' ' character
+between <nickname> and the entered text will be put, thus aligning
+nick names right and text left."
+  :group 'erc-fill
+  :type 'integer)
+
+(defcustom erc-fill-variable-maximum-indentation 17
+  "If we indent a line after a long nick, don't indent more then this
+characters. Set to nil to disable."
+  :group 'erc-fill
+  :type 'integer)
+
+(defcustom erc-fill-column 78
+  "The column at which a filled paragraph is broken."
+  :group 'erc-fill
+  :type 'integer)
+
+;;;###autoload
+(defun erc-fill ()
+  "Fill a region using the function referenced in `erc-fill-function'.
+You can put this on `erc-insert-modify-hook' and/or `erc-send-modify-hook'."
+  (unless (erc-string-invisible-p (buffer-substring (point-min) (point-max)))
+    (when erc-fill-function
+      (funcall erc-fill-function))))
+
+(defun erc-fill-static ()
+  "Fills a text such that messages start at column `erc-fill-static-center'."
+  (save-match-data
+    (goto-char (point-min))
+    (looking-at "^\\(\\S-+\\)")
+    (let ((nick (match-string 1)))
+        (let ((fill-column (- erc-fill-column (erc-timestamp-offset)))
+              (fill-prefix (make-string erc-fill-static-center 32)))
+          (insert (make-string (max 0 (- erc-fill-static-center
+                                         (length nick) 1))
+                               32))
+          (erc-fill-regarding-timestamp))
+        (erc-restore-text-properties))))
+
+(defun erc-fill-variable ()
+  "Fill from `point-min' to `point-max'."
+  (let ((fill-prefix erc-fill-prefix)
+        (fill-column (or erc-fill-column fill-column)))
+    (goto-char (point-min))
+    (if fill-prefix
+        (let ((first-line-offset (make-string (erc-timestamp-offset) 32)))
+          (insert first-line-offset)
+          (fill-region (point-min) (point-max) t t)
+          (goto-char (point-min))
+          (delete-char (length first-line-offset)))
+      (save-match-data
+        (let* ((nickp (looking-at "^\\(\\S-+\\)"))
+               (nick (if nickp
+                         (match-string 1)
+                       ""))
+               (fill-column (- erc-fill-column (erc-timestamp-offset)))
+               (fill-prefix (make-string (min (+ 1 (length nick))
+                                              (- fill-column 1)
+                                              (or erc-fill-variable-maximum-indentation
+                                                  fill-column))
+                                         32)))
+          (erc-fill-regarding-timestamp))))
+    (erc-restore-text-properties)))
+
+(defun erc-fill-regarding-timestamp ()
+  "Fills a text such that messages start at column `erc-fill-static-center'."
+  (fill-region (point-min) (point-max) t t)
+  (goto-char (point-min))
+  (forward-line)
+  (indent-rigidly (point) (point-max) (erc-timestamp-offset)))
+
+(defun erc-timestamp-offset ()
+  "Get length of timestamp if inserted left."
+  (if (and (boundp 'erc-timestamp-format)
+           erc-timestamp-format
+           (eq erc-insert-timestamp-function 'erc-insert-timestamp-left)
+           (not erc-hide-timestamps))
+      (length (format-time-string erc-timestamp-format))
+    0))
+
+(defun erc-restore-text-properties ()
+  "Restore the property 'erc-parsed for the region."
+  (let* ((parsed-posn (text-property-not-all (point-min) (point-max)
+                                             'erc-parsed nil))
+         (parsed-prop (when parsed-posn
+                        (get-text-property parsed-posn 'erc-parsed))))
+    (put-text-property (point-min) (point-max) 'erc-parsed parsed-prop)))
+
+(provide 'erc-fill)
+
+;;; erc-fill.el ends here
+;; Local Variables:
+;; indent-tabs-mode: nil
+;; End:
+
+;; arch-tag: 89224581-c2c2-4e26-92e5-e3a390dc516a
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lisp/erc/erc-goodies.el	Wed Feb 01 10:07:17 2006 +0000
@@ -0,0 +1,522 @@
+;; erc-goodies.el --- Collection of ERC modules
+
+;; Copyright (C) 2001, 2002, 2003, 2004, 2005 Free Software Foundation
+
+;; Author: Jorgen Schaefer <forcer@forcix.cx>
+
+;; Most code is taken verbatim from erc.el, see there for the original
+;; authors.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
+
+;;; Commentary:
+
+;; This provides some small but still useful modes for ERC.
+
+;;; Code:
+
+(require 'erc)
+
+;; Imenu Autoload
+(add-hook 'erc-mode-hook
+          (lambda ()
+            (setq imenu-create-index-function 'erc-create-imenu-index)))
+(autoload 'erc-create-imenu-index "erc-imenu" "Imenu index creation function")
+
+;;; Automatically scroll to bottom
+(defcustom erc-input-line-position nil
+  "Specify where to position the input line when using `erc-scroll-to-bottom'.
+
+This should be an integer specifying the line of the buffer on which
+the input line should stay.  A value of \"-1\" would keep the input
+line positioned on the last line in the buffer.  This is passed as an
+argument to `recenter'."
+  :group 'erc-display
+  :type '(choice integer (const nil)))
+
+(define-erc-module scrolltobottom nil
+  "This mode causes the prompt to stay at the end of the window.
+You have to activate or deactivate it in already created windows
+separately."
+  ((add-hook 'erc-mode-hook 'erc-add-scroll-to-bottom))
+  ((remove-hook 'erc-mode-hook 'erc-add-scroll-to-bottom)))
+
+(defun erc-add-scroll-to-bottom ()
+  "A hook function for `erc-mode-hook' to recenter output at bottom of window.
+
+If you find that ERC hangs when using this function, try customizing
+the value of `erc-input-line-position'.
+
+This works whenever scrolling happens, so it's added to
+`window-scroll-functions' rather than `erc-insert-post-hook'."
+  ;;(make-local-hook 'window-scroll-functions)
+  (add-hook 'window-scroll-functions 'erc-scroll-to-bottom nil t))
+
+(defun erc-scroll-to-bottom (window display-start)
+  "Recenter WINDOW so that `point' is on the last line.
+
+This is added to `window-scroll-functions' by `erc-add-scroll-to-bottom'.
+
+You can control which line is recentered to by customizing the
+variable `erc-input-line-position'.
+
+DISPLAY-START is ignored."
+  (if (and window (window-live-p window))
+      ;; Temporarily bind resize-mini-windows to nil so that users who have it
+      ;; set to a non-nil value will not suffer from premature minibuffer
+      ;; shrinkage due to the below recenter call.  I have no idea why this
+      ;; works, but it solves the problem, and has no negative side effects.
+      ;; (Fran Litterio, 2003/01/07)
+      (let ((resize-mini-windows nil))
+        (save-selected-window
+          (select-window window)
+          (save-restriction
+            (widen)
+            (when (and erc-insert-marker
+                       ;; we're editing a line. Scroll.
+                       (> (point) erc-insert-marker))
+              (save-excursion
+                (goto-char (point-max))
+                (recenter (or erc-input-line-position -1))
+                (sit-for 0))))))))
+
+;;; Make read only
+(define-erc-module readonly nil
+  "This mode causes all inserted text to be read-only."
+  ((add-hook 'erc-insert-post-hook 'erc-make-read-only)
+   (add-hook 'erc-send-post-hook 'erc-make-read-only))
+  ((remove-hook 'erc-insert-post-hook 'erc-make-read-only)
+   (remove-hook 'erc-send-post-hook 'erc-make-read-only)))
+
+(defun erc-make-read-only ()
+  "Make all the text in the current buffer read-only.
+Put this function on `erc-insert-post-hook' and/or `erc-send-post-hook'."
+  (put-text-property (point-min) (point-max) 'read-only t)
+  (put-text-property (point-min) (point-max) 'front-sticky t)
+  (put-text-property (point-min) (point-max) 'rear-nonsticky t))
+
+;; Distingush non-commands
+(defvar erc-noncommands-list '(erc-cmd-ME
+                               erc-cmd-COUNTRY
+                               erc-cmd-SV
+                               erc-cmd-SM
+                               erc-cmd-SMV
+                               erc-cmd-LASTLOG)
+  "List of commands that are aliases for CTCP ACTION or for erc messages.
+
+If a command's function symbol is in this list, the typed command
+does not appear in the ERC buffer after the user presses ENTER.")
+
+(define-erc-module noncommands nil
+  "This mode distinguishies non-commands.
+Commands listed in `erc-insert-this' know how to display
+themselves."
+  ((add-hook 'erc-send-pre-hook 'erc-send-distinguish-noncommands))
+  ((remove-hook 'erc-send-pre-hook 'erc-send-distinguish-noncommands)))
+
+(defun erc-send-distinguish-noncommands (str)
+  "If STR is an ERC non-command, set `erc-insert-this' to nil."
+  (let* ((command (erc-extract-command-from-line str))
+         (cmd-fun (and command
+                       (car command))))
+    (when (and cmd-fun
+               (not (string-match "\n.+$" str))
+               (memq cmd-fun erc-noncommands-list))
+      (setq erc-insert-this nil))))
+
+;;; IRC control character processing.
+(defgroup erc-control-characters nil
+  "Dealing with control characters"
+  :group 'erc)
+
+(defcustom erc-interpret-controls-p t
+  "*If non-nil, display IRC colours and other highlighting effects.
+
+If this is set to the symbol `remove', ERC removes all IRC colors and
+highlighting effects.  When this variable is non-nil, it can cause Emacs to run
+slowly on systems lacking sufficient CPU speed.  In chatty channels, or in an
+emergency (message flood) it can be turned off to save processing time.  See
+`erc-toggle-interpret-controls'."
+  :group 'erc-control-characters
+  :type '(choice (const :tag "Highlight control characters" t)
+                 (const :tag "Remove control characters" remove)
+                 (const :tag "Display raw control characters" nil)))
+
+(defcustom erc-interpret-mirc-color nil
+  "*If non-nil, erc will interpret mIRC color codes."
+  :group 'erc-control-characters
+  :type 'boolean)
+
+(defcustom erc-beep-p nil
+  "Beep if C-g is in the server message.
+The value `erc-interpret-controls-p' must also be t for this to work."
+  :group 'erc-control-characters
+  :type 'boolean)
+
+(defface erc-bold-face '((t (:bold t)))
+  "ERC bold face."
+  :group 'erc-faces)
+(defface erc-inverse-face
+  '((t (:foreground "White" :background "Black")))
+  "ERC inverse face."
+  :group 'erc-faces)
+(defface erc-underline-face '((t (:underline t)))
+  "ERC underline face."
+  :group 'erc-faces)
+
+(defface fg:erc-color-face0 '((t (:foreground "White")))
+  "ERC face."
+  :group 'erc-faces)
+(defface fg:erc-color-face1 '((t (:foreground "black")))
+  "ERC face."
+  :group 'erc-faces)
+(defface fg:erc-color-face2 '((t (:foreground "blue4")))
+  "ERC face."
+  :group 'erc-faces)
+(defface fg:erc-color-face3 '((t (:foreground "green4")))
+  "ERC face."
+  :group 'erc-faces)
+(defface fg:erc-color-face4 '((t (:foreground "red")))
+  "ERC face."
+  :group 'erc-faces)
+(defface fg:erc-color-face5 '((t (:foreground "brown")))
+  "ERC face."
+  :group 'erc-faces)
+(defface fg:erc-color-face6 '((t (:foreground "purple")))
+  "ERC face."
+  :group 'erc-faces)
+(defface fg:erc-color-face7 '((t (:foreground "orange")))
+  "ERC face."
+  :group 'erc-faces)
+(defface fg:erc-color-face8 '((t (:foreground "yellow")))
+  "ERC face."
+  :group 'erc-faces)
+(defface fg:erc-color-face9 '((t (:foreground "green")))
+  "ERC face."
+  :group 'erc-faces)
+(defface fg:erc-color-face10 '((t (:foreground "lightblue1")))
+  "ERC face."
+  :group 'erc-faces)
+(defface fg:erc-color-face11 '((t (:foreground "cyan")))
+  "ERC face."
+  :group 'erc-faces)
+(defface fg:erc-color-face12 '((t (:foreground "blue")))
+  "ERC face."
+  :group 'erc-faces)
+(defface fg:erc-color-face13 '((t (:foreground "deeppink")))
+  "ERC face."
+  :group 'erc-faces)
+(defface fg:erc-color-face14 '((t (:foreground "gray50")))
+  "ERC face."
+  :group 'erc-faces)
+(defface fg:erc-color-face15 '((t (:foreground "gray90")))
+  "ERC face."
+  :group 'erc-faces)
+
+(defface bg:erc-color-face0 '((t (:background "White")))
+  "ERC face."
+  :group 'erc-faces)
+(defface bg:erc-color-face1 '((t (:background "black")))
+  "ERC face."
+  :group 'erc-faces)
+(defface bg:erc-color-face2 '((t (:background "blue4")))
+  "ERC face."
+  :group 'erc-faces)
+(defface bg:erc-color-face3 '((t (:background "green4")))
+  "ERC face."
+  :group 'erc-faces)
+(defface bg:erc-color-face4 '((t (:background "red")))
+  "ERC face."
+  :group 'erc-faces)
+(defface bg:erc-color-face5 '((t (:background "brown")))
+  "ERC face."
+  :group 'erc-faces)
+(defface bg:erc-color-face6 '((t (:background "purple")))
+  "ERC face."
+  :group 'erc-faces)
+(defface bg:erc-color-face7 '((t (:background "orange")))
+  "ERC face."
+  :group 'erc-faces)
+(defface bg:erc-color-face8 '((t (:background "yellow")))
+  "ERC face."
+  :group 'erc-faces)
+(defface bg:erc-color-face9 '((t (:background "green")))
+  "ERC face."
+  :group 'erc-faces)
+(defface bg:erc-color-face10 '((t (:background "lightblue1")))
+  "ERC face."
+  :group 'erc-faces)
+(defface bg:erc-color-face11 '((t (:background "cyan")))
+  "ERC face."
+  :group 'erc-faces)
+(defface bg:erc-color-face12 '((t (:background "blue")))
+  "ERC face."
+  :group 'erc-faces)
+(defface bg:erc-color-face13 '((t (:background "deeppink")))
+  "ERC face."
+  :group 'erc-faces)
+(defface bg:erc-color-face14 '((t (:background "gray50")))
+  "ERC face."
+  :group 'erc-faces)
+(defface bg:erc-color-face15 '((t (:background "gray90")))
+  "ERC face."
+  :group 'erc-faces)
+
+(defun erc-get-bg-color-face (n)
+  "Fetches the right face for background color N (0-15)."
+  (if (stringp n) (setq n (string-to-number n)))
+  (if (not (numberp n))
+      (progn
+        (message "erc-get-bg-color-face: n is NaN: %S" n)
+        (beep)
+        'default)
+    (when (> n 16)
+      (erc-log (format "   Wrong color: %s" n))
+      (setq n (mod n 16)))
+    (cond
+     ((and (>= n 0) (< n 16))
+      (intern (concat "bg:erc-color-face" (number-to-string n))))
+     (t (erc-log (format "   Wrong color: %s" n)) 'default))))
+
+(defun erc-get-fg-color-face (n)
+  "Fetches the right face for foreground color N (0-15)."
+  (if (stringp n) (setq n (string-to-number n)))
+  (if (not (numberp n))
+      (progn
+        (message "erc-get-fg-color-face: n is NaN: %S" n)
+        (beep)
+        'default)
+    (when (> n 16)
+      (erc-log (format "   Wrong color: %s" n))
+      (setq n (mod n 16)))
+    (cond
+     ((and (>= n 0) (< n 16))
+      (intern (concat "fg:erc-color-face" (number-to-string n))))
+     (t (erc-log (format "   Wrong color: %s" n)) 'default))))
+
+(define-erc-module irccontrols nil
+  "This mode enables the interpretation of IRC control chars."
+  ((add-hook 'erc-insert-modify-hook 'erc-controls-highlight)
+   (add-hook 'erc-send-modify-hook 'erc-controls-highlight))
+  ((remove-hook 'erc-insert-modify-hook 'erc-controls-highlight)
+   (remove-hook 'erc-send-modify-hook 'erc-controls-highlight)))
+
+(defun erc-controls-interpret (str)
+   "Return a copy of STR after dealing with IRC control characters.
+See `erc-interpret-controls-p' and `erc-interpret-mirc-color' for options."
+   (when str
+     (let ((s str))
+       (cond ((eq erc-interpret-controls-p 'remove)
+              (erc-controls-strip s))
+             (erc-interpret-controls-p
+              (let ((boldp nil)
+                    (inversep nil)
+                    (underlinep nil)
+                    (fg nil)
+                    (bg nil))
+                (while (string-match erc-controls-highlight-regexp s)
+                  (let ((control (match-string 1 s))
+                        (fg-color (match-string 2 s))
+                        (bg-color (match-string 4 s))
+                        (start (match-beginning 0))
+                        (end (+ (match-beginning 0)
+                                (length (match-string 5 s)))))
+                    (setq s (erc-replace-match-subexpression-in-string
+                             "" s control 1 start))
+                    (cond ((and erc-interpret-mirc-color (or fg-color bg-color))
+                           (setq fg fg-color)
+                           (setq bg bg-color))
+                          ((string= control "\C-b")
+                           (setq boldp (not boldp)))
+                          ((string= control "\C-v")
+                           (setq inversep (not inversep)))
+                          ((string= control "\C-_")
+                           (setq underlinep (not underlinep)))
+                          ((string= control "\C-c")
+                           (setq fg nil
+                                 bg nil))
+                          ((string= control "\C-g")
+                           (when erc-beep-p
+                             (ding)))
+                          ((string= control "\C-o")
+                           (setq boldp nil
+                                 inversep nil
+                                 underlinep nil
+                                 fg nil
+                                 bg nil))
+                          (t nil))
+                    (erc-controls-propertize
+                     start end boldp inversep underlinep fg bg s)))
+                s))
+             (t s)))))
+
+(defun erc-controls-strip (str)
+  "Return a copy of STR with all IRC control characters removed."
+  (when str
+    (let ((s str))
+      (while (string-match erc-controls-remove-regexp s)
+        (setq s (replace-match "" nil nil s)))
+      s)))
+
+(defvar erc-controls-remove-regexp
+  "\C-b\\|\C-_\\|\C-v\\|\C-g\\|\C-o\\|\C-c[0-9]?[0-9]?\\(,[0-9][0-9]?\\)?"
+  "Regular expression which matches control characters to remove.")
+
+(defvar erc-controls-highlight-regexp
+  (concat "\\(\C-b\\|\C-v\\|\C-_\\|\C-g\\|\C-o\\|"
+          "\C-c\\([0-9][0-9]?\\)?\\(,\\([0-9][0-9]?\\)\\)?\\)"
+          "\\([^\C-b\C-v\C-_\C-c\C-g\C-o\n]*\\)")
+  "Regular expression which matches control chars and the text to highlight.")
+
+(defun erc-controls-highlight ()
+  "Highlight IRC control chars in the buffer.
+This is useful for `erc-insert-modify-hook' and
+`erc-send-modify-hook'. Also see `erc-interpret-controls-p' and
+`erc-interpret-mirc-color'."
+  (goto-char (point-min))
+  (cond ((eq erc-interpret-controls-p 'remove)
+         (while (re-search-forward erc-controls-remove-regexp nil t)
+           (replace-match "")))
+        (erc-interpret-controls-p
+         (let ((boldp nil)
+               (inversep nil)
+               (underlinep nil)
+               (fg nil)
+               (bg nil))
+           (while (re-search-forward erc-controls-highlight-regexp nil t)
+             (let ((control (match-string 1))
+                   (fg-color (match-string 2))
+                   (bg-color (match-string 4))
+                   (start (match-beginning 0))
+                   (end (+ (match-beginning 0) (length (match-string 5)))))
+               (replace-match "" nil nil nil 1)
+               (cond ((and erc-interpret-mirc-color (or fg-color bg-color))
+                      (setq fg fg-color)
+                      (setq bg bg-color))
+                     ((string= control "\C-b")
+                      (setq boldp (not boldp)))
+                     ((string= control "\C-v")
+                      (setq inversep (not inversep)))
+                     ((string= control "\C-_")
+                      (setq underlinep (not underlinep)))
+                     ((string= control "\C-c")
+                      (setq fg nil
+                            bg nil))
+                     ((string= control "\C-g")
+                      (when erc-beep-p
+                        (ding)))
+                     ((string= control "\C-o")
+                      (setq boldp nil
+                            inversep nil
+                            underlinep nil
+                            fg nil
+                            bg nil))
+                     (t nil))
+               (erc-controls-propertize start end
+                                        boldp inversep underlinep fg bg)))))
+        (t nil)))
+
+(defun erc-controls-propertize (from to boldp inversep underlinep fg bg
+                                     &optional str)
+  "Prepend properties from IRC control characters between FROM and TO.
+If optional argument STR is provided, apply to STR, otherwise prepend properties
+to a region in the current buffer."
+  (font-lock-prepend-text-property
+   from
+   to
+   'face
+   (append (if boldp
+               '(erc-bold-face)
+             nil)
+           (if inversep
+               '(erc-inverse-face)
+             nil)
+           (if underlinep
+               '(erc-underline-face)
+             nil)
+           (if fg
+               (list (erc-get-fg-color-face fg))
+             nil)
+           (if bg
+               (list (erc-get-bg-color-face bg))
+             nil))
+   str)
+  str)
+
+(defun erc-toggle-interpret-controls (&optional arg)
+  "Toggle interpretation of control sequences in messages.
+
+If ARG is positive, interpretation is turned on.
+Else interpretation is turned off."
+  (interactive "P")
+  (cond ((and (numberp arg) (> arg 0))
+         (setq erc-interpret-controls-p t))
+        (arg (setq erc-interpret-controls-p nil))
+        (t (setq erc-interpret-controls-p (not erc-interpret-controls-p))))
+  (message "ERC color interpretation %s"
+           (if erc-interpret-controls-p "ON" "OFF")))
+
+;; Smiley
+(define-erc-module smiley nil
+  "This mode translates text-smileys such as :-) into pictures.
+This requires the function `smiley-region', which is defined in
+smiley.el, which is part of Gnus."
+  ((add-hook 'erc-insert-modify-hook 'erc-smiley)
+   (add-hook 'erc-send-modify-hook 'erc-smiley))
+  ((remove-hook 'erc-insert-modify-hook 'erc-smiley)
+   (remove-hook 'erc-send-modify-hook 'erc-smiley)))
+
+(defun erc-smiley ()
+  "Smilify a region.
+This function should be used with `erc-insert-modify-hook'."
+  (when (fboundp 'smiley-region)
+    (smiley-region (point-min) (point-max))))
+
+;; Unmorse
+(define-erc-module unmorse nil
+  "This mode causes morse code in the current channel to be unmorsed."
+  ((add-hook 'erc-insert-modify-hook 'erc-unmorse))
+  ((remove-hook 'erc-insert-modify-hook 'erc-unmorse)))
+
+(defun erc-unmorse ()
+  "Unmorse some text.
+Add this to `erc-insert-modify-hook' if you happen to be on a
+channel that has weird people talking in morse to each other.
+
+See also `unmorse-region'."
+  (goto-char (point-min))
+  (when (re-search-forward "[.-]+\\([.-]+[/ ]\\)+[.-]+" nil t)
+    (unmorse-region (match-beginning 0) (match-end 0))))
+
+;;; erc-occur
+(defun erc-occur (string &optional proc)
+  "Search for STRING in all buffers related to current server.
+If called interactively and prefix argument is given, search on all connected
+servers.  If called from a program, PROC specifies the server process."
+  (interactive
+   (list (read-string "Search for: ")
+         (if current-prefix-arg
+             nil erc-server-process)))
+  (if (fboundp 'multi-occur)
+      (multi-occur (erc-buffer-list nil proc) string)
+    (error "`multi-occur' is not defined as a function")))
+
+(provide 'erc-goodies)
+
+;; arch-tag: d987ae26-9e28-4c72-9596-e617309fb582
+;;; erc-goodies.el ends here
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lisp/erc/erc-ibuffer.el	Wed Feb 01 10:07:17 2006 +0000
@@ -0,0 +1,192 @@
+;;; erc-ibuffer.el --- ibuffer integration with ERC
+
+;; Copyright (C) 2002, 2004 Free Software Foundation, Inc.
+
+;; Author: Mario Lang <mlang@delysid.org>
+;; Keywords: comm
+;; URL: http://www.emacswiki.org/cgi-bin/wiki.pl?ErcIbuffer
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
+
+;;; Commentary:
+
+;; This file contains code related to Ibuffer and ERC.  Totally alpha,
+;; needs work.  Usage:  Type / C-e C-h when in Ibuffer-mode to see new
+;; limiting commands
+
+;;; Code:
+
+(require 'ibuffer)
+(require 'ibuf-ext)
+(require 'erc)
+
+(defgroup erc-ibuffer nil
+  "The Ibuffer group for ERC."
+  :group 'erc)
+
+(defcustom erc-ibuffer-keyword-char ?k
+  "Char used to indicate a channel which had keyword traffic lately (hidden)."
+  :group 'erc-ibuffer
+  :type 'character)
+(defcustom erc-ibuffer-pal-char ?p
+  "Char used to indicate a channel which had pal traffic lately (hidden)."
+  :group 'erc-ibuffer
+  :type 'character)
+(defcustom erc-ibuffer-fool-char ?f
+  "Char used to indicate a channel which had fool traffic lately (hidden)."
+  :group 'erc-ibuffer
+  :type 'character)
+(defcustom erc-ibuffer-dangerous-host-char ?d
+  "Char used to indicate a channel which had dangerous-host traffic lately
+\(hidden)."
+  :group 'erc-ibuffer
+  :type 'character)
+
+(define-ibuffer-filter erc-server
+  "Toggle current view to buffers which are related to ERC servers."
+  (:description "erc servers"
+   :reader
+   (let ((regexp
+	  (read-from-minibuffer "Limit by server (regexp) (RET for all): ")))
+     (if (string= regexp "")
+	 ".*"
+       regexp)))
+  (with-current-buffer buf
+    (and (eq major-mode 'erc-mode)
+	 (string-match qualifier (or erc-server-announced-name
+				     erc-session-server)))))
+
+(define-ibuffer-column erc-modified (:name "M")
+  (if (and (boundp 'erc-track-mode)
+	   erc-track-mode)
+      (let ((entry (assq (current-buffer) erc-modified-channels-alist)))
+	(if entry
+	    (if (> (length entry) 1)
+		(cond ((eq 'pal (nth 1 entry))
+		       (string erc-ibuffer-pal-char))
+		      ((eq 'fool (nth 1 entry))
+		       (string erc-ibuffer-fool-char))
+		      ((eq 'keyword (nth 1 entry))
+		       (string erc-ibuffer-keyword-char))
+		      ((eq 'dangerous-host (nth 1 entry))
+		       (string erc-ibuffer-dangerous-host-char))
+		      (t "$"))
+	      (string ibuffer-modified-char))
+	  " "))
+    " "))
+
+(define-ibuffer-column erc-server-name (:name "Server")
+  (if (and (boundp 'erc-server-process) (processp erc-server-process))
+      (with-current-buffer (process-buffer erc-server-process)
+	(or erc-server-announced-name erc-session-server))
+    ""))
+
+(define-ibuffer-column erc-target (:name "Target")
+  (if (eq major-mode 'erc-mode)
+      (cond ((and (boundp 'erc-server-process) (processp erc-server-process)
+		  (eq (current-buffer) (process-buffer erc-server-process)))
+	     (concat "Server " erc-session-server ":"
+		     (erc-port-to-string erc-session-port)))
+	    ((erc-channel-p (erc-default-target))
+	     (concat (erc-default-target)))
+	    ((erc-default-target)
+	     (concat "Query: " (erc-default-target)))
+	    (t "(parted)"))
+    (buffer-name)))
+
+(define-ibuffer-column erc-topic (:name "Topic")
+  (if (and (eq major-mode 'erc-mode)
+	   erc-channel-topic)
+      (erc-controls-interpret erc-channel-topic)
+    ""))
+
+(define-ibuffer-column
+ erc-members (:name "Users")
+  (if (and (eq major-mode 'erc-mode)
+	   (boundp 'erc-channel-users)
+	   (hash-table-p erc-channel-users)
+	   (> (hash-table-size erc-channel-users) 0))
+     (number-to-string (hash-table-size erc-channel-users))
+    ""))
+
+(define-ibuffer-column erc-away (:name "A")
+  (if (and (boundp 'erc-server-process)
+	   (processp erc-server-process)
+	   (with-current-buffer (process-buffer erc-server-process)
+	     erc-away))
+      "A"
+    " "))
+
+(define-ibuffer-column
+ erc-op (:name "O")
+  (if (and (eq major-mode 'erc-mode)
+	   (erc-channel-user-op-p (erc-current-nick)))
+      "@"
+    " "))
+
+(define-ibuffer-column erc-voice (:name "V")
+  (if (and (eq major-mode 'erc-mode)
+	   (erc-channel-user-voice-p (erc-current-nick)))
+      "+"
+    " "))
+
+(define-ibuffer-column erc-channel-modes (:name "Mode")
+  (if (and (eq major-mode 'erc-mode)
+	   (or (> (length erc-channel-modes) 0)
+	       erc-channel-user-limit))
+      (concat (apply 'concat
+		     "(+" erc-channel-modes)
+	      (if erc-channel-user-limit
+		  (format "l %d" erc-channel-user-limit)
+		"")
+	      ")")
+    (if (not (eq major-mode 'erc-mode))
+	mode-name
+      "")))
+
+(define-ibuffer-column erc-nick (:name "Nick")
+  (if (eq major-mode 'erc-mode)
+      (erc-current-nick)
+    ""))
+
+(defvar erc-ibuffer-formats
+  '((mark erc-modified erc-away erc-op erc-voice " " (erc-nick 8 8) " "
+	  (erc-target 18 40) (erc-members 5 5 :center)
+	  (erc-channel-modes 6 16 :center) " " (erc-server-name 20 30) " "
+	  (erc-topic 10 -1))
+    (mark erc-modified erc-away erc-op erc-voice " " (erc-target 18 40)
+	  (erc-members 5 5 :center) (erc-channel-modes 9 20 :center) " "
+	  (erc-topic 10 -1))))
+(setq ibuffer-formats (append ibuffer-formats erc-ibuffer-formats))
+
+(defvar erc-ibuffer-limit-map nil
+  "Prefix keymap to use for ERC related limiting.")
+(define-prefix-command 'erc-ibuffer-limit-map)
+(define-key 'erc-ibuffer-limit-map (kbd "s") 'ibuffer-limit-by-erc-server)
+(define-key ibuffer-mode-map (kbd "/ \C-e") 'erc-ibuffer-limit-map)
+
+(provide 'erc-ibuffer)
+
+;;; erc-ibuffer.el ends here
+;;
+;; Local Variables:
+;; indent-tabs-mode: t
+;; tab-width: 8
+;; End:
+
+;; arch-tag: fbad56a5-8595-45e0-a8c8-d8bb91e26944
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lisp/erc/erc-identd.el	Wed Feb 01 10:07:17 2006 +0000
@@ -0,0 +1,87 @@
+;;; erc-identd.el --- RFC1413 (identd authentication protocol) server
+
+;; Copyright (C) 2003 Free Software Foundation, Inc.
+
+;; Author: John Wiegley <johnw@gnu.org>
+;; Keywords: comm, processes
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
+
+;;; Commentary:
+
+;; You can have a local identd server (running on port 8113; I use DNAT
+;; to bind 113->8113) if you add this to .emacs.el:
+
+;;    (add-hook 'erc-connect-pre-hook 'erc-identd-start)
+;;    (add-hook 'erc-disconnected-hook 'erc-identd-stop)
+
+;;; Code:
+
+(defvar erc-identd-process nil)
+
+(defun erc-identd-filter (proc string)
+  "This filter implements RFC1413 (identd authentication protocol)."
+  (let ((erc-identd-process proc))
+    (when (string-match "\\([0-9]+\\)\\s-*,\\s-*\\([0-9]+\\)" string)
+      (let ((port-on-server (match-string 1 string))
+	    (port-on-client (match-string 2 string)))
+	(send-string erc-identd-process
+		     (format "%s, %s : USERID : %s : %s\n"
+			     port-on-server port-on-client
+			     system-type (user-login-name)))
+	(process-send-eof erc-identd-process)))))
+
+(defun erc-identd-start (&optional port)
+  "Start an identd server listening to port 8113.
+Port 113 (auth) will need to be redirected to port 8113 on your
+machine -- using iptables, or a program like redir which can be
+run from inetd.  The idea is to provide a simple identd server
+when you need one, without having to install one globally on your
+system."
+  (interactive (list (read-string "Serve identd requests on port: " "8113")))
+  (if (null port)
+      (setq port 8113)
+    (if (stringp port)
+	(setq port (string-to-number port))))
+  (if erc-identd-process
+      (delete-process erc-identd-process))
+  (if (fboundp 'make-network-process)
+      (setq erc-identd-process
+	    (make-network-process :name "identd"
+				  :buffer (generate-new-buffer "identd")
+				  :service port :server t :noquery t
+				  :filter 'erc-identd-filter))
+    (open-network-stream-server "identd" (generate-new-buffer "identd")
+				port nil 'erc-identd-filter)))
+
+(defun erc-identd-stop (&rest ignore)
+  (interactive)
+  (when erc-identd-process
+    (delete-process erc-identd-process)
+    (setq erc-identd-process nil)))
+
+(provide 'erc-identd)
+
+;;; erc-identd.el ends here
+;;
+;; Local Variables:
+;; indent-tabs-mode: t
+;; tab-width: 8
+;; End:
+
+;; arch-tag: e0b5f926-0f35-40b9-8ddb-ca06b62a7544
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lisp/erc/erc-imenu.el	Wed Feb 01 10:07:17 2006 +0000
@@ -0,0 +1,143 @@
+;;; erc-imenu.el -- Imenu support for ERC
+
+;; Copyright (C) 2001, 2002, 2004 Free Software Foundation, Inc.
+
+;; Author: Mario Lang <mlang@delysid.org>
+;; Keywords: comm
+;; URL: http://www.emacswiki.org/cgi-bin/wiki.pl?ErcImenu
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
+
+;;; Commentary:
+
+;; This file contains code related to Ibuffer and ERC.  Totally alpha,
+;; needs work.  Usage:  Type / C-e C-h when in Ibuffer-mode to see new
+;; limiting commands
+
+;;; Code:
+
+
+;; Author: Mario Lang <mlang@delysid.org>
+
+;; This file is not part of GNU Emacs. But the same license applies.
+
+;;; Commentary:
+
+;; This package defines the function `erc-create-imenu-index'.  ERC
+;; uses this for `imenu-create-index-function', and autoloads it.
+;; Therefore, nothing needs to be done to use this package.
+
+;;; Code:
+
+(require 'erc)
+(require 'imenu)
+
+(defun erc-unfill-notice ()
+  "Return text from point to a computed end as a string unfilled.
+Don't rely on this function, read it first!"
+  (let ((str (buffer-substring
+	      (save-excursion
+		(re-search-forward (regexp-quote erc-notice-prefix)))
+	      (progn
+		(while (save-excursion
+			 (forward-line 1)
+			 (looking-at "    "))
+		  (forward-line 1))
+		(end-of-line) (point)))))
+    (with-temp-buffer
+      (insert str)
+      (goto-char (point-min))
+      (while (re-search-forward "\n +" nil t)
+	(replace-match " "))
+      (buffer-substring (point-min) (point-max)))))
+
+;;;###autoload
+(defun erc-create-imenu-index ()
+  (let ((index-alist '())
+	(notice-alist '())
+	(join-alist '())
+	(left-alist '())
+	(quit-alist '())
+	(message-alist '())
+	(mode-change-alist '())
+	(topic-change-alist '())
+	prev-pos)
+    (goto-char (point-max))
+    (imenu-progress-message prev-pos 0)
+    (while (if (bolp)
+	       (> (forward-line -1)
+		  -1)
+	     (progn (forward-line 0)
+		    t))
+      (imenu-progress-message prev-pos nil t)
+      (save-match-data
+	(when (looking-at (concat (regexp-quote erc-notice-prefix)
+				  "\\(.+\\)$"))
+	  (let ((notice-text  ;; Ugly hack, but seems to work.
+		 (save-excursion (erc-unfill-notice)))
+		(pos (point)))
+	    (push (cons notice-text pos) notice-alist)
+	    (or
+	     (when (string-match "^\\(.*\\) has joined channel" notice-text)
+	       (push (cons (match-string 1 notice-text) pos) join-alist))
+	     (when (string-match "^\\(.+\\) has left channel" notice-text)
+	       (push (cons (match-string 1 notice-text) pos) left-alist))
+	     (when (string-match "^\\(.+\\) has quit\\(.*\\)$" notice-text)
+	       (push (cons (concat (match-string 1 notice-text)
+				   (match-string 2 notice-text))
+			   (point))
+		     quit-alist))
+	     (when (string-match
+		    "^\\(\\S-+\\) (.+) has changed mode for \\S-+ to \\(.*\\)$"
+		    notice-text)
+	       (push (cons (concat (match-string 1 notice-text) ": "
+				   (match-string 2 notice-text))
+			   (point))
+		     mode-change-alist))
+	     (when (string-match
+		    "^\\(\\S-+\\) (.+) has set the topic for \\S-+: \\(.*\\)$"
+		    notice-text)
+	       (push (cons (concat (match-string 1 notice-text) ": "
+				   (match-string 2 notice-text)) pos)
+		     topic-change-alist)))))
+	(when (looking-at "<\\(\\S-+\\)> \\(.+\\)$")
+	  (let ((from (match-string 1))
+		(message-text (match-string 2)))
+	    (push (cons (concat from ": " message-text) (point))
+		  message-alist)))))
+    (and notice-alist (push (cons "notices" notice-alist) index-alist))
+    (and join-alist (push (cons "joined" join-alist) index-alist))
+    (and left-alist (push (cons "parted" left-alist) index-alist))
+    (and quit-alist (push (cons "quit" quit-alist) index-alist))
+    (and mode-change-alist (push (cons "mode-change" mode-change-alist)
+				 index-alist))
+    (and message-alist (push (cons "messages" message-alist) index-alist))
+    (and topic-change-alist (push (cons "topic-change" topic-change-alist)
+				  index-alist))
+    index-alist))
+
+(provide 'erc-imenu)
+
+;;; erc-imenu.el ends here
+;;
+;; Local Variables:
+;; indent-tabs-mode: t
+;; tab-width: 8
+;; End:
+
+;; arch-tag: 35c69082-ca29-43f7-a050-8da5f400de81
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lisp/erc/erc-lang.el	Wed Feb 01 10:07:17 2006 +0000
@@ -0,0 +1,213 @@
+;;; erc-lang.el --- provide the LANG command to ERC
+
+;; Copyright (C) 2002, 2004 Free Software Foundation, Inc.
+
+;; Author: Alex Schroeder <alex@gnu.org>
+;; Maintainer: Alex Schroeder <alex@gnu.org>
+;; Version: 1.0.0
+;; URL: http://www.emacswiki.org/cgi-bin/wiki.pl?ErcLang
+;; Keywords: comm languages processes
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
+
+;;; Commentary:
+
+;; This provides two commands: `language' is for everyday use, and
+;; `erc-cmd-LANG' provides the /LANG command to ERC.
+
+;;; Code:
+
+(require 'erc)
+
+(defvar iso-638-languages
+  '(("aa" . "Afar")
+    ("ab" . "Abkhazian")
+    ("af" . "Afrikaans")
+    ("am" . "Amharic")
+    ("ar" . "Arabic")
+    ("as" . "Assamese")
+    ("ay" . "Aymara")
+    ("az" . "Azerbaijani")
+    ("ba" . "Bashkir")
+    ("be" . "Byelorussian")
+    ("bg" . "Bulgarian")
+    ("bh" . "Bihari")
+    ("bi" . "Bislama")
+    ("bn" . "Bengali; Bangla")
+    ("bo" . "Tibetan")
+    ("br" . "Breton")
+    ("ca" . "Catalan")
+    ("co" . "Corsican")
+    ("cs" . "Czech")
+    ("cy" . "Welsh")
+    ("da" . "Danish")
+    ("de" . "German")
+    ("dz" . "Bhutani")
+    ("el" . "Greek")
+    ("en" . "English")
+    ("eo" . "Esperanto")
+    ("es" . "Spanish")
+    ("et" . "Estonian")
+    ("eu" . "Basque")
+    ("fa" . "Persian")
+    ("fi" . "Finnish")
+    ("fj" . "Fiji")
+    ("fo" . "Faroese")
+    ("fr" . "French")
+    ("fy" . "Frisian")
+    ("ga" . "Irish")
+    ("gd" . "Scots Gaelic")
+    ("gl" . "Galician")
+    ("gn" . "Guarani")
+    ("gu" . "Gujarati")
+    ("ha" . "Hausa")
+    ("he" . "Hebrew (formerly iw)")
+    ("hi" . "Hindi")
+    ("hr" . "Croatian")
+    ("hu" . "Hungarian")
+    ("hy" . "Armenian")
+    ("ia" . "Interlingua")
+    ("id" . "Indonesian (formerly in)")
+    ("ie" . "Interlingue")
+    ("ik" . "Inupiak")
+    ("is" . "Icelandic")
+    ("it" . "Italian")
+    ("iu" . "Inuktitut")
+    ("ja" . "Japanese")
+    ("jw" . "Javanese")
+    ("ka" . "Georgian")
+    ("kk" . "Kazakh")
+    ("kl" . "Greenlandic")
+    ("km" . "Cambodian")
+    ("kn" . "Kannada")
+    ("ko" . "Korean")
+    ("ks" . "Kashmiri")
+    ("ku" . "Kurdish")
+    ("ky" . "Kirghiz")
+    ("la" . "Latin")
+    ("ln" . "Lingala")
+    ("lo" . "Laothian")
+    ("lt" . "Lithuanian")
+    ("lv" . "Latvian, Lettish")
+    ("mg" . "Malagasy")
+    ("mi" . "Maori")
+    ("mk" . "Macedonian")
+    ("ml" . "Malayalam")
+    ("mn" . "Mongolian")
+    ("mo" . "Moldavian")
+    ("mr" . "Marathi")
+    ("ms" . "Malay")
+    ("mt" . "Maltese")
+    ("my" . "Burmese")
+    ("na" . "Nauru")
+    ("ne" . "Nepali")
+    ("nl" . "Dutch")
+    ("no" . "Norwegian")
+    ("oc" . "Occitan")
+    ("om" . "(Afan) Oromo")
+    ("or" . "Oriya")
+    ("pa" . "Punjabi")
+    ("pl" . "Polish")
+    ("ps" . "Pashto, Pushto")
+    ("pt" . "Portuguese")
+    ("qu" . "Quechua")
+    ("rm" . "Rhaeto-Romance")
+    ("rn" . "Kirundi")
+    ("ro" . "Romanian")
+    ("ru" . "Russian")
+    ("rw" . "Kinyarwanda")
+    ("sa" . "Sanskrit")
+    ("sd" . "Sindhi")
+    ("sg" . "Sangho")
+    ("sh" . "Serbo-Croatian")
+    ("si" . "Sinhalese")
+    ("sk" . "Slovak")
+    ("sl" . "Slovenian")
+    ("sm" . "Samoan")
+    ("sn" . "Shona")
+    ("so" . "Somali")
+    ("sq" . "Albanian")
+    ("sr" . "Serbian")
+    ("ss" . "Siswati")
+    ("st" . "Sesotho")
+    ("su" . "Sundanese")
+    ("sv" . "Swedish")
+    ("sw" . "Swahili")
+    ("ta" . "Tamil")
+    ("te" . "Telugu")
+    ("tg" . "Tajik")
+    ("th" . "Thai")
+    ("ti" . "Tigrinya")
+    ("tk" . "Turkmen")
+    ("tl" . "Tagalog")
+    ("tn" . "Setswana")
+    ("to" . "Tonga")
+    ("tr" . "Turkish")
+    ("ts" . "Tsonga")
+    ("tt" . "Tatar")
+    ("tw" . "Twi")
+    ("ug" . "Uighur")
+    ("uk" . "Ukrainian")
+    ("ur" . "Urdu")
+    ("uz" . "Uzbek")
+    ("vi" . "Vietnamese")
+    ("vo" . "Volapuk")
+    ("wo" . "Wolof")
+    ("xh" . "Xhosa")
+    ("yi" . "Yiddish (formerly ji)")
+    ("yo" . "Yoruba")
+    ("za" . "Zhuang")
+    ("zh" . "Chinese")
+    ("zu" . "Zulu"))
+  "Alist of ISO language codes and language names.
+This is based on the technical contents of ISO 639:1988 (E/F)
+\"Code for the representation of names of languages\".
+
+Typed by Keld.Simonsen@dkuug.dk 1990-11-30
+   <ftp://dkuug.dk/i18n/ISO_639>
+Minor corrections, 1992-09-08 by Keld Simonsen
+Sundanese corrected, 1992-11-11 by Keld Simonsen
+Telugu corrected, 1995-08-24 by Keld Simonsen
+Hebrew, Indonesian, Yiddish corrected 1995-10-10 by Michael Everson
+Inuktitut, Uighur, Zhuang added 1995-10-10 by Michael Everson
+Sinhalese corrected, 1995-10-10 by Michael Everson
+Faeroese corrected to Faroese, 1995-11-18 by Keld Simonsen
+Sangro corrected to Sangho, 1996-07-28 by Keld Simonsen
+
+Two-letter lower-case symbols are used.
+The Registration Authority for ISO 639 is Infoterm, Osterreichisches
+Normungsinstitut (ON), Postfach 130, A-1021 Vienna, Austria.")
+
+(defun language (code)
+  "Return the language name for the ISO CODE."
+  (interactive (list (completing-read "ISO language code: "
+				      iso-638-languages)))
+  (message (cdr (assoc code iso-638-languages))))
+
+(defun erc-cmd-LANG (language)
+  "Display the language name for the language code given by LANGUAGE."
+  (let ((lang (cdr (assoc language iso-638-languages))))
+    (erc-display-message
+     nil 'notice 'active
+     (or lang (concat line ": No such domain"))))
+  t)
+
+(provide 'erc-lang)
+
+;; arch-tag: 8ffb1563-cc03-4517-b067-16309d4ff97b
+;;; erc-lang.el ends here
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lisp/erc/erc-list.el	Wed Feb 01 10:07:17 2006 +0000
@@ -0,0 +1,396 @@
+;;; erc-list.el --- Provide a faster channel listing mechanism
+
+;; Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+;; Copyright (C) 2004 Brian Palmer
+
+;; Author: Mario Lang <mlang@lexx.delysid.org>
+;; Keywords: comm
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
+
+;;; Commentary:
+
+;; This file provides a simple derived mode for viewing Channel lists.
+;; It also serves as a demonstration of how the new server hook facility
+;; can be used.
+
+;;; Code:
+
+(require 'erc)
+(require 'erc-nets)
+(require 'sort)
+(unless (fboundp 'make-overlay)
+  (require 'overlay))
+(eval-when-compile (require 'cl))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; User customizable variables.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defgroup erc-list nil
+  "Display IRC channels in another window when using /LIST"
+  :group 'erc)
+
+(defcustom erc-chanlist-progress-message t
+  "*Show progress message while accumulating channel list."
+  :group 'erc-list
+  :type 'boolean)
+
+(defcustom erc-no-list-networks nil
+  "*A list of network names on which the /LIST command refuses to work."
+  :group 'erc-list
+  :type '(repeat string))
+
+(defcustom erc-chanlist-frame-parameters nil
+  "*If nil, the channel list is displayed in a new window; if non-nil,
+this variable holds the frame parameters used to make a frame to
+display the channel list."
+  :group 'erc-list
+  :type 'list)
+
+(defcustom erc-chanlist-hide-modeline nil
+  "*If nil, the channel list buffer has a modeline, otherwise the modeline is hidden."
+  :group 'erc-list
+  :type 'boolean)
+
+(defface erc-chanlist-header-face '((t (:bold t)))
+  "Face used for the headers in erc's channel list."
+  :group 'erc-faces)
+
+(defface erc-chanlist-odd-line-face '((t (:inverse-video t)))
+  "Face used for the odd lines in erc's channel list."
+  :group 'erc-faces)
+
+(defface erc-chanlist-even-line-face '((t (:inverse-video nil)))
+  "Face used for the even lines in erc's channel list."
+  :group 'erc-faces)
+
+(defface erc-chanlist-highlight '((t (:foreground "red")))
+  "Face used to highlight the current line in the channel list."
+  :group 'erc-faces)
+
+;; This should perhaps be a defface that inherits values from the highlight face
+;; but xemacs does not support inheritance
+(defcustom erc-chanlist-highlight-face 'erc-chanlist-highlight
+  "Face used for highlighting the current line in a list."
+  :type 'face
+  :group 'erc-faces)
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; All variables below this line are for internal use only.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defvar erc-chanlist-channel-line-regexp "^\\([#&\\*][^ \t\n]*\\)\\s-+[0-9]+"
+  "Regexp that matches a channel line in the channel list buffer.")
+
+(defvar erc-chanlist-buffer nil)
+(make-variable-buffer-local 'erc-chanlist-buffer)
+
+(defvar erc-chanlist-last-time 0
+  "A time value used to throttle the progress indicator.")
+
+(defvar erc-chanlist-frame nil
+  "The frame displaying the most recent channel list buffer.")
+
+(defvar erc-chanlist-sort-state 'channel
+  "The sort mode of the channel list buffer.  Either 'channel or 'users.")
+(make-variable-buffer-local 'erc-chanlist-sort-state)
+
+(defvar erc-chanlist-highlight-overlay nil
+  "The overlay used for erc chanlist highlighting")
+(make-variable-buffer-local 'erc-chanlist-highlight-overlay)
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Define erc-chanlist-mode.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defcustom erc-chanlist-mode-hook nil
+  "Hook run by erc-chanlist-mode."
+  :group 'erc-list
+  :type 'hook)
+
+(define-derived-mode erc-chanlist-mode fundamental-mode "ERC Channel List"
+  "Mode for viewing a channel list of a particular server.
+
+\\{erc-chanlist-mode-map}"
+  (local-set-key "\C-c\C-j" 'erc-join-channel)
+  (local-set-key "j" 'erc-chanlist-join-channel)
+  (local-set-key "n" 'next-line)
+  (local-set-key "p" 'previous-line)
+  (local-set-key "q" 'erc-chanlist-quit)
+  (local-set-key "s" 'erc-chanlist-toggle-sort-state)
+  (local-set-key "t" 'toggle-truncate-lines)
+  (setq erc-chanlist-sort-state 'channel)
+  (setq truncate-lines t)
+  (add-hook 'post-command-hook 'erc-chanlist-post-command-hook 'append 'local))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Functions.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;;;###autoload
+(defun erc-cmd-LIST (&rest channel)
+  "Display a buffer containing a list of channels on the current server.
+Optional argument CHANNEL specifies a single channel to list (instead of every
+available channel)."
+  (interactive
+   (remove "" (split-string
+	       (read-from-minibuffer "List channels (RET for all): ") " ")))
+  (if (and (null channel)
+	   (erc-member-ignore-case (erc-network-name) erc-no-list-networks))
+      (erc-display-line "ERC is configured not to allow the /LIST command on this network!"
+			(current-buffer))
+    (erc-display-line (erc-make-notice (concat "Listing channel"
+					       (if channel
+						   "."
+						 "s.  This may take a while."))))
+    (erc-chanlist channel))
+  t)
+
+;;;###autoload
+(defun erc-chanlist (&optional channels)
+  "Show a channel listing of the current server in a special mode.
+Please note that this function only works with IRC servers which conform
+to RFC and send the LIST header (#321) at start of list transmission."
+  (interactive)
+  (with-current-buffer (erc-server-buffer)
+    (erc-once-with-server-event
+     321
+     '(progn
+	(add-hook 'erc-server-322-functions 'erc-chanlist-322 nil t)
+
+	(erc-once-with-server-event
+	 323
+	 '(progn
+	    (remove-hook 'erc-server-322-functions 'erc-chanlist-322 t)
+	    (let ((buf erc-chanlist-buffer))
+	      (if (not (buffer-live-p buf))
+		  (error "`erc-chanlist-buffer' does not refer to a live buffer"))
+
+	      (set-buffer buf)
+	      (buffer-disable-undo)
+	      (let (buffer-read-only
+		    (sort-fold-case t))
+		(sort-lines nil (point-min) (point-max))
+		(setq erc-chanlist-sort-state 'channel)
+
+		(let ((sum (count-lines (point-min) (point-max))))
+		  (goto-char (point-min))
+		  (insert (substitute-command-keys
+			   (concat "'\\[erc-chanlist-toggle-sort-state]' toggle sort mode.\n"
+				   "'\\[erc-chanlist-quit]' kill this buffer.\n"
+				   "'\\[toggle-truncate-lines]' toggle line truncation.\n"
+				   "'\\[erc-chanlist-join-channel]' join the channel listed on the current line.\n\n")))
+		  (insert (format "%d channels (sorted by %s).\n\n"
+				  sum (if (eq erc-chanlist-sort-state 'channel)
+					  "channel name"
+					"number of users"))))
+
+		(insert (format "%-25s%5s %s\n------------------------ ----- ----------------------------\n"
+				"Channel"
+				"Users"
+				"Topic"))
+
+		;; Display the channel list buffer.
+		(if erc-chanlist-frame-parameters
+		    (progn
+		      (if (or (null erc-chanlist-frame)
+			      (not (frame-live-p erc-chanlist-frame)))
+			  (setq erc-chanlist-frame
+				(make-frame `((name . ,(format "Channels on %s"
+							       erc-session-server))
+					      ,@erc-chanlist-frame-parameters))))
+		      (select-frame erc-chanlist-frame)
+		      (switch-to-buffer buf)
+		      (erc-prettify-channel-list))
+		  (pop-to-buffer buf)
+		  (erc-prettify-channel-list))))
+	    (goto-char (point-min))
+	    (search-forward-regexp "^------" nil t)
+	    (forward-line 1)
+	    (erc-chanlist-highlight-line)
+	    (message "")
+	    t))
+
+	(setq erc-chanlist-buffer (get-buffer-create
+				   (format "*Channels on %s*"
+					   (erc-response.sender parsed))))
+	(with-current-buffer erc-chanlist-buffer
+	  (setq buffer-read-only nil)
+	  (erase-buffer)
+	  (erc-chanlist-mode)
+	  (setq erc-server-process proc)
+	  (if erc-chanlist-hide-modeline
+	      (setq mode-line-format nil))
+	  (setq buffer-read-only t))
+	t))
+
+    ;; Now that we've setup our callbacks, pull the trigger.
+    (if (interactive-p)
+	(message "Collecting channel list for server %s" erc-session-server))
+    (erc-server-send (if (null channels)
+			  "LIST"
+			(concat "LIST "
+				(mapconcat #'identity channels ","))))))
+
+(defun erc-chanlist-322 (proc parsed)
+  "Process an IRC 322 message.
+
+The message carries information about one channel for the LIST
+command."
+  (multiple-value-bind (channel num-users)
+      (cdr (erc-response.command-args parsed))
+    (let ((topic (erc-response.contents parsed)))
+      (with-current-buffer erc-chanlist-buffer
+	(save-excursion
+	  (goto-char (point-max))
+	  (let (buffer-read-only)
+	    (insert (format "%-26s%4s %s\n" (erc-controls-strip channel)
+			    num-users
+			    (erc-controls-strip topic))))
+
+	  ;; Maybe display a progress indicator in the minibuffer.
+	  (when (and erc-chanlist-progress-message
+		     (> (erc-time-diff
+			 erc-chanlist-last-time (erc-current-time))
+			3))
+	    (setq erc-chanlist-last-time (erc-current-time))
+	    (message "Accumulating channel list ... %c"
+		     (aref [?/ ?| ?\\ ?- ?! ?O ?o] (random 7))))
+
+	  ;; Return success to prevent other hook functions from being run.
+	  t)))))
+
+(defun erc-chanlist-post-command-hook ()
+  "Keep the current line highlighted."
+  (ignore-errors
+    (save-excursion
+      (beginning-of-line)
+      (if (looking-at erc-chanlist-channel-line-regexp)
+	  (erc-chanlist-highlight-line)
+	(erc-chanlist-dehighlight-line)))))
+
+(defun erc-chanlist-highlight-line ()
+  "Highlight the current line."
+  (unless erc-chanlist-highlight-overlay
+    (setq erc-chanlist-highlight-overlay
+	  (make-overlay (point-min) (point-min)))
+    ;; Detach it from the buffer.
+    (delete-overlay erc-chanlist-highlight-overlay)
+    (overlay-put erc-chanlist-highlight-overlay
+		 'face erc-chanlist-highlight-face)
+    ;; Expressly put it at a higher priority than the text
+    ;; properties used for faces later on. Gnu emacs promises that
+    ;; right now overlays are higher priority than text properties,
+    ;; but why take chances?
+    (overlay-put erc-chanlist-highlight-overlay 'priority 1))
+  (move-overlay erc-chanlist-highlight-overlay (point) (1+ (point-at-eol))))
+
+(defun erc-chanlist-dehighlight-line ()
+  "Remove the line highlighting."
+  (delete-overlay erc-chanlist-highlight-overlay))
+
+(defun erc-prettify-channel-list ()
+  "Make the channel list buffer look pretty.
+When this function runs, the current buffer must be the channel
+list buffer, or it does nothing."
+  (if (eq major-mode 'erc-chanlist-mode)
+      (save-excursion
+	(let ((inhibit-read-only t))
+	  (goto-char (point-min))
+	  (when (search-forward-regexp "^-------" nil t)
+	    (add-text-properties
+	     (point-min) (1+ (point-at-eol)) '(face erc-chanlist-header-face))
+	    (forward-line 1))
+
+	  (while (not (eobp))
+	    (add-text-properties
+	     (point) (1+ (point-at-eol)) '(face erc-chanlist-odd-line-face))
+	    (forward-line 1)
+	    (unless (eobp)
+	      (add-text-properties
+	       (point) (1+ (point-at-eol)) '(face erc-chanlist-even-line-face)))
+	    (forward-line 1))))))
+
+(defun erc-chanlist-toggle-sort-state ()
+  "Toggle the channel list buffer sorting method.
+Either sort by channel names or by number of users in each channel."
+  (interactive)
+  (let ((inhibit-read-only t)
+	(sort-fold-case t))
+    (save-excursion
+      (goto-char (point-min))
+      (search-forward-regexp "^-----" nil t)
+      (forward-line 1)
+      (unless (eobp)
+	(if (eq erc-chanlist-sort-state 'channel)
+	    (progn
+	      (sort-numeric-fields 2 (point) (point-max))
+	      (reverse-region (point) (point-max))
+	      (setq erc-chanlist-sort-state 'users))
+	  (sort-lines nil (point) (point-max))
+	  (setq erc-chanlist-sort-state 'channel))
+
+	(goto-char (point-min))
+	(if (search-forward-regexp "^[0-9]+ channels (sorted by \\(.*\\)).$"
+				   nil t)
+	    (replace-match (if (eq erc-chanlist-sort-state 'channel)
+			       "channel name"
+			     "number of users")
+			   nil nil nil 1))
+
+	(goto-char (point-min))
+	(search-forward-regexp "^-----" nil t)
+	(forward-line 1)
+	(recenter -1)
+
+	(erc-prettify-channel-list)))))
+
+(defun erc-chanlist-quit ()
+  "Quit Chanlist mode.
+Kill the channel list buffer, window, and frame (if there's a frame
+devoted to the channel list)."
+  (interactive)
+  (kill-buffer (current-buffer))
+  (if (eq (selected-frame) erc-chanlist-frame)
+      (delete-frame)
+    (delete-window)))
+
+(defun erc-chanlist-join-channel ()
+  "Join the channel listed on the current line of the channel list buffer.
+Private channels, which are shown as asterisks (*), are ignored."
+  (interactive)
+  (save-excursion
+    (beginning-of-line)
+    (when (looking-at erc-chanlist-channel-line-regexp)
+      (let ((channel-name (match-string 1)))
+	(when (and (stringp channel-name)
+		   (not (string= channel-name "*")))
+	  (run-at-time 0.5 nil 'erc-join-channel channel-name))))))
+
+(provide 'erc-list)
+
+;;; erc-list.el ends here
+;;
+;; Local Variables:
+;; indent-tabs-mode: t
+;; tab-width: 8
+;; End:
+
+;; arch-tag: 4a13196a-a61b-465a-9926-044dfbc7e5ff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lisp/erc/erc-log.el	Wed Feb 01 10:07:17 2006 +0000
@@ -0,0 +1,358 @@
+;;; erc-log.el --- Logging facilities for ERC.
+
+;; Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc.
+
+;; Author: Lawrence Mitchell <wence@gmx.li>
+;; Keywords: IRC, chat, client, Internet, logging
+
+;; Created 2003-04-26
+;; Logging code taken from erc.el and modified to use markers.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
+
+;;; Commentary:
+
+;; This file implements log file writing support for ERC.
+
+;; Quick start:
+;;
+;; (setq erc-enable-logging t)
+;; (setq erc-log-channels-directory "/path/to/logfiles") ; must be writable
+;;
+;; There are two ways to setup logging. The first will write to the log files
+;; on each incoming or outgoing line - this may not be optimal on a laptop
+;; HDD. To do this, M-x customize-variable erc-modules, and add "log".
+;;
+;; The second method will save buffers on /part, /quit, or killing the
+;; channel buffer. To do this, add the following to your .emacs:
+;;
+;; (require 'erc-log)
+;;
+;; You may optionally want the following code, to save all ERC buffers
+;; without confirmation when exiting emacs:
+;;
+;; (defadvice save-buffers-kill-emacs (before save-logs (&rest args) activate)
+;;  (save-some-buffers t (lambda ()
+;;                         (when (and (eq major-mode 'erc-mode)
+;;                                    (not (null buffer-file-name))) t))))
+;;
+;; If you only want to save logs for some buffers, customise the
+;; variable `erc-enable-logging'.
+
+;; How it works:
+;;
+;; If logging is enabled, at some point, `erc-save-buffer-in-logs'
+;; will be called.  The "end" of the buffer is taken from
+;; `erc-insert-marker', while `erc-last-saved-position' holds the
+;; position the buffer was last saved at (as a marker, or if the
+;; buffer hasn't been saved before, as the number 1 (point-min)).
+
+;; The region between `erc-last-saved-position' and
+;; `erc-insert-marker' is saved to the current buffer's logfile, and
+;; `erc-last-saved-position' is updated to reflect this.
+
+;;; History:
+;; 2003-04-26: logging code pulled out of erc.el.  Switched to using
+;; markers.
+
+;;; TODO:
+;; * Erc needs a generalised make-safe-file-name function, so that
+;;   generated file names don't contain any invalid file characters.
+;;
+;; * Really, we need to lock the logfiles somehow, so that if a user
+;;   is running multiple emacsen and/or on the same channel as more
+;;   than one user, only one process writes to the logfile.  This is
+;;   especially needed for those logfiles with no nick in them, as
+;;   these would become corrupted.
+;;   For a single emacs process, the problem could be solved using a
+;;   variable which contained the names of buffers already being
+;;   logged.  This would require that logging be buffer-local,
+;;   possibly not a bad thing anyway, since many people don't want to
+;;   log the server buffer.
+;;   For multiple emacsen the problem is trickier.  On some systems,
+;;   on could use the function `lock-buffer' and `unlock-buffer'.
+;;   However, file locking isn't implemented on all platforms, for
+;;   example, there is none on w32 systems.
+;;   A third possibility might be to fake lockfiles.  However, this
+;;   might lead to problems if an emacs crashes, as the lockfile
+;;   would be left lying around.
+
+;;; Code:
+
+(require 'erc)
+(eval-when-compile (require 'cl))
+
+(defgroup erc-log nil
+  "Logging facilities for ERC."
+  :group 'erc)
+
+(defcustom erc-generate-log-file-name-function 'erc-generate-log-file-name-long
+  "*A function to generate a log filename.
+The function must take five arguments: BUFFER, TARGET, NICK, SERVER and PORT.
+BUFFER is the buffer to be saved,
+TARGET is the name of the channel, or the target of the query,
+NICK is the current nick,
+SERVER and PORT are the parameters used to connect BUFFERs
+`erc-server-process'."
+  :group 'erc-log
+  :type '(choice (const erc-generate-log-file-name-long)
+		 (const erc-generate-log-file-name-short)
+		 (const erc-generate-log-file-name-with-date)
+		 (symbol)))
+
+(defcustom erc-save-buffer-on-part nil
+  "*Save the channel buffer content using `erc-save-buffer-in-logs' on PART."
+  :group 'erc-log
+  :type 'boolean)
+
+(defcustom erc-truncate-buffer-on-save nil
+  "Truncate any ERC (channel, query, server) buffer when it is saved."
+  :group 'erc-log
+  :type 'boolean)
+
+(defcustom erc-enable-logging t
+  "If non-nil, ERC will log IRC conversations.
+This can either be a boolean value of nil or t, or a function.
+If the value is a function, it will be called with one argument, the
+name of the current ERC buffer.  One possible function, which saves
+all but server buffers is `erc-log-all-but-server-buffers'.
+
+This variable is buffer local.  Setting it via \\[customize] sets the
+default value.
+
+Log files are stored in `erc-log-channels-directory'."
+  :group 'erc-log
+  :type '(choice boolean
+		 function))
+(make-variable-buffer-local 'erc-enable-logging)
+
+(defcustom erc-log-channels-directory "~/log"
+  "The directory to place log files for channels.
+Leave blank to disable logging.  If not nil, all the channel
+buffers are logged in separate files in that directory.  The
+directory should not end with a trailing slash."
+  :group 'erc-log
+  :type '(choice directory
+		 (const nil)))
+
+(defcustom erc-log-insert-log-on-open t
+  "*Insert log file contents into the buffer if a log file exists."
+  :group 'erc-log
+  :type 'boolean)
+
+(defcustom erc-save-queries-on-quit nil
+  "Save all query (also channel) buffers of the server on QUIT.
+See the variable `erc-save-buffer-on-part' for details."
+  :group 'erc-log
+  :type 'boolean)
+
+(defcustom erc-log-file-coding-system (if (featurep 'xemacs)
+					  'binary
+					'emacs-mule)
+  "*The coding system ERC should use for writing log files.
+
+This should ideally, be a \"catch-all\" coding system, like
+`emacs-mule', or `iso-2022-7bit'."
+  :group 'erc-log)
+
+;;;###autoload (autoload 'erc-log-mode "erc-log" nil t)
+(define-erc-module log nil
+  "Automatically logs things you receive on IRC into files.
+Files are stored in `erc-log-channels-directory'; file name
+format is defined through a formatting function on
+`erc-generate-log-file-name-function'.
+
+Since automatic logging is not always a Good Thing (especially if
+people say things in different coding systems), you can turn logging
+behaviour on and off with the variable `erc-enable-logging', which can
+also be a predicate function. To only log when you are not set away, use:
+
+\(setq erc-enable-logging
+      (lambda (buffer)
+	(with-current-buffer buffer
+	  (not erc-away))))"
+  ;; enable
+  ((add-hook 'erc-insert-post-hook
+	     'erc-save-buffer-in-logs)
+   (add-hook 'erc-send-post-hook
+	     'erc-save-buffer-in-logs))
+  ;; disable
+  ((remove-hook 'erc-insert-post-hook
+		'erc-save-buffer-in-logs)
+   (remove-hook 'erc-send-post-hook
+		'erc-save-buffer-in-logs)))
+
+(when erc-enable-logging
+  (add-hook 'erc-kill-buffer-hook
+	    'erc-save-buffer-in-logs)
+  (add-hook 'erc-kill-channel-hook
+	    'erc-save-buffer-in-logs)
+  (add-hook 'erc-quit-hook
+	    'erc-conditional-save-queries)
+  (add-hook 'erc-part-hook
+	    'erc-conditional-save-buffer))
+
+(define-key erc-mode-map "\C-c\C-l" 'erc-save-buffer-in-logs)
+
+;;;functionality referenced from erc.el
+(defun erc-log-setup-logging ()
+  "Setup the buffer-local logging variables in the current buffer.
+This function is destined to be run from `erc-connect-pre-hook'."
+  (when (erc-logging-enabled)
+    (auto-save-mode -1)
+    (setq buffer-offer-save t
+	  buffer-file-name "")
+    (set (make-local-variable 'write-file-functions)
+	 '(erc-save-buffer-in-logs))
+    (when erc-log-insert-log-on-open
+      (ignore-errors (insert-file-contents (erc-current-logfile))
+		     (move-marker erc-last-saved-position
+				  (1- (point-max)))))))
+
+;;; Append, so that 'erc-initialize-log-marker keeps running first.
+(add-hook 'erc-connect-pre-hook 'erc-log-setup-logging 'append)
+
+(defun erc-log-all-but-server-buffers (buffer)
+  "Returns t if logging should be enabled in BUFFER.
+Returns nil iff `erc-server-buffer-p' returns t."
+  (save-excursion
+    (save-window-excursion
+      (set-buffer buffer)
+      (not (erc-server-buffer-p)))))
+
+(defun erc-save-query-buffers (process)
+  "Save all buffers process."
+  (erc-with-all-buffers-of-server process
+				  nil
+				  (erc-save-buffer-in-logs)))
+
+(defun erc-conditional-save-buffer (buffer)
+  "Save Query BUFFER if `erc-save-queries-on-quit' is t."
+  (when erc-save-buffer-on-part
+    (erc-save-buffer-in-logs buffer)))
+
+(defun erc-conditional-save-queries (process)
+  "Save Query buffers of PROCESS if `erc-save-queries-on-quit' is t."
+  (when erc-save-queries-on-quit
+    (erc-save-query-buffers process)))
+
+;;;###autoload
+(defun erc-logging-enabled (&optional buffer)
+  "Return non-nil if logging is enabled for BUFFER.
+If BUFFER is nil, the value of `current-buffer' is used.
+Logging is enabled if `erc-log-channels-directory' is non-nil, the directory
+is writeable (it will be created as necessary) and
+`erc-enable-logging' returns a non-nil value."
+  (and erc-log-channels-directory
+       (erc-directory-writable-p erc-log-channels-directory)
+       (if (functionp erc-enable-logging)
+	   (funcall erc-enable-logging (or buffer (current-buffer)))
+	 erc-enable-logging)))
+
+(defun erc-current-logfile (&optional buffer)
+  "Return the logfile to use for BUFFER.
+If BUFFER is nil, the value of `current-buffer' is used.
+This is determined by `erc-generate-log-file-name-function'.
+The result is converted to lowercase, as IRC is case-insensitive"
+  (expand-file-name
+   (downcase (funcall erc-generate-log-file-name-function
+		      (or buffer (current-buffer))
+		      (or (erc-default-target) (buffer-name buffer))
+		      (erc-current-nick)
+		      erc-session-server erc-session-port))
+   erc-log-channels-directory))
+
+(defun erc-generate-log-file-name-with-date (buffer &rest ignore)
+  "This function computes a short log file name.
+The name of the log file is composed of BUFFER and the current date.
+This function is a possible value for `erc-generate-log-file-name-function'."
+  (concat (buffer-name buffer) "-" (format-time-string "%Y-%m-%d") ".txt"))
+
+(defun erc-generate-log-file-name-short (buffer &rest ignore)
+  "This function computes a short log file name.
+In fact, it only uses the buffer name of the BUFFER argument, so
+you can affect that using `rename-buffer' and the-like.  This
+function is a possible value for
+`erc-generate-log-file-name-function'."
+  (concat (buffer-name buffer) ".txt"))
+
+(defun erc-generate-log-file-name-long (buffer target nick server port)
+  "Generates a log-file name in the way ERC always did it.
+This results in a file name of the form #channel!nick@server:port.txt.
+This function is a possible value for `erc-generate-log-file-name-function'."
+  (let ((file (concat
+	       (if target (concat target "!"))
+	       nick "@" server ":" (cond ((stringp port) port)
+					 ((numberp port)
+					  (number-to-string port))) ".txt")))
+    ;; we need a make-safe-file-name function.
+    (convert-standard-filename file)))
+
+;;;###autoload
+(defun erc-save-buffer-in-logs (&optional buffer)
+  "Append BUFFER contents to the log file, if logging is enabled.
+If BUFFER is not provided, current buffer is used.
+Logging is enabled if `erc-logging-enabled' returns non-nil.
+
+This is normally done on exit, to save the unsaved portion of the
+buffer, since only the text that runs off the buffer limit is logged
+automatically.
+
+You can save every individual message by putting this function on
+`erc-insert-post-hook'."
+  (interactive)
+  (or buffer (setq buffer (current-buffer)))
+  (when (erc-logging-enabled buffer)
+    (let ((file (erc-current-logfile buffer))
+	  (coding-system-for-write erc-log-file-coding-system))
+      (save-excursion
+	(with-current-buffer buffer
+	  (save-restriction
+	    (widen)
+	    ;; early on in the initalisation, don't try and write the log out
+	    (when (and (markerp erc-last-saved-position)
+		       (> erc-insert-marker (1+ erc-last-saved-position)))
+	      (write-region (1+ (marker-position erc-last-saved-position))
+			    (marker-position erc-insert-marker)
+			    file t 'nomessage)
+	      (if (and erc-truncate-buffer-on-save (interactive-p))
+		  (progn
+		    (let ((inhibit-read-only t)) (erase-buffer))
+		    (move-marker erc-last-saved-position (point-max))
+		    (erc-display-prompt))
+		(move-marker erc-last-saved-position
+			     ;; If we place erc-last-saved-position at
+			     ;; erc-insert-marker, because text gets
+			     ;; inserted /before/ erc-insert-marker,
+			     ;; the log file will not be saved
+			     ;; (erc-last-saved-position will always
+			     ;; be equal to erc-insert-marker).
+			     (1- (marker-position erc-insert-marker)))))
+	    (set-buffer-modified-p nil))))))
+  t)
+
+(provide 'erc-log)
+
+;;; erc-log.el ends here
+;;
+;; Local Variables:
+;; indent-tabs-mode: t
+;; tab-width: 8
+;; End:
+
+;; arch-tag: 54072f99-9f0a-4846-8908-2ccde92221de
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lisp/erc/erc-match.el	Wed Feb 01 10:07:17 2006 +0000
@@ -0,0 +1,658 @@
+;;; erc-match.el --- Highlight messages matching certain regexps
+
+;; Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+
+;; Author: Andreas Fuchs <asf@void.at>
+;; Keywords: comm, faces
+;; URL: http://www.emacswiki.org/cgi-bin/wiki.pl?ErcMatch
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
+
+;;; Commentary:
+
+;; This file includes stuff to work with pattern matching in ERC. If
+;; you were used to customizing erc-fools, erc-keywords, erc-pals,
+;; erc-dangerous-hosts and the like, this file contains these
+;; customizable variables.
+
+;; Usage:
+;; Put (erc-match-mode 1) into your ~/.emacs file.
+
+;;; Code:
+
+(require 'erc)
+(eval-when-compile (require 'cl))
+
+;; Customisation:
+
+(defgroup erc-match nil
+  "Keyword and Friend/Foe/... recognition.
+Group containing all things concerning pattern matching in ERC
+messages."
+  :group 'erc)
+
+;;;###autoload (autoload 'erc-match-mode "erc-match")
+(define-erc-module match nil
+  "This mode checks whether messages match certain patterns.  If so,
+they are hidden or highlighted.  This is controlled via the variables
+`erc-pals', `erc-fools', `erc-keywords', `erc-dangerous-hosts', and
+`erc-current-nick-highlight-type'.  For all these highlighting types,
+you can decide whether the entire message or only the sending nick is
+highlighted."
+  ((add-hook 'erc-insert-modify-hook 'erc-match-message 'append))
+  ((remove-hook 'erc-insert-modify-hook 'erc-match-message)))
+
+;; Remaining customizations
+
+(defcustom erc-pals nil
+  "List of pals on IRC."
+  :group 'erc-match
+  :type '(repeat regexp))
+
+(defcustom erc-fools nil
+  "List of fools on IRC."
+  :group 'erc-match
+  :type '(repeat regexp))
+
+(defcustom erc-keywords nil
+  "List of keywords to highlight in all incoming messages.
+Each entry in the list is either a regexp, or a cons cell with the
+regexp in the car and the face to use in the cdr.  If no face is
+specified, `erc-keyword-face' is used."
+  :group 'erc-match
+  :type '(repeat (choice regexp
+			 (list regexp face))))
+
+(defcustom erc-dangerous-hosts nil
+  "List of regexps for hosts to highlight.
+Useful to mark nicks from dangerous hosts."
+  :group 'erc-match
+  :type '(repeat regexp))
+
+(defcustom erc-current-nick-highlight-type 'keyword
+  "*Determines how to highlight text in which your current nickname appears
+\(does not apply to text sent by you\).
+
+The following values are allowed:
+
+ nil              - do not highlight the message at all
+ 'keyword         - highlight all instances of current nickname in message
+ 'nick            - highlight the nick of the user who typed your nickname
+ 'nick-or-keyword - highlight the nick of the user who typed your nickname,
+                    or all instances of the current nickname if there was
+                    no sending user
+ 'all             - highlight the entire message where current nickname occurs
+
+Any other value disables highlighting of current nickname altogether."
+  :group 'erc-match
+  :type '(choice (const nil)
+		 (const nick)
+		 (const keyword)
+		 (const nick-or-keyword)
+		 (const all)))
+
+(defcustom erc-pal-highlight-type 'nick
+  "*Determines how to highlight messages by pals.
+See `erc-pals'.
+
+The following values are allowed:
+
+    nil   - do not highlight the message at all
+    'nick - highlight pal's nickname only
+    'all  - highlight the entire message from pal
+
+Any other value disables pal highlighting altogether."
+  :group 'erc-match
+  :type '(choice (const nil)
+		 (const nick)
+		 (const all)))
+
+(defcustom erc-fool-highlight-type 'nick
+  "*Determines how to highlight messages by fools.
+See `erc-fools'.
+
+The following values are allowed:
+
+    nil   - do not highlight the message at all
+    'nick - highlight fool's nickname only
+    'all  - highlight the entire message from fool
+
+Any other value disables fool highlighting altogether."
+  :group 'erc-match
+  :type '(choice (const nil)
+		 (const nick)
+		 (const all)))
+
+(defcustom erc-keyword-highlight-type 'keyword
+  "*Determines how to highlight messages containing keywords.
+See variable `erc-keywords'.
+
+The following values are allowed:
+
+    'keyword - highlight keyword only
+    'all     - highlight the entire message containing keyword
+
+Any other value disables keyword highlighting altogether."
+  :group 'erc-match
+  :type '(choice (const nil)
+		 (const keyword)
+		 (const all)))
+
+(defcustom erc-dangerous-host-highlight-type 'nick
+  "*Determines how to highlight messages by nicks from dangerous-hosts.
+See `erc-dangerous-hosts'.
+
+The following values are allowed:
+
+    'nick - highlight nick from dangerous-host only
+    'all  - highlight the entire message from dangerous-host
+
+Any other value disables dangerous-host highlighting altogether."
+  :group 'erc-match
+  :type '(choice (const nil)
+		 (const nick)
+		 (const all)))
+
+
+(defcustom erc-log-matches-types-alist '((keyword . "ERC Keywords"))
+  "Alist telling ERC where to log which match types.
+Valid match type keys are:
+- keyword
+- pal
+- dangerous-host
+- fool
+- current-nick
+
+The other element of each cons pair in this list is the buffer name to
+use for the logged message."
+  :group 'erc-match
+  :type '(repeat (cons (choice :tag "Key"
+			       (const keyword)
+			       (const pal)
+			       (const dangerous-host)
+			       (const fool)
+			       (const current-nick))
+		       (string :tag "Buffer name"))))
+
+(defcustom erc-log-matches-flag 'away
+  "Flag specifying when matched message logging should happen.
+When nil, don't log any matched messages.
+When t, log messages.
+When 'away, log messages only when away."
+  :group 'erc-match
+  :type '(choice (const nil)
+		 (const away)
+		 (const t)))
+
+(defcustom erc-log-match-format "%t<%n:%c> %m"
+  "Format for matched Messages.
+This variable specifies how messages in the corresponding log buffers will
+be formatted. The various format specs are:
+
+%t Timestamp (uses `erc-timestamp-format' if non-nil or \"[%Y-%m-%d %H:%M] \")
+%n Nickname of sender
+%u Nickname!user@host of sender
+%c Channel in which this was received
+%m Message"
+  :group 'erc-match
+  :type 'string)
+
+(defcustom erc-beep-match-types '(current-nick)
+  "Types of matches to beep for when a match occurs.
+The function `erc-beep-on-match' needs to be added to `erc-text-matched-hook'
+for beeping to work."
+  :group 'erc-match
+  :type '(choice (repeat :tag "Beep on match" (choice
+					       (const current-nick)
+					       (const keyword)
+					       (const pal)
+					       (const dangerous-host)
+					       (const fool)))
+		 (const :tag "Don't beep" nil)))
+
+(defcustom erc-text-matched-hook '(erc-log-matches)
+  "Hook run when text matches a given match-type.
+Functions in this hook are passed as arguments:
+\(match-type nick!user@host message) where MATCH-TYPE is a symbol of:
+current-nick, keyword, pal, dangerous-host, fool"
+  :options '(erc-log-matches erc-hide-fools erc-beep-on-match)
+  :group 'erc-match
+  :type 'hook)
+
+;; Internal variables:
+
+;; This is exactly the same as erc-button-syntax-table.  Should we
+;; just put it in erc.el
+(defvar erc-match-syntax-table
+  (let ((table (make-syntax-table)))
+    (modify-syntax-entry ?\( "w" table)
+    (modify-syntax-entry ?\) "w" table)
+    (modify-syntax-entry ?\[ "w" table)
+    (modify-syntax-entry ?\] "w" table)
+    (modify-syntax-entry ?\{ "w" table)
+    (modify-syntax-entry ?\} "w" table)
+    (modify-syntax-entry ?` "w" table)
+    (modify-syntax-entry ?' "w" table)
+    (modify-syntax-entry ?^ "w" table)
+    (modify-syntax-entry ?- "w" table)
+    (modify-syntax-entry ?_ "w" table)
+    (modify-syntax-entry ?| "w" table)
+    (modify-syntax-entry ?\\ "w" table)
+    table)
+  "Syntax table used when highlighting messages.
+This syntax table should make all the legal nick characters word
+constituents.")
+
+;; Faces:
+
+(defface erc-current-nick-face '((t (:bold t :foreground "DarkTurquoise")))
+  "ERC face for occurrences of your current nickname."
+  :group 'erc-faces)
+
+(defface erc-dangerous-host-face '((t (:foreground "red")))
+  "ERC face for people on dangerous hosts.
+See `erc-dangerous-hosts'."
+  :group 'erc-faces)
+
+(defface erc-pal-face '((t (:bold t :foreground "Magenta")))
+  "ERC face for your pals.
+See `erc-pals'."
+  :group 'erc-faces)
+
+(defface erc-fool-face '((t (:foreground "dim gray")))
+  "ERC face for fools on the channel.
+See `erc-fools'."
+  :group 'erc-faces)
+
+(defface erc-keyword-face '((t (:bold t :foreground "pale green")))
+  "ERC face for your keywords.
+Note that this is the default face to use if
+`erc-keywords' does not specify another."
+  :group 'erc-faces)
+
+;; Functions:
+
+(defun erc-add-entry-to-list (list prompt &optional completions)
+  "Add an entry interactively to a list.
+LIST must be passed as a symbol
+The query happens using PROMPT.
+Completion is performed on the optional alist COMPLETIONS."
+  (let ((entry (completing-read
+		prompt
+		completions
+		(lambda (x)
+		  (not (erc-member-ignore-case (car x) (symbol-value list)))))))
+    (if (erc-member-ignore-case entry (symbol-value list))
+	(error (format "\"%s\" is already on the list" entry))
+      (set list (cons entry (symbol-value list))))))
+
+(defun erc-remove-entry-from-list (list prompt)
+  "Remove an entry interactively from a list.
+LIST must be passed as a symbol.
+The elements of LIST can be strings, or cons cells where the
+car is the string."
+  (let* ((alist (mapcar (lambda (x)
+			  (if (listp x)
+			      x
+			    (list x)))
+			(symbol-value list)))
+	 (entry (completing-read
+		 prompt
+		 alist
+		 nil
+		 t)))
+    (if (erc-member-ignore-case entry (symbol-value list))
+	;; plain string
+	(set list (delete entry (symbol-value list)))
+      ;; cons cell
+      (set list (delete (assoc entry (symbol-value list))
+			(symbol-value list))))))
+
+;;;###autoload
+(defun erc-add-pal ()
+  "Add pal interactively to `erc-pals'."
+  (interactive)
+  (erc-add-entry-to-list 'erc-pals "Add pal: " (erc-get-server-nickname-alist)))
+
+;;;###autoload
+(defun erc-delete-pal ()
+  "Delete pal interactively to `erc-pals'."
+  (interactive)
+  (erc-remove-entry-from-list 'erc-pals "Delete pal: "))
+
+;;;###autoload
+(defun erc-add-fool ()
+  "Add fool interactively to `erc-fools'."
+  (interactive)
+  (erc-add-entry-to-list 'erc-fools "Add fool: "
+			 (erc-get-server-nickname-alist)))
+
+;;;###autoload
+(defun erc-delete-fool ()
+  "Delete fool interactively to `erc-fools'."
+  (interactive)
+  (erc-remove-entry-from-list 'erc-fools "Delete fool: "))
+
+;;;###autoload
+(defun erc-add-keyword ()
+  "Add keyword interactively to `erc-keywords'."
+  (interactive)
+  (erc-add-entry-to-list 'erc-keywords "Add keyword: "))
+
+;;;###autoload
+(defun erc-delete-keyword ()
+  "Delete keyword interactively to `erc-keywords'."
+  (interactive)
+  (erc-remove-entry-from-list 'erc-keywords "Delete keyword: "))
+
+;;;###autoload
+(defun erc-add-dangerous-host ()
+  "Add dangerous-host interactively to `erc-dangerous-hosts'."
+  (interactive)
+  (erc-add-entry-to-list 'erc-dangerous-hosts "Add dangerous-host: "))
+
+;;;###autoload
+(defun erc-delete-dangerous-host ()
+  "Delete dangerous-host interactively to `erc-dangerous-hosts'."
+  (interactive)
+  (erc-remove-entry-from-list 'erc-dangerous-hosts "Delete dangerous-host: "))
+
+(defun erc-match-current-nick-p (nickuserhost msg)
+  "Check whether the current nickname is in MSG.
+NICKUSERHOST will be ignored."
+  (with-syntax-table erc-match-syntax-table
+    (and msg
+	 (string-match (concat "\\b"
+			       (regexp-quote (erc-current-nick))
+			       "\\b")
+		       msg))))
+
+(defun erc-match-pal-p (nickuserhost msg)
+  "Check whether NICKUSERHOST is in `erc-pals'.
+MSG will be ignored."
+  (and nickuserhost
+       (erc-list-match erc-pals nickuserhost)))
+
+(defun erc-match-fool-p (nickuserhost msg)
+  "Check whether NICKUSERHOST is in `erc-fools' or MSG is directed at a fool."
+  (and msg nickuserhost
+       (or (erc-list-match erc-fools nickuserhost)
+	   (erc-match-directed-at-fool-p msg))))
+
+(defun erc-match-keyword-p (nickuserhost msg)
+  "Check whether any keyword of `erc-keywords' matches for MSG.
+NICKUSERHOST will be ignored."
+  (and msg
+       (erc-list-match
+	(mapcar (lambda (x)
+		  (if (listp x)
+		      (car x)
+		    x))
+		erc-keywords)
+	msg)))
+
+(defun erc-match-dangerous-host-p (nickuserhost msg)
+  "Check whether NICKUSERHOST is in `erc-dangerous-hosts'.
+MSG will be ignored."
+  (and nickuserhost
+       (erc-list-match erc-dangerous-hosts nickuserhost)))
+
+(defun erc-match-directed-at-fool-p (msg)
+  "Check whether MSG is directed at a fool.
+In order to do this, every entry in `erc-fools' will be used.
+In any of the following situations, MSG is directed at an entry FOOL:
+
+- MSG starts with \"FOOL: \" or \"FOO, \"
+- MSG contains \", FOOL.\" (actually, \"\\s. FOOL\\s.\")"
+  (let ((fools-beg (mapcar (lambda (entry)
+				 (concat "^" entry "[:,] "))
+			   erc-fools))
+	(fools-end (mapcar (lambda (entry)
+				 (concat "\\s. " entry "\\s."))
+			       erc-fools)))
+    (or (erc-list-match fools-beg msg)
+	(erc-list-match fools-end msg))))
+
+(defun erc-get-parsed-vector (point)
+  "Return the whole parsed vector on POINT."
+  (get-text-property point 'erc-parsed))
+
+(defun erc-get-parsed-vector-nick (vect)
+  "Return nickname in the parsed vector VECT."
+  (let* ((untreated-nick (and vect (erc-response.sender vect)))
+	 (maybe-nick (when untreated-nick
+		       (car (split-string untreated-nick "!")))))
+    (when (and (not (null maybe-nick))
+	       (erc-is-valid-nick-p maybe-nick))
+      untreated-nick)))
+
+(defun erc-get-parsed-vector-type (vect)
+  "Return message type in the parsed vector VECT."
+  (and vect
+       (erc-response.command vect)))
+
+(defun erc-match-message ()
+  "Mark certain keywords in a region.
+Use this defun with `erc-insert-modify-hook'."
+  ;; This needs some refactoring.
+  (goto-char (point-min))
+  (let* ((to-match-nick-dep '("pal" "fool" "dangerous-host"))
+	 (to-match-nick-indep '("keyword" "current-nick"))
+	 (vector (erc-get-parsed-vector (point-min)))
+	 (nickuserhost (erc-get-parsed-vector-nick vector))
+	 (nickname (and nickuserhost
+			(nth 0 (erc-parse-user nickuserhost))))
+	 (old-pt (point))
+	 (nick-beg (and nickname
+			(re-search-forward (regexp-quote nickname)
+					   (point-max) t)
+			(match-beginning 0)))
+	 (nick-end (when nick-beg
+		     (match-end 0)))
+	 (message (buffer-substring (if (and nick-end
+					     (<= (+ 2 nick-end) (point-max)))
+					(+ 2 nick-end)
+				      (point-min))
+				    (point-max))))
+    (when vector
+      (mapc
+       (lambda (match-type)
+	 (goto-char (point-min))
+	 (let* ((match-prefix (concat "erc-" match-type))
+		(match-pred (intern (concat "erc-match-" match-type "-p")))
+		(match-htype (eval (intern (concat match-prefix
+						   "-highlight-type"))))
+		(match-regex (if (string= match-type "current-nick")
+				 (regexp-quote (erc-current-nick))
+			       (eval (intern (concat match-prefix "s")))))
+		(match-face (intern (concat match-prefix "-face"))))
+	   (when (funcall match-pred nickuserhost message)
+	     (cond
+	      ;; Highlight the nick of the message
+	      ((and (eq match-htype 'nick)
+		    nick-end)
+	       (erc-put-text-property
+		nick-beg nick-end
+		'face match-face (current-buffer)))
+	      ;; Highlight the nick of the message, or the current
+	      ;; nick if there's no nick in the message (e.g. /NAMES
+	      ;; output)
+	      ((and (string= match-type "current-nick")
+		    (eq match-htype 'nick-or-keyword))
+	       (if nick-end
+		   (erc-put-text-property
+		    nick-beg nick-end
+		    'face match-face (current-buffer))
+		 (goto-char (+ 2 (or nick-end
+				     (point-min))))
+		 (while (re-search-forward match-regex nil t)
+		   (erc-put-text-property (match-beginning 0) (match-end 0)
+					  'face match-face))))
+	      ;; Highlight the whole message
+	      ((eq match-htype 'all)
+	       (erc-put-text-property
+		(point-min) (point-max)
+		'face match-face (current-buffer)))
+	      ;; Highlight all occurrences of the word to be
+	      ;; highlighted.
+	      ((and (string= match-type "keyword")
+		    (eq match-htype 'keyword))
+	       (mapc (lambda (elt)
+		       (let ((regex elt)
+			     (face match-face))
+			 (when (consp regex)
+			   (setq regex (car elt)
+				 face (cdr elt)))
+			 (goto-char (+ 2 (or nick-end
+					     (point-min))))
+			 (while (re-search-forward regex nil t)
+			   (erc-put-text-property
+			    (match-beginning 0) (match-end 0)
+			    'face face))))
+		     match-regex))
+	      ;; Highlight all occurrences of our nick.
+	      ((and (string= match-type "current-nick")
+		    (eq match-htype 'keyword))
+	       (goto-char (+ 2 (or nick-end
+				   (point-min))))
+	       (while (re-search-forward match-regex nil t)
+		 (erc-put-text-property (match-beginning 0) (match-end 0)
+					'face match-face)))
+	      ;; Else twiddle your thumbs.
+	      (t nil))
+	     (run-hook-with-args
+	      'erc-text-matched-hook
+	      (intern match-type)
+	      (or nickuserhost
+		  (concat "Server:" (erc-get-parsed-vector-type vector)))
+	      message))))
+       (if nickuserhost
+	   (append to-match-nick-dep to-match-nick-indep)
+	 to-match-nick-indep)))))
+
+(defun erc-log-matches (match-type nickuserhost message)
+  "Log matches in a separate buffer, determined by MATCH-TYPE.
+The behaviour of this function is controlled by the variables
+`erc-log-matches-types-alist' and `erc-log-matches-flag'. Specify the
+match types which should be logged in the former, and
+deactivate/activate match logging in the latter. See
+`erc-log-match-format'."
+  (let  ((match-buffer-name (cdr (assq match-type
+				       erc-log-matches-types-alist)))
+	 (nick (nth 0 (erc-parse-user nickuserhost))))
+    (when (and
+	   (or (eq erc-log-matches-flag t)
+	       (and (eq erc-log-matches-flag 'away)
+		    erc-away))
+	   match-buffer-name)
+      (let ((line (format-spec erc-log-match-format
+		   (format-spec-make
+		    ?n nick
+		    ?t (format-time-string
+			(or (and (boundp 'erc-timestamp-format)
+				 erc-timestamp-format)
+			    "[%Y-%m-%d %H:%M] "))
+		    ?c (or (erc-default-target) "")
+		    ?m message
+		    ?u nickuserhost))))
+	(with-current-buffer (erc-log-matches-make-buffer match-buffer-name)
+	  (toggle-read-only -1)
+	  (point-max)
+	  (insert line)
+	  (toggle-read-only 1))))))
+
+(defun erc-log-matches-make-buffer (name)
+  "Create or get a log-matches buffer named NAME and return it."
+  (let* ((buffer-already (get-buffer name))
+	 (buffer (or buffer-already
+		     (get-buffer-create name))))
+    (with-current-buffer buffer
+      (unless buffer-already
+	(insert " == Type \"q\" to dismiss messages ==\n")
+	(erc-view-mode-enter nil (lambda (buffer)
+				   (when (y-or-n-p "Discard messages?")
+				     (kill-buffer buffer)))))
+      buffer)))
+
+(defun erc-log-matches-come-back (proc parsed)
+  "Display a notice that messages were logged while away."
+  (when (and erc-away
+	     (eq erc-log-matches-flag 'away))
+    (mapc
+     (lambda (match-type)
+       (let ((buffer (get-buffer (cdr match-type)))
+	     (buffer-name (cdr match-type)))
+	 (when buffer
+	   (let* ((last-msg-time (erc-emacs-time-to-erc-time
+				  (with-current-buffer buffer
+				    (get-text-property (1- (point-max))
+						       'timestamp))))
+		  (away-time     (erc-emacs-time-to-erc-time erc-away)))
+	     (when (and away-time last-msg-time
+			(erc-time-gt last-msg-time away-time))
+	       (erc-display-message
+		nil 'notice 'active
+		(format "You have logged messages waiting in \"%s\"."
+			buffer-name))
+	       (erc-display-message
+		nil 'notice 'active
+		(format "Type \"C-c C-k %s RET\" to view them."
+			buffer-name)))))))
+     erc-log-matches-types-alist))
+  nil)
+
+; This handler must be run _before_ erc-process-away is.
+(add-hook 'erc-server-305-functions 'erc-log-matches-come-back nil)
+
+(defun erc-go-to-log-matches-buffer ()
+  "Interactively open an erc-log-matches buffer."
+  (interactive)
+  (let ((buffer-name (completing-read "Switch to ERC Log buffer: "
+				      (mapcar (lambda (x)
+						(cons (cdr x) t))
+					      erc-log-matches-types-alist)
+				      (lambda (buffer-cons)
+					(get-buffer (car buffer-cons))))))
+    (switch-to-buffer buffer-name)))
+
+(define-key erc-mode-map "\C-c\C-k" 'erc-go-to-log-matches-buffer)
+
+(defun erc-hide-fools (match-type nickuserhost message)
+ "Hide foolish comments.
+This function should be called from `erc-text-matched-hook'."
+ (when (eq match-type 'fool)
+   (erc-put-text-properties (point-min) (point-max)
+			    '(invisible intangible)
+			    (current-buffer))))
+
+(defun erc-beep-on-match (match-type nickuserhost message)
+  "Beep when text matches.
+This function is meant to be called from `erc-text-matched-hook'."
+  (when (member match-type erc-beep-match-types)
+    (beep)))
+
+(provide 'erc-match)
+
+;;; erc-match.el ends here
+;;
+;; Local Variables:
+;; indent-tabs-mode: t
+;; tab-width: 8
+;; End:
+
+;; arch-tag: 1f1f595e-abcc-4b0b-83db-598a1d3f0f82
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lisp/erc/erc-menu.el	Wed Feb 01 10:07:17 2006 +0000
@@ -0,0 +1,121 @@
+;; erc-menu.el -- Menu-bar definitions for ERC
+
+;; Copyright (C) 2001, 2002, 2004, 2005 Free Software Foundation, Inc.
+
+;; Author: Mario Lang <mlang@delysid.org>
+;; Keywords: comm, processes, menu
+;; URL: http://www.emacswiki.org/cgi-bin/wiki.pl?ErcMenu
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
+
+;;; Commentary:
+
+;; Loading this file defines a menu for ERC.
+
+;;; Code:
+
+(require 'easymenu)
+
+(defvar erc-menu-definition
+  (list "IRC"
+	["Connect to server..." erc-select t]
+	["Disconnect from server..." erc-quit-server erc-server-connected]
+	"-"
+	["List channels..." erc-cmd-LIST
+	 (and erc-server-connected (fboundp 'erc-cmd-LIST))]
+	["Join channel..." erc-join-channel erc-server-connected]
+	["Start a query..." erc-cmd-QUERY erc-server-connected]
+	"-"
+	["List users in channel" erc-channel-names erc-channel-users]
+	["List channel operators" erc-cmd-OPS erc-channel-users]
+	["Input action..." erc-input-action (erc-default-target)]
+	["Set topic..." erc-set-topic
+	 (and (and (erc-default-target) (not (erc-query-buffer-p)))
+	      (or (not (member "t" erc-channel-modes))
+		  (erc-channel-user-op-p (erc-current-nick))))]
+	(list "Channel modes"
+	      ["Change mode..." erc-insert-mode-command
+	       (erc-channel-user-op-p (erc-current-nick))]
+	      ["No external send" (erc-toggle-channel-mode "n")
+	       :active (erc-channel-user-op-p (erc-current-nick))
+	       :style toggle :selected (member "n" erc-channel-modes)]
+	      ["Topic set by channel operator" (erc-toggle-channel-mode "t")
+	       :style toggle :selected (member "t" erc-channel-modes)
+	       :active (erc-channel-user-op-p (erc-current-nick))]
+	      ["Invite only" (erc-toggle-channel-mode "i")
+	       :style toggle :selected (member "i" erc-channel-modes)
+	       :active (erc-channel-user-op-p (erc-current-nick))]
+	      ["Private" (erc-toggle-channel-mode "p")
+	       :style toggle :selected (member "p" erc-channel-modes)
+	       :active (erc-channel-user-op-p (erc-current-nick))]
+	      ["Secret" (erc-toggle-channel-mode "s")
+	       :style toggle :selected (member "s" erc-channel-modes)
+	       :active (erc-channel-user-op-p (erc-current-nick))]
+	      ["Moderated" (erc-toggle-channel-mode "m")
+	       :style toggle :selected (member "m" erc-channel-modes)
+	       :active (erc-channel-user-op-p (erc-current-nick))]
+	      ["Set a limit..." erc-set-channel-limit
+	       (erc-channel-user-op-p (erc-current-nick))]
+	      ["Set a key..." erc-set-channel-key
+	       (erc-channel-user-op-p (erc-current-nick))])
+	["Leave this channel..." erc-part-from-channel erc-channel-users]
+	"-"
+	(list "Pals, fools and other keywords"
+	      ["Add pal..." erc-add-pal]
+	      ["Delete pal..." erc-delete-pal]
+	      ["Add fool..." erc-add-fool]
+	      ["Delete fool..." erc-delete-fool]
+	      ["Add keyword..." erc-add-keyword]
+	      ["Delete keyword..." erc-delete-keyword]
+	      ["Add dangerous host..." erc-add-dangerous-host]
+	      ["Delete dangerous host..." erc-delete-dangerous-host])
+	"-"
+	(list "IRC services"
+	      ["Identify to NickServ..." erc-nickserv-identify
+	       (and erc-server-connected (functionp 'erc-nickserv-identify))])
+	"-"
+	["Save buffer in log" erc-save-buffer-in-logs
+	 (fboundp 'erc-save-buffer-in-logs)]
+	["Truncate buffer" erc-truncate-buffer (fboundp 'erc-truncate-buffer)]
+	"-"
+	["Customize ERC" (customize-group 'erc) t]
+	["Enable/Disable ERC Modules" (customize-variable 'erc-modules) t]
+	["Show ERC version" erc-version t])
+  "ERC menu definition.")
+
+;; `erc-mode-map' must be defined before doing this
+(eval-after-load "erc"
+  '(progn
+     (easy-menu-define erc-menu erc-mode-map "ERC menu" erc-menu-definition)
+     (easy-menu-add erc-menu erc-mode-map)
+
+     ;; for some reason the menu isn't automatically added to the menu bar
+     (when (featurep 'xemacs)
+       (add-hook 'erc-mode-hook
+		 (lambda () (easy-menu-add erc-menu erc-mode-map))))))
+
+(provide 'erc-menu)
+
+;;; erc-menu.el ends here
+;;
+;; Local Variables:
+;; indent-tabs-mode: t
+;; tab-width: 8
+;; End:
+
+;; arch-tag: 671219f2-b082-4753-a185-1d0c7e0c05bd
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lisp/erc/erc-nets.el	Wed Feb 01 10:07:17 2006 +0000
@@ -0,0 +1,861 @@
+;;; erc-nets.el --- IRC networks
+
+;; Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc.
+
+;; Author: Mario Lang <mlang@lexx.delysid.org>
+;; Keywords: comm
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
+
+;;; Commentary:
+
+;; This file deals with IRC networks.
+;;
+;; Usage:
+;;
+;; Put into your .emacs:
+;;
+;; (require 'erc-nets)
+;;
+;; M-x erc-server-select provides an alternative way to connect to servers by
+;; choosing networks.
+;; You can use (eq (erc-network) 'Network) if you'd like to set variables or do
+;; certain actions according to which network you're connected to.
+;; If a network you use is not listed in `erc-networks-alist', you can put
+;; (add-to-list 'erc-networks-alist '(Network "irc.server-name.net")) in your
+;; config file.
+
+;;; Code:
+
+(require 'erc)
+(eval-when-compile (require 'cl))
+
+;; Variables
+
+(defgroup erc-networks nil
+  "IRC Networks"
+  :group 'erc)
+
+(defcustom erc-server-alist
+'(("4-irc: Random server" 4-irc "4-irc.com" 6667)
+  ("A5KNet: Random server" A5KNet "irc.a5knet.com" ((6660 6669)))
+  ("AbleNet: Random server" AbleNet "irc.ablenet.org" 6667)
+  ("Accessirc: Random server" Accessirc "irc.accessirc.net" 6667)
+  ("Acestar: Random server" Acestar "irc.acestar.org" 6667)
+  ("Action-IRC: Random server" Action-IRC "irc.action-irc.net" ((6660 6669)))
+  ("AfterNET: Random server" AfterNET "irc.afternet.org" 6667)
+  ("Alternativenet: Random server" Alternativenet "irc.altnet.org" 6667)
+  ("AmigaNet: Random server" AmigaNet "irc.amiganet.org" 6667)
+  ("AngelEyez: Random server" AngelEyez "irc.angeleyez.net" ((6666 7000)))
+  ("AnotherNet: Random server" Anothernet "irc.another.net" (6667 7000 ))
+  ("ArabChat: Random server" ArabChat "irc.arabchat.org" ((6660 6667)))
+  ("AsiaTalk: Random server" AsiaTalk "irc.asiatalk.org" ((6667 6669) 7000 ))
+  ("AstroLink: Random server" AstroLink "irc.astrolink.org" ((6660 6667)))
+  ("Asylumnet: Random server" Asylumnet "irc.asylum-net.org" ((6661 6669) 7000 7777 ))
+  ("Austnet: Random AU server" Austnet "au.austnet.org" 6667)
+  ("Austnet: Random NZ server" Austnet "nz.austnet.org" 6667)
+  ("Austnet: Random SG server" Austnet "sg.austnet.org" 6667)
+  ("Austnet: Random US server" Austnet "us.austnet.org" 6667)
+  ("AwesomeChat: Random server" AwesomeChat "irc.awesomechat.net" ((6661 6669)))
+  ("Awesomechristians: Random server" Awesomechristians "irc.awesomechristians.com" 7000)
+  ("Axenet: Random server" Axenet "irc.axenet.org" ((6660 6667)))
+  ("BeyondIRC: Random server" Beyondirc "irc.beyondirc.net" ((6660 6669)))
+  ("BGIRC: Random server" BGIRC "irc.bulgaria.org" ((6666 6669) 7000 ))
+  ("Blabbernet: Random server" Blabbernet "irc.blabber.net" (6667 7000 ))
+  ("Blitzed: Random server" Blitzed "irc.blitzed.org" (6667 7000 ))
+  ("Brasirc: Random server" Brasirc "irc.brasirc.net" ((6666 6667)))
+  ("Brasirc: BR, PA, Belem" Brasirc "irc.libnet.com.br" ((6666 6668) 7777 8002 ))
+  ("BRASnet: Random European server" BRASnet "eu.brasnet.org" ((6665 6669)))
+  ("BRASnet: Random US server" BRASnet "us.brasnet.org" ((6665 6669)))
+  ("BubbleNet: Random server" BubbleNet "irc.bubblenet.org" ((6667 6669)))
+  ("CCnet: Random server" CCnet "irc.cchat.net" (6667 7000 ))
+  ("CCnet: US, TX, Dallas" CCnet "irc2.cchat.net" (6667 7000 ))
+  ("Chat-Net: Random server" Chat-Net "irc.chat-net.org" 6667)
+  ("Chat-Solutions: Random server" Chat-Solutions "irc.chat-solutions.org" 6667)
+  ("Chatcafe: Random server" Chatcafe "irc.chatcafe.net" 6667)
+  ("Chatchannel: Random server" Chatchannel "irc.chatchannel.org" ((6666 6669) 7000 ))
+  ("ChatCircuit: Random server" ChatCircuit "irc.chatcircuit.com" 6668)
+  ("Chatlink: Random server" Chatlink "irc.chatlink.org" 6667)
+  ("Chatnet: Random AU server" Chatnet "au.chatnet.org" 6667)
+  ("Chatnet: Random EU server" Chatnet "eu.chatnet.org" 6667)
+  ("Chatnet: Random US server" Chatnet "us.chatnet.org" 6667)
+  ("ChatNut: Random server" ChatNut "irc.chatnut.net" (6667 7000 ))
+  ("Chatpinoy: Random server" Chatpinoy "irc.chatpinoy.com" 6667)
+  ("ChatPR: Random server" ChatPR "irc.chatpr.org" 6667)
+  ("Chatroom: Random server" Chatroom "irc.chatroom.org" 6667)
+  ("Chatster: Random server" Chatster "irc.chatster.org" 6667)
+  ("ChatX: Random server" ChatX "irc.chatx.net" 6667)
+  ("China263: Random server" China263 "irc.263.net" 6667)
+  ("Cineplex1: Random server" Cineplex1 "irc.cineplex1.com" ((6666 6668)))
+  ("CNN: CNN News discussions" CNN "chat.cnn.com" ((6667 6669) 7000 ))
+  ("CobraNet: Random server" CobraNet "irc.cobra.net" 6667)
+  ("Coolchat: Random server" Coolchat "irc.coolchat.net" 6667)
+  ("Criten: Random server" Criten "irc.criten.net" 6667)
+  ("Cyberchat: Random server" Cyberchat "irc.cyberchat.org" (6667 6668 ))
+  ("CyGanet: Random server" CyGanet "irc.cyga.net" 6667)
+  ("DALnet: AS, MY, Coins" DALnet "coins.dal.net" ((6663 6668) 7000 ))
+  ("DALnet: CA, ON, Sodre" DALnet "sodre.on.ca.dal.net" ((6661 6669) 7000 ))
+  ("DALnet: EU, DE, Nexgo" DALnet "nexgo.de.eu.dal.net" ((6664 6669) 7000 ))
+  ("DALnet: EU, NO, Powertech" DALnet "powertech.no.eu.dal.net" ((6666 6667) 7000 ))
+  ("DALnet: EU, SE, Borg" DALnet "borg.se.eu.dal.net" (6667 7000 ))
+  ("DALnet: EU, SE, Ced" DALnet "ced.se.eu.dal.net" (6667 7000 ))
+  ("DALnet: US, GA, Astro" DALnet "astro.ga.us.dal.net" ((6661 6669) 7000 ))
+  ("DALnet: US, GA, Dragons" DALnet "dragons.ga.us.dal.net" ((6661 6669) 7000 ))
+  ("DALnet: US, GA, Elysium" DALnet "elysium.ga.us.dal.net" ((6661 6669) 7000 ))
+  ("DALnet: US, MA, Twisted" DALnet "twisted.ma.us.dal.net" ((6660 6669) 7001 7002 ))
+  ("DALnet: US, MO, Global" DALnet "global.mo.us.dal.net" ((6661 6669) 7000 ))
+  ("DALnet: US, NJ, Liberty" DALnet "liberty.nj.us.dal.net" ((6662 6669) 7000 ))
+  ("DALnet: US, VA, Wombat" DALnet "wombat.va.us.dal.net" ((6661 6669) 7000 ))
+  ("DALnet: Random EU server" DALnet "irc.eu.dal.net" 6667)
+  ("DALnet: Random US server" DALnet "irc.dal.net" ((6660 6667)))
+  ("Dark-Tou-Net: Random server" Dark-Tou-Net "irc.d-t-net.de" 6667)
+  ("Darkfire: Random server" Darkfire "irc.darkfire.net" (6667 7000 8000 ))
+  ("DarkMyst: Random server" DarkMyst "irc.darkmyst.org" 6667)
+  ("Darkserv: Random server" Darkserv "irc.darkserv.net" 6667)
+  ("Darksystem: Random server" Darksystem "irc.darksystem.com" 6667)
+  ("Darktree: Random server" Darktree "irc.darktree.net" 6667)
+  ("DayNet: Random server" DayNet "irc.daynet.org" 6667)
+  ("Deepspace: Disability network" Deepspace "irc.deepspace.org" 6667)
+  ("Different: Random server" Different "irc.different.net" 6667)
+  ("Digarix: Random server" Digarix "irc.digarix.net" 6667)
+  ("Digatech: Random server" Digatech "irc.digatech.net" 6667)
+  ("Digital-Base: Random server" Digital-Base "irc.digital-base.net" ((6660 7000)))
+  ("Digitalirc: Random server" Digitalirc "irc.digitalirc.net" 6667)
+  ("Discussioni: Random server" Discussioni "irc.discussioni.org" ((6666 6669)))
+  ("DorukNet: TR, Istanbul" DorukNet "irc.doruk.net.tr" ((6660 6669) 7000 8888 ))
+  ("Dreamcast: Random server" Dreamcast "irc0.dreamcast.com" 6667)
+  ("DWChat: Random server" DWChat "irc.dwchat.net" 6667)
+  ("Dynastynet: Random server" Dynastynet "irc.dynastynet.net" 6667)
+  ("EFnet: CA, AB, Edmonton (arcti)" EFnet "irc.arcti.ca" 6667)
+  ("EFnet: CA, AB, Edmonton (mpls)" EFnet "irc.mpls.ca" ((6660 6669)))
+  ("EFnet: CA, ON, Toronto" EFnet "irc2.magic.ca" 6667)
+  ("EFnet: CA, QB, Montreal" EFnet "irc.qeast.net" 6667)
+  ("EFnet: EU, DK, Aarhus" EFnet "irc.inet.tele.dk" 6667)
+  ("EFnet: EU, FI, Helsinki" EFnet "efnet.cs.hut.fi" 6667)
+  ("EFnet: EU, FR, Paris" EFnet "irc.isdnet.fr" ((6667 6669)))
+  ("EFnet: EU, NL, Amsterdam" EFnet "efnet.vuurwerk.nl" 6667)
+  ("EFnet: EU, NO, Homelien" EFnet "irc.homelien.no" (5190 (6666 6667) (7000 7001) ))
+  ("EFnet: EU, NO, Oslo" EFnet "irc.daxnet.no" ((6666 7000)))
+  ("EFnet: EU, PL, Warszawa" EFnet "irc.efnet.pl" 6667)
+  ("EFnet: EU, RU, Moscow" EFnet "irc.rt.ru" ((6661 6669)))
+  ("EFnet: EU, SE, Dalarna" EFnet "irc.du.se" ((6666 6669)))
+  ("EFnet: EU, SE, Gothenberg" EFnet "irc.hemmet.chalmers.se" ((6666 7000)))
+  ("EFnet: EU, SE, Sweden" EFnet "irc.light.se" 6667)
+  ("EFnet: EU, UK, London (carrier)" EFnet "irc.carrier1.net.uk" ((6666 6669)))
+  ("EFnet: EU, UK, London (demon)" EFnet "efnet.demon.co.uk" ((6665 6669)))
+  ("EFnet: ME, IL, Inter" EFnet "irc.inter.net.il" ((6665 6669)))
+  ("EFnet: US, AZ, Phoenix" EFnet "irc.easynews.com" (6660 (6665 6667) 7000 ))
+  ("EFnet: US, CA, San Jose" EFnet "irc.concentric.net" ((6665 6668)))
+  ("EFnet: US, CA, San Luis Obispo" EFnet "irc.prison.net" ((6666 6667)))
+  ("EFnet: US, GA, Atlanta" EFnet "irc.mindspring.com" ((6660 6669)))
+  ("EFnet: US, MI, Ann Arbor" EFnet "irc.umich.edu" 6667)
+  ("EFnet: US, MN, Twin Cities" EFnet "irc.umn.edu" ((6665 6669)))
+  ("EFnet: US, NY, Mineola" EFnet "irc.lightning.net" ((6665 7000)))
+  ("EFnet: US, NY, New York (east)" EFnet "irc.east.gblx.net" 6667)
+  ("EFnet: US, NY, New York (flamed)" EFnet "irc.flamed.net" ((6665 6669)))
+  ("EFnet: US, TX, Houston" EFnet "ircd.lagged.org" ((6660 6669)))
+  ("EFnet: US, VA, Ashburn" EFnet "irc.secsup.uu.net" ((6665 6669) 8080 ))
+  ("EFnet: Random AU server" EFnet "au.rr.efnet.net" 6667)
+  ("EFnet: Random CA server" EFnet "ca.rr.efnet.net" 6667)
+  ("EFnet: Random EU server" EFnet "eu.rr.efnet.net" 6667)
+  ("EFnet: Random US server" EFnet "us.rr.efnet.net" 6667)
+  ("EgyptianIRC: Random server" EgyptianIRC "irc.egyptianirc.net" ((6667 6669)))
+  ("Eircnet: Random server" Eircnet "irc.eircnet.org" ((6660 6669) 7000 ))
+  ("Eleethal: Random server" Eleethal "irc.eleethal.com" ((6660 6669) 7000 ))
+  ("EntertheGame: Random server" EntertheGame "irc.enterthegame.com" ((6667 6669)))
+  ("EpiKnet: Random server" EpiKnet "irc.epiknet.org" ((6660 6669) 7000 7001 ))
+  ("EsperNet: Random server" EsperNet "irc.esper.net" (5555 (6667 6669) ))
+  ("Esprit: Random server" Esprit "irc.esprit.net" 6667)
+  ("euIRC: Random server" euIRC "irc.euirc.net" ((6665 6669)))
+  ("Evilzinc: Random server" Evilzinc "irc.evilzinc.net" ((6660 6669) 7000 8000 ))
+  ("ExodusIRC: Random server" ExodusIRC "irc.exodusirc.net" ((6660 6669)))
+  ("FDFnet: Random server" FDFnet "irc.fdfnet.net" ((6666 6668) 9999 ))
+  ("FEFnet: Random server" FEFnet "irc.fef.net" 6667)
+  ("Financialchat: Random server" Financialchat "irc.financialchat.com" ((6667 6669) 7000 ))
+  ("Forestnet: Random server" Forestnet "irc.forestnet.org" (6667 7000 ))
+  ("ForeverChat: Random server" ForeverChat "irc.foreverchat.net" ((6660 6669) 7000 ))
+  ("Fraggers: Random server" Fraggers "irc.fraggers.co.uk" ((6661 6669) (7000 7001) ))
+  ("FreedomChat: Random server" FreedomChat "chat.freedomchat.net" 6667)
+  ("FreedomIRC: Random server" FreedomIRC "irc.freedomirc.net" 6667)
+  ("Freenode: Random server" freenode "irc.freenode.net" 6667)
+  ("Freenode: Random EU server" freenode "irc.eu.freenode.net" 6667)
+  ("Freenode: Random US server" freenode "irc.us.freenode.net" 6667)
+  ("FunNet: Random server" FunNet "irc.funnet.org" 6667)
+  ("Galaxynet: Random server" GalaxyNet "irc.galaxynet.org" ((6662 6668) 7000 ))
+  ("Galaxynet: AU, NZ, Auckland" GalaxyNet "auckland.nz.galaxynet.org" ((6661 6669)))
+  ("Galaxynet: EU, BE, Online" GalaxyNet "online.be.galaxynet.org" ((6661 6669)))
+  ("Galaxynet: US, FL, Florida" GalaxyNet "gymnet.us.galaxynet.org" ((6661 6669)))
+  ("Gamesnet: Random east US server" Gamesnet "east.gamesnet.net" 6667)
+  ("Gamesnet: Random west US server" Gamesnet "west.gamesnet.net" 6667)
+  ("GammaForce: Random server" GammaForce "irc.gammaforce.org" ((6660 6669) 7000 ))
+  ("GIKInet: Random server" GIKInet "irc.giki.edu.pk" 6667)
+  ("GizNet: Random server" GizNet "irc.giznet.org" ((6666 6669) 7000 ))
+  ("Globalchat: Random server" Globalchat "irc.globalchat.org" 6667)
+  ("GlobIRC: Random server" GlobIRC "irc.globirc.net" ((6666 6668) 9999 ))
+  ("Goldchat: Random server" Goldchat "irc.goldchat.nl" ((6660 6669) 7000 ))
+  ("Goodchatting: Random server" Goodchatting "irc.goodchatting.com" ((6661 6669) 7000 ))
+  ("GravityLords: Random server" GravityLords "irc.gravitylords.net" 6667)
+  ("Grnet: Random EU server" GRnet "gr.irc.gr" (6667 7000 ))
+  ("Grnet: Random server" GRnet "srv.irc.gr" (6667 7000 ))
+  ("Grnet: Random US server" GRnet "us.irc.gr" (6667 7000 ))
+  ("GulfChat: Random server" GulfChat "irc.gulfchat.net" ((6660 6669)))
+  ("HabberNet: Random server" HabberNet "irc.habber.net" 6667)
+  ("HanIRC: Random server" HanIRC "irc.hanirc.org" 6667)
+  ("Hellenicnet: Random server" Hellenicnet "irc.mirc.gr" (6667 7000 ))
+  ("IceNet: Random server" IceNet "irc.icenet.org.za" 6667)
+  ("ICQnet: Random server" ICQnet "irc.icq.com" 6667)
+  ("Infatech: Random server" Infatech "irc.infatech.net" ((6660 6669)))
+  ("Infinity: Random server" Infinity "irc.infinity-irc.org" 6667)
+  ("Infomatrix: Random server" Infomatrix "irc.infomatrix.net" 6667)
+  ("Inside3D: Random server" Inside3D "irc.inside3d.net" ((6661 6669)))
+  ("InterlinkChat: Random server" InterlinkChat "irc.interlinkchat.net" ((6660 6669) 7000 ))
+  ("IRC-Chile: Random server" IRC-Chile "irc.cl" 6667)
+  ("IRC-Hispano: Random server" IRC-Hispano "irc.irc-hispano.org" 6667)
+  ("IRCchat: Random server" IRCchat "irc.ircchat.tk" 6667)
+  ("IRCGate: Random server" IRCGate "irc.ircgate.net" ((6667 6669)))
+  ("IRCGeeks: Random server" IRCGeeks "irc.ircgeeks.org" ((6660 6669)))
+  ("IRChat: Random server" IRChat "irc.irchat.net" ((6660 6669)))
+  ("IrcLordz: Random server" IrcLordz "irc.irclordz.com" 6667)
+  ("IrcMalta: Random server" IrcMalta "irc.ircmalta.org" ((6660 6667)))
+  ("IRCnet: EU, FR, Random" IRCnet "irc.fr.ircnet.net" 6667)
+  ("IRCnet: EU, IT, Random" IRCnet "irc.ircd.it" ((6665 6669)))
+  ("IRCnet: AS, IL, Haifa" IRCnet "ircnet.netvision.net.il" ((6661 6668)))
+  ("IRCnet: AS, JP, Tokyo" IRCnet "irc.tokyo.wide.ad.jp" 6667)
+  ("IRCnet: AS, TW, Seed" IRCnet "irc.seed.net.tw" 6667)
+  ("IRCnet: EU, AT, Linz" IRCnet "linz.irc.at" ((6666 6668)))
+  ("IRCnet: EU, AT, Wien" IRCnet "vienna.irc.at" ((6666 6669)))
+  ("IRCnet: EU, BE, Brussels" IRCnet "irc.belnet.be" 6667)
+  ("IRCnet: EU, BE, Zaventem" IRCnet "ircnet.wanadoo.be" ((6661 6669)))
+  ("IRCnet: EU, CZ, Prague" IRCnet "irc.felk.cvut.cz" 6667)
+  ("IRCnet: EU, DE, Berlin" IRCnet "irc.fu-berlin.de" ((6665 6669)))
+  ("IRCnet: EU, DE, Dusseldorf" IRCnet "irc.freenet.de" ((6665 6669)))
+  ("IRCnet: EU, DE, Stuttgart" IRCnet "irc.belwue.de" ((6665 6669)))
+  ("IRCnet: EU, DK, Copenhagen" IRCnet "irc.ircnet.dk" 6667)
+  ("IRCnet: EU, EE, Tallinn" IRCnet "irc.estpak.ee" ((6666 6668)))
+  ("IRCnet: EU, FI, Helsinki" IRCnet "irc.cs.hut.fi" 6667)
+  ("IRCnet: EU, GR, Thessaloniki" IRCnet "irc.ee.auth.gr" ((6666 6669)))
+  ("IRCnet: EU, HU, Budapest" IRCnet "irc.elte.hu" 6667)
+  ("IRCnet: EU, IS, Reykjavik (ircnet)" IRCnet "irc.ircnet.is" ((6661 6669)))
+  ("IRCnet: EU, IS, Reykjavik (simnet)" IRCnet "irc.simnet.is" ((6661 6669)))
+  ("IRCnet: EU, IT, Rome" IRCnet "irc.tin.it" ((6665 6669)))
+  ("IRCnet: EU, NL, Amsterdam (nlnet)" IRCnet "irc.nl.uu.net" ((6660 6669)))
+  ("IRCnet: EU, NL, Amsterdam (xs4all)" IRCnet "irc.xs4all.nl" ((6660 6669)))
+  ("IRCnet: EU, NL, Enschede" IRCnet "irc.snt.utwente.nl" ((6660 6669)))
+  ("IRCnet: EU, NL, Nijmegen" IRCnet "irc.sci.kun.nl" ((6660 6669)))
+  ("IRCnet: EU, NO, Oslo" IRCnet "irc.ifi.uio.no" 6667)
+  ("IRCnet: EU, NO, Trondheim" IRCnet "irc.pvv.ntnu.no" 6667)
+  ("IRCnet: EU, PL, Lublin" IRCnet "lublin.irc.pl" ((6666 6668)))
+  ("IRCnet: EU, PL, Warsaw" IRCnet "warszawa.irc.pl" ((6666 6668)))
+  ("IRCnet: EU, RU, Moscow" IRCnet "irc.msu.ru" 6667)
+  ("IRCnet: EU, SE, Lulea" IRCnet "irc.ludd.luth.se" ((6661 6669)))
+  ("IRCnet: EU, UK, London (Demon)" IRCnet "ircnet.demon.co.uk" ((6665 6669)))
+  ("IRCnet: EU, UK, London (Easynet)" IRCnet "ircnet.easynet.co.uk" ((6666 6669)))
+  ("IRCnet: US, NY, New York" IRCnet "irc.stealth.net" ((6660 6669)))
+  ("IRCnet: Random AU server" IRCnet "au.ircnet.org" 6667)
+  ("IRCnet: Random EU server" IRCnet "eu.ircnet.org" ((6665 6668)))
+  ("IRCnet: Random US server" IRCnet "us.ircnet.org" ((6665 6668)))
+  ("IRCSoulZ: Random server" IRCSoulZ "irc.ircsoulz.net" 6667)
+  ("IRCSul: BR, PR, Maringa" IRCSul "irc.wnet.com.br" 6667)
+  ("IrcTalk: Random server" IrcTalk "irc.irctalk.net" ((6660 6669)))
+  ("Irctoo: Random server" Irctoo "irc.irctoo.net" 6667)
+  ("IRCtown: Random server" IRCtown "irc.irctown.net" ((6666 6669) 7000 ))
+  ("IRCworld: Random server" IRCworld "irc.ircworld.org" 6667)
+  ("ircXtreme: Random server" ircXtreme "irc.ircXtreme.net" ((6660 6669)))
+  ("Israelnet: Random server" Israelnet "irc.israel.net" 6667)
+  ("K0wNet: Random server" K0wNet "irc.k0w.net" ((6660 6669)))
+  ("KDFSnet: Random server" KDFSnet "irc.kdfs.net" ((6667 6669)))
+  ("Kemik: Random server" Kemik "irc.kemik.net" 6667)
+  ("Kewl.Org: Random server" Kewl.Org "irc.kewl.org" (6667 7000 ))
+  ("Kickchat: Random server" Kickchat "irc.kickchat.com" ((6660 6669) 7000 ))
+  ("Kidsworld: Random server" KidsWorld "irc.kidsworld.org" ((6666 6669)))
+  ("Knightnet: AF, ZA, Durban" Knightnet "orc.dbn.za.knightnet.net" (6667 5555 ))
+  ("Knightnet: US, CA, Goldengate" Knightnet "goldengate.ca.us.knightnet.net" (6667 5555 ))
+  ("Konfido.Net: Random server" Konfido.Net "irc.konfido.net" 6667)
+  ("KreyNet: Random server" Kreynet "irc.krey.net" 6667)
+  ("Krono: Random server" Krono "irc.krono.net" ((6660 6669) 7000 ))
+  ("Krushnet: Random server" Krushnet "irc.krushnet.org" 6667)
+  ("LagNet: Random server" LagNet "irc.lagnet.org.za" 6667)
+  ("LagNet: AF, ZA, Cape Town" LagNet "reaper.lagnet.org.za" 6667)
+  ("LagNet: AF, ZA, Johannesburg" LagNet "mystery.lagnet.org.za" 6667)
+  ("Librenet: Random server" Librenet "irc.librenet.net" 6667)
+  ("LinkNet: Random server" LinkNet "irc.link-net.org" ((6667 6669)))
+  ("Liquidized: Random server" Liquidized "irc.liquidized.net" (6667 7000 ))
+  ("M-IRC: Random server" M-IRC "irc.m-sys.org" ((6667 6669)))
+  ("MagicStar: Random server" MagicStar "irc.magicstar.net" 6667)
+  ("Mavra: Random server" Mavra "irc.mavra.net" 6667)
+  ("MediaDriven: Random server" MediaDriven "irc.mediadriven.com" ((6667 6669)))
+  ("mIRC-X: Random server" mIRC-X "irc.mircx.com" (6667 7000 ))
+  ("Morat: Random server" Morat "irc.morat.net" 6667)
+  ("MusicCity: Random server" MusicCity "chat.musiccity.com" 6667)
+  ("Mysteria: Random server" Mysteria "irc.mysteria.net" (6667 7000 ))
+  ("Mysterychat: Random server" Mysterychat "irc.mysterychat.net" ((6667 6669)))
+  ("Mystical: Random server" Mystical "irc.mystical.net" (6667 7000 ))
+  ("Narancs: Random server" Narancs "irc.narancs.com" ((6667 6669) 7000 ))
+  ("Net-France: Random server" Net-France "irc.net-france.com" 6667)
+  ("Nevernet: Random server" Nevernet "irc.nevernet.net" 6667)
+  ("Newnet: Random server" Newnet "irc.newnet.net" ((6665 6667)))
+  ("Nexusirc: Random server" Nexusirc "irc.nexusirc.org" 6667)
+  ("Nightstar: Random server" NightStar "irc.nightstar.net" ((6665 6669)))
+  ("NitrousNet: Random server" NitrousNet "irc.nitrousnet.net" 6667)
+  ("Novernet: Random server" Novernet "irc.novernet.com" ((6665 6669) 7000 ))
+  ("Nullrouted: Random server" Nullrouted "irc.nullrouted.org" ((6666 6669) 7000 ))
+  ("NullusNet: Random server" NullusNet "irc.nullus.net" 6667)
+  ("OpChat: Random server" OpChat "irc.opchat.org" ((6667 6669)))
+  ("Othernet: Random server" Othernet "irc.othernet.org" 6667)
+  ("Othernet: US, FL, Miami" Othernet "miami.fl.us.othernet.org" 6667)
+  ("Othernet: US, MO, StLouis" Othernet "stlouis.mo.us.othernet.org" 6667)
+  ("Otherside: Random server" OtherSide "irc.othersideirc.net" 6667)
+  ("Outsiderz: Random server" Outsiderz "irc.outsiderz.com" 6667)
+  ("OzOrg: AU, Perth" OzOrg "iinet.perth.oz.org" 6667)
+  ("Peacefulhaven: Random server" Peacefulhaven "irc.peacefulhaven.net" ((6660 6669) 7000 ))
+  ("PhazedIRC: Random server" PhazedIRC "irc.phazedirc.net" 6667)
+  ("Philchat: Random server" Philchat "irc.philchat.net" 6667)
+  ("phrozN: Random server" phrozN "irc.phrozn.net" 6667)
+  ("PiNet: Random server" PiNet "irc.praetorians.org" ((6665 6669)))
+  ("Pinoycentral: Random server" Pinoycentral "chat.abs-cbn.com" 6667)
+  ("Planetarion: Random server" Planetarion "irc.planetarion.com" 6667)
+  ("POLNet: Random server" POLNet "irc.ircnet.pl" 6667)
+  ("Psionics: CA, PQ, Montreal" Psionics "chat.psionics.net" ((6660 6669)))
+  ("PTirc: Random server" PTirc "irc.ptirc.com.pt" 6667)
+  ("PTlink: Random server" PTlink "irc.ptlink.net" 6667)
+  ("PTnet: Random server" PTnet "irc.ptnet.org" 6667)
+  ("QChat: Random server" QChat "irc.qchat.net" 6667)
+  ("QuakeNet: Random German server" QuakeNet "de.quakenet.org" ((6667 6669)))
+  ("QuakeNet: Random server" QuakeNet "irc.quakenet.eu.org" ((6667 6669)))
+  ("QuakeNet: Random Swedish server" QuakeNet "se.quakenet.org" ((6667 6669)))
+  ("QuakeNet: Random UK server" QuakeNet "uk.quakenet.org" ((6667 6669)))
+  ("QuakeNet: Random US server" QuakeNet "us.quakenet.org" ((6667 6669)))
+  ("Realirc: Random server" Realirc "irc.realirc.org" 6667)
+  ("RealmNET: Random server" RealmNET "irc.realmnet.com" 6667)
+  ("Rebelchat: Random server" Rebelchat "irc.rebelchat.org" 6667)
+  ("Red-Latina: Random server" Red-Latina "irc.red-latina.org" 6667)
+  ("RedLatona: Random server" RedLatona "irc.redlatona.net" (6667 6668 ))
+  ("Relicnet: Random server" Relicnet "irc.relic.net" 6667)
+  ("Rezosup: Random server" Rezosup "irc.rezosup.org" 6667)
+  ("Risanet: Random server" Risanet "irc.risanet.com" ((6667 6669)))
+  ("Rubiks: Random server" Rubiks "irc.rubiks.net" 6667)
+  ("Rusnet: EU, RU, Tomsk" Rusnet "irc.tsk.ru" ((6667 6669) (7770 7775) ))
+  ("Rusnet: EU, RU, Vladivostok" Rusnet "irc.vladivostok.ru" ((6667 6669) (7770 7775) ))
+  ("Rusnet: EU, UA, Kiev" Rusnet "irc.kar.net" ((6667 6669) (7770 7775) ))
+  ("Sandnet: Random server" Sandnet "irc.sandnet.net" ((6660 6669) 7000 ))
+  ("Scunc: Random server" Scunc "irc.scunc.net" 6667)
+  ("SerbianCafe: Random server" SerbianCafe "irc.serbiancafe.ws" ((6665 6669)))
+  ("SexNet: Random server" SexNet "irc.sexnet.org" 6667)
+  ("ShadowFire: Random server" ShadowFire "irc.shadowfire.org" 6667)
+  ("ShadowWorld: Random server" ShadowWorld "irc.shadowworld.net" 6667)
+  ("SkyNet: Random server" SkyNet "irc.bronowski.pl" ((6666 6668)))
+  ("Slashnet: Random server" Slashnet "irc.slashnet.org" 6667)
+  ("SolarStone: Random server" SolarStone "irc.solarstone.net" ((6660 6669)))
+  ("Sorcerynet: Random server" Sorcery "irc.sorcery.net" (6667 7000 9000 ))
+  ("Sorcerynet: EU, SE, Karlskrona" Sorcery "nexus.sorcery.net" (6667 7000 9000 ))
+  ("Sorcerynet: US, CA, Palo Alto" Sorcery "kechara.sorcery.net" (6667 7000 9000 ))
+  ("SourceIRC: Random server" SourceIRC "irc.sourceirc.net" ((6667 6669) 7000 ))
+  ("SpaceTronix: Random server" SpaceTronix "irc.spacetronix.net" ((6660 6669) 7000 ))
+  ("Spirit-Harmony: Random server" Spirit-Harmony "irc.spirit-harmony.com" ((6661 6669)))
+  ("StarChat: Random server" StarChat "irc.starchat.net" ((6667 6669) 7000 ))
+  ("StarEquinox: Random server" StarEquinox "irc.starequinox.net" ((6660 6669)))
+  ("StarLink: Random server" Starlink "irc.starlink.net" ((6660 6669)))
+  ("StarLink-irc: Random server" starlink-irc "irc.starlink-irc.org" 6667)
+  ("StarWars-IRC: Random server" StarWars-IRC "irc.starwars-irc.net" ((6663 6667)))
+  ("Stormdancing: Random server" Stormdancing "irc.stormdancing.net" ((6664 6669) 7000 9000 ))
+  ("Superchat: Random server" Superchat "irc.superchat.org" ((6660 6668)))
+  ("Sysopnet: Random server" Sysopnet "irc.sysopnet.org" ((6666 6668)))
+  ("Telstra: Random server" Telstra "irc.telstra.com" ((6667 6669)))
+  ("TR-net: EU, TR, Ankara" TR-net "irc.dominet.com.tr" 6667)
+  ("TR-net: EU, Tr, Istanbul" TR-net "irc.teklan.com.tr" 6667)
+  ("Tri-net: Random server" Tri-net "irc.tri-net.org" 6667)
+  ("TriLink: Random server" TriLink "irc.ft4u.net" 6667)
+  ("TurkishChat: Random server" TurkishChat "irc.turkishchat.org" ((6660 6669) 7000 ))
+  ("UberNinja: Random server" UberNinja "irc.uberninja.net" ((6667 6669)))
+  ("UICN: Random server" UICN "irc.uicn.net" 6667)
+  ("UltraIRC: Random server" UltraIRC "irc.ultrairc.net" 6667)
+  ("UnderChat: Random server" UnderChat "irc.underchat.it" ((6660 6669) 7000 ))
+  ("Undernet: CA, ON, Toronto" Undernet "toronto.on.ca.undernet.org" ((6661 6669)))
+  ("Undernet: CA, QC, Montreal" Undernet "montreal.qu.ca.undernet.org" ((6660 6669)))
+  ("Undernet: EU, AT, Graz" Undernet "graz.at.eu.undernet.org" ((6661 6669)))
+  ("Undernet: EU, BE, Antwerp" Undernet "flanders.be.eu.undernet.org" ((6660 6669)))
+  ("Undernet: EU, BE, Brussels" Undernet "brussels.be.eu.undernet.org" 6667)
+  ("Undernet: EU, CH, Geneva" Undernet "geneva.ch.eu.undernet.org" ((6660 6669) 7777 8000 ))
+  ("Undernet: EU, FR, Caen" Undernet "caen.fr.eu.undernet.org" ((6666 6669)))
+  ("Undernet: EU, NL, Diemen" Undernet "diemen.nl.eu.undernet.org" ((6660 6669)))
+  ("Undernet: EU, NL, Haarlem" Undernet "haarlem.nl.eu.undernet.org" ((6660 6669)))
+  ("Undernet: EU, NO, Oslo" Undernet "oslo.no.eu.undernet.org" ((6660 6669)))
+  ("Undernet: EU, SE, Stockholm" Undernet "stockholm.se.eu.undernet.org" ((6666 6669)))
+  ("Undernet: EU, UK, Surrey" Undernet "surrey.uk.eu.undernet.org" ((6660 6669)))
+  ("Undernet: US, AZ, Mesa" Undernet "mesa.az.us.undernet.org" ((6665 6667)))
+  ("Undernet: US, CA, San Diego" Undernet "sandiego.ca.us.undernet.org" ((6660 6670)))
+  ("Undernet: US, DC, Washington" Undernet "washington.dc.us.undernet.org" ((6660 6669)))
+  ("Undernet: US, KS, Manhattan" Undernet "manhattan.ks.us.undernet.org" ((6660 6669)))
+  ("Undernet: US, NV, Las Vegas" Undernet "lasvegas.nv.us.undernet.org" ((6660 6669)))
+  ("Undernet: US, TX, Austin" Undernet "austin.tx.us.undernet.org" ((6660 6669)))
+  ("Undernet: US, UT, Saltlake" Undernet "saltlake.ut.us.undernet.org" ((6660 6669)))
+  ("Undernet: US, VA, Arlington" Undernet "arlington.va.us.undernet.org" ((6660 6669)))
+  ("Undernet: US, VA, McLean" Undernet "mclean.va.us.undernet.org" ((6666 6669)))
+  ("Undernet: Random EU server" Undernet "eu.undernet.org" 6667)
+  ("Undernet: Random US server" Undernet "us.undernet.org" 6667)
+  ("UnderZ: Random server" UnderZ "irc.underz.org" ((6667 6668)))
+  ("UniChat: Random server" UniChat "irc.uni-chat.net" 6667)
+  ("UnionLatina: Random server" UnionLatina "irc.unionlatina.org" 6667)
+  ("Univers: Random server" Univers "irc.univers.org" ((6665 6669)))
+  ("UnixR: Random server" UnixR "irc.unixr.net" ((6667 6669)))
+  ("Vidgamechat: Random server" Vidgamechat "irc.vidgamechat.com" 6667)
+  ("VirtuaNet: Random server" VirtuaNet "irc.virtuanet.org" ((6660 6669) 7000 ))
+  ("Vitamina: Random server" Vitamina "irc.vitamina.ca" 6667)
+  ("Voila: Random server" Voila "irc.voila.fr" 6667)
+  ("Wahou: Random server" Wahou "irc.wahou.org" ((6665 6669)))
+  ("Warpednet: Random server" Warpednet "irc.warped.net" 6667)
+  ("Weaklinks: Random server" Weaklinks "irc.weaklinks.net" ((6667 6669)))
+  ("Webnet: Random server" Webnet "irc.webchat.org" ((6667 6669) 7000 ))
+  ("Webnet: US, CA, Santa Clara" Webnet "webmaster.ca.us.webchat.org" ((6661 6669)))
+  ("WinChat: Random server" WinChat "irc.winchat.net" ((6661 6669)))
+  ("WinIRC: Random server" WinIRC "irc.winirc.org" ((6667 6669) 4400 ))
+  ("WorldIRC: Random server" WorldIRC "irc.worldirc.org" ((6660 6667)))
+  ("WyldRyde: Random server" WyldRyde "irc.wyldryde.net" ((6666 6669)))
+  ("XentoniX: Random server" XentoniX "irc.xentonix.net" ((6661 6669)))
+  ("Xevion: Random server" Xevion "irc.xevion.net" (6667 7000 ))
+  ("XNet: Random server" XNet "irc.xnet.org" 6667)
+  ("XWorld: Random server" XWorld "irc.xworld.org" 6667)
+  ("ZAnet Net: Random server" ZAnetNet "irc.zanet.net" 6667)
+  ("ZAnet Org: UK, London" ZAnetOrg "mystic.zanet.org.za" 6667)
+  ("ZiRC: Random server" ZiRC "irc.zirc.org" ((6660 6669)))
+  ("ZUHnet: Random server" ZUHnet "irc.zuh.net" 6667)
+  ("Zurna: Random server" Zurna "irc.zurna.net" 6667))
+  "Alist of irc servers. (NAME NET HOST PORTS) where
+NAME is a name for that server,
+NET is a symbol indicating to which network from `erc-networks-alist' this
+  server corresponds,
+HOST is the servers hostname and
+PORTS is either a number, a list of numbers, or a list of port ranges."
+  :group 'erc-networks
+  :type 'sexp)
+
+(defcustom erc-networks-alist
+  '((4-irc "4-irc.com")
+    (A5KNet "a5knet.com")
+    (AbleNet "ablenet.org")
+    (Accessirc "accessirc.net")
+    (Acestar "acestar.org")
+    (Action-IRC "action-irc.net")
+    (AfterNET "afternet.org")
+    (Alternativenet "altnet.org")
+    (AmigaNet "amiganet.org")
+    (AngelEyez "angeleyez.net")
+    (Anothernet "another.net")
+    (ArabChat "arabchat.org")
+    (AsiaTalk "asiatalk.org")
+    (AstroLink "astrolink.org")
+    (Asylumnet "asylumnet.org")
+    (Austnet "austnet.org")
+    (AwesomeChat "awesomechat.net")
+    (Awesomechristians "awesomechristians.com")
+    (Axenet "axenet.org")
+    (Beyondirc "beyondirc.net")
+    (BGIRC "bulgaria.org")
+    (Blabbernet "blabber.net")
+    (Blitzed "blitzed.org")
+    (BrasIRC "brasirc.net")
+    (BRASnet "brasnet.org")
+    (BubbleNet "bubblenet.org")
+    (CCnet "christian-chat.net")
+    (Chat-Net "chat-net.org")
+    (Chat-Solutions "chat-solutions.org")
+    (Chatcafe "chatcafe.net")
+    (Chatchannel "chatchannel.org")
+    (ChatCircuit "chatcircuit.com")
+    (Chatlink "chatlink.org")
+    (Chatnet "chatnet.org")
+    (ChatNut "chatnut.net")
+    (Chatpinoy "chatpinoy.com")
+    (ChatPR "chatpr.org")
+    (Chatroom "chatroom.org")
+    (Chatster "chatster.org")
+    (ChatX "chatx.net")
+    (China263 "263.net")
+    (Cineplex1 "cineplex1.com")
+    (CNN "cnn.com")
+    (CobraNet "cobra.net")
+    (Coolchat "coolchat.net")
+    (Criten "criten.net")
+    (Cyberchat "cyberchat.org")
+    (CyGanet "cyga.net")
+    (DALnet "dal.net")
+    (Dark-Tou-Net "d-t-net.de")
+    (Darkfire "darkfire.net")
+    (DarkMyst "darkmyst.org")
+    (Darkserv "darkserv.net")
+    (Darksystem "darksystem.com")
+    (Darktree "darktree.net")
+    (DayNet "daynet.org")
+    (Deepspace "deepspace.org")
+    (Different "different.net")
+    (Digarix "digarix.net")
+    (Digatech "digatech.net")
+    (Digital-Base "digital-base.net")
+    (Digitalirc "digitalirc.net")
+    (Discussioni "discussioni.org")
+    (DorukNet "doruk.net.tr")
+    (DWChat "dwchat.net")
+    (Dynastynet "dynastynet.net")
+    (EFnet nil)
+    (EgyptianIRC "egyptianirc.net")
+    (Eircnet "eircnet.org")
+    (Eleethal "eleethal.com")
+    (EntertheGame "enterthegame.com")
+    (EpiKnet "epiknet.org")
+    (EsperNet "esper.net")
+    (Esprit "esprit.net")
+    (euIRC "euirc.net")
+    (Evilzinc "evilzinc.net")
+    (ExodusIRC "exodusirc.net")
+    (FDFnet "fdfnet.net")
+    (FEFnet "fef.net")
+    (Financialchat "financialchat.com")
+    (Forestnet "forestnet.org")
+    (ForeverChat "foreverchat.net")
+    (Fraggers "fraggers.co.uk")
+    (FreedomChat "freedomchat.net")
+    (FreedomIRC "freedomirc.net")
+    (freenode "freenode.net")
+    (FunNet "funnet.org")
+    (GalaxyNet "galaxynet.org")
+    (Gamesnet "gamesnet.net")
+    (GammaForce "gammaforce.org")
+    (GIKInet "giki.edu.pk")
+    (GizNet "giznet.org")
+    (Globalchat "globalchat.org")
+    (GlobIRC "globirc.net")
+    (Goldchat "goldchat.nl")
+    (Goodchatting "goodchatting.com")
+    (GravityLords "gravitylords.net")
+    (GRnet "irc.gr")
+    (GulfChat "gulfchat.net")
+    (HabberNet "habber.net")
+    (HanIRC "hanirc.org")
+    (Hellenicnet "mirc.gr")
+    (IceNet "icenet.org.za")
+    (ICQnet "icq.com")
+    (iip "anon.iip")
+    (Infatech "infatech.net")
+    (Infinity "infinity-irc.org")
+    (Infomatrix "infomatrix.net")
+    (Inside3D "inside3d.net")
+    (InterlinkChat "interlinkchat.net")
+    (IRC-Chile "irc.cl")
+    (IRC-Hispano "irc-hispano.org")
+    (IRCchat "ircchat.tk")
+    (IRCGate "ircgate.net")
+    (IRCGeeks "ircgeeks.org")
+    (IRChat "irchat.net")
+    (IrcLordz "irclordz.com")
+    (IrcMalta "ircmalta.org")
+    (IRCnet nil)
+    (IRCSoulZ "ircsoulz.net")
+    (IRCSul "wnet.com.br")
+    (IrcTalk "irctalk.net")
+    (Irctoo "irctoo.net")
+    (IRCtown "irc.irctown.net")
+    (IRCworld "ircworld.org")
+    (ircXtreme "ircXtreme.net")
+    (Israelnet "israel.net")
+    (K0wNet "k0w.net")
+    (KDFSnet "kdfs.net")
+    (Kemik "kemik.net")
+    (Kewl\.Org "kewl.org")
+    (Kickchat "kickchat.com")
+    (KidsWorld "kidsworld.org")
+    (Knightnet "knightnet.net")
+    (Konfido\.Net "konfido.net")
+    (Kreynet "krey.net")
+    (Krono "krono.net")
+    (Krushnet "krushnet.org")
+    (LagNet "lagnet.org.za")
+    (Librenet "librenet.net")
+    (LinkNet "link-net.org")
+    (Liquidized "liquidized.net")
+    (M-IRC "m-sys.org")
+    (MagicStar "magicstar.net")
+    (Mavra "mavra.net")
+    (MediaDriven "mediadriven.com")
+    (mIRC-X "mircx.com")
+    (Morat "morat.net")
+    (MusicCity "musiccity.com")
+    (Mysteria "mysteria.net")
+    (Mysterychat "mysterychat.net")
+    (Mystical "mystical.net")
+    (Narancs "narancs.com")
+    (Net-France "net-france.com")
+    (Nevernet "nevernet.net")
+    (Newnet "newnet.net")
+    (Nexusirc "nexusirc.org")
+    (NightStar "nightstar.net")
+    (NitrousNet "nitrousnet.net")
+    (Novernet "novernet.com")
+    (Nullrouted "nullrouted.org")
+    (NullusNet "nullus.net")
+    (OpChat "opchat.org")
+    (Openprojects "openprojects.net")
+    (Othernet "othernet.org")
+    (OtherSide "othersideirc.net")
+    (Outsiderz "outsiderz.com")
+    (OzOrg "oz.org")
+    (Peacefulhaven "peacefulhaven.net")
+    (PhazedIRC "phazedirc.net")
+    (Philchat "philchat.net")
+    (phrozN "phrozn.net")
+    (PiNet "praetorians.org")
+    (Pinoycentral "abs-cbn.com")
+    (Planetarion "planetarion.com")
+    (POLNet "ircnet.pl")
+    (Psionics "psionics.net")
+    (PTirc "ptirc.com.pt")
+    (PTlink "ptlink.net")
+    (PTnet "ptnet.org")
+    (QChat "qchat.net")
+    (QuakeNet "quakenet.org")
+    (Realirc "realirc.org")
+    (RealmNET "realmnet.com")
+    (Rebelchat "rebelchat.org")
+    (Red-Latina "red-latina.org")
+    (RedLatona "redlatona.net")
+    (Relicnet "relic.net")
+    (Rezosup "rezosup.org")
+    (Risanet "risanet.com")
+    (Rubiks "rubiks.net")
+    (Rusnet "nil")
+    (Sandnet "sandnet.net")
+    (Scunc "scunc.net")
+    (SerbianCafe "serbiancafe.ws")
+    (SexNet "sexnet.org")
+    (ShadowFire "shadowfire.org")
+    (ShadowWorld "shadowworld.net")
+    (SkyNet "bronowski.pl")
+    (SlashNET "slashnet.org")
+    (SolarStone "solarstone.net")
+    (Sorcery "sorcery.net")
+    (SourceIRC "sourceirc.net")
+    (SpaceTronix "spacetronix.net")
+    (Spirit-Harmony "spirit-harmony.com")
+    (StarChat "starchat.net")
+    (StarEquinox "starequinox.net")
+    (Starlink "starlink.net")
+    (starlink-irc "starlink-irc.org")
+    (StarWars-IRC "starwars-irc.net")
+    (Stormdancing "stormdancing.net")
+    (Superchat "superchat.org")
+    (Sysopnet "sysopnet.org")
+    (Telstra "telstra.com")
+    (TR-net "dominet.com.tr")
+    (Tri-net "tri-net.org")
+    (TriLink "ft4u.net")
+    (TurkishChat "turkishchat.org")
+    (UberNinja "uberninja.net")
+    (UICN "uicn.net")
+    (UltraIRC "ultrairc.net")
+    (UnderChat "underchat.it")
+    (Undernet "undernet.org")
+    (UnderZ "underz.org")
+    (UniChat "irc.uni-chat.net")
+    (UnionLatina "unionlatina.org")
+    (Univers "univers.org")
+    (UnixR "unixr.net")
+    (Vidgamechat "vidgamechat.com")
+    (VirtuaNet "virtuanet.org")
+    (Vitamina "vitamina.ca")
+    (Voila "voila.fr")
+    (Wahou "wf-net.org")
+    (Warpednet "warped.net")
+    (Weaklinks "weaklinks.net")
+    (Webnet "webchat.org")
+    (WinChat "winchat.net")
+    (WinIRC "winirc.org")
+    (WorldIRC "worldirc.org")
+    (WyldRyde "wyldryde.net")
+    (XentoniX "xentonix.net")
+    (Xevion "xevion.net")
+    (XNet "xnet.org")
+    (XWorld "xworld.org")
+    (ZAnetNet "zanet.net")
+    (ZAnetOrg "zanet.org.za")
+    (ZiRC "zirc.org")
+    (ZUHnet "zuh.net")
+    (Zurna "zurna.net"))
+  "Alist of IRC networks. (NET MATCHER) where
+NET is a symbol naming that IRC network and
+MATCHER is used to find a corresponding network to a server while connected to
+  it. If it is regexp, it's used to match against `erc-server-announced-name'.
+  It can also be a function (predicate). Then it is executed with the
+  server buffer as current-buffer."
+  :group 'erc-networks
+  :type '(repeat
+	  (list :tag "Network"
+		(symbol :tag "Network name")
+		(choice :tag "Network's common server ending"
+		 (regexp)
+		 (const :tag "Network has no common server ending" nil)))))
+
+(defvar erc-network nil
+  "The name of the network you are connected to (a symbol).")
+(make-variable-buffer-local 'erc-network)
+
+;; Functions:
+
+;;;###autoload
+(defun erc-determine-network ()
+  "Return the name of the network or \"Unknown\" as a symbol.  Use the
+server parameter NETWORK if provided, otherwise parse the server name and
+search for a match in `erc-networks-alist'."
+  ;; The server made it easy for us and told us the name of the NETWORK
+  (if (assoc "NETWORK" erc-server-parameters)
+      (intern (cdr (assoc "NETWORK" erc-server-parameters)))
+    (or
+     ;; Loop through `erc-networks-alist' looking for a match.
+     (let ((server (or erc-server-announced-name erc-session-server)))
+       (loop for (name matcher) in erc-networks-alist
+	     when (and matcher
+		       (string-match (concat matcher "\\'") server))
+	     do (return name)))
+     'Unknown)))
+
+(defun erc-network ()
+  "Return the value of `erc-network' for the current server."
+  (with-current-buffer (erc-server-buffer) erc-network))
+
+(defun erc-current-network ()
+  "Deprecated.  Use `erc-network' instead.  Return the name of this server's
+network as a symbol."
+  (with-current-buffer (erc-server-buffer)
+    (intern (downcase (symbol-name erc-network)))))
+
+(erc-make-obsolete 'erc-current-network 'erc-network
+		   "Obsolete since erc-nets 1.5")
+
+(defun erc-network-name ()
+  "Returns the name of the current network as a string."
+  (with-current-buffer (erc-server-buffer) (symbol-name erc-network)))
+
+(defun erc-set-network-name (proc parsed)
+  "Set `erc-network' to the value returned by `erc-determine-network'."
+  (unless erc-server-connected
+    (setq erc-network (erc-determine-network)))
+  nil)
+
+(defun erc-unset-network-name (nick ip reason)
+  "Set `erc-network' to nil."
+  (setq erc-network nil)
+  nil)
+
+(add-hook 'erc-server-375-functions 'erc-set-network-name)
+(add-hook 'erc-server-422-functions 'erc-set-network-name)
+(add-hook 'erc-disconnected-hook 'erc-unset-network-name)
+
+(defun erc-ports-list (ports)
+  "Return a list of PORTS.
+
+PORTS should be a list of either:
+  A number, in which case it is returned a list.
+  Or a pair of the form (LOW HIGH), in which case, a list of all the
+  numbers between LOW and HIGH (inclusive) is returned.
+
+As an example:
+  (erc-ports-list '(1)) => (1)
+  (erc-ports-list '((1 5))) => (1 2 3 4 5)
+  (erc-ports-list '(1 (3 5))) => (1 3 4 5)"
+  (let (result)
+    (dolist (p ports)
+      (cond ((numberp p)
+	     (push p result))
+	    ((listp p)
+	     (setq result (nconc (loop for i from (cadr p) downto (car p)
+				       collect i)
+				 result)))))
+    (nreverse result)))
+
+;;;###autoload
+(defun erc-server-select ()
+  "Interactively select a server to connect to using `erc-server-alist'."
+  (interactive)
+  (let* ((completion-ignore-case t)
+	 (net (intern
+	       (completing-read "Network: "
+				(erc-delete-dups
+				 (mapcar (lambda (x)
+					   (list (symbol-name (nth 1 x))))
+					 erc-server-alist)))))
+	 (srv (assoc
+	       (completing-read "Server: "
+				(delq nil
+				      (mapcar (lambda (x)
+						(when (equal (nth 1 x) net)
+						  x))
+					      erc-server-alist)))
+	       erc-server-alist))
+	 (host (nth 2 srv))
+	 (ports (if (listp (nth 3 srv))
+		    (erc-ports-list (nth 3 srv))
+		  (list (nth 3 srv))))
+	 (port (nth (random (length ports)) ports)))
+    (erc host port erc-nick erc-user-full-name t)))
+
+;;; The following experimental
+;; It does not work yet, help me with it if you
+;; think it is worth the effort.
+
+(defvar erc-settings
+  '((pals freenode ("kensanata" "shapr" "anti\\(fuchs\\|gone\\)"))
+    (format-nick-function (freenode "#emacs") erc-format-@nick))
+  "Experimental: Alist of configuration options.
+The format is (VARNAME SCOPE VALUE) where
+VARNAME is a symbol identifying the configuration option,
+SCOPE is either a symbol which identifies an entry from
+  `erc-networks-alist' or a list (NET TARGET) where NET is a network symbol and
+  TARGET is a string identifying the channel/query target.
+VALUE is the options value.")
+
+(defun erc-get (var &optional net target)
+  (let ((items erc-settings)
+	elt val)
+    (while items
+      (setq elt (car items)
+	    items (cdr items))
+      (when (eq (car elt) var)
+	(cond ((and net target (listp (nth 1 elt))
+		    (eq net (car (nth 1 elt)))
+		    (string-equal target (nth 1 (nth 1 elt))))
+	       (setq val (nth 2 elt)
+		     items nil))
+	      ((and net (eq net (nth 1 elt)))
+	       (setq val (nth 2 elt)
+		     items nil))
+	      ((and (not net) (not target) (not (nth 1 elt)))
+	       (setq val (nth 2 elt)
+		     items nil)))))
+    val))
+
+(erc-get 'pals 'freenode)
+
+
+(provide 'erc-nets)
+
+;;; erc-nets.el ends here
+;;
+;; Local Variables:
+;; indent-tabs-mode: t
+;; tab-width: 8
+;; End:
+
+;; arch-tag: 68cccabd-f66b-456c-9abe-5f993a2dc91c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lisp/erc/erc-netsplit.el	Wed Feb 01 10:07:17 2006 +0000
@@ -0,0 +1,212 @@
+;;; erc-netsplit.el --- Reduce JOIN/QUIT messages on netsplits
+
+;; Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+
+;; Author: Mario Lang <mlang@delysid.org>
+;; Keywords: comm
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
+
+;;; Commentary:
+
+;; This module hides quit/join messages if a netsplit occurs.
+;; To enable, add the following to your ~/.emacs:
+;; (require 'erc-netsplit)
+;; (erc-netsplit-mode 1)
+
+;;; Code:
+
+(require 'erc)
+(eval-when-compile (require 'cl))
+
+(defgroup erc-netsplit nil
+  "Netsplit detection tries to automatically figure when a
+netsplit happens, and filters the QUIT messages. It also keeps
+track of netsplits, so that it can filter the JOIN messages on a netjoin too."
+  :group 'erc)
+
+;;;###autoload (autoload 'erc-netsplit-mode "erc-netsplit")
+(define-erc-module netsplit nil
+  "This mode hides quit/join messages if a netsplit occurs."
+  ((erc-netsplit-install-message-catalogs)
+   (add-hook 'erc-server-JOIN-functions 'erc-netsplit-JOIN)
+   (add-hook 'erc-server-MODE-functions 'erc-netsplit-MODE)
+   (add-hook 'erc-server-QUIT-functions 'erc-netsplit-QUIT)
+   (add-hook 'erc-timer-hook 'erc-netsplit-timer))
+  ((remove-hook 'erc-server-JOIN-functions 'erc-netsplit-JOIN)
+   (remove-hook 'erc-server-MODE-functions 'erc-netsplit-MODE)
+   (remove-hook 'erc-server-QUIT-functions 'erc-netsplit-QUIT)
+   (remove-hook 'erc-timer-hook 'erc-netsplit-timer)))
+
+(defcustom erc-netsplit-show-server-mode-changes-flag nil
+  "Set to t to enable display of server mode changes."
+  :group 'erc-netsplit
+  :type 'boolean)
+
+(defcustom erc-netsplit-debug nil
+  "If non-nil, debug messages will be shown in the
+sever buffer."
+  :group 'erc-netsplit
+  :type 'boolean)
+
+(defcustom erc-netsplit-regexp "^[^ @!\"]+\\.[^ @!]+ [^ @!]+\\.[^ @!\"]+$"
+  "This regular expression should match quit reasons produced
+by netsplits."
+  :group 'erc-netsplit
+  :type 'regexp)
+
+(defcustom erc-netsplit-hook nil
+  "Run whenever a netsplit is detected the first time.
+Args: PROC is the process the netsplit originated from and
+      SPLIT is the netsplit (e.g. \"server.name.1 server.name.2\")."
+  :group 'erc-hooks
+  :type 'hook)
+
+(defcustom erc-netjoin-hook nil
+  "Run whenever a netjoin is detected the first time.
+Args: PROC is the process the netjoin originated from and
+      SPLIT is the netsplit (e.g. \"server.name.1 server.name.2\")."
+  :group 'erc-hooks
+  :type 'hook)
+
+(defvar erc-netsplit-list nil
+  "This is a list of the form
+\((\"a.b.c.d e.f.g\" TIMESTAMP FIRST-JOIN \"nick1\" ... \"nickn\") ...)
+where FIRST-JOIN is t or nil, depending on whether or not the first
+join from that split has been detected or not.")
+(make-variable-buffer-local 'erc-netsplit-list)
+
+(defun erc-netsplit-install-message-catalogs ()
+  (erc-define-catalog
+   'english
+   '((netsplit	       . "netsplit: %s")
+     (netjoin	       . "netjoin: %s, %N were split")
+     (netjoin-done     . "netjoin: All lost souls are back!")
+     (netsplit-none    . "No netsplits in progress")
+     (netsplit-wholeft . "split: %s missing: %n %t"))))
+
+(defun erc-netsplit-JOIN (proc parsed)
+  "Show/don't show rejoins."
+  (let ((nick (erc-response.sender parsed))
+	(no-next-hook nil))
+    (dolist (elt erc-netsplit-list)
+      (if (member nick (nthcdr 3 elt))
+	  (progn
+	    (if (not (caddr elt))
+		(progn
+		  (erc-display-message
+		   parsed 'notice (process-buffer proc)
+		   'netjoin ?s (car elt) ?N (length (nthcdr 3 elt)))
+		  (setcar (nthcdr 2 elt) t)
+		  (run-hook-with-args 'erc-netjoin-hook proc (car elt))))
+	    ;; need to remove this nick, perhaps the whole entry here.
+	    ;; Note that by removing the nick now, we can't tell if further
+	    ;; join messages (for other channels) should also be
+	    ;; suppressed.
+	    (if (null (nthcdr 4 elt))
+		(progn
+		  (erc-display-message
+		   parsed 'notice (process-buffer proc)
+		   'netjoin-done ?s (car elt))
+		  (setq erc-netsplit-list (delq elt erc-netsplit-list)))
+	      (delete nick elt))
+	    (setq no-next-hook t))))
+    no-next-hook))
+
+(defun erc-netsplit-MODE (proc parsed)
+  "Hide mode changes from servers."
+  ;; regexp matches things with a . in them, and no ! or @ in them.
+  (when (string-match "^[^@!]+\\.[^@!]+$" (erc-response.sender parsed))
+    (and erc-netsplit-debug
+	 (erc-display-message
+	  parsed 'notice (process-buffer proc)
+	  "[debug] server mode change."))
+    (not erc-netsplit-show-server-mode-changes-flag)))
+
+(defun erc-netsplit-QUIT (proc parsed)
+  "Detect netsplits."
+  (let ((split (erc-response.contents parsed))
+	(nick (erc-response.sender parsed))
+	ass)
+    (when (string-match erc-netsplit-regexp split)
+      (setq ass (assoc split erc-netsplit-list))
+      (if ass
+	  ;; element for this netsplit exists already
+	  (progn
+	    (setcdr (nthcdr 2 ass) (cons nick (nthcdr 3 ass)))
+	    (when (caddr ass) 
+	      ;; There was already a netjoin for this netsplit, it
+	      ;; seems like the old one didn't get finished...
+	      (erc-display-message 
+	       parsed 'notice (process-buffer proc)
+	       'netsplit ?s split)
+	      (setcar (nthcdr 2 ass) t)
+	      (run-hook-with-args 'erc-netsplit-hook proc split)))
+	;; element for this netsplit does not yet exist
+	(setq erc-netsplit-list
+	      (cons (list split
+			  (erc-current-time)
+			  nil
+			  nick)
+		    erc-netsplit-list))
+	(erc-display-message
+	 parsed 'notice (process-buffer proc)
+	 'netsplit ?s split)
+	(run-hook-with-args 'erc-netsplit-hook proc split))
+      t)))
+
+(defun erc-netsplit-timer (now)
+  "Clean cruft from `erc-netsplit-list' older than 10 minutes."
+  (dolist (elt erc-netsplit-list)
+    (when (> (erc-time-diff (cadr elt) now) 600)
+      (when erc-netsplit-debug
+	(erc-display-message
+	 nil 'notice (current-buffer)
+	 (concat "Netsplit: Removing " (car elt))))
+      (setq erc-netsplit-list (delq elt erc-netsplit-list)))))
+
+;;;###autoload
+(defun erc-cmd-WHOLEFT ()
+  "Show who's gone."
+  (with-current-buffer (erc-server-buffer)
+    (if (null erc-netsplit-list)
+	(erc-display-message
+	 nil 'notice 'active
+	 'netsplit-none)
+      (dolist (elt erc-netsplit-list)
+	(erc-display-message
+	 nil 'notice 'active
+	 'netsplit-wholeft ?s (car elt)
+	 ?n (mapconcat 'erc-extract-nick (nthcdr 3 elt) " ")
+	 ?t (if (caddr elt)
+		"(joining)"
+	      "")))))
+  t)
+
+(defalias 'erc-cmd-WL 'erc-cmd-WHOLEFT)
+
+(provide 'erc-netsplit)
+
+;;; erc-netsplit.el ends here
+;;
+;; Local Variables:
+;; indent-tabs-mode: t
+;; tab-width: 8
+;; End:
+
+;; arch-tag: 61a85cb0-7e7b-4312-a4f6-313c7a25a6e8
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lisp/erc/erc-nicklist.el	Wed Feb 01 10:07:17 2006 +0000
@@ -0,0 +1,411 @@
+;;; erc-nicklist.el --- Display channel nicknames in a side buffer.
+
+;; Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc.
+
+;; Filename: erc-nicklist.el
+;; Author: Lawrence Mitchell <wence@gmx.li>
+;; Created: 2004-04-30
+;; Keywords: IRC chat client Internet
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
+
+;;; Commentary:
+;;
+;; This provides a minimal mIRC style nicklist buffer for ERC.  To
+;; activate, do M-x erc-nicklist RET in the channel buffer you want
+;; the nicklist to appear for.  To close and quit the nicklist
+;; buffer, do M-x erc-nicklist-quit RET.
+;;
+;; TODO:
+;; o Somehow associate nicklist windows with channel windows so they
+;;   appear together, and if one gets buried, then the other does.
+;;
+;; o Make "Query" and "Message" work.
+;;
+;; o Prettify the actual list of nicks in some way.
+;;
+;; o Add a proper erc-module that people can turn on and off, figure
+;;   out a way of creating the nicklist window at an appropriate time
+;;   --- probably in `erc-join-hook'.
+;;
+;; o Ensure XEmacs compatibility --- the mouse-menu support is likely
+;;   broken.
+;;
+;; o Add option to display in a separate frame --- will again need to
+;;   be able to associate the nicklist with the currently active
+;;   channel buffer or something similar.
+;;
+;; o Allow toggling of visibility of nicklist via ERC commands.
+
+;;; History:
+;;
+
+;; Changes by Edgar Gonçalves <edgar.goncalves@inesc-id.pt>
+;; Jun 25 2005:
+;;     - images are changed to a standard set of names.
+;;     - /images now contain gaim's status icons.
+;; May 31 2005:
+;;     - tooltips are improved. they try to access bbdb for a nice nick!
+;; Apr 26 2005:
+;;     - erc-nicklist-channel-users-info was fixed (sorting bug)
+;;     - Away names don't need parenthesis when using icons
+;; Apr 26 2005:
+;;     - nicks can display icons of their connection type (msn, icq, for now)
+;; Mar 15 2005:
+;;     - nicks now are different for unvoiced and op users
+;;     - nicks now have tooltips displaying more info
+;; Mar 18 2005:
+;;     - queries now work ok, both on menu and keyb shortcut RET.
+;;     - nicklist is now sorted ignoring the case. Voiced nicks will
+;;       appear according to `erc-nicklist-voiced-position'.
+
+;;; Code:
+
+(require 'erc)
+(condition-case nil
+    (require 'erc-bbdb)
+  (error nil))
+(eval-when-compile (require 'cl))
+
+(defgroup erc-nicklist nil
+  "Display a list of nicknames in a separate window."
+  :group 'erc)
+
+(defcustom erc-nicklist-use-icons t
+  "*If non-nil, display an icon instead of the name of the chat medium.
+By \"chat medium\", we mean IRC, AOL, MSN, ICQ, etc."
+  :group 'erc-nicklist
+  :type 'boolean)
+
+(defcustom erc-nicklist-icons-directory
+  (concat default-directory "images/")
+  "*Directory of the PNG files for chat icons.
+Icons are displayed if `erc-nicklist-use-icons' is non-nil."
+  :group 'erc-nicklist
+  :type 'string)
+
+(defcustom erc-nicklist-voiced-position 'bottom
+  "*Position of voiced nicks in the nicklist.
+The value can be `top', `bottom' or nil (don't sort)."
+  :group 'erc-nicklist
+  :type  '(choice
+	   (const :tag "Top" 'top)
+	   (const :tag "Bottom" 'bottom)
+	   (const :tag "Mixed" nil)))
+
+(defcustom erc-nicklist-window-size 20.0
+  "*The size of the nicklist window.
+
+This specifies a percentage of the channel window width.
+
+A negative value means the nicklist window appears on the left of the
+channel window, and vice versa."
+  :group 'erc-nicklist
+  :type 'float)
+
+
+(defun erc-nicklist-buffer-name (&optional buffer)
+  "Return the buffer name for a nicklist associated with BUFFER.
+
+If BUFFER is nil, use the value of `current-buffer'."
+  (format " *%s-nicklist*" (buffer-name (or buffer (current-buffer)))))
+
+(defun erc-nicklist-make-window ()
+  "Create an ERC nicklist window.
+
+See also `erc-nicklist-window-size'."
+  (let ((width (floor (* (window-width) (/ erc-nicklist-window-size 100.0))))
+	(buffer (erc-nicklist-buffer-name))
+	window)
+    (split-window-horizontally (- width))
+    (setq window (next-window))
+    (set-window-buffer window (get-buffer-create buffer))
+    (with-current-buffer buffer
+      (set-window-dedicated-p window t))))
+
+
+(defvar erc-nicklist-images-alist '()
+  "Alist that maps a connection type to an icon.")
+
+(defun erc-nicklist-insert-medium-name-or-icon (host channel is-away)
+  "Inserts an icon or a string identifying the current host type.
+This is configured using `erc-nicklist-use-icons' and
+`erc-nicklist-icons-directory'."
+  ;; identify the network (for bitlebee usage):
+  (let ((bitlbee-p (save-match-data
+		     (string-match "\\`&bitlbee\\b"
+				   (buffer-name channel)))))
+    (cond ((and bitlbee-p
+		(string= "login.icq.com" host))
+	   (if erc-nicklist-use-icons
+	       (if is-away
+		   (insert-image (cdr (assoc 'icq-away
+					     erc-nicklist-images-alist)))
+		 (insert-image (cdr (assoc 'icq
+					   erc-nicklist-images-alist))))
+	     (insert "ICQ")))
+	  (bitlbee-p
+	   (if erc-nicklist-use-icons
+	       (if is-away
+		   (insert-image (cdr (assoc 'msn-away
+					     erc-nicklist-images-alist)))
+		 (insert-image (cdr (assoc 'msn
+					   erc-nicklist-images-alist))))
+	     (insert "MSN")))
+	  (t
+	   (if erc-nicklist-use-icons
+	       (if is-away
+		   (insert-image (cdr (assoc 'irc-away
+					     erc-nicklist-images-alist)))
+		 (insert-image (cdr (assoc 'irc
+					   erc-nicklist-images-alist))))
+	     (insert "IRC"))))
+    (insert " ")))
+
+(defun erc-nicklist-search-for-nick (finger-host)
+  "Return the bitlbee-nick field for this contact given FINGER-HOST.
+Seach for the BBDB record of this contact.  If not found, return nil."
+  (when (boundp 'erc-bbdb-bitlbee-name-field)
+    (let ((record (car
+		   (erc-member-if
+		    #'(lambda (r)
+			(let ((fingers (bbdb-record-finger-host r)))
+			  (when fingers
+			    (string-match finger-host
+					  (car (bbdb-record-finger-host r))))))
+		    (bbdb-records)))))
+      (when record
+	(bbdb-get-field record erc-bbdb-bitlbee-name-field)))))
+
+(defun erc-nicklist-insert-contents (channel)
+  "Insert the nicklist contents, with text properties and the optional images."
+  (setq buffer-read-only nil)
+  (erase-buffer)
+  (dolist (u (erc-nicklist-channel-users-info channel))
+    (let* ((server-user (car u))
+	   (channel-user (cdr u))
+	   (nick     (erc-server-user-nickname server-user))
+	   (host     (erc-server-user-host server-user))
+	   (login    (erc-server-user-login server-user))
+	   (full-name(erc-server-user-full-name server-user))
+	   (info     (erc-server-user-info server-user))
+	   (channels (erc-server-user-buffers server-user))
+	   (op       (erc-channel-user-op channel-user))
+	   (voice    (erc-channel-user-voice channel-user))
+	   (bbdb-nick (erc-nicklist-search-for-nick (concat login "@" host)))
+	   (away-status (if voice "" "\n(Away)"))
+	   (balloon-text (concat bbdb-nick (if (string= "" bbdb-nick)
+					       "" "\n")
+				 "Login: " login "@" host
+				 away-status)))
+      (erc-nicklist-insert-medium-name-or-icon host channel (not voice))
+      (unless (or voice erc-nicklist-use-icons)
+	(setq nick (concat "(" nick ")")))
+      (when op
+	(setq nick (concat nick " (OP)")))
+      (insert (erc-propertize nick
+			      'erc-nicklist-nick nick
+			      'mouse-face 'highlight
+			      'erc-nicklist-channel channel
+			      'help-echo balloon-text)
+	      "\n")))
+  (erc-nicklist-mode))
+
+
+(defun erc-nicklist ()
+  "Create an ERC nicklist buffer."
+  (interactive)
+  (let ((channel (current-buffer)))
+    (unless (or (not erc-nicklist-use-icons)
+		erc-nicklist-images-alist)
+      (setq erc-nicklist-images-alist
+	    `((msn      . ,(create-image (concat erc-nicklist-icons-directory
+						 "msn-online.png")))
+	      (msn-away . ,(create-image (concat erc-nicklist-icons-directory
+						 "msn-offline.png")))
+	      (irc      . ,(create-image (concat erc-nicklist-icons-directory
+						 "irc-online.png")))
+	      (irc-away . ,(create-image (concat erc-nicklist-icons-directory
+						 "irc-offline.png")))
+	      (icq      . ,(create-image (concat erc-nicklist-icons-directory
+						 "icq-online.png")))
+	      (icq-away . ,(create-image (concat erc-nicklist-icons-directory
+						 "icq-offline.png"))))))
+    (erc-nicklist-make-window)
+    (with-current-buffer (get-buffer (erc-nicklist-buffer-name channel))
+      (erc-nicklist-insert-contents channel)))
+  (add-hook 'erc-channel-members-changed-hook #'erc-nicklist-update))
+
+(defun erc-nicklist-update ()
+  "Update the ERC nicklist buffer."
+  (let ((b (get-buffer (erc-nicklist-buffer-name)))
+	(channel (current-buffer)))
+    (when b
+      (with-current-buffer b
+	(erc-nicklist-insert-contents channel)))))
+
+(defvar erc-nicklist-mode-map
+  (let ((map (make-sparse-keymap)))
+    (define-key map (kbd "<down-mouse-3>") 'erc-nicklist-menu)
+    (define-key map "\C-j" 'erc-nicklist-kbd-menu)
+    (define-key map "q"  'erc-nicklist-quit)
+    (define-key map (kbd "RET") 'erc-nicklist-kbd-cmd-QUERY)
+    map)
+  "Keymap for `erc-nicklist-mode'.")
+
+(define-derived-mode erc-nicklist-mode fundamental-mode
+  "Nicklist"
+  "Major mode for the ERC nicklist buffer."
+  (setq buffer-read-only t))
+
+(defun erc-nicklist-call-erc-command (command point buffer window)
+  "Call an ERC COMMAND.
+
+Depending on what COMMAND is, it's called with one of POINT, BUFFER,
+or WINDOW as arguments."
+  (when command
+    (let* ((p (text-properties-at point))
+	   (b (plist-get p 'erc-nicklist-channel)))
+      (if (memq command '(erc-nicklist-quit ignore))
+	  (funcall command window)
+	;; EEEK!  Horrble, but it's the only way we can ensure the
+	;; response goes to the correct buffer.
+	(erc-set-active-buffer b)
+	(switch-to-buffer-other-window b)
+	(funcall command (plist-get p 'erc-nicklist-nick))))))
+
+(defun erc-nicklist-cmd-QUERY (user &optional server)
+  "Opens a query buffer with USER."
+  ;; FIXME: find a way to switch to that buffer afterwards...
+  (let ((send (if server
+		  (format "QUERY %s %s" user server)
+		  (format "QUERY %s" user))))
+    (erc-cmd-QUERY user)
+    t))
+
+(defun erc-nicklist-kbd-cmd-QUERY (&optional window)
+  (interactive)
+  (let* ((p      (text-properties-at (point)))
+	 (server (plist-get p 'erc-nicklist-channel))
+	 (nick   (plist-get p 'erc-nicklist-nick))
+	 (nick   (or (and (string-match "(\\(.*\\))" nick)
+			  (match-string 1 nick))
+		     nick))
+	 (nick   (or (and (string-match "\\+\\(.*\\)" nick)
+			  (match-string 1 nick))
+		     nick))
+	 (send   (format "QUERY %s %s" nick server)))
+    (switch-to-buffer-other-window server)
+    (erc-cmd-QUERY nick)))
+
+
+(defvar erc-nicklist-menu
+  (let ((map (make-sparse-keymap "Action")))
+    (define-key map [erc-cmd-WHOIS]
+      '("Whois" . erc-cmd-WHOIS))
+    (define-key map [erc-cmd-DEOP]
+      '("Deop" . erc-cmd-DEOP))
+    (define-key map [erc-cmd-MSG]
+      '("Message" . erc-cmd-MSG)) ;; TODO!
+    (define-key map [erc-nicklist-cmd-QUERY]
+      '("Query" . erc-nicklist-kbd-cmd-QUERY))
+    (define-key map [ignore]
+      '("Cancel" . ignore))
+    (define-key map [erc-nicklist-quit]
+      '("Close nicklist" . erc-nicklist-quit))
+    map)
+  "Menu keymap for the ERC nicklist.")
+
+(defun erc-nicklist-quit (&optional window)
+  "Delete the ERC nicklist.
+
+Deletes WINDOW and stops updating the nicklist buffer."
+  (interactive)
+  (let ((b (window-buffer window)))
+    (with-current-buffer b
+      (set-buffer-modified-p nil)
+      (kill-this-buffer)
+      (remove-hook 'erc-channel-members-changed-hook 'erc-nicklist-update))))
+
+
+(defun erc-nicklist-kbd-menu ()
+  "Show the ERC nicklist menu."
+  (interactive)
+  (let* ((point (point))
+	 (window (selected-window))
+	 (buffer (current-buffer)))
+    (with-current-buffer buffer
+      (erc-nicklist-call-erc-command
+       (car (x-popup-menu point
+			  erc-nicklist-menu))
+       point
+       buffer
+       window))))
+
+(defun erc-nicklist-menu (&optional arg)
+  "Show the ERC nicklist menu.
+
+ARG is a parametrized event (see `interactive')."
+  (interactive "e")
+  (let* ((point (nth 1 (cadr arg)))
+	 (window (car (cadr arg)))
+	 (buffer (window-buffer window)))
+    (with-current-buffer buffer
+      (erc-nicklist-call-erc-command
+       (car (x-popup-menu arg
+			  erc-nicklist-menu))
+       point
+       buffer
+       window))))
+
+
+(defun erc-nicklist-channel-users-info (channel)
+  "Return a nick-sorted list of all users on CHANNEL.
+Result are elements in the form (SERVER-USER . CHANNEL-USER). The
+list has all the voiced users according to
+`erc-nicklist-voiced-position'."
+  (let* ((nicks (erc-sort-channel-users-alphabetically
+		 (with-current-buffer channel (erc-get-channel-user-list)))))
+    (if erc-nicklist-voiced-position
+	(let ((voiced-nicks (erc-remove-if-not
+			     #'(lambda (x)
+				 (null (erc-channel-user-voice (cdr x))))
+			     nicks))
+	      (devoiced-nicks (erc-remove-if-not
+			       #'(lambda (x)
+				   (erc-channel-user-voice
+				    (cdr x)))
+			       nicks)))
+	  (cond ((eq erc-nicklist-voiced-position 'top)
+		 (append devoiced-nicks voiced-nicks))
+		((eq erc-nicklist-voiced-position 'bottom)
+		 (append voiced-nicks devoiced-nicks))))
+      nicks)))
+
+
+
+(provide 'erc-nicklist)
+
+;;; erc-nicklist.el ends here
+;;
+;; Local Variables:
+;; indent-tabs-mode: t
+;; tab-width: 8
+;; End:
+
+;; arch-tag: db37a256-87a7-4544-bd90-e5f16c9f5ca5
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lisp/erc/erc-nickserv.el	Wed Feb 01 10:07:17 2006 +0000
@@ -0,0 +1,337 @@
+;;; erc-nickserv.el --- Identify to NickServ
+
+;; Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
+
+;;; Commentary:
+
+;; There are two ways to go about identifying yourself automatically to
+;; NickServ with this module.  The more secure way is to listen for identify
+;; requests from the user NickServ.  Another way is to identify yourself to
+;; NickServ directly after a successful connection and every time you change
+;; your nickname.  This method is rather insecure, though, because no checks
+;; are made to test if NickServ is the real NickServ for a given network or
+;; server.
+
+;; As a default, ERC has the data for the official nickname services on the
+;; networks Austnet, BrasNET, Dalnet, freenode, GalaxyNet, and Slashnet.
+;; You can add more by using M-x customize-variable RET erc-nickserv-alist.
+
+;; Usage:
+;;
+;; Put into your .emacs:
+;;
+;; (require 'erc-nickserv)
+;; (erc-services-mode 1)
+;;
+;; Add your nickname and NickServ password to `erc-nickserv-passwords'.
+;; Using the freenode network as an example:
+;;
+;; (setq erc-nickserv-passwords '((freenode (("nickname" "password")))))
+;;
+;; The default automatic identification mode is autodetection of NickServ
+;; identify requests.  Set the variable `erc-nickserv-identify-mode' if
+;; you'd like to change this behavior.  You can also change the way
+;; automatic identification is handled by using:
+;;
+;; M-x erc-nickserv-identify-mode
+;;
+;; If you'd rather not identify yourself automatically but would like access
+;; to the functions contained in this file, just load this file without
+;; enabling `erc-services-mode'.
+;;
+
+;;; Code:
+
+(require 'erc)
+(require 'erc-nets)
+(eval-when-compile (require 'cl))
+
+;; Customization:
+
+(defgroup erc-services nil
+  "Configuration for IRC services.
+
+On some networks, there exists a special type of automated irc bot,
+called Services.  Those usually allow you to register your nickname,
+post/read memos to other registered users who are currently offline,
+and do various other things.
+
+This group allows you to set variables to somewhat automate
+communication with those Services."
+  :group 'erc)
+
+;;;###autoload (autoload 'erc-services-mode "erc-nickserv" nil t)
+(define-erc-module services nickserv
+  "This mode automates communication with services."
+  ((erc-nickserv-identify-mode erc-nickserv-identify-mode))
+  ((remove-hook 'erc-server-NOTICE-functions
+		'erc-nickserv-identify-autodetect)
+   (remove-hook 'erc-after-connect
+		'erc-nickserv-identify-on-connect)
+   (remove-hook 'erc-nick-changed-functions
+		'erc-nickserv-identify-on-nick-change)))
+
+;;;###autoload
+(defun erc-nickserv-identify-mode (mode)
+  "Set up hooks according to which MODE the user has chosen."
+  (interactive
+   (list (intern (completing-read
+		  "Choose Nickserv identify mode (RET to disable): "
+		  '(("autodetect") ("nick-change")) nil t))))
+  (cond ((eq mode 'autodetect)
+	 (setq erc-nickserv-identify-mode 'autodetect)
+	 (add-hook 'erc-server-NOTICE-functions
+		   'erc-nickserv-identify-autodetect)
+	 (remove-hook 'erc-nick-changed-functions
+		      'erc-nickserv-identify-on-nick-change)
+	 (remove-hook 'erc-after-connect
+		      'erc-nickserv-identify-on-connect))
+	((eq mode 'nick-change)
+	 (setq erc-nickserv-identify-mode 'nick-change)
+	 (add-hook 'erc-after-connect
+		   'erc-nickserv-identify-on-connect)
+	 (add-hook 'erc-nick-changed-functions
+		   'erc-nickserv-identify-on-nick-change)
+	 (remove-hook 'erc-server-NOTICE-functions
+		      'erc-nickserv-identify-autodetect))
+	(t
+	 (setq erc-nickserv-identify-mode nil)
+	 (remove-hook 'erc-server-NOTICE-functions
+		      'erc-nickserv-identify-autodetect)
+	 (remove-hook 'erc-after-connect
+		      'erc-nickserv-identify-on-connect)
+	 (remove-hook 'erc-nick-changed-functions
+		      'erc-nickserv-identify-on-nick-change))))
+
+(defcustom erc-nickserv-identify-mode 'autodetect
+  "The mode which is used when identifying to Nickserv.
+
+Possible settings are:.
+
+'autodetect  - Identify when the real Nickserv sends an identify request.
+'nick-change - Identify when you change your nickname.
+nil          - Disables automatic Nickserv identification.
+
+You can also use M-x erc-nickserv-identify-mode to change modes."
+  :group 'erc-services
+  :type '(choice (const autodetect)
+		 (const nick-change)
+		 (const nil))
+  :set (lambda (sym val)
+	 (set-default sym val)
+	 (erc-nickserv-identify-mode val)))
+
+(defcustom erc-prompt-for-nickserv-password t
+  "Ask for the password when identifying to NickServ."
+  :group 'erc-services
+  :type 'boolean)
+
+(defcustom erc-nickserv-passwords nil
+  "Passwords used when identifying to NickServ automatically.
+
+Example of use:
+  (setq erc-nickserv-passwords
+        '((freenode ((\"nick-one\" . \"password\")
+                     (\"nick-two\" . \"password\")))
+          (DALnet ((\"nick\" . \"password\")))))"
+  :group 'erc-services
+  :type '(repeat
+	  (list :tag "Network"
+		(choice :tag "Network name"
+			(const freenode)
+			(const DALnet)
+			(const GalaxyNet)
+			(const SlashNET)
+			(const BRASnet)
+			(const iip)
+			(const Austnet)
+			(symbol :tag "Network name"))
+		(repeat :tag "Nickname and password"
+			(cons :tag "Identity"
+			      (string :tag "Nick")
+			      (string :tag "Password"))))))
+
+;; Variables:
+
+(defcustom erc-nickserv-alist
+  '((DALnet
+     "NickServ!service@dal.net"
+     "/msg\\s-NickServ@services.dal.net\\s-IDENTIFY\\s-<password>"
+     "NickServ@services.dal.net"
+     "IDENTIFY"
+     nil)
+    (freenode
+     "NickServ!NickServ@services."
+     "/msg\\s-NickServ\\s-IDENTIFY\\s-<password>"
+     "NickServ"
+     "IDENTIFY"
+     nil)
+    (GalaxyNet
+     "NS!nickserv@galaxynet.org"
+     "Please\\s-change\\s-nicks\\s-or\\s-authenticate."
+     "NS@services.galaxynet.org"
+     "AUTH"
+     t)
+    (SlashNET
+     "NickServ!services@services.slashnet.org"
+     "/msg\\s-NickServ\\s-IDENTIFY\\s-password"
+     "NickServ@services.slashnet.org"
+     "IDENTIFY"
+     nil)
+    (iip
+     "Trent@anon.iip"
+     "type\\s-/squery\\s-Trent\\s-identify\\s-<password>"
+     "Trent@anon.iip"
+     "IDENTIFY"
+     nil
+     "SQUERY")
+    (BRASnet
+     "NickServ!services@brasnet.org"
+     "/NickServ\\s-IDENTIFY\\s-senha"
+     "NickServ"
+     "IDENTIFY"
+     nil
+     "")
+     (Austnet
+      "NickOP!service@austnet.org"
+      "/msg\\s-NickOP@austnet.org\\s-identify\\s-<password>"
+      "nickop@austnet.org"
+      "identify"
+      nil)
+     (Azzurra
+      "NickServ!service@azzurra.org"
+      "/ns\\s-IDENTIFY\\s-password"
+      "NickServ"
+      "IDENTIFY"
+      nil)
+     (OFTC
+      "NickServ!services@services.oftc.net"
+      "/msg\\s-NickServ\\s-IDENTIFY\\s-\^_password"
+      "NickServ"
+      "IDENTIFY"
+      nil))
+   "Alist of NickServer details, sorted by network.
+Every element in the list has the form
+  \(SYMBOL NICKSERV REGEXP NICK KEYWORD USE-CURRENT ANSWER)
+
+SYMBOL is a network identifier, a symbol, as used in `erc-networks-alist'.
+NICKSERV is the description of the nickserv in the form nick!user@host.
+REGEXP is a regular expression matching the message from nickserv.
+NICK is nickserv's nickname.  Use nick@server where necessary/possible.
+KEYWORD is the keyword to use in the reply message to identify yourself.
+USE-CURRENT indicates whether the current nickname must be used when
+  identifying.
+ANSWER is the command to use for the answer.  The default is 'privmsg.
+  This last element is optional."
+   :group 'erc-services
+   :type '(repeat
+	   (list :tag "Nickserv data"
+		 (symbol :tag "Network name")
+		 (string :tag "Nickserv's nick!user@host")
+		 (regexp :tag "Identify request sent by Nickserv")
+		 (string :tag "Identify to")
+		 (string :tag "Identify keyword")
+		 (boolean :tag "Use current nick in identify message?")
+		 (choice :tag "Command to use (optional)"
+		  (string :tag "Command")
+		  (const :tag "No special command necessary" nil)))))
+
+;; Functions:
+
+(defun erc-nickserv-identify-autodetect (proc parsed)
+  "Check for a NickServ identify request everytime a notice is received.
+Make sure it is the real NickServ for this network and that it has
+specifically asked the user to IDENTIFY.
+If `erc-prompt-for-nickserv-password' is non-nil, prompt the user for the
+password for this nickname, otherwise try to send it automatically."
+  (unless (and (null erc-nickserv-passwords)
+	       (null erc-prompt-for-nickserv-password))
+    (let* ((network (erc-network))
+	   (nickserv (nth 1 (assoc network erc-nickserv-alist)))
+	   (identify-regex (nth 2 (assoc network erc-nickserv-alist)))
+	   (sspec (erc-response.sender parsed))
+	   (nick (car (erc-response.command-args parsed)))
+	   (msg (erc-response.contents parsed)))
+      ;; continue only if we're sure it's the real nickserv for this network
+      ;; and it's asked us to identify
+      (when (and nickserv (equal sspec nickserv)
+		 (string-match identify-regex msg))
+	(erc-log "NickServ IDENTIFY request detected")
+	(erc-nickserv-call-identify-function nick)
+	nil))))
+
+(defun erc-nickserv-identify-on-connect (server nick)
+  "Identify to Nickserv after the connection to the server is established."
+  (unless (and (null erc-nickserv-passwords)
+	       (null erc-prompt-for-nickserv-password))
+    (erc-nickserv-call-identify-function nick)))
+
+(defun erc-nickserv-identify-on-nick-change (nick old-nick)
+  "Identify to Nickserv whenever your nick changes."
+  (unless (and (null erc-nickserv-passwords)
+	       (null erc-prompt-for-nickserv-password))
+    (erc-nickserv-call-identify-function nick)))
+
+(defun erc-nickserv-call-identify-function (nickname)
+  "Call `erc-nickserv-identify' interactively or run it with NICKNAME's
+password.
+The action is determined by the value of `erc-prompt-for-nickserv-password'."
+  (if erc-prompt-for-nickserv-password
+      (call-interactively 'erc-nickserv-identify)
+    (when erc-nickserv-passwords
+      (erc-nickserv-identify
+       (cdr (assoc nickname
+		   (nth 1 (assoc (erc-network)
+				 erc-nickserv-passwords))))))))
+
+;;;###autoload
+(defun erc-nickserv-identify (password)
+  "Send an \"identify <PASSWORD>\" message to NickServ.
+When called interactively, read the password using `read-passwd'."
+  (interactive
+   (list (read-passwd
+	  (format "NickServ password for %s on %s (RET to cancel): "
+		  (erc-current-nick)
+		  (or (and (erc-network)
+			   (symbol-name (erc-network)))
+		      "Unknown network")))))
+  (when (and password (not (string= "" password)))
+    (let* ((erc-auto-discard-away nil)
+	   (network (erc-network))
+	   (nickserv-info (assoc network erc-nickserv-alist))
+	   (nickserv (or (nth 3 nickserv-info) "NickServ"))
+	   (identify-word (or (nth 4 nickserv-info) "IDENTIFY"))
+	   (nick (if (nth 5 nickserv-info)
+		     (concat (erc-current-nick) " ")
+		   ""))
+	   (msgtype (or (nth 6 nickserv-info) "PRIVMSG")))
+      (erc-message msgtype
+		   (concat nickserv " " identify-word " " nick password)))))
+
+(provide 'erc-nickserv)
+
+;;; erc-nickserv.el ends here
+;;
+;; Local Variables:
+;; indent-tabs-mode: t
+;; tab-width: 8
+;; End:
+
+;; arch-tag: d401c8aa-d938-4255-96a9-3efb64c47e58
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lisp/erc/erc-notify.el	Wed Feb 01 10:07:17 2006 +0000
@@ -0,0 +1,254 @@
+;;; erc-notify.el --- Online status change notification
+
+;; Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+
+;; Author: Mario Lang <mlang@lexx.delysid.org>
+;; Keywords: comm
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
+
+;;; Commentary:
+
+;; This module defines a new command, /NOTIFY
+;; See the docstring of `erc-cmd-NOTIFY' for details.
+
+;;; Code:
+
+(require 'erc)
+(require 'erc-nets)
+(eval-when-compile
+ (require 'cl)
+ (require 'pcomplete))
+
+;;;; Customizable variables
+
+(defgroup erc-notify nil
+  "Track online status of certain nicknames."
+  :group 'erc)
+
+(defcustom erc-notify-list nil
+  "*List of nicknames you want to be notified about online/offline
+status change."
+  :group 'erc-notify
+  :type '(repeat string))
+
+(defcustom erc-notify-interval 60
+  "*Time interval (in seconds) for checking online status of notificated
+people."
+  :group 'erc-notify
+  :type 'integer)
+
+(defcustom erc-notify-signon-hook nil
+  "*Hook run after someone on `erc-notify-list' has signed on.
+Two arguments are passed to the function, SERVER and NICK, both
+strings."
+  :group 'erc-notify
+  :type 'hook
+  :options '(erc-notify-signon))
+
+(defcustom erc-notify-signoff-hook nil
+  "*Hook run after someone on `erc-notify-list' has signed off.
+Two arguments are passed to the function, SERVER and NICK, both
+strings."
+  :group 'erc-notify
+  :type 'hook
+  :options '(erc-notify-signoff))
+
+(defun erc-notify-signon (server nick)
+  (message "%s signed on at %s" nick server))
+
+(defun erc-notify-signoff (server nick)
+  (message "%s signed off from %s" nick server))
+
+;;;; Internal variables
+
+(defvar erc-last-ison nil
+  "Last ISON information received through `erc-notify-timer'.")
+(make-variable-buffer-local 'erc-last-ison)
+
+(defvar erc-last-ison-time 0
+  "Last time ISON was sent to the server in `erc-notify-timer'.")
+(make-variable-buffer-local 'erc-last-ison-time)
+
+;;;; Setup
+
+(defun erc-notify-install-message-catalogs ()
+  (erc-define-catalog
+   'english
+   '((notify_current . "Notificated people online: %l")
+     (notify_list    . "Current notify list: %l")
+     (notify_on      . "Detected %n on IRC network %m")
+     (notify_off     . "%n has left IRC network %m"))))
+
+;;;###autoload (autoload 'erc-notify-mode "erc-notify" nil t)
+(define-erc-module notify nil
+  "Periodically check for the online status of certain users and report
+changes."
+  ((add-hook 'erc-timer-hook 'erc-notify-timer)
+   (add-hook 'erc-server-JOIN-functions 'erc-notify-JOIN)
+   (add-hook 'erc-server-NICK-functions 'erc-notify-NICK)
+   (add-hook 'erc-server-QUIT-functions 'erc-notify-QUIT))
+  ((remove-hook 'erc-timer-hook 'erc-notify-timer)
+   (remove-hook 'erc-server-JOIN-functions 'erc-notify-JOIN)
+   (remove-hook 'erc-server-NICK-functions 'erc-notify-NICK)
+   (remove-hook 'erc-server-QUIT-functions 'erc-notify-QUIT)))
+
+;;;; Timer handler
+
+(defun erc-notify-timer (now)
+  (when (and erc-notify-list
+	     (> (erc-time-diff
+		 erc-last-ison-time now)
+		erc-notify-interval))
+    (erc-once-with-server-event
+     303
+     '(let* ((server (erc-response.sender parsed))
+	     (ison-list (delete "" (split-string
+				    (erc-response.contents parsed))))
+	     (new-list ison-list)
+	     (old-list (with-current-buffer (erc-server-buffer)
+			 erc-last-ison)))
+	(while new-list
+	  (when (not (erc-member-ignore-case (car new-list) old-list))
+	    (run-hook-with-args 'erc-notify-signon-hook server (car new-list))
+	    (erc-display-message
+	     parsed 'notice proc
+	     'notify_on ?n (car new-list) ?m (erc-network-name)))
+	  (setq new-list (cdr new-list)))
+	(while old-list
+	  (when (not (erc-member-ignore-case (car old-list) ison-list))
+	    (run-hook-with-args 'erc-notify-signoff-hook server (car old-list))
+	    (erc-display-message
+	     parsed 'notice proc
+	     'notify_off ?n (car old-list) ?m (erc-network-name)))
+	  (setq old-list (cdr old-list)))
+	(setq erc-last-ison ison-list)
+	t))
+    (erc-server-send
+     (concat "ISON " (mapconcat 'identity erc-notify-list " ")))
+    (setq erc-last-ison-time now)))
+
+(defun erc-notify-JOIN (proc parsed)
+  "Check if channel joiner is on `erc-notify-list' and not on `erc-last-ison'.
+If this condition is satisfied, produce a notify_on message and add the nick
+to `erc-last-ison' to prevent any further notifications."
+  (let ((nick (erc-extract-nick (erc-response.sender parsed))))
+    (when (and (erc-member-ignore-case nick erc-notify-list)
+	       (not (erc-member-ignore-case nick erc-last-ison)))
+      (add-to-list 'erc-last-ison nick)
+      (run-hook-with-args 'erc-notify-signon-hook
+			  (or erc-server-announced-name erc-session-server)
+			  nick)
+      (erc-display-message
+       parsed 'notice proc
+       'notify_on ?n nick ?m (erc-network-name)))
+    nil))
+
+(defun erc-notify-NICK (proc parsed)
+  "Check if new nick is on `erc-notify-list' and not on `erc-last-ison'.
+If this condition is satisfied, produce a notify_on message and add the nick
+to `erc-last-ison' to prevent any further notifications."
+  (let ((nick (erc-response.contents parsed)))
+    (when (and (erc-member-ignore-case nick erc-notify-list)
+	       (not (erc-member-ignore-case nick erc-last-ison)))
+      (add-to-list 'erc-last-ison nick)
+      (run-hook-with-args 'erc-notify-signon-hook
+			  (or erc-server-announced-name erc-session-server)
+			  nick)
+      (erc-display-message
+       parsed 'notice proc
+       'notify_on ?n nick ?m (erc-network-name)))
+    nil))
+
+(defun erc-notify-QUIT (proc parsed)
+  "Check if quitter is on `erc-notify-list' and on `erc-last-ison'.
+If this condition is satisfied, produce a notify_off message and remove the
+nick from `erc-last-ison' to prevent any further notifications."
+  (let ((nick (erc-extract-nick (erc-response.sender parsed))))
+    (when (and (erc-member-ignore-case nick erc-notify-list)
+	       (erc-member-ignore-case nick erc-last-ison))
+      (setq erc-last-ison (erc-delete-if `(lambda (el)
+					    (string= ,(erc-downcase nick)
+						     (erc-downcase el)))
+					 erc-last-ison))
+      (run-hook-with-args 'erc-notify-signoff-hook
+			  (or erc-server-announced-name erc-session-server)
+			  nick)
+      (erc-display-message
+       parsed 'notice proc
+       'notify_off ?n nick ?m (erc-network-name)))
+    nil))
+
+;;;; User level command
+
+;;;###autoload
+(defun erc-cmd-NOTIFY (&rest args)
+  "Change `erc-notify-list' or list current notify-list members online.
+Without args, list the current list of notificated people online,
+with args, toggle notify status of people."
+  (cond
+   ((null args)
+    ;; Print current notificated people (online)
+    (let ((ison (with-current-buffer (erc-server-buffer) erc-last-ison)))
+      (if (not ison)
+	  (erc-display-message
+	   nil 'notice 'active "No ison-list yet!")
+	(erc-display-message
+	 nil 'notice 'active
+	 'notify_current ?l ison))))
+   ((string= (car args) "-l")
+    (erc-display-message nil 'notice 'active
+			 'notify_list ?l (mapconcat 'identity erc-notify-list
+						    " ")))
+   (t
+    (while args
+      (if (erc-member-ignore-case (car args) erc-notify-list)
+	  (progn
+	    (setq erc-notify-list (delete (car args) erc-notify-list))
+	    ;; Remove the nick from the value of erc-last-ison in
+	    ;; every server buffer.  This prevents seeing a signoff
+	    ;; notification for a nick that you have just _removed_
+	    ;; from your notify list.
+	    (dolist (buf (erc-buffer-list))
+	      (with-current-buffer buf
+		(if (erc-server-buffer-p)
+		    (setq erc-last-ison (delete (car args) erc-last-ison))))))
+	(setq erc-notify-list (cons (erc-string-no-properties (car args))
+				    erc-notify-list)))
+      (setq args (cdr args)))
+    (erc-display-message
+     nil 'notice 'active
+     'notify_list ?l (mapconcat 'identity erc-notify-list " "))))
+  t)
+
+;;;###autoload
+(defun pcomplete/erc-mode/NOTIFY ()
+  (pcomplete-here (pcomplete-erc-all-nicks)))
+
+(erc-notify-install-message-catalogs)
+
+(provide 'erc-notify)
+
+;;; erc-notify.el ends here
+;;
+;; Local Variables:
+;; indent-tabs-mode: t
+;; tab-width: 8
+;; End:
+
+;; arch-tag: 0fb19dd0-1359-458a-89b7-81dc195a588e
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lisp/erc/erc-page.el	Wed Feb 01 10:07:17 2006 +0000
@@ -0,0 +1,108 @@
+;; erc-page.el - CTCP PAGE support for ERC
+
+;; Copyright (C) 2002, 2004 Free Software Foundation
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
+
+;;; Commentary:
+
+;; Requiring this file will make ERC react to CTCP PAGE messages
+;; received, and it will provide a new /PAGE command to send such
+;; messages yourself.  To enable it, customize the variable
+;; `erc-page-mode'.
+
+;;; Code:
+
+(require 'erc)
+
+;;;###autoload (autoload 'erc-page-mode "erc-page")
+(define-erc-module page ctcp-page
+  "Process CTCP PAGE requests from IRC."
+  nil nil)
+
+(erc-define-catalog-entry 'english 'CTCP-PAGE "Page from %n (%u@%h): %m")
+
+(defgroup erc-page nil
+  "React to CTCP PAGE messages."
+  :group 'erc)
+
+(defcustom erc-page-function nil
+  "A function to process a \"page\" request.
+If nil, this prints the page message in the minibuffer and calls
+`beep'.  If non-nil, it must be a function that takes two arguments:
+SENDER and MSG, both strings.
+
+Example for your ~/.emacs file:
+
+\(setq erc-page-function
+      (lambda (sender msg)
+	(play-sound-file \"/home/alex/elisp/erc/sounds/ni.wav\")
+	(message \"IRC Page from %s: %s\" sender msg)))"
+  :group 'erc-page
+  :type '(choice (const nil)
+		 (function)))
+
+(defcustom erc-ctcp-query-PAGE-hook '(erc-ctcp-query-PAGE)
+  "List of functions to be called when a CTCP PAGE is received.
+This is called from `erc-process-ctcp-query'.  The functions are called
+with six arguments: PROC NICK LOGIN HOST TO MSG.  Note that you can
+also set `erc-page-function' to a function, which only gets two arguments,
+SENDER and MSG, so that might be easier to use."
+  :group 'erc-page
+  :type '(repeat function))
+
+(defun erc-ctcp-query-PAGE (proc nick login host to msg)
+  "Deal with an CTCP PAGE query, if `erc-page-mode' is non-nil.
+This will call `erc-page-function', if defined, or it will just print
+a message and `beep'.  In addition to that, the page message is also
+inserted into the server buffer."
+  (when (and erc-page-mode
+	     (string-match "PAGE\\(\\s-+.*\\)?$" msg))
+    (let* ((m (match-string 1 msg))
+	   (page-msg (if m (erc-controls-interpret (substring m 1))
+		       "[no message]"))
+	   text)
+      (if m (setq m (substring m 1)))
+      (setq text (erc-format-message 'CTCP-PAGE
+				     ?n nick ?u login
+				     ?h host ?m page-msg))
+      (if erc-page-function
+	  (funcall erc-page-function nick page-msg)
+	;; if no function is defined
+	(message "%s" text)
+	(beep))
+      ;; insert text into buffer
+      (erc-display-message
+       nil 'notice nil text)))
+  nil)
+
+(defun erc-cmd-PAGE (line &optional force)
+  "Send a CTCP page to the user given as the first word in LINE.
+The rest of LINE is the message to send.  Note that you will only
+receive pages if `erc-page-mode' is on."
+  (when (string-match "^\\s-*\\(\\S-+\\) ?\\(.*\\)" line)
+    (let ((nick (match-string 1 line))
+	  (msg (match-string 2 line)))
+      (erc-cmd-CTCP nick "PAGE" msg))))
+
+(put 'erc-cmd-PAGE 'do-not-parse-args t)
+
+(provide 'erc-page)
+
+;; arch-tag: 82fd2e0e-6060-4dd2-9788-8c1411e844de
+;;; erc-page.el ends here
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lisp/erc/erc-pcomplete.el	Wed Feb 01 10:07:17 2006 +0000
@@ -0,0 +1,275 @@
+;;; erc-pcomplete.el --- Provides programmable completion for ERC
+
+;; Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+
+;; Author: Sacha Chua <sacha@free.net.ph>
+;; Keywords: comm, convenience
+;; URL: http://www.emacswiki.org/cgi-bin/wiki.pl?ErcCompletion
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
+
+;;; Commentary:
+
+;; This file replaces erc-complete.el.  It provides nick completion
+;; for ERC based on pcomplete.  If you do not have pcomplete, you may
+;; try to use erc-complete.el.
+;;
+;; To use, (require 'erc-auto) or (require 'erc-pcomplete), then
+;;   (erc-pcomplete-mode 1)
+;;
+;; If you want nickname completions ordered such that the most recent
+;; speakers are listed first, set
+;; `erc-pcomplete-order-nickname-completions' to `t'.
+;;
+;; See CREDITS for other contributors.
+;;
+;;; Code:
+
+(require 'pcomplete)
+(require 'erc)
+(require 'erc-compat)
+(require 'time-date)
+(eval-when-compile (require 'cl))
+
+(defgroup erc-pcomplete nil
+  "Programmable completion for ERC"
+  :group 'erc)
+
+(defcustom erc-pcomplete-nick-postfix ": "
+  "*When `pcomplete' is used in the first word after the prompt,
+add this string to nicks completed."
+  :group 'erc-pcomplete
+  :type 'string)
+
+(defcustom erc-pcomplete-order-nickname-completions t
+  "If t, channel nickname completions will be ordered such that
+the most recent speakers are listed first."
+  :group 'erc-pcomplete
+  :type 'boolean)
+
+;;;###autoload (autoload 'erc-completion-mode "erc-pcomplete" nil t)
+(define-erc-module pcomplete Completion
+  "In ERC Completion mode, the TAB key does completion whenever possible."
+  ((add-hook 'erc-mode-hook 'pcomplete-erc-setup)
+   (add-hook 'erc-complete-functions 'erc-pcomplete)
+   (erc-buffer-list #'pcomplete-erc-setup))
+  ((remove-hook 'erc-mode-hook 'pcomplete-erc-setup)
+   (remove-hook 'erc-complete-functions 'erc-pcomplete)))
+
+(defun erc-pcomplete ()
+  "Complete the nick before point."
+  (interactive)
+  (when (> (point) (erc-beg-of-input-line))
+    (let ((last-command (if (eq last-command 'erc-complete-word)
+                            'pcomplete
+                          last-command)))
+      (call-interactively 'pcomplete))
+    t))
+
+;;; Setup function
+
+(defun pcomplete-erc-setup ()
+  "Setup `erc-mode' to use pcomplete."
+  (set (make-local-variable 'pcomplete-ignore-case)
+       t)
+  (set (make-local-variable 'pcomplete-use-paring)
+       nil)
+  (set (make-local-variable 'pcomplete-suffix-list)
+       '(?  ?:))
+  (set (make-local-variable 'pcomplete-parse-arguments-function)
+       'pcomplete-parse-erc-arguments)
+  (set (make-local-variable 'pcomplete-command-completion-function)
+       'pcomplete/erc-mode/complete-command)
+  (set (make-local-variable 'pcomplete-command-name-function)
+       'pcomplete-erc-command-name)
+  (set (make-local-variable 'pcomplete-default-completion-function)
+       (lambda () (pcomplete-here (pcomplete-erc-nicks)))))
+
+;;; Programmable completion logic
+
+(defun pcomplete/erc-mode/complete-command ()
+  (pcomplete-here
+   (append
+    (pcomplete-erc-commands)
+    (pcomplete-erc-nicks erc-pcomplete-nick-postfix))))
+
+(defvar erc-pcomplete-ctcp-commands
+  '("ACTION" "CLIENTINFO" "ECHO" "FINGER" "PING" "TIME" "USERINFO" "VERSION"))
+
+(defun pcomplete/erc-mode/CTCP ()
+  (pcomplete-here (pcomplete-erc-nicks))
+  (pcomplete-here erc-pcomplete-ctcp-commands))
+
+(defun pcomplete/erc-mode/CLEARTOPIC ()
+  (pcomplete-here (pcomplete-erc-channels)))
+
+(defun pcomplete/erc-mode/DEOP ()
+  (while (pcomplete-here (pcomplete-erc-ops))))
+
+(defun pcomplete/erc-mode/DESCRIBE ()
+  (pcomplete-here (pcomplete-erc-nicks)))
+
+(defun pcomplete/erc-mode/IDLE ()
+  (while (pcomplete-here (pcomplete-erc-nicks))))
+
+(defun pcomplete/erc-mode/KICK ()
+  (pcomplete-here (pcomplete-erc-channels))
+  (pcomplete-here (pcomplete-erc-nicks)))
+
+(defun pcomplete/erc-mode/LOAD ()
+  (pcomplete-here (pcomplete-entries)))
+
+(defun pcomplete/erc-mode/MODE ()
+  (pcomplete-here (pcomplete-erc-channels))
+  (while (pcomplete-here (pcomplete-erc-nicks))))
+
+(defun pcomplete/erc-mode/ME ()
+  (while (pcomplete-here (pcomplete-erc-nicks))))
+
+(defun pcomplete/erc-mode/SAY ()
+  (pcomplete-here (pcomplete-erc-nicks))
+  (pcomplete-here (pcomplete-erc-nicks))
+  (while (pcomplete-here (pcomplete-erc-nicks))))
+
+(defun pcomplete/erc-mode/MSG ()
+  (pcomplete-here (append (pcomplete-erc-all-nicks)
+                          (pcomplete-erc-channels)))
+  (while (pcomplete-here (pcomplete-erc-nicks))))
+
+(defun pcomplete/erc-mode/NAMES ()
+  (while (pcomplete-here (pcomplete-erc-channels))))
+
+(defalias 'pcomplete/erc-mode/NOTICE 'pcomplete/erc-mode/MSG)
+
+(defun pcomplete/erc-mode/OP ()
+  (while (pcomplete-here (pcomplete-erc-not-ops))))
+
+(defun pcomplete/erc-mode/PART ()
+  (pcomplete-here (pcomplete-erc-channels)))
+
+(defalias 'pcomplete/erc-mode/LEAVE 'pcomplete/erc-mode/PART)
+
+(defun pcomplete/erc-mode/QUERY ()
+  (pcomplete-here (append (pcomplete-erc-all-nicks)
+                          (pcomplete-erc-channels)))
+  (while (pcomplete-here (pcomplete-erc-nicks)))
+  )
+
+(defun pcomplete/erc-mode/SOUND ()
+  (while (pcomplete-here (pcomplete-entries))))
+
+(defun pcomplete/erc-mode/TOPIC ()
+  (pcomplete-here (pcomplete-erc-channels)))
+
+(defun pcomplete/erc-mode/WHOIS ()
+  (while (pcomplete-here (pcomplete-erc-nicks))))
+
+(defun pcomplete/erc-mode/UNIGNORE ()
+  (pcomplete-here (with-current-buffer (erc-server-buffer) erc-ignore-list)))
+
+;;; Functions that provide possible completions.
+
+(defun pcomplete-erc-commands ()
+  "Returns a list of strings of the defined user commands."
+  (let ((case-fold-search nil))
+    (mapcar (lambda (x)
+              (concat "/" (downcase (substring (symbol-name x) 8))))
+            (apropos-internal "erc-cmd-[A-Z]+"))))
+
+(defun pcomplete-erc-ops ()
+  "Returns a list of nicks with ops."
+  (let (ops)
+    (maphash (lambda (nick cdata)
+               (if (and (cdr cdata)
+                        (erc-channel-user-op (cdr cdata)))
+                   (setq ops (cons nick ops))))
+             erc-channel-users)
+    ops))
+
+(defun pcomplete-erc-not-ops ()
+  "Returns a list of nicks without ops."
+  (let (not-ops)
+    (maphash (lambda (nick cdata)
+               (if (and (cdr cdata)
+                        (not (erc-channel-user-op (cdr cdata))))
+                   (setq not-ops (cons nick not-ops))))
+             erc-channel-users)
+    not-ops))
+
+
+(defun pcomplete-erc-nicks (&optional postfix)
+  "Returns a list of nicks in the current channel."
+  (let ((users (erc-get-channel-user-list)))
+    (if erc-pcomplete-order-nickname-completions
+        (setq users (erc-sort-channel-users-by-activity users)))
+  (mapcar (lambda (x)
+              (concat (erc-server-user-nickname (car x)) postfix))
+            users)))
+
+(defun pcomplete-erc-all-nicks (&optional postfix)
+  "Returns a list of all nicks on the current server."
+  (let (nicks)
+    (with-current-buffer (process-buffer erc-server-process)
+      (maphash (lambda (nick user)
+                 (setq nicks (cons (concat nick postfix) nicks)))
+               erc-server-users))
+      nicks))
+
+(defun pcomplete-erc-channels ()
+  "Returns a list of channels associated with the current server."
+  (mapcar (lambda (buf) (with-current-buffer buf (erc-default-target)))
+          (erc-channel-list erc-server-process)))
+
+;;; Functions for parsing
+
+(defun pcomplete-erc-command-name ()
+  "Returns the command name of the first argument."
+  (if (eq (elt (pcomplete-arg 'first) 0) ?/)
+      (upcase (substring (pcomplete-arg 'first) 1))
+    "SAY"))
+
+(defun pcomplete-parse-erc-arguments ()
+  "Returns a list of parsed whitespace-separated arguments.
+These are the words from the beginning of the line after the prompt
+up to where point is right now."
+  (let* ((start erc-input-marker)
+         (end (point))
+         args beginnings)
+    (save-excursion
+      (if (< (skip-chars-backward " \t\n" start) 0)
+          (setq args '("")
+                beginnings (list end)))
+      (setq end (point))
+      (while (< (skip-chars-backward "^ \t\n" start) 0)
+        (setq beginnings (cons (point) beginnings)
+              args (cons (buffer-substring-no-properties
+                          (point) end)
+                         args))
+        (skip-chars-backward " \t\n" start)
+        (setq end (point))))
+    (cons args beginnings)))
+
+(provide 'erc-pcomplete)
+
+;;; erc-pcomplete.el ends here
+;;
+;; Local Variables:
+;; indent-tabs-mode: nil
+;; End:
+
+;; arch-tag: 32a7703b-be87-45a4-82f3-9eed5a628911
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lisp/erc/erc-replace.el	Wed Feb 01 10:07:17 2006 +0000
@@ -0,0 +1,93 @@
+;; erc-replace.el -- wash and massage messages inserted into the buffer
+
+;; Copyright (C) 2001, 2002, 2004 Free Software Foundation, Inc.
+
+;; Author: Andreas Fuchs <asf@void.at>
+;; Maintainer: Mario Lang (mlang@delysid.org)
+;; Keywords: IRC, client, Internet
+;; URL: http://www.emacswiki.org/cgi-bin/wiki.pl?ErcReplace
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
+
+;;; Commentary:
+
+;; This module allows you to systematically replace text in incoming
+;; messages.  Load erc-replace, and customize `erc-replace-alist'.
+;; Then add to your ~/.emacs:
+
+;; (require 'erc-replace)
+;; (erc-replace-mode 1)
+
+;;; Code:
+
+(require 'erc)
+
+(defgroup erc-replace nil
+  "Replace text from incoming messages"
+  :group 'erc)
+
+(defcustom erc-replace-alist nil
+  "Alist describing text to be replaced in incoming messages.
+This is useful for filters.
+
+The alist has elements of the form (FROM . TO).  FROM can be a regular
+expression or a variable, or any sexp, TO can be a string or a
+function to call, or any sexp.  If a function, it will be called with
+one argument, the string to be replaced, and it should return a
+replacement string."
+  :group 'erc-replace
+  :type '(repeat (cons :tag "Search & Replace"
+		       (choice :tag "From"
+			       regexp
+			       variable
+			       sexp)
+		       (choice :tag "To"
+			       string
+			       function
+			       sexp))))
+
+(defun erc-replace-insert ()
+  "Function to run from `erc-insert-modify-hook'.
+It replaces text according to `erc-replace-alist'."
+  (mapcar (lambda (elt)
+	    (goto-char (point-min))
+	    (let ((from (car elt))
+		  (to (cdr elt)))
+	      (unless (stringp from)
+		(setq from (eval from)))
+	      (while (re-search-forward from nil t)
+		(cond ((stringp to)
+		       (replace-match to))
+		      ((and (symbolp to) (fboundp to))
+		       (replace-match (funcall to (match-string 0))))
+		      (t
+		       (eval to))))))
+	  erc-replace-alist))
+
+;;;###autoload (autoload 'erc-replace-mode "erc-replace")
+(define-erc-module replace nil
+  "This mode replaces incoming text according to `erc-replace-alist'."
+  ((add-hook 'erc-insert-modify-hook
+	     'erc-replace-insert))
+  ((remove-hook 'erc-insert-modify-hook
+		'erc-replace-insert)))
+
+(provide 'erc-replace)
+
+;; arch-tag: dd904a59-d8a6-47f8-ac3a-76b698289a18
+;;; erc-replace.el ends here
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lisp/erc/erc-ring.el	Wed Feb 01 10:07:17 2006 +0000
@@ -0,0 +1,148 @@
+;; erc-ring.el -- Command history handling for erc using ring.el
+
+;; Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+
+;; Author: Alex Schroeder <alex@gnu.org>
+;; Keywords: comm
+;; URL: http://www.emacswiki.org/cgi-bin/wiki.pl?ErcHistory
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
+
+;;; Commentary:
+
+;; This file implements an input ring -- a history of the stuff you
+;; wrote.  To activate:
+;;
+;; (require 'erc-auto) or (require 'erc-ring)
+;; (erc-ring-mode 1)
+;;
+;; Use M-n and M-p to navigate the ring
+
+;;; Code:
+
+(require 'erc)
+(require 'comint)
+(require 'ring)
+
+;;;###autoload (autoload 'erc-ring-mode "erc-ring" nil t)
+(define-erc-module ring nil
+  "Stores input in a ring so that previous commands and messages can
+be recalled using M-p and M-n."
+  ((add-hook 'erc-send-pre-hook 'erc-add-to-input-ring)
+   (define-key erc-mode-map "\M-p" 'erc-previous-command)
+   (define-key erc-mode-map "\M-n" 'erc-next-command))
+  ((remove-hook 'erc-send-pre-hook 'erc-add-to-input-ring)
+   (define-key erc-mode-map "\M-p" 'undefined)
+   (define-key erc-mode-map "\M-n" 'undefined)))
+
+(defvar erc-input-ring nil "Input ring for erc.")
+(make-variable-buffer-local 'erc-input-ring)
+
+(defvar erc-input-ring-index nil
+  "Position in the input ring for erc.
+If nil, the input line is blank and the user is conceptually 'after'
+the most recently added item in the ring. If an integer, the input
+line is non-blank and displays the item from the ring indexed by this
+variable.")
+(make-variable-buffer-local 'erc-input-ring-index)
+
+(defun erc-input-ring-setup ()
+  "Do the setup required so that we can use comint style input rings.
+Call this function when setting up the mode."
+  (setq erc-input-ring (make-ring comint-input-ring-size))
+  (setq erc-input-ring-index nil))
+
+(defun erc-add-to-input-ring (s)
+  "Add string S to the input ring and reset history position."
+  (unless erc-input-ring (erc-input-ring-setup))
+  (ring-insert erc-input-ring s)
+  (setq erc-input-ring-index nil))
+
+(defun erc-clear-input-ring ()
+  "Remove all entries from the input ring, then call garbage-collect.
+You might use this for security purposes if you have typed a command
+containing a password."
+  (interactive)
+  (setq erc-input-ring (make-ring comint-input-ring-size)
+        erc-input-ring-index nil)
+  (garbage-collect)
+  (message "ERC input ring cleared."))
+
+(defun erc-previous-command ()
+  "Replace current command with the previous one from the history."
+  (interactive)
+  (unless erc-input-ring (erc-input-ring-setup))
+  ;; if the ring isn't empty
+  (when (> (ring-length erc-input-ring) 0)
+    (if (and erc-input-ring-index
+             (= (ring-length erc-input-ring) (1+ erc-input-ring-index)))
+        (progn
+          (erc-replace-current-command "")
+          (setq erc-input-ring-index nil))
+
+      ;; If we are not viewing old input and there's text in the input
+      ;; area, push it on the history ring before moving back through
+      ;; the input history, so it will be there when we return to the
+      ;; front.
+      (if (null erc-input-ring-index)
+          (when (> (point-max) erc-input-marker)
+            (erc-add-to-input-ring (buffer-substring erc-input-marker
+                                                     (point-max)))
+            (setq erc-input-ring-index 0)))
+
+      (setq erc-input-ring-index (if erc-input-ring-index
+                                     (ring-plus1 erc-input-ring-index
+                                                 (ring-length erc-input-ring))
+                                   0))
+      (erc-replace-current-command (ring-ref erc-input-ring
+                                             erc-input-ring-index)))))
+
+(defun erc-next-command ()
+  "Replace current command with the next one from the history."
+  (interactive)
+  (unless erc-input-ring (erc-input-ring-setup))
+  ;; if the ring isn't empty
+  (when (> (ring-length erc-input-ring) 0)
+    (if (and erc-input-ring-index
+             (= 0 erc-input-ring-index))
+        (progn
+          (erc-replace-current-command "")
+          (setq erc-input-ring-index nil))
+      (setq erc-input-ring-index (ring-minus1 (or erc-input-ring-index 0)
+                                              (ring-length erc-input-ring)))
+      (erc-replace-current-command (ring-ref erc-input-ring
+      erc-input-ring-index)))))
+
+
+(defun erc-replace-current-command (s)
+  "Replace current command with string S."
+  ;; delete line
+  (let ((inhibit-read-only t))
+    (delete-region
+     (progn (goto-char erc-insert-marker) (erc-bol))
+     (goto-char (point-max)))
+    (insert s)))
+
+(provide 'erc-ring)
+
+;;; erc-ring.el ends here
+;; Local Variables:
+;; indent-tabs-mode: nil
+;; End:
+
+;; arch-tag: b77924a8-a80e-489d-84cd-b351761ea5c8
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lisp/erc/erc-sound.el	Wed Feb 01 10:07:17 2006 +0000
@@ -0,0 +1,149 @@
+;;; erc-sound.el --- CTCP SOUND support for ERC
+
+;; Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
+
+;;; Commentary:
+
+;; This used to be in erc.el, I (Jorgen) just extracted it from there
+;; and put it in this file.  Bugs and features are those of the
+;; original author.
+
+;;; Code:
+
+(require 'erc)
+
+;;;###autoload (autoload 'erc-sound-mode "erc-sound")
+(define-erc-module sound ctcp-sound
+  "In ERC sound mode, the client will respond to CTCP SOUND requests
+and play sound files as requested."
+  ;; Enable:
+  ((define-key erc-mode-map "\C-c\C-s" 'erc-toggle-sound))
+  ;; Disable:
+  ((define-key erc-mode-map "\C-c\C-s" 'undefined)))
+
+(erc-define-catalog-entry 'english 'CTCP-SOUND "%n (%u@%h) plays %s:%m")
+
+(defgroup erc-sound nil
+  "Make ERC play bells and whistles while chatting with people."
+  :group 'erc)
+
+(defcustom erc-play-sound t
+  "*Play sound on SOUND ctcp requests (used in ICQ chat)."
+  :group 'erc-sound
+  :type 'boolean)
+
+(defcustom erc-sound-path nil
+  "List of directories that contain sound samples to play on SOUND events."
+  :group 'erc-sound
+  :type '(repeat directory))
+
+(defcustom erc-default-sound nil
+  "Play this sound if the requested file was not found."
+  :group 'erc-sound
+  :type '(choice (const nil)
+		 file))
+
+(defcustom erc-play-command "play"
+  "Command for playing sound samples."
+  :group 'erc-sound
+  :type 'string)
+
+(defun erc-cmd-SOUND (line &optional force)
+  "Play the sound given in LINE."
+  (cond
+   ((string-match "^\\s-*\\(\\S-+\\)\\(\\s-.*\\)?$" line)
+    (let ((file (match-string 1 line))
+	  (msg (match-string 2 line))
+	  (tgt (erc-default-target)))
+      (if (null msg)
+	  (setq msg "")
+	;; remove the first white space
+	(setq msg (substring msg 1)))
+      (if tgt
+	  (progn
+	    (erc-send-ctcp-message tgt (format "SOUND %s %s" file msg) force)
+	    (if erc-play-sound (erc-play-sound file)))
+	(erc-display-message nil 'error (current-buffer) 'no-target))
+      t))
+   (t nil)))
+
+(defvar erc-ctcp-query-SOUND-hook '(erc-ctcp-query-SOUND))
+(defun erc-ctcp-query-SOUND (proc nick login host to msg)
+  (when (string-match "^SOUND\\s-+\\(\\S-+\\)\\(\\(\\s-+.*\\)\\|\\(\\s-*\\)\\)$" msg)
+    (let ((sound (match-string 1 msg))
+	  (comment (match-string 2 msg)))
+      (when erc-play-sound (erc-play-sound sound))
+      (erc-display-message
+       nil 'notice nil
+       'CTCP-SOUND ?n nick ?u login ?h host ?s sound ?m comment)))
+  nil)
+
+(defun erc-play-sound (file)
+  "Plays a sound file located in one of the directories in `erc-sound-path'
+with a command `erc-play-command'."
+  (let ((filepath (erc-find-file file erc-sound-path)))
+    (if (and (not filepath) erc-default-sound)
+	(setq filepath erc-default-sound))
+    (cond ((and filepath (file-exists-p filepath))
+	   (if (and (fboundp 'device-sound-enabled-p)
+		    (device-sound-enabled-p))
+	       ; For XEmacs
+	       (play-sound-file filepath)
+;	     (start-process "erc-sound" nil erc-play-command filepath)
+	     (start-process "erc-sound" nil "/bin/tcsh"  "-c"
+			    (concat erc-play-command " " filepath))))
+	  (t (beep)))
+    (erc-log (format "Playing sound file %S" filepath))))
+
+;(defun erc-play-sound (file)
+;  "Plays a sound file located in one of the directories in `erc-sound-path'
+;   with a command `erc-play-command'."
+;  (let ((filepath nil)
+;	(paths erc-sound-path))
+;    (while (and paths
+;		(progn (setq filepath (expand-file-name file (car paths)))
+;		       (not (file-exists-p filepath))))
+;      (setq paths (cdr paths)))
+;    (if (and (not (and filepath (file-exists-p filepath)))
+;	     erc-default-sound)
+;	(setq filepath erc-default-sound))
+;    (cond ((and filepath (file-exists-p filepath))
+;;	   (start-process "erc-sound" nil erc-play-command filepath)
+;	   (start-process "erc-sound" nil "/bin/tcsh"  "-c"
+;			  (concat erc-play-command " " filepath))
+;	   )
+;	  (t (beep)))
+;    (erc-log (format "Playing sound file %S" filepath))))
+
+(defun erc-toggle-sound (&optional arg)
+  "Toggles playing sounds on and off.  With positive argument,
+  turns them on.  With any other argument turns sounds off."
+  (interactive "P")
+  (cond ((and (numberp arg) (> arg 0))
+	 (setq erc-play-sound t))
+	(arg (setq erc-play-sound nil))
+	(t (setq erc-play-sound (not erc-play-sound))))
+  (message "ERC sound is %s" (if erc-play-sound "ON" "OFF")))
+
+
+(provide 'erc-sound)
+
+;; arch-tag: 53657d1d-007f-4a20-91c1-588e71cf0cee
+;;; erc-sound.el ends here
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lisp/erc/erc-speedbar.el	Wed Feb 01 10:07:17 2006 +0000
@@ -0,0 +1,370 @@
+;;; erc-speedbar.el --- Speedbar support for ERC
+
+;; Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+
+;; Author: Mario Lang <mlang@delysid.org>
+;; Contributor: Eric M. Ludlam <eric@siege-engine.com>
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
+
+;;; Commentary:
+
+;; This module provides integration of ERC into the Speedbar.
+
+;;; TODO / ideas:
+
+;; * Write intelligent update function:
+;;   update-channel, update-nick, remove-nick-from-channel, ...
+;; * Use indicator-strings for op/voice
+;; * Extract/convert face notes field from bbdb if available and show
+;;   it using sb-image.el
+;;
+;;; Code:
+
+(require 'erc)
+(require 'speedbar)
+(condition-case nil (require 'dframe) (error nil))
+(eval-when-compile (require 'cl))
+
+;;; Customization:
+
+(defgroup erc-speedbar nil
+  "Integration of ERC in the Speedbar"
+  :group 'erc)
+
+(defcustom erc-speedbar-sort-users-type 'activity
+  "How channel nicknames are sorted.
+
+'activity     - Sort users by channel activity
+'alphabetical - Sort users alphabetically
+nil           - Do not sort users"
+  :group 'erc-speedbar
+  :type '(choice (const :tag "Sort users by channel activity" activity)
+		 (const :tag "Sort users alphabetically" alphabetical)
+		 (const :tag "Do not sort users" nil)))
+
+(defvar erc-speedbar-key-map nil
+  "Keymap used when in erc display mode.")
+
+(defun erc-install-speedbar-variables ()
+  "Install those variables used by speedbar to enhance ERC."
+  (if erc-speedbar-key-map
+      nil
+    (setq erc-speedbar-key-map (speedbar-make-specialized-keymap))
+
+    ;; Basic tree features
+    (define-key erc-speedbar-key-map "e" 'speedbar-edit-line)
+    (define-key erc-speedbar-key-map "\C-m" 'speedbar-edit-line)
+    (define-key erc-speedbar-key-map "+" 'speedbar-expand-line)
+    (define-key erc-speedbar-key-map "=" 'speedbar-expand-line)
+    (define-key erc-speedbar-key-map "-" 'speedbar-contract-line))
+
+  (speedbar-add-expansion-list '("ERC" erc-speedbar-menu-items
+				 erc-speedbar-key-map
+				 erc-speedbar-server-buttons))
+  (speedbar-add-mode-functions-list
+   '("ERC" (speedbar-item-info . erc-speedbar-item-info))))
+
+(defvar erc-speedbar-menu-items
+  '(["Goto buffer" speedbar-edit-line t]
+    ["Expand Node" speedbar-expand-line
+     (save-excursion (beginning-of-line)
+		     (looking-at "[0-9]+: *.\\+. "))]
+    ["Contract Node" speedbar-contract-line
+     (save-excursion (beginning-of-line)
+		     (looking-at "[0-9]+: *.-. "))])
+  "Additional menu-items to add to speedbar frame.")
+
+;; Make sure our special speedbar major mode is loaded
+(if (featurep 'speedbar)
+    (erc-install-speedbar-variables)
+  (add-hook 'speedbar-load-hook 'erc-install-speedbar-variables))
+
+;;; ERC hierarchy display method
+;;;###autoload
+(defun erc-speedbar-browser ()
+  "Initialize speedbar to display an ERC browser.
+This will add a speedbar major display mode."
+  (interactive)
+  (require 'speedbar)
+  ;; Make sure that speedbar is active
+  (speedbar-frame-mode 1)
+  ;; Now, throw us into Info mode on speedbar.
+  (speedbar-change-initial-expansion-list "ERC")
+  (speedbar-get-focus))
+
+(defun erc-speedbar-buttons (buffer)
+  "Create buttons for speedbar in BUFFER."
+  (erase-buffer)
+  (let (serverp chanp queryp)
+    (with-current-buffer buffer
+      (setq serverp (eq buffer (process-buffer erc-server-process)))
+      (setq chanp (erc-channel-p (erc-default-target)))
+      (setq queryp (erc-query-buffer-p)))
+    (cond (serverp
+	   (erc-speedbar-channel-buttons nil 0 buffer))
+	  (chanp
+	   (erc-speedbar-insert-target buffer 0)
+	   (forward-line -1)
+	   (erc-speedbar-expand-channel "+" buffer 0))
+	  (queryp
+	   (erc-speedbar-insert-target buffer 0))
+	  (t (ignore)))))
+
+(defun erc-speedbar-server-buttons (directory depth)
+  "Insert the initial list of servers you are connected to."
+  (let ((servers (erc-buffer-list
+		  (lambda ()
+		    (eq (current-buffer)
+			(process-buffer erc-server-process))))))
+    (when servers
+      (speedbar-with-writable
+	(dolist (server servers)
+	  (speedbar-make-tag-line
+	   'bracket ?+ 'erc-speedbar-expand-server server
+	   (buffer-name server) 'erc-speedbar-goto-buffer server nil
+	   depth))
+	t))))
+
+(defun erc-speedbar-expand-server (text server indent)
+  (cond ((string-match "+" text)
+	 (speedbar-change-expand-button-char ?-)
+	 (if (speedbar-with-writable
+	       (save-excursion
+		 (end-of-line) (forward-char 1)
+		 (erc-speedbar-channel-buttons nil (1+ indent) server)))
+	     (speedbar-change-expand-button-char ?-)
+	   (speedbar-change-expand-button-char ??)))
+	((string-match "-" text)	;we have to contract this node
+	 (speedbar-change-expand-button-char ?+)
+	 (speedbar-delete-subblock indent))
+	(t (error "Ooops... not sure what to do")))
+  (speedbar-center-buffer-smartly))
+
+(defun erc-speedbar-channel-buttons (directory depth server-buffer)
+  (when (get-buffer server-buffer)
+    (let* ((proc (with-current-buffer server-buffer erc-server-process))
+	   (targets (erc-buffer-list
+		     (lambda ()
+		       (not (eq (process-buffer erc-server-process)
+				(current-buffer))))
+		     proc)))
+      (when targets
+	(speedbar-with-writable
+	  (dolist (target targets)
+	    (erc-speedbar-insert-target target depth))
+	  t)))))
+
+(defun erc-speedbar-insert-target (buffer depth)
+  (if (with-current-buffer buffer
+	(erc-channel-p (erc-default-target)))
+      (speedbar-make-tag-line
+       'bracket ?+ 'erc-speedbar-expand-channel buffer
+       (buffer-name buffer) 'erc-speedbar-goto-buffer buffer nil
+       depth)
+    ;; Query target
+    (speedbar-make-tag-line
+     nil nil nil nil
+     (buffer-name buffer) 'erc-speedbar-goto-buffer buffer nil
+     depth)))
+
+(defun erc-speedbar-expand-channel (text channel indent)
+  "For the line matching TEXT, in CHANNEL, expand or contract a line.
+INDENT is the current indentation level."
+  (cond
+   ((string-match "+" text)
+    (speedbar-change-expand-button-char ?-)
+    (speedbar-with-writable
+     (save-excursion
+       (end-of-line) (forward-char 1)
+       (let ((modes (with-current-buffer channel
+		      (concat (apply 'concat
+				     erc-channel-modes)
+			      (cond
+			       ((and erc-channel-user-limit
+				     erc-channel-key)
+				(if erc-show-channel-key-p
+				    (format "lk %.0f %s"
+					    erc-channel-user-limit
+					    erc-channel-key)
+				  (format "kl %.0f" erc-channel-user-limit)))
+			       (erc-channel-user-limit
+				;; Emacs has no bignums
+				(format "l %.0f" erc-channel-user-limit))
+			       (erc-channel-key
+				(if erc-show-channel-key-p
+				    (format "k %s" erc-channel-key)
+				  "k"))
+			       (t "")))))
+	     (topic (erc-controls-interpret
+		     (with-current-buffer channel erc-channel-topic))))
+	 (speedbar-make-tag-line
+	  'angle ?i nil nil
+	  (concat "Modes: +" modes) nil nil nil
+	  (1+ indent))
+	 (unless (string= topic "")
+	   (speedbar-make-tag-line
+	    'angle ?i nil nil
+	    (concat "Topic: " topic) nil nil nil
+	    (1+ indent)))
+	 (let ((names (cond ((eq erc-speedbar-sort-users-type 'alphabetical)
+			     (erc-sort-channel-users-alphabetically
+			      (with-current-buffer channel
+				(erc-get-channel-user-list))))
+			    ((eq erc-speedbar-sort-users-type 'activity)
+			     (erc-sort-channel-users-by-activity
+			      (with-current-buffer channel
+				(erc-get-channel-user-list))))
+			    (t (with-current-buffer channel
+				 (erc-get-channel-user-list))))))
+	   (when names
+	     (speedbar-with-writable
+	      (dolist (entry names)
+		(erc-speedbar-insert-user entry ?+ (1+ indent))))))))))
+   ((string-match "-" text)
+    (speedbar-change-expand-button-char ?+)
+    (speedbar-delete-subblock indent))
+   (t (error "Ooops... not sure what to do")))
+  (speedbar-center-buffer-smartly))
+
+(defun erc-speedbar-insert-user (entry exp-char indent)
+  "Insert one user based on the channel member list ENTRY.
+EXP-CHAR is the expansion character to use.
+INDENT is the current indentation level."
+  (let* ((user (car entry))
+	 (cuser (cdr entry))
+	 (nick (erc-server-user-nickname user))
+	 (host (erc-server-user-host user))
+	 (info (erc-server-user-info user))
+	 (login (erc-server-user-login user))
+	 (name (erc-server-user-full-name user))
+	 (voice (and cuser (erc-channel-user-voice cuser)))
+	 (op (and cuser (erc-channel-user-op cuser)))
+	 (nick-str (concat (if op "@" "") (if voice "+" "") nick))
+	 (finger (concat login (when (or login host) "@") host))
+	 (sbtoken (list finger name info)))
+    (if (or login host name info) ; we want to be expandable
+	(speedbar-make-tag-line
+	 'bracket ?+ 'erc-speedbar-expand-user sbtoken
+	 nick-str nil sbtoken nil
+	 indent)
+      (when (equal exp-char ?-)
+	(forward-line -1)
+	(erc-speedbar-expand-user "+" (list finger name info) indent))
+      (speedbar-make-tag-line
+       'statictag ?? nil nil
+       nick-str nil nil nil
+       indent))))
+
+(defun erc-speedbar-update-channel (buffer)
+  "Update the speedbar information about a ERC buffer. The update
+is only done when the channel is actually expanded already."
+  ;; This is only a rude hack and doesn't care about multiserver usage
+  ;; yet, consider this a brain storming, better ideas?
+  (with-current-buffer speedbar-buffer
+    (save-excursion
+      (goto-char (point-min))
+      (when (re-search-forward (concat "^1: *.+. *"
+				       (regexp-quote (buffer-name buffer)))
+			       nil t)
+	(beginning-of-line)
+	(speedbar-delete-subblock 1)
+	(erc-speedbar-expand-channel "+" buffer 1)))))
+
+(defun erc-speedbar-expand-user (text token indent)
+  (cond ((string-match "+" text)
+	 (speedbar-change-expand-button-char ?-)
+	 (speedbar-with-writable
+	   (save-excursion
+	     (end-of-line) (forward-char 1)
+	     (let ((finger (nth 0 token))
+		   (name (nth 1 token))
+		   (info (nth 2 token)))
+	       (when finger
+		 (speedbar-make-tag-line
+		  nil nil nil nil
+		  finger nil nil nil
+		  (1+ indent)))
+	       (when name
+		 (speedbar-make-tag-line
+		  nil nil nil nil
+		  name nil nil nil
+		  (1+ indent)))
+	       (when info
+		 (speedbar-make-tag-line
+		  nil nil nil nil
+		  info nil nil nil
+		  (1+ indent)))))))
+	((string-match "-" text)
+	 (speedbar-change-expand-button-char ?+)
+	 (speedbar-delete-subblock indent))
+	(t (error "Ooops... not sure what to do")))
+  (speedbar-center-buffer-smartly))
+
+(defun erc-speedbar-goto-buffer (text buffer indent)
+  "When user clicks on TEXT, goto an ERC buffer.
+The INDENT level is ignored."
+  (if (featurep 'dframe)
+      (progn
+	(dframe-select-attached-frame speedbar-frame)
+	(let ((bwin (get-buffer-window buffer 0)))
+	  (if bwin
+	      (progn
+		(select-window bwin)
+		(raise-frame (window-frame bwin)))
+	    (if dframe-power-click
+		(let ((pop-up-frames t))
+		  (select-window (display-buffer buffer)))
+	      (dframe-select-attached-frame speedbar-frame)
+	      (switch-to-buffer buffer)))))
+    (let ((bwin (get-buffer-window buffer 0)))
+      (if bwin
+	  (progn
+	    (select-window bwin)
+	    (raise-frame (window-frame bwin)))
+	(if speedbar-power-click
+	    (let ((pop-up-frames t)) (select-window (display-buffer buffer)))
+	  (dframe-select-attached-frame speedbar-frame)
+	  (switch-to-buffer buffer))))))
+
+(defun erc-speedbar-line-text ()
+  "Return the text for the item on the current line."
+  (beginning-of-line)
+  (when (re-search-forward "[]>] " nil t)
+    (buffer-substring-no-properties (point) (point-at-eol))))
+
+(defun erc-speedbar-item-info ()
+  "Display information about the current buffer on the current line."
+  (let ((data (speedbar-line-token))
+	(txt (erc-speedbar-line-text)))
+    (cond ((and data (listp data))
+	   (message "%s: %s" txt (car data)))
+	  ((bufferp data)
+	   (message "Channel: %s" txt))
+	  (t
+	   (message "%s" txt)))))
+
+(provide 'erc-speedbar)
+;;; erc-speedbar.el ends here
+;;
+;; Local Variables:
+;; indent-tabs-mode: t
+;; tab-width: 8
+;; End:
+
+;; arch-tag: 7a6558a4-3308-4bf5-a284-e1d042c933c6
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lisp/erc/erc-spelling.el	Wed Feb 01 10:07:17 2006 +0000
@@ -0,0 +1,93 @@
+;;; erc-spelling.el --- use flyspell in ERC
+
+;; Copyright (C) 2005, 2006  Free Software Foundation, Inc.
+
+;; Author: Jorgen Schaefer <forcer@forcix.cx>
+;; Keywords: irc
+;; URL: http://www.emacswiki.org/cgi-bin/wiki.pl?ErcSpelling
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
+
+;;; Commentary:
+
+;; This is an ERC module to enable flyspell mode in ERC buffers. This
+;; ensures correct behavior of flyspell, and even sets up a
+;; channel-local dictionary if so required.
+
+;;; Code:
+
+(require 'erc)
+(require 'flyspell)
+
+;;;###autoload (autoload 'erc-spelling-mode "erc-spelling" nil t)
+(define-erc-module spelling nil
+  "Enable flyspell mode in ERC buffers."
+  ;; Use erc-connect-pre-hook instead of erc-mode-hook as pre-hook is
+  ;; called AFTER the server buffer is initialized.
+  ((add-hook 'erc-connect-pre-hook 'erc-spelling-init)
+   (mapc (lambda (buffer)
+           (with-current-buffer buffer (erc-spelling-init)))
+         (erc-buffer-list)))
+  ((remove-hook 'erc-connect-pre-hook 'erc-spelling-init)
+   (mapc (lambda (buffer)
+           (with-current-buffer buffer (flyspell-mode 0)))
+         (erc-buffer-list))))
+
+(defcustom erc-spelling-dictionaries nil
+  "An alist mapping buffer names to dictionaries.
+The `car' of every cell is a buffer name, the `cadr' is the
+string name of an associated dictionary.
+The dictionary is inherited from server buffers, so if you want a
+default dictionary for some server, you can use a server buffer
+name here."
+  :type '(choice (const nil)
+                 (repeat (cons (string :tag "Buffer name")
+                               (string :tag "Dictionary"))))
+  :group 'erc-spelling)
+
+(defun erc-spelling-init ()
+  "Enable flyspell mode in an ERC buffer."
+  (let ((name (downcase (buffer-name)))
+        (dicts erc-spelling-dictionaries))
+    (while (and dicts
+                (not (string= name (downcase (caar dicts)))))
+      (setq dicts (cdr dicts)))
+    (setq ispell-local-dictionary
+          (if dicts
+              (cadr (car dicts))
+            (let ((server (erc-server-buffer)))
+              (if server
+                  (with-current-buffer server
+                    ispell-local-dictionary)
+                nil)))))
+  (setq flyspell-generic-check-word-p 'erc-spelling-flyspell-verify)
+  (flyspell-mode 1))
+
+(put 'erc-mode
+     'flyspell-mode-predicate
+     'erc-spelling-flyspell-verify)
+
+(defun erc-spelling-flyspell-verify ()
+  "Flyspell only the input line, nothing else."
+  (> (point)
+     erc-input-marker))
+
+(provide 'erc-spelling)
+
+;; arch-tag: 04ae1c46-0fd1-4e1a-8b80-55bfa471c945
+;;; erc-spelling.el ends here
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lisp/erc/erc-stamp.el	Wed Feb 01 10:07:17 2006 +0000
@@ -0,0 +1,341 @@
+;;; erc-stamp.el --- Timestamping for Emacs IRC CLient
+
+;; Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+
+;; Author: Mario Lang <mlang@delysid.org>
+;; Keywords: comm, processes, timestamp
+;; URL: http://www.emacswiki.org/cgi-bin/wiki.pl?ErcStamp
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
+
+;;; Commentary:
+
+;; The code contained in this module is responsible for inserting
+;; timestamps into ERC buffers.  In order to actually activate this,
+;; you must call `erc-timestamp-mode'.
+
+;; You can choose between two different ways of inserting timestamps.
+;; Customize `erc-insert-timestamp-function' and
+;; `erc-insert-away-timestamp-function'.
+
+;;; Code:
+
+(require 'erc)
+(require 'erc-compat)
+
+(defgroup erc-stamp nil
+  "For long conversation on IRC it is sometimes quite
+useful to have individual messages timestamp.  This
+group provides settings related to the format and display
+of timestamp information in `erc-mode' buffer.
+
+For timestamping to be activated, you just need to load `erc-stamp'
+in your .emacs file or interactively using `load-library'."
+  :group 'erc)
+
+(defcustom erc-timestamp-format "[%H:%M]"
+  "*If set to a string, messages will be timestamped.
+This string is processed using `format-time-string'.
+Good examples are \"%T\" and \"%H:%M\".
+
+If nil, timestamping is turned off."
+  :group 'erc-stamp
+  :type '(choice (const nil)
+		 (string)))
+
+(defcustom erc-insert-timestamp-function 'erc-insert-timestamp-right
+  "*Function to use to insert timestamps.
+
+It takes a single argument STRING which is the final string
+which all text-properties already appended.  This function only cares about
+inserting this string at the right position.  Narrowing is in effect
+while it is called, so (point-min) and (point-max) determine the region to
+operate on."
+  :group 'erc-stamp
+  :type '(choice (const :tag "Right" erc-insert-timestamp-right)
+		 (const :tag "Left" erc-insert-timestamp-left)
+		 function))
+
+(defcustom erc-away-timestamp-format "<%H:%M>"
+  "*Timestamp format used when marked as being away.
+
+If nil, timestamping is turned off when away unless `erc-timestamp-format'
+is set.
+
+If `erc-timestamp-format' is set, this will not be used."
+  :group 'erc-stamp
+  :type '(choice (const nil)
+		 (string)))
+
+(defcustom erc-insert-away-timestamp-function 'erc-insert-timestamp-right
+  "*Function to use to insert the away timestamp.
+
+See `erc-insert-timestamp-function' for details."
+  :group 'erc-stamp
+  :type '(choice (const :tag "Right" erc-insert-timestamp-right)
+		 (const :tag "Left" erc-insert-timestamp-left)
+		 function))
+
+(defcustom erc-hide-timestamps nil
+  "*If non-nil, timestamps will be invisible.
+
+This is useful for logging, because, although timestamps will be
+hidden, they will still be present in the logs."
+  :group 'erc-stamp
+  :type 'boolean)
+
+(defcustom erc-echo-timestamps nil
+  "*If non-nil, print timestamp in the minibuffer when point is moved.
+Using this variable, you can turn off normal timestamping,
+and simply move point to an irc message to see its timestamp
+printed in the minibuffer."
+  :group 'erc-stamp
+  :type 'boolean)
+
+(defcustom erc-echo-timestamp-format "Timestamped %A, %H:%M:%S"
+  "*Format string to be used when `erc-echo-timestamps' is non-nil.
+This string specifies the format of the timestamp being echoed in
+the minibuffer."
+  :group 'erc-stamp
+  :type 'string)
+
+(defcustom erc-timestamp-intangible t
+  "*Whether the timestamps should be intangible, i.e. prevent the point
+from entering them and instead jump over them."
+  :group 'erc-stamp
+  :type 'boolean)
+
+(defface erc-timestamp-face '((t (:bold t :foreground "green")))
+  "ERC timestamp face."
+  :group 'erc-faces)
+
+;;;###autoload (autoload 'erc-timestamp-mode "erc-stamp" nil t)
+(define-erc-module stamp timestamp
+  "This mode timestamps messages in the channel buffers."
+  ((add-hook 'erc-mode-hook 'erc-munge-invisibility-spec)
+   (add-hook 'erc-insert-modify-hook 'erc-add-timestamp t)
+   (add-hook 'erc-send-modify-hook 'erc-add-timestamp t))
+  ((remove-hook 'erc-mode-hook 'erc-munge-invisibility-spec)
+   (remove-hook 'erc-insert-modify-hook 'erc-add-timestamp)
+   (remove-hook 'erc-send-modify-hook 'erc-add-timestamp)))
+
+(defun erc-add-timestamp ()
+  "Add timestamp and text-properties to message.
+
+This function is meant to be called from `erc-insert-modify-hook'
+or `erc-send-modify-hook'."
+  (unless (get-text-property (point) 'invisible)
+    (let ((ct (current-time)))
+      (if (fboundp erc-insert-timestamp-function)
+	  (funcall erc-insert-timestamp-function
+		   (erc-format-timestamp ct erc-timestamp-format))
+	(error "Timestamp function unbound"))
+      (when (and (fboundp erc-insert-away-timestamp-function)
+		 erc-away-timestamp-format
+		 (with-current-buffer (erc-server-buffer) erc-away)
+		 (not erc-timestamp-format))
+	(funcall erc-insert-away-timestamp-function
+		 (erc-format-timestamp ct erc-away-timestamp-format)))
+      (add-text-properties (point-min) (point-max)
+			   (list 'timestamp ct))
+      (add-text-properties (point-min) (point-max)
+			   (list 'point-entered 'erc-echo-timestamp)))))
+
+(defvar erc-timestamp-last-inserted nil
+  "Last timestamp inserted into the buffer.")
+(make-variable-buffer-local 'erc-timestamp-last-inserted)
+
+(defcustom erc-timestamp-only-if-changed-flag t
+  "*Insert timestamp only if its value changed since last insertion.
+If `erc-insert-timestamp-function' is `erc-insert-timestamp-left', a
+string of spaces which is the same size as the timestamp is added to
+the beginning of the line in its place. If you use
+`erc-insert-timestamp-right', nothing gets inserted in place of the
+timestamp."
+  :group 'erc-stamp
+  :type 'boolean)
+
+(defcustom erc-timestamp-right-column nil
+  "*If non-nil, the column at which the timestamp is inserted,
+if the timestamp is to be printed to the right.  If nil,
+`erc-insert-timestamp-right' will use other means to determine
+the correct column."
+  :group 'erc-stamp
+  :type '(choice
+	  (integer :tag "Column number")
+	  (const :tag "Unspecified" nil)))
+
+(defcustom erc-timestamp-right-align-by-pixel nil
+  "*If non-nil, insert the right timestamp based on a pixel value.
+This is needed when variable-width text precedes a timestamp.
+Unfortunately, it only works in Emacs 22 and when using the X
+Window System."
+  :group 'erc-stamp
+  :type 'boolean)
+
+(defun erc-insert-timestamp-left (string)
+  "Insert timestamps at the beginning of the line."
+  (goto-char (point-min))
+  (let* ((ignore-p (and erc-timestamp-only-if-changed-flag
+			(string-equal string erc-timestamp-last-inserted)))
+	 (len (length string))
+	 (s (if ignore-p (make-string len ? ) string)))
+    (unless ignore-p (setq erc-timestamp-last-inserted string))
+    (erc-put-text-property 0 len 'field 'erc-timestamp s)
+    (insert s)))
+
+(defun erc-insert-aligned (string pos &optional fallback)
+  "Insert STRING based on a fraction of the width of the buffer.
+Fraction is roughly (/ POS (window-width)).
+
+If `erc-timestamp-right-align-by-pixel' is nil, use
+\(- POS FALLBACK) to determine how many spaces to insert."
+  (if (not erc-timestamp-right-align-by-pixel)
+      (insert (make-string (- pos fallback) ? ) string)
+    (insert " ")
+    (let ((offset (floor (* (/ (1- pos) (window-width) 1.0)
+			    (nth 2 (window-inside-pixel-edges))))))
+      (put-text-property (1- (point)) (point) 'display
+			 `(space :align-to (,offset))))
+    (insert string)))
+
+(defun erc-insert-timestamp-right (string)
+  "Insert timestamp on the right side of the screen.
+STRING is the timestamp to insert.  The function is a possible value
+for `erc-insert-timestamp-function'.
+
+If `erc-timestamp-only-if-changed-flag' is nil, a timestamp is always
+printed.  If this variable is non-nil, a timestamp is only printed if
+it is different from the last.
+
+If `erc-timestamp-right-column' is set, its value will be used as the
+column at which the timestamp is to be printed.  If it is nil, and
+`erc-fill-mode' is active, then the timestamp will be printed just
+before `erc-fill-column'.  Otherwise, if the current buffer is
+shown in a window, that window's width is used.  If the buffer is
+not shown, and `fill-column' is set, then the timestamp will be
+printed just `fill-column'.  As a last resort, the timestamp will
+be printed just before the window-width."
+  (unless (and erc-timestamp-only-if-changed-flag
+	       (string-equal string erc-timestamp-last-inserted))
+    (setq erc-timestamp-last-inserted string)
+    (goto-char (point-max))
+    (forward-char -1);; before the last newline
+    (let* ((current-window (get-buffer-window (current-buffer)))
+	   (pos (cond
+		 (erc-timestamp-right-column
+		  (+ erc-timestamp-right-column (length string)))
+		 ((and (boundp 'erc-fill-mode)
+		       erc-fill-mode
+		       (boundp 'erc-fill-column))
+		  (1+ erc-fill-column))
+		 (current-window
+		  (- (window-width current-window)
+		     1))
+		 (fill-column
+		  (1+ fill-column))
+		 (t
+		  (- (window-width)
+		     1))))
+	   (from (point))
+	   (col (current-column))
+	   indent)
+      ;; deal with variable-width characters
+      (setq pos (- pos (string-width string))
+	    ;; the following is a kludge that works with most
+	    ;; international input
+	    col (+ col (ceiling (/ (- col (- (point) (point-at-bol))) 1.6))))
+      (if (< col pos)
+	  (erc-insert-aligned string pos col)
+	(newline)
+	(setq from (point))
+	(indent-to pos)
+	(insert string))
+      (erc-put-text-property from (1+ (point)) 'field 'erc-timestamp)
+      (erc-put-text-property from (1+ (point)) 'rear-nonsticky t)
+      (when erc-timestamp-intangible
+	(erc-put-text-property from (1+ (point)) 'intangible t)))))
+
+;; for testing: (setq erc-timestamp-only-if-changed-flag nil)
+
+(defun erc-format-timestamp (time format)
+  "Return TIME formatted as string according to FORMAT.
+Return the empty string if FORMAT is nil."
+  (if format
+      (let ((ts (format-time-string format time)))
+	(erc-put-text-property 0 (length ts) 'face 'erc-timestamp-face ts)
+	(erc-put-text-property 0 (length ts) 'invisible 'timestamp ts)
+	(erc-put-text-property 0 (length ts)
+			       'isearch-open-invisible 'timestamp ts)
+	;; N.B. Later use categories instead of this harmless, but
+	;; inelegant, hack. -- BPT
+	(when erc-timestamp-intangible
+	  (erc-put-text-property 0 (length ts) 'intangible t ts))
+	ts)
+    ""))
+
+;; This function is used to munge `buffer-invisibility-spec to an
+;; appropriate value. Currently, it only handles timestamps, thus its
+;; location.  If you add other features which affect invisibility,
+;; please modify this function and move it to a more appropriate
+;; location.
+(defun erc-munge-invisibility-spec ()
+  (if erc-hide-timestamps
+      (setq buffer-invisibility-spec
+	    (if (listp buffer-invisibility-spec)
+		(cons 'timestamp buffer-invisibility-spec)
+	      (list 't 'timestamp)))
+    (setq buffer-invisibility-spec
+	  (if (listp buffer-invisibility-spec)
+	      (remove 'timestamp buffer-invisibility-spec)
+	    (list 't)))))
+
+(defun erc-hide-timestamps ()
+  "Hide timestamp information from display."
+  (interactive)
+  (setq erc-hide-timestamps t)
+  (erc-munge-invisibility-spec))
+
+(defun erc-show-timestamps ()
+  "Show timestamp information on display.
+This function only works if `erc-timestamp-format' was previously
+set, and timestamping is already active."
+  (interactive)
+  (setq erc-hide-timestamps nil)
+  (erc-munge-invisibility-spec))
+
+(defun erc-echo-timestamp (before now)
+  "Print timestamp text-property of an IRC message.
+Argument BEFORE is where point was before it got moved and
+NOW is position of point currently."
+  (when erc-echo-timestamps
+    (let ((stamp (get-text-property now 'timestamp)))
+      (when stamp
+	(message (format-time-string erc-echo-timestamp-format
+				     stamp))))))
+
+(provide 'erc-stamp)
+
+;;; erc-stamp.el ends here
+;;
+;; Local Variables:
+;; indent-tabs-mode: t
+;; tab-width: 8
+;; End:
+
+;; arch-tag: 9f6d31bf-61ba-45c5-bdbf-56331486ea27
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lisp/erc/erc-track.el	Wed Feb 01 10:07:17 2006 +0000
@@ -0,0 +1,839 @@
+;;; erc-track.el --- Track modified channel buffers
+
+;; Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+
+;; Author: Mario Lang <mlang@delysid.org>
+;; Keywords: comm, faces
+;; URL: http://www.emacswiki.org/cgi-bin/wiki.pl?ErcChannelTracking
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
+
+;;; Commentary:
+
+;; Highlights keywords and pals (friends), and hides or highlights fools
+;; (using a dark color).  Add to your ~/.emacs:
+
+;; (require 'erc-track)
+;; (erc-track-mode 1)
+
+;; Todo:
+;; * Add extensibility so that custom functions can track
+;;   custom modification types.
+
+(eval-when-compile (require 'cl))
+(require 'erc)
+(require 'erc-compat)
+(require 'erc-match)
+
+;;; Code:
+
+(defgroup erc-track nil
+  "Track active buffers and show activity in the modeline."
+  :group 'erc)
+
+(defcustom erc-track-visibility t
+  "Where do we look for buffers to determine their visibility?
+The value of this variable determines, when a buffer is considered
+visible or invisible.  New messages in invisible buffers are tracked,
+while switching to visible buffers when they are tracked removes them
+from the list.  See also `erc-track-when-inactive-mode'.
+
+Possible values are:
+
+t                - all frames
+visible          - all visible frames
+nil              - only the selected frame
+selected-visible - only the selected frame if it is visible
+
+Activity means that there was no user input in the last 10 seconds."
+  :group 'erc-track
+  :type  '(choice (const :tag "All frames" t)
+		  (const :tag "All visible frames" visible)
+		  (const :tag "Only the selected frame" nil)
+		  (const :tag "Only the selected frame if it was active"
+			 active)))
+
+(defcustom erc-track-exclude nil
+  "A list targets (channel names or query targets) which should not be tracked."
+  :group 'erc-track
+  :type '(repeat string))
+
+(defcustom erc-track-exclude-types '("NICK")
+  "*List of message types to be ignored.
+This list could look like '(\"JOIN\" \"PART\")."
+  :group 'erc-track
+  :type 'erc-message-type)
+
+(defcustom erc-track-exclude-server-buffer nil
+  "*If true, don't perform tracking on the server buffer; this is
+useful for excluding all the things like MOTDs from the server and
+other miscellaneous functions."
+  :group 'erc-track
+  :type 'boolean)
+
+(defcustom erc-track-shorten-start 1
+  "This number specifies the minimum number of characters a channel name in
+the mode-line should be reduced to."
+  :group 'erc-track
+  :type 'number)
+
+(defcustom erc-track-shorten-cutoff 4
+  "All channel names longer than this value will be shortened."
+  :group 'erc-track
+  :type 'number)
+
+(defcustom erc-track-shorten-aggressively nil
+  "*If non-nil, channel names will be shortened more aggressively.
+Usually, names are not shortened if this will save only one character.
+Example: If there are two channels, #linux-de and #linux-fr, then
+normally these will not be shortened.  When shortening aggressively,
+however, these will be shortened to #linux-d and #linux-f.
+
+If this variable is set to `max', then channel names will be shortened
+to the max.  Usually, shortened channel names will remain unique for a
+given set of existing channels.  When shortening to the max, the shortened
+channel names will be unique for the set of active channels only.
+Example: If there are tow active channels #emacs and #vi, and two inactive
+channels #electronica and #folk, then usually the active channels are
+shortened to #em and #v.  When shortening to the max, however, #emacs is
+not compared to #electronica -- only to #vi, therefore it can be shortened
+even more and the result is #e and #v.
+
+This setting is used by `erc-track-shorten-names'."
+  :group 'erc-track
+  :type '(choice (const :tag "No" nil)
+		 (const :tag "Yes" t)
+		 (const :tag "Max" max)))
+
+(defcustom erc-track-shorten-function 'erc-track-shorten-names
+  "*This function will be used to reduce the channel names before display.
+It takes one argument, CHANNEL-NAMES which is a list of strings.
+It should return a list of strings of the same number of elements.
+If nil instead of a function, shortening is disabled."
+  :group 'erc-track
+  :type '(choice (const :tag "Disabled")
+		 function))
+
+(defcustom erc-track-use-faces t
+  "*Use faces in the mode-line.
+The faces used are the same as used for text in the buffers.
+\(e.g. `erc-pal-face' is used if a pal sent a message to that channel.)"
+  :group 'erc-track
+  :type 'boolean)
+
+(defcustom erc-track-faces-priority-list
+  '(erc-error-face erc-current-nick-face erc-keyword-face erc-pal-face
+    erc-nick-msg-face erc-direct-msg-face erc-button erc-dangerous-host-face
+    erc-default-face erc-action-face erc-nick-default-face erc-fool-face
+    erc-notice-face erc-input-face erc-prompt-face)
+  "A list of faces used to highlight active buffer names in the modeline.
+If a message contains one of the faces in this list, the buffer name will
+be highlighted using that face.  The first matching face is used."
+  :group 'erc-track
+  :type '(repeat face))
+
+(defcustom erc-track-priority-faces-only nil
+  "Only track text highlighted with a priority face.
+If you would like to ignore changes in certain channels where there
+are no faces corresponding to your `erc-track-faces-priority-list', set
+this variable.  You can set a list of channel name strings, so those
+will be ignored while all other channels will be tracked as normal.
+Other options are 'all, to apply this to all channels or nil, to disable
+this feature.
+Note: If you have a lot of faces listed in `erc-track-faces-priority-list',
+setting this variable might not be very useful."
+  :group 'erc-track
+  :type '(choice (const nil)
+		 (repeat string)
+		 (const all)))
+
+(defcustom erc-track-position-in-mode-line 'before-modes
+  "Where to show modified channel information in the mode-line.
+
+Setting this variable only has effects in GNU Emacs versions above 21.3.
+
+Choices are:
+'before-modes - add to the beginning of `mode-line-modes'
+'after-modes  - add to the end of `mode-line-modes'
+
+Any other value means add to the end of `global-mode-string'."
+  :group 'erc-track
+  :type '(choice (const :tag "Just before mode information" before-modes)
+		 (const :tag "Just after mode information" after-modes)
+		 (const :tag "After all other information" nil))
+  :set (lambda (sym val)
+	 (set sym val)
+	 (when (and (boundp 'erc-track-mode)
+		    erc-track-mode)
+	   (erc-track-remove-from-mode-line)
+	   (erc-track-add-to-mode-line val))))
+
+(defun erc-modified-channels-object (strings)
+  "Generate a new `erc-modified-channels-object' based on STRINGS.
+If STRINGS is nil, we initialize `erc-modified-channels-object' to
+an appropriate initial value for this flavor of Emacs."
+  (if strings
+      (if (featurep 'xemacs)
+	  (let ((e-m-c-s '("[")))
+	    (push (cons (extent-at 0 (car strings)) (car strings))
+		  e-m-c-s)
+	    (dolist (string (cdr strings))
+	      (push "," e-m-c-s)
+	      (push (cons (extent-at 0 string) string)
+		    e-m-c-s))
+	    (push "] " e-m-c-s)
+	    (reverse e-m-c-s))
+	(concat (if (eq erc-track-position-in-mode-line 'after-modes)
+		    "[" " [")
+		(mapconcat 'identity (nreverse strings) ",")
+		(if (eq erc-track-position-in-mode-line 'before-modes)
+		    "] " "]")))
+    (if (featurep 'xemacs) '() "")))
+
+(defvar erc-modified-channels-object (erc-modified-channels-object nil)
+  "Internal object used for displaying modified channels in the mode line.")
+
+(put 'erc-modified-channels-object 'risky-local-variable t); allow properties
+
+(defvar erc-modified-channels-alist nil
+  "An ALIST used for tracking channel modification activity.
+Each element looks like (BUFFER COUNT FACE) where BUFFER is a buffer
+object of the channel the entry corresponds to, COUNT is a number
+indicating how often activity was noticed, and FACE is the face to use
+when displaying the buffer's name.  See `erc-track-faces-priority-list',
+and `erc-track-showcount'.
+
+Entries in this list should only happen for buffers where activity occurred
+while the buffer was not visible.")
+
+(defcustom erc-track-showcount nil
+  "If non-nil, count of unseen messages will be shown for each channel."
+  :type 'boolean
+  :group 'erc-track)
+
+(defcustom erc-track-showcount-string ":"
+  "The string to display between buffer name and the count in the mode line.
+The default is a colon, resulting in \"#emacs:9\"."
+  :type 'string
+  :group 'erc-track)
+
+(defcustom erc-track-switch-from-erc t
+  "If non-nil, `erc-track-switch-buffer' will return to the last non-erc buffer
+when there are no more active channels."
+  :type 'boolean
+  :group 'erc-track)
+
+(defcustom erc-track-switch-direction 'oldest
+  "Direction `erc-track-switch-buffer' should switch.
+
+  oldest      -  find oldest active buffer
+  newest      -  find newest active buffer
+  leastactive -  find buffer with least unseen messages
+  mostactive  -  find buffer with most unseen messages."
+  :group 'erc-track
+  :type '(choice (const oldest)
+		 (const newest)
+		 (const leastactive)
+		 (const mostactive)))
+
+
+(defun erc-track-remove-from-mode-line ()
+  "Remove `erc-track-modified-channels' from the mode-line"
+  (when (boundp 'mode-line-modes)
+    (setq mode-line-modes
+	  (remove '(t erc-modified-channels-object) mode-line-modes)))
+  (when (consp global-mode-string)
+    (setq global-mode-string
+	  (delq 'erc-modified-channels-object global-mode-string))))
+
+(defun erc-track-add-to-mode-line (position)
+  "Add `erc-track-modified-channels' to POSITION in the mode-line.
+See `erc-track-position-in-mode-line' for possible values."
+  ;; CVS Emacs has a new format string, and global-mode-string
+  ;; is very far to the right.
+  (cond ((and (eq position 'before-modes)
+	      (boundp 'mode-line-modes))
+	 (add-to-list 'mode-line-modes
+		      '(t erc-modified-channels-object)))
+	((and (eq position 'after-modes)
+	      (boundp 'mode-line-modes))
+	 (add-to-list 'mode-line-modes
+		      '(t erc-modified-channels-object) t))
+	(t
+	 (when (not global-mode-string)
+	   (setq global-mode-string '(""))) ; Padding for mode-line wart
+	 (add-to-list 'global-mode-string
+		      'erc-modified-channels-object
+		      t))))
+
+;;; Shortening of names
+
+(defun erc-track-shorten-names (channel-names)
+  "Call `erc-unique-channel-names' with the correct parameters.
+This function is a good value for `erc-track-shorten-function'.
+The list of all channels is returned by `erc-all-buffer-names'.
+CHANNEL-NAMES is the list of active channel names.
+Only channel names longer than `erc-track-shorten-cutoff' are
+actually shortened, and they are only shortened to a minimum
+of `erc-track-shorten-start' characters."
+  (erc-unique-channel-names
+   (erc-all-buffer-names)
+   channel-names
+   (lambda (s)
+     (> (length s) erc-track-shorten-cutoff))
+   erc-track-shorten-start))
+
+(defvar erc-default-recipients)
+
+(defun erc-all-buffer-names ()
+  "Return all channel or query buffer names.
+Note that we cannot use `erc-channel-list' with a nil argument,
+because that does not return query buffers."
+  (save-excursion
+    (let (result)
+      (dolist (buf (buffer-list))
+	(set-buffer buf)
+	(when (or (eq major-mode 'erc-mode) (eq major-mode 'erc-dcc-chat-mode))
+	  (setq result (cons (buffer-name) result))))
+      result)))
+
+(defun erc-unique-channel-names (all active &optional predicate start)
+  "Return a list of unique channel names.
+ALL is the list of all channel and query buffer names.
+ACTIVE is the list of active buffer names.
+PREDICATE is a predicate that should return non-nil if a name needs
+  no shortening.
+START is the minimum length of the name used."
+  (if (eq 'max erc-track-shorten-aggressively)
+      ;; Return the unique substrings of all active channels.
+      (erc-unique-substrings active predicate start)
+    ;; Otherwise, determine the unique substrings of all channels, and
+    ;; for every active channel, return the corresponding substring.
+    ;; Given the names of the active channels, we now need to find the
+    ;; corresponding short name from the list of all substrings.  To
+    ;; avoid problems when there are two channels and one is a
+    ;; substring of the other (notorious examples are #hurd and
+    ;; #hurd-bunny), every candidate gets the longest possible
+    ;; substring.
+    (let ((all-substrings (sort
+			   (erc-unique-substrings all predicate start)
+			   (lambda (a b) (> (length a) (length b)))))
+	  result)
+      (dolist (channel active)
+	(let ((substrings all-substrings)
+	      candidate
+	      winner)
+	  (while (and substrings (not winner))
+	    (setq candidate (car substrings)
+		  substrings (cdr substrings))
+	    (when (and (string= candidate
+				(substring channel
+					   0
+					   (min (length candidate)
+						(length channel))))
+		       (not (member candidate result)))
+	      (setq winner candidate)))
+	  (setq result (cons winner result))))
+      (nreverse result))))
+
+(defun erc-unique-substrings (strings &optional predicate start)
+  "Return a list of unique substrings of STRINGS."
+  (if (or (not (numberp start))
+	  (< start 0))
+      (setq start 2))
+  (mapcar
+   (lambda (str)
+     (let* ((others (delete str (copy-sequence strings)))
+	    (maxlen (length str))
+	    (i (min start
+		    (length str)))
+	    candidate
+	    done)
+       (if (and (functionp predicate) (not (funcall predicate str)))
+	   ;; do not shorten if a predicate exists and it returns nil
+	   str
+	 ;; Start with smallest substring candidate, ie. length 1.
+	 ;; Then check all the others and see whether any of them starts
+	 ;; with the same substring.  While there is such another
+	 ;; element in the list, increase the length of the candidate.
+	 (while (not done)
+	   (if (> i maxlen)
+	       (setq done t)
+	     (setq candidate (substring str 0 i)
+		   done (not (erc-unique-substring-1 candidate others))))
+	   (setq i (1+ i)))
+	 (if (and (= (length candidate) (1- maxlen))
+		  (not erc-track-shorten-aggressively))
+	     str
+	   candidate))))
+   strings))
+
+(defun erc-unique-substring-1 (candidate others)
+  "Return non-nil when any string in OTHERS starts with CANDIDATE."
+  (let (result other (maxlen (length candidate)))
+    (while (and others
+		(not result))
+      (setq other (car others)
+	    others (cdr others))
+      (when (and (>= (length other) maxlen)
+		 (string= candidate (substring other 0 maxlen)))
+	(setq result other)))
+    result))
+
+;;; Test:
+
+(erc-assert
+ (and
+  ;; verify examples from the doc strings
+  (equal (let ((erc-track-shorten-aggressively nil))
+	   (erc-unique-channel-names
+	    '("#emacs" "#vi" "#electronica" "#folk")
+	    '("#emacs" "#vi")))
+	 '("#em" "#vi"))	 ; emacs is different from electronica
+  (equal (let ((erc-track-shorten-aggressively t))
+	   (erc-unique-channel-names
+	    '("#emacs" "#vi" "#electronica" "#folk")
+	    '("#emacs" "#vi")))
+	 '("#em" "#v"))		       ; vi is shortened by one letter
+  (equal (let ((erc-track-shorten-aggressively 'max))
+	   (erc-unique-channel-names
+	    '("#emacs" "#vi" "#electronica" "#folk")
+	    '("#emacs" "#vi")))
+	 '("#e" "#v"))  ; emacs need not be different from electronica
+  (equal (let ((erc-track-shorten-aggressively nil))
+	   (erc-unique-channel-names
+	    '("#linux-de" "#linux-fr")
+	    '("#linux-de" "#linux-fr")))
+	 '("#linux-de" "#linux-fr")) ; shortening by one letter is too aggressive
+  (equal (let ((erc-track-shorten-aggressively t))
+	   (erc-unique-channel-names
+	    '("#linux-de" "#linux-fr")
+	    '("#linux-de" "#linux-fr")))
+	 '("#linux-d" "#linux-f")); now we want to be aggressive
+  ;; specific problems
+  (equal (let ((erc-track-shorten-aggressively nil))
+	   (erc-unique-channel-names
+	    '("#dunnet" "#lisp" "#sawfish" "#fsf" "#guile"
+	      "#testgnome" "#gnu" "#fsbot" "#hurd" "#hurd-bunny"
+	      "#emacs")
+	    '("#hurd-bunny" "#hurd" "#sawfish" "#lisp")))
+	 '("#hurd-" "#hurd" "#s" "#l"))
+  (equal (let ((erc-track-shorten-aggressively nil))
+	   (erc-unique-substrings
+	    '("#emacs" "#vi" "#electronica" "#folk")))
+	 '("#em" "#vi" "#el" "#f"))
+  (equal (let ((erc-track-shorten-aggressively t))
+	   (erc-unique-substrings
+	    '("#emacs" "#vi" "#electronica" "#folk")))
+	 '("#em" "#v" "#el" "#f"))
+  (equal (let ((erc-track-shorten-aggressively nil))
+	   (erc-unique-channel-names
+	    '("#emacs" "#burse" "+linux.de" "#starwars"
+	      "#bitlbee" "+burse" "#ratpoison")
+	    '("+linux.de" "#starwars" "#burse")))
+	 '("+l" "#s" "#bu"))
+  (equal (let ((erc-track-shorten-aggressively nil))
+	   (erc-unique-channel-names
+	    '("fsbot" "#emacs" "deego")
+	    '("fsbot")))
+	 '("fs"))
+  (equal (let ((erc-track-shorten-aggressively nil))
+	   (erc-unique-channel-names
+	    '("fsbot" "#emacs" "deego")
+	    '("fsbot")
+	    (lambda (s)
+	      (> (length s) 4))
+	    1))
+	 '("f"))
+  (equal (let ((erc-track-shorten-aggressively nil))
+	   (erc-unique-channel-names
+	    '("fsbot" "#emacs" "deego")
+	    '("fsbot")
+	    (lambda (s)
+	      (> (length s) 4))
+	    2))
+	 '("fs"))
+  (let ((erc-track-shorten-aggressively nil))
+    (equal (erc-unique-channel-names '("deego" "#hurd" "#hurd-bunny" "#emacs")
+				     '("#hurd" "#hurd-bunny"))
+	   '("#hurd" "#hurd-")))
+  ;; general examples
+  (let ((erc-track-shorten-aggressively t))
+    (and (equal (erc-unique-substring-1 "abc" '("ab" "abcd")) "abcd")
+	 (not (erc-unique-substring-1 "a" '("xyz" "xab")))
+	 (equal (erc-unique-substrings '("abc" "xyz" "xab"))
+		'("ab" "xy" "xa"))
+	 (equal (erc-unique-substrings '("abc" "abcdefg"))
+		'("abc" "abcd"))))
+  (let ((erc-track-shorten-aggressively nil))
+    (and (equal (erc-unique-substring-1 "abc" '("ab" "abcd")) "abcd")
+	 (not (erc-unique-substring-1 "a" '("xyz" "xab")))
+	 (equal (erc-unique-substrings '("abc" "xyz" "xab"))
+		'("abc" "xyz" "xab"))
+	 (equal (erc-unique-substrings '("abc" "abcdefg"))
+		'("abc" "abcd"))))))
+
+;;; Module
+
+;;;###autoload (autoload 'erc-track-mode "erc-track" nil t)
+(define-erc-module track track-modified-channels
+  "This mode tracks ERC channel buffers with activity."
+  ((erc-track-add-to-mode-line erc-track-position-in-mode-line)
+   (setq erc-modified-channels-object (erc-modified-channels-object nil))
+   (erc-update-mode-line)
+   (if (featurep 'xemacs)
+       (defadvice switch-to-buffer (after erc-update (&rest args) activate)
+	 (erc-modified-channels-update))
+     (add-hook 'window-configuration-change-hook 'erc-modified-channels-update))
+   (add-hook 'erc-insert-post-hook 'erc-track-modified-channels)
+   (add-hook 'erc-disconnected-hook 'erc-modified-channels-update))
+  ((erc-track-remove-from-mode-line)
+   (if (featurep 'xemacs)
+       (ad-disable-advice 'switch-to-buffer 'after 'erc-update)
+     (remove-hook 'window-configuration-change-hook
+		  'erc-modified-channels-update))
+   (remove-hook 'erc-disconnected-hook 'erc-modified-channels-update)
+   (remove-hook 'erc-insert-post-hook 'erc-track-modified-channels)))
+
+;;;###autoload (autoload 'erc-track-when-inactive-mode "erc-track" nil t)
+(define-erc-module track-when-inactive nil
+  "This mode enables channel tracking even for visible buffers,
+if you are inactivity."
+  ((if (featurep 'xemacs)
+       (defadvice switch-to-buffer (after erc-update-when-inactive (&rest args) activate)
+	 (erc-user-is-active))
+     (add-hook 'window-configuration-change-hook 'erc-user-is-active))
+   (add-hook 'erc-send-completed-hook 'erc-user-is-active)
+   (add-hook 'erc-server-001-functions 'erc-user-is-active))
+  ((erc-track-remove-from-mode-line)
+   (if (featurep 'xemacs)
+       (ad-disable-advice 'switch-to-buffer 'after 'erc-update-when-inactive)
+     (remove-hook 'window-configuration-change-hook 'erc-user-is-active))
+   (remove-hook 'erc-send-completed-hook 'erc-user-is-active)
+   (remove-hook 'erc-server-001-functions 'erc-user-is-active)
+   (remove-hook 'erc-timer-hook 'erc-user-is-active)))
+
+;;; Visibility
+
+(defvar erc-buffer-activity nil
+  "Last time the user sent something.")
+
+(defvar erc-buffer-activity-timeout 10
+  "How many seconds of inactivity by the user
+to consider when `erc-track-visibility' is set to
+only consider active buffers visible.")
+
+(defun erc-user-is-active (&rest ignore)
+  "Set `erc-buffer-activity'."
+  (setq erc-buffer-activity (erc-current-time))
+  (erc-track-modified-channels))
+
+(defun erc-buffer-visible (buffer)
+  "Return non-nil when the buffer is visible."
+  (if erc-track-when-inactive-mode
+      (when erc-buffer-activity; could be nil
+	(and (get-buffer-window buffer erc-track-visibility)
+	     (<= (erc-time-diff erc-buffer-activity (erc-current-time))
+		 erc-buffer-activity-timeout)))
+    (get-buffer-window buffer erc-track-visibility)))
+
+;;; Tracking the channel modifications
+
+(defvar erc-modified-channels-update-inside nil
+  "Variable to prevent running `erc-modified-channels-update' multiple
+times.  Without it, you cannot debug `erc-modified-channels-display',
+because the debugger also cases changes to the window-configuration.")
+
+(defun erc-modified-channels-update (&rest args)
+  "This function updates the information in `erc-modified-channels-alist'
+according to buffer visibility.  It calls
+`erc-modified-channels-display' at the end. This should usually be
+called via `window-configuration-change-hook'.
+ARGS are ignored."
+  (interactive)
+  (unless erc-modified-channels-update-inside
+    (let ((erc-modified-channels-update-inside t))
+      (mapcar (lambda (elt)
+		(let ((buffer (car elt)))
+		  (when (or (not (bufferp buffer))
+			    (not (buffer-live-p buffer))
+			    (erc-buffer-visible buffer)
+			    (not (with-current-buffer buffer
+				   erc-server-connected)))
+		    (erc-modified-channels-remove-buffer buffer))))
+	      erc-modified-channels-alist)
+      (erc-modified-channels-display)
+      (force-mode-line-update t))))
+
+(defun erc-make-mode-line-buffer-name (string buffer &optional faces count)
+  "Return STRING as a button that switches to BUFFER when clicked.
+If FACES are provided, color STRING with them."
+  ;; We define a new sparse keymap every time, because 1. this data
+  ;; structure is very small, the alternative would require us to
+  ;; defvar a keymap, 2. the user is not interested in customizing it
+  ;; (really?), 3. the defun needs to switch to BUFFER, so we would
+  ;; need to save that value somewhere.
+  (let ((map (make-sparse-keymap))
+	(name (if erc-track-showcount
+		  (concat string
+			  erc-track-showcount-string
+			  (int-to-string count))
+		(copy-sequence string))))
+    (define-key map (vector 'mode-line 'mouse-2)
+      `(lambda (e)
+	 (interactive "e")
+	 (save-selected-window
+	   (select-window
+	    (posn-window (event-start e)))
+	   (switch-to-buffer ,buffer))))
+    (define-key map (vector 'mode-line 'mouse-3)
+      `(lambda (e)
+	 (interactive "e")
+	 (save-selected-window
+	   (select-window
+	    (posn-window (event-start e)))
+	   (switch-to-buffer-other-window ,buffer))))
+    (put-text-property 0 (length name) 'local-map map name)
+    (when (and faces erc-track-use-faces)
+      (put-text-property 0 (length name) 'face faces name))
+    name))
+
+(defun erc-modified-channels-display ()
+  "Set `erc-modified-channels-object'
+according to `erc-modified-channels-alist'.
+Use `erc-make-mode-line-buffer-name' to create buttons."
+  (if (or
+	(eq 'mostactive erc-track-switch-direction)
+	(eq 'leastactive erc-track-switch-direction))
+      (erc-track-sort-by-activest))
+  (if (null erc-modified-channels-alist)
+      (setq erc-modified-channels-object (erc-modified-channels-object nil))
+    ;; erc-modified-channels-alist contains all the data we need.  To
+    ;; better understand what is going on, we split things up into
+    ;; four lists: BUFFERS, COUNTS, SHORT-NAMES, and FACES.  These
+    ;; four lists we use to create a new
+    ;; `erc-modified-channels-object' using
+    ;; `erc-make-mode-line-buffer-name'.
+    (let* ((buffers (mapcar 'car erc-modified-channels-alist))
+	   (counts (mapcar 'cadr erc-modified-channels-alist))
+	   (faces (mapcar 'cddr erc-modified-channels-alist))
+	   (long-names (mapcar #'(lambda (buf)
+				   (or (buffer-name buf)
+				       ""))
+			       buffers))
+	   (short-names (if (functionp erc-track-shorten-function)
+			    (funcall erc-track-shorten-function
+				     long-names)
+			  long-names))
+	   strings)
+      (while buffers
+	(when (car short-names)
+	  (setq strings (cons (erc-make-mode-line-buffer-name
+			       (car short-names)
+			       (car buffers)
+			       (car faces)
+			       (car counts))
+			      strings)))
+	(setq short-names (cdr short-names)
+	      buffers (cdr buffers)
+	      counts (cdr counts)
+	      faces (cdr faces)))
+      (when (featurep 'xemacs)
+	(erc-modified-channels-object nil))
+      (setq erc-modified-channels-object
+	    (erc-modified-channels-object strings)))))
+
+(defun erc-modified-channels-remove-buffer (buffer)
+  "Remove BUFFER from `erc-modified-channels-alist'."
+  (interactive "bBuffer: ")
+  (setq erc-modified-channels-alist
+	(delete (assq buffer erc-modified-channels-alist)
+		erc-modified-channels-alist))
+  (when (interactive-p)
+    (erc-modified-channels-display)))
+
+(defun erc-track-find-face (faces)
+  "Return the face to use in the modeline from the faces in FACES.
+If `erc-track-faces-priority-list' is set, the one from FACES who is
+first in that list will be used."
+  (let ((candidates erc-track-faces-priority-list)
+	candidate face)
+    (while (and candidates (not face))
+      (setq candidate (car candidates)
+	    candidates (cdr candidates))
+      (when (memq candidate faces)
+	(setq face candidate)))
+    face))
+
+(defun erc-track-modified-channels ()
+  "Hook function for `erc-insert-post-hook' to check if the current
+buffer should be added to the modeline as a hidden, modified
+channel.  Assumes it will only be called when current-buffer
+is in `erc-mode'."
+  (let ((this-channel (or (erc-default-target)
+			  (buffer-name (current-buffer)))))
+    (if (and (not (erc-buffer-visible (current-buffer)))
+	     (not (member this-channel erc-track-exclude))
+	     (not (and erc-track-exclude-server-buffer
+		       (string= this-channel
+				(buffer-name (erc-server-buffer)))))
+	     (not (erc-message-type-member
+		   (or (erc-find-parsed-property)
+		       (point-min))
+		   erc-track-exclude-types)))
+	;; If the active buffer is not visible (not shown in a
+	;; window), and not to be excluded, determine the kinds of
+	;; faces used in the current message, and unless the user
+	;; wants to ignore changes in certain channels where there
+	;; are no faces corresponding to `erc-track-faces-priority-list',
+	;; and the faces in the current message are found in said
+	;; priority list, add the buffer to the erc-modified-channels-alist,
+	;; if it is not already there.  If the buffer is already on the list
+	;; (in the car), change its face attribute (in the cddr) if
+	;; necessary.  See `erc-modified-channels-alist' for the
+	;; exact data structure used.
+	(let ((faces (erc-faces-in (buffer-string))))
+	  (unless (and
+		   (or (eq erc-track-priority-faces-only 'all)
+		       (member this-channel erc-track-priority-faces-only))
+		   (not (catch 'found
+			  (dolist (f faces)
+			    (when (member f erc-track-faces-priority-list)
+			      (throw 'found t))))))
+	    (if (not (assq (current-buffer) erc-modified-channels-alist))
+		;; Add buffer, faces and counts
+		(setq erc-modified-channels-alist
+		      (cons (cons (current-buffer)
+				  (cons 1 (erc-track-find-face faces)))
+			    erc-modified-channels-alist))
+	      ;; Else modify the face for the buffer, if necessary.
+	      (when faces
+		(let* ((cell (assq (current-buffer)
+				   erc-modified-channels-alist))
+		       (old-face (cddr cell))
+		       (new-face (erc-track-find-face
+				  (if old-face
+				      (cons old-face faces)
+				    faces))))
+		  (setcdr cell (cons (1+ (cadr cell)) new-face)))))
+	    ;; And display it
+	    (erc-modified-channels-display)))
+      ;; Else if the active buffer is the current buffer, remove it
+      ;; from our list.
+      (when (or (erc-buffer-visible (current-buffer))
+		(and this-channel
+		     (assq (current-buffer) erc-modified-channels-alist)
+		     (member this-channel erc-track-exclude)))
+	;; Remove it from mode-line if buffer is visible or
+	;; channel was added to erc-track-exclude recently.
+	(erc-modified-channels-remove-buffer (current-buffer))
+	(erc-modified-channels-display)))))
+
+(defun erc-faces-in (str)
+  "Return a list of all faces used in STR."
+  (let ((i 0)
+	(m (length str))
+	(faces (erc-list (get-text-property 0 'face str))))
+    (while (and (setq i (next-single-property-change i 'face str m))
+		(not (= i m)))
+      (dolist (face (erc-list (get-text-property i 'face str)))
+	(add-to-list 'faces face)))
+    faces))
+
+(erc-assert
+ (let ((str "is bold"))
+   (put-text-property 3 (length str)
+		      'face '(bold erc-current-nick-face)
+		      str)
+   (erc-faces-in str)))
+
+(defun erc-find-parsed-property ()
+  "Find the next occurrence of the `erc-parsed' text property."
+  (text-property-not-all (point-min) (point-max) 'erc-parsed nil))
+
+;;; Buffer switching
+
+(defvar erc-track-last-non-erc-buffer nil
+  "Stores the name of the last buffer you were in before activating
+`erc-track-switch-buffers'")
+
+(defun erc-track-sort-by-activest ()
+  "Sort erc-modified-channels-alist by activity.
+That means the number of unseen messages in a channel."
+  (setq erc-modified-channels-alist
+	(sort erc-modified-channels-alist
+	      (lambda (a b) (> (nth 1 a) (nth 1 b))))))
+
+(defun erc-track-get-active-buffer (arg)
+  "Return the buffer name of ARG in `erc-modified-channels-alist'.
+Negative arguments index in the opposite direction.  This direction is
+relative to `erc-track-switch-direction'"
+  (let ((dir erc-track-switch-direction)
+	offset)
+    (when (< arg 0)
+      (setq dir (case dir
+		  (oldest      'newest)
+		  (newest      'oldest)
+		  (mostactive  'leastactive)
+		  (leastactive 'mostactive)))
+      (setq arg (- arg)))
+    (setq offset (case dir
+		   ((oldest leastactive)
+		    (- (length erc-modified-channels-alist) arg))
+		   (t (1- arg))))
+    ;; normalise out of range user input
+    (cond ((>= offset (length erc-modified-channels-alist))
+	   (setq offset (1- (length erc-modified-channels-alist))))
+	  ((< offset 0)
+	   (setq offset 0)))
+    (car (nth offset erc-modified-channels-alist))))
+
+(defun erc-track-switch-buffer (arg)
+  "Switch to the next active ERC buffer, or if there are no active buffers,
+switch back to the last non-ERC buffer visited.  Next is defined by
+`erc-track-switch-direction', a negative argument will reverse this."
+  (interactive "p")
+  (when erc-track-mode
+    (cond (erc-modified-channels-alist
+	   ;; if we're not in erc-mode, set this buffer to return to
+	   (unless (eq major-mode 'erc-mode)
+	     (setq erc-track-last-non-erc-buffer (current-buffer)))
+	   ;; and jump to the next active channel
+	   (switch-to-buffer (erc-track-get-active-buffer arg)))
+	  ;; if no active channels, switch back to what we were doing before
+	  ((and erc-track-last-non-erc-buffer
+		erc-track-switch-from-erc
+		(buffer-live-p erc-track-last-non-erc-buffer))
+	   (switch-to-buffer erc-track-last-non-erc-buffer)))))
+
+;; These bindings are global, because they pop us from any other
+;; buffer to an active ERC buffer!
+
+(global-set-key (kbd "C-c C-@") 'erc-track-switch-buffer)
+(global-set-key (kbd "C-c C-SPC") 'erc-track-switch-buffer)
+
+(provide 'erc-track)
+
+;;; erc-track.el ends here
+;;
+;; Local Variables:
+;; indent-tabs-mode: t
+;; tab-width: 8
+;; End:
+
+;; arch-tag: 11b439f5-e5d7-4c6c-bb3f-eda98f9b0ac1
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lisp/erc/erc-truncate.el	Wed Feb 01 10:07:17 2006 +0000
@@ -0,0 +1,121 @@
+;;; erc-truncate.el --- Functions for truncating ERC buffers
+
+;; Copyright (C) 2003, 2004 Free Software Foundation, Inc.
+
+;; Author: Andreas Fuchs <asf@void.at>
+;; Keywords: IRC, chat, client, Internet, logging
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
+
+;;; Commentary:
+
+;; This implements buffer truncation (and optional log file writing
+;; support for the Emacs IRC client. Use `erc-truncate-mode' to switch
+;; on. Use `erc-enable-logging' to enable logging of the stuff which
+;; is getting truncated.
+
+;;; Code:
+
+(require 'erc)
+
+(defgroup erc-truncate nil
+  "Truncate buffers when they reach a certain size"
+  :group 'erc)
+
+(defcustom erc-max-buffer-size 30000
+  "*Maximum size in chars of each ERC buffer.
+Used only when auto-truncation is enabled.
+\(see `erc-truncate-buffer' and `erc-insert-post-hook')."
+  :group 'erc-truncate
+  :type 'integer)
+
+;;;###autoload (autoload 'erc-truncate-mode "erc-truncate" nil t)
+(define-erc-module truncate nil
+  "Truncate a query buffer if it gets too large.
+This prevents the query buffer from getting too large, which can
+bring any grown emacs to its knees after a few days worth of
+tracking heavy-traffic channels."
+  ;;enable
+  ((add-hook 'erc-insert-post-hook 'erc-truncate-buffer))
+  ;; disable
+  ((remove-hook 'erc-insert-post-hook 'erc-truncate-buffer)))
+
+;;;###autoload
+(defun erc-truncate-buffer-to-size (size &optional buffer)
+  "Truncates the buffer to the size SIZE.
+If BUFFER is not provided, the current buffer is assumed.  The deleted
+region is logged if `erc-logging-enabled' returns non-nil."
+  ;; If buffer is non-nil, but get-buffer does not return anything,
+  ;; then this is a bug.  If buffer is a buffer name, get the buffer
+  ;; object.  If buffer is nil, use the current buffer.
+  (if (not buffer)
+      (setq buffer (current-buffer))
+    (unless (get-buffer buffer)
+      (error "erc-truncate-buffer-to-size: %S is not a buffer" buffer)))
+  (when (> (buffer-size buffer) (+ size 512))
+    (save-excursion
+      (set-buffer buffer)
+      ;; Note that when erc-insert-post-hook runs, the buffer is
+      ;; narrowed to the new message.  So do this delicate widening.
+      ;; I am not sure, I think this was not recommended behaviour in
+      ;; Emacs 20.
+      (save-restriction
+	(widen)
+	(let ((end (- erc-insert-marker size)))
+	  ;; truncate at line boundaries
+	  (goto-char end)
+	  (beginning-of-line)
+	  (setq end (point))
+	  ;; try to save the current buffer using
+	  ;; `erc-save-buffer-in-logs'.  We use this, in case the
+	  ;; user has both `erc-save-buffer-in-logs' and
+	  ;; `erc-truncate-buffer' in `erc-insert-post-hook'.  If
+	  ;; this is the case, only the non-saved part of the current
+	  ;; buffer should be saved.  Rather than appending the
+	  ;; deleted part of the buffer to the log file.
+	  ;;
+	  ;; Alternatively this could be made conditional on:
+	  ;; (not (memq 'erc-save-buffer-in-logs
+	  ;;             erc-insert-post-hook))
+	  ;; Comments?
+	  (when (and (boundp 'erc-enable-logging)
+		     erc-enable-logging
+		     (erc-logging-enabled buffer))
+	    (erc-save-buffer-in-logs))
+	  ;; disable undoing for the truncating
+	  (buffer-disable-undo)
+	  (let ((inhibit-read-only t))
+	    (delete-region (point-min) end)))
+	(buffer-enable-undo)))))
+
+;;;###autoload
+(defun erc-truncate-buffer ()
+  "Truncates the current buffer to `erc-max-buffer-size'.
+Meant to be used in hooks, like `erc-insert-post-hook'."
+  (interactive)
+  (erc-truncate-buffer-to-size erc-max-buffer-size))
+
+(provide 'erc-truncate)
+;;; erc-truncate.el ends here
+;;
+;; Local Variables:
+;; indent-tabs-mode: t
+;; tab-width: 8
+;; End:
+
+;; arch-tag: 22a2ea78-871f-4870-8f1e-efe534170311
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lisp/erc/erc-xdcc.el	Wed Feb 01 10:07:17 2006 +0000
@@ -0,0 +1,130 @@
+;;; erc-xdcc.el --- XDCC file-server support for ERC
+
+;; Copyright (C) 2003, 2004 Free Software Foundation, Inc.
+
+;; Author: Mario Lang <mlang@delysid.org>
+;; Keywords: comm, processes
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
+
+;;; Commentary:
+
+;; This file provides a very simple XDCC file server for the Emacs IRC Client.
+
+;;; Code:
+
+(require 'erc-dcc)
+
+(defcustom erc-xdcc-files nil
+  "*List of files to offer via XDCC.
+Your friends should issue \"/ctcp yournick XDCC list\" to see this."
+  :group 'erc-dcc
+  :type '(repeat file))
+
+(defcustom erc-xdcc-verbose-flag t
+  "*Report XDCC CTCP requests in the server buffer."
+  :group 'erc-dcc
+  :type 'boolean)
+
+(defcustom erc-xdcc-handler-alist
+  '(("help" . erc-xdcc-help)
+    ("list" . erc-xdcc-list)
+    ("send" . erc-xdcc-send))
+  "*Sub-command handler alist for XDCC CTCP queries."
+  :group 'erc-dcc
+  :type '(alist :key-type (string :tag "Sub-command") :value-type function))
+
+(defcustom erc-xdcc-help-text
+  '(("Hey " nick ", wondering how this works?  Pretty easy.")
+    ("Available commands: XDCC ["
+     (mapconcat 'car erc-xdcc-handler-alist "|") "]")
+    ("Type \"/ctcp " (erc-current-nick)
+     " XDCC list\" to see the list of offered files, then type \"/ctcp "
+     (erc-current-nick) " XDCC send #\" to get a particular file number."))
+  "*Help text sent in response to XDCC help command.
+A list of messages, each consisting of strings and expressions, expressions
+being evaluated and should return stings."
+  :group 'erc-dcc
+  :type '(repeat (repeat :tag "Message" (choice string sexp))))
+
+;;;###autoload
+(defun erc-xdcc-add-file (file)
+  "Add a file to `erc-xdcc-files'."
+  (interactive "fFilename to add to XDCC: ")
+  (if (file-exists-p file)
+      (add-to-list 'erc-xdcc-files file)))
+
+(defun erc-xdcc-reply (proc nick msg)
+  (process-send-string proc
+   (format "PRIVMSG %s :%s\n" nick msg)))
+
+;; CTCP query handlers
+
+(defvar erc-ctcp-query-XDCC-hook '(erc-xdcc)
+  "Hook called whenever a CTCP XDCC message is received.")
+
+(defun erc-xdcc (proc nick login host to query)
+  "Handle incoming CTCP XDCC queries."
+  (when erc-xdcc-verbose-flag
+    (erc-display-message nil 'notice proc
+     (format "XDCC %s (%s@%s) sends %S" nick login host query)))
+  (let* ((args (cdr (delete "" (split-string query " "))))
+	 (handler (cdr (assoc (downcase (car args)) erc-xdcc-handler-alist))))
+    (if (and handler (functionp handler))
+	(funcall handler proc nick login host (cdr args))
+      (erc-xdcc-reply
+       proc nick
+       (format "Unknown XDCC sub-command, try \"/ctcp %s XDCC help\""
+	       (erc-current-nick))))))
+
+(defun erc-xdcc-help (proc nick login host args)
+  "Send basic help information to NICK."
+  (mapc
+   (lambda (msg)
+     (erc-xdcc-reply proc nick
+      (mapconcat (lambda (elt) (if (stringp elt) elt (eval elt))) msg "")))
+   erc-xdcc-help-text))
+
+(defun erc-xdcc-list (proc nick login host args)
+  "Show the contents of `erc-xdcc-files' via privmsg to NICK."
+  (if (null erc-xdcc-files)
+      (erc-xdcc-reply proc nick "No files offered, sorry")
+    (erc-xdcc-reply proc nick "Num  Filename")
+    (erc-xdcc-reply proc nick "---  -------------")
+    (let ((n 0))
+      (dolist (file erc-xdcc-files)
+	(erc-xdcc-reply proc nick
+	 (format "%02d.  %s"
+		 (setq n (1+ n))
+		 (erc-dcc-file-to-name file)))))))
+
+(defun erc-xdcc-send (proc nick login host args)
+  "Send a file to NICK."
+  (let ((n (string-to-number (car args)))
+	(len (length erc-xdcc-files)))
+    (cond
+     ((= len 0)
+      (erc-xdcc-reply proc nick "No files offered, sorry"))
+     ((or (< n 1) (> n len))
+      (erc-xdcc-reply proc nick (format "%d out of range" n)))
+     (t (erc-dcc-send-file nick (nth (1- n) erc-xdcc-files) proc)))))
+
+(provide 'erc-xdcc)
+
+;; arch-tag: a13b62fe-2399-4562-af4e-f18a8dd4b9c8
+;;; erc-xdcc.el ends here
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lisp/erc/erc.el	Wed Feb 01 10:07:17 2006 +0000
@@ -0,0 +1,6145 @@
+;; erc.el --- An Emacs Internet Relay Chat client
+
+;; Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
+;;   2006 Free Software Foundation, Inc.
+;; Copyright (C) 2004 Brian Palmer
+
+;; Author: Alexander L. Belikoff (alexander@belikoff.net)
+;; Contributors: Sergey Berezin (sergey.berezin@cs.cmu.edu),
+;;               Mario Lang (mlang@delysid.org),
+;;               Alex Schroeder (alex@gnu.org)
+;;               Andreas Fuchs (afs@void.at)
+;;               Gergely Nagy (algernon@midgard.debian.net)
+;;               David Edmondson (dme@dme.org)
+;; Maintainer: Mario Lang (mlang@delysid.org)
+;; Keywords: IRC, chat, client, Internet
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
+
+;;; Commentary:
+
+;; ERC is an IRC client for Emacs.
+
+;; For more information, see the following URLs:
+;; * http://sf.net/projects/erc/
+;; * http://www.emacswiki.org/cgi-bin/wiki.pl?EmacsIRCClient
+
+;; Jul-26-2001. erc.el is now in CVS on SourceForge.  I invite everyone
+;; who wants to hack it to contact me <mlang@delysid.org> in order to
+;; get write access on the CVS.
+
+;; Installation:
+
+;; Put erc.el in your load-path, and put (require 'erc) in your .emacs.
+
+;; Configuration:
+
+;; Use M-x customize-group RET erc RET to get an overview
+;; of all the variables you can tweak.
+
+;; Usage:
+
+;; To connect to an IRC server, do
+;;
+;; M-x erc-select RET
+;;
+;; After you are connected to a server, you can use C-h m or have a look at
+;; the IRC menu.
+
+;;; History:
+;;
+
+;;; Code:
+
+(defconst erc-version-string "Version 5.1 (Emacs 22)"
+  "ERC version.  This is used by function `erc-version'.")
+
+(eval-when-compile (require 'cl))
+(require 'font-lock)
+(require 'pp)
+(require 'thingatpt)
+(require 'erc-compat)
+(require 'erc-menu)
+
+(defvar erc-official-location
+  "http://erc.sf.net (comments mailto://mlang@delysid.org)"
+  "Location of the ERC client on the Internet.")
+
+(defgroup erc nil
+  "Emacs Internet Relay Chat client."
+  :link '(url-link "http://www.emacswiki.org/cgi-bin/wiki.pl?EmacsIRCClient")
+  :prefix "erc-"
+  :group 'applications)
+
+(defgroup erc-buffers nil
+  "Creating new ERC buffers"
+  :group 'erc)
+
+(defgroup erc-display nil
+  "Settings for how various things are displayed"
+  :group 'erc)
+
+(defgroup erc-mode-line-and-header nil
+  "Displaying information in the mode-line and header"
+  :group 'erc-display)
+
+(defgroup erc-ignore nil
+  "Ignoring certain messages"
+  :group 'erc)
+
+(defgroup erc-query nil
+  "Using separate buffers for private discussions"
+  :group 'erc)
+
+(defgroup erc-quit-and-part nil
+  "Quitting and parting channels"
+  :group 'erc)
+
+(defgroup erc-paranoia nil
+  "Know what is sent and received; control the display of sensitive data."
+  :group 'erc)
+
+(defgroup erc-scripts nil
+  "Running scripts at startup and with /LOAD"
+  :group 'erc)
+
+(require 'erc-backend)
+
+;; compatibility with older ERC releases
+
+(if (fboundp 'defvaralias)
+    (progn
+      (defvaralias 'erc-announced-server-name 'erc-server-announced-name)
+      (erc-make-obsolete-variable 'erc-announced-server-name
+				  'erc-server-announced-name
+				  "ERC 5.1")
+      (defvaralias 'erc-process 'erc-server-process)
+      (erc-make-obsolete-variable 'erc-process 'erc-server-process "ERC 5.1")
+      (defvaralias 'erc-default-coding-system 'erc-server-coding-system)
+      (erc-make-obsolete-variable 'erc-default-coding-system
+				  'erc-server-coding-system
+				  "ERC 5.1"))
+  (message (concat "ERC: The function `defvaralias' is not bound.  See the "
+		   "NEWS file for variable name changes since ERC 5.0.4.")))
+
+(defalias 'erc-send-command 'erc-server-send)
+(erc-make-obsolete 'erc-send-command 'erc-server-send "ERC 5.1")
+
+;; tunable connection and authentication parameters
+
+(defcustom erc-server nil
+  "IRC server to use.
+See function `erc-compute-server' for more details on connection
+parameters and authentication."
+  :group 'erc
+  :type '(choice (const nil) string))
+
+(defcustom erc-port nil
+  "IRC port to use."
+  :group 'erc
+  :type '(choice (const nil) number string))
+
+(defcustom erc-nick nil
+  "Nickname to use.
+
+Can be either a string, or a list of strings.
+In the latter case, if the first nick in the list is already in use,
+other nicks are tried in the list order.
+
+See function `erc-compute-nick' for more details on connection
+parameters and authentication."
+  :group 'erc
+  :type '(choice (const nil)
+		 (string :tag "Nickname")
+		 (repeat string)))
+
+(defcustom erc-nick-uniquifier "`"
+  "The character to append to the nick if it is already in use."
+  :group 'erc
+  :type 'string)
+
+(defcustom erc-manual-set-nick-on-bad-nick-p nil
+  "If the nickname you chose isn't available, ERC should not automatically
+attempt to set another nickname.  You can manually set another nickname with
+the /NICK command."
+  :group 'erc
+  :type 'boolean)
+
+(defcustom erc-user-full-name nil
+  "User full name.
+
+See function `erc-compute-full-name' for more details on connection
+parameters and authentication."
+  :group 'erc
+  :type '(choice (const nil) string function)
+  :set (lambda (sym val)
+	 (if (functionp val)
+	     (set sym (funcall val))
+	   (set sym val))))
+
+(defvar erc-password nil
+  "ERC password to use in authentication (not necessary).")
+
+(defcustom erc-user-mode nil
+  "Initial user modes to be set after a connection is established."
+  :group 'erc
+  :type '(choice (const nil) string function))
+
+
+(defcustom erc-prompt-for-password t
+  "Asks before using the default password, or whether to enter a new one."
+  :group 'erc
+  :type 'boolean)
+
+(defcustom erc-warn-about-blank-lines t
+  "Warn the user if they attempt to send a blank line."
+  :group 'erc
+  :type 'boolean)
+
+(defcustom erc-send-whitespace-lines nil
+  "If set to non-nil, send lines consisting of only whitespace."
+  :group 'erc
+  :type 'boolean)
+
+(defcustom erc-hide-prompt nil
+  "If non-nil, do not display the prompt for commands.
+
+\(A command is any input starting with a '/').
+
+See also the variables `erc-prompt' and `erc-command-indicator'."
+  :group 'erc-display
+  :type 'boolean)
+
+;; tunable GUI stuff
+
+(defcustom erc-show-my-nick t
+  "If non-nil, display one's own nickname when sending a message.
+
+If non-nil, \"<nickname>\" will be shown.
+If nil, only \"> \" will be shown."
+  :group 'erc-display
+  :type 'boolean)
+
+(define-widget 'erc-message-type 'set
+  "A set of standard IRC Message types."
+  :args '((const "JOIN")
+	  (const "KICK")
+	  (const "NICK")
+	  (const "PART")
+	  (const "QUIT")
+	  (const "MODE")
+	  (repeat :inline t :tag "Others" (string :tag "IRC Message Type"))))
+
+(defcustom erc-hide-list nil
+  "*List of IRC type messages to hide.
+A typical value would be '(\"JOIN\" \"PART\" \"QUIT\")."
+  :group 'erc-ignore
+  :type 'erc-message-type)
+
+(defvar erc-session-password nil
+  "The password used for the current session.")
+(make-variable-buffer-local 'erc-session-password)
+
+(defcustom erc-disconnected-hook nil
+  "Run this hook with arguments (NICK IP REASON) when disconnected.
+This happens before automatic reconnection.  Note, that
+`erc-server-QUIT-functions' might not be run when we disconnect,
+simply because we do not necessarily receive the QUIT event."
+  :group 'erc-hooks
+  :type 'hook)
+
+(defcustom erc-complete-functions nil
+  "These functions get called when the user hits TAB in ERC.
+Each function in turn is called until one returns non-nil to
+indicate it has handled the input."
+  :group 'erc-hooks
+  :type 'hook)
+
+(defcustom erc-join-hook nil
+  "Hook run when we join a channel.  Hook functions are called
+without arguments, with the current buffer set to the buffer of
+the new channel.
+
+See also `erc-server-JOIN-functions', `erc-part-hook'."
+  :group 'erc-hooks
+  :type 'hook)
+
+(defcustom erc-quit-hook nil
+  "Hook run when processing a quit command directed at our nick.
+
+The hook receives one argument, the current PROCESS.
+See also `erc-server-QUIT-functions' and `erc-disconnected-hook'."
+  :group 'erc-hooks
+  :type 'hook)
+
+(defcustom erc-part-hook nil
+  "Hook run when processing a PART message directed at our nick.
+
+The hook receives one argument, the current BUFFER.
+See also `erc-server-QUIT-functions', `erc-quit-hook' and
+`erc-disconnected-hook'."
+  :group 'erc-hooks
+  :type 'hook)
+
+(defcustom erc-kick-hook nil
+  "Hook run when processing a KICK message directed at our nick.
+
+The hook receives one argument, the current BUFFER.
+See also `erc-server-PART-functions' and `erc-part-hook'."
+  :group 'erc-hooks
+  :type 'hook)
+
+(defcustom erc-nick-changed-functions nil
+  "List of functions run when your nick was successfully changed.
+
+Each function should accept two arguments, NEW-NICK and OLD-NICK."
+  :group 'erc-hooks
+  :type 'hook)
+
+(defcustom erc-connect-pre-hook '(erc-initialize-log-marker)
+  "Hook called just before `erc' calls `erc-connect'.
+Functions are run in the buffer-to-be."
+  :group 'erc-hooks
+  :type 'hook)
+
+
+(defvar erc-channel-users nil
+  "A hash table of members in the current channel, which
+associates nicknames with cons cells of the form:
+\(USER . MEMBER-DATA) where USER is a pointer to an
+erc-server-user struct, and MEMBER-DATA is a pointer to an
+erc-channel-user struct.")
+(make-variable-buffer-local 'erc-channel-users)
+
+(defvar erc-server-users nil
+  "A hash table of users on the current server, which associates
+nicknames with erc-server-user struct instances.")
+(make-variable-buffer-local 'erc-server-users)
+
+(defun erc-downcase (string)
+  "Convert STRING to IRC standard conforming downcase."
+  (let ((s (downcase string))
+	(c '((?\[ . ?\{)
+	     (?\] . ?\})
+	     (?\\ . ?\|)
+	     (?~  . ?^))))
+    (save-match-data
+      (while (string-match "[]\\[~]" s)
+	(aset s (match-beginning 0)
+	      (cdr (assq (aref s (match-beginning 0)) c)))))
+    s))
+
+(defstruct (erc-server-user (:type vector) :named)
+  ;; User data
+  nickname host login full-name info
+  ;; Buffers
+  ;;
+  ;; This is an alist of the form (BUFFER . CHANNEL-DATA), where
+  ;; CHANNEL-DATA is either nil or an erc-channel-user struct.
+  (buffers nil)
+  )
+
+(defstruct (erc-channel-user (:type vector) :named)
+  op voice
+  ;; Last message time (in the form of the return value of
+  ;; (current-time)
+  ;;
+  ;; This is useful for ordered name completion.
+  (last-message-time nil))
+
+(defsubst erc-get-channel-user (nick)
+  "Finds the (USER . CHANNEL-DATA) element corresponding to NICK
+in the current buffer's `erc-channel-users' hash table."
+  (gethash (erc-downcase nick) erc-channel-users))
+
+(defsubst erc-get-server-user (nick)
+  "Finds the USER corresponding to NICK in the current server's
+`erc-server-users' hash table."
+  (with-current-buffer (process-buffer erc-server-process)
+    (gethash (erc-downcase nick) erc-server-users)))
+
+(defsubst erc-add-server-user (nick user)
+  "This function is for internal use only.
+
+Adds USER with nickname NICK to the `erc-server-users' hash table."
+  (with-current-buffer (process-buffer erc-server-process)
+    (puthash (erc-downcase nick) user erc-server-users)))
+
+(defsubst erc-remove-server-user (nick)
+  "This function is for internal use only.
+
+Removes the user with nickname NICK from the `erc-server-users'
+hash table.  This user is not removed from the
+`erc-channel-users' lists of other buffers.
+
+See also: `erc-remove-user'."
+  (with-current-buffer (process-buffer erc-server-process)
+    (remhash (erc-downcase nick) erc-server-users)))
+
+(defun erc-change-user-nickname (user new-nick)
+  "This function is for internal use only.
+
+Changes the nickname of USER to NEW-NICK in the
+`erc-server-users' hash table.  The `erc-channel-users' lists of
+other buffers are also changed."
+  (let ((nick (erc-server-user-nickname user)))
+    (setf (erc-server-user-nickname user) new-nick)
+    (with-current-buffer (process-buffer erc-server-process)
+      (remhash (erc-downcase nick) erc-server-users)
+      (puthash (erc-downcase new-nick) user erc-server-users))
+    (dolist (buf (erc-server-user-buffers user))
+      (if (buffer-live-p buf)
+	  (with-current-buffer buf
+	    (let ((cdata (erc-get-channel-user nick)))
+	      (remhash (erc-downcase nick) erc-channel-users)
+	      (puthash (erc-downcase new-nick) cdata
+		       erc-channel-users)))))))
+
+(defun erc-remove-channel-user (nick)
+  "This function is for internal use only.
+
+Removes the user with nickname NICK from the `erc-channel-users'
+list for this channel.  If this user is not in the
+`erc-channel-users' list of any other buffers, the user is also
+removed from the server's `erc-server-users' list.
+
+See also: `erc-remove-server-user' and `erc-remove-user'."
+  (let ((channel-data (erc-get-channel-user nick)))
+    (when channel-data
+      (let ((user (car channel-data)))
+	(setf (erc-server-user-buffers user)
+	      (delq (current-buffer)
+		    (erc-server-user-buffers user)))
+	(remhash (erc-downcase nick) erc-channel-users)
+	(if (null (erc-server-user-buffers user))
+	    (erc-remove-server-user nick))))))
+
+(defun erc-remove-user (nick)
+  "This function is for internal use only.
+
+Removes the user with nickname NICK from the `erc-server-users'
+list as well as from all `erc-channel-users' lists.
+
+See also: `erc-remove-server-user' and
+`erc-remove-channel-user'."
+  (let ((user (erc-get-server-user nick)))
+    (when user
+      (let ((buffers (erc-server-user-buffers user)))
+	(dolist (buf buffers)
+	  (if (buffer-live-p buf)
+	      (with-current-buffer buf
+		(remhash (erc-downcase nick) erc-channel-users)
+		(run-hooks 'erc-channel-members-changed-hook)))))
+      (erc-remove-server-user nick))))
+
+(defun erc-remove-channel-users ()
+  "This function is for internal use only.
+
+Removes all users in the current channel.  This is called by
+`erc-server-PART' and `erc-server-QUIT'."
+  (when (and erc-server-connected
+	     (erc-server-process-alive)
+	     (hash-table-p erc-channel-users))
+    (maphash (lambda (nick cdata)
+	       (erc-remove-channel-user nick))
+	     erc-channel-users)
+    (clrhash erc-channel-users)))
+
+(defsubst erc-channel-user-op-p (nick)
+  "Return `t' if NICK is an operator in the current channel."
+  (and nick
+       (hash-table-p erc-channel-users)
+       (let ((cdata (erc-get-channel-user nick)))
+	 (and cdata (cdr cdata)
+	      (erc-channel-user-op (cdr cdata))))))
+
+(defsubst erc-channel-user-voice-p (nick)
+  "Return `t' if NICK has voice in the current channel."
+  (and nick
+       (hash-table-p erc-channel-users)
+       (let ((cdata (erc-get-channel-user nick)))
+	 (and cdata (cdr cdata)
+	      (erc-channel-user-voice (cdr cdata))))))
+
+(defun erc-get-channel-user-list ()
+  "Returns a list of users in the current channel.  Each element
+of the list is of the form (USER . CHANNEL-DATA), where USER is
+an erc-server-user struct, and CHANNEL-DATA is either `nil' or an
+erc-channel-user struct.
+
+See also: `erc-sort-channel-users-by-activity'"
+  (let (users)
+    (if (hash-table-p erc-channel-users)
+      (maphash (lambda (nick cdata)
+		 (setq users (cons cdata users)))
+	       erc-channel-users))
+    users))
+
+(defun erc-get-server-nickname-list ()
+  "Returns a list of known nicknames on the current server."
+    (if (erc-server-process-alive)
+	(with-current-buffer (erc-server-buffer)
+	  (let (nicks)
+	    (when (hash-table-p erc-server-users)
+	      (maphash (lambda (n user)
+			 (setq nicks
+			       (cons (erc-server-user-nickname user)
+				     nicks)))
+		       erc-server-users)
+	      nicks)))))
+
+(defun erc-get-channel-nickname-list ()
+  "Returns a list of known nicknames on the current channel."
+  (let (nicks)
+    (when (hash-table-p erc-channel-users)
+      (maphash (lambda (n cdata)
+		 (setq nicks
+		       (cons (erc-server-user-nickname (car cdata))
+			     nicks)))
+	       erc-channel-users)
+      nicks)))
+
+(defun erc-get-server-nickname-alist ()
+  "Returns an alist of known nicknames on the current server."
+    (if (erc-server-process-alive)
+	(with-current-buffer (erc-server-buffer)
+	  (let (nicks)
+	    (when (hash-table-p erc-server-users)
+	      (maphash (lambda (n user)
+			 (setq nicks
+			       (cons (cons (erc-server-user-nickname user) nil)
+				     nicks)))
+		       erc-server-users)
+	      nicks)))))
+
+(defun erc-get-channel-nickname-alist ()
+  "Returns an alist of known nicknames on the current channel."
+  (let (nicks)
+    (when (hash-table-p erc-channel-users)
+      (maphash (lambda (n cdata)
+		 (setq nicks
+		       (cons (cons (erc-server-user-nickname (car cdata)) nil)
+			     nicks)))
+	       erc-channel-users)
+      nicks)))
+
+(defun erc-sort-channel-users-by-activity (list)
+  "Sorts LIST such that users which have spoken most recently are
+listed first.  LIST must be of the form (USER . CHANNEL-DATA).
+
+See also: `erc-get-channel-user-list'."
+  (sort list
+	(lambda (x y)
+	  (when (and
+		 (cdr x) (cdr y))
+	    (let ((tx (erc-channel-user-last-message-time (cdr x)))
+		  (ty (erc-channel-user-last-message-time (cdr y))))
+	      (if tx
+		  (if ty
+		      (time-less-p ty tx)
+		    t)
+		nil))))))
+
+(defun erc-sort-channel-users-alphabetically (list)
+  "Sort LIST so that users' nicknames are in alphabetical order.
+LIST must be of the form (USER . CHANNEL-DATA).
+
+See also: `erc-get-channel-user-list'."
+  (sort list
+	(lambda (x y)
+	  (when (and
+		 (cdr x) (cdr y))
+	    (let ((nickx (downcase (erc-server-user-nickname (car x))))
+		  (nicky (downcase (erc-server-user-nickname (car y)))))
+	      (if nickx
+		  (if nicky
+		      (string-lessp nickx nicky)
+		    t)
+		nil))))))
+
+(defvar erc-channel-topic nil
+  "A topic string for the channel.  Should only be used in channel-buffers.")
+(make-variable-buffer-local 'erc-channel-topic)
+
+(defvar erc-channel-modes nil
+  "List of strings representing channel modes.
+E.g. '(\"i\" \"m\" \"s\" \"b Quake!*@*\")
+\(not sure the ban list will be here, but why not)")
+(make-variable-buffer-local 'erc-channel-modes)
+
+(defvar erc-insert-marker nil
+  "The place where insertion of new text in erc buffers should happen.")
+(make-variable-buffer-local 'erc-insert-marker)
+
+(defvar erc-input-marker nil
+  "The marker where input should be inserted.")
+(make-variable-buffer-local 'erc-input-marker)
+
+(defun erc-string-no-properties (string)
+  "Return a copy of STRING will all text-properties removed."
+  (let ((newstring (copy-sequence string)))
+    (set-text-properties 0 (length newstring) nil newstring)
+    newstring))
+
+(defcustom erc-prompt "ERC>"
+  "Prompt used by ERC.  Trailing whitespace is not required."
+  :group 'erc-display
+  :type '(choice string function))
+
+(defun erc-prompt ()
+  "Return the input prompt as a string.
+
+See also the variable `erc-prompt'."
+  (let ((prompt (if (functionp erc-prompt)
+		    (funcall erc-prompt)
+		  erc-prompt)))
+    (if (> (length prompt) 0)
+	(concat prompt " ")
+      prompt)))
+
+(defcustom erc-command-indicator nil
+  "Indicator used by ERC for showing commands.
+
+If non-nil, this will be used in the ERC buffer to indicate
+commands (i.e., input starting with a '/').
+
+If nil, the prompt will be constructed from the variable `erc-prompt'."
+  :group 'erc-display
+  :type '(choice (const nil) string function))
+
+(defun erc-command-indicator ()
+  "Return the command indicator prompt as a string.
+
+This only has any meaning if the variable `erc-command-indicator' is non-nil."
+  (and erc-command-indicator
+       (let ((prompt (if (functionp erc-command-indicator)
+			 (funcall erc-command-indicator)
+			 erc-command-indicator)))
+	 (if (> (length prompt) 0)
+	     (concat prompt " ")
+	     prompt))))
+
+(defcustom erc-notice-prefix "*** "
+  "*Prefix for all notices."
+  :group 'erc-display
+  :type 'string)
+
+(defcustom erc-notice-highlight-type 'all
+  "*Determines how to highlight notices.
+See `erc-notice-prefix'.
+
+The following values are allowed:
+
+    'prefix - highlight notice prefix only
+    'all    - highlight the entire notice
+
+Any other value disables notice's highlighting altogether."
+  :group 'erc-display
+  :type '(choice (const :tag "highlight notice prefix only" prefix)
+		 (const :tag "highlight the entire notice" all)
+		 (const :tag "don't highlight notices at all" nil)))
+
+(defcustom erc-echo-notice-hook nil
+  "*Specifies a list of functions to call to echo a private
+notice.  Each function is called with four arguments, the string
+to display, the parsed server message, the target buffer (or
+nil), and the sender.  The functions are called in order, until a
+function evaluates to non-nil.  These hooks are called after
+those specified in `erc-echo-notice-always-hook'.
+
+See also: `erc-echo-notice-always-hook',
+`erc-echo-notice-in-default-buffer',
+`erc-echo-notice-in-target-buffer',
+`erc-echo-notice-in-minibuffer',
+`erc-echo-notice-in-server-buffer',
+`erc-echo-notice-in-active-non-server-buffer',
+`erc-echo-notice-in-active-buffer',
+`erc-echo-notice-in-user-buffers',
+`erc-echo-notice-in-user-and-target-buffers',
+`erc-echo-notice-in-first-user-buffer'"
+  :group 'erc-hooks
+  :type 'hook
+  :options '(erc-echo-notice-in-default-buffer
+	     erc-echo-notice-in-target-buffer
+	     erc-echo-notice-in-minibuffer
+	     erc-echo-notice-in-server-buffer
+	     erc-echo-notice-in-active-non-server-buffer
+	     erc-echo-notice-in-active-buffer
+	     erc-echo-notice-in-user-buffers
+	     erc-echo-notice-in-user-and-target-buffers
+	     erc-echo-notice-in-first-user-buffer))
+
+(defcustom erc-echo-notice-always-hook
+  '(erc-echo-notice-in-default-buffer)
+  "*Specifies a list of functions to call to echo a private
+notice.  Each function is called with four arguments, the string
+to display, the parsed server message, the target buffer (or
+nil), and the sender.  The functions are called in order, and all
+functions are called.  These hooks are called before those
+specified in `erc-echo-notice-hook'.
+
+See also: `erc-echo-notice-hook',
+`erc-echo-notice-in-default-buffer',
+`erc-echo-notice-in-target-buffer',
+`erc-echo-notice-in-minibuffer',
+`erc-echo-notice-in-server-buffer',
+`erc-echo-notice-in-active-non-server-buffer',
+`erc-echo-notice-in-active-buffer',
+`erc-echo-notice-in-user-buffers',
+`erc-echo-notice-in-user-and-target-buffers',
+`erc-echo-notice-in-first-user-buffer'"
+  :group 'erc-hooks
+  :type 'hook
+  :options '(erc-echo-notice-in-default-buffer
+	     erc-echo-notice-in-target-buffer
+	     erc-echo-notice-in-minibuffer
+	     erc-echo-notice-in-server-buffer
+	     erc-echo-notice-in-active-non-server-buffer
+	     erc-echo-notice-in-active-buffer
+	     erc-echo-notice-in-user-buffers
+	     erc-echo-notice-in-user-and-target-buffers
+	     erc-echo-notice-in-first-user-buffer))
+
+;; other tunable parameters
+
+(defcustom erc-whowas-on-nosuchnick nil
+  "*If non-nil, do a whowas on a nick if no such nick."
+  :group 'erc
+  :type 'boolean)
+
+(defcustom erc-verbose-server-ping nil
+  "*If non-nil, show every time you get a PING or PONG from the server."
+  :group 'erc-paranoia
+  :type 'boolean)
+
+(defcustom erc-public-away-p nil
+  "*Let others know you are back when you are no longer marked away.
+This happens in this form:
+* <nick> is back (gone for <time>)
+
+Many consider it impolite to do so automatically."
+  :group 'erc
+  :type 'boolean)
+
+(defcustom erc-away-nickname nil
+  "*The nickname to take when you are marked as being away."
+  :group 'erc
+  :type '(choice (const nil)
+		 string))
+
+(defcustom erc-paranoid nil
+  "If non-nil, then all incoming CTCP requests will be shown."
+  :group 'erc-paranoia
+  :type 'boolean)
+
+(defcustom erc-disable-ctcp-replies nil
+  "Disable replies to CTCP requests that require a reply.
+If non-nil, then all incoming CTCP requests that normally require
+an automatic reply (like VERSION or PING) will be ignored.  Good to
+set if some hacker is trying to flood you away."
+  :group 'erc-paranoia
+  :type 'boolean)
+
+(defcustom erc-anonymous-login t
+  "Be paranoid, don't give away your machine name."
+  :group 'erc-paranoia
+  :type 'boolean)
+
+(defcustom erc-prompt-for-channel-key nil
+  "Prompt for channel key when using `erc-join-channel' interactively"
+  :group 'erc
+  :type 'boolean)
+
+(defcustom erc-email-userid "user"
+  "Use this as your email user ID."
+  :group 'erc
+  :type 'string)
+
+(defcustom erc-ignore-list nil
+  "*List of regexps matching user identifiers to ignore.
+
+A user identifier has the form \"nick!login@host\".  If an
+identifier matches, the message from the person will not be
+processed."
+  :group 'erc-ignore
+  :type '(repeat regexp))
+(make-variable-buffer-local 'erc-ignore-list)
+
+(defcustom erc-ignore-reply-list nil
+  "*List of regexps matching user identifiers to ignore completely.
+
+This differs from `erc-ignore-list' in that it also ignores any
+messages directed at the user.
+
+A user identifier has the form \"nick!login@host\".
+
+If an identifier matches, or a message is addressed to a nick
+whose identifier matches, the message will not be processed.
+
+CAVEAT: ERC doesn't know about the user and host of anyone who
+was already in the channel when you joined, but never said
+anything, so it won't be able to match the user and host of those
+people. You can update the ERC internal info using /WHO *."
+  :group 'erc-ignore
+  :type '(repeat regexp))
+
+(defvar erc-flood-protect t
+  "*If non-nil, flood protection is enabled.
+Flooding is sending too much information to the server in too
+short of an interval, which may cause the server to terminate the
+connection.
+
+See `erc-server-flood-margin' for other flood-related parameters.")
+
+;; Script parameters
+
+(defcustom erc-startup-file-list
+  '("~/.ercrc.el" "~/.ercrc" ".ercrc.el" ".ercrc")
+  "List of files to try for a startup script.
+The first existent and readable one will get executed.
+
+If the filename ends with `.el' it is presumed to be an emacs-lisp
+script and it gets (load)ed.  Otherwise is is treated as a bunch of
+regular IRC commands"
+  :group 'erc-scripts
+  :type '(repeat file))
+
+(defcustom erc-script-path nil
+  "List of directories to look for a script in /load command.
+The script is first searched in the current directory, then in each
+directory in the list."
+  :group 'erc-scripts
+  :type '(repeat directory))
+
+(defcustom erc-script-echo t
+  "*If not-NIL, echo the IRC script commands locally."
+  :group 'erc-scripts
+  :type 'boolean)
+
+(defvar erc-last-saved-position nil
+  "A marker containing the position the current buffer was last saved at.")
+(make-variable-buffer-local 'erc-last-saved-position)
+
+(defcustom erc-kill-buffer-on-part nil
+  "Kill the channel buffer on PART.
+This variable should probably stay nil, as ERC can reuse buffers if
+you rejoin them later."
+  :group 'erc-quit-and-part
+  :type 'boolean)
+
+(defcustom erc-kill-queries-on-quit nil
+  "Kill all query (also channel) buffers of this server on QUIT.
+See the variable `erc-kill-buffer-on-part' for details."
+  :group 'erc-quit-and-part
+  :type 'boolean)
+
+(defcustom erc-kill-server-buffer-on-quit nil
+  "Kill the server buffer of the process on QUIT."
+  :group 'erc-quit-and-part
+  :type 'boolean)
+
+(defcustom erc-quit-reason-various-alist nil
+  "Alist of possible arguments to the /quit command.
+
+Each element has the form:
+  (REGEXP RESULT)
+
+If REGEXP matches the argument to /quit, then its relevant RESULT
+will be used.  RESULT may be either a string, or a function.  If
+a function, it should return the quit message as a string.
+
+If no elements match, then the empty string is used.
+
+As an example:
+  (setq erc-quit-reason-various-alist
+      '((\"zippy\" erc-quit-reason-zippy)
+	(\"xmms\" dme:now-playing)
+	(\"version\" erc-quit-reason-normal)
+	(\"home\" \"Gone home !\")
+	(\"\" \"Default Reason\")))
+If the user types \"/quit zippy\", then a Zippy the Pinhead quotation
+will be used as the quit message."
+  :group 'erc-quit-and-part
+  :type '(repeat (list regexp (choice (string) (function)))))
+
+(defcustom erc-part-reason-various-alist nil
+  "Alist of possible arguments to the /part command.
+
+Each element has the form:
+  (REGEXP RESULT)
+
+If REGEXP matches the argument to /part, then its relevant RESULT
+will be used.  RESULT may be either a string, or a function.  If
+a function, it should return the part message as a string.
+
+If no elements match, then the empty string is used.
+
+As an example:
+  (setq erc-part-reason-various-alist
+      '((\"zippy\" erc-part-reason-zippy)
+	(\"xmms\" dme:now-playing)
+	(\"version\" erc-part-reason-normal)
+	(\"home\" \"Gone home !\")
+	(\"\" \"Default Reason\")))
+If the user types \"/part zippy\", then a Zippy the Pinhead quotation
+will be used as the part message."
+  :group 'erc-quit-and-part
+  :type '(repeat (list regexp (choice (string) (function)))))
+
+(defcustom erc-quit-reason 'erc-quit-reason-normal
+  "*A function which returns the reason for quitting.
+
+The function is passed a single argument, the string typed by the
+user after \"/quit\"."
+  :group 'erc-quit-and-part
+  :type '(choice (const erc-quit-reason-normal)
+		 (const erc-quit-reason-zippy)
+		 (const erc-quit-reason-various)
+		 (symbol)))
+
+(defcustom erc-part-reason 'erc-part-reason-normal
+  "A function which returns the reason for parting a channel.
+
+The function is passed a single argument, the string typed by the
+user after \"/PART\"."
+  :group 'erc-quit-and-part
+  :type '(choice (const erc-part-reason-normal)
+		 (const erc-part-reason-zippy)
+		 (const erc-part-reason-various)
+		 (symbol)))
+
+(defvar erc-grab-buffer-name "*erc-grab*"
+  "The name of the buffer created by `erc-grab-region'.")
+
+;; variables available for IRC scripts
+
+(defvar erc-user-information "ERC User"
+  "USER_INFORMATION IRC variable.")
+
+;; Hooks
+
+(defgroup erc-hooks nil
+  "Hook variables for fancy customizations of ERC."
+  :group 'erc)
+
+(defcustom erc-mode-hook nil
+  "Hook run after `erc-mode' setup is finished."
+  :group 'erc-hooks
+  :type 'hook
+  :options '(erc-add-scroll-to-bottom))
+
+(defcustom erc-timer-hook nil
+  "Put functions which should get called more or less periodically here.
+The idea is that servers always play ping pong with the client, and so there
+is no need for any idle-timer games with Emacs."
+  :group 'erc-hooks
+  :type 'hook)
+
+(defcustom erc-insert-pre-hook nil
+  "Hook called first when some text is inserted through `erc-display-line'.
+It gets called with one argument, STRING.
+To be able to modify the inserted text, use `erc-insert-modify-hook' instead.
+Filtering functions can set `erc-insert-this' to nil to avoid
+display of that particular string at all."
+  :group 'erc-hooks
+  :type 'hook)
+
+(defcustom erc-send-pre-hook nil
+  "Hook called first when some text is sent through `erc-send-current-line'.
+It gets called with one argument, STRING.
+
+To change the text that will be sent, set the variable STR which is
+used in `erc-send-current-line'.
+
+To change the text inserted into the buffer without changing the text
+that will be sent, use `erc-send-modify-hook' instead.
+
+Filtering functions can set `erc-send-this' to nil to avoid sending of
+that particular string at all and `erc-insert-this' to prevent
+inserting that particular string into the buffer.
+
+Note that it's useless to set `erc-send-this' to nil and
+`erc-insert-this' to t.  ERC is sane enough to not insert the text
+anyway."
+  :group 'erc-hooks
+  :type 'hook)
+
+(defvar erc-insert-this t
+  "Insert the text into the target buffer or not.
+Functions on `erc-insert-pre-hook' can set this variable to nil
+if they wish to avoid insertion of a particular string.")
+
+(defvar erc-send-this t
+  "Send the text to the target or not.
+Functions on `erc-send-pre-hook' can set this variable to nil
+if they wish to avoid sending of a particular string.")
+
+(defcustom erc-insert-modify-hook ()
+  "Insertion hook for functions that will change the text's appearance.
+This hook is called just after `erc-insert-pre-hook' when the value
+of `erc-insert-this' is t.
+While this hook is run, narrowing is in effect and `current-buffer' is
+the buffer where the text got inserted.  One possible value to add here
+is `erc-fill'."
+  :group 'erc-hooks
+  :type 'hook)
+
+(defcustom erc-insert-post-hook nil
+  "This hook is called just after `erc-insert-modify-hook'.
+At this point, all modifications from prior hook functions are done."
+  :group 'erc-hooks
+  :type 'hook
+  :options '(erc-truncate-buffer
+	     erc-make-read-only
+	     erc-save-buffer-in-logs))
+
+(defcustom erc-send-modify-hook nil
+  "Sending hook for functions that will change the text's appearance.
+This hook is called just after `erc-send-pre-hook' when the values
+of `erc-send-this' and `erc-insert-this' are both t.
+While this hook is run, narrowing is in effect and `current-buffer' is
+the buffer where the text got inserted.
+
+Note that no function in this hook can change the appearance of the
+text that is sent.  Only changing the sent text's appearance on the
+sending user's screen is possible.  One possible value to add here
+is `erc-fill'."
+  :group 'erc-hooks
+  :type 'hook)
+
+(defcustom erc-send-post-hook nil
+  "This hook is called just after `erc-send-modify-hook'.
+At this point, all modifications from prior hook functions are done.
+NOTE: The functions on this hook are called _before_ sending a command
+to the server.
+
+This function is called with narrowing, ala `erc-send-modify-hook'"
+  :group 'erc-hooks
+  :type 'hook
+  :options '(erc-make-read-only))
+
+(defcustom erc-send-completed-hook
+  (when (featurep 'emacspeak)
+    (list (byte-compile
+	   (lambda (str)
+	     (emacspeak-auditory-icon 'select-object)))))
+  "Hook called after a message has been parsed by ERC.
+
+The single argument to the functions is the unmodified string
+which the local user typed."
+  :group 'erc-hooks
+  :type 'hook)
+;; mode-specific tables
+
+(defvar erc-mode-syntax-table
+  (let ((syntax-table (make-syntax-table)))
+    (modify-syntax-entry ?\" ".   " syntax-table)
+    (modify-syntax-entry ?\\ ".   " syntax-table)
+    (modify-syntax-entry ?' "w   " syntax-table)
+    ;; Make dabbrev-expand useful for nick names
+    (modify-syntax-entry ?< "." syntax-table)
+    (modify-syntax-entry ?> "." syntax-table)
+    syntax-table)
+  "Syntax table used while in ERC mode.")
+
+(defvar erc-mode-abbrev-table nil
+  "Abbrev table used while in ERC mode.")
+(define-abbrev-table 'erc-mode-abbrev-table ())
+
+(defvar erc-mode-map
+  (let ((map (make-sparse-keymap)))
+    (define-key map "\C-m" 'erc-send-current-line)
+    (define-key map "\C-a" 'erc-bol)
+    (define-key map [home] 'erc-bol)
+    (define-key map "\C-c\C-a" 'erc-bol)
+    (define-key map "\C-c\C-b" 'erc-iswitchb)
+    (define-key map "\C-c\C-c" 'erc-toggle-interpret-controls)
+    (define-key map "\C-c\C-d" 'erc-input-action)
+    (define-key map "\C-c\C-e" 'erc-toggle-ctcp-autoresponse)
+    (define-key map "\C-c\C-f" 'erc-toggle-flood-control)
+    (define-key map "\C-c\C-i" 'erc-invite-only-mode)
+    (define-key map "\C-c\C-j" 'erc-join-channel)
+    (define-key map "\C-c\C-n" 'erc-channel-names)
+    (define-key map "\C-c\C-o" 'erc-get-channel-mode-from-keypress)
+    (define-key map "\C-c\C-p" 'erc-part-from-channel)
+    (define-key map "\C-c\C-q" 'erc-quit-server)
+    (define-key map "\C-c\C-r" 'erc-remove-text-properties-region)
+    (define-key map "\C-c\C-t" 'erc-set-topic)
+    (define-key map "\C-c\C-u" 'erc-kill-input)
+    (define-key map "\M-\t" 'ispell-complete-word)
+    (define-key map "\t" 'erc-complete-word)
+
+    ;; Suppress `font-lock-fontify-block' key binding since it
+    ;; destroys face properties.
+    (if (fboundp 'command-remapping)
+	(define-key map [remap font-lock-fontify-block] 'undefined)
+      (substitute-key-definition
+       'font-lock-fontify-block 'undefined map global-map))
+
+    map)
+  "ERC keymap.")
+
+;; Faces
+
+; Honestly, I have a horrible sense of color and the "defaults" below
+; are supposed to be really bad. But colors ARE required in IRC to
+; convey different parts of conversation. If you think you know better
+; defaults - send them to me.
+
+;; Now colors are a bit nicer, at least to my eyes.
+;; You may still want to change them to better fit your background.-- S.B.
+
+(defgroup erc-faces nil
+  "Faces for ERC."
+  :group 'erc)
+
+(defface erc-default-face '((t))
+  "ERC default face."
+  :group 'erc-faces)
+
+(defface erc-direct-msg-face '((t (:foreground "IndianRed")))
+  "ERC face used for messages you receive in the main erc buffer."
+  :group 'erc-faces)
+
+(defface erc-input-face '((t (:foreground "brown")))
+  "ERC face used for your input."
+  :group 'erc-faces)
+
+(defface erc-prompt-face
+  '((t (:bold t :foreground "Black" :background"lightBlue2")))
+  "ERC face for the prompt."
+  :group 'erc-faces)
+
+(defface erc-command-indicator-face
+    '((t (:bold t)))
+  "ERC face for the command indicator.
+See the variable `erc-command-indicator'."
+  :group 'erc-faces)
+
+(defface erc-notice-face '((t (:bold t :foreground "SlateBlue")))
+  "ERC face for notices."
+  :group 'erc-faces)
+
+(defface erc-action-face '((t (:bold t)))
+  "ERC face for actions generated by /ME."
+  :group 'erc-faces)
+
+(defface erc-error-face '((t (:foreground "red")))
+  "ERC face for errors."
+  :group 'erc-faces)
+
+(defface erc-nick-default-face '((t (:bold t)))
+  "ERC nickname default face."
+  :group 'erc-faces)
+
+(defface erc-nick-msg-face '((t (:bold t :foreground "IndianRed")))
+  "ERC nickname face for private messages."
+  :group 'erc-faces)
+
+;; Debugging support
+
+(defvar erc-log-p nil
+  "When set to t, generate debug messages in a separate debug buffer.")
+
+(defvar erc-debug-log-file (expand-file-name "ERC.debug")
+  "Debug log file name.")
+
+(defvar erc-dbuf nil)
+(make-variable-buffer-local 'erc-dbuf)
+
+(defmacro define-erc-module (name alias doc enable-body disable-body
+			     &optional local-p)
+  "Define a new minor mode using ERC conventions.
+Symbol NAME is the name of the module.
+Symbol ALIAS is the alias to use, or nil.
+DOC is the documentation string to use for the minor mode.
+ENABLE-BODY is a list of expressions used to enable the mode.
+DISABLE-BODY is a list of expressions used to disable the mode.
+If LOCAL-P is non-nil, the mode will be created as a buffer-local
+mode.  Rather than a global one.
+
+This will define a minor mode called erc-NAME-mode, possibly
+an alias erc-ALIAS-mode, as well as the helper functions
+erc-NAME-enable, and erc-NAME-disable.
+
+Example:
+
+  ;;;###autoload (autoload 'erc-replace-mode \"erc-replace\")
+  (define-erc-module replace nil
+    \"This mode replaces incoming text according to `erc-replace-alist'.\"
+    ((add-hook 'erc-insert-modify-hook
+	       'erc-replace-insert))
+    ((remove-hook 'erc-insert-modify-hook
+		  'erc-replace-insert)))"
+  (let* ((sn (symbol-name name))
+	 (mode (intern (format "erc-%s-mode" (downcase sn))))
+	 (group (intern (format "erc-%s" (downcase sn))))
+	 (enable (intern (format "erc-%s-enable" (downcase sn))))
+	 (disable (intern (format "erc-%s-disable" (downcase sn)))))
+    `(progn
+       (erc-define-minor-mode
+	,mode
+	,(format "Toggle ERC %S mode.
+With arg, turn ERC %S mode on if and only if arg is positive.
+%s" name name doc)
+	nil nil nil
+	:global ,(not local-p) :group (quote ,group)
+	(if ,mode
+	    (,enable)
+	  (,disable)))
+       (defun ,enable ()
+	 ,(format "Enable ERC %S mode."
+		  name)
+	 (interactive)
+	 (add-to-list 'erc-modules (quote ,name))
+	 (setq ,mode t)
+	 ,@enable-body)
+       (defun ,disable ()
+	 ,(format "Disable ERC %S mode."
+		  name)
+	 (interactive)
+	 (setq erc-modules (delq (quote ,name) erc-modules))
+	 (setq ,mode nil)
+	 ,@disable-body)
+       ,(when (and alias (not (eq name alias)))
+	  `(defalias
+	     (quote
+	      ,(intern
+		(format "erc-%s-mode"
+			(downcase (symbol-name alias)))))
+	     (quote
+	      ,mode))))))
+
+(put 'define-erc-module 'doc-string-elt 3)
+
+(defun erc-once-with-server-event (event &rest forms)
+  "Execute FORMS the next time EVENT occurs in the `current-buffer'.
+
+You should make sure that `current-buffer' is a server buffer.
+
+This function temporarily adds a function to EVENT's hook to
+execute FORMS.  After FORMS are run, the function is removed from
+EVENT's hook.  The last expression of FORMS should be either nil
+or t.  nil indicates that the other functions on EVENT's hook
+should be run too, and t indicates that other functions should
+not be run.
+
+Please be sure to use this function in server-buffers.  In
+channel-buffers it may not work at all, as it uses the LOCAL
+argument of `add-hook' and `remove-hook' to ensure multiserver
+capabilities."
+  (unless (erc-server-buffer-p)
+    (error
+     "You should only run `erc-once-with-server-event' in a server buffer"))
+  (let ((fun (erc-gensym))
+	(hook (erc-get-hook event)))
+     (put fun 'erc-original-buffer (current-buffer))
+     (fset fun `(lambda (proc parsed)
+		  (with-current-buffer (get ',fun 'erc-original-buffer)
+		    (remove-hook ',hook ',fun t))
+		  (fmakunbound ',fun)
+		  ,@forms))
+     (add-hook hook fun nil t)
+     fun))
+
+(defun erc-once-with-server-event-global (event &rest forms)
+  "Execute FORMS the next time EVENT occurs in any server buffer.
+
+This function temporarily prepends a function to EVENT's hook to
+execute FORMS.  After FORMS are run, the function is removed from
+EVENT's hook.  The last expression of FORMS should be either nil
+or t.  nil indicates that the other functions on EVENT's hook
+should be run too, and t indicates that other functions should
+not be run.
+
+When FORMS execute, the current buffer is the server buffer associated with the
+connection over which the data was received that triggered EVENT."
+  (let ((fun (erc-gensym))
+	(hook (erc-get-hook event)))
+     (fset fun `(lambda (proc parsed)
+		  (remove-hook ',hook ',fun)
+		  (fmakunbound ',fun)
+		  ,@forms))
+     (add-hook hook fun nil nil)
+     fun))
+
+(defmacro erc-log (string)
+  "Logs STRING if logging is on (see `erc-log-p')."
+  `(when erc-log-p
+     (erc-log-aux ,string)))
+
+(defun erc-server-buffer ()
+  "Return the server buffer for the current buffer's process.
+The buffer-local variable `erc-server-process' is used to find
+the process buffer."
+  (and (erc-server-buffer-live-p)
+       (process-buffer erc-server-process)))
+
+(defun erc-server-buffer-live-p ()
+  "Return t if the buffer associated with `erc-server-process'
+has not been killed."
+  (and (processp erc-server-process)
+       (buffer-live-p (process-buffer erc-server-process))))
+
+(defun erc-server-buffer-p (&optional buffer)
+  "Return non-nil if argument BUFFER is an ERC server buffer.
+
+If BUFFER is nil, the current buffer is used."
+  (with-current-buffer (or buffer (current-buffer))
+    (and (eq major-mode 'erc-mode)
+	 (null (erc-default-target)))))
+
+(defun erc-query-buffer-p (&optional buffer)
+  "Return non-nil if BUFFER is an ERC query buffer.
+If BUFFER is nil, the current buffer is used."
+  (with-current-buffer (or buffer (current-buffer))
+    (let ((target (erc-default-target)))
+      (and (eq major-mode 'erc-mode)
+	   target
+	   (not (memq (aref target 0) '(?# ?& ?+ ?!)))))))
+
+(defun erc-ison-p (nick)
+  "Return non-nil if NICK is online."
+  (interactive "sNick: ")
+  (with-current-buffer (erc-server-buffer)
+    (let ((erc-online-p 'unknown))
+      (erc-once-with-server-event
+       303
+       `(let ((ison (split-string (aref parsed 3))))
+	  (setq erc-online-p (car (erc-member-ignore-case ,nick ison)))
+	  t))
+      (erc-server-send (format "ISON %s" nick))
+      (while (eq erc-online-p 'unknown) (accept-process-output))
+      (if (interactive-p)
+	  (message "%s is %sonline"
+		   (or erc-online-p nick)
+		   (if erc-online-p "" "not "))
+	erc-online-p))))
+
+(defun erc-log-aux (string)
+  "Do the debug logging of STRING."
+  (let ((cb (current-buffer))
+	(point 1)
+	(was-eob nil)
+	(session-buffer (erc-server-buffer)))
+    (if session-buffer
+	(progn
+	  (set-buffer session-buffer)
+	  (if (not (and erc-dbuf (bufferp erc-dbuf) (buffer-live-p erc-dbuf)))
+	      (progn
+		(setq erc-dbuf (get-buffer-create
+				(concat "*ERC-DEBUG: "
+					erc-session-server "*")))))
+	  (set-buffer erc-dbuf)
+	  (setq point (point))
+	  (setq was-eob (eobp))
+	  (goto-char (point-max))
+	  (insert (concat "** " string "\n"))
+	  (if was-eob (goto-char (point-max))
+	    (goto-char point))
+	  (set-buffer cb))
+      (message "ERC: ** %s" string))))
+
+;; Last active buffer, to print server messages in the right place
+
+(defvar erc-active-buffer nil
+  "The current active buffer, the one where the user typed the last command.
+Defaults to the server buffer, and should only be set in the
+server buffer")
+(make-variable-buffer-local 'erc-active-buffer)
+
+(defun erc-active-buffer ()
+  "Return the value of `erc-active-buffer' for the current server.
+Defaults to the server buffer."
+  (with-current-buffer (erc-server-buffer) erc-active-buffer))
+
+(defun erc-set-active-buffer (buffer)
+  "Set the value of `erc-active-buffer' to BUFFER."
+  (cond ((erc-server-buffer)
+	 (with-current-buffer (erc-server-buffer)
+	   (setq erc-active-buffer buffer)))
+	(t (setq erc-active-buffer buffer))))
+
+;; Mode activation routines
+
+(defun erc-mode ()
+  "Major mode for Emacs IRC.
+Special commands:
+
+\\{erc-mode-map}
+
+Turning on `erc-mode' runs the hook `erc-mode-hook'."
+  (kill-all-local-variables)
+  (use-local-map erc-mode-map)
+  (setq mode-name "ERC"
+	major-mode 'erc-mode
+	local-abbrev-table erc-mode-abbrev-table)
+  (set-syntax-table erc-mode-syntax-table)
+  (when (boundp 'next-line-add-newlines)
+    (set (make-local-variable 'next-line-add-newlines) nil))
+  (setq line-move-ignore-invisible t)
+  (set (make-local-variable 'paragraph-separate)
+       (concat "\C-l\\|\\(^" (regexp-quote (erc-prompt)) "\\)"))
+  (set (make-local-variable 'paragraph-start)
+       (concat "\\(" (regexp-quote (erc-prompt)) "\\)"))
+  ;; Run the mode hooks
+  (run-hooks 'erc-mode-hook))
+
+;; activation
+
+(defconst erc-default-server "irc.freenode.net"
+  "IRC server to use if it cannot be detected otherwise.")
+
+(defconst erc-default-port "ircd"
+  "IRC port to use if it cannot be detected otherwise.")
+
+(defcustom erc-join-buffer 'buffer
+  "Determines how to display the newly created IRC buffer.
+'window - in another window,
+'window-noselect - in another window, but don't select that one,
+'frame - in another frame,
+'bury - bury it in a new buffer,
+any other value - in place of the current buffer"
+  :group 'erc-buffers
+  :type '(choice (const window)
+		 (const window-noselect)
+		 (const frame)
+		 (const bury)
+		 (const buffer)))
+
+(defcustom erc-frame-alist nil
+  "*Alist of frame parameters for creating erc frames.
+A value of `nil means to use `default-frame-alist'."
+  :group 'erc-buffers
+  :type '(repeat (cons :format "%v"
+		       (symbol :tag "Parameter")
+		       (sexp :tag "Value"))))
+
+(defcustom erc-frame-dedicated-flag nil
+  "*Non-nil means the erc frames are dedicated to that buffer.
+This only has effect when `erc-join-buffer' is set to `frame'."
+  :group 'erc-buffers
+  :type 'boolean)
+
+(defun erc-channel-p (channel)
+  "Return non-nil if CHANNEL seems to be an IRC channel name."
+  (cond ((stringp channel)
+	 (memq (aref channel 0) '(?# ?& ?+ ?!)))
+	((and (bufferp channel) (buffer-live-p channel))
+	 (with-current-buffer channel
+	   (erc-channel-p (erc-default-target))))
+	(t nil)))
+
+(defcustom erc-reuse-buffers t
+  "*If nil, create new buffers on joining a channel/query.
+If non-nil, a new buffer will only be created when you join
+channels with same names on different servers, or have query buffers
+open with nicks of the same name on different servers.  Otherwise,
+the existing buffers will be reused."
+  :group 'erc-buffers
+  :type 'boolean)
+
+(defun erc-normalize-port (port)
+  "Normalize the port specification PORT to integer form.
+PORT may be an integer, a string or a symbol.  If it is a string or a
+symbol, it may have these values:
+* irc         -> 194
+* ircs        -> 994
+* ircd        -> 6667
+* ircd-dalnet -> 7000"
+  (cond
+   ((symbolp port)
+    (erc-normalize-port (symbol-name port)))
+   ((stringp port)
+    (let ((port-nr (string-to-number port)))
+      (cond
+       ((> port-nr 0)
+	port-nr)
+       ((string-equal port "irc")
+	194)
+       ((string-equal port "ircs")
+	994)
+       ((string-equal port "ircd")
+	6667)
+       ((string-equal port "ircd-dalnet")
+	7000)
+       (t
+	nil))))
+   ((numberp port)
+    port)
+   (t
+    nil)))
+
+(defun erc-port-equal (a b)
+  "Check whether ports A and B are equal."
+  (= (erc-normalize-port a) (erc-normalize-port b)))
+
+(defun erc-generate-new-buffer-name (server port target &optional proc)
+  "Create a new buffer name based on the arguments."
+  (when (numberp port) (setq port (number-to-string port)))
+  (let* ((buf-name (or target
+		       (or (let ((name (concat server ":" port)))
+			     (when (> (length name) 1)
+			       name))
+			   ; This fallback should in fact never happen
+			   "*erc-server-buffer*"))))
+    ;; Reuse existing buffers, but not if the buffer is a connected server
+    ;; buffer and not if its associated with a different server than the
+    ;; current ERC buffer.
+    (if (and erc-reuse-buffers
+	     (get-buffer buf-name)
+	     (or target
+		 (with-current-buffer (get-buffer buf-name)
+		   (and (erc-server-buffer-p)
+			(not erc-server-connected))))
+	     (with-current-buffer (get-buffer buf-name)
+	       (and (string= erc-session-server server)
+		    (erc-port-equal erc-session-port port))))
+	buf-name
+      (generate-new-buffer-name buf-name))))
+
+(defun erc-get-buffer-create (server port target &optional proc)
+  "Create a new buffer based on the arguments."
+  (get-buffer-create (erc-generate-new-buffer-name server port target proc)))
+
+
+(defun erc-member-ignore-case (string list)
+  "Return non-nil if STRING is a member of LIST.
+
+All strings are compared according to IRC protocol case rules, see
+`erc-downcase'."
+  (setq string (erc-downcase string))
+  (catch 'result
+    (while list
+      (if (string= string (erc-downcase (car list)))
+	  (throw 'result list) (setq list (cdr list))))))
+
+(defmacro erc-with-buffer (spec &rest body)
+  "Execute BODY in the buffer associated with SPEC.
+
+SPEC should have the form
+
+ (TARGET [PROCESS])
+
+If TARGET is a buffer, use it.  Otherwise, use the buffer
+matching TARGET in the process specified by PROCESS.
+
+If PROCESS is nil, use the current `erc-server-process'
+See `erc-get-buffer' for details.
+
+See also `with-current-buffer'.
+
+\(fn (TARGET [PROCESS]) BODY...)"
+  (let ((buf (erc-gensym))
+	(proc (erc-gensym))
+	(target (erc-gensym))
+	(process (erc-gensym)))
+    `(let* ((,target ,(car spec))
+	    (,process ,(cadr spec))
+	    (,buf (if (bufferp ,target)
+		      ,target
+		    (let ((,proc (or ,process
+				     (and (processp erc-server-process)
+					  erc-server-process))))
+		      (if (and ,target ,proc)
+			  (erc-get-buffer ,target ,proc))))))
+       (when ,buf
+	 (with-current-buffer ,buf
+	   ,@body)))))
+(put 'erc-with-buffer 'lisp-indent-function 1)
+(put 'erc-with-buffer 'edebug-form-spec '((form &optional form) body))
+
+(defun erc-get-buffer (target &optional proc)
+  "Return the buffer matching TARGET in the process PROC.
+If PROC is not supplied, all processes are searched."
+  (let ((downcased-target (erc-downcase target)))
+    (catch 'buffer
+      (erc-buffer-filter
+       (lambda ()
+	 (let ((current (erc-default-target)))
+	   (and (stringp current)
+		(string-equal downcased-target (erc-downcase current))
+		(throw 'buffer (current-buffer)))))
+       proc))))
+
+(defun erc-buffer-filter (predicate &optional proc)
+  "Return a list of `erc-mode' buffers matching certain criteria.
+PREDICATE is a function executed with each buffer, if it returns t, that buffer
+is considered a valid match.
+
+PROC is either an `erc-server-process', identifying a certain
+server connection, or nil which means all open connections."
+  (save-excursion
+    (delq
+     nil
+     (mapcar (lambda (buf)
+	       (with-current-buffer buf
+		 (and (eq major-mode 'erc-mode)
+		      (or (not proc)
+			  (eq proc erc-server-process))
+		      (funcall predicate)
+		      buf)))
+	     (buffer-list)))))
+
+(defun erc-buffer-list (&optional predicate proc)
+  "Return a list of ERC buffers.
+PREDICATE is a function which executes with every buffer satisfying
+the predicate.  If PREDICATE is passed as nil, return a list of all ERC
+buffers.  If PROC is given, the buffers local variable `erc-server-process'
+needs to match PROC."
+  (unless predicate
+    (setq predicate (lambda () t)))
+  (erc-buffer-filter predicate proc))
+
+(defmacro erc-with-all-buffers-of-server (process pred &rest forms)
+  "Execute FORMS in all buffers which have same process as this server.
+FORMS will be evaluated in all buffers having the process PROCESS and
+where PRED matches or in all buffers of the server process if PRED is
+nil."
+  ;; Make the evaluation have the correct order
+  (let ((pre (erc-gensym))
+	(pro (erc-gensym)))
+    `(let ((,pro ,process)
+	   (,pre ,pred))
+       (mapcar (lambda (buffer)
+		 (with-current-buffer buffer
+		   ,@forms))
+	       (erc-buffer-list ,pre
+				,pro)))))
+(put 'erc-with-all-buffers-of-server 'lisp-indent-function 1)
+(put 'erc-with-all-buffers-of-server 'edebug-form-spec '(form form body))
+
+(defun erc-iswitchb (&optional arg)
+  "Use `iswitchb-read-buffer' to prompt for a ERC buffer to switch to.
+When invoked with prefix argument, use all erc buffers.  Without prefix
+ARG, allow only buffers related to same session server.
+If `erc-track-mode' is in enabled, put the last element of
+`erc-modified-channels-alist' in front of the buffer list.
+
+Due to some yet unresolved reason, global function `iswitchb-mode'
+needs to be active for this function to work."
+  (interactive "P")
+  (eval-when-compile
+    (require 'iswitchb))
+  (let ((iswitchb-make-buflist-hook
+	 (lambda ()
+	   (setq iswitchb-temp-buflist
+		 (mapcar 'buffer-name
+			 (erc-buffer-list
+			  nil
+			  (when (and arg (boundp 'erc-server-process))
+			    erc-server-process)))))))
+    (switch-to-buffer
+     (iswitchb-read-buffer
+      "Switch-to: "
+      (if (boundp 'erc-modified-channels-alist)
+	  (buffer-name (caar (last erc-modified-channels-alist)))
+	nil)
+      t))))
+
+(defun erc-channel-list (proc)
+  "Return a list of channel buffers.
+PROC is the process for the server connection.  If PROC is nil, return
+all channel buffers on all servers."
+  (erc-buffer-filter
+   (lambda ()
+     (and (erc-default-target)
+	  (erc-channel-p (erc-default-target))))
+   proc))
+
+(defun erc-buffer-list-with-nick (nick proc)
+  "Return buffers containing NICK in the `erc-channel-users' list."
+  (with-current-buffer (process-buffer proc)
+    (let ((user (gethash (erc-downcase nick) erc-server-users)))
+      (if user
+	  (erc-server-user-buffers user)
+	nil))))
+
+;; Some local variables
+
+(defvar erc-default-recipients nil
+  "List of default recipients of the current buffer.")
+(make-variable-buffer-local 'erc-default-recipients)
+
+(defvar erc-session-user-full-name nil
+  "Full name of the user on the current server.")
+(make-variable-buffer-local 'erc-session-user-full-name)
+
+(defvar erc-channel-user-limit nil
+  "Limit of users per channel.")
+(make-variable-buffer-local 'erc-channel-user-limit)
+
+(defvar erc-channel-key nil
+  "Key needed to join channel.")
+(make-variable-buffer-local 'erc-channel-key)
+
+(defvar erc-invitation nil
+  "Last invitation channel.")
+(make-variable-buffer-local 'erc-invitation)
+
+(defvar erc-away nil
+  "Non-nil indicates that we are away.")
+(make-variable-buffer-local 'erc-away)
+
+(defvar erc-channel-list nil
+  "Server channel list.")
+(make-variable-buffer-local 'erc-channel-list)
+
+(defvar erc-bad-nick nil
+  "Non-nil indicates that we got a `nick in use' error while connecting.")
+(make-variable-buffer-local 'erc-bad-nick)
+
+(defvar erc-logged-in nil
+  "Non-nil indicates that we are logged in.")
+(make-variable-buffer-local 'erc-logged-in)
+
+(defvar erc-default-nicks nil
+  "The local copy of `erc-nick' - the list of nicks to choose from.")
+(make-variable-buffer-local 'erc-default-nicks)
+
+(defvar erc-nick-change-attempt-count 0
+  "Used to keep track of how many times an attempt at changing nick is made.")
+(make-variable-buffer-local 'erc-nick-change-attempt-count)
+
+(defcustom erc-modules '(netsplit fill button match track pcomplete readonly
+				  ring autojoin noncommands irccontrols
+				  stamp)
+  "A list of modules which erc should enable.
+If you set the value of this without using `customize' remember to call
+\(erc-update-modules) after you change it.  When using `customize', modules
+removed from the list will be disabled."
+  :set (lambda (sym val)
+	 ;; disable modules which have just been removed
+	 (when (and (boundp 'erc-modules) erc-modules val)
+	   (dolist (module erc-modules)
+	     (unless (member module val)
+	       (let ((f (intern-soft (format "erc-%s-mode" module))))
+		 (when (and (fboundp f) (boundp f) (symbol-value f))
+		   (message "Disabling `erc-%s'" module)
+		   (funcall f 0))))))
+	 (set-default sym val)
+	 ;; this test is for the case where erc hasn't been loaded yet
+	 (when (fboundp 'erc-update-modules)
+	   (erc-update-modules)))
+  :type '(set :greedy t
+	      (const :tag "Set away status automatically" autoaway)
+	      (const :tag "Join channels automatically" autojoin)
+	      (const :tag "Integrate with Big Brother Database" bbdb)
+	      (const :tag "Buttonize URLs, nicknames, and other text" button)
+	      (const :tag "Wrap long lines" fill)
+	      (const :tag "Highlight or remove IRC control characters"
+		     irccontrols)
+	      (const :tag "Save buffers in logs" log)
+	      (const :tag "Highlight pals, fools, and other keywords" match)
+	      (const :tag "Detect netsplits" netsplit)
+	      (const :tag "Don't display non-IRC commands after evaluation"
+		     noncommands)
+	      (const :tag
+		     "Notify when the online status of certain users changes"
+		     notify)
+	      (const :tag "Complete nicknames and commands (programmable)"
+		     pcomplete)
+	      (const :tag "Complete nicknames and commands (old)" completion)
+	      (const :tag "Make displayed lines read-only" readonly)
+	      (const :tag "Replace text in messages" replace)
+	      (const :tag "Enable an input history" ring)
+	      (const :tag "Scroll to the bottom of the buffer" scrolltobottom)
+	      (const :tag "Identify to Nickserv (IRC Services) automatically"
+		     services)
+	      (const :tag "Convert smileys to pretty icons" smiley)
+	      (const :tag "Play sounds when you receive CTCP SOUND requests"
+		     sound)
+	      (const :tag "Add timestamps to messages" stamp)
+	      (const :tag "Check spelling" spelling)
+	      (const :tag "Track channel activity in the mode-line" track)
+	      (const :tag "Truncate buffers to a certain size" truncate)
+	      (const :tag "Translate morse code in messages" unmorse)
+	      (repeat :tag "Others" :inline t symbol))
+  :group 'erc)
+
+(defun erc-update-modules ()
+  "Run this to enable erc-foo-mode for all modules in `erc-modules'."
+  (let (req)
+    (dolist (mod erc-modules)
+      (setq req (concat "erc-" (symbol-name mod)))
+      (cond
+       ;; yuck. perhaps we should bring the filenames into sync?
+       ((string= req "erc-completion")
+	(setq req "erc-pcomplete")
+	(setq mod 'pcomplete))
+       ((string= req "erc-services")
+	(setq req "erc-nickserv")
+	(setq mod 'services)))
+      (condition-case nil
+	  (require (intern req))
+	(error nil))
+      (funcall (or (intern-soft (concat "erc-" (symbol-name mod) "-mode"))
+		   (error "`%s' is not a known ERC module" mod))
+	       1))))
+
+(defun erc-setup-buffer (buffer)
+  "Consults `erc-join-buffer' to find out how to display `BUFFER'."
+  (cond ((eq erc-join-buffer 'window)
+	 (if (active-minibuffer-window)
+	     (display-buffer buffer)
+	   (switch-to-buffer-other-window buffer)))
+	((eq erc-join-buffer 'window-noselect)
+	 (display-buffer buffer))
+	((eq erc-join-buffer 'bury)
+	 nil)
+	((eq erc-join-buffer 'frame)
+	 (funcall '(lambda (frame)
+		     (raise-frame frame)
+		     (select-frame frame))
+		  (make-frame (or erc-frame-alist
+				  default-frame-alist)))
+	 (switch-to-buffer buffer)
+	 (when erc-frame-dedicated-flag
+	   (set-window-dedicated-p (selected-window) t)))
+	(t
+	 (if (active-minibuffer-window)
+	     (display-buffer buffer)
+	   (switch-to-buffer buffer)))))
+
+(defun erc (&optional server port nick full-name
+		      connect passwd tgt-list channel process)
+  "ERC is a powerful, modular, and extensible IRC client.
+
+Connect to SERVER on PORT as NICK with FULL-NAME.
+
+If CONNECT is non-nil, connect to the server.  Otherwise assume
+already connected and just create a separate buffer for the new
+target CHANNEL.
+
+Use PASSWD as user password on the server.  If TGT-LIST is
+non-nil, use it to initialise `erc-default-recipients'.
+
+Returns the buffer for the given server or channel."
+  (let ((server-announced-name (when (and (boundp 'erc-session-server)
+					  (string= server erc-session-server))
+				 erc-server-announced-name))
+	(connected-p (unless connect erc-server-connected))
+	(buffer (erc-get-buffer-create server port channel))
+	(old-buffer (current-buffer))
+	continued-session)
+    (erc-update-modules)
+    (set-buffer buffer)
+    (erc-mode)
+    (setq erc-server-announced-name server-announced-name)
+    (setq erc-server-connected connected-p)
+    ;; connection parameters
+    (setq erc-server-process process)
+    (setq erc-insert-marker (make-marker))
+    (setq erc-input-marker (make-marker))
+    ;; go to the end of the buffer and open a new line
+    ;; (the buffer may have existed)
+    (goto-char (point-max))
+    (forward-line 0)
+    (when (get-text-property (point) 'erc-prompt)
+      (setq continued-session t)
+      (set-marker erc-input-marker
+		  (or (next-single-property-change (point) 'erc-prompt)
+		      (point-max))))
+    (unless continued-session
+      (goto-char (point-max))
+      (insert "\n"))
+    (set-marker erc-insert-marker (point))
+    ;; stack of default recipients
+    (setq erc-default-recipients tgt-list)
+    (setq erc-server-current-nick nil)
+    ;; Initialize erc-server-users and erc-channel-users
+    (if connect
+	(progn ;; server buffer
+	  (setq erc-server-users
+		(make-hash-table :test 'equal))
+	  (setq erc-channel-users nil))
+      (progn ;; target buffer
+	(setq erc-server-users nil)
+	(setq erc-channel-users
+	      (make-hash-table :test 'equal))))
+    ;; clear last incomplete line read
+    (setq erc-server-filter-data nil)
+    (setq erc-channel-topic "")
+    ;; limit on the number of users on the channel (mode +l)
+    (setq erc-channel-user-limit nil)
+    (setq erc-channel-key nil)
+    ;; last active buffer, defaults to this one
+    (erc-set-active-buffer buffer)
+    ;; last invitation channel
+    (setq erc-invitation nil)
+    ;; away flag
+    ;; Should only be used in session-buffers
+    (setq erc-away (let ((serverbuf (erc-server-buffer)))
+		     (and serverbuf (with-current-buffer serverbuf erc-away))))
+    ;; Server channel list
+    (setq erc-channel-list ())
+    ;; login-time 'nick in use' error
+    (setq erc-bad-nick nil)
+    ;; whether we have logged in
+    (setq erc-logged-in nil)
+    ;; The local copy of `erc-nick' - the list of nicks to choose
+    (setq erc-default-nicks (if (consp erc-nick) erc-nick (list erc-nick)))
+    ;; password stuff
+    (setq erc-session-password passwd)
+    ;; debug output buffer
+    (setq erc-dbuf
+	  (when erc-log-p
+	    (get-buffer-create (concat "*ERC-DEBUG: " server "*"))))
+    (erc-determine-parameters server port nick full-name)
+
+    ;; Saving log file on exit
+    (run-hooks 'erc-connect-pre-hook)
+
+    (when connect
+      (erc-server-connect erc-session-server erc-session-port))
+    (erc-update-mode-line)
+    (set-marker erc-insert-marker (point))
+    (unless continued-session
+      (goto-char (point-max))
+      (insert "\n"))
+    (set-marker (process-mark erc-server-process) (point))
+    (unless continued-session
+      (set-marker erc-insert-marker (point))
+      (erc-display-prompt)
+      (goto-char (point-max)))
+
+    ;; Now display the buffer in a window as per user wishes.
+    (unless (eq buffer old-buffer)
+      (when erc-log-p
+	;; we can't log to debug buffer, it may not exist yet
+	(message "erc: old buffer %s, switching to %s"
+		 old-buffer buffer))
+      (erc-setup-buffer buffer))
+
+    buffer))
+
+(defun erc-initialize-log-marker ()
+  "Initialize the `erc-last-saved-position' marker to a sensible position."
+    (setq erc-last-saved-position (make-marker))
+    (move-marker erc-last-saved-position
+		 (1- (marker-position erc-insert-marker))))
+
+;; interactive startup
+
+(defvar erc-server-history-list nil
+  "IRC server interactive selection history list.")
+
+(defvar erc-nick-history-list nil
+  "Nickname interactive selection history list.")
+
+(defun erc-already-logged-in (server port nick)
+  "Return the buffers corresponding to a NICK on PORT of a session SERVER.
+This is determined by looking for the appropriate buffer and checking
+whether the connection is still alive.
+If no buffer matches, return nil."
+  (erc-buffer-list
+   (lambda ()
+     (and (erc-server-process-alive)
+	  (string= erc-session-server server)
+	  (erc-port-equal erc-session-port port)
+	  (erc-current-nick-p nick)))))
+
+(if (not (fboundp 'read-passwd))
+    (defun read-passwd (prompt)
+      "Substitute for read-passwd in early emacsen"
+      (read-from-minibuffer prompt)))
+
+(defcustom erc-before-connect nil
+  "Hook called before connecting to a server.
+This hook gets executed before `erc-select' actually invokes `erc-mode'
+with your input data.  The functions in here get called with three
+parameters, SERVER, PORT and NICK."
+  :group 'erc-hooks
+  :type 'hook)
+
+(defcustom erc-after-connect nil
+  "Hook called after connecting to a server.
+This hook gets executed when an end of MOTD has been received.	All
+functions in here get called with the parameters SERVER and NICK."
+  :group 'erc-hooks
+  :type 'hook)
+
+;;;###autoload
+(defun erc-select-read-args ()
+  "Prompt the user for values of nick, server, port, and password."
+  (let (user-input server port nick passwd)
+    (setq user-input (read-from-minibuffer
+		      "IRC server: "
+		      (erc-compute-server) nil nil 'erc-server-history-list))
+
+    (if (string-match "\\(.*\\):\\(.*\\)\\'" user-input)
+	(setq port (erc-string-to-port (match-string 2 user-input))
+	      user-input (match-string 1 user-input))
+      (setq port
+	    (erc-string-to-port (read-from-minibuffer
+				 "IRC port: " (erc-port-to-string
+					       (erc-compute-port))))))
+
+    (if (string-match "\\`\\(.*\\)@\\(.*\\)" user-input)
+	(setq nick (match-string 1 user-input)
+	      user-input (match-string 2 user-input))
+      (setq nick
+	    (if (erc-already-logged-in server port nick)
+		(read-from-minibuffer
+		 (erc-format-message 'nick-in-use ?n nick)
+		 nick
+		 nil nil 'erc-nick-history-list)
+	      (read-from-minibuffer
+	       "Nickname: " (erc-compute-nick nick)
+	       nil nil 'erc-nick-history-list))))
+
+    (setq server user-input)
+
+    (setq passwd (if erc-prompt-for-password
+		     (if (and erc-password
+			      (y-or-n-p "Use the default password? "))
+			 erc-password
+		       (read-passwd "Password: "))
+		   erc-password))
+    (when (and passwd (string= "" passwd))
+      (setq passwd nil))
+
+    (while (erc-already-logged-in server port nick)
+      ;; hmm, this is a problem when using multiple connections to a bnc
+      ;; with the same nick. Currently this code prevents using more than one
+      ;; bnc with the same nick. actually it would be nice to have
+      ;; bncs transparent, so that erc-compute-buffer-name displays
+      ;; the server one is connected to.
+      (setq nick (read-from-minibuffer
+		  (erc-format-message 'nick-in-use ?n nick)
+		  nick
+		  nil nil 'erc-nick-history-list)))
+    (list :server server :port port :nick nick :password passwd)))
+
+;;;###autoload
+(defun* erc-select (&key (server (erc-compute-server))
+			 (port   (erc-compute-port))
+			 (nick   (erc-compute-nick))
+			 password
+			 (full-name (erc-compute-full-name)))
+  "Select connection parameters and run ERC.
+Non-interactively, it takes keyword arguments
+   (server (erc-compute-server))
+   (port   (erc-compute-port))
+   (nick   (erc-compute-nick))
+   password
+   (full-name (erc-compute-full-name)))
+
+That is, if called with
+   (erc-select :server \"irc.freenode.net\" :full-name \"Harry S Truman\")
+server and full-name will be set to those values, whereas
+erc-compute-port, erc-compute-nick and erc-compute-full-name will
+be invoked for those parameters' values"
+  (interactive (erc-select-read-args))
+
+  (run-hook-with-args 'erc-before-connect server port nick)
+  (erc server port nick erc-user-full-name t password))
+
+
+(defun erc-select-ssl (&rest r)
+  "Interactively select SSL connection parameters and run ERC.
+Arguments are as to erc-select."
+  (interactive (erc-select-read-args))
+  (let ((erc-server-connect-function 'erc-open-ssl-stream))
+    (apply 'erc-select r)))
+
+(defun erc-open-ssl-stream (name buffer host port)
+  "Open an SSL stream to an IRC server.
+The process will be given the name NAME, its target buffer will be
+BUFFER.	 HOST and PORT specify the connection target."
+  (when (require 'tls)
+    (let ((proc (open-tls-stream name buffer host port)))
+      ;; Ugly hack, but it works for now. Problem is it is
+      ;; very hard to detect when ssl is established, because s_client
+      ;; doesn't give any CONNECTIONESTABLISHED kind of message, and
+      ;; most IRC servers send nothing and wait for you to identify.
+      ;; Disabled when switching to tls.el -- jas
+      ;(sit-for 5)
+      proc)))
+
+;;; Debugging the protocol
+
+(defvar erc-debug-irc-protocol nil
+  "If non-nil, log all IRC protocol traffic to the buffer \"*erc-protocol*\".
+
+The buffer is created if it doesn't exist.
+
+NOTE: If this variable is non-nil, and you kill the the only
+visible \"*erc-protocol*\" buffer, it will be recreated shortly,
+but you won't see it.
+
+WARNING: Do not set this variable directly!  Instead, use the
+function `erc-toggle-debug-irc-protocol' to toggle its value.")
+
+(defun erc-log-irc-protocol (string &optional outbound)
+  "Append STRING to the buffer *erc-protocol*.
+
+This only has any effect if `erc-debug-irc-protocol' is non-nil.
+
+The buffer is created if it doesn't exist.
+
+If OUTBOUND is non-nil, STRING is being sent to the IRC server
+and appears in erc-input-face in the buffer."
+  (when erc-debug-irc-protocol
+    (let ((network-name (or (ignore-errors (erc-network-name))
+			    "???")))
+      (with-current-buffer (get-buffer-create "*erc-protocol*")
+	(save-excursion
+	  (goto-char (point-max))
+	  (let ((inhibit-read-only t))
+	    (insert (if (not outbound)
+			;; Cope with the fact that string might
+			;; contain multiple lines of text.
+			(let ((lines (delete "" (split-string string
+							      "\n\\|\r\n")))
+			      (result ""))
+			  (dolist (line lines)
+			    (setq result (concat result network-name
+						 " << " line "\n")))
+			  result)
+		      (erc-propertize
+			(concat network-name " >> " string
+				(if (/= ?\n
+					(aref string
+					      (1- (length string))))
+				    "\n"))
+			'face 'erc-input-face)))))
+	(let ((orig-win (selected-window))
+	      (debug-buffer-window (get-buffer-window (current-buffer) t)))
+	  (when debug-buffer-window
+	     (select-window debug-buffer-window)
+	     (when (= 1 (count-lines (point) (point-max)))
+	       (goto-char (point-max))
+	       (recenter -1))
+	     (select-window orig-win)))))))
+
+(defun erc-toggle-debug-irc-protocol (&optional arg)
+  "Toggle the value of `erc-debug-irc-protocol'.
+
+If ARG is non-nil, show the *erc-protocol* buffer."
+  (interactive "P")
+  (let* ((buf (get-buffer-create "*erc-protocol*")))
+    (with-current-buffer buf
+      (erc-view-mode-enter 1)
+      (when (null (current-local-map))
+	(let ((inhibit-read-only t))
+	  (insert (erc-make-notice "This buffer displays all IRC protocol traffic exchanged with each server.\n"))
+	  (insert (erc-make-notice "Kill this buffer to terminate protocol logging.\n\n")))
+	(use-local-map (make-sparse-keymap))
+	(local-set-key (kbd "RET") 'erc-toggle-debug-irc-protocol))
+      (add-hook 'kill-buffer-hook
+		#'(lambda () (setq erc-debug-irc-protocol nil))
+		nil 'local)
+      (goto-char (point-max))
+      (let ((inhibit-read-only t))
+	(insert (erc-make-notice
+		 (format "IRC protocol logging %s at %s -- Press ENTER to toggle logging.\n"
+			 (if erc-debug-irc-protocol "disabled" "enabled")
+			 (current-time-string))))))
+    (setq erc-debug-irc-protocol (not erc-debug-irc-protocol))
+    (if (and arg
+	     (not (get-buffer-window "*erc-protocol*" t)))
+	(display-buffer buf t))
+    (message "IRC protocol traffic logging %s (see buffer *erc-protocol*)."
+	     (if erc-debug-irc-protocol "enabled" "disabled"))))
+
+;;; I/O interface
+
+;; send interface
+
+(defun erc-send-action (tgt str &optional force)
+  "Send CTCP ACTION information described by STR to TGT."
+  (erc-send-ctcp-message tgt (format "ACTION %s" str) force)
+  (erc-display-message
+   nil 'input (current-buffer)
+   'ACTION ?n (erc-current-nick) ?a str ?u "" ?h ""))
+
+;; Display interface
+
+(defun erc-string-invisible-p (string)
+  "Check whether STRING is invisible or not.
+I.e. any char in it has the `invisible' property set."
+  (text-property-any 0 (length string) 'invisible t string))
+
+(defun erc-display-line-1 (string buffer)
+  "Display STRING in `erc-mode' BUFFER.
+Auxiliary function used in `erc-display-line'.	The line gets filtered to
+interpret the control characters.  Then, `erc-insert-pre-hook' gets called.
+If `erc-insert-this' is still t, STRING gets inserted into the buffer.
+Afterwards, `erc-insert-modify' and `erc-insert-post-hook' get called.
+If STRING is nil, the function does nothing."
+  (when string
+    (save-excursion
+      (set-buffer (or buffer (process-buffer erc-server-process)))
+      (let ((insert-position (or (marker-position erc-insert-marker)
+				 (point-max))))
+	(let ((string string) ;; FIXME! Can this be removed?
+	      (buffer-undo-list t)
+	      (inhibit-read-only t))
+	  (unless (string-match "\n$" string)
+	    (setq string (concat string "\n"))
+	    (when (erc-string-invisible-p string)
+	      (erc-put-text-properties 0 (length string) string
+				       '(invisible intangible))))
+	  (erc-log (concat "erc-display-line: " string
+			   (format "(%S)" string) " in buffer "
+			   (format "%s" buffer)))
+	  (setq erc-insert-this t)
+	  (run-hook-with-args 'erc-insert-pre-hook string)
+	  (if (null erc-insert-this)
+	      ;; Leave erc-insert-this set to t as much as possible.  Fran
+	      ;; Litterio <franl> has seen erc-insert-this set to nil while
+	      ;; erc-send-pre-hook is running, which should never happen.  This
+	      ;; may cure it.
+	      (setq erc-insert-this t)
+	    (save-excursion ;; to restore point in the new buffer
+	      (save-restriction
+		(widen)
+		(goto-char insert-position)
+		(insert-before-markers string)
+		;; run insertion hook, with point at restored location
+		(save-restriction
+		  (narrow-to-region insert-position (point))
+		  (run-hooks 'erc-insert-modify-hook)
+		  (run-hooks 'erc-insert-post-hook))))))
+	(erc-update-undo-list (- (or (marker-position erc-insert-marker)
+				     (point-max))
+				 insert-position))))))
+
+(defun erc-update-undo-list (shift)
+  ;; Translate buffer positions in buffer-undo-list by SHIFT.
+  (unless (or (zerop shift) (atom buffer-undo-list))
+    (let ((list buffer-undo-list) elt)
+      (while list
+	(setq elt (car list))
+	(cond ((integerp elt)		; POSITION
+	       (incf (car list) shift))
+	      ((or (atom elt)		; nil, EXTENT
+		   ;; (eq t (car elt))	; (t HIGH . LOW)
+		   (markerp (car elt)))	; (MARKER . DISTANCE)
+	       nil)
+	      ((integerp (car elt))	; (BEGIN . END)
+	       (incf (car elt) shift)
+	       (incf (cdr elt) shift))
+	      ((stringp (car elt))	; (TEXT . POSITION)
+	       (incf (cdr elt) (* (if (natnump (cdr elt)) 1 -1) shift)))
+	      ((null (car elt))		; (nil PROPERTY VALUE BEG . END)
+	       (let ((cons (nthcdr 3 elt)))
+		 (incf (car cons) shift)
+		 (incf (cdr cons) shift)))
+	      ((and (featurep 'xemacs)
+		    (extentp (car elt))) ; (EXTENT START END)
+	       (incf (nth 1 elt) shift)
+	       (incf (nth 2 elt) shift)))
+	(setq list (cdr list))))))
+
+(defvar erc-valid-nick-regexp "[]a-zA-Z^[;\\`_{}|][]^[;\\`_{}|a-zA-Z0-9-]*"
+  "Regexp which matches all legal characters in a IRC nickname.")
+
+(defun erc-is-valid-nick-p (nick)
+  "Check if NICK is a valid IRC nickname."
+  (string-match (concat "^" erc-valid-nick-regexp "$") nick))
+
+(defun erc-display-line (string &optional buffer)
+  "Display STRING in the ERC BUFFER.
+All screen output must be done through this function.  If BUFFER is nil
+or omitted, the default ERC buffer for the `erc-session-server' is used.
+The BUFFER can be an actual buffer, a list of buffers, 'all or 'active.
+If BUFFER = 'all, the string is displayed in all the ERC buffers for the
+current session.  'active means the current active buffer
+\(`erc-active-buffer').	 If the buffer can't be resolved, the current
+buffer is used.	 `erc-display-line-1' is used to display STRING.
+
+If STRING is nil, the function does nothing."
+  (let ((inhibit-point-motion-hooks t)
+	new-bufs)
+    (dolist (buf (cond
+		  ((bufferp buffer) (list buffer))
+		  ((listp buffer) buffer)
+		  ((processp buffer) (list (process-buffer buffer)))
+		  ((eq 'all buffer)
+		   (and (boundp 'erc-server-process)
+			;; Hmm, or all of the same session server?
+			(erc-buffer-list nil erc-server-process)))
+		  ((and (eq 'active buffer) (erc-active-buffer))
+		   (list (erc-active-buffer)))
+		  ((erc-server-buffer-live-p)
+		   (list (process-buffer erc-server-process)))
+		  (t (list (current-buffer)))))
+      (when (buffer-live-p buf)
+	(erc-display-line-1 string buf)
+	(add-to-list 'new-bufs buf)))
+    (when (null new-bufs)
+      (if (erc-server-buffer-live-p)
+	  (erc-display-line-1 string (process-buffer erc-server-process))
+	(erc-display-line-1 string (current-buffer))))))
+
+(defun erc-display-message-highlight (type string)
+  "Highlight STRING according to TYPE, where erc-TYPE-face is an erc face.
+
+See also `erc-make-notice'"
+  (cond ((eq type 'notice)
+	 (erc-make-notice string))
+	(t
+	 (erc-put-text-property
+	  0 (length string)
+	  'face (or (intern-soft
+		     (concat "erc-" (symbol-name type) "-face"))
+		    "erc-default-face")
+	  string)
+	 string)))
+
+(defun erc-display-message (parsed type buffer msg &rest args)
+  "Display MSG in BUFFER.
+
+ARGS, PARSED, and TYPE are used to format MSG sensibly.
+
+See also `erc-format-message' and `erc-display-line'."
+  (let ((string (if (symbolp msg)
+		    (apply 'erc-format-message msg args)
+		  msg)))
+    (setq string
+	  (cond
+	   ((listp type)
+	    (mapc (lambda (type)
+		    (setq string
+			  (erc-display-message-highlight type string)))
+		  type)
+	    string)
+	   ((symbolp type)
+	    (erc-display-message-highlight type string))))
+
+    (if (not (erc-response-p parsed))
+	(erc-display-line string buffer)
+      (unless (member (erc-response.command parsed) erc-hide-list)
+      (erc-put-text-property 0 (length string) 'erc-parsed parsed string)
+	(erc-put-text-property 0 (length string) 'rear-sticky t string)
+	(erc-display-line string buffer)))))
+
+(defun erc-message-type-member (position list)
+  "Return non-nil if the erc-parsed text-property at POSITION is in LIST.
+
+This function relies on the erc-parsed text-property being
+present."
+  (let ((prop-val (get-text-property position 'erc-parsed)))
+    (and prop-val (member (erc-response.command prop-val) list))))
+
+(defvar erc-send-input-line-function 'erc-send-input-line)
+(make-variable-buffer-local 'erc-send-input-line-function)
+
+(defun erc-send-input-line (target line &optional force)
+  "Send LINE to TARGET.
+
+See also `erc-server-send'."
+  (setq line (format "PRIVMSG %s :%s"
+		     target
+		     ;; If the line is empty, we still want to
+		     ;; send it - i.e. an empty pasted line.
+		     (if (string= line "\n")
+			 " \n"
+		       line)))
+  (erc-server-send line force target))
+
+(defun erc-get-arglist (fun)
+  "Return the argument list of a function without the parens."
+  (let ((arglist (format "%S" (erc-function-arglist fun))))
+    (if (string-match "^(\\(.*\\))$" arglist)
+	(match-string 1 arglist)
+      arglist)))
+
+(defun erc-command-name (cmd)
+  "For CMD being the function name of a ERC command, something like
+erc-cmd-FOO, this returns a string /FOO."
+  (let ((command-name (symbol-name cmd)))
+    (if (string-match "^erc-cmd-\\(.*\\)$" command-name)
+	(concat "/" (match-string 1 command-name))
+      command-name)))
+
+(defun erc-process-input-line (line &optional force no-command)
+  "Translate LINE to an RFC1459 command and send it based.
+Returns non-nil if the command is actually sent to the server, and nil
+otherwise.
+
+If the command in the LINE is not bound as a function `erc-cmd-<COMMAND>',
+it is passed to `erc-cmd-default'.  If LINE is not a command (ie. doesn't
+start with /<COMMAND>) then it is sent as a message.
+
+An optional FORCE argument forces sending the line when flood
+protection is in effect.  The optional NO-COMMAND argument prohibits
+this function from interpreting the line as a command."
+  (let ((command-list (erc-extract-command-from-line line)))
+    (if	(and command-list
+	     (not no-command))
+	(let* ((cmd  (nth 0 command-list))
+	       (args (nth 1 command-list)))
+	  (condition-case nil
+	      (if (listp args)
+		  (apply cmd args)
+		(funcall cmd args))
+	    (wrong-number-of-arguments
+	     (erc-display-message nil 'error (current-buffer) 'incorrect-args
+				  ?c (erc-command-name cmd)
+				  ?u (or (erc-get-arglist cmd)
+					 "")
+				  ?d (format "%s\n"
+					     (or (documentation cmd) "")))
+	     nil)))
+      (let ((r (erc-default-target)))
+	(if r
+	    (funcall erc-send-input-line-function r line force)
+	  (erc-display-message nil 'error (current-buffer) 'no-target)
+	  nil)))))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;		      Input commands handlers
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defun erc-cmd-AMSG (line)
+  "Send LINE to all channels of the current server that you are on."
+  (interactive "sSend to all channels you're on: ")
+  (setq line (erc-trim-string line))
+  (erc-with-all-buffers-of-server nil
+   (lambda ()
+     (erc-channel-p (erc-default-target)))
+   (erc-send-message line)))
+(put 'erc-cmd-AMSG 'do-not-parse-args t)
+
+(defun erc-cmd-SAY (line)
+  "Send LINE to the current query or channel as a message, not a command.
+
+Use this when you want to send a message with a leading '/'.  Note
+that since multi-line messages are never a command, you don't
+need this when pasting multiple lines of text."
+  (if (string-match "^\\s-*$" line)
+      nil
+    (string-match "^ ?\\(.*\\)" line)
+    (erc-process-input-line (match-string 1 line) nil t)))
+(put 'erc-cmd-SAY 'do-not-parse-args t)
+
+(defun erc-cmd-SET (line)
+  "Set the variable named by the first word in LINE to some VALUE.
+VALUE is computed by evaluating the rest of LINE in Lisp."
+  (cond
+   ((string-match "^\\s-*\\(\\S-+\\)\\s-+\\(.*\\)$" line)
+    (let ((var (read (concat "erc-" (match-string 1 line))))
+	  (val (read (match-string 2 line))))
+      (if (boundp var)
+	  (progn
+	    (set var (eval val))
+	    (erc-display-message
+	     nil nil 'active (format "Set %S to %S" var val))
+	    t)
+	(setq var (read (match-string 1 line)))
+	(if (boundp var)
+	    (progn
+	      (set var (eval val))
+	      (erc-display-message
+	       nil nil 'active (format "Set %S to %S" var val))
+	      t)
+	  (erc-display-message nil 'error 'active 'variable-not-bound)
+	  nil))))
+   ((string-match "^\\s-*$" line)
+    (erc-display-line
+     (concat "Available user variables:\n"
+	     (apply
+	      'concat
+	      (mapcar
+	       (lambda (var)
+		 (let ((val (symbol-value var)))
+		   (concat (format "%S:" var)
+			   (if (consp val)
+			       (concat "\n" (pp-to-string val))
+			     (format " %S\n" val)))))
+	       (apropos-internal "^erc-" 'user-variable-p))))
+     (current-buffer)) t)
+   (t nil)))
+(defalias 'erc-cmd-VAR 'erc-cmd-SET)
+(defalias 'erc-cmd-VARIABLE 'erc-cmd-SET)
+(put 'erc-cmd-SET 'do-not-parse-args t)
+
+(defun erc-cmd-default (line)
+  "Fallback command.
+
+Commands for which no erc-cmd-xxx exists, are tunnelled through
+this function.  LINE is sent to the server verbatim, and
+therefore has to contain the command itself as well."
+  (erc-log (format "cmd: DEFAULT: %s" line))
+  (erc-server-send (substring line 1))
+  t)
+
+(defun erc-cmd-IGNORE (&optional user)
+  "Ignore USER.  This should be a regexp matching nick!user@host.
+If no USER argument is specified, list the contents of `erc-ignore-list'."
+  (if user
+      (progn
+	(erc-display-line
+	 (erc-make-notice (format "Now ignoring %s" user))
+	 'active)
+	(with-current-buffer (erc-server-buffer)
+	  (add-to-list 'erc-ignore-list user)))
+    (if (null (with-current-buffer (erc-server-buffer) erc-ignore-list))
+	(erc-display-line (erc-make-notice "Ignore list is empty") 'active)
+      (erc-display-line (erc-make-notice "Ignore list:") 'active)
+      (mapc #'(lambda (item)
+		(erc-display-line (erc-make-notice item)
+				  'active))
+	    (with-current-buffer (erc-server-buffer) erc-ignore-list))))
+  t)
+
+(defun erc-cmd-UNIGNORE (user)
+  "Remove the user specified in USER from the ignore list."
+  (let ((ignored-nick (car (with-current-buffer (erc-server-buffer)
+			     (erc-member-ignore-case user erc-ignore-list)))))
+    (if (null ignored-nick)
+	(erc-display-line
+	 (erc-make-notice (format "%s is not currently ignored!" user))
+	 'active)
+      (erc-display-line
+       (erc-make-notice (format "No longer ignoring %s" user))
+       'active))
+    (with-current-buffer (erc-server-buffer)
+      (setq erc-ignore-list (delete ignored-nick erc-ignore-list))))
+  t)
+
+(defun erc-cmd-CLEAR ()
+  "Clear the window content."
+  (recenter 0)
+  t)
+
+(defun erc-cmd-OPS ()
+  "Show the ops in the current channel."
+  (interactive)
+  (let ((ops nil))
+    (if erc-channel-users
+	(maphash (lambda (nick user-data)
+		   (let ((cuser (cdr user-data)))
+		     (if (and cuser
+			      (erc-channel-user-op cuser))
+			 (setq ops (cons (erc-server-user-nickname
+					  (car user-data))
+					 ops)))))
+		 erc-channel-users))
+    (setq ops (sort ops 'string-lessp))
+    (if ops
+	(erc-display-message
+	 nil 'notice (current-buffer) 'ops
+	 ?i (length ops) ?s (if (> (length ops) 1) "s" "")
+	 ?o (mapconcat 'identity ops " "))
+      (erc-display-message nil 'notice (current-buffer) 'ops-none)))
+  t)
+
+(defun erc-cmd-COUNTRY (tld)
+  "Display the country associated with the top level domain TLD."
+  (require 'mail-extr)
+  (let ((co (ignore-errors (what-domain tld))))
+    (if co
+	(erc-display-message
+	 nil 'notice 'active 'country ?c co ?d tld)
+      (erc-display-message
+       nil 'notice 'active 'country-unknown ?d tld))
+  t))
+
+(defun erc-cmd-AWAY (line)
+  "Mark the user as being away, the reason being indicated by LINE.
+If no reason is given, unset away status."
+  (when (string-match "^\\s-*\\(.*\\)$" line)
+    (let ((reason (match-string 1 line)))
+      (erc-log (format "cmd: AWAY: %s" reason))
+      (erc-server-send
+       (if (string= reason "")
+	   "AWAY"
+	 (concat "AWAY :" reason))))
+    t))
+(put 'erc-cmd-AWAY 'do-not-parse-args t)
+
+(defun erc-cmd-GAWAY (line)
+  "Mark the user as being away everywhere, the reason being indicated by LINE."
+  ;; on all server buffers.
+  (erc-with-all-buffers-of-server nil
+   #'erc-server-buffer-p
+   (erc-cmd-AWAY line)))
+(put 'erc-cmd-GAWAY 'do-not-parse-args t)
+
+(defun erc-cmd-CTCP (nick cmd &rest args)
+  "Send a Client To Client Protocol message to NICK.
+
+CMD is the CTCP command, possible values being ECHO, FINGER, CLIENTINFO, TIME,
+VERSION and so on.  It is called with ARGS."
+  (let ((str (concat cmd
+		     (when args
+		       (concat " " (mapconcat #'identity args " "))))))
+    (erc-log (format "cmd: CTCP [%s]: [%s]" nick str))
+    (erc-send-ctcp-message nick str)
+    t))
+
+(defun erc-cmd-HELP (&optional func)
+  "Popup help information.
+
+If FUNC contains a valid function or variable, help about that
+will be displayed.  If FUNC is empty, display an apropos about
+erc commands.  Otherwise, do apropos in the erc namespace
+\(\"erc-.*LINE\"\).
+
+Examples:
+To find out about erc and bbdb, do
+  /help bbdb.*
+
+For help about the WHOIS command, do:
+  /help whois
+
+For a list of user commands (/join /part, ...):
+  /help."
+  (if func
+    (let* ((sym (or (let ((sym (intern-soft
+				(concat "erc-cmd-" (upcase func)))))
+		      (if (and sym (or (boundp sym) (fboundp sym)))
+			  sym
+			nil))
+		    (let ((sym (intern-soft func)))
+		      (if (and sym (or (boundp sym) (fboundp sym)))
+			  sym
+			nil))
+		    (let ((sym (intern-soft (concat "erc-" func))))
+		      (if (and sym (or (boundp sym) (fboundp sym)))
+			  sym
+			nil)))))
+      (if sym
+	  (cond
+	   ((boundp sym) (describe-variable sym))
+	   ((fboundp sym) (describe-function sym))
+	   (t nil))
+	(apropos-command (concat "erc-.*" func) nil
+			 (lambda (x)
+			   (or (commandp x)
+			       (get x 'custom-type))))
+	t))
+    (apropos "erc-cmd-")
+    (message "Type C-h m to get additional information about keybindings.")
+    t))
+
+(defalias 'erc-cmd-H 'erc-cmd-HELP)
+
+(defun erc-cmd-JOIN (channel &optional key)
+  "Join the channel given in CHANNEL, optionally with KEY.
+If CHANNEL is specified as \"-invite\", join the channel to which you
+were most recently invited.  See also `invitation'."
+  (let (chnl)
+    (if (string= (upcase channel) "-INVITE")
+	(if erc-invitation
+	    (setq chnl erc-invitation)
+	  (erc-display-message nil 'error (current-buffer) 'no-invitation))
+      (setq chnl (erc-ensure-channel-name channel)))
+    (when chnl
+      ;; Prevent double joining of same channel on same server.
+      (let ((joined-channels
+	     (mapcar #'(lambda (chanbuf)
+			 (with-current-buffer chanbuf (erc-default-target)))
+		     (erc-channel-list erc-server-process))))
+	(if (erc-member-ignore-case chnl joined-channels)
+	    (switch-to-buffer (car (erc-member-ignore-case chnl
+							   joined-channels)))
+	  (erc-log (format "cmd: JOIN: %s" chnl))
+	  (if (and chnl key)
+	      (erc-server-send (format "JOIN %s %s" chnl key))
+	    (erc-server-send (format "JOIN %s" chnl)))))))
+  t)
+
+(defalias 'erc-cmd-CHANNEL 'erc-cmd-JOIN)
+(defalias 'erc-cmd-J 'erc-cmd-JOIN)
+
+(defvar erc-channel-new-member-names nil
+  "If non-nil, a names list is currently being received.
+
+If non-nil, this variable is a hash-table that associates
+received nicks with t.")
+(make-variable-buffer-local 'erc-channel-new-member-names)
+
+(defun erc-cmd-NAMES (&optional channel)
+  "Display the users in CHANNEL.
+If CHANNEL is not specified, display the users in the current channel.
+This function clears the channel name list first, then sends the
+command."
+  (let ((tgt (or (and (erc-channel-p channel) channel)
+		 (erc-default-target))))
+    (if (and tgt (erc-channel-p tgt))
+	(progn
+	  (erc-log (format "cmd: DEFAULT: NAMES %s" tgt))
+	  (erc-with-buffer
+	   (tgt)
+	   (erc-channel-begin-receiving-names))
+	  (erc-server-send (concat "NAMES " tgt)))
+      (erc-display-message nil 'error (current-buffer) 'no-default-channel)))
+  t)
+(defalias 'erc-cmd-N 'erc-cmd-NAMES)
+
+(defun erc-cmd-KICK (target &optional reason-or-nick &rest reasonwords)
+  "Kick the user indicated in LINE from the current channel.
+LINE has the format: \"#CHANNEL NICK REASON\" or \"NICK REASON\"."
+  (let ((reasonstring (mapconcat 'identity reasonwords " ")))
+    (if (string= "" reasonstring)
+	(setq reasonstring (format "Kicked by %s" (erc-current-nick))))
+    (if (erc-channel-p target)
+	(let ((nick reason-or-nick))
+	  (erc-log (format "cmd: KICK: %s/%s: %s" nick target reasonstring))
+	  (erc-server-send (format "KICK %s %s :%s" target nick reasonstring)
+			   nil target)
+	  t)
+      (when target
+	(let ((ch (erc-default-target)))
+	  (setq reasonstring (concat
+			      (if reason-or-nick (concat reason-or-nick " "))
+			      reasonstring))
+	  (if ch
+	      (progn
+		(erc-log
+		 (format "cmd: KICK: %s/%s: %s" target ch reasonstring))
+		(erc-server-send
+		 (format "KICK %s %s :%s" ch target reasonstring) nil ch))
+	    (erc-display-message nil 'error (current-buffer)
+				 'no-default-channel))
+	  t)))))
+
+(defvar erc-script-args nil)
+
+(defun erc-cmd-LOAD (line)
+  "Load the script provided in the LINE.
+If LINE continues beyond the file name,
+the rest of it is put in a (local) variable
+`erc-script-args', which can be used in elisp scripts.
+
+The optional FORCE argument is ignored here - you can't force loading
+a script after exceeding the flood threshold."
+  (cond
+   ((string-match "^\\s-*\\(\\S-+\\)\\(.*\\)$" line)
+    (let* ((file-to-find (match-string 1 line))
+	   (erc-script-args (match-string 2 line))
+	   (file (erc-find-file file-to-find erc-script-path)))
+      (erc-log (format "cmd: LOAD: %s" file-to-find))
+      (cond
+       ((not file)
+	(erc-display-message nil 'error (current-buffer)
+			     'cannot-find-file ?f file-to-find))
+       ((not (file-readable-p file))
+	(erc-display-message nil 'error (current-buffer)
+			     'cannot-read-file ?f file))
+       (t
+	(message "Loading \'%s\'..." file)
+	(erc-load-script file)
+	(message "Loading \'%s\'...done" file))))
+    t)
+   (t nil)))
+
+(defun erc-cmd-WHOIS (user &optional server)
+  "Display whois information for USER.
+
+If SERVER is non-nil, use that, rather than the current server."
+  ;; FIXME: is the above docstring correct?  -- Lawrence 2004-01-08
+  (let ((send (if server
+		  (format "WHOIS %s %s" user server)
+		(format "WHOIS %s" user))))
+    (erc-log (format "cmd: %s" send))
+    (erc-server-send send)
+  t))
+(defalias 'erc-cmd-WI 'erc-cmd-WHOIS)
+
+(defun erc-cmd-WHOAMI ()
+  "Display whois information about yourself."
+  (erc-cmd-WHOIS (erc-current-nick))
+  t)
+
+(defun erc-cmd-IDLE (nick)
+  "Show the length of time NICK has been idle."
+  (let ((serverbuf (erc-server-buffer))
+	(origbuf (current-buffer))
+	symlist)
+    (with-current-buffer serverbuf
+      (add-to-list 'symlist
+		   (cons (erc-once-with-server-event
+			  311 `(string= ,nick
+					(second
+					 (erc-response.command-args parsed))))
+			 'erc-server-311-functions))
+      (add-to-list 'symlist
+		   (cons (erc-once-with-server-event
+			  312 `(string= ,nick
+					(second
+					 (erc-response.command-args parsed))))
+			 'erc-server-312-functions))
+      (add-to-list 'symlist
+		   (cons (erc-once-with-server-event
+			  318 `(string= ,nick
+					(second
+					 (erc-response.command-args parsed))))
+			 'erc-server-318-functions))
+      (add-to-list 'symlist
+		   (cons (erc-once-with-server-event
+			  319 `(string= ,nick
+					(second
+					 (erc-response.command-args parsed))))
+			 'erc-server-319-functions))
+      (add-to-list 'symlist
+		   (cons (erc-once-with-server-event
+			  320 `(string= ,nick
+					(second
+					 (erc-response.command-args parsed))))
+			 'erc-server-320-functions))
+      (add-to-list 'symlist
+		   (cons (erc-once-with-server-event
+			  330 `(string= ,nick
+					(second
+					 (erc-response.command-args parsed))))
+			 'erc-server-330-functions))
+      (add-to-list 'symlist
+		   (cons (erc-once-with-server-event
+			  317
+			  `(let ((idleseconds
+				  (string-to-number
+				   (third
+				    (erc-response.command-args parsed)))))
+			     (erc-display-line
+			      (erc-make-notice
+			       (format "%s has been idle for %s."
+				       (erc-string-no-properties ,nick)
+				       (erc-seconds-to-string idleseconds)))
+			      ,origbuf))
+			  t)
+			 'erc-server-317-functions))
+
+      ;; Send the WHOIS command.
+      (erc-cmd-WHOIS nick)
+
+      ;; Remove the uninterned symbols from the server hooks that did not run.
+      (run-at-time 20 nil `(lambda ()
+			     (with-current-buffer ,(current-buffer)
+			       (dolist (sym ',symlist)
+				 (let ((hooksym (cdr sym))
+				       (funcsym (car sym)))
+				   (remove-hook hooksym funcsym t))))))))
+  t)
+
+(defun erc-cmd-DESCRIBE (line)
+  "Pose some action to a certain user.
+LINE has the format \"USER ACTION\"."
+  (cond
+   ((string-match
+     "^\\s-*\\(\\S-+\\)\\s-\\(.*\\)$" line)
+    (let ((dst (match-string 1 line))
+	  (s (match-string 2 line)))
+      (erc-log (format "cmd: DESCRIBE: [%s] %s" dst s))
+      (erc-send-action dst s))
+    t)
+   (t nil)))
+(put 'erc-cmd-DESCRIBE 'do-not-parse-args t)
+
+(defun erc-cmd-ME (line)
+  "Send LINE as an action."
+  (cond
+   ((string-match "^\\s-\\(.*\\)$" line)
+    (let ((s (match-string 1 line)))
+      (erc-log (format "cmd: ME: %s" s))
+      (erc-send-action (erc-default-target) s))
+    t)
+   (t nil)))
+(put 'erc-cmd-ME 'do-not-parse-args t)
+
+(defun erc-cmd-LASTLOG (line)
+  "Show all lines in the current buffer matching the regexp LINE.
+
+If a match spreads across multiple lines, all those lines are shown.
+
+The lines are shown in a buffer named `*Occur*'.
+It serves as a menu to find any of the occurrences in this buffer.
+\\[describe-mode] in that buffer will explain how.
+
+If LINE contains upper case characters (excluding those preceded by `\'),
+the matching is case-sensitive."
+  (occur line)
+  t)
+(put 'erc-cmd-LASTLOG 'do-not-parse-args t)
+
+(defun erc-send-message (line &optional force)
+  "Send LINE to the current channel or user and display it.
+
+See also `erc-message' and `erc-display-line'."
+  (erc-message "PRIVMSG" (concat (erc-default-target) " " line) force)
+  (erc-display-line
+   (concat (erc-format-my-nick) line)
+     (current-buffer))
+  ;; FIXME - treat multiline, run hooks, or remove me?
+  t)
+
+(defun erc-cmd-MODE (line)
+  "Change or display the mode value of a channel or user.
+The first word specifies the target.  The rest is the mode string
+to send.
+
+If only one word is given, display the mode of that target.
+
+A list of valid mode strings for Freenode may be found at
+`http://freenode.net/using_the_network.shtml'."
+  (cond
+   ((string-match "^\\s-\\(.*\\)$" line)
+    (let ((s (match-string 1 line)))
+      (erc-log (format "cmd: MODE: %s" s))
+      (erc-server-send (concat "MODE " line)))
+    t)
+   (t nil)))
+(put 'erc-cmd-MODE 'do-not-parse-args t)
+
+(defun erc-cmd-NOTICE (channel-or-user &rest message)
+  "Send a notice to the channel or user given as the first word.
+The rest is the message to send."
+  (erc-message "NOTICE" (concat channel-or-user " "
+				(mapconcat #'identity message " "))))
+
+(defun erc-cmd-MSG (line)
+  "Send a message to the channel or user given as the first word in LINE.
+
+The rest of LINE is the message to send."
+  (erc-message "PRIVMSG" line))
+
+(defalias 'erc-cmd-M 'erc-cmd-MSG)
+(put 'erc-cmd-MSG 'do-not-parse-args t)
+
+(defun erc-cmd-SQUERY (line)
+  "Send a Service Query to the service given as the first word in LINE.
+
+The rest of LINE is the message to send."
+  (erc-message "SQUERY" line))
+
+(defun erc-cmd-NICK (nick)
+  "Change current nickname to NICK."
+  (erc-log (format "cmd: NICK: %s (erc-bad-nick: %S)" nick erc-bad-nick))
+  (let ((nicklen (cdr (assoc "NICKLEN" (with-current-buffer (erc-server-buffer)
+				    erc-server-parameters)))))
+    (and nicklen (> (length nick) (string-to-number nicklen))
+	 (erc-display-message
+	  nil 'notice 'active 'nick-too-long
+	  ?i (length nick) ?l nicklen)))
+  (erc-server-send (format "NICK %s" nick))
+  (cond (erc-bad-nick
+	 (erc-set-current-nick nick)
+	 (erc-update-mode-line)
+	 (setq erc-bad-nick nil)))
+  t)
+
+(defun erc-cmd-PART (line)
+  "When LINE is an empty string, leave the current channel.
+Otherwise leave the channel indicated by LINE."
+  (cond
+   ((string-match "^\\s-*\\([&#+!]\\S-+\\)\\s-?\\(.*\\)$" line)
+    (let* ((ch (match-string 1 line))
+	   (msg (match-string 2 line))
+	   (reason (funcall erc-part-reason (if (equal msg "") nil msg))))
+      (erc-log (format "cmd: PART: %s: %s" ch reason))
+      (erc-server-send (if (string= reason "")
+			   (format "PART %s" ch)
+			 (format "PART %s :%s" ch reason))
+		       nil ch))
+    t)
+   ((string-match "^\\s-*\\(.*\\)$" line)
+    (let* ((ch (erc-default-target))
+	   (msg (match-string 1 line))
+	   (reason (funcall erc-part-reason (if (equal msg "") nil msg))))
+      (if (and ch (erc-channel-p ch))
+	  (progn
+	    (erc-log (format "cmd: PART: %s: %s" ch reason))
+	    (erc-server-send (if (string= reason "")
+				 (format "PART %s" ch)
+			       (format "PART %s :%s" ch reason))
+			     nil ch))
+	(erc-display-message nil 'error (current-buffer) 'no-target)))
+    t)
+   (t nil)))
+(put 'erc-cmd-PART 'do-not-parse-args t)
+
+(defalias 'erc-cmd-LEAVE 'erc-cmd-PART)
+
+(defun erc-cmd-PING (recipient)
+  "Ping RECIPIENT."
+  (let ((time (format "%f" (erc-current-time))))
+    (erc-log (format "cmd: PING: %s" time))
+    (erc-cmd-CTCP recipient "PING" time)))
+
+(defun erc-cmd-QUOTE (line)
+  "Send LINE directly to the server.
+All the text given as argument is sent to the sever as unmodified,
+just as you provided it.  Use this command with care!"
+  (cond
+   ((string-match "^\\s-\\(.+\\)$" line)
+    (erc-server-send (match-string 1 line)))
+   (t nil)))
+(put 'erc-cmd-QUOTE 'do-not-parse-args t)
+
+(defun erc-cmd-QUERY (&optional user)
+  "Open a query with USER.
+The type of query window/frame/etc will depend on the value of
+`erc-join-buffer'.  If USER is omitted, close the current query buffer if one
+exists - except this is broken now ;-)"
+  (interactive
+   (list (read-from-minibuffer "Start a query with: " nil)))
+  (let ((session-buffer (erc-server-buffer)))
+    (if user
+	(erc-query user session-buffer)
+      ;; currently broken, evil hack to display help anyway
+      ;(erc-delete-query))))
+      (signal 'wrong-number-of-arguments ""))))
+(defalias 'erc-cmd-Q 'erc-cmd-QUERY)
+
+(defun erc-quit-reason-normal (&optional s)
+  "Normal quit message.
+
+If S is non-nil, it will be used as the quit reason."
+  (or s
+      (format "\C-bERC\C-b %s (IRC client for Emacs)"; - \C-b%s\C-b"
+	      erc-version-string) ; erc-official-location)
+  ))
+
+(defun erc-quit-reason-zippy (&optional s)
+  "Zippy quit message.
+
+If S is non-nil, it will be used as the quit reason."
+  (or s
+      (erc-replace-regexp-in-string "\n" "" (yow))))
+
+(defun erc-quit-reason-various (s)
+  "Choose a quit reason based on S (a string)."
+  (when (featurep 'xemacs) (require 'poe))
+  (let ((res (car (assoc-default (or s "")
+		   erc-quit-reason-various-alist 'string-match))))
+    (cond
+     ((functionp res) (funcall res))
+     ((stringp res) res)
+     ;; hopefully never reached
+     (s))))
+
+(defun erc-part-reason-normal (&optional s)
+  "Normal part message.
+
+If S is non-nil, it will be used as the quit reason."
+  (or s
+      (format "\C-bERC\C-b %s (IRC client for Emacs)"; - \C-b%s\C-b"
+	      erc-version-string) ; erc-official-location)
+  ))
+
+(defun erc-part-reason-zippy (&optional s)
+  "Zippy part message.
+
+If S is non-nil, it will be used as the quit reason."
+  (or s
+      (erc-replace-regexp-in-string "\n" "" (yow))))
+
+(defun erc-part-reason-various (s)
+  "Choose a part reason based on S (a string)."
+  (when (featurep 'xemacs) (require 'poe))
+  (let ((res (car (assoc-default (or s "")
+		   erc-part-reason-various-alist 'string-match))))
+    (cond
+     ((functionp res) (funcall res))
+     ((stringp res) res)
+     (s))))
+
+(defun erc-cmd-QUIT (reason)
+  "Disconnect from the current server.
+If REASON is omitted, display a default quit message, otherwise display
+the message given by REASON."
+  (unless reason
+    (setq reason ""))
+  (cond
+   ((string-match "^\\s-*\\(.*\\)$" reason)
+    (let* ((s (match-string 1 reason))
+	   (buffer (erc-server-buffer))
+	   (reason (funcall erc-quit-reason (if (equal s "") nil s))))
+      (with-current-buffer (if (and buffer
+				    (bufferp buffer))
+			       buffer
+			     (current-buffer))
+	(erc-log (format "cmd: QUIT: %s" reason))
+	(setq erc-server-quitting t)
+	(erc-set-active-buffer (erc-server-buffer))
+	(erc-server-send (format "QUIT :%s" reason)))
+      (run-hook-with-args 'erc-quit-hook erc-server-process)
+      (when erc-kill-queries-on-quit
+	(erc-kill-query-buffers erc-server-process)))
+    t)
+   (t nil)))
+
+(defalias 'erc-cmd-BYE 'erc-cmd-QUIT)
+(defalias 'erc-cmd-EXIT 'erc-cmd-QUIT)
+(defalias 'erc-cmd-SIGNOFF 'erc-cmd-QUIT)
+(put 'erc-cmd-QUIT 'do-not-parse-args t)
+
+(defun erc-cmd-GQUIT (reason)
+  "Disconnect from all servers at once with the same quit REASON."
+  (erc-with-all-buffers-of-server nil #'(lambda ()
+					  (and (erc-server-buffer-p)
+					       (erc-server-process-alive)))
+				  (erc-cmd-QUIT reason)))
+
+(defalias 'erc-cmd-GQ 'erc-cmd-GQUIT)
+(put 'erc-cmd-GQUIT 'do-not-parse-args t)
+
+(defun erc-cmd-SERVER (server)
+  "Connect to SERVER, leaving existing connection intact."
+  (erc-log (format "cmd: SERVER: %s" server))
+  (condition-case nil
+      (erc-select :server server :nick (erc-current-nick))
+    (error
+     (message "Cannot find host %s." server)
+     (beep)))
+  t)
+
+(eval-when-compile
+  (defvar motif-version-string)
+  (defvar gtk-version-string))
+
+(defun erc-cmd-SV ()
+  "Say the current ERC and Emacs version into channel."
+  (erc-send-message (format "I'm using ERC %s with %s %s (%s%s%s)!"
+			    erc-version-string
+			    (if (featurep 'xemacs) "XEmacs" "GNU Emacs")
+			    emacs-version
+			    system-configuration
+			    (concat
+			     (cond ((featurep 'motif)
+				    (concat ", " (substring
+						  motif-version-string 4)))
+				   ((featurep 'gtk)
+				    (concat ", GTK+ Version "
+					    gtk-version-string))
+				   ((featurep 'mac-carbon) ", Mac Carbon")
+				   ((featurep 'x-toolkit) ", X toolkit")
+				   (t ""))
+			     (if (and (boundp 'x-toolkit-scroll-bars)
+				      (memq x-toolkit-scroll-bars
+					    '(xaw xaw3d)))
+				 (format ", %s scroll bars"
+					 (capitalize (symbol-name
+						      x-toolkit-scroll-bars)))
+			       "")
+			     (if (featurep 'multi-tty) ", multi-tty" ""))
+			    (concat ", built " erc-emacs-build-time)))
+  t)
+
+(defun erc-cmd-SM ()
+  "Say the current ERC modes into channel."
+  (erc-send-message (format "I'm using the following modules: %s!"
+			    (erc-modes)))
+  t)
+
+(defun erc-cmd-SMV ()
+  "Say the current ERC module versions into channel."
+  (erc-send-message (format "I'm using the following module revisions: %s!"
+			    (erc-version-modules)))
+  t)
+
+(defun erc-cmd-DEOP (&rest people)
+  "Remove the operator setting from user(s) given in PEOPLE."
+  (when (> (length people) 0)
+    (erc-server-send (concat "MODE " (erc-default-target)
+			      " -"
+			      (make-string (length people) ?o)
+			      " "
+			      (mapconcat 'identity people " ")))
+    t))
+
+(defun erc-cmd-OP (&rest people)
+  "Add the operator setting to users(s) given in PEOPLE."
+  (when (> (length people) 0)
+    (erc-server-send (concat "MODE " (erc-default-target)
+			      " +"
+			      (make-string (length people) ?o)
+			      " "
+			      (mapconcat 'identity people " ")))
+    t))
+
+(defun erc-cmd-TIME (&optional line)
+  "Request the current time and date from the current server."
+  (cond
+   ((and line (string-match "^\\s-*\\(.*\\)$" line))
+    (let ((args (match-string 1 line)))
+      (erc-log (format "cmd: TIME: %s" args))
+      (erc-server-send (concat "TIME " args)))
+    t)
+   (t (erc-server-send "TIME"))))
+(defalias 'erc-cmd-DATE 'erc-cmd-TIME)
+
+(defun erc-cmd-TOPIC (topic)
+  "Set or request the topic for a channel.
+LINE has the format: \"#CHANNEL TOPIC\", \"#CHANNEL\", \"TOPIC\"
+or the empty string.
+
+If no #CHANNEL is given, the default channel is used.  If TOPIC is
+given, the channel topic is modified, otherwise the current topic will
+be displayed."
+  (cond
+   ;; /topic #channel TOPIC
+   ((string-match "^\\s-*\\([&#+!]\\S-+\\)\\s-\\(.*\\)$" topic)
+    (let ((ch (match-string 1 topic))
+	  (topic (match-string 2 topic)))
+      (erc-log (format "cmd: TOPIC [%s]: %s" ch topic))
+      (erc-server-send (format "TOPIC %s :%s" ch topic) nil ch))
+    t)
+   ;; /topic #channel
+   ((string-match "^\\s-*\\([&#+!]\\S-+\\)" topic)
+    (let ((ch (match-string 1 topic)))
+      (erc-server-send (format "TOPIC %s" ch) nil ch)
+      t))
+   ;; /topic
+   ((string-match "^\\s-*$" topic)
+    (let ((ch (erc-default-target)))
+      (erc-server-send (format "TOPIC %s" ch) nil ch)
+      t))
+   ;; /topic TOPIC
+   ((string-match "^\\s-*\\(.*\\)$" topic)
+    (let ((ch (erc-default-target))
+	  (topic (match-string 1 topic)))
+      (if (and ch (erc-channel-p ch))
+	  (progn
+	    (erc-log (format "cmd: TOPIC [%s]: %s" ch topic))
+	    (erc-server-send (format "TOPIC %s :%s" ch topic) nil ch))
+	(erc-display-message nil 'error (current-buffer) 'no-target)))
+    t)
+   (t nil)))
+(defalias 'erc-cmd-T 'erc-cmd-TOPIC)
+(put 'erc-cmd-TOPIC 'do-not-parse-args t)
+
+(defun erc-cmd-APPENDTOPIC (topic)
+  "Append TOPIC to the current channel topic, separated by a space."
+  (let ((oldtopic erc-channel-topic))
+    ;; display help when given no arguments
+    (when (string-match "^\\s-*$" topic)
+      (signal 'wrong-number-of-arguments nil))
+    ;; strip trailing ^O
+    (when (string-match "\\(.*\\)\C-o" oldtopic)
+      (erc-cmd-TOPIC (concat (match-string 1 oldtopic) topic)))))
+(defalias 'erc-cmd-AT 'erc-cmd-APPENDTOPIC)
+(put 'erc-cmd-APPENDTOPIC 'do-not-parse-args t)
+
+(defun erc-cmd-CLEARTOPIC (&optional channel)
+  "Clear the topic for a CHANNEL.
+If CHANNEL is not specified, clear the topic for the default channel."
+  (interactive "sClear topic of channel (RET is current channel): ")
+  (let ((chnl (or (and (erc-channel-p channel) channel) (erc-default-target))))
+    (when chnl
+      (erc-server-send (format "TOPIC %s :" chnl))
+      t)))
+
+;;; Banlists
+
+(defvar erc-channel-banlist nil
+  "A list of bans seen for the current channel.
+
+Each ban is an alist of the form:
+  (WHOSET . MASK)
+
+The property `received-from-server' indicates whether
+or not the ban list has been requested from the server.")
+(make-variable-buffer-local 'erc-channel-banlist)
+(put 'erc-channel-banlist 'received-from-server nil)
+
+(defun erc-cmd-BANLIST ()
+  "Pretty-print the contents of `erc-channel-banlist'.
+
+The ban list is fetched from the server if necessary."
+  (let ((chnl (erc-default-target))
+	(chnl-name (buffer-name)))
+
+    (cond
+     ((not (erc-channel-p chnl))
+      (erc-display-line (erc-make-notice "You're not on a channel\n")
+			'active))
+
+     ((not (get 'erc-channel-banlist 'received-from-server))
+      (let ((old-367-hook erc-server-367-functions))
+	(setq erc-server-367-functions 'erc-banlist-store
+	      erc-channel-banlist nil)
+	;; fetch the ban list then callback
+	(with-current-buffer (erc-server-buffer)
+	  (erc-once-with-server-event
+	   368
+	   `(with-current-buffer ,chnl-name
+	      (put 'erc-channel-banlist 'received-from-server t)
+	      (setq erc-server-367-functions ',old-367-hook)
+	      (erc-cmd-BANLIST)
+	      t))
+	  (erc-server-send (format "MODE %s b" chnl)))))
+
+     ((null erc-channel-banlist)
+      (erc-display-line (erc-make-notice
+			 (format "No bans for channel: %s\n" chnl))
+			'active)
+      (put 'erc-channel-banlist 'received-from-server nil))
+
+     (t
+      (let* ((erc-fill-column (or (and (boundp 'erc-fill-column)
+				       erc-fill-column)
+				  (and (boundp 'fill-column)
+				       fill-column)
+				  (1- (window-width))))
+	     (separator (make-string erc-fill-column (string-to-char "=")))
+	     (fmt (concat
+		   "%-" (number-to-string (/ erc-fill-column 2)) "s"
+		   "%" (number-to-string (/ erc-fill-column 2)) "s")))
+
+	(erc-display-line
+	 (erc-make-notice (format "Ban list for channel: %s\n"
+				  (erc-default-target)))
+	 'active)
+
+	(erc-display-line separator 'active)
+	(erc-display-line (format fmt "Ban Mask" "Banned By") 'active)
+	(erc-display-line separator 'active)
+
+	(mapc
+	 (lambda (x)
+	   (erc-display-line
+	    (format fmt
+		    (truncate-string-to-width (cdr x) (/ erc-fill-column 2))
+		    (if (car x)
+			(truncate-string-to-width (car x) (/ erc-fill-column 2))
+		      ""))
+	    'active))
+	 erc-channel-banlist)
+
+	(erc-display-line (erc-make-notice "End of Ban list")
+			  'active)
+	(put 'erc-channel-banlist 'received-from-server nil)))))
+  t)
+
+(defalias 'erc-cmd-BL 'erc-cmd-BANLIST)
+
+(defun erc-cmd-MASSUNBAN ()
+  "Mass Unban.
+
+Unban all currently banned users in the current channel."
+  (let ((chnl (erc-default-target)))
+    (cond
+
+     ((not (erc-channel-p chnl))
+      (erc-display-line
+       (erc-make-notice "You're not on a channel\n")
+       'active))
+
+     ((not (get 'erc-channel-banlist 'received-from-server))
+      (let ((old-367-hook erc-server-367-functions))
+	(setq erc-server-367-functions 'erc-banlist-store)
+      ;; fetch the ban list then callback
+      (with-current-buffer (erc-server-buffer)
+	(erc-once-with-server-event
+	 368
+	 `(with-current-buffer ,chnl
+	    (put 'erc-channel-banlist 'received-from-server t)
+	      (setq erc-server-367-functions ,old-367-hook)
+	    (erc-cmd-MASSUNBAN)
+	    t))
+	  (erc-server-send (format "MODE %s b" chnl)))))
+
+     (t (let ((bans (mapcar 'cdr erc-channel-banlist)))
+    (when bans
+      ;; Glob the bans into groups of three, and carry out the unban.
+      ;; eg. /mode #foo -bbb a*!*@* b*!*@* c*!*@*
+      (mapc
+       (lambda (x)
+	 (erc-server-send
+	  (format "MODE %s -%s %s" (erc-default-target)
+		  (make-string (length x) (string-to-char "b"))
+			(mapconcat 'identity x " "))))
+       (erc-group-list bans 3))))
+	t))))
+
+(defalias 'erc-cmd-MUB 'erc-cmd-MASSUNBAN)
+
+;;;; End of IRC commands
+
+(defun erc-ensure-channel-name (channel)
+  "Return CHANNEL if it is a valid channel name.
+Eventually add a # in front of it, if that turns it into a valid channel name."
+  (if (erc-channel-p channel)
+      channel
+    (concat "#" channel)))
+
+(defun erc-grab-region (start end)
+  "Copy the region between START and END in a recreatable format.
+
+Converts all the IRC text properties in each line of the region
+into control codes and writes them to a separate buffer.  The
+resulting text may be used directly as a script to generate this
+text again."
+  (interactive "r")
+  (erc-set-active-buffer (current-buffer))
+  (save-excursion
+    (let* ((cb (current-buffer))
+	   (buf (generate-new-buffer erc-grab-buffer-name))
+	   (region (buffer-substring start end))
+	   (lines (erc-split-multiline-safe region)))
+      (set-buffer buf)
+      (dolist (line lines)
+	(insert (concat line "\n")))
+      (set-buffer cb)
+      (switch-to-buffer-other-window buf)))
+  (message "erc-grab-region doesn't grab colors etc. anymore. If you use this, please tell the maintainers.")
+  (ding))
+
+(defun erc-display-prompt (&optional buffer pos prompt face)
+  "Display PROMPT in BUFFER at position POS.
+Display an ERC prompt in BUFFER.
+
+If PROMPT is nil, one is constructed with the function `erc-prompt'.
+If BUFFER is nil, the `current-buffer' is used.
+If POS is nil, PROMPT will be displayed at `point'.
+If FACE is non-nil, it will be used to propertize the prompt.  If it is nil,
+`erc-prompt-face' will be used."
+  (let* ((prompt (or prompt (erc-prompt)))
+	 (l (length prompt))
+	 (ob (current-buffer)))
+    ;; We cannot use save-excursion because we move point, therefore
+    ;; we resort to the ol' ob trick to restore this.
+    (when (and buffer (bufferp buffer))
+      (set-buffer buffer))
+
+    ;; now save excursion again to store where point and mark are
+    ;; in the current buffer
+    (save-excursion
+      (setq pos (or pos (point)))
+      (goto-char pos)
+      (when (> l 0)
+	;; Do not extend the text properties when typing at the end
+	;; of the prompt, but stuff typed in front of the prompt
+	;; shall remain part of the prompt.
+	(setq prompt (erc-propertize prompt
+				     'start-open t ; XEmacs
+				     'rear-nonsticky t ; Emacs
+				     'erc-prompt t
+				     'front-sticky t
+				     'read-only t))
+	(erc-put-text-property 0 (1- (length prompt))
+			       'face (or face 'erc-prompt-face)
+			       prompt)
+	(insert prompt))
+      ;; Set the input marker
+      (set-marker erc-input-marker (point)))
+
+    ;; Now we are back at the old position.  If the prompt was
+    ;; inserted here or before us, advance point by the length of
+    ;; the prompt.
+    (when (or (not pos) (<= (point) pos))
+      (forward-char l))
+    ;; Clear the undo buffer now, so the user can undo his stuff,
+    ;; but not the stuff we did. Sneaky!
+    (setq buffer-undo-list nil)
+    (set-buffer ob)))
+
+;; interactive operations
+
+(defun erc-input-message ()
+  "Read input from the minibuffer."
+  (interactive)
+  (let ((minibuffer-allow-text-properties t)
+	(read-map minibuffer-local-map))
+    (insert (read-from-minibuffer "Message: "
+				  (string last-command-char) read-map))
+    (erc-send-current-line)))
+
+(defvar erc-action-history-list ()
+  "History list for interactive action input.")
+
+(defun erc-input-action ()
+  "Interactively input a user action and send it to IRC."
+  (interactive "")
+  (erc-set-active-buffer (current-buffer))
+  (let ((action (read-from-minibuffer
+		 "Action: " nil nil nil 'erc-action-history-list)))
+    (if (not (string-match "^\\s-*$" action))
+	(erc-send-action (erc-default-target) action))))
+
+(defun erc-join-channel (channel &optional key)
+  "Join CHANNEL.
+
+If `point' is at the beginning of a channel name, use that as default."
+  (interactive
+   (list
+    (let ((chnl (if (looking-at "\\([&#+!][^ ]+\\)") (match-string 1) ""))
+	  (table (when (erc-server-buffer-live-p)
+		   (set-buffer (process-buffer erc-server-process))
+		   erc-channel-list)))
+      (completing-read "Join channel: " table nil nil nil nil chnl))
+    (when erc-prompt-for-channel-key
+      (read-from-minibuffer "Channel key (RET for none): " nil))))
+  (erc-cmd-JOIN channel (when (>= (length key) 1) key)))
+
+(defun erc-part-from-channel (reason)
+  "Part from the current channel and prompt for a REASON."
+  (interactive
+   (list
+    (if (and (boundp 'reason) (stringp reason) (not (string= reason "")))
+	reason
+      (read-from-minibuffer (concat "Leave " (erc-default-target)
+				    ", Reason? ")
+			    (cons "No reason" 0)))))
+  (erc-cmd-PART (concat (erc-default-target)" " reason)))
+
+(defun erc-set-topic (topic)
+  "Prompt for a TOPIC for the current channel."
+  (interactive
+   (list
+    (read-from-minibuffer
+     (concat "Set topic of " (erc-default-target) ": ")
+     (when erc-channel-topic
+       (cons (apply 'concat (butlast (split-string erc-channel-topic "\C-o")))
+	     0)))))
+  (let ((topic-list (split-string topic "\C-o"))) ; strip off the topic setter
+    (erc-cmd-TOPIC (concat (erc-default-target) " " (car topic-list)))))
+
+(defun erc-set-channel-limit (&optional limit)
+  "Set a LIMIT for the current channel.  Remove limit if nil.
+Prompt for one if called interactively."
+  (interactive (list (read-from-minibuffer
+		      (format "Limit for %s (RET to remove limit): "
+			      (erc-default-target)))))
+  (let ((tgt (erc-default-target)))
+    (if (and limit (>= (length limit) 1))
+	(erc-server-send (format "MODE %s +l %s" tgt limit))
+      (erc-server-send (format "MODE %s -l" tgt)))))
+
+(defun erc-set-channel-key (&optional key)
+  "Set a KEY for the current channel.  Remove key if nil.
+Prompt for one if called interactively."
+  (interactive (list (read-from-minibuffer
+		      (format "Key for %s (RET to remove key): "
+			      (erc-default-target)))))
+  (let ((tgt (erc-default-target)))
+    (if (and key (>= (length key) 1))
+	(erc-server-send (format "MODE %s +k %s" tgt key))
+      (erc-server-send (format "MODE %s -k" tgt)))))
+
+(defun erc-quit-server (reason)
+  "Disconnect from current server after prompting for REASON.
+`erc-quit-reason' works with this just like with `erc-cmd-QUIT'."
+  (interactive (list (read-from-minibuffer
+		      (format "Reason for quitting %s: "
+			      (or erc-server-announced-name
+				  erc-session-server)))))
+  (erc-cmd-QUIT reason))
+
+;; Movement of point
+
+(defun erc-bol ()
+  "Move `point' to the beginning of the current line.
+
+This places `point' just after the prompt, or at the beginning of the line."
+  (interactive)
+  (forward-line 0)
+  (when (get-text-property (point) 'erc-prompt)
+    (goto-char erc-input-marker))
+  (point))
+
+(defun erc-kill-input ()
+  "Kill current input line using `erc-bol' followed by `kill-line'."
+  (interactive)
+  (when (and (erc-bol)
+	     (/= (point) (point-max))) ;; Prevent a (ding) and an error when
+				       ;; there's nothing to kill
+    (if (boundp 'erc-input-ring-index)
+	(setq erc-input-ring-index nil))
+    (kill-line)))
+
+(defun erc-complete-word ()
+  "Complete the word before point.
+
+This function uses `erc-complete-functions'."
+  (interactive)
+  (unless (run-hook-with-args-until-success 'erc-complete-functions)
+    (beep)))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;;			  IRC SERVER INPUT HANDLING
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;;;; New Input parsing
+
+; Stolen from ZenIRC. I just wanna test this code, so here is
+; experiment area.
+
+(defcustom erc-default-server-hook '(erc-debug-missing-hooks
+				     erc-default-server-handler)
+  "*Default for server messages which aren't covered by `erc-server-hooks'."
+  :group 'erc-server-hooks
+  :type 'hook)
+
+(defun erc-default-server-handler (proc parsed)
+  "Default server handler.
+
+Displays PROC and PARSED appropriately using `erc-display-message'."
+  (erc-display-message
+   parsed 'notice proc
+   (mapconcat
+    'identity
+    (let (res)
+      (mapc #'(lambda (x)
+		(if (stringp x)
+		    (setq res (append res (list x)))))
+	    parsed)
+      res)
+    " ")))
+
+(defvar erc-server-vectors
+  '(["msgtype" "sender" "to" "arg1" "arg2" "arg3" "..."])
+  "List of received server messages which ERC does not specifically handle.
+See `erc-debug-missing-hooks'.")
+;(make-variable-buffer-local 'erc-server-vectors)
+
+(defun erc-debug-missing-hooks (proc parsed)
+  "Add PARSED server message ERC does not yet handle to `erc-server-vectors'.
+These vectors can be helpful when adding new server message handlers to ERC.
+See `erc-default-server-hook'."
+  (nconc erc-server-vectors (list parsed))
+  nil)
+
+(defun erc-query (target server)
+  "Open a query buffer on TARGET, using SERVER.
+To change how this query window is displayed, use `let' to bind
+`erc-join-buffer' before calling this."
+  (unless (and server
+	       (buffer-live-p server)
+	       (set-buffer server))
+    (error "Couldn't switch to server buffer"))
+  (let ((buf (erc erc-session-server
+		  erc-session-port
+		  (erc-current-nick)
+		  erc-session-user-full-name
+		  nil
+		  nil
+		  (list target)
+		  target
+		  erc-server-process)))
+    (unless buf
+      (error "Couldn't open query window"))
+    (erc-update-mode-line)
+    buf))
+
+(defcustom erc-auto-query nil
+  "If non-nil, create a query buffer each time you receive a private message.
+
+If the buffer doesn't already exist it is created.  This can be
+set to a symbol, to control how the new query window should
+appear.  See the documentation for `erc-join-buffer' for
+available choices."
+  :group 'erc-query
+  :type '(choice (const nil)
+		 (const buffer)
+		 (const window)
+		 (const window-noselect)
+		 (const bury)
+		 (const frame)))
+
+(defcustom erc-query-on-unjoined-chan-privmsg t
+  "If non-nil create query buffer on receiving any PRIVMSG at all.
+This includes PRIVMSGs directed to channels.  If you are using an IRC
+bouncer, such as dircproxy, to keep a log of channels when you are
+disconnected, you should set this option to t."
+  :group 'erc-query
+  :type 'boolean)
+
+(defcustom erc-format-query-as-channel-p t
+  "If non-nil, format text from others in a query buffer like in a channel,
+otherwise format like a private message."
+  :group 'erc-query
+  :type 'boolean)
+
+(defcustom erc-minibuffer-notice nil
+  "If non-nil, print ERC notices for the user in the minibuffer.
+Only happens when the session buffer isn't visible."
+  :group 'erc-display
+  :type 'boolean)
+
+(defcustom erc-minibuffer-ignored nil
+  "If non-nil, print a message in the minibuffer if we ignored something."
+  :group 'erc-ignore
+  :type 'boolean)
+
+(defun erc-wash-quit-reason (reason nick login host)
+  "Remove duplicate text from quit REASON.
+Specifically in relation to NICK (user@host) information.  Returns REASON
+unmodified if nothing can be removed.
+E.g. \"Read error to Nick [user@some.host]: 110\" would be shortened to
+\"Read error: 110\". The same applies for \"Ping Timeout\"."
+  (setq nick (regexp-quote nick)
+	login (regexp-quote login)
+	host (regexp-quote host))
+  (or (when (string-match (concat "^\\(Read error\\) to "
+				  nick "\\[" host "\\]: "
+				  "\\(.+\\)$") reason)
+	(concat (match-string 1 reason) ": " (match-string 2 reason)))
+      (when (string-match (concat "^\\(Ping timeout\\) for "
+				  nick "\\[" host "\\]$") reason)
+	(match-string 1 reason))
+      reason))
+
+(defun erc-nickname-in-use (nick reason)
+  "If NICK is unavailable, tell the user the REASON.
+
+See also `erc-display-error-notice'."
+  (if (or erc-manual-set-nick-on-bad-nick-p
+	  ;; how many default-nicks are left + one more try...
+	  (eq erc-nick-change-attempt-count
+	      (if (consp erc-nick)
+		  (+ (length erc-nick) 1)
+		1)))
+      (erc-display-error-notice
+       nil
+       (format "Nickname %s is %s, try another." nick reason))
+    (setq erc-nick-change-attempt-count (+ erc-nick-change-attempt-count 1))
+    (let ((newnick (nth 1 erc-default-nicks))
+	  (nicklen (cdr (assoc "NICKLEN"
+			       (with-current-buffer (erc-server-buffer)
+				 erc-server-parameters)))))
+      (setq erc-bad-nick t)
+      ;; try to use a different nick
+      (if erc-default-nicks
+	  (setq erc-default-nicks (cdr erc-default-nicks)))
+      (if (not newnick)
+	  (setq newnick (concat (truncate-string-to-width
+				 nick
+				 (if (and erc-server-connected nicklen)
+				     (- (string-to-number nicklen) 1)
+				   ;; rfc2812 max nick length = 9
+				   ;; we must assume this is the
+				   ;; server's setting if we haven't
+				   ;; established a connection yet
+				   8))
+				erc-nick-uniquifier)))
+      (erc-cmd-NICK newnick)
+      (erc-display-error-notice
+       nil
+       (format "Nickname %s is %s, trying %s"
+	       nick reason newnick)))))
+
+;;; Server messages
+
+(defgroup erc-server-hooks nil
+  "Server event callbacks.
+Every server event - like numeric replies - has it's own hook.
+Those hooks are all called using `run-hook-with-args-until-success'.
+They receive as first argument the process object from where the event
+originated from,
+and as second argument the event parsed as a vector."
+  :group 'erc-hooks)
+
+(defun erc-display-server-message (proc parsed)
+  "Display the message sent by the server as a notice."
+  (erc-display-message
+   parsed 'notice 'active (erc-response.contents parsed)))
+
+(defun erc-auto-query (proc parsed)
+  ;; FIXME: This needs more documentation, unless it's not a user function --
+  ;; Lawrence 2004-01-08
+  "Put this on `erc-server-PRIVMSG-functions'."
+  (when erc-auto-query
+    (let* ((nick (car (erc-parse-user (erc-response.sender parsed))))
+	   (target (car (erc-response.command-args parsed)))
+	   (msg (erc-response.contents parsed))
+	   (query  (if (not erc-query-on-unjoined-chan-privmsg)
+		       nick
+		     (if (erc-current-nick-p target)
+			 nick
+		       target))))
+      (and (not (erc-ignored-user-p (erc-response.sender parsed)))
+	   (or erc-query-on-unjoined-chan-privmsg
+	       (string= target (erc-current-nick)))
+	   (not (erc-get-buffer query proc))
+	   (not (erc-is-message-ctcp-and-not-action-p msg))
+	   (let ((erc-join-buffer erc-auto-query))
+	     (erc-cmd-QUERY query))
+	   nil))))
+
+(defun erc-is-message-ctcp-p (message)
+  "Check if MESSAGE is a CTCP message or not."
+  (string-match "^\C-a\\([^\C-a]*\\)\C-a?$" message))
+
+(defun erc-is-message-ctcp-and-not-action-p (message)
+  "Check if MESSAGE is a CTCP message or not."
+  (and (erc-is-message-ctcp-p message)
+       (not (string-match "^\C-a\\ACTION.*\C-a$" message))))
+
+(defun erc-format-privmessage (nick msg privp msgp)
+  "Format a PRIVMSG in an insertible fashion."
+  (let* ((mark-s (if msgp (if privp "*" "<") "-"))
+	 (mark-e (if msgp (if privp "*" ">") "-"))
+	 (str	 (format "%s%s%s %s" mark-s nick mark-e msg))
+	 (nick-face (if privp 'erc-nick-msg-face 'erc-nick-default-face))
+	 (msg-face (if privp 'erc-direct-msg-face 'erc-default-face)))
+    ;; add text properties to text before the nick, the nick and after the nick
+    (erc-put-text-property 0 (length mark-s) 'face msg-face str)
+    (erc-put-text-property (length mark-s) (+ (length mark-s) (length nick))
+			   'face nick-face str)
+    (erc-put-text-property (+ (length mark-s) (length nick)) (length str)
+			   'face msg-face str)
+    str))
+
+(defcustom erc-format-nick-function 'erc-format-nick
+  "*Function to format a nickname for message display."
+  :group 'erc-display
+  :type 'function)
+
+(defun erc-format-nick (&optional user channel-data)
+  "Standard nickname formatting function.  Only returns the value
+of NICK."
+  (if user
+      (erc-server-user-nickname user)))
+
+(defun erc-format-@nick (&optional user channel-data)
+  "Format a nickname such that @ or + are prefix for the NICK
+if OP or VOICE are t respectively."
+  (if user
+      (let (op voice)
+	(if channel-data
+	    (setq op (erc-channel-user-op channel-data)
+		  voice (erc-channel-user-voice channel-data)))
+    (concat (if voice "+" "")
+	    (if op "@" "")
+		(erc-server-user-nickname user)))))
+
+(defun erc-format-my-nick ()
+  "Return the beginning of this user's message, correctly propertized"
+  (if erc-show-my-nick
+      (let ((open "<")
+	    (close "> ")
+	    (nick (erc-current-nick)))
+	(concat
+	 (erc-propertize open 'face 'erc-default-face)
+	 (erc-propertize nick 'face 'erc-nick-default-face)
+	 (erc-propertize close 'face 'erc-default-face)))
+    (let ((prefix "> "))
+      (erc-propertize prefix 'face 'erc-default-face))))
+
+(defun erc-echo-notice-in-default-buffer (s parsed buffer sender)
+  "Echos a private notice in the default buffer, namely the
+target buffer specified by BUFFER, or there is no target buffer,
+the server buffer.  This function is designed to be added to
+either `erc-echo-notice-hook' or `erc-echo-notice-always-hook',
+and always returns t."
+  (erc-display-message parsed nil buffer s)
+  t)
+
+(defun erc-echo-notice-in-target-buffer (s parsed buffer sender)
+  "Echos a private notice in BUFFER, if BUFFER is non-nil.  This
+function is designed to be added to either `erc-echo-notice-hook'
+or `erc-echo-notice-always-hook', and returns non-nil iff BUFFER
+is non-nil."
+  (if buffer
+      (progn (erc-display-message parsed nil buffer s) t)
+    nil))
+
+(defun erc-echo-notice-in-minibuffer (s parsed buffer sender)
+  "Echos a private notice in the minibuffer.  This function is
+designed to be added to either `erc-echo-notice-hook' or
+`erc-echo-notice-always-hook', and always returns t."
+  (message "%s" (concat "NOTICE: " s))
+  t)
+
+(defun erc-echo-notice-in-server-buffer (s parsed buffer sender)
+  "Echos a private notice in the server buffer.  This function is
+designed to be added to either `erc-echo-notice-hook' or
+`erc-echo-notice-always-hook', and always returns t."
+  (erc-display-message parsed nil nil s)
+  t)
+
+(defun erc-echo-notice-in-active-non-server-buffer (s parsed buffer sender)
+  "Echos a private notice in the active buffer if the active
+buffer is not the server buffer.  This function is designed to be
+added to either `erc-echo-notice-hook' or
+`erc-echo-notice-always-hook', and returns non-nil iff the active
+buffer is not the server buffer."
+  (if (not (eq (erc-server-buffer) (erc-active-buffer)))
+      (progn (erc-display-message parsed nil 'active s) t)
+    nil))
+
+(defun erc-echo-notice-in-active-buffer (s parsed buffer sender)
+  "Echos a private notice in the active buffer.  This function is
+designed to be added to either `erc-echo-notice-hook' or
+`erc-echo-notice-always-hook', and always returns t."
+  (erc-display-message parsed nil 'active s)
+  t)
+
+(defun erc-echo-notice-in-user-buffers (s parsed buffer sender)
+  "Echos a private notice in all of the buffers for which SENDER
+is a member.  This function is designed to be added to either
+`erc-echo-notice-hook' or `erc-echo-notice-always-hook', and
+returns non-nil iff there is at least one buffer for which the
+sender is a member.
+
+See also: `erc-echo-notice-in-first-user-buffer',
+`erc-buffer-list-with-nick'"
+  (let ((buffers (erc-buffer-list-with-nick sender erc-server-process)))
+    (if buffers
+	(progn (erc-display-message parsed nil buffers s) t)
+      nil)))
+
+(defun erc-echo-notice-in-user-and-target-buffers (s parsed buffer sender)
+  "Echos a private notice in BUFFER and in all of the buffers for
+which SENDER is a member.  This function is designed to be added
+to either `erc-echo-notice-hook' or
+`erc-echo-notice-always-hook', and returns non-nil iff there is
+at least one buffer for which the sender is a member or the
+default target.
+
+See also: `erc-echo-notice-in-user-buffers',
+`erc-buffer-list-with-nick'"
+  (let ((buffers (erc-buffer-list-with-nick sender erc-server-process)))
+    (add-to-list 'buffers buffer)
+    (if buffers
+	(progn (erc-display-message parsed nil buffers s) t)
+      nil)))
+
+(defun erc-echo-notice-in-first-user-buffer (s parsed buffer sender)
+  "Echos a private notice in one of the buffers for which SENDER
+is a member.  This function is designed to be added to either
+`erc-echo-notice-hook' or `erc-echo-notice-always-hook', and
+returns non-nil iff there is at least one buffer for which the
+sender is a member.
+
+See also: `erc-echo-notice-in-user-buffers',
+`erc-buffer-list-with-nick'"
+  (let ((buffers (erc-buffer-list-with-nick sender erc-server-process)))
+    (if buffers
+	(progn (erc-display-message parsed nil (car buffers) s) t)
+      nil)))
+
+;;; Ban manipulation
+
+(defun erc-banlist-store (proc parsed)
+  "Record ban entries for a channel."
+  (multiple-value-bind (channel mask whoset)
+      (cdr (erc-response.command-args parsed))
+    ;; Determine to which buffer the message corresponds
+    (let ((buffer (erc-get-buffer channel proc)))
+      (with-current-buffer buffer
+	(unless (member (cons whoset mask) erc-channel-banlist)
+	  (setq erc-channel-banlist (cons (cons whoset mask)
+					  erc-channel-banlist))))))
+  nil)
+
+(defun erc-banlist-finished (proc parsed)
+  "Record that we have received the banlist."
+  (let* ((channel (second (erc-response.command-args parsed)))
+	 (buffer (erc-get-buffer channel proc)))
+    (with-current-buffer buffer
+      (put 'erc-channel-banlist 'received-from-server t)))
+  t)					; suppress the 'end of banlist' message
+
+(defun erc-banlist-update (proc parsed)
+  "Check MODE commands for bans and update the banlist appropriately."
+  ;; FIXME: Possibly incorrect. -- Lawrence 2004-05-11
+  (let* ((tgt (first (erc-response.command-args parsed)))
+	 (mode (erc-response.contents parsed))
+	 (whoset (erc-response.sender parsed))
+	 (buffer (erc-get-buffer tgt proc)))
+    (when buffer
+      (with-current-buffer buffer
+	(cond ((not (get 'erc-channel-banlist 'received-from-server)) nil)
+	      ((string-match "^\\([+-]\\)b" mode)
+	       ;; This is a ban
+	       (cond
+		((string-match "^-" mode)
+		 ;; Remove the unbanned masks from the ban list
+		 (setq erc-channel-banlist
+		       (erc-delete-if
+			#'(lambda (y)
+			    (member (upcase (cdr y))
+				    (mapcar #'upcase
+					    (cdr (split-string mode)))))
+			erc-channel-banlist)))
+		((string-match "^+" mode)
+		 ;; Add the banned mask(s) to the ban list
+		 (mapc
+		  (lambda (mask)
+		    (unless (member (cons whoset mask) erc-channel-banlist)
+		      (setq erc-channel-banlist
+			    (cons (cons whoset mask) erc-channel-banlist))))
+		  (cdr (split-string mode))))))))))
+  nil)
+
+;; used for the banlist cmds
+(defun erc-group-list (list n)
+  "Group LIST into sublists of length N."
+  (cond ((null list) nil)
+	((null (nthcdr n list)) (list list))
+	(t (cons (erc-subseq list 0 n) (erc-group-list (nthcdr n list) n)))))
+
+
+;;; MOTD numreplies
+
+(defun erc-handle-login ()
+  "Handle the logging in process of connection."
+  (unless erc-logged-in
+    (setq erc-logged-in t)
+    (message "Logging in as \'%s\'... done" (erc-current-nick))
+    ;; execute a startup script
+    (let ((f (erc-select-startup-file)))
+      (when f
+	(erc-load-script f)))))
+
+(defun erc-connection-established (proc parsed)
+  "Run just after connection.
+
+Set user modes and run `erc-after-connect hook'."
+  (unless erc-server-connected ; only once per session
+    (let ((server (or erc-server-announced-name (erc-response.sender parsed)))
+	  (nick (car (erc-response.command-args parsed ))))
+      (setq erc-server-connected t)
+      (erc-update-mode-line)
+      (erc-set-initial-user-mode nick)
+      (erc-server-setup-periodical-server-ping)
+      (run-hook-with-args 'erc-after-connect server nick))))
+
+(defun erc-set-initial-user-mode (nick)
+  "If `erc-user-mode' is non-nil for NICK, set the user modes."
+  (when erc-user-mode
+    (let ((mode (if (functionp erc-user-mode)
+		    (funcall erc-user-mode)
+		  erc-user-mode)))
+      (when (stringp mode)
+	(erc-log (format "changing mode for %s to %s" nick mode))
+	(erc-server-send (format "MODE %s %s" nick mode))))))
+
+(defun erc-display-error-notice (parsed string)
+  "Display STRING as an error notice.
+
+See also `erc-display-message'."
+  (erc-display-message
+   parsed '(notice error) 'active string))
+
+(defun erc-process-ctcp-query (proc parsed nick login host)
+  ;; FIXME: This needs a proper docstring -- Lawrence 2004-01-08
+  "Process a CTCP query."
+  (let ((queries (delete "" (split-string (erc-response.contents parsed)
+					  "\C-a"))))
+    (if (> (length queries) 4)
+	(erc-display-message
+	 parsed (list 'notice 'error) proc 'ctcp-too-many)
+      (if (= 0 (length queries))
+	  (erc-display-message
+	   parsed (list 'notice 'error) proc
+	   'ctcp-empty ?n nick)
+	(while queries
+	  (let* ((type (upcase (car (split-string (car queries)))))
+		 (hook (intern-soft (concat "erc-ctcp-query-" type "-hook"))))
+	    (if (and hook (boundp hook))
+		(if (string-equal type "ACTION")
+		    (run-hook-with-args-until-success
+		     hook proc parsed nick login host
+		     (car (erc-response.command-args parsed))
+		     (car queries))
+		  (when erc-paranoid
+		    (if (erc-current-nick-p
+			 (car (erc-response.command-args parsed)))
+			(erc-display-message
+			 parsed 'error 'active 'ctcp-request
+			 ?n nick ?u login ?h host ?r (car queries))
+		      (erc-display-message
+		       parsed 'error 'active 'ctcp-request-to
+		       ?n nick ?u login ?h host ?r (car queries)
+		       ?t (car (erc-response.command-args parsed)))))
+		  (run-hook-with-args-until-success
+		   hook proc nick login host
+		   (car (erc-response.command-args parsed))
+		   (car queries)))
+	      (erc-display-message
+	       parsed (list 'notice 'error) proc
+	       'undefined-ctcp)))
+	  (setq queries (cdr queries)))))))
+
+(defvar erc-ctcp-query-ACTION-hook '(erc-ctcp-query-ACTION))
+
+(defun erc-ctcp-query-ACTION (proc parsed nick login host to msg)
+  "Respond to a CTCP ACTION query."
+  (when (string-match "^ACTION\\s-\\(.*\\)\\s-*$" msg)
+    (let ((s (match-string 1 msg))
+	  (buf (or (erc-get-buffer to proc)
+		   (erc-get-buffer nick proc)
+		   (process-buffer proc))))
+      (erc-display-message
+       parsed 'action buf
+       'ACTION ?n nick ?u login ?h host ?a s))))
+
+(defvar erc-ctcp-query-CLIENTINFO-hook '(erc-ctcp-query-CLIENTINFO))
+
+(defun erc-ctcp-query-CLIENTINFO (proc nick login host to msg)
+  "Respond to a CTCP CLIENTINFO query."
+  (when (string-match "^CLIENTINFO\\(\\s-*\\|\\s-+.*\\)$" msg)
+    (let ((s (erc-client-info (erc-trim-string (match-string 1 msg)))))
+      (unless erc-disable-ctcp-replies
+	  (erc-send-ctcp-notice nick (format "CLIENTINFO %s" s)))))
+  nil)
+
+(defvar erc-ctcp-query-ECHO-hook '(erc-ctcp-query-ECHO))
+(defun erc-ctcp-query-ECHO (proc nick login host to msg)
+  "Respond to a CTCP ECHO query."
+  (when (string-match "^ECHO\\s-+\\(.*\\)\\s-*$" msg)
+    (let ((s (match-string 1 msg)))
+      (unless erc-disable-ctcp-replies
+	(erc-send-ctcp-notice nick (format "ECHO %s" s)))))
+  nil)
+
+(defvar erc-ctcp-query-FINGER-hook '(erc-ctcp-query-FINGER))
+(defun erc-ctcp-query-FINGER (proc nick login host to msg)
+  "Respond to a CTCP FINGER query."
+  (unless erc-disable-ctcp-replies
+    (let ((s (if erc-anonymous-login
+		 (format "FINGER I'm %s." (erc-current-nick))
+	       (format "FINGER %s (%s@%s)."
+		       (user-full-name)
+		       (user-login-name)
+		       (system-name))))
+	  (ns (erc-time-diff erc-server-last-sent-time (erc-current-time))))
+	(when (> ns 0)
+	    (setq s (concat s " Idle for " (erc-sec-to-time ns))))
+	(erc-send-ctcp-notice nick s)))
+  nil)
+
+(defvar erc-ctcp-query-PING-hook '(erc-ctcp-query-PING))
+(defun erc-ctcp-query-PING (proc nick login host to msg)
+  "Respond to a CTCP PING query."
+  (when (string-match "^PING\\s-+\\(.*\\)" msg)
+    (unless erc-disable-ctcp-replies
+      (let ((arg (match-string 1 msg)))
+	(erc-send-ctcp-notice nick (format "PING %s" arg)))))
+  nil)
+
+(defvar erc-ctcp-query-TIME-hook '(erc-ctcp-query-TIME))
+(defun erc-ctcp-query-TIME (proc nick login host to msg)
+  "Respond to a CTCP TIME query."
+  (unless erc-disable-ctcp-replies
+    (erc-send-ctcp-notice nick (format "TIME %s" (current-time-string))))
+  nil)
+
+(defvar erc-ctcp-query-USERINFO-hook '(erc-ctcp-query-USERINFO))
+(defun erc-ctcp-query-USERINFO (proc nick login host to msg)
+  "Respond to a CTCP USERINFO query."
+  (unless erc-disable-ctcp-replies
+    (erc-send-ctcp-notice nick (format "USERINFO %s" erc-user-information)))
+  nil)
+
+(defvar erc-ctcp-query-VERSION-hook '(erc-ctcp-query-VERSION))
+(defun erc-ctcp-query-VERSION (proc nick login host to msg)
+  "Respond to a CTCP VERSION query."
+  (unless erc-disable-ctcp-replies
+    (erc-send-ctcp-notice
+     nick (format
+	   "VERSION \C-bERC\C-b %s - an IRC client for emacs (\C-b%s\C-b)"
+	   erc-version-string
+	   erc-official-location)))
+  nil)
+
+(defun erc-process-ctcp-reply (proc parsed nick login host msg)
+  "Process MSG as a CTCP reply."
+  (let* ((type (car (split-string msg)))
+	 (hook (intern (concat "erc-ctcp-reply-" type "-hook"))))
+    (if (boundp hook)
+	(run-hook-with-args-until-success
+	 hook proc nick login host
+	 (car (erc-response.command-args parsed)) msg)
+      (erc-display-message
+       parsed 'notice 'active
+       'CTCP-UNKNOWN ?n nick ?u login ?h host ?m msg))))
+
+(defvar erc-ctcp-reply-ECHO-hook '(erc-ctcp-reply-ECHO))
+(defun erc-ctcp-reply-ECHO (proc nick login host to msg)
+  "Handle a CTCP ECHO reply."
+  (when (string-match "^ECHO\\s-+\\(.*\\)\\s-*$" msg)
+    (let ((message (match-string 1 msg)))
+      (erc-display-message
+       nil '(notice action) 'active
+       'CTCP-ECHO ?n nick ?m message)))
+  nil)
+
+(defvar erc-ctcp-reply-CLIENTINFO-hook '(erc-ctcp-reply-CLIENTINFO))
+(defun erc-ctcp-reply-CLIENTINFO (proc nick login host to msg)
+  "Handle a CTCP CLIENTINFO reply."
+  (when (string-match "^CLIENTINFO\\s-+\\(.*\\)\\s-*$" msg)
+    (let ((message (match-string 1 msg)))
+      (erc-display-message
+       nil 'notice 'active
+       'CTCP-CLIENTINFO ?n nick ?m message)))
+  nil)
+
+(defvar erc-ctcp-reply-FINGER-hook '(erc-ctcp-reply-FINGER))
+(defun erc-ctcp-reply-FINGER (proc nick login host to msg)
+  "Handle a CTCP FINGER reply."
+  (when (string-match "^FINGER\\s-+\\(.*\\)\\s-*$" msg)
+    (let ((message (match-string 1 msg)))
+      (erc-display-message
+       nil 'notice 'active
+       'CTCP-FINGER ?n nick ?m message)))
+  nil)
+
+(defvar erc-ctcp-reply-PING-hook '(erc-ctcp-reply-PING))
+(defun erc-ctcp-reply-PING (proc nick login host to msg)
+  "Handle a CTCP PING reply."
+  (if (not (string-match "^PING\\s-+\\([0-9.]+\\)" msg))
+      nil
+    (let ((time (match-string 1 msg)))
+      (condition-case nil
+	  (let ((delta (erc-time-diff (string-to-number time)
+				      (erc-current-time))))
+	    (erc-display-message
+	     nil 'notice 'active
+	     'CTCP-PING ?n nick
+	     ?t (erc-sec-to-time delta)))
+	(range-error
+	 (erc-display-message
+	  nil 'error 'active
+	  'bad-ping-response ?n nick ?t time))))))
+
+(defvar erc-ctcp-reply-TIME-hook '(erc-ctcp-reply-TIME))
+(defun erc-ctcp-reply-TIME (proc nick login host to msg)
+  "Handle a CTCP TIME reply."
+  (when (string-match "^TIME\\s-+\\(.*\\)\\s-*$" msg)
+    (let ((message (match-string 1 msg)))
+      (erc-display-message
+       nil 'notice 'active
+       'CTCP-TIME ?n nick ?m message)))
+  nil)
+
+(defvar erc-ctcp-reply-VERSION-hook '(erc-ctcp-reply-VERSION))
+(defun erc-ctcp-reply-VERSION (proc nick login host to msg)
+  "Handle a CTCP VERSION reply."
+  (when (string-match "^VERSION\\s-+\\(.*\\)\\s-*$" msg)
+    (let ((message (match-string 1 msg)))
+      (erc-display-message
+       nil 'notice 'active
+       'CTCP-VERSION ?n nick ?m message)))
+  nil)
+
+(defun erc-process-away (proc away-p)
+  ;; FIXME: This docstring is AWFUL -- Lawrence 2004-01-08
+  "Process the user being away, or returning from an away break."
+  (let ((sessionbuf (process-buffer proc)))
+    (when sessionbuf
+      (with-current-buffer sessionbuf
+	(when erc-away-nickname
+	  (erc-log (format "erc-process-away: away-nick: %s, away-p: %s"
+			   erc-away-nickname away-p))
+	  (erc-cmd-NICK (if away-p
+			    erc-away-nickname
+			  erc-nick)))
+	(cond
+	 (away-p
+	  (erc-with-all-buffers-of-server proc nil
+					  (setq erc-away (current-time))))
+	 (t
+	  (let ((away-time erc-away))
+	    ;; away must be set to NIL BEFORE sending anything to prevent
+	    ;; an infinite recursion
+	    (erc-with-all-buffers-of-server proc nil
+					    (setq erc-away nil))
+	    (save-excursion
+	      (set-buffer (erc-active-buffer))
+	      (when erc-public-away-p
+		(erc-send-action
+		 (erc-default-target)
+		 (if away-time
+		     (format "is back (gone for %s)"
+			     (erc-sec-to-time
+			      (erc-time-diff
+			       (erc-emacs-time-to-erc-time away-time)
+			       (erc-current-time))))
+		   "is back")))))))))
+    (erc-update-mode-line)))
+
+;;;; List of channel members handling
+
+(defun erc-channel-begin-receiving-names ()
+  "Internal function.
+
+Used when a channel names list is about to be received.  Should
+be called with the current buffer set to the channel buffer.
+
+See also `erc-channel-end-receiving-names'."
+  (setq erc-channel-new-member-names (make-hash-table :test 'equal)))
+
+(defun erc-channel-end-receiving-names ()
+  "Internal function.
+
+Used to fix `erc-channel-users' after a channel names list has been
+received.  Should be called with the current buffer set to the
+channel buffer.
+
+See also `erc-channel-begin-receiving-names'."
+  (maphash (lambda (nick user)
+	     (if (null (gethash nick erc-channel-new-member-names))
+		 (erc-remove-channel-user nick)))
+	   erc-channel-users)
+  (setq erc-channel-new-member-names nil))
+
+(defun erc-channel-receive-names (names-string)
+  "This function is for internal use only.
+
+Update `erc-channel-users' according to NAMES-STRING.
+NAMES-STRING is a string listing some of the names on the
+channel."
+  (let (names name op voice)
+      ;; We need to delete "" because in XEmacs, (split-string "a ")
+      ;; returns ("a" "").
+      (setq names (delete "" (split-string names-string)))
+      (let ((erc-channel-members-changed-hook nil))
+	(dolist (item names)
+	  (cond ((string-match "^@\\(.*\\)$" item)
+		 (setq name (match-string 1 item)
+		       op 'on
+		       voice 'off))
+		((string-match "^+\\(.*\\)$" item)
+		 (setq name (match-string 1 item)
+		       op 'off
+		       voice 'on))
+		(t (setq name item
+			 op 'off
+			 voice 'off)))
+	(puthash (erc-downcase name) t
+		 erc-channel-new-member-names)
+	(erc-update-current-channel-member
+	 name name t op voice)))
+    (run-hooks 'erc-channel-members-changed-hook)))
+
+(defcustom erc-channel-members-changed-hook nil
+  "*This hook is called every time the variable `channel-members' changes.
+The buffer where the change happened is current while this hook is called."
+  :group 'erc-hooks
+  :type 'hook)
+
+(defun erc-update-user-nick (nick &optional new-nick
+				  host login full-name info)
+  "Updates the stored user information for the user with nickname
+NICK.
+
+See also: `erc-update-user'"
+  (erc-update-user (erc-get-server-user nick) new-nick
+		   host login full-name info))
+
+(defun erc-update-user (user &optional new-nick
+			     host login full-name info)
+  "Update user info for USER.  USER must be an erc-server-user
+struct.  Any of NEW-NICK, HOST, LOGIN, FULL-NAME, INFO which are
+non-nil and not equal to the existing values for USER are used to
+replace the stored values in USER.
+
+If, any only if a change is made,
+`erc-channel-members-changed-hook' is run for each channel for
+which USER is a member, and `t' is returned."
+  (let (changed)
+    (when user
+      (when (and new-nick
+		 (not (equal (erc-server-user-nickname user)
+			     new-nick)))
+	(setq changed t)
+	(erc-change-user-nickname user new-nick))
+      (when (and host
+		 (not (equal (erc-server-user-host user) host)))
+	(setq changed t)
+	(setf (erc-server-user-host user) host))
+      (when (and login
+		 (not (equal (erc-server-user-login user) login)))
+	(setq changed t)
+	(setf (erc-server-user-login user) login))
+      (when (and full-name
+		 (not (equal (erc-server-user-full-name user)
+			     full-name)))
+	(setq changed t)
+	(setf (erc-server-user-full-name user) full-name))
+      (when (and info
+		 (not (equal (erc-server-user-info user) info)))
+	(setq changed t)
+	(setf (erc-server-user-info user) info))
+      (if changed
+	  (dolist (buf (erc-server-user-buffers user))
+	    (if (buffer-live-p buf)
+		(with-current-buffer buf
+		  (run-hooks 'erc-channel-members-changed-hook))))))
+    changed))
+
+(defun erc-update-current-channel-member
+  (nick new-nick &optional add op voice host login full-name info
+	update-message-time)
+  "Updates the stored user information for the user with nickname
+NICK.  `erc-update-user' is called to handle changes to nickname,
+host, login, full-name, and info.  If `op' or `voice' are
+non-nil, they must be equal to either `on' or `off', in which
+case the operator or voice status of USER in the current channel
+is changed accordingly.  If `update-message-time' is non-nil, the
+last-message-time of the user in the current channel is set
+to (current-time).
+
+If ADD is non-nil, the user will be added with the specified
+information if it is not already present in the user or channel
+lists.
+
+If, and only if, changes are made, or the user is added,
+`erc-channel-members-updated-hook' is run, and `t' is returned.
+
+See also: `erc-update-user' and `erc-update-channel-member'."
+  (let* (changed user-changed
+	 (channel-data (erc-get-channel-user nick))
+	 (cuser (if channel-data (cdr channel-data)))
+	 (user (if channel-data (car channel-data)
+		 (erc-get-server-user nick))))
+    (if cuser
+	(progn
+	  (erc-log (format "update-member: user = %S, cuser = %S" user cuser))
+	  (when (and op
+		     (not (eq (erc-channel-user-op cuser) op)))
+	      (setq changed t)
+	    (setf (erc-channel-user-op cuser)
+		  (cond ((eq op 'on) t)
+				   ((eq op 'off) nil)
+				   (t op))))
+	  (when (and voice
+		     (not (eq (erc-channel-user-voice cuser) voice)))
+	      (setq changed t)
+	    (setf (erc-channel-user-voice cuser)
+		  (cond ((eq voice 'on) t)
+				      ((eq voice 'off) nil)
+				      (t voice))))
+	  (when update-message-time
+	    (setf (erc-channel-user-last-message-time cuser) (current-time)))
+	  (setq user-changed
+		(erc-update-user user new-nick
+				 host login full-name info)))
+      (when add
+	(if (null user)
+	    (progn
+	      (setq user (make-erc-server-user
+			  :nickname nick
+			  :host host
+			  :full-name full-name
+			  :login login
+			  :info info
+			  :buffers (list (current-buffer))))
+	      (erc-add-server-user nick user))
+	  (setf (erc-server-user-buffers user)
+		(cons (current-buffer)
+		      (erc-server-user-buffers user))))
+	(setq cuser (make-erc-channel-user
+		     :op (cond ((eq op 'on) t)
+				       ((eq op 'off) nil)
+				       (t op))
+		     :voice (cond ((eq voice 'on) t)
+				       ((eq voice 'off) nil)
+				       (t voice))
+		     :last-message-time
+		     (if update-message-time (current-time))))
+	(puthash (erc-downcase nick) (cons user cuser)
+		 erc-channel-users)
+	(setq changed t)))
+    (when (and changed (null user-changed))
+      (run-hooks 'erc-channel-members-changed-hook))
+    (or changed user-changed add)))
+
+(defun erc-update-channel-member (channel nick new-nick
+				  &optional add op voice host login
+				  full-name info update-message-time)
+  "Updates user and channel information for the user with
+nickname NICK in channel CHANNEL.
+
+See also: `erc-update-current-channel-member'"
+  (erc-with-buffer
+   (channel)
+   (erc-update-current-channel-member nick new-nick add op voice host
+				      login full-name info
+				      update-message-time)))
+
+(defun erc-remove-current-channel-member (nick)
+  "Remove NICK from current channel membership list.  Runs
+`erc-channel-members-changed-hook'."
+  (let ((channel-data (erc-get-channel-user nick)))
+    (when channel-data
+      (erc-remove-channel-user nick)
+      (run-hooks 'erc-channel-members-changed-hook))))
+
+(defun erc-remove-channel-member (channel nick)
+  "Remove NICK from CHANNEL's membership list.
+
+See also `erc-remove-current-channel-member'."
+  (erc-with-buffer
+   (channel)
+   (erc-remove-current-channel-member nick)))
+
+(defun erc-update-channel-topic (channel topic &optional modify)
+  "Find a buffer for CHANNEL and set the TOPIC for it.
+
+If optional MODIFY is 'append or 'prepend, then append or prepend the
+TOPIC string to the current topic."
+  (erc-with-buffer (channel)
+    (cond ((eq modify 'append)
+	   (setq erc-channel-topic (concat erc-channel-topic topic)))
+	  ((eq modify 'prepend)
+	   (setq erc-channel-topic (concat topic erc-channel-topic)))
+	  (t (setq erc-channel-topic topic)))
+    (erc-update-mode-line-buffer (current-buffer))))
+
+(defun erc-set-modes (tgt mode-string)
+  "Set the modes for the TGT provided as MODE-STRING."
+  (let* ((modes (erc-parse-modes mode-string))
+	 (add-modes (nth 0 modes))
+	 (remove-modes (nth 1 modes))
+	 ;; list of triples: (mode-char 'on/'off argument)
+	 (arg-modes (nth 2 modes)))
+    (cond ((erc-channel-p tgt); channel modes
+	   (let ((buf (and (boundp 'erc-server-process) erc-server-process
+			   (erc-get-buffer tgt erc-server-process))))
+	     (when buf
+	       (with-current-buffer buf
+		 (setq erc-channel-modes add-modes)
+		 (setq erc-channel-user-limit nil)
+		 (setq erc-channel-key nil)
+		 (while arg-modes
+		   (let ((mode (nth 0 (car arg-modes)))
+			 (onoff (nth 1 (car arg-modes)))
+			 (arg (nth 2 (car arg-modes))))
+		     (cond ((string-match "^[Ll]" mode)
+			    (erc-update-channel-limit tgt onoff arg))
+			   ((string-match "^[Kk]" mode)
+			    (erc-update-channel-key tgt onoff arg))
+			   (t nil)))
+		   (setq arg-modes (cdr arg-modes)))
+		 (erc-update-mode-line-buffer buf)))))
+	  ;; we do not keep our nick's modes yet
+	  ;;(t (setq erc-user-modes add-modes))
+	  )
+    ))
+
+(defun erc-sort-strings (list-of-strings)
+  "Sort LIST-OF-STRINGS in lexicographic order.
+
+Side-effect free."
+  (sort (copy-sequence list-of-strings) 'string<))
+
+(defun erc-parse-modes (mode-string)
+  "Parse MODE-STRING into a list.
+
+Returns a list of three elements:
+
+  (ADD-MODES REMOVE-MODES ARG-MODES).
+
+The add-modes and remove-modes are lists of single-character strings
+for modes without parameters to add and remove respectively.  The
+arg-modes is a list of triples of the form:
+
+  (MODE-CHAR ON/OFF ARGUMENT)."
+  (if (string-match "^\\s-*\\(\\S-+\\)\\(\\s-.*$\\|$\\)" mode-string)
+      (let ((chars (mapcar 'char-to-string (match-string 1 mode-string)))
+	    ;; arguments in channel modes
+	    (args-str (match-string 2 mode-string))
+	    (args nil)
+	    (add-modes nil)
+	    (remove-modes nil)
+	    (arg-modes nil); list of triples: (mode-char 'on/'off argument)
+	    (add-p t))
+	;; make the argument list
+	(while (string-match "^\\s-*\\(\\S-+\\)\\(\\s-+.*$\\|$\\)" args-str)
+	  (setq args (cons (match-string 1 args-str) args))
+	  (setq args-str (match-string 2 args-str)))
+	(setq args (nreverse args))
+	;; collect what modes changed, and match them with arguments
+	(while chars
+	  (cond ((string= (car chars) "+") (setq add-p t))
+		((string= (car chars) "-") (setq add-p nil))
+		((string-match "^[ovbOVB]" (car chars))
+		 (setq arg-modes (cons (list (car chars)
+					     (if add-p 'on 'off)
+					     (if args (car args) nil))
+				       arg-modes))
+		 (if args (setq args (cdr args))))
+		((string-match "^[LlKk]" (car chars))
+		 (setq arg-modes (cons (list (car chars)
+					     (if add-p 'on 'off)
+					     (if (and add-p args)
+						 (car args) nil))
+				       arg-modes))
+		 (if (and add-p args) (setq args (cdr args))))
+		(add-p (setq add-modes (cons (car chars) add-modes)))
+		(t (setq remove-modes (cons (car chars) remove-modes))))
+	  (setq chars (cdr chars)))
+	(setq add-modes (nreverse add-modes))
+	(setq remove-modes (nreverse remove-modes))
+	(setq arg-modes (nreverse arg-modes))
+	(list add-modes remove-modes arg-modes))
+    nil))
+
+(defun erc-update-modes (tgt mode-string &optional nick host login)
+  "Update the mode information for TGT, provided as MODE-STRING.
+Optional arguments: NICK, HOST and LOGIN - the attributes of the
+person who changed the modes."
+  (let* ((modes (erc-parse-modes mode-string))
+	 (add-modes (nth 0 modes))
+	 (remove-modes (nth 1 modes))
+	 ;; list of triples: (mode-char 'on/'off argument)
+	 (arg-modes (nth 2 modes)))
+    ;; now parse the modes changes and do the updates
+    (cond ((erc-channel-p tgt); channel modes
+	   (let ((buf (and (boundp 'erc-server-process) erc-server-process
+			   (erc-get-buffer tgt erc-server-process))))
+	     (when buf
+	       ;; FIXME! This used to have an original buffer
+	       ;; variable, but it never switched back to the original
+	       ;; buffer. Is this wanted behavior?
+	       (set-buffer buf)
+	       (if (not (boundp 'erc-channel-modes))
+		   (setq erc-channel-modes nil))
+	       (while remove-modes
+		 (setq erc-channel-modes (delete (car remove-modes)
+						 erc-channel-modes)
+		       remove-modes (cdr remove-modes)))
+	       (while add-modes
+		 (setq erc-channel-modes (cons (car add-modes)
+					       erc-channel-modes)
+		       add-modes (cdr add-modes)))
+	       (setq erc-channel-modes (erc-sort-strings erc-channel-modes))
+	       (while arg-modes
+		 (let ((mode (nth 0 (car arg-modes)))
+		       (onoff (nth 1 (car arg-modes)))
+		       (arg (nth 2 (car arg-modes))))
+		   (cond ((string-match "^[oO]" mode)
+			  (erc-update-channel-member tgt arg arg nil onoff))
+			 ((string-match "^[Vv]" mode)
+			  (erc-update-channel-member tgt arg arg nil nil
+						     onoff))
+			 ((string-match "^[Ll]" mode)
+			  (erc-update-channel-limit tgt onoff arg))
+			 ((string-match "^[Kk]" mode)
+			  (erc-update-channel-key tgt onoff arg))
+			 (t nil)); only ops are tracked now
+		   (setq arg-modes (cdr arg-modes))))
+	       (erc-update-mode-line buf))))
+	  ;; nick modes - ignored at this point
+	  (t nil))))
+
+(defun erc-update-channel-limit (channel onoff n)
+  ;; FIXME: what does ONOFF actually do?  -- Lawrence 2004-01-08
+  "Update CHANNEL's user limit to N."
+  (if (or (not (eq onoff 'on))
+	  (and (stringp n) (string-match "^[0-9]+$" n)))
+      (erc-with-buffer
+       (channel)
+      (cond ((eq onoff 'on) (setq erc-channel-user-limit (string-to-number n)))
+	    (t (setq erc-channel-user-limit nil))))))
+
+(defun erc-update-channel-key (channel onoff key)
+  "Update CHANNEL's key to KEY if ONOFF is 'on or to nil if it's 'off."
+  (erc-with-buffer
+   (channel)
+   (cond ((eq onoff 'on) (setq erc-channel-key key))
+	 (t (setq erc-channel-key nil)))))
+
+(defun erc-handle-user-status-change (type nlh &optional l)
+  "Handle changes in any user's status.
+
+So far, only nick change is handled.
+
+Generally, the TYPE argument is a symbol describing the change type, NLH is
+a list containing the original nickname, login name and hostname for the user,
+and L is a list containing additional TYPE-specific arguments.
+
+So far the following TYPE/L pairs are supported:
+
+       Event			TYPE		       L
+
+    nickname change	       'nick		    (NEW-NICK)"
+  (erc-log (format "user-change: type: %S  nlh: %S  l: %S" type nlh l))
+  (cond
+   ;; nickname change
+   ((equal type 'nick)
+    t)
+   (t
+    nil)))
+
+(defun erc-highlight-notice (s)
+  "Highlight notice message S and return it.
+See also variable `erc-notice-highlight-type'"
+  (cond
+   ((eq erc-notice-highlight-type 'prefix)
+    (erc-put-text-property 0 (length erc-notice-prefix)
+			   'face 'erc-notice-face s)
+    s)
+   ((eq erc-notice-highlight-type 'all)
+    (erc-put-text-property 0 (length s) 'face 'erc-notice-face s)
+    s)
+   (t s)))
+
+(defun erc-make-notice (message)
+  "Notify the user of MESSAGE."
+  (when erc-minibuffer-notice
+    (message "%s" message))
+  (erc-highlight-notice (concat erc-notice-prefix message)))
+
+(defun erc-highlight-error (s)
+  "Highlight error message S and return it."
+  (erc-put-text-property 0 (length s) 'face 'erc-error-face s)
+  s)
+
+(defun erc-put-text-property (start end property value &optional object)
+  "Set text-property for an object (usually a string).
+START and END define the characters covered.
+PROPERTY is the text-property set, usually the symbol `face'.
+VALUE is the value for the text-property, usually a face symbol such as
+the face `bold' or `erc-pal-face'.
+OBJECT is a string which will be modified and returned.
+OBJECT is modified without being copied first.
+
+You can redefine or `defadvice' this function in order to add
+EmacsSpeak support."
+  (put-text-property start end property value object))
+
+(defun erc-list (thing)
+  "Return THING if THING is a list, or a list with THING as its element."
+  (if (listp thing)
+      thing
+    (list thing)))
+
+(defun erc-parse-user (string)
+  "Parse STRING as a user specification (nick!login@host).
+
+Return a list of the three separate tokens."
+  (cond
+   ((string-match "^\\([^!]*\\)!\\([^@]*\\)@\\(.*\\)$" string)
+    (list (match-string 1 string)
+	  (match-string 2 string)
+	  (match-string 3 string)))
+   ;; Some bogus bouncers send Nick!(null), try to live with that.
+   ((string-match "^\\([^!]*\\)!\\(.*\\)$" string)
+    (list (match-string 1 string)
+	  ""
+	  (match-string 2 string)))
+   (t
+    (list string "" ""))))
+
+(defun erc-extract-nick (string)
+  "Return the nick corresponding to a user specification STRING.
+
+See also `erc-parse-user'."
+  (car (erc-parse-user string)))
+
+(defun erc-put-text-properties (start end properties
+				&optional object value-list)
+  "Set text-properties for OBJECT.
+
+START and END describe positions in OBJECT.
+If VALUE-LIST is nil, set each property in PROPERTIES to t, else set
+each property to the corresponding value in VALUE-LIST."
+  (unless value-list
+    (setq value-list (mapcar (lambda (x)
+			       t)
+			     properties)))
+  (mapcar* (lambda (prop value)
+	     (erc-put-text-property start end prop value object))
+	   properties value-list))
+
+;;; Input area handling:
+
+(defun erc-beg-of-input-line ()
+  "Return the value of `point' at the beginning of the input line.
+
+Specifically, return the position of `erc-insert-marker'."
+  (or (and (boundp 'erc-insert-marker)
+	   (markerp erc-insert-marker))
+      (error "erc-insert-marker has no value, please report a bug"))
+  (marker-position erc-insert-marker))
+
+(defun erc-end-of-input-line ()
+  "Return the value of `point' at the end of the input line."
+  (point-max))
+
+(defun erc-send-current-line ()
+  "Parse current line and send it to IRC."
+  (interactive)
+  (save-restriction
+    (widen)
+    (cond
+     ((< (point) (erc-beg-of-input-line))
+      (message "Point is not in the input area")
+      (beep))
+     ((not (erc-server-buffer-live-p))
+      (message "ERC: No process running")
+      (beep))
+     (t
+      (erc-set-active-buffer (current-buffer))
+      (let ((inhibit-read-only t)
+	    (str (erc-user-input))
+	    (old-buf (current-buffer)))
+
+	;; Kill the input and the prompt
+	(delete-region (erc-beg-of-input-line)
+		       (erc-end-of-input-line))
+
+	(unwind-protect
+	    (erc-send-input str)
+	  ;; Fix the buffer if the command didn't kill it
+	  (when (buffer-live-p old-buf)
+	    (with-current-buffer old-buf
+	      (save-restriction
+		(widen)
+		(goto-char (point-max))
+		(set-marker (process-mark erc-server-process) (point))
+		(set-marker erc-insert-marker (point))
+		(let ((buffer-modified (buffer-modified-p)))
+		  (erc-display-prompt)
+		  (set-buffer-modified-p buffer-modified))))))
+
+	;; Only when last hook has been run...
+	(run-hook-with-args 'erc-send-completed-hook str))))))
+
+(defun erc-user-input ()
+  "Return the input of the user in the current buffer."
+  (buffer-substring
+   erc-input-marker
+   (erc-end-of-input-line)))
+
+(defun erc-send-input (input)
+  "Treat INPUT as typed in by the user. It is assumed that the input
+and the prompt is already deleted.
+This returns non-nil only iff we actually send anything."
+  ;; Handle different kinds of inputs
+  (cond
+   ;; Ignore empty input
+   ((if erc-send-whitespace-lines
+	(string= input "")
+      (string-match "\\`[ \t\r\f\n]*\\'" input))
+    (when erc-warn-about-blank-lines
+      (message "Blank line - ignoring...")
+      (beep))
+    nil)
+   (t
+    (let ((str input)
+	  (erc-insert-this t))
+      (setq erc-send-this t)
+      (run-hook-with-args 'erc-send-pre-hook input)
+      (when erc-send-this
+	(if (or (string-match "\n" str)
+		(not (char-equal (aref str 0) ?/)))
+	    (mapc
+	     (lambda (line)
+	       (mapc
+		(lambda (line)
+		  ;; Insert what has to be inserted for this.
+		  (erc-display-msg line)
+		  (erc-process-input-line (concat line "\n")
+					  (null erc-flood-protect) t))
+		(erc-split-line line)))
+	     (split-string str "\n"))
+	  ;; Insert the prompt along with the command.
+	  (erc-display-command str)
+	  (erc-process-input-line (concat str "\n") t nil))
+	t)))))
+
+(defun erc-display-command (line)
+  (when erc-insert-this
+    (let ((insert-position (point)))
+      (unless erc-hide-prompt
+	(erc-display-prompt nil nil (erc-command-indicator)
+			    (and (erc-command-indicator)
+				 'erc-command-indicator-face)))
+      (let ((beg (point)))
+	(insert line)
+	(erc-put-text-property beg (point)
+			       'face 'erc-command-indicator-face)
+	(insert "\n"))
+      (set-marker (process-mark erc-server-process) (point))
+      (set-marker erc-insert-marker (point))
+      (save-excursion
+	(save-restriction
+	  (narrow-to-region insert-position (point))
+	  (run-hooks 'erc-send-modify-hook)
+	  (run-hooks 'erc-send-post-hook))))))
+
+(defun erc-display-msg (line)
+  "Display LINE as a message of the user to the current target at the
+current position."
+  (when erc-insert-this
+    (let ((insert-position (point)))
+      (insert (erc-format-my-nick))
+      (let ((beg (point)))
+	(insert line)
+	(erc-put-text-property beg (point)
+			       'face 'erc-input-face))
+      (insert "\n")
+      (set-marker (process-mark erc-server-process) (point))
+      (set-marker erc-insert-marker (point))
+      (save-excursion
+	(save-restriction
+	  (narrow-to-region insert-position (point))
+	  (run-hooks 'erc-send-modify-hook)
+	  (run-hooks 'erc-send-post-hook))))))
+
+(defun erc-command-symbol (command)
+  "Return the erc command symbol for COMMAND if it exists and is bound."
+  (let ((cmd (intern-soft (format "erc-cmd-%s" (upcase command)))))
+    (when (fboundp cmd) cmd)))
+
+(defun erc-extract-command-from-line (line)
+  "Extract command and args from the input LINE.
+If no command was given, return nil.  If command matches, return a
+list of the form: (command args) where both elements are strings."
+  (when (string-match "^/\\([A-Za-z]+\\)\\(\\s-+.*\\|\\s-*\\)$" line)
+    (let* ((cmd (erc-command-symbol (match-string 1 line)))
+	   ;; note: return is nil, we apply this simply for side effects
+	   (canon-defun (while (and cmd (symbolp (symbol-function cmd)))
+			  (setq cmd (symbol-function cmd))))
+	   (cmd-fun (or cmd #'erc-cmd-default))
+	   (arg (if cmd
+		    (if (get cmd-fun 'do-not-parse-args)
+			(format "%s" (match-string 2 line))
+		      (delete "" (split-string (erc-trim-string
+						(match-string 2 line)) " ")))
+		  line)))
+      (list cmd-fun arg))))
+
+(defun erc-split-multiline-safe (string)
+  "Split STRING, containing multiple lines and return them in a list.
+Do it only for STRING as the complete input, do not carry unfinished
+strings over to the next call."
+  (let ((l ())
+	(i0 0)
+	(doit t))
+    (while doit
+      (let ((i (string-match "\r?\n" string i0))
+	    (s (substring string i0)))
+	(cond (i (setq l (cons (substring string i0 i) l))
+		 (setq i0 (match-end 0)))
+	      ((> (length s) 0)
+		 (setq l (cons s l))(setq doit nil))
+	      (t (setq doit nil)))))
+    (nreverse l)))
+
+;; nick handling
+
+(defun erc-set-current-nick (nick)
+  "Set the current nickname to NICK."
+  (with-current-buffer (or (erc-server-buffer)
+			   (current-buffer))
+    (setq erc-server-current-nick nick)))
+
+(defun erc-current-nick ()
+  "Return the current nickname."
+  (with-current-buffer (if (buffer-live-p (erc-server-buffer))
+			   (erc-server-buffer)
+			 (current-buffer))
+    erc-server-current-nick))
+
+(defun erc-current-nick-p (nick)
+  "Return non-nil if NICK is the current nickname."
+  (erc-nick-equal-p nick (erc-current-nick)))
+
+(defun erc-nick-equal-p (nick1 nick2)
+  "Return non-nil if NICK1 and NICK2 are the same.
+
+This matches strings according to the IRC protocol's case convention.
+
+See also `erc-downcase'."
+  (string= (erc-downcase nick1)
+	   (erc-downcase nick2)))
+
+;; default target handling
+
+(defun erc-default-target ()
+  "Return the current default target (as a character string) or nil if none."
+  (let ((tgt (car erc-default-recipients)))
+    (cond
+     ((not tgt) nil)
+     ((listp tgt) (cdr tgt))
+     (t tgt))))
+
+(defun erc-add-default-channel (channel)
+  "Add CHANNEL to the default channel list."
+
+  (let ((d1 (car erc-default-recipients))
+	(d2 (cdr erc-default-recipients))
+	(chl (downcase channel)))
+      (setq erc-default-recipients
+	    (cons chl erc-default-recipients))))
+
+(defun erc-delete-default-channel (channel &optional buffer)
+  "Delete CHANNEL from the default channel list."
+  (let ((ob (current-buffer)))
+    (with-current-buffer (if (and buffer
+				  (bufferp buffer))
+			     buffer
+			   (current-buffer))
+      (setq erc-default-recipients (delete (downcase channel)
+					   erc-default-recipients)))))
+
+(defun erc-add-query (nickname)
+  "Add QUERY'd NICKNAME to the default channel list.
+
+The previous default target of QUERY type gets removed"
+  (let ((d1 (car erc-default-recipients))
+	(d2 (cdr erc-default-recipients))
+	(qt (cons 'QUERY (downcase nickname))))
+    (if (and (listp d1)
+	     (eq (car d1) 'QUERY))
+	(setq erc-default-recipients (cons qt d2))
+      (setq erc-default-recipients (cons qt erc-default-recipients)))))
+
+(defun erc-delete-query ()
+  "Delete the topmost target if it is a QUERY."
+
+  (let ((d1 (car erc-default-recipients))
+	(d2 (cdr erc-default-recipients)))
+    (if (and (listp d1)
+	     (eq (car d1) 'QUERY))
+	(setq erc-default-recipients d2)
+      (error "Current target is not a QUERY"))))
+
+(defun erc-ignored-user-p (spec)
+  "Return non-nil if SPEC matches something in `erc-ignore-list'.
+
+Takes a full SPEC of a user in the form \"nick!login@host\", and
+matches against all the regexp's in `erc-ignore-list'.  If any
+match, returns that regexp."
+  (dolist (ignored (with-current-buffer (erc-server-buffer) erc-ignore-list))
+    (if (string-match ignored spec)
+	;; We have `require'd cl, so we can return from the block named nil
+	(return ignored))))
+
+(defun erc-ignored-reply-p (msg tgt proc)
+  ;; FIXME: this docstring needs fixing -- Lawrence 2004-01-08
+  "Return non-nil if MSG matches something in `erc-ignore-reply-list'.
+
+Takes a message MSG to a channel and returns non-nil if the addressed
+user matches any regexp in `erc-ignore-reply-list'."
+  (let ((target-nick (erc-message-target msg)))
+    (if (not target-nick)
+	nil
+      (erc-with-buffer (tgt proc)
+	(let ((user (erc-get-server-user target-nick)))
+	  (when user
+	    (erc-list-match erc-ignore-reply-list
+			    (erc-user-spec user))))))))
+
+(defun erc-message-target (msg)
+  "Return the addressed target in MSG.
+
+The addressed target is the string before the first colon in MSG."
+  (if (string-match "^\\([^: ]*\\):" msg)
+      (match-string 1 msg)
+    nil))
+
+(defun erc-user-spec (user)
+  "Create a nick!user@host spec from a user struct."
+  (let ((nick (erc-server-user-nickname user))
+	(host (erc-server-user-host user))
+	(login (erc-server-user-login user)))
+  (concat (if nick
+	      nick
+	    "")
+	  "!"
+	  (if login
+	      login
+	    "")
+	  "@"
+	  (if host
+	      host
+	    ""))))
+
+(defun erc-list-match (lst str)
+  "Return non-nil if any regexp in LST matches STR."
+  (memq nil (mapcar (lambda (regexp)
+		      (not (string-match regexp str)))
+		    lst)))
+
+;; other "toggles"
+
+(defun erc-toggle-ctcp-autoresponse (&optional arg)
+  "Toggle automatic CTCP replies (like VERSION and PING).
+
+If ARG is positive, turns CTCP replies on.
+
+If ARG is non-nil and not positive, turns CTCP replies off."
+  (interactive "P")
+  (cond ((and (numberp arg) (> arg 0))
+	 (setq erc-disable-ctcp-replies t))
+	(arg (setq erc-disable-ctcp-replies nil))
+	(t (setq erc-disable-ctcp-replies (not erc-disable-ctcp-replies))))
+  (message "ERC CTCP replies are %s" (if erc-disable-ctcp-replies "OFF" "ON")))
+
+(defun erc-toggle-flood-control (&optional arg)
+  "Toggle use of flood control on sent messages.
+
+If ARG is non-nil, use flood control.
+If ARG is nil, do not use flood control.
+
+See `erc-server-flood-margin' for an explanation of the available
+flood control parameters."
+  (interactive "P")
+  (setq erc-flood-protect arg)
+  (message "ERC flood control is %s"
+	   (cond (erc-flood-protect "ON")
+		 (t "OFF"))))
+
+;; Some useful channel and nick commands for fast key bindings
+
+(defun erc-invite-only-mode (&optional arg)
+  "Turn on the invite only mode (+i) for the current channel.
+
+If ARG is non-nil, turn this mode off (-i).
+
+This command is sent even if excess flood is detected."
+  (interactive "P")
+  (erc-set-active-buffer (current-buffer))
+  (let ((tgt (erc-default-target))
+	(erc-force-send t))
+    (cond ((or (not tgt) (not (erc-channel-p tgt)))
+	   (erc-display-message nil 'error (current-buffer) 'no-target))
+	  (arg (erc-load-irc-script-lines (list (concat "/mode " tgt " -i"))
+					  t))
+	  (t (erc-load-irc-script-lines (list (concat "/mode " tgt " +i"))
+					t)))))
+
+(defun erc-get-channel-mode-from-keypress (key)
+  "Read a key sequence and call the corresponding channel mode function.
+After doing C-c C-o type in a channel mode letter.
+
+C-g means quit.
+RET let's you type more than one mode at a time.
+If \"l\" is pressed, `erc-set-channel-limit' gets called.
+If \"k\" is pressed, `erc-set-channel-key' gets called.
+Anything else will be sent to `erc-toggle-channel-mode'."
+  (interactive "kChannel mode (RET to set more than one): ")
+  (when (featurep 'xemacs)
+    (setq key (char-to-string (event-to-character (aref key 0)))))
+  (cond ((equal key "\C-g")
+	 (keyboard-quit))
+	((equal key "\C-m")
+	 (erc-insert-mode-command))
+	((equal key "l")
+	 (call-interactively 'erc-set-channel-limit))
+	((equal key "k")
+	 (call-interactively 'erc-set-channel-key))
+	(t (erc-toggle-channel-mode key))))
+
+(defun erc-toggle-channel-mode (mode &optional channel)
+  "Toggle channel MODE.
+
+If CHANNEL is non-nil, toggle MODE for that channel, otherwise use
+`erc-default-target'."
+  (interactive "P")
+  (erc-set-active-buffer (current-buffer))
+  (let ((tgt (or channel (erc-default-target)))
+	(erc-force-send t))
+    (cond ((or (null tgt) (null (erc-channel-p tgt)))
+	   (erc-display-message nil 'error 'active 'no-target))
+	  ((member mode erc-channel-modes)
+	   (erc-log (format "%s: Toggle mode %s OFF" tgt mode))
+	   (message "Toggle channel mode %s OFF" mode)
+	   (erc-server-send (format "MODE %s -%s" tgt mode)))
+	  (t (erc-log (format "%s: Toggle channel mode %s ON" tgt mode))
+	     (message "Toggle channel mode %s ON" mode)
+	     (erc-server-send (format "MODE %s +%s" tgt mode))))))
+
+(defun erc-insert-mode-command ()
+  "Insert the line \"/mode <current target> \" at `point'."
+  (interactive)
+  (let ((tgt (erc-default-target)))
+    (if tgt (insert (concat "/mode " tgt " "))
+      (erc-display-message nil 'error (current-buffer) 'no-target))))
+
+(defun erc-channel-names ()
+  "Run \"/names #channel\" in the current channel."
+  (interactive)
+  (erc-set-active-buffer (current-buffer))
+  (let ((tgt (erc-default-target)))
+    (if tgt (erc-load-irc-script-lines (list (concat "/names " tgt)))
+      (erc-display-message nil 'error (current-buffer) 'no-target))))
+
+(defun erc-remove-text-properties-region (start end &optional object)
+  "Clears the region (START,END) in OBJECT from all colors, etc."
+  (interactive "r")
+  (save-excursion
+    (let ((inhibit-read-only t))
+      (set-text-properties start end nil object))))
+
+;; script execution and startup
+
+(defun erc-find-file (file &optional path)
+  "Search for a FILE in the filesystem.
+First the `default-directory' is searched for FILE, then any directories
+specified in the list PATH.
+
+If FILE is found, return the path to it."
+  (let ((filepath file))
+    (if (file-readable-p filepath) filepath
+      (progn
+	(while (and path
+		    (progn (setq filepath (expand-file-name file (car path)))
+			   (not (file-readable-p filepath))))
+	  (setq path (cdr path)))
+	(if path filepath nil)))))
+
+(defun erc-select-startup-file ()
+  "Select an ERC startup file.
+See also `erc-startup-file-list'."
+  (let ((l erc-startup-file-list)
+	(f nil))
+    (while (and (not f) l)
+      (if (file-readable-p (car l))
+	  (setq f (car l)))
+      (setq l (cdr l)))
+    f))
+
+(defun erc-find-script-file (file)
+  "Search for FILE in `default-directory', and any in `erc-script-path'."
+  (erc-find-file file erc-script-path))
+
+(defun erc-load-script (file)
+  "Load a script from FILE.
+
+FILE must be the full name, it is not searched in the
+`erc-script-path'.  If the filename ends with `.el', then load it
+as a emacs-lisp program.  Otherwise, treat it as a regular IRC
+script"
+  (erc-log (concat "erc-load-script: " file))
+  (cond
+   ((string-match "\\.el$" file)
+    (load file))
+   (t
+    (erc-load-irc-script file))))
+
+(defun erc-process-script-line (line &optional args)
+  "Process an IRC script LINE.
+
+Does script-specific substitutions (script arguments, current nick,
+server, etc.)  in LINE and returns it.
+
+Substitutions are: %C and %c = current target (channel or nick),
+%S %s = current server, %N %n = my current nick, and %x is x verbatim,
+where x is any other character;
+$* = the entire argument string, $1 = the first argument, $2 = the second,
+end so on."
+  (if (not args) (setq args ""))
+  (let* ((arg-esc-regexp "\\(\\$\\(\\*\\|[1-9][0-9]*\\)\\)\\([^0-9]\\|$\\)")
+	 (percent-regexp "\\(%.\\)")
+	 (esc-regexp (concat arg-esc-regexp "\\|" percent-regexp))
+	 (tgt (erc-default-target))
+	 (server (and (boundp 'erc-session-server) erc-session-server))
+	 (nick (erc-current-nick))
+	 (res "")
+	 (tmp nil)
+	 (arg-list nil)
+	 (arg-num 0))
+    (if (not tgt) (setq tgt ""))
+    (if (not server) (setq server ""))
+    (if (not nick) (setq nick ""))
+    ;; First, compute the argument list
+    (setq tmp args)
+    (while (string-match "^\\s-*\\(\\S-+\\)\\(\\s-+.*$\\|$\\)" tmp)
+      (setq arg-list (cons (match-string 1 tmp) arg-list))
+      (setq tmp (match-string 2 tmp)))
+    (setq arg-list (nreverse arg-list))
+    (setq arg-num (length arg-list))
+    ;; now do the substitution
+    (setq tmp (string-match esc-regexp line))
+    (while tmp
+      ;;(message "beginning of while: tmp=%S" tmp)
+      (let* ((hd (substring line 0 tmp))
+	     (esc "")
+	     (subst "")
+	     (tail (substring line tmp)))
+	(cond ((string-match (concat "^" arg-esc-regexp) tail)
+	       (setq esc (match-string 1 tail))
+	       (setq tail (substring tail (match-end 1))))
+	      ((string-match (concat "^" percent-regexp) tail)
+	       (setq esc (match-string 1 tail))
+	       (setq tail (substring tail (match-end 1)))))
+	;;(message "hd=%S, esc=%S, tail=%S, arg-num=%S" hd esc tail arg-num)
+	(setq res (concat res hd))
+	(setq subst
+	      (cond ((string= esc "") "")
+		    ((string-match "^\\$\\*$" esc) args)
+		    ((string-match "^\\$\\([0-9]+\\)$" esc)
+		     (let ((n (string-to-number (match-string 1 esc))))
+		       (message "n = %S, integerp(n)=%S" n (integerp n))
+		       (if (<= n arg-num) (nth (1- n) arg-list) "")))
+		    ((string-match "^%[Cc]$" esc) tgt)
+		    ((string-match "^%[Ss]$" esc) server)
+		    ((string-match "^%[Nn]$" esc) nick)
+		    ((string-match "^%\\(.\\)$" esc) (match-string 1 esc))
+		    (t (erc-log (format "BUG in erc-process-script-line: bad escape sequence: %S\n" esc))
+		       (message "BUG IN ERC: esc=%S" esc)
+		       "")))
+	(setq line tail)
+	(setq tmp (string-match esc-regexp line))
+	(setq res (concat res subst))
+	;;(message "end of while: line=%S, res=%S, tmp=%S" line res tmp)
+	))
+    (setq res (concat res line))
+    res))
+
+(defun erc-load-irc-script (file &optional force)
+  "Load an IRC script from FILE."
+  (erc-log (concat "erc-load-script: " file))
+  (let ((str (with-temp-buffer
+	       (insert-file-contents file)
+	       (buffer-string))))
+    (erc-load-irc-script-lines (erc-split-multiline-safe str) force)))
+
+(defun erc-load-irc-script-lines (lines &optional force noexpand)
+  "Load IRC script LINES (a list of strings).
+
+If optional NOEXPAND is non-nil, do not expand script-specific
+sequences, process the lines verbatim.  Use this for multiline
+user input."
+  (let* ((cb (current-buffer))
+	 (pnt (point))
+	 (s "")
+	 (sp (or (erc-command-indicator) (erc-prompt)))
+	 (args (and (boundp 'erc-script-args) erc-script-args)))
+    (if (and args (string-match "^ " args))
+	(setq args (substring args 1)))
+    ;; prepare the prompt string for echo
+    (erc-put-text-property 0 (length sp)
+			   'face 'erc-command-indicator-face sp)
+    (while lines
+      (setq s (car lines))
+      (erc-log (concat "erc-load-script: CMD: " s))
+      (unless (string-match "^\\s-*$" s)
+	(let ((line (if noexpand s (erc-process-script-line s args))))
+	  (if (and (erc-process-input-line line force)
+		   erc-script-echo)
+	      (progn
+		(erc-put-text-property 0 (length line)
+				       'face 'erc-input-face line)
+		(erc-display-line (concat sp line) cb)))))
+      (setq lines (cdr lines)))))
+
+;; authentication
+
+(defun erc-login ()
+  "Perform user authentication at the IRC server."
+  (erc-log (format "login: nick: %s, user: %s %s %s :%s"
+		   (erc-current-nick)
+		   (user-login-name)
+		   (system-name)
+		   erc-session-server
+		   erc-session-user-full-name))
+  (if erc-session-password
+      (erc-server-send (format "PASS %s" erc-session-password))
+    (message "Logging in without password"))
+  (erc-server-send (format "NICK %s" (erc-current-nick)))
+  (erc-server-send
+   (format "USER %s %s %s :%s"
+	   ;; hacked - S.B.
+	   (if erc-anonymous-login erc-email-userid (user-login-name))
+	   "0" "*"
+	   erc-session-user-full-name))
+  (erc-update-mode-line))
+
+;; connection properties' heuristics
+
+(defun erc-determine-parameters (&optional server port nick name)
+  "Determine the connection and authentication parameters.
+Sets the buffer local variables:
+
+- erc-session-server
+- erc-session-port
+- erc-session-full-name
+- erc-server-current-nick"
+  (setq erc-session-server (erc-compute-server server)
+	erc-session-port (or port erc-default-port)
+	erc-session-user-full-name (erc-compute-full-name name))
+  (erc-set-current-nick (erc-compute-nick nick)))
+
+(defun erc-compute-server (&optional server)
+  "Return an IRC server name.
+
+Tries a number of increasingly more default methods until a non-nil value is
+found:
+
+- SERVER
+- `erc-server'
+- The value of the IRCSERVER environment variable
+- `erc-default-server'."
+  (or server
+      erc-server
+      (getenv "IRCSERVER")
+      erc-default-server))
+
+(defun erc-compute-nick (&optional nick)
+  "Return user's NICK.
+
+Tries a number of increasingly more default methods until a non-nil value is
+found:
+
+- NICK
+- `erc-nick'
+- The value of the IRCNICK environment variable
+- via the function `user-login-name'."
+  (or nick
+      (if (consp erc-nick) (car erc-nick) erc-nick)
+      (getenv "IRCNICK")
+      (user-login-name)))
+
+
+(defun erc-compute-full-name (&optional full-name)
+  "Return user's FULL-NAME.
+
+Tries a number of increasingly more default methods until a non-nil value is
+found:
+
+- FULL-NAME
+- `erc-user-full-name'
+- The value of the IRCNAME environment variable
+- via the function `user-full-name'."
+  (or full-name
+      erc-user-full-name
+      (getenv "IRCNAME")
+      (if erc-anonymous-login "unknown" nil)
+      (user-full-name)))
+
+(defun erc-compute-port (&optional port)
+  "Return a port for an IRC server.
+
+Tries a number of increasingly more default methods until a non-nil
+value is found:
+
+- PORT
+- \"ircd\"."
+  (or port erc-port "ircd"))
+
+;; time routines
+
+(defun erc-string-to-emacs-time (string)
+  "Convert the long number represented by STRING into an Emacs format.
+Returns a list of the form (HIGH LOW), compatible with Emacs time format."
+  (let* ((n (string-to-number (concat string ".0"))))
+    (list (truncate (/ n 65536))
+	  (truncate (mod n 65536)))))
+
+(defun erc-emacs-time-to-erc-time (time)
+  "Convert Emacs TIME to a number of seconds since the epoch."
+  (when time
+    (+ (* (nth 0 time) 65536.0) (nth 1 time))))
+;  (round (+ (* (nth 0 tm) 65536.0) (nth 1 tm))))
+
+(defun erc-current-time ()
+  "Return the `current-time' as a number of seconds since the epoch.
+
+See also `erc-emacs-time-to-erc-time'."
+  (erc-emacs-time-to-erc-time (current-time)))
+
+(defun erc-time-diff (t1 t2)
+  "Return the time difference in seconds between T1 and T2."
+  (abs (- t2 t1)))
+
+(defun erc-time-gt (t1 t2)
+  "Check whether T1 > T2."
+  (> t1 t2))
+
+(defun erc-sec-to-time (ns)
+  "Convert NS to a time string HH:MM.SS."
+  (setq ns (truncate ns))
+  (format "%02d:%02d.%02d"
+	  (/ ns 3600)
+	  (/ (% ns 3600) 60)
+	  (% ns 60)))
+
+(defun erc-seconds-to-string (seconds)
+  "Convert a number of SECONDS into an English phrase."
+  (let (days hours minutes format-args output)
+    (setq days		(/ seconds 86400)
+	  seconds	(% seconds 86400)
+	  hours		(/ seconds 3600)
+	  seconds	(% seconds 3600)
+	  minutes	(/ seconds 60)
+	  seconds	(% seconds 60)
+	  format-args	(if (> days 0)
+			    `("%d days, %d hours, %d minutes, %d seconds"
+			      ,days ,hours ,minutes ,seconds)
+			  (if (> hours 0)
+			      `("%d hours, %d minutes, %d seconds"
+				,hours ,minutes ,seconds)
+			    (if (> minutes 0)
+				`("%d minutes, %d seconds" ,minutes ,seconds)
+			      `("%d seconds" ,seconds))))
+	  output	(apply 'format format-args))
+    ;; Change all "1 units" to "1 unit".
+    (while (string-match "\\([^0-9]\\|^\\)1 \\S-+\\(s\\)" output)
+      (setq output (erc-replace-match-subexpression-in-string
+		    "" output (match-string 2 output) 2 (match-beginning 2))))
+    output))
+
+
+;; info
+
+(defconst erc-clientinfo-alist
+  '(("ACTION" . "is used to inform about one's current activity")
+    ("CLIENTINFO" . "gives help on CTCP commands supported by client")
+    ("ECHO" . "echoes its arguments back")
+    ("FINGER" . "shows user's name, location, and idle time")
+    ("PING" . "measures delay between peers")
+    ("TIME" . "shows client-side time")
+    ("USERINFO" . "shows information provided by a user")
+    ("VERSION" . "shows client type and version"))
+  "Alist of CTCP CLIENTINFO for ERC commands.")
+
+(defun erc-client-info (s)
+  "Return CTCP CLIENTINFO on command S.
+If S is NIL or an empty string then return general CLIENTINFO"
+  (if (or (not s) (string= s ""))
+      (concat
+       (apply #'concat
+	      (mapcar (lambda (e)
+			(concat (car e) " "))
+		      erc-clientinfo-alist))
+       ": use CLIENTINFO <COMMAND> to get more specific information")
+    (let ((h (assoc (upcase s) erc-clientinfo-alist)))
+      (if h
+	  (concat s " " (cdr h))
+	(concat s ": unknown command")))))
+
+;; Hook functions
+
+(defun erc-directory-writable-p (dir)
+  "Determine whether DIR is a writable directory.
+If it doesn't exist, create it."
+  (unless (file-attributes dir) (make-directory dir))
+  (or (file-accessible-directory-p dir) (error "Cannot access %s" dir)))
+
+(defun erc-kill-query-buffers (process)
+  "Kill all buffers of PROCESS."
+  ;; here, we only want to match the channel buffers, to avoid
+  ;; "selecting killed buffers" b0rkage.
+  (erc-with-all-buffers-of-server process
+				  (lambda ()
+				    (not (erc-server-buffer-p)))
+				  (kill-buffer (current-buffer))))
+
+(defun erc-nick-at-point ()
+  "Give information about the nickname at `point'.
+
+If called interactively, give a human readable message in the
+minibuffer.  If called programatically, return the corresponding
+entry of `channel-members'."
+  (interactive)
+  (require 'thingatpt)
+  (let* ((word (word-at-point))
+	 (channel-data (erc-get-channel-user word))
+	 (cuser (cdr channel-data))
+	 (user (if channel-data
+		   (car channel-data)
+		 (erc-get-server-user word)))
+	 host login full-name info nick op voice)
+    (when user
+      (setq nick (erc-server-user-nickname user)
+	    host (erc-server-user-host user)
+	    login (erc-server-user-login user)
+	    full-name (erc-server-user-full-name user)
+	    info (erc-server-user-info user))
+      (if cuser
+	  (setq op (erc-channel-user-op cuser)
+		voice (erc-channel-user-voice cuser)))
+      (if (interactive-p)
+	  (message "%s is %s@%s%s%s"
+		   nick login host
+		   (if full-name (format " (%s)" full-name) "")
+		   (if (or op voice)
+			       (format " and is +%s%s on %s"
+			       (if op "o" "")
+			       (if voice "v" "")
+				       (erc-default-target))
+			     ""))
+	user))))
+
+(defun erc-away-p ()
+  "Return t if the current ERC process is set away."
+  (save-excursion
+    (and (erc-server-buffer-live-p)
+	 (set-buffer (process-buffer erc-server-process))
+	 erc-away)))
+
+;; Mode line handling
+
+(defcustom erc-mode-line-format "%s %a"
+  "A string to be formatted and shown in the mode-line in `erc-mode'.
+
+The string is formatted using `format-spec' and the result is set as the value
+of `mode-line-buffer-identification'.
+
+The following characters are replaced:
+%a: String indicating away status or \"\" if you are not away
+%m: The modes of the channel
+%n: The current nick name
+%o: The topic of the channel
+%p: The session port
+%t: The name of the target (channel, nickname, or servername:port)
+%s: In the server-buffer, this gets filled with the value of
+    `erc-server-announced-name', in a channel, the value of
+    (erc-default-target) also get concatenated."
+  :group 'erc-mode-line-and-header
+  :type 'string)
+
+(defcustom erc-header-line-format "[IRC] %n on %t %m %o"
+  "A string to be formatted and shown in the header-line in `erc-mode'.
+Only used in Emacs 21.
+
+See `erc-mode-line-format' for which characters are can be used."
+  :group 'erc-mode-line-and-header
+  :type 'string)
+
+(defcustom erc-header-line-uses-help-echo-p t
+  "Show the contents of the header line in the echo area or as a tooltip
+when you move point into the header line."
+  :group 'erc-mode-line-and-header
+  :type 'boolean)
+
+(defcustom erc-show-channel-key-p t
+  "Show the the channel key in the header line."
+  :group 'erc-paranoia
+  :type 'boolean)
+
+(defcustom erc-common-server-suffixes
+  '(("openprojects.net$" . "OPN")
+    ("freenode.net$" . "OPN"))
+  "Alist of common server name suffixes.
+This variable is used in mode-line display to save screen
+real estate.  Set it to nil if you want to avoid changing
+displayed hostnames."
+  :group 'erc-mode-line-and-header
+  :type 'alist)
+
+(defcustom erc-mode-line-away-status-format
+  "(AWAY since %a %b %d %H:%M) "
+  "When you're away on a server, this is shown in the mode line.
+This should be a string with substitution variables recognized by
+format-time-message."
+  :group 'erc-mode-line-and-header
+  :type 'string)
+
+(defun erc-shorten-server-name (server-name)
+  "Shorten SERVER-NAME according to `erc-common-server-suffixes'."
+  (if (stringp server-name)
+      (with-temp-buffer
+	(insert server-name)
+	(let ((alist erc-common-server-suffixes))
+	  (while alist
+	    (goto-char (point-min))
+	(if (re-search-forward (caar alist) nil t)
+	    (replace-match (cdar alist)))
+	(setq alist (cdr alist))))
+	(buffer-string))))
+
+(defun erc-format-target ()
+  "Return the name of the target (channel or nickname or servername:port)."
+  (let ((target (erc-default-target)))
+    (or target
+	(concat (erc-shorten-server-name
+		 (or erc-server-announced-name
+		     erc-session-server))
+		":" (erc-port-to-string erc-session-port)))))
+
+(defun erc-format-target-and/or-server ()
+  "Return the server name or the current target and server name combined."
+  (let ((server-name (erc-shorten-server-name
+		      (or erc-server-announced-name
+			  erc-session-server))))
+    (cond ((erc-default-target)
+	   (concat (erc-string-no-properties (erc-default-target))
+		   "@" server-name))
+	  (server-name server-name)
+	  (t (buffer-name (current-buffer))))))
+
+(defun erc-format-away-status ()
+  "Return a formatted `erc-mode-line-away-status-format'
+if `erc-away' is non-nil."
+  (let ((a (when (erc-server-buffer-live-p)
+	     (with-current-buffer (process-buffer erc-server-process)
+	       erc-away))))
+    (if a
+	(format-time-string erc-mode-line-away-status-format a)
+      "")))
+
+(defun erc-format-channel-modes ()
+  "Return the current channel's modes and the estimated lag."
+  (let ((lag (when (erc-server-buffer-live-p)
+	       (with-current-buffer (process-buffer erc-server-process)
+		 erc-server-lag))))
+    (concat (apply 'concat
+		   "(+" erc-channel-modes)
+	    (cond ((and erc-channel-user-limit erc-channel-key)
+		   (if erc-show-channel-key-p
+		       (format "lk %.0f %s" erc-channel-user-limit
+			       erc-channel-key)
+		     (format "kl %.0f" erc-channel-user-limit)))
+		  (erc-channel-user-limit
+		   ;; Emacs has no bignums
+		   (format "l %.0f" erc-channel-user-limit))
+		  (erc-channel-key
+		   (if erc-show-channel-key-p
+		       (format "k %s" erc-channel-key)
+		     "k"))
+		  (t ""))
+	    (if lag (format ",lag:%.0f" lag) "")
+	    ")")))
+
+(defun erc-update-mode-line-buffer (buffer)
+  "Update the mode line in a single ERC buffer BUFFER."
+  (with-current-buffer buffer
+    (let ((spec (format-spec-make
+		 ?a (erc-format-away-status)
+		 ?m (erc-format-channel-modes)
+		 ?n (or (erc-current-nick) "")
+		 ?o (erc-controls-strip erc-channel-topic)
+		 ?p (erc-port-to-string erc-session-port)
+		 ?s (erc-format-target-and/or-server)
+		 ?t (erc-format-target)))
+	  (process-status (cond ((and (erc-server-process-alive)
+				      (not erc-server-connected))
+				 ":connecting")
+				((erc-server-process-alive)
+				 "")
+				(t
+				 ": CLOSED"))))
+      (cond ((featurep 'xemacs)
+	     (setq modeline-buffer-identification
+		   (list (format-spec erc-mode-line-format spec)))
+	     (setq modeline-process (list process-status)))
+	    (t
+	     (setq mode-line-buffer-identification
+		   (list (format-spec erc-mode-line-format spec)))
+	     (setq mode-line-process (list process-status))))
+      (when (boundp 'header-line-format)
+	(let ((header (if erc-header-line-format
+			  (format-spec erc-header-line-format spec)
+			nil)))
+	  (cond ((null header)
+		 (setq header-line-format nil))
+		(erc-header-line-uses-help-echo-p
+		 (let ((help-echo (with-temp-buffer
+				    (insert header)
+				    (fill-region (point-min) (point-max))
+				    (buffer-string))))
+		   (setq header-line-format
+			 (erc-replace-regexp-in-string
+			  "%"
+			  "%%"
+			  (erc-propertize header 'help-echo help-echo)))))
+		(t (setq header-line-format header))))))
+    (if (featurep 'xemacs)
+	(redraw-modeline)
+      (force-mode-line-update))))
+
+(defun erc-update-mode-line (&optional buffer)
+  "Update the mode line in BUFFER.
+
+If BUFFER is nil, update the mode line in all ERC buffers."
+  (if (and buffer (bufferp buffer))
+      (erc-update-mode-line-buffer buffer)
+    (dolist (buf (erc-buffer-list))
+      (when (buffer-live-p buf)
+	(erc-update-mode-line-buffer buf)))))
+
+;; Miscellaneous
+
+(defun erc-port-to-string (p)
+  "Convert port P to a string.
+P may be an integer or a service name."
+  (if (integerp p)
+      (int-to-string p)
+    p))
+
+(defun erc-string-to-port (s)
+  "Convert string S to either an integer port number or a service name."
+  (let ((n (string-to-number s)))
+    (if (= n 0)
+	s
+      n)))
+
+(defun erc-version (&optional here)
+  "Show the version number of ERC in the minibuffer.
+If optional argument HERE is non-nil, insert version number at point."
+  (interactive "P")
+  (let ((version-string
+	 (format "ERC %s" erc-version-string)))
+    (if here
+	(insert version-string)
+      (if (interactive-p)
+	  (message "%s" version-string)
+	version-string))))
+
+(defun erc-version-modules (&optional here)
+  "Show the version numbers of all loaded ERC modules in the minibuffer.
+If optional argument HERE is non-nil, insert version number at point."
+  (interactive "P")
+  (let ((version-string
+	 (mapconcat 'identity
+		    (let (versions (case-fold-search nil))
+		      (dolist (var (apropos-internal "^erc-.*version$"))
+			(when (and (boundp var)
+				   (stringp (symbol-value var)))
+			  (setq versions (cons (format "%S: %s"
+						       var (symbol-value var))
+					       versions))))
+		      versions) ", ")))
+    (if here
+	(insert version-string)
+      (if (interactive-p)
+	  (message "%s" version-string)
+	version-string))))
+
+(defun erc-modes (&optional here)
+  "Show the active ERC modes in the minibuffer.
+If optional argument HERE is non-nil, insert version number at point."
+  (interactive "P")
+  (let ((string
+	 (mapconcat 'identity
+		    (let (modes (case-fold-search nil))
+		      (dolist (var (apropos-internal "^erc-.*mode$"))
+			(when (and (boundp var)
+				   (symbol-value var))
+			  (setq modes (cons (symbol-name var)
+					    modes))))
+		      modes)
+		    ", ")))
+    (if here
+	(insert string)
+      (if (interactive-p)
+	  (message "%s" string)
+	string))))
+
+(defun erc-latest-version ()
+  "Retrieve the latest erc.el version from CVS."
+  (interactive)
+  (if (ignore-errors (require 'url))
+      (progn
+	(switch-to-buffer (get-buffer-create "*erc.el latest version*"))
+	(delete-region (point-min) (point-max))
+	(kill-all-local-variables)
+	(url-insert-file-contents (concat
+				   "http://cvs.sourceforge.net/viewcvs.py/"
+				   "*checkout*/erc/erc/erc.el?content-type"
+				   "=text%2Fplain&rev=HEAD"))
+	(emacs-lisp-mode)
+	(current-buffer))
+    (error "URL needs to be installed")))
+
+(defun erc-ediff-latest-version ()
+  "Ediff your installed erc.el with the latest CVS version.
+See also `erc-latest-version'."
+  (interactive)
+  (let ((current (locate-library "erc.el")))
+    (if current
+	(ediff-buffers (find-file current)
+		       (erc-latest-version))
+      (error "You do not appear to have the uncompiled erc.el file"))))
+
+(defun erc-trim-string (s)
+  "Trim leading and trailing spaces off S."
+  (cond
+   ((not (stringp s)) nil)
+   ((string-match "^\\s-*$" s)
+    "")
+   ((string-match "^\\s-*\\(.*\\S-\\)\\s-*$" s)
+    (match-string 1 s))
+   (t
+    s)))
+
+(defun erc-arrange-session-in-multiple-windows ()
+  "Open a window for every non-server buffer related to `erc-session-server'.
+
+All windows are opened in the current frame."
+  (interactive)
+  (unless (boundp 'erc-server-process)
+    (error "No erc-process found in current buffer"))
+  (let ((bufs (erc-buffer-list nil erc-server-process)))
+    (when bufs
+      (delete-other-windows)
+      (switch-to-buffer (car bufs))
+      (setq bufs (cdr bufs))
+      (while bufs
+	(split-window)
+	(switch-to-buffer-other-window (car bufs))
+	(setq bufs (cdr bufs))
+	(balance-windows)))))
+
+(defun erc-popup-input-buffer ()
+  "Provide a input buffer."
+   (interactive)
+   (let ((buffer-name (generate-new-buffer-name "*ERC input*"))
+	 (mode (intern
+		(completing-read
+		 "Mode: "
+		 (mapcar (lambda (e)
+			   (list (symbol-name e)))
+			 (apropos-internal "-mode$" 'commandp))
+		 nil t))))
+     (pop-to-buffer (make-indirect-buffer (current-buffer) buffer-name))
+     (funcall mode)
+     (narrow-to-region (point) (point))
+     (shrink-window-if-larger-than-buffer)))
+
+;;; Message catalog
+
+(defun erc-make-message-variable-name (catalog entry)
+  "Create a variable name corresponding to CATALOG's ENTRY."
+  (intern (concat "erc-message-"
+		  (symbol-name catalog) "-" (symbol-name entry))))
+
+(defun erc-define-catalog-entry (catalog entry format-spec)
+  "Set CATALOG's ENTRY to FORMAT-SPEC."
+  (set (erc-make-message-variable-name catalog entry)
+       format-spec))
+
+(defun erc-define-catalog (catalog entries)
+  "Define a CATALOG according to ENTRIES."
+  (dolist (entry entries)
+    (erc-define-catalog-entry catalog (car entry) (cdr entry))))
+
+(erc-define-catalog
+ 'english
+ '((bad-ping-response . "Unexpected PING response from %n (time %t)")
+   (bad-syntax . "Error occurred - incorrect usage?\n%c %u\n%d")
+   (incorrect-args . "Incorrect arguments. Usage:\n%c %u\n%d")
+   (cannot-find-file . "Cannot find file %f")
+   (cannot-read-file . "Cannot read file %f")
+   (connect . "Connecting to %S:%p... ")
+   (country . "%c")
+   (country-unknown . "%d: No such domain")
+   (ctcp-empty . "Illegal empty CTCP query received from %n. Ignoring.")
+   (ctcp-request . "==> CTCP request from %n (%u@%h): %r")
+   (ctcp-request-to . "==> CTCP request from %n (%u@%h) to %t: %r")
+   (ctcp-too-many . "Too many CTCP queries in single message. Ignoring")
+   (flood-ctcp-off . "FLOOD PROTECTION: Automatic CTCP responses turned off.")
+   (flood-strict-mode . "FLOOD PROTECTION: Switched to Strict Flood Control mode.")
+   (disconnected . "Connection failed!  Re-establishing connection...")
+   (disconnected-noreconnect . "Connection failed!  Not re-establishing connection.")
+   (login . "Logging in as \'%n\'...")
+   (nick-in-use . "%n is in use. Choose new nickname: ")
+   (nick-too-long . "WARNING: Nick length (%i) exceeds max NICKLEN(%l) defined by server")
+   (no-default-channel . "No default channel")
+   (no-invitation . "You've got no invitation")
+   (no-target . "No target")
+   (ops . "%i operator%s: %o")
+   (ops-none . "No operators in this channel.")
+   (undefined-ctcp . "Undefined CTCP query received. Silently ignored")
+   (variable-not-bound . "Variable not bound!")
+   (ACTION . "* %n %a")
+   (CTCP-CLIENTINFO . "Client info for %n: %m")
+   (CTCP-ECHO . "Echo %n: %m")
+   (CTCP-FINGER . "Finger info for %n: %m")
+   (CTCP-PING . "Ping time to %n is %t")
+   (CTCP-TIME . "Time by %n is %m")
+   (CTCP-UNKNOWN . "Unknown CTCP message from %n (%u@%h): %m")
+   (CTCP-VERSION . "Version for %n is %m")
+   (ERROR  . "==> ERROR from %s: %c\n")
+   (INVITE . "%n (%u@%h) invites you to channel %c")
+   (JOIN   . "%n (%u@%h) has joined channel %c")
+   (JOIN-you . "You have joined channel %c")
+   (KICK . "%n (%u@%h) has kicked %k off channel %c: %r")
+   (KICK-you . "You have been kicked off channel %c by %n (%u@%h): %r")
+   (KICK-by-you . "You have kicked %k off channel %c: %r")
+   (MODE   . "%n (%u@%h) has changed mode for %t to %m")
+   (MODE-nick . "%n has changed mode for %t to %m")
+   (NICK   . "%n (%u@%h) is now known as %N")
+   (NICK-you . "Your new nickname is %N")
+   (PART   . erc-message-english-PART)
+   (PING   . "PING from server (last: %s sec. ago)")
+   (PONG   . "PONG from %h (%i second%s)")
+   (QUIT   . "%n (%u@%h) has quit: %r")
+   (TOPIC  . "%n (%u@%h) has set the topic for %c: \"%T\"")
+   (WALLOPS . "Wallops from %n: %m")
+   (s004   . "%s %v %U %C")
+   (s221   . "User modes for %n: %m")
+   (s252   . "%i operator(s) online")
+   (s253   . "%i unknown connection(s)")
+   (s254   . "%i channels formed")
+   (s301   . "%n is AWAY: %r")
+   (s303   . "Is online: %n")
+   (s305   . "%m")
+   (s306   . "%m")
+   (s311   . "%n is %f (%u@%h)")
+   (s312   . "%n is/was on server %s (%c)")
+   (s313   . "%n is an IRC operator")
+   (s314   . "%n was %f (%u@%h)")
+   (s317   . "%n has been idle for %i")
+   (s317-on-since . "%n has been idle for %i, on since %t")
+   (s319   . "%n is on channel(s): %c")
+   (s320   . "%n is an identified user")
+   (s321   . "Channel  Users  Topic")
+   (s322   . "%c [%u] %t")
+   (s324   . "%c modes: %m")
+   (s329   . "%c was created on %t")
+   (s330   . "%n %a %i")
+   (s331   . "No topic is set for %c")
+   (s332   . "Topic for %c: %T")
+   (s333   . "%c: topic set by %n, %t")
+   (s341   . "Inviting %n to channel %c")
+   (s352   . "%-11c %-10n %-4a %u@%h (%f)")
+   (s353   . "Users on %c: %u")
+   (s367   . "Ban on %b on %c set by %s on %t (Use /banlist!)")
+   (s368   . "Banlist of %c ends.")
+   (s379   . "%c: Forwarded to %f")
+   (s391   . "The time at %s is %t")
+   (s401   . "%n: No such nick/channel")
+   (s403   . "%c: No such channel")
+   (s404   . "%c: Cannot send to channel")
+   (s405   . "%c: You have joined too many channels")
+   (s406   . "%n: There was no such nickname")
+   (s412   . "No text to send")
+   (s421   . "%c: Unknown command")
+   (s431   . "No nickname given")
+   (s432   . "%n is an erroneous nickname")
+   (s442   . "%c: You're not on that channel")
+   (s445   . "SUMMON has been disabled")
+   (s446   . "USERS has been disabled")
+   (s451   . "You have not registered")
+   (s461   . "%c: not enough parameters")
+   (s462   . "Unauthorized command (already registered)")
+   (s463   . "Your host isn't among the privileged")
+   (s464   . "Password incorrect")
+   (s465   . "You are banned from this server")
+   (s474   . "You can't join %c because you're banned (+b)")
+   (s475   . "You must specify the correct channel key (+k) to join %c")
+   (s481   . "Permission Denied - You're not an IRC operator")
+   (s482   . "You need to be a channel operator of %c to do that")
+   (s483   . "You can't kill a server!")
+   (s484   . "Your connection is restricted!")
+   (s485   . "You're not the original channel operator")
+   (s491   . "No O-lines for your host")
+   (s501   . "Unknown MODE flag")
+   (s502   . "You can't change modes for other users")))
+
+(defun erc-message-english-PART (&rest args)
+  "Format a proper PART message.
+
+This function is an example on what could be done with formatting
+functions."
+  (let ((nick (cadr (memq ?n args)))
+	(user (cadr (memq ?u args)))
+	(host (cadr (memq ?h args)))
+	(channel (cadr (memq ?c args)))
+	(reason (cadr (memq ?r args))))
+    (if (string= nick (erc-current-nick))
+	(format "You have left channel %s" channel)
+      (format "%s (%s@%s) has left channel %s%s"
+	      nick user host channel
+	      (if (not (string= reason ""))
+		  (format ": %s" reason)
+		"")))))
+
+
+(defvar erc-current-message-catalog 'english)
+(make-variable-buffer-local 'erc-current-message-catalog)
+
+(defun erc-retrieve-catalog-entry (entry &optional catalog)
+  "Retrieve ENTRY from CATALOG.
+
+If CATALOG is nil, `erc-current-message-catalog' is used.
+
+If ENTRY is nil in CATALOG, it is retrieved from the fallback,
+english, catalog."
+  (unless catalog (setq catalog erc-current-message-catalog))
+  (let ((var (erc-make-message-variable-name catalog entry)))
+    (if (boundp var)
+	(symbol-value var)
+      (when (boundp (erc-make-message-variable-name 'english entry))
+	(symbol-value (erc-make-message-variable-name 'english entry))))))
+
+(defun erc-format-message (msg &rest args)
+  "Format MSG according to ARGS.
+
+See also `format-spec'."
+  (when (eq (logand (length args) 1) 1)	; oddp
+    (error "Obscure usage of this function appeared"))
+  (let ((entry (erc-retrieve-catalog-entry msg)))
+    (when (not entry)
+      (error "No format spec for message %s" msg))
+    (when (functionp entry)
+      (setq entry (apply entry args)))
+    (format-spec entry (apply 'format-spec-make args))))
+
+;;; Various hook functions
+
+(add-hook 'kill-buffer-hook 'erc-kill-buffer-function)
+
+(defcustom erc-kill-server-hook '(erc-kill-server)
+  "*Invoked whenever a server-buffer is killed via `kill-buffer'."
+  :group 'erc-hooks
+  :type 'hook)
+
+(defcustom erc-kill-channel-hook '(erc-kill-channel)
+  "*Invoked whenever a channel-buffer is killed via `kill-buffer'."
+  :group 'erc-hooks
+  :type 'hook)
+
+(defcustom erc-kill-buffer-hook nil
+  "*Hook run whenever a non-server or channel buffer is killed.
+
+See also `kill-buffer'."
+  :group 'erc-hooks
+  :type 'hook)
+
+(defun erc-kill-buffer-function ()
+  "Function to call when an ERC buffer is killed.
+This function should be on `kill-buffer-hook'.
+When the current buffer is in `erc-mode', this function will run
+one of the following hooks:
+`erc-kill-server-hook' if the server buffer was killed,
+`erc-kill-channel-hook' if a channel buffer was killed,
+or `erc-kill-buffer-hook' if any other buffer."
+  (when (eq major-mode 'erc-mode)
+    (erc-remove-channel-users)
+    (cond
+     ((eq (erc-server-buffer) (current-buffer))
+      (run-hooks 'erc-kill-server-hook))
+     ((erc-channel-p (erc-default-target))
+      (run-hooks 'erc-kill-channel-hook))
+     (t
+      (run-hooks 'erc-kill-buffer-hook)))))
+
+(defun erc-kill-server ()
+  "Sends a QUIT command to the server when the server buffer is killed.
+This function should be on `erc-kill-server-hook'."
+  (when (erc-server-process-alive)
+    (setq erc-server-quitting t)
+    (erc-server-send (format "QUIT :%s" (funcall erc-quit-reason nil)))))
+
+(defun erc-kill-channel ()
+  "Sends a PART command to the server when the channel buffer is killed.
+This function should be on `erc-kill-channel-hook'."
+  (when (erc-server-process-alive)
+    (let ((tgt (erc-default-target)))
+      (erc-server-send (format "PART %s :%s" tgt
+			       (funcall erc-part-reason nil))
+		       nil tgt))))
+
+(provide 'erc)
+
+;;; Deprecated. We might eventually stop requiring the goodies automatically.
+;;; IMPORTANT: This require must appear _after_ the above (provide 'erc) to
+;;; avoid a recursive require error when byte-compiling the entire package.
+(require 'erc-goodies)
+
+;;; erc.el ends here
+;;
+;; Local Variables:
+;; outline-regexp: ";;+"
+;; indent-tabs-mode: t
+;; tab-width: 8
+;; End:
+
+;; arch-tag: d19587f6-627e-48c1-8d86-58595fa3eca3
--- a/lisp/files.el	Thu Jan 26 02:23:05 2006 +0000
+++ b/lisp/files.el	Wed Feb 01 10:07:17 2006 +0000
@@ -2450,6 +2450,10 @@
   "Non-nil if SYM could be dangerous as a file-local variable with value VAL.
 If VAL is nil or omitted, the question is whether any value might be
 dangerous."
+  ;; If this is an alias, check the base name.
+  (condition-case nil
+      (setq sym (indirect-variable sym))
+    (error nil))
   (let ((safep (get sym 'safe-local-variable)))
     (or (get sym 'risky-local-variable)
 	(and (string-match "-hooks?$\\|-functions?$\\|-forms?$\\|-program$\\|-commands?$\\|-predicates?$\\|font-lock-keywords$\\|font-lock-keywords-[0-9]+$\\|font-lock-syntactic-keywords$\\|-frame-alist$\\|-mode-alist$\\|-map$\\|-map-alist$"
--- a/lisp/gnus/ChangeLog	Thu Jan 26 02:23:05 2006 +0000
+++ b/lisp/gnus/ChangeLog	Wed Feb 01 10:07:17 2006 +0000
@@ -1,8 +1,60 @@
+2006-01-31  Andreas Seltenreich <uwi7@stud.uni-karlsruhe.de>
+
+	* nnweb.el (nnweb-group-alist): Use defvar instead of defvoo,
+	there's only one active file for all servers.
+	(nnweb-request-scan): Make sure nnweb-articles is initialized on
+	solid groups.  Gnus might have used a FAST request to select the
+	group.
+	(nnweb-request-group, nnweb-google-parse-1): Don't keep nnweb-type
+	and nnweb-search redundantly in the active file.
+	(nnweb-request-list): Don't list bogus groups.  There can only be
+	one.
+	(nnweb-request-create-group): Don't use ARGS.
+	(nnweb-possibly-change-server, nnweb-request-group): Remove some
+	initialisations.  Let nnoo do the work.
+
+2006-01-31  Romain Francoise  <romain@orebokech.com>
+
+	* message.el (message-alternative-emails): Improve docstring.
+	(message-setup-1): Call `message-use-alternative-email-as-from'
+	after `message-setup-hook' to give it precedence over posting
+	styles, etc.
+	(message-use-alternative-email-as-from): Add docstring.  Remove
+	the original From header if present.
+
+2006-01-31  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+	* mm-uu.el (mm-uu-emacs-sources-extract): Say the part has been
+	decoded.
+	(mm-uu-diff-extract): Ditto.
+
+2006-01-31  Kevin Ryde  <user42@zip.com.au>
+
+	* mailcap.el (mailcap-viewer-passes-test): Don't put "(nil t)" into
+	mailcap-viewer-test-cache when there's no 'test clause, since that
+	will invert the meaning of a "nil" test previously determined by
+	mailcap-mailcap-entry-passes-test.
+
+2006-01-30  Reiner Steib  <Reiner.Steib@gmx.de>
+
+	* nnweb.el (nnweb-google-parse-1): Clarify some comments.
+
+2006-01-30  Andreas Seltenreich <uwi7@stud.uni-karlsruhe.de>
+
+	* nnweb.el (nnweb-type-definition, nnweb-google-parse-1)
+	(nnweb-google-create-mapping, nnweb-google-search): Adapt to
+	current Google Groups.
+
+2006-01-26  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+	* Makefile.in (clean): New rule.
+	(distclean): Use it.
+
 2006-01-25  Katsumi Yamaoka  <yamaoka@jpl.org>
 
 	* mm-uu.el (mm-uu-dissect-text-parts): Ignore it if a given part
 	is dissected into a single part of which the type is the same as
-	the given one.
+	the given one; decode charset.
 
 2006-01-21  Kevin Ryde  <user42@zip.com.au>
 
@@ -122,8 +174,8 @@
 
 2006-01-05  Reiner Steib  <Reiner.Steib@gmx.de>
 
-	* gnus-group.el (gnus-useful-groups): Use Gmane for ding.  Use
-	nntp for bug archive.
+	* gnus-group.el (gnus-useful-groups): Use Gmane for ding.
+	Use nntp for bug archive.
 
 2006-01-05  Katsumi Yamaoka  <yamaoka@jpl.org>
 
@@ -162,7 +214,7 @@
 	* gnus-msg.el (gnus-copy-article-buffer): Remove MIME buttons
 	associated with multipart/alternative parts.
 
-2005-12-19  Mark Plaksin <happy@mcplaksin.org>  (tiny change)
+2005-12-19  Mark Plaksin  <happy@mcplaksin.org>  (tiny change)
 
 	* nnrss.el (nnrss-check-group): Put the RSS dc:subject in the
 	article.
@@ -235,7 +287,7 @@
 
 2005-12-09  ARISAWA Akihiro  <ari@mbf.ocn.ne.jp>  (tiny change)
 
-	* mm-decode.el (mm-display-external): Add lacked cdr.
+	* mm-decode.el (mm-display-external): Add missing cdr.
 
 2005-12-12  Richard M. Stallman  <rms@gnu.org>
 
@@ -288,7 +340,7 @@
 	* nnmail.el (nnmail-fancy-expiry-target): Protect against invalid
 	date header.
 
-2005-11-16  Boris Samorodov <bsam@ipt.ru>  (tiny patch)
+2005-11-16  Boris Samorodov  <bsam@ipt.ru>  (tiny patch)
 
 	* imap.el (imap-kerberos4-open): Ignore SSL stuff.
 
@@ -329,7 +381,7 @@
 	error.
 	(nntp-retrieve-data): Rethrow new error condition to break out of
 	recursive call to nntp-send-authinfo.
-	
+
 2005-11-13  Katsumi Yamaoka  <yamaoka@jpl.org>
 
 	* gnus-start.el (gnus-dribble-read-file): Use make-local-variable
@@ -379,8 +431,8 @@
 	(message-insert-courtesy-copy, message-fill-address)
 	(message-fill-header, message-shorten-references)
 	(message-setup-1, message-cancel-news)
-	(message-forward-make-body-plain) (message-forward-make-body-mime)
-	(message-forward-make-body-mml) (message-encode-message-body)
+	(message-forward-make-body-plain, message-forward-make-body-mime)
+	(message-forward-make-body-mml, message-encode-message-body)
 	(message-forward-make-body-digest-plain)
 	(message-forward-make-body-digest-mime)
 	(message-use-alternative-email-as-from): Insert `hard-newline'
@@ -412,7 +464,7 @@
 	whitespace removed in revision 7.8.  Use concatenated string to
 	protect trailing whitespace.
 
-2005-10-27  Jouni K Seppanen <jks@iki.fi>  (tiny change)
+2005-10-27  Jouni K Seppanen  <jks@iki.fi>  (tiny change)
 
 	* nnimap.el (nnimap-search-uids-not-since-is-evil): Add variable.
 	(nnimap-request-expire-articles): Use it to avoid sending 'UID
@@ -511,11 +563,11 @@
 	* message.el (message-expand-group): Pass the common
 	prefix substring of completion to `display-completion-list'.
 
-2005-10-09  Daniel Brockman <daniel@brockman.se>
+2005-10-09  Daniel Brockman  <daniel@brockman.se>
 
 	* format-spec.el (format-spec): Propagate text properties of % spec.
 
-2005-01-21  Derek Atkins <warlord@MIT.EDU>  (tiny change)
+2005-01-21  Derek Atkins  <warlord@MIT.EDU>  (tiny change)
 
 	* pgg-pgp.el (pgg-pgp-decrypt-region): Use passphrase cache.
 
@@ -1777,11 +1829,11 @@
 
 	* nnimap.el (nnimap-retrieve-headers-from-server): Fix last change.
 
-2005-03-10  Arne J,Ax(Brgensen <arne@arnested.dk>  (tiny change)
+2005-03-10  Arne J,Ax(Brgensen  <arne@arnested.dk>  (tiny change)
 
 	* nnimap.el (nnimap-retrieve-headers-from-server): Fix off-by-one flaw.
 
-2005-03-08  Bjorn Solberg <bjorn_ding@hekneby.org>  (tiny change)
+2005-03-08  Bjorn Solberg  <bjorn_ding@hekneby.org>  (tiny change)
 
 	* nnimap.el (nnimap-retrieve-headers-from-server): Sort NOV
 	buffer (since IMAP server might return FETCH response out of
@@ -2352,7 +2404,7 @@
 
 	* legacy-gnus-agent.el
 	(gnus-agent-convert-to-compressed-agentview-prompt):
-	New function. Used internally to only display 'gnus converting
+	New function.  Used internally to only display 'gnus converting
 	files' message when actually necessary.
 
 	* gnus-sum.el: Remove (require 'gnus-agent) as required
@@ -2369,7 +2421,7 @@
 	(gnus-agent-unfetch-articles): New function.
 	(gnus-agent-fetch-headers): Use gnus-agent-braid-nov to validate
 	article numbers even when local .overview file is missing.
-	(gnus-agent-read-article-number): New function. Only accepts
+	(gnus-agent-read-article-number): New function.  Only accepts
 	27-bit article numbers.
 	(gnus-agent-copy-nov-line, gnus-agent-uncached-articles):
 	Use gnus-agent-read-article-number.
@@ -2465,12 +2517,12 @@
 	* gnus-agent.el (gnus-agent-read-agentview): Add a missing arg to
 	error.
 
-2004-10-18  Kevin Greiner <kevin.greiner@compsol.cc>
+2004-10-18  Kevin Greiner  <kevin.greiner@compsol.cc>
 
 	* gnus-start.el (gnus-convert-old-newsrc): Only write the conversion
 	message to newsrc-dribble when an actual conversion is performed.
 
-2004-10-18  Kevin Greiner <kevin.greiner@compsol.cc>
+2004-10-18  Kevin Greiner  <kevin.greiner@compsol.cc>
 
 	* gnus-agent.el (gnus-agent-read-local):
 	Bind nnheader-file-coding-system to gnus-agent-file-coding-system to
@@ -2479,9 +2531,9 @@
 	coding-system-for-write, as the with-temp-file macro first prints
 	to a buffer then saves the buffer.
 
-2004-10-18  Kevin Greiner <kgreiner@xpediantsolutions.com>
-
-	* legacy-gnus-agent.el (): New. Provides converters that are only
+2004-10-18  Kevin Greiner  <kgreiner@xpediantsolutions.com>
+
+	* legacy-gnus-agent.el (): New.  Provides converters that are only
 	loaded when gnus-convert-old-newsrc needs to call them.
 
 	* gnus-agent.el (gnus-agent-read-agentview): Remove support for
@@ -2499,7 +2551,7 @@
 	should be protected from potentially irreversable changes by the
 	function.
 
-2004-10-18  Kevin Greiner <kgreiner@xpediantsolutions.com>
+2004-10-18  Kevin Greiner  <kgreiner@xpediantsolutions.com>
 
 	* gnus-int.el (gnus-request-accept-article): Inform the agent that
 	articles are being added to a group.
@@ -2512,7 +2564,7 @@
 	(gnus-agent-regenerate-group): The REREAD parameter can now be a
 	list of articles that will be marked as unread.
 
-2004-10-18  Kevin Greiner <kevin.greiner@compsol.cc>
+2004-10-18  Kevin Greiner  <kevin.greiner@compsol.cc>
 
 	* gnus-range.el (gnus-sorted-range-intersection): Now accepts
 	single-interval range of the form (min . max).  Previously the
@@ -2524,18 +2576,18 @@
 	* gnus-sum.el (gnus-summary-highlight-line): Articles stored in
 	the cache, but not the agent, now appear with their usual face.
 
-2004-10-18  Kevin Greiner <kevin.greiner@compsol.cc>
+2004-10-18  Kevin Greiner  <kevin.greiner@compsol.cc>
 
 	* gnus-sum.el (gnus-adjust-marks): Now correctly handles a list of
 	marks consisting of a single range {for example, (3 . 5)} rather
 	than a list of a single range { ((3 . 5)) }.
 
-2004-10-18  Kevin Greiner <kevin.greiner@compsol.cc>
+2004-10-18  Kevin Greiner  <kevin.greiner@compsol.cc>
 
 	* gnus-sum.el (gnus-adjust-marks): Avoid splicing null INTO the
 	uncompressed list.
 
-2004-10-18  Kevin Greiner <kevin.greiner@compsol.cc>
+2004-10-18  Kevin Greiner  <kevin.greiner@compsol.cc>
 
 	* gnus-draft.el (gnus-group-send-queue): Pass the group name
 	"nndraft:queue" along to gnus-draft-send.
@@ -3337,7 +3389,7 @@
 	* gnus-msg.el (gnus-summary-followup-with-original):
 	Document yanking of region when active.
 
-2004-04-13 Kevin Greiner <kgreiner@xpediantsolutions.com>
+2004-04-13 Kevin Greiner  <kgreiner@xpediantsolutions.com>
 
 	* gnus-agent.el: Merged 7.3 through 7.7 updates into branch.
 	Revision 7.2 changes excluded to maintain compatibility with all
--- a/lisp/gnus/mailcap.el	Thu Jan 26 02:23:05 2006 +0000
+++ b/lisp/gnus/mailcap.el	Wed Feb 01 10:07:17 2006 +0000
@@ -1,7 +1,7 @@
 ;;; mailcap.el --- MIME media types configuration
 
 ;; Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004,
-;;   2005 Free Software Foundation, Inc.
+;;   2005, 2006 Free Software Foundation, Inc.
 
 ;; Author: William M. Perry <wmperry@aventail.com>
 ;;	Lars Magne Ingebrigtsen <larsi@gnus.org>
@@ -640,30 +640,31 @@
 	 (viewer (cdr (assoc 'viewer viewer-info)))
 	 (default-directory (expand-file-name "~/"))
 	 status parsed-test cache result)
-    (if (setq cache (assoc test mailcap-viewer-test-cache))
-	(cadr cache)
-      (setq
-       result
-       (cond
-	((not test-info) t)		; No test clause
-	((not test) nil)		; Already failed test
-	((eq test t) t)			; Already passed test
-	((functionp test)		; Lisp function as test
-	 (funcall test type-info))
-	((and (symbolp test)		; Lisp variable as test
-	      (boundp test))
-	 (symbol-value test))
-	((and (listp test)		; List to be eval'd
-	      (symbolp (car test)))
-	 (eval test))
-	(t
-	 (setq test (mailcap-unescape-mime-test test type-info)
-	       test (list shell-file-name nil nil nil
-			  shell-command-switch test)
-	       status (apply 'call-process test))
-	 (eq 0 status))))
-      (push (list otest result) mailcap-viewer-test-cache)
-      result)))
+    (cond ((setq cache (assoc test mailcap-viewer-test-cache))
+	   (cadr cache))
+	  ((not test-info) t)		; No test clause
+	  (t
+	   (setq
+	    result
+	    (cond
+	     ((not test) nil)		; Already failed test
+	     ((eq test t) t)		; Already passed test
+	     ((functionp test)		; Lisp function as test
+	      (funcall test type-info))
+	     ((and (symbolp test)	; Lisp variable as test
+		   (boundp test))
+	      (symbol-value test))
+	     ((and (listp test)		; List to be eval'd
+		   (symbolp (car test)))
+	      (eval test))
+	     (t
+	      (setq test (mailcap-unescape-mime-test test type-info)
+		    test (list shell-file-name nil nil nil
+			       shell-command-switch test)
+		    status (apply 'call-process test))
+	      (eq 0 status))))
+	   (push (list otest result) mailcap-viewer-test-cache)
+	   result))))
 
 (defun mailcap-add-mailcap-entry (major minor info)
   (let ((old-major (assoc major mailcap-mime-data)))
--- a/lisp/gnus/message.el	Thu Jan 26 02:23:05 2006 +0000
+++ b/lisp/gnus/message.el	Wed Feb 01 10:07:17 2006 +0000
@@ -1388,8 +1388,13 @@
 		 (integer 1000000)))
 
 (defcustom message-alternative-emails nil
-  "A regexp to match the alternative email addresses.
-The first matched address (not primary one) is used in the From field."
+  "*Regexp matching alternative email addresses.
+The first address in the To, Cc or From headers of the original
+article matching this variable is used as the From field of
+outgoing messages.
+
+This variable has precedence over posting styles and anything that runs
+off `message-setup-hook'."
   :group 'message-headers
   :link '(custom-manual "(message)Message Headers")
   :type '(choice (const :tag "Always use primary" nil)
@@ -5546,10 +5551,6 @@
     (when message-default-mail-headers
       (insert message-default-mail-headers)
       (or (bolp) (insert ?\n)))
-    (save-restriction
-      (message-narrow-to-headers)
-      (if message-alternative-emails
-	  (message-use-alternative-email-as-from)))
     (when message-generate-headers-first
       (message-generate-headers
        (message-headers-to-generate
@@ -5565,6 +5566,12 @@
   (set-buffer-modified-p nil)
   (setq buffer-undo-list nil)
   (run-hooks 'message-setup-hook)
+  ;; Do this last to give it precedence over posting styles, etc.
+  (when (message-mail-p)
+    (save-restriction
+      (message-narrow-to-headers)
+      (if message-alternative-emails
+	  (message-use-alternative-email-as-from))))
   (message-position-point)
   (undo-boundary))
 
@@ -6848,6 +6855,9 @@
       (read-string prompt initial-contents))))
 
 (defun message-use-alternative-email-as-from ()
+  "Set From field of the outgoing message to the first matching
+address in `message-alternative-emails', looking at To, Cc and
+From headers in the original article."
   (require 'mail-utils)
   (let* ((fields '("To" "Cc"))
 	 (emails
@@ -6862,6 +6872,7 @@
 		emails nil))
       (pop emails))
     (unless (or (not email) (equal email user-mail-address))
+      (message-remove-header "From")
       (goto-char (point-max))
       (insert "From: " email "\n"))))
 
--- a/lisp/gnus/mm-uu.el	Thu Jan 26 02:23:05 2006 +0000
+++ b/lisp/gnus/mm-uu.el	Wed Feb 01 10:07:17 2006 +0000
@@ -266,7 +266,7 @@
 
 (defun mm-uu-emacs-sources-extract ()
   (mm-make-handle (mm-uu-copy-to-buffer start-point end-point)
-		  '("application/emacs-lisp")
+		  '("application/emacs-lisp" (charset . gnus-decoded))
 		  nil nil
 		  (list mm-dissect-disposition
 			(cons 'filename file-name))))
@@ -282,7 +282,7 @@
 
 (defun mm-uu-diff-extract ()
   (mm-make-handle (mm-uu-copy-to-buffer start-point end-point)
-		  '("text/x-patch")))
+		  '("text/x-patch" (charset . gnus-decoded))))
 
 (defun mm-uu-diff-test ()
   (and gnus-newsgroup-name
@@ -509,31 +509,53 @@
 	(setq result (cons "multipart/mixed" (nreverse result))))
       result)))
 
-(defun mm-uu-dissect-text-parts (handle)
-  "Dissect text parts and put uu handles into HANDLE."
+;;;###autoload
+(defun mm-uu-dissect-text-parts (handle &optional decoded)
+  "Dissect text parts and put uu handles into HANDLE.
+Assume text has been decoded if DECODED is non-nil."
   (let ((buffer (mm-handle-buffer handle)))
     (cond ((stringp buffer)
 	   (dolist (elem (cdr handle))
-	     (mm-uu-dissect-text-parts elem)))
+	     (mm-uu-dissect-text-parts elem decoded)))
 	  ((bufferp buffer)
 	   (let ((type (mm-handle-media-type handle))
 		 (case-fold-search t) ;; string-match
-		 encoding children)
+		 children charset encoding)
 	     (when (and
 		    (stringp type)
 		    ;; Mutt still uses application/pgp even though
 		    ;; it has already been withdrawn.
 		    (string-match "\\`text/\\|\\`application/pgp\\'" type)
-		    (setq children
-			  (with-current-buffer buffer
-			    (if (setq encoding (mm-handle-encoding handle))
-				;; Inherit the multibyteness of the `buffer'.
-				(with-temp-buffer
-				  (insert-buffer-substring buffer)
-				  (mm-decode-content-transfer-encoding
-				   encoding type)
-				  (mm-uu-dissect t (mm-handle-type handle)))
-			      (mm-uu-dissect t (mm-handle-type handle))))))
+		    (setq
+		     children
+		     (with-current-buffer buffer
+		       (cond
+			((or decoded
+			     (eq (setq charset (mail-content-type-get
+						(mm-handle-type handle)
+						'charset))
+				 'gnus-decoded))
+			 (setq decoded t)
+			 (mm-uu-dissect
+			  t (cons type '((charset . gnus-decoded)))))
+			(charset
+			 (setq decoded t)
+			 (mm-with-multibyte-buffer
+			   (insert (mm-decode-string (mm-get-part handle)
+						     charset))
+			   (mm-uu-dissect
+			    t (cons type '((charset . gnus-decoded))))))
+			((setq encoding (mm-handle-encoding handle))
+			 (setq decoded nil)
+			 ;; Inherit the multibyteness of the `buffer'.
+			 (with-temp-buffer
+			   (insert-buffer-substring buffer)
+			   (mm-decode-content-transfer-encoding
+			    encoding type)
+			   (mm-uu-dissect t (list type))))
+			(t
+			 (setq decoded nil)
+			 (mm-uu-dissect t (list type)))))))
 	       ;; Ignore it if a given part is dissected into a single
 	       ;; part of which the type is the same as the given one.
 	       (if (and (<= (length children) 2)
@@ -544,10 +566,10 @@
 		 (setcdr handle (cdr children))
 		 (setcar handle (car children)) ;; "multipart/mixed"
 		 (dolist (elem (cdr children))
-		   (mm-uu-dissect-text-parts elem))))))
+		   (mm-uu-dissect-text-parts elem decoded))))))
 	  (t
 	   (dolist (elem handle)
-	     (mm-uu-dissect-text-parts elem))))))
+	     (mm-uu-dissect-text-parts elem decoded))))))
 
 (provide 'mm-uu)
 
--- a/lisp/gnus/nnweb.el	Thu Jan 26 02:23:05 2006 +0000
+++ b/lisp/gnus/nnweb.el	Wed Feb 01 10:07:17 2006 +0000
@@ -1,7 +1,7 @@
 ;;; nnweb.el --- retrieving articles via web search engines
 
 ;; Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
-;;   2004, 2005 Free Software Foundation, Inc.
+;;   2004, 2005, 2006 Free Software Foundation, Inc.
 
 ;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
 ;; Keywords: news
@@ -27,11 +27,8 @@
 
 ;; Note: You need to have `w3' installed for some functions to work.
 
-;; FIXME: Due to changes in the HTML output of Google Groups and Gmane, stuff
-;; related to web groups (gnus-group-make-web-group) doesn't work anymore.
-
-;; Fetching an article by MID (cf. gnus-refer-article-method) over Google
-;; Groups should work.
+;; FIXME: Due to changes in the HTML output of Gmane, stuff related to Gmane
+;; web groups (`gnus-group-make-web-group') doesn't work anymore.
 
 ;;; Code:
 
@@ -61,6 +58,7 @@
 (defvar nnweb-type-definition
   '((google
      (id . "http://www.google.com/groups?as_umsgid=%s&hl=en&dmode=source")
+     (result . "http://groups.google.com/group/%s/msg/%s?dmode=source")
      (article . nnweb-google-wash-article)
      (reference . identity)
      (map . nnweb-google-create-mapping)
@@ -69,8 +67,9 @@
      (base    . "http://groups.google.com")
      (identifier . nnweb-google-identity))
     (dejanews ;; alias of google
-     (article . ignore)
-     (id . "http://groups.google.com/groups?selm=%s&output=gplain")
+     (id . "http://www.google.com/groups?as_umsgid=%s&hl=en&dmode=source")
+     (result . "http://groups.google.com/group/%s/msg/%s?dmode=source")
+     (article . nnweb-google-wash-article)
      (reference . identity)
      (map . nnweb-google-create-mapping)
      (search . nnweb-google-search)
@@ -100,7 +99,7 @@
 
 (defvoo nnweb-articles nil)
 (defvoo nnweb-buffer nil)
-(defvoo nnweb-group-alist nil)
+(defvar nnweb-group-alist nil)
 (defvoo nnweb-group nil)
 (defvoo nnweb-hashtb nil)
 
@@ -123,25 +122,19 @@
 (deffoo nnweb-request-scan (&optional group server)
   (nnweb-possibly-change-server group server)
   (if nnweb-ephemeral-p
-      (setq nnweb-hashtb (gnus-make-hashtable 4095)))
+      (setq nnweb-hashtb (gnus-make-hashtable 4095))
+    (unless nnweb-articles
+      (nnweb-read-overview group)))
   (funcall (nnweb-definition 'map))
   (unless nnweb-ephemeral-p
     (nnweb-write-active)
     (nnweb-write-overview group)))
 
 (deffoo nnweb-request-group (group &optional server dont-check)
-  (nnweb-possibly-change-server nil server)
-  (when (and group
-	     (not (equal group nnweb-group))
-	     (not nnweb-ephemeral-p))
-    (setq nnweb-group group
-	  nnweb-articles nil)
-    (let ((info (assoc group nnweb-group-alist)))
-      (when info
-	(setq nnweb-type (nth 2 info))
-	(setq nnweb-search (nth 3 info))
-	(unless dont-check
-	  (nnweb-read-overview group)))))
+  (nnweb-possibly-change-server group server)
+  (unless (or nnweb-ephemeral-p
+	      dont-check)
+    (nnweb-read-overview group))
   (cond
    ((not nnweb-articles)
     (nnheader-report 'nnweb "No matching articles"))
@@ -205,7 +198,7 @@
   (nnweb-possibly-change-server nil server)
   (save-excursion
     (set-buffer nntp-server-buffer)
-    (nnmail-generate-active nnweb-group-alist)
+    (nnmail-generate-active (list (assoc server nnweb-group-alist)))
     t))
 
 (deffoo nnweb-request-update-info (group info &optional server)
@@ -217,7 +210,7 @@
 (deffoo nnweb-request-create-group (group &optional server args)
   (nnweb-possibly-change-server nil server)
   (nnweb-request-delete-group group)
-  (push `(,group ,(cons 1 0) ,@args) nnweb-group-alist)
+  (push `(,group ,(cons 1 0)) nnweb-group-alist)
   (nnweb-write-active)
   t)
 
@@ -287,18 +280,16 @@
     def))
 
 (defun nnweb-possibly-change-server (&optional group server)
-  (nnweb-init server)
   (when server
     (unless (nnweb-server-opened server)
-      (nnweb-open-server server)))
+      (nnweb-open-server server))
+    (nnweb-init server))
   (unless nnweb-group-alist
     (nnweb-read-active))
   (unless nnweb-hashtb
     (setq nnweb-hashtb (gnus-make-hashtable 4095)))
   (when group
-    (when (and (not nnweb-ephemeral-p)
-	       (equal group nnweb-group))
-      (nnweb-request-group group nil t))))
+    (setq nnweb-group group)))
 
 (defun nnweb-init (server)
   "Initialize buffers and such."
@@ -337,22 +328,27 @@
       (mm-url-decode-entities))))
 
 (defun nnweb-google-parse-1 (&optional Message-ID)
+  "Parse search result in current buffer."
   (let ((i 0)
 	(case-fold-search t)
 	(active (cadr (assoc nnweb-group nnweb-group-alist)))
 	Subject Score Date Newsgroups From
 	map url mid)
     (unless active
-      (push (list nnweb-group (setq active (cons 1 0))
-		  nnweb-type nnweb-search)
+      (push (list nnweb-group (setq active (cons 1 0)))
 	    nnweb-group-alist))
     ;; Go through all the article hits on this page.
     (goto-char (point-min))
-    (while (re-search-forward
-	    "a href=/groups\\(\\?[^ \">]*selm=\\([^ &\">]+\\)\\)" nil t)
-      (setq mid (match-string 2)
+    (while
+	(re-search-forward
+	 "a +href=\"/group/\\([^>\"]+\\)/browse_thread/[^>]+#\\([0-9a-f]+\\)"
+	 nil t)
+      (setq Newsgroups (match-string-no-properties 1)
+	    ;; Note: Starting with Google Groups 2, `mid' is a Google-internal
+	    ;; ID, not a proper Message-ID.
+	    mid (match-string-no-properties 2)
 	    url (format
-		 (nnweb-definition 'id) mid))
+		 (nnweb-definition 'result) Newsgroups mid))
       (narrow-to-region (search-forward ">" nil t)
 			(search-forward "</a>" nil t))
       (mm-url-remove-markup)
@@ -360,25 +356,22 @@
       (setq Subject (buffer-string))
       (goto-char (point-max))
       (widen)
-      (forward-line 2)
-      (when (looking-at "<br><font[^>]+>")
-	(goto-char (match-end 0)))
-      (if (not (looking-at "<a[^>]+>"))
-	  (skip-chars-forward " \t")
-	(narrow-to-region (point)
-			  (search-forward "</a>" nil t))
-	(mm-url-remove-markup)
-	(mm-url-decode-entities)
-	(setq Newsgroups (buffer-string))
-	(goto-char (point-max))
-	(widen)
-	(skip-chars-forward "- \t"))
+      (narrow-to-region (point)
+			(search-forward "</td" nil t))
+
+      (mm-url-remove-markup)
+      (mm-url-decode-entities)
+      (search-backward " - ")
       (when (looking-at
-	     "\\([0-9]+\\)[/ ]\\([A-Za-z]+\\)[/ ]\\([0-9]+\\)[ \t]*by[ \t]*\\([^<]*\\) - <a")
+	     " - \\([a-zA-Z]+\\) \\([0-9]+\\)\\(?: \\([0-9]\\{4\\}\\)\\)?, [^\n]+by \\([^<\n]+\\)\n")
 	(setq From (match-string 4)
 	      Date (format "%s %s 00:00:00 %s"
-			   (match-string 2) (match-string 1)
-			   (match-string 3))))
+			   (match-string 1)
+			   (match-string 2)
+			   (or (match-string 3)
+			       (substring (current-time-string) -4)))))
+
+      (widen)
       (forward-line 1)
       (incf i)
       (unless (nnweb-get-hashtb url)
@@ -419,7 +412,7 @@
 	    (goto-char (point-min))
 	    (incf i 100)
 	    (if (or (not (re-search-forward
-			  "<td nowrap><a href=\\([^>]+\\).*<span class=b>Next</span>" nil t))
+			  "<td><a href=\"\n\\([^>\"]+\\)\"><img src=\"/img/nav_next" nil t))
 		    (>= i nnweb-max-hits))
 		(setq more nil)
 	      ;; Yup, there are more articles
@@ -443,7 +436,8 @@
        ("hl" . "en")
        ("lr" . "")
        ("safe" . "off")
-       ("sites" . "groups")))))
+       ("sites" . "groups")
+       ("filter" . "0")))))
   t)
 
 (defun nnweb-google-identity (url)
--- a/lisp/help-fns.el	Thu Jan 26 02:23:05 2006 +0000
+++ b/lisp/help-fns.el	Wed Feb 01 10:07:17 2006 +0000
@@ -113,7 +113,8 @@
      (setq val (completing-read (if fn
 				    (format "Describe function (default %s): " fn)
 				  "Describe function: ")
-				obarray 'fboundp t nil nil (symbol-name fn)))
+				obarray 'fboundp t nil nil
+				(and fn (symbol-name fn))))
      (list (if (equal val "")
 	       fn (intern val)))))
   (if (null function)
--- a/lisp/image-mode.el	Thu Jan 26 02:23:05 2006 +0000
+++ b/lisp/image-mode.el	Wed Feb 01 10:07:17 2006 +0000
@@ -137,11 +137,14 @@
 	    (message "Repeat this command to go back to displaying the image")))
     ;; Turn the image data into a real image, but only if the whole file
     ;; was inserted
-    (let* ((data
-	    (string-make-unibyte
-	     (buffer-substring-no-properties (point-min) (point-max))))
-	   (image
-	    (create-image data nil t))
+    (let* ((image
+	    (if (and (buffer-file-name)
+		     (not (buffer-modified-p)))
+		(create-image (buffer-file-name))
+	      (create-image
+	       (string-make-unibyte
+		(buffer-substring-no-properties (point-min) (point-max)))
+	       nil t)))
 	   (props
 	    `(display ,image
 		      intangible ,image
--- a/lisp/international/latexenc.el	Thu Jan 26 02:23:05 2006 +0000
+++ b/lisp/international/latexenc.el	Wed Feb 01 10:07:17 2006 +0000
@@ -1,4 +1,4 @@
-;;; latexenc.el --- guess correct coding system in LaTeX files
+;;; latexenc.el --- guess correct coding system in LaTeX files -*-coding: iso-2022-7bit -*-
 
 ;; Copyright (C) 2005, 2006 Free Software Foundation, Inc.
 
@@ -167,7 +167,7 @@
                   (setq latexenc-main-file (tex-guess-main-file)))))
             ;; if we found a master/main file get the coding system from it
             (if (and latexenc-main-file
-		     (file-regular-p latexenc-main-file)
+                     (file-regular-p latexenc-main-file)
                      (file-readable-p latexenc-main-file))
                 (let* ((latexenc-dont-use-tex-guess-main-file-flag t)
                        (latexenc-dont-use-TeX-master-flag t)
--- a/lisp/mail/rmailsum.el	Thu Jan 26 02:23:05 2006 +0000
+++ b/lisp/mail/rmailsum.el	Wed Feb 01 10:07:17 2006 +0000
@@ -332,9 +332,8 @@
 	    (if (looking-at "Summary-line: ")
 		(progn
 		  (goto-char (match-end 0))
-		  (setq line
-			(buffer-substring (point)
-					  (progn (forward-line 1) (point)))))))))
+		  (buffer-substring (point)
+				    (progn (forward-line 1) (point))))))))
     ;; Obsolete status lines lacking a # should be flushed.
     (and line
 	 (not (string-match "#" line))
--- a/lisp/makefile.w32-in	Thu Jan 26 02:23:05 2006 +0000
+++ b/lisp/makefile.w32-in	Wed Feb 01 10:07:17 2006 +0000
@@ -82,6 +82,7 @@
 	calendar \
 	emacs-lisp \
 	emulation \
+	erc \
 	eshell \
 	gnus \
 	international \
@@ -301,14 +302,18 @@
 # the autoloads for the MH-E entry points, which are already in
 # loaddefs.el.
 MH_E_SRC = $(lisp)/mh-e/mh-acros.el $(lisp)/mh-e/mh-alias.el	\
-	$(lisp)/mh-e/mh-buffers.el $(lisp)/mh-e/mh-comp.el	\
-	$(lisp)/mh-e/mh-customize.el $(lisp)/mh-e/mh-e.el	\
-	$(lisp)/mh-e/mh-funcs.el $(lisp)/mh-e/mh-identity.el	\
-	$(lisp)/mh-e/mh-inc.el $(lisp)/mh-e/mh-init.el		\
-	$(lisp)/mh-e/mh-junk.el $(lisp)/mh-e/mh-mime.el		\
-	$(lisp)/mh-e/mh-print.el $(lisp)/mh-e/mh-search.el	\
-	$(lisp)/mh-e/mh-seq.el $(lisp)/mh-e/mh-speed.el		\
-	$(lisp)/mh-e/mh-utils.el
+	$(lisp)/mh-e/mh-buffers.el $(lisp)/mh-e/mh-compat.el	\
+	$(lisp)/mh-e/mh-comp.el $(lisp)/mh-e/mh-e.el		\
+	$(lisp)/mh-e/mh-folder.el $(lisp)/mh-e/mh-funcs.el	\
+	$(lisp)/mh-e/mh-gnus.el $(lisp)/mh-e/mh-identity.el	\
+	$(lisp)/mh-e/mh-inc.el $(lisp)/mh-e/mh-junk.el		\
+	$(lisp)/mh-e/mh-letter.el $(lisp)/mh-e/mh-limit.el	\
+	$(lisp)/mh-e/mh-mime.el $(lisp)/mh-e/mh-print.el	\
+	$(lisp)/mh-e/mh-scan.el $(lisp)/mh-e/mh-search.el	\
+	$(lisp)/mh-e/mh-seq.el $(lisp)/mh-e/mh-show.el		\
+	$(lisp)/mh-e/mh-speed.el $(lisp)/mh-e/mh-thread.el	\
+	$(lisp)/mh-e/mh-tool-bar.el $(lisp)/mh-e/mh-utils.el	\
+	$(lisp)/mh-e/mh-xface.el
 
 mh-autoloads: $(lisp)/mh-e/mh-loaddefs.el
 $(lisp)/mh-e/mh-loaddefs.el: $(MH_E_SRC)
--- a/lisp/mh-e/.cvsignore	Thu Jan 26 02:23:05 2006 +0000
+++ b/lisp/mh-e/.cvsignore	Wed Feb 01 10:07:17 2006 +0000
@@ -1,2 +1,3 @@
 mh-autoloads.el
+mh-cus-load.el
 mh-loaddefs.el
--- a/lisp/mh-e/ChangeLog	Thu Jan 26 02:23:05 2006 +0000
+++ b/lisp/mh-e/ChangeLog	Wed Feb 01 10:07:17 2006 +0000
@@ -1,3 +1,555 @@
+2006-01-31  Bill Wohler  <wohler@newt.com>
+
+	* mh-acros.el (mh-defun-compat, mh-defmacro-compat): Add name
+	argument since compatibility functions should have our package
+	prefix (mh-) by Emacs convention and to avoid messing up checks
+	for the same functions in other packages. Use explicit argument
+	instead of forming name by adding mh-e prefix so that one can grep
+	and find the definition.
+
+	* mh-alias.el (mh-alias-local-users, mh-alias-reload)
+	(mh-alias-expand, mh-alias-minibuffer-confirm-address): Use
+	mh-assoc-string instead of assoc-string.
+
+	* mh-compat.el (assoc-string): Rename to mh-assoc-string.
+	(mh-mail-abbrev-make-syntax-table, mh-url-hexify-string): Move
+	here from mh-utils.el.
+	(mh-display-completion-list): Move here from mh-comp.el.
+	(mh-face-foreground, mh-face-background): Move here from
+	mh-xface.el.
+	(mh-write-file-functions): Move here from mh-folder.el
+
+	* mh-folder.el (mh-write-file-functions-compat): Move to
+	mh-compat.el and rename to mh-write-file-functions.
+	(mh-folder-mode): Use the new name.
+
+	* mh-gnus.el (gnus-local-map-property): Rename to
+	mh-gnus-local-map-property.
+	(mm-merge-handles): Rename to mh-mm-merge-handles.
+	(mm-set-handle-multipart-parameter): Rename to
+	mh-mm-set-handle-multipart-parameter.
+	(mm-inline-text-vcard): Rename to mh-mm-inline-text-vcard.
+	(mm-possibly-verify-or-decrypt): Rename to
+	mh-mm-possibly-verify-or-decrypt.
+	(mm-handle-multipart-ctl-parameter): Rename to
+	mh-mm-handle-multipart-ctl-parameter.
+	(mm-readable-p): Rename to mh-mm-readable-p.
+	(mm-long-lines-p): Rename to mh-mm-long-lines-p.
+	(mm-keep-viewer-alive-p): Rename to mh-mm-keep-viewer-alive-p.
+	(mm-destroy-parts): Rename to mh-mm-destroy-parts.
+	(mm-uu-dissect-text-parts): Rename to mh-mm-uu-dissect-text-parts.
+	(mml-minibuffer-read-disposition): Rename to
+	mh-mml-minibuffer-read-disposition.
+
+	* mh-identity.el (mh-identity-field-handler): Use mh-assoc-string
+	instead of assoc-string.
+
+	* mh-mime.el (mh-mm-inline-media-tests, mh-mm-inline-message)
+	(mh-mime-display, mh-mime-display-security)
+	(mh-insert-mime-button, mh-insert-mime-security-button)
+	(mh-handle-set-external-undisplayer)
+	(mh-mime-security-press-button, mh-mime-security-show-details)
+	(mh-mml-attach-file, mh-mime-cleanup)
+	(mh-destroy-postponed-handles): Use new mh-* names for
+	compatibility functions.
+
+	* mh-utils.el (mail-abbrev-make-syntax-table): Move to
+	mh-compat.el and rename to mh-mail-abbrev-make-syntax-table.
+	(mh-beginning-of-word): Use the new name.
+	(mh-get-field): Delete ancient alias.
+
+	* mh-xface.el (mh-face-foreground-compat): Move to mh-compat.el
+	and rename to mh-face-foreground
+	(mh-face-background-compat): Move to mh-compat.el
+	and rename to mh-face-background.
+	(mh-face-display-function): Use the new names.
+	(mh-x-image-url-cache-canonicalize): Use mh-url-hexify-string
+	instead of url-hexify-string.
+	(url-unreserved-chars): Move to mh-compat.el and rename to
+	mh-url-unreserved-chars.
+	(url-hexify-string): Move to mh-compat.el and rename to
+	mh-url-hexify-string.
+
+	* mh-letter.el (mh-complete-word): Fix bug in call to
+	mh-display-completion-list. Wrong argument was passed, so
+	completions wouldn't show highlighted prefix.
+
+2006-01-29  Bill Wohler  <wohler@newt.com>
+
+	* mh-e.el (mh-scan-format-file-check): Allow any non-nil for
+	mh-adaptive-cmd-note-flag.
+
+	* mh-comp.el (sc-cite-original): Remove autoload of "sc" with old
+	docstring. sc-cite-original is autoloaded via loaddefs.el for all
+	supported versions. In addition, the package name "sc" has been
+	made obsolete by "supercite since at least Emacs 21.
+
+	* mh-scan.el (mh-note-copied, mh-note-printed): Reorganization
+	revealed character constants that were still strings (closes SF
+	#770772).
+
+	* mh-comp.el (mh-letter-hide-all-skipped-fields)
+	(mh-get-header-field): Move to mh-utils.el so that you can read
+	messages without having to load mh-comp.el and mh-letter.el.
+
+	* mh-letter.el (mh-hidden-header-keymap)
+	(mh-letter-toggle-header-field-display)
+	(mh-letter-skipped-header-field-p)
+	(mh-letter-skip-leading-whitespace-in-header-field)
+	(mh-letter-truncate-header-field): Move to mh-utils.el so that you
+	can read messages without having to load mh-comp.el and
+	mh-letter.el.
+
+	* mh-utils.el (mh-get-header-field)
+	(mh-letter-hide-all-skipped-fields) 
+	(mh-letter-skipped-header-field-p, mh-hidden-header-keymap)
+	(mh-letter-toggle-header-field-display)
+	(mh-letter-skip-leading-whitespace-in-header-field)
+	(mh-letter-truncate-header-field): Move here from mh-comp.el and
+	mh-letter.el so that you can read messages without having to load
+	mh-comp.el and mh-letter.el.
+
+	* mh-comp.el (mh-insert-fields): Handle nil values. Rmail, at
+	least, will deliver them to us.
+
+	* mh-e.el (mh-after-commands-processed-hook)
+	(mh-before-commands-processed-hook): Specify what sort of requests
+	in docstring.
+
+	* mh-folder.el (mh-folder-mode): Use add-to-list to modify
+	minor-mode-alias.
+
+	* mh-letter.el (mh-letter-menu): Remove. Defvar no longer needed
+	to shush compiler.
+	(mh-letter-mode): Remove Mail menu.
+
+2006-01-29  Bill Wohler  <wohler@newt.com>
+
+	The Great Cleanup
+	Remove circular dependencies. mh-e.el now includes few require
+	statements and stands alone. Other files should need to require
+	mh-e.el, which requires mh-loaddefs.el, plus variable-only files
+	such as mh-scan.el.
+	Remove unneeded require statements.
+	Remove unneeded load statements, or replace them with non-fatal
+	require statements.
+	Break out components into their own files that were often spread
+	between many files.
+	As a result, many functions that are now only used within a single
+	file no longer need to be autoloaded.
+	Rearrange and provide consistent headings.
+	Untabify.
+
+	* mh-acros.el: Update commentary to reflect current usage. Add
+	autoload cookies to all macros.
+	(mh-require-cl): Merge docstring and comment.
+	(mh-do-in-xemacs): Fix typo in docstring.
+	(assoc-string): Move to new file mh-compat.el.
+	(with-mh-folder-updating, mh-in-show-buffer)
+	(mh-do-at-event-location, mh-seq-msgs): Move here from
+	mh-utils.el.
+	(mh-iterate-on-messages-in-region, mh-iterate-on-range): Move here
+	from mh-seq.el.
+
+	* mh-alias.el (mh-address-mail-regexp)
+	(mh-goto-address-find-address-at-point): Move here from
+	mh-utils.el.
+	(mh-folder-line-matches-show-buffer-p): Move here from mh-e.el.
+
+	* mh-buffers.el: Update descriptive text.	
+
+	* mh-comp.el (mh-note-repl, mh-note-forw, mh-note-dist): Move to
+	new file mh-scan.el.
+	(mh-yank-hooks, mh-to-field-choices, mh-position-on-field)
+	(mh-letter-menu, mh-letter-mode-help-messages)
+	(mh-letter-buttons-init-flag, mh-letter-mode)
+	(mh-font-lock-field-data, mh-letter-header-end)
+	(mh-auto-fill-for-letter, mh-to-field, mh-to-fcc)
+	(mh-file-is-vcard-p, mh-insert-signature, mh-check-whom)
+	(mh-insert-letter, mh-extract-from-attribution, mh-yank-cur-msg)
+	(mh-filter-out-non-text, mh-insert-prefix-string)
+	(mh-current-fill-prefix, mh-open-line, mh-complete-word)
+	(mh-folder-expand-at-point, mh-letter-complete-function-alist)
+	(mh-letter-complete, mh-letter-complete-or-space)
+	(mh-letter-confirm-address, mh-letter-header-field-at-point)
+	(mh-letter-next-header-field-or-indent)
+	(mh-letter-next-header-field, mh-letter-previous-header-field)
+	(mh-letter-skipped-header-field-p)
+	(mh-letter-skip-leading-whitespace-in-header-field)
+	(mh-hidden-header-keymap)
+	(mh-letter-toggle-header-field-display-button)
+	(mh-letter-toggle-header-field-display)
+	(mh-letter-truncate-header-field, mh-letter-mode-map): Move to new
+	file mh-letter.el.
+	(mh-letter-mode-map, mh-sent-from-folder, mh-send-args)
+	(mh-pgp-support-flag, mh-x-mailer-string)
+	(mh-letter-header-field-regexp): Move to mh-e.el.
+	(mh-goto-header-field, mh-goto-header-end)
+	(mh-extract-from-header-value, mh-beginning-of-word): Move to
+	mh-utils.el.
+	(mh-insert-header-separator): Move to mh-comp.el.
+	(mh-display-completion-list-compat): Move to new file
+	mh-compat.el.
+
+	* mh-compat.el: New file.
+	(assoc-string): Move here from mh-acros.el.
+	(mh-display-completion-list): Move here from mh-comp.el.
+
+	* mh-customize.el: Move content into mh-e.el and remove.
+	
+	* mh-e.el (mh-folder-mode-map, mh-folder-seq-tool-bar-map)
+	(mh-folder-tool-bar-map, mh-inc-spool-map, mh-letter-mode-map)
+	(mh-letter-tool-bar-map, mh-search-mode-map, mh-show-mode-map)
+	(mh-show-seq-tool-bar-map, mh-show-tool-bar-map): All maps now
+	declared here so that they can be used in docstrings.
+	(mh-sent-from-folder, mh-sent-from-msg)
+	(mh-letter-header-field-regexp, mh-pgp-support-flag)
+	(mh-x-mailer-string): Move here from mh-comp.el.
+	(mh-folder-line-matches-show-buffer-p): Move to mh-alias.el.
+	(mh-thread-scan-line-map, mh-thread-scan-line-map-stack): Move
+	here from mh-seq.el.
+	(mh-draft-folder, mh-inbox, mh-user-path, mh-current-folder)
+	(mh-previous-window-config, mh-seen-list, mh-seq-list)
+	(mh-show-buffer, mh-showing-mode, mh-globals-hash)
+	(mh-show-folder-buffer, mh-mail-header-separator)
+	(mh-unseen-seq, mh-previous-seq, mh-page-to-next-msg-flag)
+	(mh-signature-separator, mh-signature-separator-regexp)
+	(mh-list-to-string, mh-list-to-string-1): Move here from
+	mh-utils.el.
+	(mh-index-max-cmdline-args, mh-xargs, mh-quote-for-shell)
+	(mh-exec-cmd, mh-exec-cmd-error, mh-exec-cmd-daemon)
+	(mh-exec-cmd-env-daemon, mh-process-daemon, mh-exec-cmd-quiet)
+	(mh-exec-cmd-output)
+	(mh-exchange-point-and-mark-preserving-active-mark)
+	(mh-exec-lib-cmd-output, mh-handle-process-error): Move here from
+	deprecated file mh-exec.el.
+	(mh-path): Move here from deprecated file mh-customize.el.
+	(mh-sys-path, mh-variants, mh-variant-in-use, mh-progs, mh-lib)
+	(mh-flists-present-flag, mh-variants, mh-variant-mh-info)
+	(mh-variant-mu-mh-info, mh-variant-nmh-info, mh-file-command-p)
+	(mh-variant-set-variant, mh-variant-p, mh-profile-component)
+	(mh-profile-component-value, mh-defface-compat): Move here from
+	deprecated file mh-init.el.
+	(mh-goto-next-button, mh-folder-mime-action)
+	(mh-folder-toggle-mime-part, mh-folder-inline-mime-part)
+	(mh-folder-save-mime-part, mh-toggle-mime-buttons): Move to to
+	mh-mime.el.
+	(mh-scan-format-mh, mh-scan-format-nmh, mh-note-deleted)
+	(mh-note-refiled, mh-note-cur, mh-scan-good-msg-regexp)
+	(mh-scan-deleted-msg-regexp, mh-scan-refiled-msg-regexp)
+	(mh-scan-valid-regexp, mh-scan-cur-msg-number-regexp)
+	(mh-scan-date-regexp, mh-scan-rcpt-regexp, mh-scan-body-regexp)
+	(mh-scan-subject-regexp, mh-scan-sent-to-me-sender-regexp)
+	(mh-scan-cmd-note-width, mh-scan-destination-width)
+	(mh-scan-date-width, mh-scan-date-flag-width)
+	(mh-scan-from-mbox-width, mh-scan-from-mbox-sep-width)
+	(mh-scan-field-destination-offset)
+	(mh-scan-field-from-start-offset, mh-scan-field-from-end-offset)
+	(mh-scan-field-subject-start-offset, mh-scan-format)
+	(mh-msg-num-width-to-column, mh-set-cmd-note): Move to new file
+	mh-scan.el.
+	(mh-partial-folder-mode-line-annotation)
+	(mh-folder-font-lock-keywords, mh-folder-font-lock-subject)
+	(mh-generate-sequence-font-lock, mh-last-destination)
+	(mh-last-destination-write, mh-first-msg-num, mh-last-msg-num)
+	(mh-rmail, mh-nmail, mh-delete-msg, mh-delete-msg-no-motion)
+	(mh-execute-commands, mh-first-msg, mh-header-display)
+	(mh-inc-folder, mh-last-msg, mh-next-undeleted-msg)
+	(mh-folder-from-address, mh-prompt-for-refile-folder)
+	(mh-refile-msg, mh-refile-or-write-again, mh-quit, mh-page-msg)
+	(mh-previous-page, mh-previous-undeleted-msg)
+	(mh-previous-unread-msg, mh-next-button, mh-prev-button)
+	(mh-reset-threads-and-narrowing, mh-rescan-folder)
+	(mh-write-msg-to-file, mh-toggle-showing, mh-undo)
+	(mh-visit-folder, mh-update-sequences, mh-delete-a-msg)
+	(mh-refile-a-msg, mh-next-msg, mh-next-unread-msg)
+	(mh-set-scan-mode, mh-undo-msg, mh-make-folder)
+	(mh-folder-sequence-menu, mh-folder-message-menu)
+	(mh-folder-folder-menu, mh-remove-xemacs-horizontal-scrollbar)
+	(mh-write-file-functions-compat, mh-folder-mode)
+	(mh-restore-desktop-buffer, mh-scan-folder)
+	(mh-regenerate-headers, mh-generate-new-cmd-note)
+	(mh-get-new-mail, mh-make-folder-mode-line, mh-goto-cur-msg)
+	(mh-process-or-undo-commands, mh-process-commands)
+	(mh-update-unseen, mh-delete-scan-msgs)
+	(mh-outstanding-commands-p): Move to new file mh-folder.el.
+	(mh-mapc, mh-colors-available-p, mh-colors-in-use-p)
+	(mh-make-local-vars, mh-coalesce-msg-list, mh-greaterp)
+	(mh-lessp): Move to mh-utils.el.
+	(mh-parse-flist-output-line, mh-folder-size-folder)
+	(mh-folder-size-flist, mh-folder-size, mh-add-sequence-notation)
+	(mh-remove-sequence-notation, mh-remove-cur-notation)
+	(mh-remove-all-notation, mh-delete-seq-locally)
+	(mh-read-folder-sequences, mh-read-msg-list)
+	(mh-notate-user-sequences, mh-internal-seqs, mh-internal-seq)
+	(mh-valid-seq-p, mh-delete-msg-from-seq, mh-catchup)
+	(mh-delete-a-msg-from-seq, mh-undefine-sequence)
+	(mh-define-sequence, mh-seq-containing-msg): Move to mh-seq.el.
+	(mh-xemacs-flag)
+	(mh-customize, mh-e, mh-alias, mh-folder, mh-folder-selection)
+	(mh-identity, mh-inc, mh-junk, mh-letter, mh-ranges)
+	(mh-scan-line-formats, mh-search, mh-sending-mail, mh-sequences)
+	(mh-show, mh-speedbar, mh-thread, mh-tool-bar, mh-hooks)
+	(mh-faces, mh-alias-completion-ignore-case-flag)
+	(mh-alias-expand-aliases-flag, mh-alias-flash-on-comma)
+	(mh-alias-insert-file, mh-alias-insertion-location)
+	(mh-alias-local-users, mh-alias-local-users-prefix)
+	(mh-alias-passwd-gecos-comma-separator-flag)
+	(mh-new-messages-folders, mh-ticked-messages-folders)
+	(mh-large-folder, mh-recenter-summary-flag)
+	(mh-recursive-folders-flag, mh-sortm-args)
+	(mh-default-folder-for-message-function, mh-default-folder-list)
+	(mh-default-folder-must-exist-flag, mh-default-folder-prefix)
+	(mh-identity-list, mh-auto-fields-list)
+	(mh-auto-fields-prompt-flag, mh-identity-default)
+	(mh-identity-handlers, mh-inc-prog, mh-inc-spool-list)
+	(mh-junk-choice, mh-junk-function-alist, mh-junk-choose)
+	(mh-junk-background, mh-junk-disposition, mh-junk-program)
+	(mh-compose-insertion, mh-compose-skipped-header-fields)
+	(mh-compose-space-does-completion-flag)
+	(mh-delete-yanked-msg-window-flag)
+	(mh-extract-from-attribution-verb, mh-ins-buf-prefix)
+	(mh-letter-complete-function, mh-letter-fill-column)
+	(mh-mml-method-default, mh-signature-file-name)
+	(mh-signature-separator-flag, mh-x-face-file, mh-yank-behavior)
+	(mh-interpret-number-as-range-flag, mh-adaptive-cmd-note-flag)
+	(mh-scan-format-file-check, mh-scan-format-file)
+	(mh-adaptive-cmd-note-flag-check, mh-scan-prog)
+	(mh-search-program, mh-compose-forward-as-mime-flag)
+	(mh-compose-letter-function, mh-compose-prompt-flag)
+	(mh-forward-subject-format, mh-insert-x-mailer-flag)
+	(mh-redist-full-contents-flag, mh-reply-default-reply-to)
+	(mh-reply-show-message-flag, mh-refile-preserves-sequences-flag)
+	(mh-tick-seq, mh-update-sequences-after-mh-show-flag)
+	(mh-bury-show-buffer-flag, mh-clean-message-header-flag)
+	(mh-decode-mime-flag, mh-display-buttons-for-alternatives-flag)
+	(mh-display-buttons-for-inline-parts-flag)
+	(mh-do-not-confirm-flag, mh-fetch-x-image-url)
+	(mh-graphical-smileys-flag, mh-graphical-emphasis-flag)
+	(mh-highlight-citation-style)
+	(mh-invisible-header-fields-internal)
+	(mh-delay-invisible-header-generation-flag)
+	(mh-invisible-header-fields, mh-invisible-header-fields-default)
+	(mh-invisible-header-fields-compiled, mh-invisible-headers)
+	(mh-lpr-command-format, mh-max-inline-image-height)
+	(mh-max-inline-image-width, mh-mhl-format-file)
+	(mh-mime-save-parts-default-directory, mh-print-background-flag)
+	(mh-show-maximum-size, mh-show-use-goto-addr-flag)
+	(mh-show-use-xface-flag, mh-store-default-directory)
+	(mh-summary-height, mh-speed-update-interval)
+	(mh-show-threads-flag, mh-tool-bar-search-function)
+	(mh-after-commands-processed-hook, mh-alias-reloaded-hook)
+	(mh-before-commands-processed-hook, mh-before-quit-hook)
+	(mh-before-send-letter-hook, mh-delete-msg-hook)
+	(mh-find-path-hook, mh-folder-mode-hook, mh-forward-hook)
+	(mh-inc-folder-hook, mh-insert-signature-hook)
+	(mh-kill-folder-suppress-prompt-hooks, mh-letter-mode-hook)
+	(mh-mh-to-mime-hook, mh-search-mode-hook, mh-quit-hook)
+	(mh-refile-msg-hook, mh-show-hook, mh-show-mode-hook)
+	(mh-unseen-updated-hook, mh-min-colors-defined-flag)
+	(mh-folder-address, mh-folder-body)
+	(mh-folder-cur-msg-number, mh-folder-date, mh-folder-deleted)
+	(mh-folder-followup, mh-folder-msg-number, mh-folder-refiled)
+	(mh-folder-sent-to-me-hint, mh-folder-sent-to-me-sender)
+	(mh-folder-subject, mh-folder-tick, mh-folder-to)
+	(mh-search-folder, mh-letter-header-field, mh-show-cc)
+	(mh-show-date, mh-show-from, mh-show-header, mh-show-pgg-bad)
+	(mh-show-pgg-good, mh-show-pgg-unknown, mh-show-signature)
+	(mh-show-subject, mh-show-to, mh-show-xface, mh-speedbar-folder)
+	(mh-speedbar-folder-with-unseen-messages)
+	(mh-speedbar-selected-folder)
+	(mh-speedbar-selected-folder-with-unseen-messages): Move here from
+	deprecated file mh-customize.el.
+
+	* mh-exec.el: Move content into mh-e.el and remove.
+	
+	* mh-folder.el: New file. Contains mh-folder-mode from mh-e.el
+
+	* mh-funcs.el (mh-note-copied, mh-note-printed): Move to new file
+	mh-scan.el.
+	(mh-ephem-message, mh-help, mh-prefix-help): Move to mh-utils.el.
+
+	* mh-gnus.el (mm-uu-dissect-text-parts): Add.
+	(mh-mail-abbrev-make-syntax-table): Move to mh-utils.el and rename
+	to mail-abbrev-make-syntax-table.
+
+	* mh-identity.el (mh-identity-menu): New variable for existing
+	menu.
+	(mh-identity-make-menu-no-autoload): New alias for
+	mh-identity-make-menu which can be called from mh-e.el.
+	(mh-identity-list-set): Move to mh-e.el.
+	(mh-identity-add-menu): New function
+	(mh-insert-identity): Add optional argument maybe-insert so that
+	local variable mh-identity-local does not have to be visible.
+	(mh-identity-handler-default):
+
+	* mh-inc.el (mh-inc-spool-map): Move declaration to mh-e.el (with
+	rest of keymaps). Update key binding for ? to call mh-help with
+	help messages in new argument.
+	(mh-inc-spool-make-no-autoload): New alias for mh-inc-spool-make
+	which can be called from mh-e.el.
+	(mh-inc-spool-list-set): Simplify update of mh-inc-spool-map-help.
+
+	* mh-init.el: Move content into mh-e.el and remove.
+	
+	* mh-junk.el: Update requires, untabify, and add mh-autoload
+	cookies.
+
+	* mh-letter.el: New file. Contains mh-letter-mode from mh-comp.el.
+
+	* mh-limit.el: New file. Contains display limit commands from
+	mh-mime.el.
+
+	* mh-mime.el: Rearrange for consistency with other files.
+	(mh-buffer-data, mh-mm-inline-media-tests): Move here from
+	mh-utils.el.
+	(mh-folder-inline-mime-part, mh-folder-save-mime-part)
+	(mh-folder-toggle-mime-part, mh-toggle-mime-buttons)
+	(mh-goto-next-button): Move here from mh-e.el.
+
+	* mh-print.el: Rearrange for consistency with other files.
+
+	* mh-scan.el: New file. Contains scan line constants and utilities
+	from XXX, mh-funcs, mh-utils.el.
+
+	* mh-search.el: Rearrange for consistency with other files.
+	(mh-search-mode-map): Drop C-c C-f {dr} bindings since these
+	fields which don't exist in the saved header. Replace C-c C-f f
+	with C-c C-f m per mail-mode consistency.
+	(mh-search-mode): Use mh-set-help instead of setting
+	mh-help-messages.
+
+	* mh-seq.el (mh-thread-message, mh-thread-container)
+	(mh-thread-id-hash, mh-thread-subject-hash, mh-thread-id-table)
+	(mh-thread-id-index-map, mh-thread-index-id-map)
+	(mh-thread-scan-line-map, mh-thread-scan-line-map-stack)
+	(mh-thread-subject-container-hash, mh-thread-duplicates)
+	(mh-thread-history, mh-thread-body-width)
+	(mh-thread-find-msg-subject mh-thread-initialize-hash)
+	(mh-thread-initialize, mh-thread-id-container)
+	(mh-thread-remove-parent-link, mh-thread-add-link)
+	(mh-thread-ancestor-p, mh-thread-get-message-container)
+	(mh-thread-get-message, mh-thread-canonicalize-id)
+	(mh-thread-prune-subject, mh-thread-container-subject)
+	(mh-thread-rewind-pruning, mh-thread-prune-containers)
+	(mh-thread-sort-containers, mh-thread-group-by-subject)
+	(mh-thread-process-in-reply-to, mh-thread-set-tables)
+	(mh-thread-update-id-index-maps, mh-thread-generate)
+	(mh-thread-inc, mh-thread-generate-scan-lines)
+	(mh-thread-parse-scan-line, mh-thread-update-scan-line-map)
+	(mh-thread-add-spaces, mh-thread-print-scan-lines)
+	(mh-thread-folder, mh-toggle-threads, mh-thread-forget-message)
+	(mh-thread-current-indentation-level, mh-thread-next-sibling)
+	(mh-thread-previous-sibling, mh-thread-immediate-ancestor)
+	(mh-thread-ancestor, mh-thread-find-children)
+	(mh-message-id-regexp, mh-thread-delete, mh-thread-refile): Move
+	to new file mh-thread.el.
+	(mh-subject-to-sequence, mh-subject-to-sequence-unthreaded)
+	(mh-subject-to-sequence-threaded, mh-edit-pick-expr)
+	(mh-pick-args-list, mh-narrow-to-subject, mh-narrow-to-from)
+	(mh-narrow-to-cc, mh-narrow-to-to, mh-narrow-to-header-field)
+	(mh-current-message-header-field, mh-narrow-to-range)
+	(mh-delete-subject, mh-delete-subject-or-thread): Move to new file
+	mh-limit.el.
+	(mh-iterate-on-messages-in-region, mh-iterate-on-range): Move to
+	mh-acros.el.
+	(mh-internal-seqs, mh-catchup, mh-delete-msg-from-seq)
+	(mh-internal-seq, mh-valid-seq-p, mh-seq-containing-msg)
+	(mh-define-sequence, mh-undefine-sequence)
+	(mh-delete-a-msg-from-seq, mh-delete-seq-locally)
+	(mh-folder-size, mh-folder-size-flist, mh-folder-size-folder)
+	(mh-parse-flist-output-line, mh-read-folder-sequences)
+	(mh-read-msg-list, mh-notate-user-sequences)
+	(mh-remove-cur-notation, mh-add-sequence-notation)
+	(mh-remove-sequence-notation, mh-remove-all-notation): Move here
+	from mh-e.el.
+	(mh-make-seq, mh-seq-name, mh-find-seq, mh-seq-to-msgs)
+	(mh-add-msgs-to-seq, mh-notate): Move here from mh-utils.el.
+
+	* mh-show.el: New file. Contains mh-show-mode from mh-utils.el.
+
+	* mh-speed.el: Rearrange for consistency with other files.
+
+	* mh-thread.el: New file. Contains threading code from mh-seq.el.
+
+	* mh-tool-bar.el: New file. Contains tool bar creation code from
+	deprecated file mh-customize.el.
+
+	* mh-utils.el (recursive-load-depth-limit): Remove setting. No
+	longer needed.
+	(mh-scan-msg-number-regexp, mh-scan-msg-overflow-regexp)
+	(mh-scan-msg-format-regexp, mh-scan-msg-format-string)
+	(mh-scan-msg-search-regexp, mh-cmd-note, mh-note-seq)
+	(mh-update-scan-format, mh-msg-num-width): Move to new file
+	mh-scan.el.
+	(mh-show-buffer-mode-line-buffer-id, mh-letter-header-font-lock)
+	(mh-header-field-font-lock, mh-header-to-font-lock)
+	(mh-header-cc-font-lock, mh-header-subject-font-lock)
+	(mh-show-font-lock-keywords)
+	(mh-show-font-lock-keywords-with-cite)
+	(mh-show-font-lock-fontify-region)
+	(mh-gnus-article-highlight-citation, mh-showing-with-headers)
+	(mh-start-of-uncleaned-message, mh-invalidate-show-buffer)
+	(mh-unvisit-file, mh-defun-show-buffer, mh-show-mode-map)
+	(mh-show-sequence-menu, mh-show-message-menu)
+	(mh-show-folder-menu, mh-show-mode, mh-show-addr)
+	(mh-maybe-show, mh-show, mh-show-msg, mh-show-unquote-From)
+	(mh-msg-folder, mh-display-msg, mh-clean-msg-header): Move to new
+	file mh-show.el.
+	(mh-mail-header-separator, mh-signature-separator-regexp)
+	(mh-signature-separator, mh-globals-hash, mh-user-path)
+	(mh-draft-folder, mh-unseen-seq, mh-previous-seq, mh-inbox)
+	(mh-previous-window-config, mh-current-folder mh-show-buffer)
+	(mh-showing-mode, mh-show-mode-map, mh-show-folder-buffer)
+	(mh-showing-mode, mh-seq-list, mh-seen-list, mh-summary-height)
+	(mh-list-to-string, mh-list-to-string-1): Move to mh-e.el.
+	(mh-buffer-data, mh-mm-inline-media-tests): Move to mh-mime.el.
+	(mh-address-mail-regexp, mh-goto-address-find-address-at-point):
+	Move to mh-alias.el.
+	(mh-letter-font-lock-keywords): Move to new file mh-letter.el.
+	(mh-folder-filename, mh-msg-count, mh-recenter, mh-msg-filename)
+	(mh-show-mouse, mh-modify, mh-goto-msg, mh-set-folder-modified-p):
+	Move to new file mh-folder.el.
+	(with-mh-folder-updating, mh-in-show-buffer)
+	(mh-do-at-event-location, mh-seq-msgs): Moved to mh-acros.el.
+	(mh-make-seq, mh-seq-name, mh-notate, mh-find-seq)
+	(mh-seq-to-msgs, mh-add-msgs-to-seq, mh-canonicalize-sequence):
+	Moved to mh-seq.el.
+	(mh-show-xface-function, mh-uncompface-executable, mh-face-to-png)
+	(mh-uncompface, mh-icontopbm, mh-face-foreground-compat)
+	(mh-face-background-compat, mh-face-display-function)
+	(mh-show-xface, mh-picon-directory-list)
+	(mh-picon-existing-directory-list)
+	(mh-picon-cache, mh-picon-image-types)
+	(mh-picon-set-directory-list, mh-picon-get-image)
+	(mh-picon-file-contents, mh-picon-generate-path)
+	(mh-x-image-cache-directory, mh-x-image-scaling-function)
+	(mh-wget-executable, mh-wget-choice, mh-wget-option)
+	(mh-x-image-temp-file, mh-x-image-url, mh-x-image-marker)
+	(mh-x-image-url-cache-file, mh-x-image-scale-with-pnm)
+	(mh-x-image-scale-with-convert)
+	(url-unreserved-chars, url-hexify-string)
+	(mh-x-image-url-cache-canonicalize)
+	(mh-x-image-set-download-state, mh-x-image-get-download-state)
+	(mh-x-image-url-fetch-image, mh-x-image-display)
+	(mh-x-image-scale-and-display, mh-x-image-url-sane-p)
+	(mh-x-image-url-display): Move to new file mh-xface.el.
+	(mh-logo-display): Call mh-image-load-path.
+	(mh-find-path-run, mh-find-path): Move here from deprecated file
+	mh-init.el.
+	(mh-help-messages): Now an alist of modes to an alist of messages.
+	(mh-set-help): New function used to set mh-help-messages
+	(mh-help): Adjust for new format of mh-help-messages. Add
+	help-messages argument.
+	(mh-prefix-help): Refactor to use mh-help.
+	(mh-coalesce-msg-list, mh-greaterp, mh-lessp): Move here from
+	mh-e.el.
+	(mh-clear-sub-folders-cache): New function added to avoid exposing
+	mh-sub-folders-cache variable.
+
+	* mh-xface.el: New file. Contains X-Face and Face header field
+	display routines from mh-utils.el.
+
 2006-01-17  Bill Wohler  <wohler@newt.com>
 
 	* mh-acros.el (assoc-string): Fix typo in argument.
--- a/lisp/mh-e/mh-acros.el	Thu Jan 26 02:23:05 2006 +0000
+++ b/lisp/mh-e/mh-acros.el	Wed Feb 01 10:07:17 2006 +0000
@@ -1,4 +1,4 @@
-;;; mh-acros.el --- Macros used in MH-E
+;;; mh-acros.el --- macros used in MH-E
 
 ;; Copyright (C) 2004, 2006 Free Software Foundation, Inc.
 
@@ -26,74 +26,88 @@
 
 ;;; Commentary:
 
-;; This file contains most, if not all, macros. It is so named with a
-;; silent "m" so that it is compiled first. Otherwise, "make
-;; recompile" in CVS Emacs may use compiled files with stale macro
-;; definitions.
+;; This file contains all macros that are used in more than one file.
+;; If you run "make recompile" in CVS Emacs and see the message
+;; "Source is newer than compiled," it is a sign that macro probably
+;; needs to be moved here.
 
-;; This file must always be included like this:
-;;
-;;   (eval-when-compile (require 'mh-acros))
+;; Historically, it was so named with a silent "m" so that it would be
+;; compiled first. Otherwise, "make recompile" in CVS Emacs would use
+;; compiled files with stale macro definitions. Later, no-byte-compile
+;; was added to the Local Variables section to avoid this problem and
+;; because it's pointless to compile a file full of macros. But we
+;; kept the name.
 
 ;;; Change Log:
 
 ;;; Code:
 
 (require 'cl)
-(require 'advice)
+
+
 
-;; The Emacs coding conventions require that the cl package not be required at
-;; runtime. However, the cl package in versions of Emacs prior to 21.4 left cl
-;; routines in their macro expansions. Use mh-require-cl to provide the cl
-;; routines in the best way possible.
+;;; Compatibility
+
+;;;###mh-autoload
 (defmacro mh-require-cl ()
   "Macro to load \"cl\" if needed.
-Some versions of \"cl\" produce code for the expansion of
-\(setf (gethash ...) ...) that uses functions in \"cl\" at run
-time. This macro recognizes that and loads \"cl\" where
-appropriate."
+
+Emacs coding conventions require that the \"cl\" package not be
+required at runtime. However, the \"cl\" package in Emacs 21.4
+and earlier left \"cl\" routines in their macro expansions. In
+particular, the expansion of (setf (gethash ...) ...) used
+functions in \"cl\" at run time. This macro recognizes that and
+loads \"cl\" appropriately."
   (if (eq (car (macroexpand '(setf (gethash foo bar) baz))) 'cl-puthash)
       `(require 'cl)
     `(eval-when-compile (require 'cl))))
 
-;; Macros to generate correct code for different emacs variants
-
+;;;###mh-autoload
 (defmacro mh-do-in-gnu-emacs (&rest body)
   "Execute BODY if in GNU Emacs."
   (unless (featurep 'xemacs) `(progn ,@body)))
 (put 'mh-do-in-gnu-emacs 'lisp-indent-hook 'defun)
 
+;;;###mh-autoload
 (defmacro mh-do-in-xemacs (&rest body)
-  "Execute BODY if in GNU Emacs."
+  "Execute BODY if in XEmacs."
   (when (featurep 'xemacs) `(progn ,@body)))
 (put 'mh-do-in-xemacs 'lisp-indent-hook 'defun)
 
+;;;###mh-autoload
 (defmacro mh-funcall-if-exists (function &rest args)
   "Call FUNCTION with ARGS as parameters if it exists."
   (when (fboundp function)
     `(when (fboundp ',function)
        (funcall ',function ,@args))))
 
-(defmacro mh-defun-compat (function arg-list &rest body)
-  "This is a macro to define functions which are not defined.
-It is used for functions which were added to Emacs recently.
-If FUNCTION is not defined then it is defined to have argument
-list, ARG-LIST and body, BODY."
+;;;###mh-autoload
+(defmacro mh-defun-compat (name function arg-list &rest body)
+  "Create function NAME.
+If FUNCTION exists, then NAME becomes an alias for FUNCTION.
+Otherwise, create function NAME with ARG-LIST and BODY."
   (let ((defined-p (fboundp function)))
-    (unless defined-p
-      `(defun ,function ,arg-list ,@body))))
+    (if defined-p
+        `(defalias ',name ',function)
+      `(defun ,name ,arg-list ,@body))))
 (put 'mh-defun-compat 'lisp-indent-function 'defun)
 
-(defmacro mh-defmacro-compat (function arg-list &rest body)
-  "This is a macro to define functions which are not defined.
-It is used for macros which were added to Emacs recently.
-If FUNCTION is not defined then it is defined to have argument
-list, ARG-LIST and body, BODY."
-  (let ((defined-p (fboundp function)))
-    (unless defined-p
-      `(defmacro ,function ,arg-list ,@body))))
+;;;###mh-autoload
+(defmacro mh-defmacro-compat (name macro arg-list &rest body)
+  "Create macro NAME.
+If MACRO exists, then NAME becomes an alias for MACRO.
+Otherwise, create macro NAME with ARG-LIST and BODY."
+  (let ((defined-p (fboundp macro)))
+    (if defined-p
+        `(defalias ',name ',macro)
+      `(defmacro ,name ,arg-list ,@body))))
 (put 'mh-defmacro-compat 'lisp-indent-function 'defun)
 
+
+
+;;; Miscellaneous
+
+;;;###mh-autoload
 (defmacro mh-make-local-hook (hook)
   "Make HOOK local if needed.
 XEmacs and versions of GNU Emacs before 21.1 require
@@ -102,6 +116,7 @@
              (not (get 'make-local-hook 'byte-obsolete-info)))
     `(make-local-hook ,hook)))
 
+;;;###mh-autoload
 (defmacro mh-mark-active-p (check-transient-mark-mode-flag)
   "A macro that expands into appropriate code in XEmacs and nil in GNU Emacs.
 In GNU Emacs if CHECK-TRANSIENT-MARK-MODE-FLAG is non-nil then
@@ -114,6 +129,10 @@
          `(and (boundp 'transient-mark-mode) transient-mark-mode
                (boundp 'mark-active) mark-active))))
 
+;; Shush compiler.
+(eval-when-compile (mh-do-in-xemacs (defvar struct) (defvar x) (defvar y)))
+
+;;;###mh-autoload
 (defmacro mh-defstruct (name-spec &rest fields)
   "Replacement for `defstruct' from the \"cl\" package.
 The `defstruct' in the \"cl\" library produces compiler warnings,
@@ -150,15 +169,145 @@
                           (list 'nth ,x z)))
        (quote ,struct-name))))
 
-(unless (fboundp 'assoc-string)
-  (defsubst assoc-string (key list case-fold)
-    "Like `assoc' but specifically for strings.
-Case is ignored if CASE-FOLD is non-nil.
-This function added by MH-E for Emacs versions that lack
-`assoc-string', introduced in Emacs 22."
-    (if case-fold
-        (assoc-ignore-case key list)
-      (assoc key list))))
+;;;###mh-autoload
+(defmacro with-mh-folder-updating (save-modification-flag &rest body)
+  "Format is (with-mh-folder-updating (SAVE-MODIFICATION-FLAG) &body BODY).
+Execute BODY, which can modify the folder buffer without having to
+worry about file locking or the read-only flag, and return its result.
+If SAVE-MODIFICATION-FLAG is non-nil, the buffer's modification flag
+is unchanged, otherwise it is cleared."
+  (setq save-modification-flag (car save-modification-flag)) ; CL style
+  `(prog1
+       (let ((mh-folder-updating-mod-flag (buffer-modified-p))
+             (buffer-read-only nil)
+             (buffer-file-name nil))    ;don't let the buffer get locked
+         (prog1
+             (progn
+               ,@body)
+           (mh-set-folder-modified-p mh-folder-updating-mod-flag)))
+     ,@(if (not save-modification-flag)
+           '((mh-set-folder-modified-p nil)))))
+(put 'with-mh-folder-updating 'lisp-indent-hook 'defun)
+
+;;;###mh-autoload
+(defmacro mh-in-show-buffer (show-buffer &rest body)
+  "Format is (mh-in-show-buffer (SHOW-BUFFER) &body BODY).
+Display buffer SHOW-BUFFER in other window and execute BODY in it.
+Stronger than `save-excursion', weaker than `save-window-excursion'."
+  (setq show-buffer (car show-buffer))  ; CL style
+  `(let ((mh-in-show-buffer-saved-window (selected-window)))
+     (switch-to-buffer-other-window ,show-buffer)
+     (if mh-bury-show-buffer-flag (bury-buffer (current-buffer)))
+     (unwind-protect
+         (progn
+           ,@body)
+       (select-window mh-in-show-buffer-saved-window))))
+(put 'mh-in-show-buffer 'lisp-indent-hook 'defun)
+
+;;;###mh-autoload
+(defmacro mh-do-at-event-location (event &rest body)
+  "Switch to the location of EVENT and execute BODY.
+After BODY has been executed return to original window. The
+modification flag of the buffer in the event window is
+preserved."
+  (let ((event-window (make-symbol "event-window"))
+        (event-position (make-symbol "event-position"))
+        (original-window (make-symbol "original-window"))
+        (original-position (make-symbol "original-position"))
+        (modified-flag (make-symbol "modified-flag")))
+    `(save-excursion
+       (let* ((,event-window
+               (or (mh-funcall-if-exists posn-window (event-start ,event))
+                   (mh-funcall-if-exists event-window ,event)))
+              (,event-position
+               (or (mh-funcall-if-exists posn-point (event-start ,event))
+                   (mh-funcall-if-exists event-closest-point ,event)))
+              (,original-window (selected-window))
+              (,original-position (progn
+                                   (set-buffer (window-buffer ,event-window))
+                                   (set-marker (make-marker) (point))))
+              (,modified-flag (buffer-modified-p))
+              (buffer-read-only nil))
+         (unwind-protect (progn
+                           (select-window ,event-window)
+                           (goto-char ,event-position)
+                           ,@body)
+           (set-buffer-modified-p ,modified-flag)
+           (goto-char ,original-position)
+           (set-marker ,original-position nil)
+           (select-window ,original-window))))))
+(put 'mh-do-at-event-location 'lisp-indent-hook 'defun)
+
+
+
+;;; Sequences and Ranges
+
+;;;###mh-autoload
+(defmacro mh-seq-msgs (sequence)
+  "Extract messages from the given SEQUENCE."
+  (list 'cdr sequence))
+
+;;;###mh-autoload
+(defmacro mh-iterate-on-messages-in-region (var begin end &rest body)
+  "Iterate over region.
+
+VAR is bound to the message on the current line as we loop
+starting from BEGIN till END. In each step BODY is executed.
+
+If VAR is nil then the loop is executed without any binding."
+  (unless (symbolp var)
+    (error "Can not bind the non-symbol %s" var))
+  (let ((binding-needed-flag var))
+    `(save-excursion
+       (goto-char ,begin)
+       (beginning-of-line)
+       (while (and (<= (point) ,end) (not (eobp)))
+         (when (looking-at mh-scan-valid-regexp)
+           (let ,(if binding-needed-flag `((,var (mh-get-msg-num t))) ())
+             ,@body))
+         (forward-line 1)))))
+(put 'mh-iterate-on-messages-in-region 'lisp-indent-hook 'defun)
+
+;;;###mh-autoload
+(defmacro mh-iterate-on-range (var range &rest body)
+  "Iterate an operation over a region or sequence.
+
+VAR is bound to each message in turn in a loop over RANGE, which
+can be a message number, a list of message numbers, a sequence, a
+region in a cons cell, or a MH range (something like last:20) in
+a string. In each iteration, BODY is executed.
+
+The parameter RANGE is usually created with
+`mh-interactive-range' in order to provide a uniform interface to
+MH-E functions."
+  (unless (symbolp var)
+    (error "Can not bind the non-symbol %s" var))
+  (let ((binding-needed-flag var)
+        (msgs (make-symbol "msgs"))
+        (seq-hash-table (make-symbol "seq-hash-table")))
+    `(cond ((numberp ,range)
+            (when (mh-goto-msg ,range t t)
+              (let ,(if binding-needed-flag `((,var ,range)) ())
+                ,@body)))
+           ((and (consp ,range)
+                 (numberp (car ,range)) (numberp (cdr ,range)))
+            (mh-iterate-on-messages-in-region ,var
+              (car ,range) (cdr ,range)
+              ,@body))
+           (t (let ((,msgs (cond ((and ,range (symbolp ,range))
+                                  (mh-seq-to-msgs ,range))
+                                 ((stringp ,range)
+                                  (mh-translate-range mh-current-folder
+                                                      ,range))
+                                 (t ,range)))
+                    (,seq-hash-table (make-hash-table)))
+                (dolist (msg ,msgs)
+                  (setf (gethash msg ,seq-hash-table) t))
+                (mh-iterate-on-messages-in-region v (point-min) (point-max)
+                  (when (gethash v ,seq-hash-table)
+                    (let ,(if binding-needed-flag `((,var v)) ())
+                      ,@body))))))))
+(put 'mh-iterate-on-range 'lisp-indent-hook 'defun)
 
 (provide 'mh-acros)
 
--- a/lisp/mh-e/mh-alias.el	Thu Jan 26 02:23:05 2006 +0000
+++ b/lisp/mh-e/mh-alias.el	Wed Feb 01 10:07:17 2006 +0000
@@ -1,5 +1,5 @@
 ;;; mh-alias.el --- MH-E mail alias completion and expansion
-;;
+
 ;; Copyright (C) 1994, 1995, 1996, 1997,
 ;;  2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
 
@@ -31,24 +31,9 @@
 
 ;;; Code:
 
-;;(message "> mh-alias")
-(eval-when-compile (require 'mh-acros))
+(require 'mh-e)
+
 (mh-require-cl)
-(require 'mh-buffers)
-(require 'mh-e)
-;;(message "< mh-alias")
-(load "cmr" t t)                        ; Non-fatal dependency for
-					; completing-read-multiple.
-(eval-when-compile (defvar mail-abbrev-syntax-table))
-
-
-
-;;; Autoloads
-
-(eval-when (compile load eval)
-  (ignore-errors
-    (require 'mailabbrev)
-    (require 'multi-prompt)))
 
 (defvar mh-alias-alist 'not-read
   "Alist of MH aliases.")
@@ -61,7 +46,7 @@
 (defvar mh-alias-read-address-map nil)
 (unless mh-alias-read-address-map
   (setq mh-alias-read-address-map
-	(copy-keymap minibuffer-local-completion-map))
+        (copy-keymap minibuffer-local-completion-map))
   (define-key mh-alias-read-address-map
     "," 'mh-alias-minibuffer-confirm-address)
   (define-key mh-alias-read-address-map " " 'self-insert-command))
@@ -77,6 +62,11 @@
 automatically included. You can update the alias list manually using
 \\[mh-alias-reload].")
 
+;; Copy of `goto-address-mail-regexp'.
+(defvar mh-address-mail-regexp
+  "[-a-zA-Z0-9._]+@\\([-a-zA-z0-9_]+\\.\\)+[a-zA-Z0-9]+"
+  "A regular expression probably matching an e-mail address.")
+
 
 
 ;;; Alias Loading
@@ -179,13 +169,12 @@
                     (if (string-equal username realname)
                         (concat "<" username ">")
                       (concat realname " <" username ">"))))
-              (when (not (assoc-string alias-name mh-alias-alist t))
+              (when (not (mh-assoc-string alias-name mh-alias-alist t))
                 (setq passwd-alist (cons (list alias-name alias-translation)
                                          passwd-alist)))))))
         (forward-line 1)))
     passwd-alist))
 
-;;;###mh-autoload
 (defun mh-alias-reload ()
   "Reload MH aliases.
 
@@ -209,12 +198,12 @@
       (cond
        ((looking-at "^[ \t]"))          ;Continuation line
        ((looking-at "\\(.+\\): .+: .*$") ; A new -blind- MH alias
-        (when (not (assoc-string (match-string 1) mh-alias-blind-alist t))
+        (when (not (mh-assoc-string (match-string 1) mh-alias-blind-alist t))
           (setq mh-alias-blind-alist
                 (cons (list (match-string 1)) mh-alias-blind-alist))
           (setq mh-alias-alist (cons (list (match-string 1)) mh-alias-alist))))
        ((looking-at "\\(.+\\): .*$")    ; A new MH alias
-        (when (not (assoc-string (match-string 1) mh-alias-alist t))
+        (when (not (mh-assoc-string (match-string 1) mh-alias-alist t))
           (setq mh-alias-alist
                 (cons (list (match-string 1)) mh-alias-alist)))))
       (forward-line 1)))
@@ -225,7 +214,7 @@
           user)
       (while local-users
         (setq user (car local-users))
-        (if (not (assoc-string (car user) mh-alias-alist t))
+        (if (not (mh-assoc-string (car user) mh-alias-alist t))
             (setq mh-alias-alist (append mh-alias-alist (list user))))
         (setq local-users (cdr local-users)))))
   (run-hooks 'mh-alias-reloaded-hook)
@@ -262,18 +251,21 @@
   "Return expansion for ALIAS.
 Blind aliases or users from /etc/passwd are not expanded."
   (cond
-   ((assoc-string alias mh-alias-blind-alist t)
+   ((mh-assoc-string alias mh-alias-blind-alist t)
     alias)                              ; Don't expand a blind alias
-   ((assoc-string alias mh-alias-passwd-alist t)
-    (cadr (assoc-string alias mh-alias-passwd-alist t)))
+   ((mh-assoc-string alias mh-alias-passwd-alist t)
+    (cadr (mh-assoc-string alias mh-alias-passwd-alist t)))
    (t
     (mh-alias-ali alias))))
 
+(require 'crm nil t)                   ; completing-read-multiple
+(require 'multi-prompt nil t)
+
 ;;;###mh-autoload
 (defun mh-read-address (prompt)
   "Read an address from the minibuffer with PROMPT."
   (mh-alias-reload-maybe)
-  (if (not mh-alias-alist)		; If still no aliases, just prompt
+  (if (not mh-alias-alist)              ; If still no aliases, just prompt
       (read-string prompt)
     (let* ((minibuffer-local-completion-map mh-alias-read-address-map)
            (completion-ignore-case mh-alias-completion-ignore-case-flag)
@@ -300,7 +292,7 @@
       (let* ((case-fold-search t)
              (beg (mh-beginning-of-word))
              (the-name (buffer-substring-no-properties beg (point))))
-        (if (assoc-string the-name mh-alias-alist t)
+        (if (mh-assoc-string the-name mh-alias-alist t)
             (message "%s -> %s" the-name (mh-alias-expand the-name))
           ;; Check if if was a single word likely to be an alias
           (if (and (equal mh-alias-flash-on-comma 1)
@@ -308,8 +300,6 @@
               (message "No alias for %s" the-name))))))
   (self-insert-command 1))
 
-(mh-do-in-xemacs (defvar mail-abbrevs))
-
 ;;;###mh-autoload
 (defun mh-alias-letter-expand-alias ()
   "Expand mail alias before point."
@@ -323,9 +313,10 @@
              (expansion (mh-alias-expand (buffer-substring begin end))))
         (delete-region begin end)
         (insert expansion)))))
+
 
 
-;;; Adding addresses to alias file.
+;;; Alias File Updating
 
 (defun mh-alias-suggest-alias (string &optional no-comma-swap)
   "Suggest an alias for STRING.
@@ -451,8 +442,8 @@
                                      (mh-alias-filenames t)))))
       (cond
        ((not autolist)
-        (error "No writable alias file.
-Set `mh-alias-insert-file' or the \"Aliasfile:\" profile component"))
+        (error "No writable alias file;
+set `mh-alias-insert-file' or the \"Aliasfile:\" profile component"))
        ((not (elt autolist 1))        ; Only one entry, use it
         (car autolist))
        ((or (not alias)
@@ -549,7 +540,6 @@
     (insert (format "%s: %s\n" alias address))
     (save-buffer)))
 
-;;;###mh-autoload
 (defun mh-alias-add-alias (alias address)
   "Add ALIAS for ADDRESS in personal alias file.
 
@@ -602,7 +592,6 @@
            (alias (mh-alias-suggest-alias address)))
       (mh-alias-add-alias alias address))))
 
-;;;###mh-autoload
 (defun mh-alias-add-address-under-point ()
   "Insert an alias for address under point."
   (interactive)
@@ -611,7 +600,19 @@
         (mh-alias-add-alias nil address)
       (message "No email address found under point"))))
 
-;;;###mh-autoload
+;; From goto-addr.el, which we don't want to force-load on users.
+(defun mh-goto-address-find-address-at-point ()
+  "Find e-mail address around or before point.
+
+Then search backwards to beginning of line for the start of an
+e-mail address. If no e-mail address found, return nil."
+  (re-search-backward "[^-_A-z0-9.@]" (line-beginning-position) 'lim)
+  (if (or (looking-at mh-address-mail-regexp) ; already at start
+          (and (re-search-forward mh-address-mail-regexp
+                                  (line-end-position) 'lim)
+               (goto-char (match-beginning 0))))
+      (match-string-no-properties 0)))
+
 (defun mh-alias-apropos (regexp)
   "Show all aliases or addresses that match a regular expression REGEXP."
   (interactive "sAlias regexp: ")
@@ -668,6 +669,21 @@
           (princ "\nLocal User Aliases:\n\n")
           (princ passwd-matches))))))
 
+(defun mh-folder-line-matches-show-buffer-p ()
+  "Return t if the message under point in folder-mode is in the show buffer.
+Return nil in any other circumstance (no message under point, no
+show buffer, the message in the show buffer doesn't match."
+  (and (eq major-mode 'mh-folder-mode)
+       (mh-get-msg-num nil)
+       mh-show-buffer
+       (get-buffer mh-show-buffer)
+       (buffer-file-name (get-buffer mh-show-buffer))
+       (string-match ".*/\\([0-9]+\\)$"
+                     (buffer-file-name (get-buffer mh-show-buffer)))
+       (string-equal
+        (match-string 1 (buffer-file-name (get-buffer mh-show-buffer)))
+        (int-to-string (mh-get-msg-num nil)))))
+
 (provide 'mh-alias)
 
 ;; Local Variables:
--- a/lisp/mh-e/mh-buffers.el	Thu Jan 26 02:23:05 2006 +0000
+++ b/lisp/mh-e/mh-buffers.el	Wed Feb 01 10:07:17 2006 +0000
@@ -1,4 +1,4 @@
-;;; mh-buffers.el --- Temporary buffer constants and utilities used by MH-E
+;;; mh-buffers.el --- MH-E buffer constants and utilities
 
 ;; Copyright (C) 1993, 1995, 1997,
 ;;  2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
@@ -27,8 +27,6 @@
 
 ;;; Commentary:
 
-;; Temporary buffer constants and utilities used by MH-E.
-
 ;;; Change Log:
 
 ;;; Code:
--- a/lisp/mh-e/mh-comp.el	Thu Jan 26 02:23:05 2006 +0000
+++ b/lisp/mh-e/mh-comp.el	Wed Feb 01 10:07:17 2006 +0000
@@ -1,4 +1,4 @@
-;;; mh-comp.el --- MH-E functions for composing messages
+;;; mh-comp.el --- MH-E functions for composing and sending messages
 
 ;; Copyright (C) 1993, 1995, 1997,
 ;;  2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
@@ -27,60 +27,27 @@
 
 ;;; Commentary:
 
-;; Internal support for MH-E package.
+;; This file includes the functions in the MH-Folder maps that get us
+;; into MH-Letter mode, as well the functions in the MH-Letter mode
+;; that are used to send the mail. Other that those, functions that
+;; are needed in mh-letter.el should be found there.
 
 ;;; Change Log:
 
 ;;; Code:
 
-;;(message "> mh-comp")
-(eval-when-compile (require 'mh-acros))
-(mh-require-cl)
+(require 'mh-e)
+(require 'mh-gnus)                      ;needed because mh-gnus.el not compiled
+(require 'mh-scan)
 
-(require 'easymenu)
-(require 'gnus-util)
-(require 'mh-buffers)
-(require 'mh-e)
-(require 'mh-gnus)
+(require 'sendmail)
 
-(eval-when (compile load eval)
-  (ignore-errors (require 'mailabbrev)))
-;;(message "< mh-comp")
+(autoload 'easy-menu-add "easymenu")
+(autoload 'mml-insert-tag "mml")
 
 
 
-;;; Autoloads
-
-(autoload 'mail-mode-fill-paragraph "sendmail")
-(autoload 'mm-handle-displayed-p "mm-decode")
-
-(autoload 'sc-cite-original "sc"
-  "Workhorse citing function which performs the initial citation.
-This is callable from the various mail and news readers' reply
-function according to the agreed upon standard.  See `sc-describe'
-for more details.  `sc-cite-original' does not do any yanking of the
-original message but it does require a few things:
-
-     1) The reply buffer is the current buffer.
-
-     2) The original message has been yanked and inserted into the
-        reply buffer.
-
-     3) Verbose mail headers from the original message have been
-        inserted into the reply buffer directly before the text of the
-        original message.
-
-     4) Point is at the beginning of the verbose headers.
-
-     5) Mark is at the end of the body of text to be cited.
-
-For Emacs 19's, the region need not be active (and typically isn't
-when this function is called.  Also, the hook `sc-pre-hook' is run
-before, and `sc-post-hook' is run after the guts of this function.")
-
-
-
-;;; Site customization (see also mh-utils.el):
+;;; Site Customization
 
 (defvar mh-send-prog "send"
   "Name of the MH send program.
@@ -93,26 +60,7 @@
 
 
 
-;;; Scan Line Formats
-
-(defvar mh-note-repl ?-
-  "Messages that have been replied to are marked by this character.")
-
-(defvar mh-note-forw ?F
-  "Messages that have been forwarded are marked by this character.")
-
-(defvar mh-note-dist ?R
-  "Messages that have been redistributed are marked by this character.")
-
-(defvar mh-yank-hooks nil
-  "Obsolete hook for modifying a citation just inserted in the mail buffer.
-
-Each hook function can find the citation between point and mark.
-And each hook function should leave point and mark around the
-citation text as modified.
-
-This is a normal hook, misnamed for historical reasons. It is
-semi-obsolete and is only used if `mail-citation-hook' is nil.")
+;;; Variables
 
 (defvar mh-comp-formfile "components"
   "Name of file to be used as a skeleton for composing messages.
@@ -145,7 +93,7 @@
           (regexp-opt
            '("Content-Type: message/rfc822" ;MIME MDN
              "------ This is a copy of the message, including all the headers. ------";from exim
-	     "--- Below this line is a copy of the message."; from qmail
+             "--- Below this line is a copy of the message."; from qmail
              "   ----- Unsent message follows -----" ;from sendmail V5
              " --------Unsent Message below:" ; from sendmail at BU
              "   ----- Original message follows -----" ;from sendmail V8
@@ -161,21 +109,6 @@
   "Regexp of header lines to remove before offering a message as a new draft\\<mh-folder-mode-map>.
 Used by the \\[mh-edit-again] and \\[mh-extract-rejected-mail] commands.")
 
-(defvar mh-to-field-choices '(("a" . "Mail-Reply-To:")
-                              ("b" . "Bcc:")
-                              ("c" . "Cc:")
-                              ("d" . "Dcc:")
-                              ("f" . "Fcc:")
-                              ("l" . "Mail-Followup-To:")
-                              ("m" . "From:")
-                              ("r" . "Reply-To:")
-                              ("s" . "Subject:")
-                              ("t" . "To:"))
-  "Alist of (final-character . field-name) choices for `mh-to-field'.")
-
-(defvar mh-letter-mode-map (copy-keymap text-mode-map)
-  "Keymap for composing mail.")
-
 (defvar mh-letter-mode-syntax-table nil
   "Syntax table used by MH-E while in MH-Letter mode.")
 
@@ -185,12 +118,6 @@
         (make-syntax-table text-mode-syntax-table))
   (modify-syntax-entry ?% "." mh-letter-mode-syntax-table))
 
-(defvar mh-sent-from-folder nil
-  "Folder of msg assoc with this letter.")
-
-(defvar mh-sent-from-msg nil
-  "Number of msg assoc with this letter.")
-
 (defvar mh-send-args nil
   "Extra args to pass to \"send\" command.")
 
@@ -204,6 +131,10 @@
   "Buffer-local variable set when `mh-insert-auto-fields' called successfully.")
 (make-variable-buffer-local 'mh-insert-auto-fields-done-local)
 
+
+
+;;; MH-E Entry Points
+
 ;;;###autoload
 (defun mh-smail ()
   "Compose a message with the MH mail system.
@@ -220,6 +151,18 @@
   (mh-find-path)
   (call-interactively 'mh-send-other-window))
 
+(defun mh-send-other-window (to cc subject)
+  "Compose a message in another window.
+
+See `mh-send' for more information and a description of how the
+TO, CC, and SUBJECT arguments are used."
+  (interactive (list
+                (mh-interactive-read-address "To: ")
+                (mh-interactive-read-address "Cc: ")
+                (mh-interactive-read-string "Subject: ")))
+  (let ((pop-up-windows t))
+    (mh-send-sub to cc subject (current-window-configuration))))
+
 (defvar mh-error-if-no-draft nil)       ;raise error over using old draft
 
 ;;;###autoload
@@ -271,6 +214,117 @@
                         (cdr (car other-headers)))
       (setq other-headers (cdr other-headers)))))
 
+;; Shush compiler.
+(eval-when-compile (mh-do-in-xemacs (defvar sendmail-coding-system)))
+
+;;;###autoload
+(defun mh-send-letter (&optional arg)
+  "Save draft and send message.
+
+When you are all through editing a message, you send it with this
+command. You can give a prefix argument ARG to monitor the first stage
+of the delivery\; this output can be found in a buffer called \"*MH-E
+Mail Delivery*\".
+
+The hook `mh-before-send-letter-hook' is run at the beginning of
+this command. For example, if you want to check your spelling in
+your message before sending, add the function `ispell-message'.
+
+In case the MH \"send\" program is installed under a different name,
+use `mh-send-prog' to tell MH-E the name."
+  (interactive "P")
+  (run-hooks 'mh-before-send-letter-hook)
+  (if (and (mh-insert-auto-fields t)
+           mh-auto-fields-prompt-flag
+           (goto-char (point-min)))
+      (if (not (y-or-n-p "Auto fields inserted, send? "))
+          (error "Send aborted")))
+  (cond ((mh-mh-directive-present-p)
+         (mh-mh-to-mime))
+        ((or (mh-mml-tag-present-p) (not (mh-ascii-buffer-p)))
+         (mh-mml-to-mime)))
+  (save-buffer)
+  (message "Sending...")
+  (let ((draft-buffer (current-buffer))
+        (file-name buffer-file-name)
+        (config mh-previous-window-config)
+        (coding-system-for-write
+         (if (and (local-variable-p 'buffer-file-coding-system
+                                    (current-buffer)) ;XEmacs needs two args
+                  ;; We're not sure why, but buffer-file-coding-system
+                  ;; tends to get set to undecided-unix.
+                  (not (memq buffer-file-coding-system
+                             '(undecided undecided-unix undecided-dos))))
+             buffer-file-coding-system
+           (or (and (boundp 'sendmail-coding-system) sendmail-coding-system)
+               (and (boundp 'default-buffer-file-coding-system )
+                    default-buffer-file-coding-system)
+               'iso-latin-1))))
+    ;; Adding a Message-ID field looks good, makes it easier to search for
+    ;; message in your +outbox, and best of all doesn't break threading for
+    ;; the recipient if you reply to a message in your +outbox.
+    (setq mh-send-args (concat "-msgid " mh-send-args))
+    ;; The default BCC encapsulation will make a MIME message unreadable.
+    ;; With nmh use the -mime arg to prevent this.
+    (if (and (mh-variant-p 'nmh)
+             (mh-goto-header-field "Bcc:")
+             (mh-goto-header-field "Content-Type:"))
+        (setq mh-send-args (concat "-mime " mh-send-args)))
+    (cond (arg
+           (pop-to-buffer mh-mail-delivery-buffer)
+           (erase-buffer)
+           (mh-exec-cmd-output mh-send-prog t "-watch" "-nopush"
+                               "-nodraftfolder" mh-send-args file-name)
+           (goto-char (point-max))      ; show the interesting part
+           (recenter -1)
+           (set-buffer draft-buffer))   ; for annotation below
+          (t
+           (mh-exec-cmd-daemon mh-send-prog nil "-nodraftfolder" "-noverbose"
+                               mh-send-args file-name)))
+    (if mh-annotate-char
+        (mh-annotate-msg mh-sent-from-msg
+                         mh-sent-from-folder
+                         mh-annotate-char
+                         "-component" mh-annotate-field
+                         "-text" (format "\"%s %s\""
+                                         (mh-get-header-field "To:")
+                                         (mh-get-header-field "Cc:"))))
+
+    (cond ((or (not arg)
+               (y-or-n-p "Kill draft buffer? "))
+           (kill-buffer draft-buffer)
+           (if config
+               (set-window-configuration config))))
+    (if arg
+        (message "Sending...done")
+      (message "Sending...backgrounded"))))
+
+;;;###autoload
+(defun mh-fully-kill-draft ()
+  "Quit editing and delete draft message.
+
+If for some reason you are not happy with the draft, you can use
+this command to kill the draft buffer and delete the draft
+message. Use the command \\[kill-buffer] if you don't want to
+delete the draft message."
+  (interactive)
+  (if (y-or-n-p "Kill draft message? ")
+      (let ((config mh-previous-window-config))
+        (if (file-exists-p buffer-file-name)
+            (delete-file buffer-file-name))
+        (set-buffer-modified-p nil)
+        (kill-buffer (buffer-name))
+        (message "")
+        (if config
+            (set-window-configuration config)))
+    (error "Message not killed")))
+
+
+
+;;; MH-Folder Commands
+
+;; Alphabetical.
+
 ;;;###mh-autoload
 (defun mh-edit-again (message)
   "Edit a MESSAGE to send it again.
@@ -509,32 +563,6 @@
       (kill-buffer draft)
       (message "Redistributing...done"))))
 
-(defun mh-show-buffer-message-number (&optional buffer)
-  "Message number of displayed message in corresponding show buffer.
-
-Return nil if show buffer not displayed.
-If in `mh-letter-mode', don't display the message number being replied
-to, but rather the message number of the show buffer associated with
-our originating folder buffer.
-Optional argument BUFFER can be used to specify the buffer."
-  (save-excursion
-    (if buffer
-        (set-buffer buffer))
-    (cond ((eq major-mode 'mh-show-mode)
-           (let ((number-start (mh-search-from-end ?/ buffer-file-name)))
-             (string-to-number (substring buffer-file-name
-                                          (1+ number-start)))))
-          ((and (eq major-mode 'mh-folder-mode)
-                mh-show-buffer
-                (get-buffer mh-show-buffer))
-           (mh-show-buffer-message-number mh-show-buffer))
-          ((and (eq major-mode 'mh-letter-mode)
-                mh-sent-from-folder
-                (get-buffer mh-sent-from-folder))
-           (mh-show-buffer-message-number mh-sent-from-folder))
-          (t
-           nil))))
-
 ;;;###mh-autoload
 (defun mh-reply (message &optional reply-to includep)
   "Reply to a MESSAGE.
@@ -667,18 +695,50 @@
     (delete-other-windows)
     (mh-send-sub to cc subject config)))
 
+
+
+;;; Support Routines
+
+(defun mh-interactive-read-address (prompt)
+  "Read an address.
+If `mh-compose-prompt-flag' is non-nil, then read an address with
+PROMPT.
+Otherwise return the empty string."
+  (if mh-compose-prompt-flag (mh-read-address prompt) ""))
+
+(defun mh-interactive-read-string (prompt)
+  "Read a string.
+If `mh-compose-prompt-flag' is non-nil, then read a string with
+PROMPT.
+Otherwise return the empty string."
+  (if mh-compose-prompt-flag (read-string prompt) ""))
+
 ;;;###mh-autoload
-(defun mh-send-other-window (to cc subject)
-  "Compose a message in another window.
+(defun mh-show-buffer-message-number (&optional buffer)
+  "Message number of displayed message in corresponding show buffer.
 
-See `mh-send' for more information and a description of how the
-TO, CC, and SUBJECT arguments are used."
-  (interactive (list
-                (mh-interactive-read-address "To: ")
-                (mh-interactive-read-address "Cc: ")
-                (mh-interactive-read-string "Subject: ")))
-  (let ((pop-up-windows t))
-    (mh-send-sub to cc subject (current-window-configuration))))
+Return nil if show buffer not displayed.
+If in `mh-letter-mode', don't display the message number being replied
+to, but rather the message number of the show buffer associated with
+our originating folder buffer.
+Optional argument BUFFER can be used to specify the buffer."
+  (save-excursion
+    (if buffer
+        (set-buffer buffer))
+    (cond ((eq major-mode 'mh-show-mode)
+           (let ((number-start (mh-search-from-end ?/ buffer-file-name)))
+             (string-to-number (substring buffer-file-name
+                                          (1+ number-start)))))
+          ((and (eq major-mode 'mh-folder-mode)
+                mh-show-buffer
+                (get-buffer mh-show-buffer))
+           (mh-show-buffer-message-number mh-show-buffer))
+          ((and (eq major-mode 'mh-letter-mode)
+                mh-sent-from-folder
+                (get-buffer mh-sent-from-folder))
+           (mh-show-buffer-message-number mh-sent-from-folder))
+          (t
+           nil))))
 
 (defun mh-send-sub (to cc subject config)
   "Do the real work of composing and sending a letter.
@@ -777,19 +837,6 @@
     (mh-exec-cmd-quiet t "mhpath" mh-draft-folder "new")
     (buffer-substring (point-min) (1- (point-max)))))
 
-(defun mh-annotate-msg (msg buffer note &rest args)
-  "Mark MSG in BUFFER with character NOTE and annotate message with ARGS.
-MSG can be a message number, a list of message numbers, or a
-sequence."
-  (apply 'mh-exec-cmd "anno" buffer
-         (if (listp msg) (append msg args) (cons msg args)))
-  (save-excursion
-    (cond ((get-buffer buffer)          ; Buffer may be deleted
-           (set-buffer buffer)
-           (mh-iterate-on-range nil msg
-             (mh-notate nil note
-                        (+ mh-cmd-note mh-scan-field-destination-offset)))))))
-
 (defun mh-insert-fields (&rest name-values)
   "Insert the NAME-VALUES pairs in the current buffer.
 If the field exists, append the value to it.
@@ -800,7 +847,8 @@
             (value (car (cdr name-values))))
         (if (not (string-match "^.*:$" field-name))
             (setq field-name (concat field-name ":")))
-        (cond ((equal value "")
+        (cond ((or (null value)
+                   (equal value ""))
                nil)
               ((mh-position-on-field field-name)
                (insert " " (or value "")))
@@ -808,459 +856,56 @@
                (insert field-name " " value "\n")))
         (setq name-values (cdr (cdr name-values)))))))
 
-(defun mh-position-on-field (field &optional ignored)
-  "Move to the end of the FIELD in the header.
-Move to end of entire header if FIELD not found.
-Returns non-nil iff FIELD was found.
-The optional second arg is for pre-version 4 compatibility and is
-IGNORED."
-  (cond ((mh-goto-header-field field)
-         (mh-header-field-end)
-         t)
-        ((mh-goto-header-end 0)
-         nil)))
-
-;;;###mh-autoload
-(defun mh-get-header-field (field)
-  "Find and return the body of FIELD in the mail header.
-Returns the empty string if the field is not in the header of the
-current buffer."
-  (if (mh-goto-header-field field)
-      (progn
-        (skip-chars-forward " \t")      ;strip leading white space in body
-        (let ((start (point)))
-          (mh-header-field-end)
-          (buffer-substring-no-properties start (point))))
-    ""))
-
-(fset 'mh-get-field 'mh-get-header-field) ;MH-E 4 compatibility
-
-(defun mh-goto-header-field (field)
-  "Move to FIELD in the message header.
-Move to the end of the FIELD name, which should end in a colon.
-Returns t if found, nil if not."
-  (goto-char (point-min))
-  (let ((case-fold-search t)
-        (headers-end (save-excursion
-                       (mh-goto-header-end 0)
-                       (point))))
-    (re-search-forward (format "^%s" field) headers-end t)))
-
-(defun mh-goto-header-end (arg)
-  "Move the cursor ARG lines after the header."
-  (if (re-search-forward "^-*$" nil nil)
-      (forward-line arg)))
-
-(defun mh-extract-from-header-value ()
-  "Extract From: string from header."
-  (save-excursion
-    (if (not (mh-goto-header-field "From:"))
-        nil
-      (skip-chars-forward " \t")
-      (buffer-substring-no-properties
-       (point) (progn (mh-header-field-end)(point))))))
-
-
-
-;;; Mode for composing and sending a draft message.
-
-(defvar mh-pgp-support-flag (not (not (locate-library "mml2015")))
-  "Non-nil means PGP support is available.")
-
-(put 'mh-letter-mode 'mode-class 'special)
+(defun mh-compose-and-send-mail (draft send-args
+                                       sent-from-folder sent-from-msg
+                                       to subject cc
+                                       annotate-char annotate-field
+                                       config)
+  "Edit and compose a draft message in buffer DRAFT and send or save it.
+SEND-ARGS is the argument passed to the send command.
+SENT-FROM-FOLDER is buffer containing scan listing of current folder,
+or nil if none exists.
+SENT-FROM-MSG is the message number or sequence name or nil.
+The TO, SUBJECT, and CC fields are passed to the
+`mh-compose-letter-function'.
+If ANNOTATE-CHAR is non-null, it is used to notate the scan listing of
+the message. In that case, the ANNOTATE-FIELD is used to build a
+string for `mh-annotate-msg'.
+CONFIG is the window configuration to restore after sending the
+letter."
+  (pop-to-buffer draft)
+  (mh-letter-mode)
 
-;; Menu extracted from mh-menubar.el V1.1 (31 July 2001)
-(eval-when-compile (defvar mh-letter-menu nil))
-(easy-menu-define
-  mh-letter-menu mh-letter-mode-map "Menu for MH-E letter mode."
-  '("Letter"
-    ["Send This Draft"          mh-send-letter t]
-    ["Split Current Line"       mh-open-line t]
-    ["Check Recipient"          mh-check-whom t]
-    ["Yank Current Message"     mh-yank-cur-msg t]
-    ["Insert a Message..."      mh-insert-letter t]
-    ["Insert Signature"         mh-insert-signature t]
-    ("Encrypt/Sign Message"
-     ["Sign Message"
-      mh-mml-secure-message-sign mh-pgp-support-flag]
-     ["Encrypt Message"
-      mh-mml-secure-message-encrypt mh-pgp-support-flag]
-     ["Sign+Encrypt Message"
-      mh-mml-secure-message-signencrypt mh-pgp-support-flag]
-     ["Disable Security"
-      mh-mml-unsecure-message mh-pgp-support-flag]
-     "--"
-     "Security Method"
-     ["PGP (MIME)" (setq mh-mml-method-default "pgpmime")
-      :style radio
-      :selected (equal mh-mml-method-default "pgpmime")]
-     ["PGP" (setq mh-mml-method-default "pgp")
-      :style radio
-      :selected (equal mh-mml-method-default "pgp")]
-     ["S/MIME" (setq mh-mml-method-default "smime")
-      :style radio
-      :selected (equal mh-mml-method-default "smime")]
-     "--"
-     ["Save Method as Default"
-      (customize-save-variable 'mh-mml-method-default mh-mml-method-default) t]
-     )
-    ["Compose Insertion..."      mh-compose-insertion t]
-    ["Compose Compressed tar (MH)..."
-     mh-mh-compose-external-compressed-tar t]
-    ["Compose Get File (MH)..."       mh-mh-compose-anon-ftp t]
-    ["Compose Forward..."        mh-compose-forward t]
-    ;; The next two will have to be merged. But I also need to make sure the
-    ;; user can't mix tags of both types.
-    ["Pull in All Compositions (MH)"
-     mh-mh-to-mime (mh-mh-directive-present-p)]
-    ["Pull in All Compositions (MML)"
-     mh-mml-to-mime (mh-mml-tag-present-p)]
-    ["Revert to Non-MIME Edit (MH)"
-     mh-mh-to-mime-undo (equal mh-compose-insertion 'mh)]
-    ["Kill This Draft"          mh-fully-kill-draft t]))
-
-
-
-;;; Help Messages
-
-;; Group messages logically, more or less.
-(defvar mh-letter-mode-help-messages
-  '((nil
-     "Send letter:          \\[mh-send-letter]"
-     "\t\tOpen line:            \\[mh-open-line]\n"
-     "Kill letter:          \\[mh-fully-kill-draft]"
-     "\t\tInsert:\n"
-     "Check recipients:     \\[mh-check-whom]"
-     "\t\t  Current message:    \\[mh-yank-cur-msg]\n"
-     "\t\t  Attachment:             \\[mh-compose-insertion]\n"
-     "\t\t  Message to forward:     \\[mh-compose-forward]\n"
-     "                          "
-     "Security:"
-     "\t\t  Encrypt message:          \\[mh-mml-secure-message-encrypt]"
-     "\t\t  Sign+Encrypt message:     \\[mh-mml-secure-message-signencrypt]"
-     "\t\t  Sign message:             \\[mh-mml-secure-message-sign]\n"
-     "                          "
-     "\t\t  Signature:              \\[mh-insert-signature]"))
-  "Key binding cheat sheet.
-
-This is an associative array which is used to show the most
-common commands. The key is a prefix char. The value is one or
-more strings which are concatenated together and displayed in the
-minibuffer if ? is pressed after the prefix character. The
-special key nil is used to display the non-prefixed commands.
-
-The substitutions described in `substitute-command-keys' are
-performed as well.")
-
-;; Shush compiler.
-(eval-when-compile
-  (defvar adaptive-fill-first-line-regexp)
-  (defvar tool-bar-map))
-
-(defvar mh-letter-buttons-init-flag nil)
-
-;;;###autoload
-(define-derived-mode mh-letter-mode mail-mode "MH-Letter"
-  "Mode for composing letters in MH-E\\<mh-letter-mode-map>.
-
-When you have finished composing, type \\[mh-send-letter] to send
-the message using the MH mail handling system.
-
-There are two types of tags used by MH-E when composing MIME
-messages: MML and MH. The option `mh-compose-insertion' controls
-what type of tags are inserted by MH-E commands. These tags can
-be converted to MIME body parts by running \\[mh-mh-to-mime] for
-MH-style directives or \\[mh-mml-to-mime] for MML tags.
-
-Options that control this mode can be changed with
-\\[customize-group]; specify the \"mh-compose\" group.
-
-When a message is composed, the hooks `text-mode-hook',
-`mail-mode-hook', and `mh-letter-mode-hook' are run (in that
-order).
-
-\\{mh-letter-mode-map}"
-  (mh-find-path)
-  (make-local-variable 'mh-send-args)
-  (make-local-variable 'mh-annotate-char)
-  (make-local-variable 'mh-annotate-field)
-  (make-local-variable 'mh-previous-window-config)
-  (make-local-variable 'mh-sent-from-folder)
-  (make-local-variable 'mh-sent-from-msg)
-  (mh-do-in-gnu-emacs
-   (unless mh-letter-buttons-init-flag
-     (mh-tool-bar-letter-buttons-init)
-     (setq mh-letter-buttons-init-flag t)))
-  ;; Set the local value of mh-mail-header-separator according to what is
-  ;; present in the buffer...
-  (set (make-local-variable 'mh-mail-header-separator)
-       (save-excursion
-         (goto-char (mh-mail-header-end))
-         (buffer-substring-no-properties (point) (line-end-position))))
-  (make-local-variable 'mail-header-separator)
-  (setq mail-header-separator mh-mail-header-separator) ;override sendmail.el
-  (make-local-variable 'mh-help-messages)
-  (setq mh-help-messages mh-letter-mode-help-messages)
-  (setq buffer-invisibility-spec '((vanish . t) t))
-  (set (make-local-variable 'line-move-ignore-invisible) t)
-
-  ;; Enable undo since a show-mode buffer might have been reused.
-  (buffer-enable-undo)
-  (set (make-local-variable 'tool-bar-map) mh-letter-tool-bar-map)
-  (mh-funcall-if-exists mh-tool-bar-init :letter)
-  (make-local-variable 'font-lock-defaults)
-  (cond
-   ((or (equal mh-highlight-citation-style 'font-lock)
-        (equal mh-highlight-citation-style 'gnus))
-    ;; Let's use font-lock even if gnus is used in show-mode.  The reason
-    ;; is that gnus uses static text properties which are not appropriate
-    ;; for a buffer that will be edited.  So the choice here is either fontify
-    ;; the citations and header...
-    (setq font-lock-defaults '(mh-letter-font-lock-keywords t)))
-   (t
-    ;; ...or the header only
-    (setq font-lock-defaults '(mh-show-font-lock-keywords t))))
-  (easy-menu-add mh-letter-menu)
-  (setq fill-column mh-letter-fill-column)
-  ;; If text-mode-hook turned on auto-fill, tune it for messages
-  (when auto-fill-function
-    (make-local-variable 'auto-fill-function)
-    (setq auto-fill-function 'mh-auto-fill-for-letter)))
+  ;; Insert identity.
+  (mh-insert-identity mh-identity-default t)
+  (mh-identity-make-menu)
+  (mh-identity-add-menu)
 
-(defun mh-font-lock-field-data (limit)
-  "Find header field region between point and LIMIT."
-  (and (< (point) (mh-letter-header-end))
-       (< (point) limit)
-       (let ((end (min limit (mh-letter-header-end)))
-             (point (point))
-             data-end data-begin field)
-         (end-of-line)
-         (setq data-end (if (re-search-forward "^[^ \t]" end t)
-                            (match-beginning 0)
-                          end))
-         (goto-char (1- data-end))
-         (if (not (re-search-backward "\\(^[^ \t][^:]*\\):[ \t]*" nil t))
-             (setq data-begin (point-min))
-           (setq data-begin (match-end 0))
-           (setq field (match-string 1)))
-         (setq data-begin (max point data-begin))
-         (goto-char (if (equal point data-end) (1+ data-end) data-end))
-         (cond ((and field (mh-letter-skipped-header-field-p field))
-                (set-match-data nil)
-                nil)
-               (t (set-match-data
-                   (list data-begin data-end data-begin data-end))
-                  t)))))
-
-(defun mh-letter-header-end ()
-  "Find the end of the message header.
-This function is to be used only for font locking. It works by
-searching for `mh-mail-header-separator' in the buffer."
-  (save-excursion
-    (goto-char (point-min))
-    (cond ((equal mh-mail-header-separator "") (point-min))
-          ((search-forward (format "\n%s\n" mh-mail-header-separator) nil t)
-           (line-beginning-position 0))
-          (t (point-min)))))
-
-(defun mh-auto-fill-for-letter ()
-  "Perform auto-fill for message.
-Header is treated specially by inserting a tab before continuation
-lines."
-  (if (mh-in-header-p)
-      (let ((fill-prefix "\t"))
-        (do-auto-fill))
-    (do-auto-fill)))
-
-(defun mh-insert-header-separator ()
-  "Insert `mh-mail-header-separator', if absent."
-  (save-excursion
-    (goto-char (point-min))
-    (rfc822-goto-eoh)
-    (if (looking-at "$")
-        (insert mh-mail-header-separator))))
+  ;; Insert extra fields.
+  (mh-insert-x-mailer)
+  (mh-insert-x-face)
 
-;;;###mh-autoload
-(defun mh-to-field ()
-  "Move to specified header field.
-
-The field is indicated by the previous keystroke (the last
-keystroke of the command) according to the list in the variable
-`mh-to-field-choices'.
-Create the field if it does not exist.
-Set the mark to point before moving."
-  (interactive)
-  (expand-abbrev)
-  (let ((target (cdr (or (assoc (char-to-string (logior last-input-char ?`))
-                                mh-to-field-choices)
-                         ;; also look for a char for version 4 compat
-                         (assoc (logior last-input-char ?`)
-                                mh-to-field-choices))))
-        (case-fold-search t))
-    (push-mark)
-    (cond ((mh-position-on-field target)
-           (let ((eol (point)))
-             (skip-chars-backward " \t")
-             (delete-region (point) eol))
-           (if (and (not (eq (logior last-input-char ?`) ?s))
-                    (save-excursion
-                      (backward-char 1)
-                      (not (looking-at "[:,]"))))
-               (insert ", ")
-             (insert " ")))
-          (t
-           (if (mh-position-on-field "To:")
-               (forward-line 1))
-           (insert (format "%s \n" target))
-           (backward-char 1)))))
-
-;;;###mh-autoload
-(defun mh-to-fcc (&optional folder)
-  "Move to \"Fcc:\" header field.
-
-This command will prompt you for the FOLDER name in which to file
-a copy of the draft."
-  (interactive (list (mh-prompt-for-folder
-                      "Fcc"
-                      (or (and mh-default-folder-for-message-function
-                               (save-excursion
-                                 (goto-char (point-min))
-                                 (funcall
-                                  mh-default-folder-for-message-function)))
-                          "")
-                      t)))
-  (let ((last-input-char ?\C-f))
-    (expand-abbrev)
-    (save-excursion
-      (mh-to-field)
-      (insert (if (mh-folder-name-p folder)
-                  (substring folder 1)
-                folder)))))
+  (mh-letter-hide-all-skipped-fields)
 
-(defun mh-file-is-vcard-p (file)
-  "Return t if FILE is a .vcf vcard."
-  (let ((case-fold-search t))
-    (and (stringp file)
-         (file-exists-p file)
-         (or (and (not (mh-have-file-command))
-                  (not (null (string-match "\.vcf$" file))))
-             (string-equal "text/x-vcard" (mh-file-mime-type file))))))
-
-;;;###mh-autoload
-(defun mh-insert-signature (&optional file)
-  "Insert signature in message.
-
-This command inserts your signature at the current cursor location.
-
-By default, the text of your signature is taken from the file
-\"~/.signature\". You can read from other sources by changing the
-option `mh-signature-file-name'.
-
-A signature separator (\"-- \") will be added if the signature block
-does not contain one and `mh-signature-separator-flag' is on.
-
-The hook `mh-insert-signature-hook' is run after the signature is
-inserted. Hook functions may access the actual name of the file or the
-function used to insert the signature with `mh-signature-file-name'.
-
-The signature can also be inserted using Identities (see
-`mh-identity-list').
-
-In a program, you can pass in a signature FILE."
-  (interactive)
-  (save-excursion
-    (insert "\n")
-    (let ((mh-signature-file-name (or file mh-signature-file-name))
-          (mh-mh-p (mh-mh-directive-present-p))
-          (mh-mml-p (mh-mml-tag-present-p)))
-      (save-restriction
-        (narrow-to-region (point) (point))
-        (cond
-         ((mh-file-is-vcard-p mh-signature-file-name)
-          (if (equal mh-compose-insertion 'mml)
-              (insert "<#part type=\"text/x-vcard\" filename=\""
-                      mh-signature-file-name
-                      "\" disposition=inline description=VCard>\n<#/part>")
-            (insert "#text/x-vcard; name=\""
-                    (file-name-nondirectory mh-signature-file-name)
-                    "\" [VCard] " (expand-file-name mh-signature-file-name))))
-         (t
-          (cond
-           (mh-mh-p
-            (insert "#\n" "Content-Description: Signature\n"))
-           (mh-mml-p
-            (mml-insert-tag 'part 'type "text/plain" 'disposition "inline"
-                            'description "Signature")))
-          (cond ((null mh-signature-file-name))
-                ((and (stringp mh-signature-file-name)
-                      (file-readable-p mh-signature-file-name))
-                 (insert-file-contents mh-signature-file-name))
-                ((functionp mh-signature-file-name)
-                 (funcall mh-signature-file-name)))))
-        (save-restriction
-          (widen)
-          (run-hooks 'mh-insert-signature-hook))
-        (goto-char (point-min))
-        (when (and (not (mh-file-is-vcard-p mh-signature-file-name))
-                   mh-signature-separator-flag
-                   (> (point-max) (point-min))
-                   (not (mh-signature-separator-p)))
-          (cond (mh-mh-p
-                 (forward-line 2))
-                (mh-mml-p
-                 (forward-line 1)))
-          (insert mh-signature-separator))
-        (if (not (> (point-max) (point-min)))
-            (message "No signature found")))))
-  (force-mode-line-update))
-
-;;;###mh-autoload
-(defun mh-check-whom ()
-  "Verify recipients, showing expansion of any aliases.
-
-This command expands aliases so you can check the actual address(es)
-in the alias. A new buffer named \"*MH-E Recipients*\" is created with
-the output of \"whom\"."
-  (interactive)
-  (let ((file-name buffer-file-name))
-    (save-buffer)
-    (message "Checking recipients...")
-    (mh-in-show-buffer (mh-recipients-buffer)
-      (bury-buffer (current-buffer))
-      (erase-buffer)
-      (mh-exec-cmd-output "whom" t file-name))
-    (message "Checking recipients...done")))
-
-(defun mh-tidy-draft-buffer ()
-  "Run when a draft buffer is destroyed."
-  (let ((buffer (get-buffer mh-recipients-buffer)))
-    (if buffer
-	(kill-buffer buffer))))
-
-
-
-;;; Routines to compose and send a letter.
-
-(defun mh-insert-x-face ()
-  "Append X-Face, Face or X-Image-URL field to header.
-If the field already exists, this function does nothing."
-  (when (and (file-exists-p mh-x-face-file)
-             (file-readable-p mh-x-face-file))
-    (save-excursion
-      (unless (or (mh-position-on-field "X-Face")
-                  (mh-position-on-field "Face")
-                  (mh-position-on-field "X-Image-URL"))
-        (save-excursion
-          (goto-char (+ (point) (cadr (insert-file-contents mh-x-face-file))))
-          (if (not (looking-at "^"))
-              (insert "\n")))
-        (unless (looking-at "\\(X-Face\\|Face\\|X-Image-URL\\): ")
-          (insert "X-Face: "))))))
-
-(defvar mh-x-mailer-string nil
-  "*String containing the contents of the X-Mailer header field.
-If nil, this variable is initialized to show the version of MH-E,
-Emacs, and MH the first time a message is composed.")
+  (setq mh-sent-from-folder sent-from-folder)
+  (setq mh-sent-from-msg sent-from-msg)
+  (setq mh-send-args send-args)
+  (setq mh-annotate-char annotate-char)
+  (setq mh-annotate-field annotate-field)
+  (setq mh-previous-window-config config)
+  (setq mode-line-buffer-identification (list "    {%b}"))
+  (mh-logo-display)
+  (mh-make-local-hook 'kill-buffer-hook)
+  (add-hook 'kill-buffer-hook 'mh-tidy-draft-buffer nil t)
+  (if (and (boundp 'mh-compose-letter-function)
+           mh-compose-letter-function)
+      ;; run-hooks will not pass arguments.
+      (let ((value mh-compose-letter-function))
+        (if (and (listp value) (not (eq (car value) 'lambda)))
+            (while value
+              (funcall (car value) to subject cc)
+              (setq value (cdr value)))
+          (funcall mh-compose-letter-function to subject cc)))))
 
 (defun mh-insert-x-mailer ()
   "Append an X-Mailer field to the header.
@@ -1283,20 +928,61 @@
                (null (mh-goto-header-field "X-Mailer")))
       (mh-insert-fields "X-Mailer:" mh-x-mailer-string))))
 
-(defun mh-regexp-in-field-p (regexp &rest fields)
-  "Non-nil means REGEXP was found in FIELDS."
+(defun mh-insert-x-face ()
+  "Append X-Face, Face or X-Image-URL field to header.
+If the field already exists, this function does nothing."
+  (when (and (file-exists-p mh-x-face-file)
+             (file-readable-p mh-x-face-file))
+    (save-excursion
+      (unless (or (mh-position-on-field "X-Face")
+                  (mh-position-on-field "Face")
+                  (mh-position-on-field "X-Image-URL"))
+        (save-excursion
+          (goto-char (+ (point) (cadr (insert-file-contents mh-x-face-file))))
+          (if (not (looking-at "^"))
+              (insert "\n")))
+        (unless (looking-at "\\(X-Face\\|Face\\|X-Image-URL\\): ")
+          (insert "X-Face: "))))))
+
+(defun mh-tidy-draft-buffer ()
+  "Run when a draft buffer is destroyed."
+  (let ((buffer (get-buffer mh-recipients-buffer)))
+    (if buffer
+        (kill-buffer buffer))))
+
+(defun mh-letter-mode-message ()
+  "Display a help message for users of `mh-letter-mode'.
+This should be the last function called when composing the draft."
+  (message "%s" (substitute-command-keys
+                 (concat "Type \\[mh-send-letter] to send message, "
+                         "\\[mh-help] for help"))))
+
+(defun mh-letter-adjust-point ()
+  "Move cursor to first header field if are using the no prompt mode."
+  (unless mh-compose-prompt-flag
+    (goto-char (point-max))
+    (mh-letter-next-header-field)))
+
+(defun mh-annotate-msg (msg buffer note &rest args)
+  "Mark MSG in BUFFER with character NOTE and annotate message with ARGS.
+MSG can be a message number, a list of message numbers, or a
+sequence."
+  (apply 'mh-exec-cmd "anno" buffer
+         (if (listp msg) (append msg args) (cons msg args)))
   (save-excursion
-    (let ((search-result nil)
-          (field))
-      (while fields
-        (setq field (car fields))
-        (if (and (mh-goto-header-field field)
-                 (re-search-forward
-                  regexp (save-excursion (mh-header-field-end)(point)) t))
-            (setq fields nil
-                  search-result t)
-          (setq fields (cdr fields))))
-      search-result)))
+    (cond ((get-buffer buffer)          ; Buffer may be deleted
+           (set-buffer buffer)
+           (mh-iterate-on-range nil msg
+             (mh-notate nil note
+                        (+ mh-cmd-note mh-scan-field-destination-offset)))))))
+
+(defun mh-insert-header-separator ()
+  "Insert `mh-mail-header-separator', if absent."
+  (save-excursion
+    (goto-char (point-min))
+    (rfc822-goto-eoh)
+    (if (looking-at "$")
+        (insert mh-mail-header-separator))))
 
 ;;;###mh-autoload
 (defun mh-insert-auto-fields (&optional non-interactive)
@@ -1332,12 +1018,13 @@
                           (value (cdar entry-list)))
                       (cond
                        ((equal ":identity" field)
-                        (when ;;(and (not mh-identity-local)
+                        (when
+                            ;;(and (not mh-identity-local)
                             ;; Bug 1204506.  But do we need to be able
-                            ;;  to set an identity manually that won't be
-                            ;;  overridden by mh-insert-auto-fields?
-                                   (assoc value mh-identity-list)
-                                   ;;)
+                            ;; to set an identity manually that won't be
+                            ;; overridden by mh-insert-auto-fields?
+                            (assoc value mh-identity-list)
+                          ;;)
                           (mh-insert-identity value)))
                        (t
                         (mh-modify-header-field field value
@@ -1365,66 +1052,20 @@
          (mh-goto-header-end 0)
          (insert field ": " value "\n"))))
 
-(defun mh-compose-and-send-mail (draft send-args
-                                       sent-from-folder sent-from-msg
-                                       to subject cc
-                                       annotate-char annotate-field
-                                       config)
-  "Edit and compose a draft message in buffer DRAFT and send or save it.
-SEND-ARGS is the argument passed to the send command.
-SENT-FROM-FOLDER is buffer containing scan listing of current folder,
-or nil if none exists.
-SENT-FROM-MSG is the message number or sequence name or nil.
-The TO, SUBJECT, and CC fields are passed to the
-`mh-compose-letter-function'.
-If ANNOTATE-CHAR is non-null, it is used to notate the scan listing of
-the message. In that case, the ANNOTATE-FIELD is used to build a
-string for `mh-annotate-msg'.
-CONFIG is the window configuration to restore after sending the
-letter."
-  (pop-to-buffer draft)
-  (mh-letter-mode)
-
-  ;; Insert identity.
-  (if (and (boundp 'mh-identity-default)
-           mh-identity-default
-           (not mh-identity-local))
-      (mh-insert-identity mh-identity-default))
-  (mh-identity-make-menu)
-  (easy-menu-add mh-identity-menu)
-
-  ;; Insert extra fields.
-  (mh-insert-x-mailer)
-  (mh-insert-x-face)
-
-  (mh-letter-hide-all-skipped-fields)
-
-  (setq mh-sent-from-folder sent-from-folder)
-  (setq mh-sent-from-msg sent-from-msg)
-  (setq mh-send-args send-args)
-  (setq mh-annotate-char annotate-char)
-  (setq mh-annotate-field annotate-field)
-  (setq mh-previous-window-config config)
-  (setq mode-line-buffer-identification (list "    {%b}"))
-  (mh-logo-display)
-  (mh-make-local-hook 'kill-buffer-hook)
-  (add-hook 'kill-buffer-hook 'mh-tidy-draft-buffer nil t)
-  (if (and (boundp 'mh-compose-letter-function)
-           mh-compose-letter-function)
-      ;; run-hooks will not pass arguments.
-      (let ((value mh-compose-letter-function))
-        (if (and (listp value) (not (eq (car value) 'lambda)))
-            (while value
-              (funcall (car value) to subject cc)
-              (setq value (cdr value)))
-          (funcall mh-compose-letter-function to subject cc)))))
-
-(defun mh-letter-mode-message ()
-  "Display a help message for users of `mh-letter-mode'.
-This should be the last function called when composing the draft."
-  (message "%s" (substitute-command-keys
-                 (concat "Type \\[mh-send-letter] to send message, "
-                         "\\[mh-help] for help"))))
+(defun mh-regexp-in-field-p (regexp &rest fields)
+  "Non-nil means REGEXP was found in FIELDS."
+  (save-excursion
+    (let ((search-result nil)
+          (field))
+      (while fields
+        (setq field (car fields))
+        (if (and (mh-goto-header-field field)
+                 (re-search-forward
+                  regexp (save-excursion (mh-header-field-end)(point)) t))
+            (setq fields nil
+                  search-result t)
+          (setq fields (cdr fields))))
+      search-result)))
 
 (defun mh-ascii-buffer-p ()
   "Check if current buffer is entirely composed of ASCII.
@@ -1435,739 +1076,6 @@
         unless (eq charset 'ascii) return nil
         finally return t))
 
-;; Shush compiler.
-(eval-when-compile (defvar sendmail-coding-system))
-
-;;;###mh-autoload
-(defun mh-send-letter (&optional arg)
-  "Save draft and send message.
-
-When you are all through editing a message, you send it with this
-command. You can give a prefix argument ARG to monitor the first stage
-of the delivery\; this output can be found in a buffer called \"*MH-E
-Mail Delivery*\".
-
-The hook `mh-before-send-letter-hook' is run at the beginning of
-this command. For example, if you want to check your spelling in
-your message before sending, add the function `ispell-message'.
-
-In case the MH \"send\" program is installed under a different name,
-use `mh-send-prog' to tell MH-E the name."
-  (interactive "P")
-  (run-hooks 'mh-before-send-letter-hook)
-  (if (and (mh-insert-auto-fields t)
-           mh-auto-fields-prompt-flag
-           (goto-char (point-min)))
-      (if (not (y-or-n-p "Auto fields inserted, send? "))
-          (error "Send aborted")))
-  (cond ((mh-mh-directive-present-p)
-         (mh-mh-to-mime))
-        ((or (mh-mml-tag-present-p) (not (mh-ascii-buffer-p)))
-         (mh-mml-to-mime)))
-  (save-buffer)
-  (message "Sending...")
-  (let ((draft-buffer (current-buffer))
-        (file-name buffer-file-name)
-        (config mh-previous-window-config)
-        (coding-system-for-write
-         (if (and (local-variable-p 'buffer-file-coding-system
-                                    (current-buffer)) ;XEmacs needs two args
-                  ;; We're not sure why, but buffer-file-coding-system
-                  ;; tends to get set to undecided-unix.
-                  (not (memq buffer-file-coding-system
-                             '(undecided undecided-unix undecided-dos))))
-             buffer-file-coding-system
-           (or (and (boundp 'sendmail-coding-system) sendmail-coding-system)
-               (and (boundp 'default-buffer-file-coding-system )
-                    default-buffer-file-coding-system)
-               'iso-latin-1))))
-    ;; Adding a Message-ID field looks good, makes it easier to search for
-    ;; message in your +outbox, and best of all doesn't break threading for
-    ;; the recipient if you reply to a message in your +outbox.
-    (setq mh-send-args (concat "-msgid " mh-send-args))
-    ;; The default BCC encapsulation will make a MIME message unreadable.
-    ;; With nmh use the -mime arg to prevent this.
-    (if (and (mh-variant-p 'nmh)
-             (mh-goto-header-field "Bcc:")
-             (mh-goto-header-field "Content-Type:"))
-        (setq mh-send-args (concat "-mime " mh-send-args)))
-    (cond (arg
-           (pop-to-buffer mh-mail-delivery-buffer)
-           (erase-buffer)
-           (mh-exec-cmd-output mh-send-prog t "-watch" "-nopush"
-                               "-nodraftfolder" mh-send-args file-name)
-           (goto-char (point-max))      ; show the interesting part
-           (recenter -1)
-           (set-buffer draft-buffer))   ; for annotation below
-          (t
-           (mh-exec-cmd-daemon mh-send-prog nil "-nodraftfolder" "-noverbose"
-                               mh-send-args file-name)))
-    (if mh-annotate-char
-        (mh-annotate-msg mh-sent-from-msg
-                         mh-sent-from-folder
-                         mh-annotate-char
-                         "-component" mh-annotate-field
-                         "-text" (format "\"%s %s\""
-                                         (mh-get-header-field "To:")
-                                         (mh-get-header-field "Cc:"))))
-
-    (cond ((or (not arg)
-               (y-or-n-p "Kill draft buffer? "))
-           (kill-buffer draft-buffer)
-           (if config
-               (set-window-configuration config))))
-    (if arg
-        (message "Sending...done")
-      (message "Sending...backgrounded"))))
-
-;;;###mh-autoload
-(defun mh-insert-letter (folder message verbatim)
-  "Insert a message.
-
-This command prompts you for the FOLDER and MESSAGE number, which
-defaults to the current message in that folder. It then inserts
-the message, indented by `mh-ins-buf-prefix' (\"> \") unless
-`mh-yank-behavior' is set to one of the supercite flavors in
-which case supercite is used to format the message. Certain
-undesirable header fields (see
-`mh-invisible-header-fields-compiled') are removed before
-insertion.
-
-If given a prefix argument VERBATIM, the header is left intact, the
-message is not indented, and \"> \" is not inserted before each line.
-This command leaves the mark before the letter and point after it."
-  (interactive
-   (let* ((folder
-           (mh-prompt-for-folder "Message from"
-                                 mh-sent-from-folder nil))
-          (default
-            (if (and (equal folder mh-sent-from-folder)
-                     (numberp mh-sent-from-msg))
-                mh-sent-from-msg
-              (nth 0 (mh-translate-range folder "cur"))))
-          (message
-           (read-string (concat "Message number"
-                                (or (and default
-                                         (format " (default %d): " default))
-                                    ": ")))))
-     (list folder message current-prefix-arg)))
-  (save-restriction
-    (narrow-to-region (point) (point))
-    (let ((start (point-min)))
-      (if (and (equal message "") (numberp mh-sent-from-msg))
-          (setq message (int-to-string mh-sent-from-msg)))
-      (insert-file-contents
-       (expand-file-name message (mh-expand-file-name folder)))
-      (when (not verbatim)
-        (mh-clean-msg-header start mh-invisible-header-fields-compiled nil)
-        (goto-char (point-max))         ;Needed for sc-cite-original
-        (push-mark)                     ;Needed for sc-cite-original
-        (goto-char (point-min))         ;Needed for sc-cite-original
-        (mh-insert-prefix-string mh-ins-buf-prefix)))))
-
-(defun mh-extract-from-attribution ()
-  "Extract phrase or comment from From header field."
-  (save-excursion
-    (if (not (mh-goto-header-field "From: "))
-        nil
-      (skip-chars-forward " ")
-      (cond
-       ((looking-at "\"\\([^\"\n]+\\)\" \\(<.+>\\)")
-        (format "%s %s " (match-string 1)(match-string 2)))
-       ((looking-at "\\([^<\n]+<.+>\\)$")
-        (format "%s " (match-string 1)))
-       ((looking-at "\\([^ ]+@[^ ]+\\) +(\\(.+\\))$")
-        (format "%s <%s> " (match-string 2)(match-string 1)))
-       ((looking-at " *\\(.+\\)$")
-        (format "%s " (match-string 1)))))))
-
-;;;###mh-autoload
-(defun mh-yank-cur-msg ()
-  "Insert the current message into the draft buffer.
-
-It is often useful to insert a snippet of text from a letter that
-someone mailed to provide some context for your reply. This
-command does this by adding an attribution, yanking a portion of
-text from the message to which you're replying, and inserting
-`mh-ins-buf-prefix' (`> ') before each line.
-
-The attribution consists of the sender's name and email address
-followed by the content of the option
-`mh-extract-from-attribution-verb'.
-
-You can also turn on the option
-`mh-delete-yanked-msg-window-flag' to delete the window
-containing the original message after yanking it to make more
-room on your screen for your reply.
-
-You can control how the message to which you are replying is
-yanked into your reply using `mh-yank-behavior'.
-
-If this isn't enough, you can gain full control over the
-appearance of the included text by setting `mail-citation-hook'
-to a function that modifies it. For example, if you set this hook
-to `trivial-cite' (which is NOT part of Emacs), set
-`mh-yank-behavior' to \"Body and Header\" (see URL
-`http://shasta.cs.uiuc.edu/~lrclause/tc.html').
-
-Note that if `mail-citation-hook' is set, `mh-ins-buf-prefix' is
-not inserted. If the option `mh-yank-behavior' is set to one of
-the supercite flavors, the hook `mail-citation-hook' is ignored
-and `mh-ins-buf-prefix' is not inserted."
-  (interactive)
-  (if (and mh-sent-from-folder
-           (save-excursion (set-buffer mh-sent-from-folder) mh-show-buffer)
-           (save-excursion (set-buffer mh-sent-from-folder)
-                           (get-buffer mh-show-buffer))
-           mh-sent-from-msg)
-      (let ((to-point (point))
-            (to-buffer (current-buffer)))
-        (set-buffer mh-sent-from-folder)
-        (if mh-delete-yanked-msg-window-flag
-            (delete-windows-on mh-show-buffer))
-        (set-buffer mh-show-buffer)     ; Find displayed message
-        (let* ((from-attr (mh-extract-from-attribution))
-               (yank-region (mh-mark-active-p nil))
-               (mh-ins-str
-                (cond ((and yank-region
-                            (or (eq 'supercite mh-yank-behavior)
-                                (eq 'autosupercite mh-yank-behavior)
-                                (eq t mh-yank-behavior)))
-                       ;; supercite needs the full header
-                       (concat
-                        (buffer-substring (point-min) (mh-mail-header-end))
-                        "\n"
-                        (buffer-substring (region-beginning) (region-end))))
-                      (yank-region
-                       (buffer-substring (region-beginning) (region-end)))
-                      ((or (eq 'body mh-yank-behavior)
-                           (eq 'attribution mh-yank-behavior)
-                           (eq 'autoattrib mh-yank-behavior))
-                       (buffer-substring
-                        (save-excursion
-                          (goto-char (point-min))
-                          (mh-goto-header-end 1)
-                          (point))
-                        (point-max)))
-                      ((or (eq 'supercite mh-yank-behavior)
-                           (eq 'autosupercite mh-yank-behavior)
-                           (eq t mh-yank-behavior))
-                       (buffer-substring (point-min) (point-max)))
-                      (t
-                       (buffer-substring (point) (point-max))))))
-          (set-buffer to-buffer)
-          (save-restriction
-            (narrow-to-region to-point to-point)
-            (insert (mh-filter-out-non-text mh-ins-str))
-            (goto-char (point-max))     ;Needed for sc-cite-original
-            (push-mark)                 ;Needed for sc-cite-original
-            (goto-char (point-min))     ;Needed for sc-cite-original
-            (mh-insert-prefix-string mh-ins-buf-prefix)
-            (when (or (eq 'attribution mh-yank-behavior)
-                      (eq 'autoattrib mh-yank-behavior))
-              (insert from-attr)
-              (mh-identity-insert-attribution-verb nil)
-              (insert "\n\n"))
-            ;; If the user has selected a region, he has already "edited" the
-            ;; text, so leave the cursor at the end of the yanked text. In
-            ;; either case, leave a mark at the opposite end of the included
-            ;; text to make it easy to jump or delete to the other end of the
-            ;; text.
-            (push-mark)
-            (goto-char (point-max))
-            (if (null yank-region)
-                (mh-exchange-point-and-mark-preserving-active-mark)))))
-    (error "There is no current message")))
-
-(defun mh-filter-out-non-text (string)
-  "Return STRING but without adornments such as MIME buttons and smileys."
-  (with-temp-buffer
-    ;; Insert the string to filter
-    (insert string)
-    (goto-char (point-min))
-
-    ;; Remove the MIME buttons
-    (let ((can-move-forward t)
-          (in-button nil))
-      (while can-move-forward
-        (cond ((and (not (get-text-property (point) 'mh-data))
-                    in-button)
-               (delete-region (1- (point)) (point))
-               (setq in-button nil))
-              ((get-text-property (point) 'mh-data)
-               (delete-region (point)
-                              (save-excursion (forward-line) (point)))
-               (setq in-button t))
-              (t (setq can-move-forward (= (forward-line) 0))))))
-
-    ;; Return the contents without properties... This gets rid of emphasis
-    ;; and smileys
-    (buffer-substring-no-properties (point-min) (point-max))))
-
-(defun mh-insert-prefix-string (mh-ins-string)
-  "Insert prefix string before each line in buffer.
-The inserted letter is cited using `sc-cite-original' if
-`mh-yank-behavior' is one of 'supercite or 'autosupercite.
-Otherwise, simply insert MH-INS-STRING before each line."
-  (goto-char (point-min))
-  (cond ((or (eq mh-yank-behavior 'supercite)
-             (eq mh-yank-behavior 'autosupercite))
-         (sc-cite-original))
-        (mail-citation-hook
-         (run-hooks 'mail-citation-hook))
-        (mh-yank-hooks                  ;old hook name
-         (run-hooks 'mh-yank-hooks))
-        (t
-         (or (bolp) (forward-line 1))
-         (while (< (point) (point-max))
-           (insert mh-ins-string)
-           (forward-line 1))
-         (goto-char (point-min)))))     ;leave point like sc-cite-original
-
-;;;###mh-autoload
-(defun mh-fully-kill-draft ()
-  "Quit editing and delete draft message.
-
-If for some reason you are not happy with the draft, you can use
-this command to kill the draft buffer and delete the draft
-message. Use the command \\[kill-buffer] if you don't want to
-delete the draft message."
-  (interactive)
-  (if (y-or-n-p "Kill draft message? ")
-      (let ((config mh-previous-window-config))
-        (if (file-exists-p buffer-file-name)
-            (delete-file buffer-file-name))
-        (set-buffer-modified-p nil)
-        (kill-buffer (buffer-name))
-        (message "")
-        (if config
-            (set-window-configuration config)))
-    (error "Message not killed")))
-
-(defun mh-current-fill-prefix ()
-  "Return the `fill-prefix' on the current line as a string."
-  (save-excursion
-    (beginning-of-line)
-    ;; This assumes that the major-mode sets up adaptive-fill-regexp
-    ;; correctly such as mh-letter-mode or sendmail.el's mail-mode.  But
-    ;; perhaps I should use the variable and simply inserts its value here,
-    ;; and set it locally in a let scope.  --psg
-    (if (re-search-forward adaptive-fill-regexp nil t)
-        (match-string 0)
-      "")))
-
-;;;###mh-autoload
-(defun mh-open-line ()
-  "Insert a newline and leave point before it.
-
-This command is similar to the command \\[open-line] in that it
-inserts a newline after point. It differs in that it also inserts
-the right number of quoting characters and spaces so that the
-next line begins in the same column as it was. This is useful
-when breaking up paragraphs in replies."
-  (interactive)
-  (let ((column (current-column))
-        (prefix (mh-current-fill-prefix)))
-    (if (> (length prefix) column)
-        (message "Sorry, point seems to be within the line prefix")
-      (newline 2)
-      (insert prefix)
-      (while (> column (current-column))
-        (insert " "))
-      (forward-line -1))))
-
-(mh-do-in-xemacs (defvar mail-abbrevs))
-
-(defmacro mh-display-completion-list-compat (word choices)
-  "Completes WORD from CHOICES using `display-completion-list'.
-Calls `display-completion-list' correctly in older environments.
-Versions of Emacs prior to version 22 lacked a COMMON-SUBSTRING
-argument which is used to highlight the next possible character you
-can enter in the current list of completions."
-  (if (>= emacs-major-version 22)
-      `(display-completion-list (all-completions ,word ,choices) ,word)
-    `(display-completion-list (all-completions ,word ,choices))))
-
-;;;###mh-autoload
-(defun mh-complete-word (word choices begin end)
-  "Complete WORD at from CHOICES.
-Any match found replaces the text from BEGIN to END."
-  (let ((completion (try-completion word choices))
-        (completions-buffer "*Completions*"))
-    (cond ((eq completion t)
-           (ignore-errors
-             (kill-buffer completions-buffer))
-           (message "Completed: %s" word))
-          ((null completion)
-           (ignore-errors
-             (kill-buffer completions-buffer))
-           (message "No completion for %s" word))
-          ((stringp completion)
-           (if (equal word completion)
-               (with-output-to-temp-buffer completions-buffer
-                 (mh-display-completion-list-compat word choices))
-             (ignore-errors
-               (kill-buffer completions-buffer))
-             (delete-region begin end)
-             (insert completion))))))
-
-;;;###mh-autoload
-(defun mh-beginning-of-word (&optional n)
-  "Return position of the N th word backwards."
-  (unless n (setq n 1))
-  (let ((syntax-table (syntax-table)))
-    (unwind-protect
-        (save-excursion
-          (mh-mail-abbrev-make-syntax-table)
-          (set-syntax-table mail-abbrev-syntax-table)
-          (backward-word n)
-          (point))
-      (set-syntax-table syntax-table))))
-
-(defun mh-folder-expand-at-point ()
-  "Do folder name completion in Fcc header field."
-  (let* ((end (point))
-         (beg (mh-beginning-of-word))
-         (folder (buffer-substring beg end))
-         (leading-plus (and (> (length folder) 0) (equal (aref folder 0) ?+)))
-         (last-slash (mh-search-from-end ?/ folder))
-         (prefix (and last-slash (substring folder 0 last-slash)))
-         (choices (mapcar #'(lambda (x)
-                              (list (cond (prefix (format "%s/%s" prefix x))
-                                          (leading-plus (format "+%s" x))
-                                          (t x))))
-                          (mh-folder-completion-function folder nil t))))
-    (mh-complete-word folder choices beg end)))
-
-(defvar mh-letter-complete-function-alist
-  '((bcc . mh-alias-letter-expand-alias)
-    (cc . mh-alias-letter-expand-alias)
-    (dcc . mh-alias-letter-expand-alias)
-    (fcc . mh-folder-expand-at-point)
-    (from . mh-alias-letter-expand-alias)
-    (mail-followup-to . mh-alias-letter-expand-alias)
-    (mail-reply-to . mh-alias-letter-expand-alias)
-    (reply-to . mh-alias-letter-expand-alias)
-    (to . mh-alias-letter-expand-alias))
-  "Alist of header fields and completion functions to use.")
-
-(defun mh-letter-complete (arg)
-  "Perform completion on header field or word preceding point.
-
-If the field contains addresses (for example, \"To:\" or \"Cc:\")
-or folders (for example, \"Fcc:\") then this command will provide
-alias completion. In the body of the message, this command runs
-`mh-letter-complete-function' instead, which is set to
-`ispell-complete-word' by default. This command takes a prefix
-argument ARG that is passed to the
-`mh-letter-complete-function'."
-  (interactive "P")
-  (let ((func nil))
-    (cond ((not (mh-in-header-p))
-           (funcall mh-letter-complete-function arg))
-          ((setq func (cdr (assoc (mh-letter-header-field-at-point)
-                                  mh-letter-complete-function-alist)))
-           (funcall func))
-          (t (funcall mh-letter-complete-function arg)))))
-
-(defun mh-letter-complete-or-space (arg)
-  "Perform completion or insert space.
-
-Turn on the option `mh-compose-space-does-completion-flag' to use
-this command to perform completion in the header. Otherwise, a
-space is inserted; use a prefix argument ARG to specify more than
-one space."
-  (interactive "p")
-  (let ((func nil)
-        (end-of-prev (save-excursion
-                       (goto-char (mh-beginning-of-word))
-                       (mh-beginning-of-word -1))))
-    (cond ((not mh-compose-space-does-completion-flag)
-           (self-insert-command arg))
-          ((not (mh-in-header-p)) (self-insert-command arg))
-          ((> (point) end-of-prev) (self-insert-command arg))
-          ((setq func (cdr (assoc (mh-letter-header-field-at-point)
-                                  mh-letter-complete-function-alist)))
-           (funcall func))
-          (t (self-insert-command arg)))))
-
-(defun mh-letter-confirm-address ()
-  "Flash alias expansion.
-
-Addresses are separated by a comma\; when you press the comma,
-this command flashes the alias expansion in the minibuffer if
-`mh-alias-flash-on-comma' is turned on."
-  (interactive)
-  (cond ((not (mh-in-header-p)) (self-insert-command 1))
-        ((eq (cdr (assoc (mh-letter-header-field-at-point)
-                         mh-letter-complete-function-alist))
-             'mh-alias-letter-expand-alias)
-         (mh-alias-reload-maybe)
-         (mh-alias-minibuffer-confirm-address))
-        (t (self-insert-command 1))))
-
-(defvar mh-letter-header-field-regexp "^\\([A-Za-z][A-Za-z0-9-]*\\):")
-
-(defun mh-letter-header-field-at-point ()
-  "Return the header field name at point.
-A symbol is returned whose name is the string obtained by
-downcasing the field name."
-  (save-excursion
-    (end-of-line)
-    (and (re-search-backward mh-letter-header-field-regexp nil t)
-         (intern (downcase (match-string 1))))))
-
-;;;###mh-autoload
-(defun mh-letter-next-header-field-or-indent (arg)
-  "Cycle to next field.
-
-Within the header of the message, this command moves between
-fields that are highlighted with the face
-`mh-letter-header-field', skipping those fields listed in
-`mh-compose-skipped-header-fields'. After the last field, this
-command then moves point to the message body before cycling back
-to the first field. If point is already past the first line of
-the message body, then this command indents by calling
-`indent-relative' with the given prefix argument ARG."
-  (interactive "P")
-  (let ((header-end (save-excursion
-                      (goto-char (mh-mail-header-end))
-                      (forward-line)
-                      (point))))
-    (if (> (point) header-end)
-        (indent-relative arg)
-      (mh-letter-next-header-field))))
-
-(defun mh-letter-next-header-field ()
-  "Cycle to the next header field.
-If we are at the last header field go to the start of the message
-body."
-  (let ((header-end (mh-mail-header-end)))
-    (cond ((>= (point) header-end) (goto-char (point-min)))
-          ((< (point) (progn
-                        (beginning-of-line)
-                        (re-search-forward mh-letter-header-field-regexp
-                                           (line-end-position) t)
-                        (point)))
-           (beginning-of-line))
-          (t (end-of-line)))
-    (cond ((re-search-forward mh-letter-header-field-regexp header-end t)
-           (if (mh-letter-skipped-header-field-p (match-string 1))
-               (mh-letter-next-header-field)
-             (mh-letter-skip-leading-whitespace-in-header-field)))
-          (t (goto-char header-end)
-             (forward-line)))))
-
-;;;###mh-autoload
-(defun mh-letter-previous-header-field ()
-  "Cycle to the previous header field.
-
-This command moves backwards between the fields and cycles to the
-body of the message after the first field. Unlike the command
-\\[mh-letter-next-header-field-or-indent], it will always take
-point to the last field from anywhere in the body."
-  (interactive)
-  (let ((header-end (mh-mail-header-end)))
-    (if (>= (point) header-end)
-        (goto-char header-end)
-      (mh-header-field-beginning))
-    (cond ((re-search-backward mh-letter-header-field-regexp nil t)
-           (if (mh-letter-skipped-header-field-p (match-string 1))
-               (mh-letter-previous-header-field)
-           (goto-char (match-end 0))
-           (mh-letter-skip-leading-whitespace-in-header-field)))
-          (t (goto-char header-end)
-             (forward-line)))))
-
-(defun mh-letter-skipped-header-field-p (field)
-  "Check if FIELD is to be skipped."
-  (let ((field (downcase field)))
-    (loop for x in mh-compose-skipped-header-fields
-          when (equal (downcase x) field) return t
-          finally return nil)))
-
-(defun mh-letter-skip-leading-whitespace-in-header-field ()
-  "Skip leading whitespace in a header field.
-If the header field doesn't have at least one space after the
-colon then a space character is added."
-  (let ((need-space t))
-    (while (memq (char-after) '(?\t ?\ ))
-      (forward-char)
-      (setq need-space nil))
-    (when need-space (insert " "))))
-
-(defvar mh-hidden-header-keymap
-  (let ((map (make-sparse-keymap)))
-    (mh-do-in-gnu-emacs
-      (define-key map [mouse-2] 'mh-letter-toggle-header-field-display-button))
-    (mh-do-in-xemacs
-      (define-key map '(button2)
-        'mh-letter-toggle-header-field-display-button))
-    map))
-
-(defun mh-letter-toggle-header-field-display-button (event)
-  "Toggle header field display at location of EVENT.
-This function does the same thing as
-`mh-letter-toggle-header-field-display' except that it is
-callable from a mouse button."
-  (interactive "e")
-  (mh-do-at-event-location event
-    (mh-letter-toggle-header-field-display nil)))
-
-(defun mh-letter-toggle-header-field-display (arg)
-  "Toggle display of header field at point.
-
-Use this command to display truncated header fields. This command
-is a toggle so entering it again will hide the field. This
-command takes a prefix argument ARG: if negative then the field
-is hidden, if positive then the field is displayed."
-  (interactive (list nil))
-  (when (and (mh-in-header-p)
-             (progn
-               (end-of-line)
-               (re-search-backward mh-letter-header-field-regexp nil t)))
-    (let ((buffer-read-only nil)
-          (modified-flag (buffer-modified-p))
-          (begin (point))
-          end)
-      (end-of-line)
-      (setq end (1- (if (re-search-forward "^[^ \t]" nil t)
-                        (match-beginning 0)
-                      (point-max))))
-      (goto-char begin)
-      ;; Make it clickable...
-      (add-text-properties begin end `(keymap ,mh-hidden-header-keymap
-                                       mouse-face highlight))
-      (unwind-protect
-          (cond ((or (and (not arg)
-                          (text-property-any begin end 'invisible 'vanish))
-                     (and (numberp arg) (>= arg 0))
-                     (and (eq arg 'long) (> (line-beginning-position 5) end)))
-                 (remove-text-properties begin end '(invisible nil))
-                 (search-forward ":" (line-end-position) t)
-                 (mh-letter-skip-leading-whitespace-in-header-field))
-                ;; XXX Redesign to make usable by user. Perhaps use a positive
-                ;; numeric prefix to make that many lines visible.
-                ((eq arg 'long)
-                 (end-of-line 4)
-                 (mh-letter-truncate-header-field end)
-                 (beginning-of-line))
-                (t (end-of-line)
-                   (mh-letter-truncate-header-field end)
-                   (beginning-of-line)))
-        (set-buffer-modified-p modified-flag)))))
-
-(defun mh-letter-truncate-header-field (end)
-  "Replace text from current line till END with an ellipsis.
-If the current line is too long truncate a part of it as well."
-  (let ((max-len (min (window-width) 62)))
-    (when (> (+ (current-column) 4) max-len)
-      (backward-char (- (+ (current-column) 5) max-len)))
-    (when (> end (point))
-      (add-text-properties (point) end '(invisible vanish)))))
-
-(defun mh-letter-hide-all-skipped-fields ()
-  "Hide all skipped fields."
-  (save-excursion
-    (goto-char (point-min))
-    (save-restriction
-      (narrow-to-region (point) (mh-mail-header-end))
-      (while (re-search-forward mh-letter-header-field-regexp nil t)
-        (if (mh-letter-skipped-header-field-p (match-string 1))
-            (mh-letter-toggle-header-field-display -1)
-          (mh-letter-toggle-header-field-display 'long))
-        (beginning-of-line 2)))))
-
-(defun mh-interactive-read-address (prompt)
-  "Read an address.
-If `mh-compose-prompt-flag' is non-nil, then read an address with
-PROMPT.
-Otherwise return the empty string."
-  (if mh-compose-prompt-flag (mh-read-address prompt) ""))
-
-(defun mh-interactive-read-string (prompt)
-  "Read a string.
-If `mh-compose-prompt-flag' is non-nil, then read a string with
-PROMPT.
-Otherwise return the empty string."
-  (if mh-compose-prompt-flag (read-string prompt) ""))
-
-(defun mh-letter-adjust-point ()
-  "Move cursor to first header field if are using the no prompt mode."
-  (unless mh-compose-prompt-flag
-    (goto-char (point-max))
-    (mh-letter-next-header-field)))
-
-
-
-;;; Build mh-letter-mode keymap
-
-;; If this changes, modify mh-letter-mode-help-messages accordingly, above.
-(gnus-define-keys  mh-letter-mode-map
-  " "                   mh-letter-complete-or-space
-  ","                   mh-letter-confirm-address
-  "\C-c?"               mh-help
-  "\C-c\C-\\"           mh-fully-kill-draft ;if no C-q
-  "\C-c\C-^"            mh-insert-signature ;if no C-s
-  "\C-c\C-c"            mh-send-letter
-  "\C-c\C-d"            mh-insert-identity
-  "\C-c\C-e"            mh-mh-to-mime
-  "\C-c\C-f\C-a"        mh-to-field
-  "\C-c\C-f\C-b"        mh-to-field
-  "\C-c\C-f\C-c"        mh-to-field
-  "\C-c\C-f\C-d"        mh-to-field
-  "\C-c\C-f\C-f"        mh-to-fcc
-  "\C-c\C-f\C-l"        mh-to-field
-  "\C-c\C-f\C-m"        mh-to-field
-  "\C-c\C-f\C-r"        mh-to-field
-  "\C-c\C-f\C-s"        mh-to-field
-  "\C-c\C-f\C-t"        mh-to-field
-  "\C-c\C-fa"           mh-to-field
-  "\C-c\C-fb"           mh-to-field
-  "\C-c\C-fc"           mh-to-field
-  "\C-c\C-fd"           mh-to-field
-  "\C-c\C-ff"           mh-to-fcc
-  "\C-c\C-fl"           mh-to-field
-  "\C-c\C-fm"           mh-to-field
-  "\C-c\C-fr"           mh-to-field
-  "\C-c\C-fs"           mh-to-field
-  "\C-c\C-ft"           mh-to-field
-  "\C-c\C-i"            mh-insert-letter
-  "\C-c\C-m\C-e"        mh-mml-secure-message-encrypt
-  "\C-c\C-m\C-f"        mh-compose-forward
-  "\C-c\C-m\C-g"        mh-mh-compose-anon-ftp
-  "\C-c\C-m\C-i"        mh-compose-insertion
-  "\C-c\C-m\C-m"        mh-mml-to-mime
-  "\C-c\C-m\C-n"        mh-mml-unsecure-message
-  "\C-c\C-m\C-s"        mh-mml-secure-message-sign
-  "\C-c\C-m\C-t"        mh-mh-compose-external-compressed-tar
-  "\C-c\C-m\C-u"        mh-mh-to-mime-undo
-  "\C-c\C-m\C-x"        mh-mh-compose-external-type
-  "\C-c\C-mee"          mh-mml-secure-message-encrypt
-  "\C-c\C-mes"          mh-mml-secure-message-signencrypt
-  "\C-c\C-mf"           mh-compose-forward
-  "\C-c\C-mg"           mh-mh-compose-anon-ftp
-  "\C-c\C-mi"           mh-compose-insertion
-  "\C-c\C-mm"           mh-mml-to-mime
-  "\C-c\C-mn"           mh-mml-unsecure-message
-  "\C-c\C-mse"          mh-mml-secure-message-signencrypt
-  "\C-c\C-mss"          mh-mml-secure-message-sign
-  "\C-c\C-mt"           mh-mh-compose-external-compressed-tar
-  "\C-c\C-mu"           mh-mh-to-mime-undo
-  "\C-c\C-mx"           mh-mh-compose-external-type
-  "\C-c\C-o"            mh-open-line
-  "\C-c\C-q"            mh-fully-kill-draft
-  "\C-c\C-s"            mh-insert-signature
-  "\C-c\C-t"            mh-letter-toggle-header-field-display
-  "\C-c\C-w"            mh-check-whom
-  "\C-c\C-y"            mh-yank-cur-msg
-  "\C-c\M-d"            mh-insert-auto-fields
-  "\M-\t"               mh-letter-complete
-  "\t"                  mh-letter-next-header-field-or-indent
-  [backtab]             mh-letter-previous-header-field)
-
-;; "C-c /" prefix is used in mh-letter-mode by pgp.el and mailcrypt.el.
-
 (provide 'mh-comp)
 
 ;; Local Variables:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lisp/mh-e/mh-compat.el	Wed Feb 01 10:07:17 2006 +0000
@@ -0,0 +1,133 @@
+;;; mh-compat.el --- make MH-E compatibile with various versions of Emacs
+
+;; Copyright (C) 2006 Free Software Foundation, Inc.
+
+;; Author: Bill Wohler <wohler@newt.com>
+;; Maintainer: Bill Wohler <wohler@newt.com>
+;; Keywords: mail
+;; See: mh-e.el
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
+
+;;; Commentary:
+
+;;; Change Log:
+
+;;; Code:
+
+;; This is a good place to gather code that is used for compatibility
+;; between different versions of Emacs. Please document which versions
+;; of Emacs that the defsubst, defalias, or defmacro applies. That
+;; way, it's easy to occasionally go through this file and see which
+;; macros we can retire.
+
+;; Please use mh-gnus.el when providing compatibility with different
+;; versions of Gnus and mh-xemacs.el for compatibility with XEmacs.
+
+;; Items are listed alphabetically.
+
+(mh-defun-compat mh-assoc-string assoc-string (key list case-fold)
+  "Like `assoc' but specifically for strings.
+Case is ignored if CASE-FOLD is non-nil.
+This function added by MH-E for Emacs versions that lack
+`assoc-string', introduced in Emacs 22."
+  (if case-fold
+      (assoc-ignore-case key list)
+    (assoc key list)))
+
+(require 'mailabbrev nil t)
+(mh-defun-compat mh-mail-abbrev-make-syntax-table
+  mail-abbrev-make-syntax-table ()
+  "Emacs 21 and XEmacs don't have this function."
+  nil)
+
+(defmacro mh-display-completion-list (completions &optional common-substring)
+  "Display the list of COMPLETIONS.
+See documentation for `display-completion-list' for a description of the
+arguments COMPLETIONS and perhaps COMMON-SUBSTRING.
+This macro added by MH-E for Emacs versions that lack a
+COMMON-SUBSTRING argument, introduced in Emacs 22."
+  (if (< emacs-major-version 22)
+      `(display-completion-list ,completions)
+    `(display-completion-list ,completions ,common-substring)))
+
+(defmacro mh-face-foreground (face &optional frame inherit)
+  "Return the foreground color name of FACE, or nil if unspecified.
+See documentation for `face-foreground' for a description of the
+arguments FACE, FRAME, and perhaps INHERIT.
+This macro added by MH-E for Emacs versions that lack an INHERIT
+argument, introduced in Emacs 22."
+  (if (< emacs-major-version 22)
+      `(face-foreground ,face ,frame)
+    `(face-foreground ,face ,frame ,inherit)))
+
+(defmacro mh-face-background (face &optional frame inherit)
+  "Return the background color name of face, or nil if unspecified.
+See documentation for `back-foreground' for a description of the
+arguments FACE, FRAME, and INHERIT.
+This macro added by MH-E for Emacs versions that lack an INHERIT
+argument, introduced in Emacs 22."
+  (if (< emacs-major-version 22)
+      `(face-background ,face ,frame)
+    `(face-background ,face ,frame ,inherit)))
+
+;; Copy of constant from url-util.el in Emacs 22; needed by Emacs 21.
+(if (not (boundp 'url-unreserved-chars))
+    (defconst mh-url-unresrved-chars
+      '(
+        ?a ?b ?c ?d ?e ?f ?g ?h ?i ?j ?k ?l ?m ?n ?o ?p ?q ?r ?s ?t ?u ?v ?w ?x ?y ?z
+        ?A ?B ?C ?D ?E ?F ?G ?H ?I ?J ?K ?L ?M ?N ?O ?P ?Q ?R ?S ?T ?U ?V ?W ?X ?Y ?Z
+        ?0 ?1 ?2 ?3 ?4 ?5 ?6 ?7 ?8 ?9
+        ?- ?_ ?. ?! ?~ ?* ?' ?\( ?\))
+      "A list of characters that are _NOT_ reserved in the URL spec.
+This is taken from RFC 2396."))
+
+(mh-defun-compat mh-url-hexify-string url-hexify-string (str)
+  "Escape characters in a string.
+This is a copy of `url-hexify-string' from url-util.el in Emacs
+22; needed by Emacs 21."
+  (mapconcat
+   (lambda (char)
+     ;; Fixme: use a char table instead.
+     (if (not (memq char mh-url-unreserved-chars))
+         (if (> char 255)
+               (error "Hexifying multibyte character %s" str)
+           (format "%%%02X" char))
+       (char-to-string char)))
+   str ""))
+
+(defmacro mh-write-file-functions ()
+  "Return `write-file-functions' if it exists.
+Otherwise return `local-write-file-hooks'.
+This macro exists purely for compatibility. The former symbol is used
+in Emacs 22 onward while the latter is used in previous versions and
+XEmacs."
+  (if (boundp 'write-file-functions)
+      ''write-file-functions            ;Emacs 22 on
+    ''local-write-file-hooks))          ;XEmacs
+
+(provide 'mh-compat)
+
+;; Local Variables:
+;; no-byte-compile: t
+;; indent-tabs-mode: nil
+;; sentence-end-double-space: nil
+;; End:
+
+;; arch-tag: 577b0eab-a5cd-45e1-8d9f-c1a426f4d73c
+;;; mh-compat.el ends here
--- a/lisp/mh-e/mh-customize.el	Thu Jan 26 02:23:05 2006 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2902 +0,0 @@
-;;; mh-customize.el --- MH-E customization
-
-;; Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
-
-;; Author: Bill Wohler <wohler@newt.com>
-;; Maintainer: Bill Wohler <wohler@newt.com>
-;; Keywords: mail
-;; See: mh-e.el
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING.  If not, write to the
-;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
-;; Boston, MA 02110-1301, USA.
-
-;;; Commentary:
-
-;; All of the defgroups, defcustoms, and deffaces in MH-E are found
-;; here. This makes it possible to customize modules that aren't loaded
-;; yet. It also makes it easier to organize the customization groups.
-
-;; This file contains the following sections:
-;;
-;; 1. MH-E Customization Groups
-;;
-;;    These are the customization group definitions. Every group has a
-;;    associated manual node. The ordering is alphabetical, except for the
-;;    groups mh-faces and mh-hooks which are last .
-;;
-;; 2. MH-E Customization
-;;
-;;    These are the actual customization variables. There is a sub-section for
-;;    each group in the MH-E Customization Groups section, in the same order,
-;;    separated by page breaks. Within each section, variables are sorted
-;;    alphabetically.
-;;
-;; 3. Hooks
-;;
-;;    All hooks must be placed in the mh-hook group; in addition, add the
-;;    group associated with the manual node in which the hook is described.
-;;    Since the mh-hook group appears near the end of this file, the hooks
-;;    will appear at the end of these other groups.
-;;
-;; 4. Faces
-;;
-;;    All faces must be placed in the mh-faces group; in addition, add the
-;;    group associated with the manual node in which the face is described.
-;;    Since the mh-faces group appears near the end of this file, the faces
-;;    will appear at the end of these other groups.
-;;
-;;; Change Log:
-
-;;; Code:
-
-;;(message "> mh-customize")
-(provide 'mh-customize)
-
-(eval-when-compile (require 'mh-acros))
-(mh-require-cl)
-
-(eval-and-compile
-  (defvar mh-xemacs-flag (featurep 'xemacs)
-    "Non-nil means the current Emacs is XEmacs.")
-  (when mh-xemacs-flag
-    (require 'mh-xemacs)))
-
-(eval-and-compile
-  (require 'mh-identity)
-  (require 'mh-init)
-  (require 'mh-loaddefs))
-;;(message "< mh-customize")
-
-;; For compiler warnings...
-(eval-when-compile
-  (defvar mh-show-buffer)
-  (defvar mh-show-folder-buffer))
-
-(defun mh-customize (&optional delete-other-windows-flag)
-  "Customize MH-E variables.
-If optional argument DELETE-OTHER-WINDOWS-FLAG is non-nil, other
-windows in the frame are removed."
-  (interactive "P")
-  (customize-group 'mh-e)
-  (when delete-other-windows-flag
-    (delete-other-windows)))
-
-
-
-;;; MH-E Customization Groups
-
-(defgroup mh-e nil
-  "Emacs interface to the MH mail system.
-MH is the Rand Mail Handler. Other implementations include nmh
-and GNU mailutils."
-  :link '(custom-manual "(mh-e)Top")
-  :group 'mail)
-
-(defgroup mh-alias nil
-  "Aliases."
-  :link '(custom-manual "(mh-e)Aliases")
-  :prefix "mh-alias-"
-  :group 'mh-e)
-
-(defgroup mh-folder nil
-  "Organizing your mail with folders."
-  :prefix "mh-"
-  :link '(custom-manual "(mh-e)Folders")
-  :group 'mh-e)
-
-(defgroup mh-folder-selection nil
-  "Folder selection."
-  :prefix "mh-"
-  :link '(custom-manual "(mh-e)Folder Selection")
-  :group 'mh-e)
-
-(defgroup mh-identity nil
-  "Identities."
-  :link '(custom-manual "(mh-e)Identities")
-  :prefix "mh-identity-"
-  :group 'mh-e)
-
-(defgroup mh-inc nil
-  "Incorporating your mail."
-  :prefix "mh-inc-"
-  :link '(custom-manual "(mh-e)Incorporating Mail")
-  :group 'mh-e)
-
-(defgroup mh-junk nil
-  "Dealing with junk mail."
-  :link '(custom-manual "(mh-e)Junk")
-  :prefix "mh-junk-"
-  :group 'mh-e)
-
-(defgroup mh-letter nil
-  "Editing a draft."
-  :prefix "mh-"
-  :link '(custom-manual "(mh-e)Editing Drafts")
-  :group 'mh-e)
-
-(defgroup mh-ranges nil
-  "Ranges."
-  :prefix "mh-"
-  :link '(custom-manual "(mh-e)Ranges")
-  :group 'mh-e)
-
-(defgroup mh-scan-line-formats nil
-  "Scan line formats."
-  :link '(custom-manual "(mh-e)Scan Line Formats")
-  :prefix "mh-"
-  :group 'mh-e)
-
-(defgroup mh-search nil
-  "Searching."
-  :link '(custom-manual "(mh-e)Searching")
-  :prefix "mh-search-"
-  :group 'mh-e)
-
-(defgroup mh-sending-mail nil
-  "Sending mail."
-  :prefix "mh-"
-  :link '(custom-manual "(mh-e)Sending Mail")
-  :group 'mh-e)
-
-(defgroup mh-sequences nil
-  "Sequences."
-  :prefix "mh-"
-  :link '(custom-manual "(mh-e)Sequences")
-  :group 'mh-e)
-
-(defgroup mh-show nil
-  "Reading your mail."
-  :prefix "mh-"
-  :link '(custom-manual "(mh-e)Reading Mail")
-  :group 'mh-e)
-
-(defgroup mh-speedbar nil
-  "The speedbar."
-  :prefix "mh-speed-"
-  :link '(custom-manual "(mh-e)Speedbar")
-  :group 'mh-e)
-
-(defgroup mh-thread nil
-  "Threading."
-  :prefix "mh-thread-"
-  :link '(custom-manual "(mh-e)Threading")
-  :group 'mh-e)
-
-(defgroup mh-tool-bar nil
-  "The tool bar"
-  :link '(custom-manual "(mh-e)Tool Bar")
-  :prefix "mh-"
-  :group 'mh-e)
-
-(defgroup mh-hooks nil
-  "MH-E hooks."
-  :link '(custom-manual "(mh-e)Top")
-  :prefix "mh-"
-  :group 'mh-e)
-
-(defgroup mh-faces nil
-  "Faces used in MH-E."
-  :link '(custom-manual "(mh-e)Top")
-  :prefix "mh-"
-  :group 'faces
-  :group 'mh-e)
-
-
-
-;;; Emacs interface to the MH mail system (:group mh-e)
-(eval-when (compile)
-  (setq mh-variant 'none))
-
-(defcustom mh-path nil
-  "*Additional list of directories to search for MH.
-See `mh-variant'."
-  :group 'mh-e
-  :type '(repeat (directory)))
-
-(defcustom mh-variant 'autodetect
-  "*Specifies the variant used by MH-E.
-
-The default setting of this option is \"Auto-detect\" which means
-that MH-E will automatically choose the first of nmh, MH, or GNU
-mailutils that it finds in the directories listed in
-`mh-path' (which you can customize), `mh-sys-path', and
-`exec-path'. If, for example, you have both nmh and mailutils
-installed and `mh-variant-in-use' was initialized to nmh but you
-want to use mailutils, then you can set this option to
-\"mailutils\".
-
-When this variable is changed, MH-E resets `mh-progs', `mh-lib',
-`mh-lib-progs', `mh-flists-present-flag', and `mh-variant-in-use'
-accordingly."
-  :type `(radio
-          (const :tag "Auto-detect" autodetect)
-          ,@(mapcar (lambda (x) `(const ,(car x))) (mh-variants)))
-  :set (lambda (symbol value)
-         (set-default symbol value)     ;Done in mh-variant-set-variant!
-         (mh-variant-set value))
-  :group 'mh-e)
-
-
-
-;;; Aliases (:group 'mh-alias)
-
-(defcustom mh-alias-completion-ignore-case-flag t
-  "*Non-nil means don't consider case significant in MH alias completion.
-
-As MH ignores case in the aliases, so too does MH-E. However, you
-may turn off this option to make case significant which can be
-used to segregate completion of your aliases. You might use
-lowercase for mailing lists and uppercase for people."
-  :type 'boolean
-  :group 'mh-alias)
-
-(defcustom mh-alias-expand-aliases-flag nil
-  "*Non-nil means to expand aliases entered in the minibuffer.
-
-In other words, aliases entered in the minibuffer will be
-expanded to the full address in the message draft. By default,
-this expansion is not performed."
-  :type 'boolean
-  :group 'mh-alias)
-
-(defcustom mh-alias-flash-on-comma t
-  "*Specify whether to flash address or warn on translation.
-
-This option controls the behavior when a [comma] is pressed while
-entering aliases or addresses. The default setting flashes the
-address associated with an address in the minibuffer briefly, but
-does not display a warning if the alias is not found."
-  :type '(choice (const :tag "Flash but Don't Warn If No Alias" t)
-                 (const :tag "Flash and Warn If No Alias" 1)
-                 (const :tag "Don't Flash Nor Warn If No Alias" nil))
-  :group 'mh-alias)
-
-(defcustom mh-alias-insert-file nil
-  "*Filename used to store a new MH-E alias.
-
-The default setting of this option is \"Use Aliasfile Profile
-Component\". This option can also hold the name of a file or a
-list a file names. If this option is set to a list of file names,
-or the \"Aliasfile:\" profile component contains more than one file
-name, MH-E will prompt for one of them when MH-E adds an alias."
-  :type '(choice (const :tag "Use Aliasfile Profile Component" nil)
-                 (file :tag "Alias File")
-                 (repeat :tag "List of Alias Files" file))
-  :group 'mh-alias)
-
-(defcustom mh-alias-insertion-location 'sorted
-  "Specifies where new aliases are entered in alias files.
-
-This option is set to \"Alphabetical\" by default. If you organize
-your alias file in other ways, then adding aliases to the \"Top\"
-or \"Bottom\" of your alias file might be more appropriate."
-  :type '(choice (const :tag "Alphabetical" sorted)
-                 (const :tag "Top" top)
-                 (const :tag "Bottom" bottom))
-  :group 'mh-alias)
-
-(defcustom mh-alias-local-users t
-  "*If on, local users are added to alias completion.
-
-Aliases are created from \"/etc/passwd\" entries with a user ID
-larger than a magical number, typically 200. This can be a handy
-tool on a machine where you and co-workers exchange messages.
-These aliases have the form \"local.first.last\" if a real name is
-present in the password file. Otherwise, the alias will have the
-form \"local.login\".
-
-If you're on a system with thousands of users you don't know, and
-the loading of local aliases slows MH-E down noticeably, then
-turn this option off.
-
-This option also takes a string which is executed to generate the
-password file. For example, use \"ypcat passwd\" to obtain the
-NIS password file."
-  :type '(choice (boolean) (string))
-  :group 'mh-alias)
-
-(defcustom mh-alias-local-users-prefix "local."
-  "*String prefixed to the real names of users from the password file.
-This option can also be set to \"Use Login\".
-
-For example, consider the following password file entry:
-
-    psg:x:1000:1000:Peter S Galbraith,,,:/home/psg:/bin/tcsh
-
-The following settings of this option will produce the associated
-aliases:
-
-    \"local.\"                  local.peter.galbraith
-    \"\"                        peter.galbraith
-    Use Login                   psg
-
-This option has no effect if variable `mh-alias-local-users' is
-turned off."
-  :type '(choice (const :tag "Use Login" nil)
-                 (string))
-  :group 'mh-alias)
-
-(defcustom mh-alias-passwd-gecos-comma-separator-flag t
-  "*Non-nil means the gecos field in the password file uses a comma separator.
-
-In the example in `mh-alias-local-users-prefix', commas are used
-to separate different values within the so-called gecos field.
-This is a fairly common usage. However, in the rare case that the
-gecos field in your password file is not separated by commas and
-whose contents may contain commas, you can turn this option off."
-  :type 'boolean
-  :group 'mh-alias)
-
-
-
-;;; Organizing Your Mail with Folders (:group 'mh-folder)
-
-(defcustom mh-new-messages-folders t
-  "Folders searched for the \"unseen\" sequence.
-
-Set this option to \"Inbox\" to search the \"+inbox\" folder or
-\"All\" to search all of the top level folders. Otherwise, list
-the folders that should be searched with the \"Choose Folders\"
-menu item.
-
-See also `mh-recursive-folders-flag'."
-  :type '(choice (const :tag "Inbox" t)
-                 (const :tag "All" nil)
-                 (repeat :tag "Choose Folders" (string :tag "Folder")))
-  :group 'mh-folder)
-
-(defcustom mh-ticked-messages-folders t
-  "Folders searched for `mh-tick-seq'.
-
-Set this option to \"Inbox\" to search the \"+inbox\" folder or
-\"All\" to search all of the top level folders. Otherwise, list
-the folders that should be searched with the \"Choose Folders\"
-menu item.
-
-See also `mh-recursive-folders-flag'."
-  :type '(choice (const :tag "Inbox" t)
-                 (const :tag "All" nil)
-                 (repeat :tag "Choose Folders" (string :tag "Folder")))
-  :group 'mh-folder)
-
-(defcustom mh-large-folder 200
-  "The number of messages that indicates a large folder.
-
-If a folder is deemed to be large, that is the number of messages
-in it exceed this value, then confirmation is needed when it is
-visited. Even when `mh-show-threads-flag' is non-nil, the folder
-is not automatically threaded, if it is large. If set to nil all
-folders are treated as if they are small."
-  :type '(choice (const :tag "No Limit") integer)
-  :group 'mh-folder)
-
-(defcustom mh-recenter-summary-flag nil
-  "*Non-nil means to recenter the summary window.
-
-If this option is turned on, recenter the summary window when the
-show window is toggled off."
-  :type 'boolean
-  :group 'mh-folder)
-
-(defcustom mh-recursive-folders-flag nil
-  "*Non-nil means that commands which operate on folders do so recursively."
-  :type 'boolean
-  :group 'mh-folder)
-
-(defcustom mh-sortm-args nil
-  "*Additional arguments for \"sortm\"\\<mh-folder-mode-map>.
-
-This option is consulted when a prefix argument is used with
-\\[mh-sort-folder]. Normally default arguments to \"sortm\" are
-specified in the MH profile. This option may be used to provide
-an alternate view. For example, \"'(\"-nolimit\" \"-textfield\"
-\"subject\")\" is a useful setting."
-  :type 'string
-  :group 'mh-folder)
-
-
-
-;;; Folder Selection (:group 'mh-folder-selection)
-
-(defcustom mh-default-folder-for-message-function nil
-  "Function to select a default folder for refiling or \"Fcc:\".
-
-The current buffer is set to the message being refiled with point
-at the start of the message. This function should return the
-default folder as a string with a leading \"+\" sign. It can also
-return nil so that the last folder name is used as the default,
-or an empty string to suppress the default entirely."
-  :type 'function
-  :group 'mh-folder-selection)
-
-(defcustom mh-default-folder-list nil
-  "*List of addresses and folders.
-
-The folder name associated with the first address found in this
-list is used as the default for `mh-refile-msg' and similar
-functions. Each element in this list contains a \"Check Recipient\"
-item. If this item is turned on, then the address is checked
-against the recipient instead of the sender. This is useful for
-mailing lists.
-
-See `mh-prompt-for-refile-folder' and `mh-folder-from-address'
-for more information."
-  :type '(repeat (list (regexp :tag "Address")
-                       (string :tag "Folder")
-                       (boolean :tag "Check Recipient")))
-  :group 'mh-folder-selection)
-
-(defcustom mh-default-folder-must-exist-flag t
-  "*Non-nil means guessed folder name must exist to be used.
-
-If the derived folder does not exist, and this option is on, then
-the last folder name used is suggested. This is useful if you get
-mail from various people for whom you have an alias, but file
-them all in the same project folder.
-
-See `mh-prompt-for-refile-folder' and `mh-folder-from-address'
-for more information."
-  :type 'boolean
-  :group 'mh-folder-selection)
-
-(defcustom mh-default-folder-prefix ""
-  "*Prefix used for folder names generated from aliases.
-The prefix is used to prevent clutter in your mail directory.
-
-See `mh-prompt-for-refile-folder' and `mh-folder-from-address'
-for more information."
-  :type 'string
-  :group 'mh-folder-selection)
-
-
-
-;;; Identities (:group 'mh-identity)
-
-(defcustom mh-identity-list nil
-  "*List of identities.
-
-To customize this option, click on the \"INS\" button and enter a label
-such as \"Home\" or \"Work\". Then click on the \"INS\" button with the
-label \"Add at least one item below\". Then choose one of the items in
-the \"Value Menu\".
-
-You can specify an alternate \"From:\" header field using the \"From
-Field\" menu item. You must include a valid email address. A standard
-format is \"First Last <login@@host.domain>\". If you use an initial
-with a period, then you must quote your name as in '\"First I. Last\"
-<login@@host.domain>'. People usually list the name of the company
-where they work using the \"Organization Field\" menu item. Set any
-arbitrary header field and value in the \"Other Field\" menu item.
-Unless the header field is a standard one, precede the name of your
-field's label with \"X-\", as in \"X-Fruit-of-the-Day:\". The value of
-\"Attribution Verb\" overrides the setting of
-`mh-extract-from-attribution-verb'. Set your signature with the
-\"Signature\" menu item. You can specify the contents of
-`mh-signature-file-name', a file, or a function. Specify a different
-key to sign or encrypt messages with the \"GPG Key ID\" menu item.
-
-You can select the identities you have added via the menu called
-\"Identity\" in the MH-Letter buffer. You can also use
-\\[mh-insert-identity]. To clear the fields and signature added by the
-identity, select the \"None\" identity.
-
-The \"Identity\" menu contains two other items to save you from having
-to set the identity on every message. The menu item \"Set Default for
-Session\" can be used to set the default identity to the current
-identity until you exit Emacs. The menu item \"Save as Default\" sets
-the option `mh-identity-default' to the current identity setting. You
-can also customize the `mh-identity-default' option in the usual
-fashion."
-  :type '(repeat (list :tag ""
-                       (string :tag "Label")
-                       (repeat :tag "Add at least one item below"
-                               (choice
-                                (cons :tag "From Field"
-                                      (const "From")
-                                      (string :tag "Value"))
-                                (cons :tag "Organization Field"
-                                      (const "Organization")
-                                      (string :tag "Value"))
-                                (cons :tag "Other Field"
-                                      (string :tag "Field")
-                                      (string :tag "Value"))
-                                (cons :tag "Attribution Verb"
-                                      (const ":attribution-verb")
-                                      (string :tag "Value"))
-                                (cons :tag "Signature"
-                                      (const :tag "Signature"
-                                             ":signature")
-                                      (choice
-                                       (const :tag "mh-signature-file-name"
-                                              nil)
-                                       (file)
-                                       (function)))
-                                (cons :tag "GPG Key ID"
-                                      (const :tag "GPG Key ID"
-                                             ":pgg-default-user-id")
-                                      (string :tag "Value"))))))
-  :set 'mh-identity-list-set
-  :group 'mh-identity)
-
-(defcustom mh-auto-fields-list nil
-  "List of recipients for which header lines are automatically inserted.
-
-This option can be used to set the identity depending on the
-recipient. To customize this option, click on the \"INS\" button and
-enter a regular expression for the recipient's address. Click on the
-\"INS\" button with the \"Add at least one item below\" label. Then choose
-one of the items in the \"Value Menu\".
-
-The \"Identity\" menu item is used to select an identity from those
-configured in `mh-identity-list'. All of the information for that
-identity will be added if the recipient matches. The \"Fcc Field\" menu
-item is used to select a folder that is used in the \"Fcc:\" header.
-When you send the message, MH will put a copy of your message in this
-folder. The \"Mail-Followup-To Field\" menu item is used to insert an
-\"Mail-Followup-To:\" header field with the recipients you provide. If
-the recipient's mail user agent supports this header field (as nmh
-does), then their replies will go to the addresses listed. This is
-useful if their replies go both to the list and to you and you don't
-have a mechanism to suppress duplicates. If you reply to someone not
-on the list, you must either remove the \"Mail-Followup-To:\" field, or
-ensure the recipient is also listed there so that he receives replies
-to your reply. Other header fields may be added using the \"Other
-Field\" menu item.
-
-These fields can only be added after the recipient is known. Once the
-header contains one or more recipients, run the
-\\[mh-insert-auto-fields] command or choose the \"Identity -> Insert
-Auto Fields\" menu item to insert these fields manually. However, you
-can just send the message and the fields will be added automatically.
-You are given a chance to see these fields and to confirm them before
-the message is actually sent. You can do away with this confirmation
-by turning off the option `mh-auto-fields-prompt-flag'.
-
-You should avoid using the same header field in `mh-auto-fields-list'
-and `mh-identity-list' definitions that may apply to the same message
-as the result is undefined."
-  :type `(repeat
-          (list :tag ""
-                (string :tag "Recipient")
-                (repeat :tag "Add at least one item below"
-                        (choice
-                         (cons :tag "Identity"
-                               (const ":identity")
-                               ,(append
-                                 '(radio)
-                                 (mapcar
-                                  (function (lambda (arg) `(const ,arg)))
-                                  (mapcar 'car mh-identity-list))))
-                         (cons :tag "Fcc Field"
-                               (const "fcc")
-                               (string :tag "Value"))
-                         (cons :tag "Mail-Followup-To Field"
-                               (const "Mail-Followup-To")
-                               (string :tag "Value"))
-                         (cons :tag "Other Field"
-                                 (string :tag "Field")
-                                 (string :tag "Value"))))))
-  :group 'mh-identity)
-
-(defcustom mh-auto-fields-prompt-flag t
-  "*Non-nil means to prompt before sending if fields inserted.
-See `mh-auto-fields-list'."
-  :type 'boolean
-  :group 'mh-identity)
-
-(defcustom mh-identity-default nil
-  "Default identity to use when `mh-letter-mode' is called.
-See `mh-identity-list'."
-  :type (append
-         '(radio)
-         (cons '(const :tag "None" nil)
-               (mapcar (function (lambda (arg) `(const ,arg)))
-                       (mapcar 'car mh-identity-list))))
-  :group 'mh-identity)
-
-(defcustom mh-identity-handlers
-  '(("From" . mh-identity-handler-top)
-    (":default" . mh-identity-handler-bottom)
-    (":attribution-verb" . mh-identity-handler-attribution-verb)
-    (":signature" . mh-identity-handler-signature)
-    (":pgg-default-user-id" . mh-identity-handler-gpg-identity))
-  "Handler functions for fields in `mh-identity-list'.
-
-This option is used to change the way that fields, signatures,
-and attributions in `mh-identity-list' are added. To customize
-`mh-identity-handlers', replace the name of an existing handler
-function associated with the field you want to change with the
-name of a function you have written. You can also click on an
-\"INS\" button and insert a field of your choice and the name of
-the function you have written to handle it.
-
-The \"Field\" field can be any field that you've used in your
-`mh-identity-list'. The special fields \":attribution-verb\",
-\":signature\", or \":pgg-default-user-id\" are used for the
-`mh-identity-list' choices \"Attribution Verb\", \"Signature\", and
-\"GPG Key ID\" respectively.
-
-The handler associated with the \":default\" field is used when no
-other field matches.
-
-The handler functions are passed two or three arguments: the
-FIELD itself (for example, \"From\"), or one of the special
-fields (for example, \":signature\"), and the ACTION 'remove or
-'add. If the action is 'add, an additional argument
-containing the VALUE for the field is given."
-  :type '(repeat (cons (string :tag "Field") function))
-  :group 'mh-identity)
-
-
-
-;;; Incorporating Your Mail (:group 'mh-inc)
-
-(defcustom mh-inc-prog "inc"
-  "*Program to incorporate new mail into a folder.
-
-This program generates a one-line summary for each of the new
-messages. Unless it is an absolute pathname, the file is assumed
-to be in the `mh-progs' directory. You may also link a file to
-\"inc\" that uses a different format. You'll then need to modify
-several scan line format variables appropriately."
-  :type 'string
-  :group 'mh-inc)
-
-(defcustom mh-inc-spool-list nil
-  "*Alternate spool files.
-
-You can use the `mh-inc-spool-list' variable to direct MH-E to
-retrieve mail from arbitrary spool files other than your system
-mailbox, file it in folders other than your \"+inbox\", and assign
-key bindings to incorporate this mail.
-
-Suppose you are subscribed to the \"mh-e-devel\" mailing list and
-you use \"procmail\" to filter this mail into \"~/mail/mh-e\" with
-the following recipe in \".procmailrc\":
-
-    MAILDIR=$HOME/mail
-    :0:
-    * ^From mh-e-devel-admin@stop.mail-abuse.org
-    mh-e
-
-In order to incorporate \"~/mail/mh-e\" into \"+mh-e\" with an
-\"I m\" (mh-inc-spool-mh-e) command, customize this option, and click
-on the \"INS\" button. Enter a \"Spool File\" of \"~/mail/mh-e\", a
-\"Folder\" of \"mh-e\", and a \"Key Binding\" of \"m\".
-
-You can use \"xbuffy\" to automate the incorporation of this mail
-using the \"gnudoit\" command in the \"gnuserv\" package as follows:
-
-    box ~/mail/mh-e
-        title mh-e
-        origMode
-        polltime 10
-        headertime 0
-        command gnudoit -q '(mh-inc-spool-mh-e)'"
-  :type '(repeat (list (file :tag "Spool File")
-                       (string :tag "Folder")
-                       (character :tag "Key Binding")))
-  :set 'mh-inc-spool-list-set
-  :group 'mh-inc)
-
-
-
-;;; Dealing with Junk Mail (:group 'mh-junk)
-
-;; Spam fighting program chosen
-(defvar mh-junk-choice nil)
-
-;; Available spam filter interfaces
-(defvar mh-junk-function-alist
-  '((spamassassin mh-spamassassin-blacklist mh-spamassassin-whitelist)
-    (bogofilter mh-bogofilter-blacklist mh-bogofilter-whitelist)
-    (spamprobe mh-spamprobe-blacklist mh-spamprobe-whitelist))
-  "Available choices of spam programs to use.
-
-This is an alist. For each element there are functions that
-blacklist a message as spam and whitelist a message incorrectly
-classified as spam.")
-
-(defun mh-junk-choose (symbol value)
-  "Choose spam program to use.
-
-The function is always called with SYMBOL bound to
-`mh-junk-program' and VALUE bound to the new value of
-`mh-junk-program'. The function sets the variable
-`mh-junk-choice' in addition to `mh-junk-program'."
-  (set symbol value)
-  (setq mh-junk-choice
-        (or value
-            (loop for element in mh-junk-function-alist
-                  until (executable-find (symbol-name (car element)))
-                  finally return (car element)))))
-
-;; User customizable variables
-(defcustom mh-junk-background nil
-  "If on, spam programs are run in background.
-
-By default, the programs are run in the foreground, but this can
-be slow when junking large numbers of messages. If you have
-enough memory or don't junk that many messages at the same time,
-you might try turning on this option."
-  :type '(choice (const :tag "Off" nil)
-                 (const :tag "On" 0))
-  :group 'mh-junk)
-
-(defcustom mh-junk-disposition nil
-  "Disposition of junk mail."
-  :type '(choice (const :tag "Delete Spam" nil)
-                 (string :tag "Spam Folder"))
-  :group 'mh-junk)
-
-(defcustom mh-junk-program nil
-  "Spam program that MH-E should use.
-
-The default setting of this option is \"Auto-detect\" which means
-that MH-E will automatically choose one of SpamAssassin,
-bogofilter, or SpamProbe in that order. If, for example, you have
-both SpamAssassin and bogofilter installed and you want to use
-bogofilter, then you can set this option to \"Bogofilter\"."
-  :type '(choice (const :tag "Auto-detect" nil)
-                 (const :tag "SpamAssassin" spamassassin)
-                 (const :tag "Bogofilter" bogofilter)
-                 (const :tag "SpamProbe" spamprobe))
-  :set 'mh-junk-choose
-  :group 'mh-junk)
-
-
-
-;;; Editing a Draft (:group 'mh-letter)
-
-(defcustom mh-compose-insertion (if (locate-library "mml") 'mml 'mh)
-  "Type of tags used when composing MIME messages.
-
-In addition to MH-style directives, MH-E also supports MML (MIME
-Meta Language) tags. (see Info node `(emacs-mime)Composing').
-This option can be used to choose between them. By default, this
-option is set to \"MML\" if it is supported since it provides a
-lot more functionality. This option can also be set to \"MH\" if
-MH-style directives are preferred."
-  :type '(choice (const :tag "MML" mml)
-                 (const :tag "MH"  mh))
-  :group 'mh-letter)
-
-(defcustom mh-compose-skipped-header-fields
-  '("From" "Organization" "References" "In-Reply-To"
-    "X-Face" "Face" "X-Image-URL" "X-Mailer")
-  "List of header fields to skip over when navigating in draft."
-  :type '(repeat (string :tag "Field"))
-  :group 'mh-letter)
-
-(defcustom mh-compose-space-does-completion-flag nil
-  "*Non-nil means \\<mh-letter-mode-map>\\[mh-letter-complete-or-space] does completion in message header."
-  :type 'boolean
-  :group 'mh-letter)
-
-(defcustom mh-delete-yanked-msg-window-flag nil
-  "*Non-nil means delete any window displaying the message.
-
-This deletes the window containing the original message after
-yanking it with \\<mh-letter-mode-map>\\[mh-yank-cur-msg] to make
-more room on your screen for your reply."
-  :type 'boolean
-  :group 'mh-letter)
-
-(defcustom mh-extract-from-attribution-verb "wrote:"
-  "*Verb to use for attribution when a message is yanked by \\<mh-letter-mode-map>\\[mh-yank-cur-msg].
-
-The attribution consists of the sender's name and email address
-followed by the content of this option. This option can be set to
-\"wrote:\", \"a écrit:\", and \"schrieb:\". You can also use the
-\"Custom String\" menu item to enter your own verb."
-  :type '(choice (const "wrote:")
-                 (const "a écrit:")
-                 (const "schrieb:")
-                 (string :tag "Custom String"))
-  :group 'mh-letter)
-
-(defcustom mh-ins-buf-prefix "> "
-  "*String to put before each line of a yanked or inserted message.
-
-The prefix \"> \" is the default setting of this option. I
-suggest that you not modify this option since it is used by many
-mailers and news readers: messages are far easier to read if
-several included messages have all been indented by the same
-string.
-
-This prefix is not inserted if you use one of the supercite
-flavors of `mh-yank-behavior' or you have added a
-`mail-citation-hook'."
-  :type 'string
-  :group 'mh-letter)
-
-(defcustom mh-letter-complete-function 'ispell-complete-word
-  "*Function to call when completing outside of address or folder fields.
-
-In the body of the message,
-\\<mh-letter-mode-map>\\[mh-letter-complete] runs this function,
-which is set to \"ispell-complete-word\" by default."
-  :type '(choice function (const nil))
-  :group 'mh-letter)
-
-(defcustom mh-letter-fill-column 72
-  "*Fill column to use in MH Letter mode.
-
-By default, this option is 72 to allow others to quote your
-message without line wrapping."
-  :type 'integer
-  :group 'mh-letter)
-
-(defcustom mh-mml-method-default (if mh-pgp-support-flag "pgpmime" "none")
-  "Default method to use in security tags.
-
-This option is used to select between a variety of mail security
-mechanisms. The default is \"PGP (MIME)\" if it is supported\;
-otherwise, the default is \"None\". Other mechanisms include
-vanilla \"PGP\" and \"S/MIME\".
-
-The `pgg' customization group may have some settings which may
-interest you (see Info node `(pgg)').
-
-In particular, I turn on the option `pgg-encrypt-for-me' so that
-all messages I encrypt are encrypted with my public key as well.
-If you keep a copy of all of your outgoing mail with a \"Fcc:\"
-header field, this setting is vital so that you can read the mail
-you write!"
-  :type '(choice (const :tag "PGP (MIME)" "pgpmime")
-                 (const :tag "PGP" "pgp")
-                 (const :tag "S/MIME" "smime")
-                 (const :tag "None" "none"))
-  :group 'mh-letter)
-
-(defcustom mh-signature-file-name "~/.signature"
-  "*Source of user's signature.
-
-By default, the text of your signature is taken from the file
-\"~/.signature\". You can read from other sources by changing this
-option. This file may contain a vCard in which case an attachment is
-added with the vCard.
-
-This option may also be a symbol, in which case that function is
-called. You may not want a signature separator to be added for you;
-instead you may want to insert one yourself. Options that you may find
-useful to do this include `mh-signature-separator' (when inserting a
-signature separator) and `mh-signature-separator-regexp' (for finding
-said separator). The function `mh-signature-separator-p', which
-reports t if the buffer contains a separator, may be useful as well.
-
-The signature is inserted into your message with the command
-\\<mh-letter-mode-map>\\[mh-insert-signature] or with the option
-`mh-identity-list'."
-  :type 'file
-  :group 'mh-letter)
-
-(defcustom mh-signature-separator-flag t
-  "*Non-nil means a signature separator should be inserted.
-
-It is not recommended that you change this option since various
-mail user agents, including MH-E, use the separator to present
-the signature differently, and to suppress the signature when
-replying or yanking a letter into a draft."
-  :type 'boolean
-  :group 'mh-letter)
-
-(defcustom mh-x-face-file "~/.face"
-  "*File containing face header field to insert in outgoing mail.
-
-If the file starts with either of the strings \"X-Face:\", \"Face:\"
-or \"X-Image-URL:\" then the contents are added to the message header
-verbatim. Otherwise it is assumed that the file contains the value of
-the \"X-Face:\" header field.
-
-The \"X-Face:\" header field, which is a low-resolution, black and
-white image, can be generated using the \"compface\" command (see URL
-`ftp://ftp.cs.indiana.edu/pub/faces/compface/compface.tar.Z'). The
-\"Online X-Face Converter\" is a useful resource for quick conversion
-of images into \"X-Face:\" header fields (see URL
-`http://www.dairiki.org/xface/').
-
-Use the \"make-face\" script to convert a JPEG image to the higher
-resolution, color, \"Face:\" header field (see URL
-`http://quimby.gnus.org/circus/face/make-face').
-
-The URL of any image can be used for the \"X-Image-URL:\" field and no
-processing of the image is required.
-
-To prevent the setting of any of these header fields, either set
-`mh-x-face-file' to nil, or simply ensure that the file defined by
-this option doesn't exist."
-  :type 'file
-  :group 'mh-letter)
-
-(defcustom mh-yank-behavior 'attribution
-  "*Controls which part of a message is yanked by \\<mh-letter-mode-map>\\[mh-yank-cur-msg].
-
-To include the entire message, including the entire header, use
-\"Body and Header\". Use \"Body\" to yank just the body without
-the header. To yank only the portion of the message following the
-point, set this option to \"Below Point\".
-
-Choose \"Invoke supercite\" to pass the entire message and header
-through supercite.
-
-If the \"Body With Attribution\" setting is used, then the
-message minus the header is yanked and a simple attribution line
-is added at the top using the value of the option
-`mh-extract-from-attribution-verb'. This is the default.
-
-If the \"Invoke supercite\" or \"Body With Attribution\" settings
-are used, the \"-noformat\" argument is passed to the \"repl\"
-program to override a \"-filter\" or \"-format\" argument. These
-settings also have \"Automatically\" variants that perform the
-action automatically when you reply so that you don't need to use
-\\[mh-yank-cur-msg] at all. Note that this automatic action is
-only performed if the show buffer matches the message being
-replied to. People who use the automatic variants tend to turn on
-the option `mh-delete-yanked-msg-window-flag' as well so that the
-show window is never displayed.
-
-If the show buffer has a region, the option `mh-yank-behavior' is
-ignored unless its value is one of Attribution variants in which
-case the attribution is added to the yanked region.
-
-If this option is set to one of the supercite flavors, the hook
-`mail-citation-hook' is ignored and `mh-ins-buf-prefix' is not
-inserted."
-  :type '(choice (const :tag "Body and Header" t)
-                 (const :tag "Body" body)
-                 (const :tag "Below Point" nil)
-                 (const :tag "Invoke supercite" supercite)
-                 (const :tag "Invoke supercite, Automatically" autosupercite)
-                 (const :tag "Body With Attribution" attribution)
-                 (const :tag "Body With Attribution, Automatically"
-                        autoattrib))
-  :group 'mh-letter)
-
-
-
-;;; Ranges (:group 'mh-ranges)
-
-(defcustom mh-interpret-number-as-range-flag t
-  "*Non-nil means interpret a number as a range.
-
-Since one of the most frequent ranges used is \"last:N\", MH-E
-will interpret input such as \"200\" as \"last:200\" if this
-option is on (which is the default). If you need to scan just the
-message 200, then use the range \"200:200\"."
-  :type 'boolean
-  :group 'mh-ranges)
-
-
-
-;;; Scan Line Formats (:group 'mh-scan-line-formats)
-
-;; Forward definition.
-(defvar mh-scan-format-file t)
-
-(defun mh-adaptive-cmd-note-flag-check (symbol value)
-  "Check if desired setting is legal.
-Throw an error if user tries to turn on
-`mh-adaptive-cmd-note-flag' when `mh-scan-format-file' isn't t.
-Otherwise, set SYMBOL to VALUE."
-  (if (and value
-           (not (eq mh-scan-format-file t)))
-      (error "%s %s" "Can't turn on unless `mh-scan-format-file'"
-             "is set to \"Use MH-E scan Format\"")
-    (set-default symbol value)))
-
-;; Forward definition.
-(defvar mh-adaptive-cmd-note-flag)
-
-(defun mh-scan-format-file-check (symbol value)
-  "Check if desired setting is legal.
-Throw an error if user tries to set `mh-scan-format-file' to
-anything but t when `mh-adaptive-cmd-note-flag' is on. Otherwise,
-set SYMBOL to VALUE."
-  (if (and (not (eq value t))
-           (eq mh-adaptive-cmd-note-flag t))
-      (error "%s %s" "You must turn off `mh-adaptive-cmd-note-flag'"
-             "unless you use \"Use MH-E scan Format\"")
-    (set-default symbol value)))
-
-(defcustom mh-adaptive-cmd-note-flag t
-  "*Non-nil means that the message number width is determined dynamically.
-
-If you've created your own format to handle long message numbers,
-you'll be pleased to know you no longer need it since MH-E adapts its
-internal format based upon the largest message number if this option
-is on (the default). This option may only be turned on when
-`mh-scan-format-file' is set to \"Use MH-E scan Format\".
-
-If you prefer fixed-width message numbers, turn off this option and
-call `mh-set-cmd-note' with the width specified by your format file
-\(see `mh-scan-format-file'). For example, the default width is 4, so
-you would use \"(mh-set-cmd-note 4)\"."
-  :type 'boolean
-  :group 'mh-scan-line-formats
-  :set 'mh-adaptive-cmd-note-flag-check)
-
-;; Update forward definition above if default changes.
-(defcustom mh-scan-format-file t
-  "Specifies the format file to pass to the scan program.
-
-The default setting for this option is \"Use MH-E scan Format\". This
-means that the format string will be taken from the either
-`mh-scan-format-mh' or `mh-scan-format-nmh' depending on whether MH or
-nmh (or GNU mailutils) is in use. This setting also enables you to
-turn on the `mh-adaptive-cmd-note-flag' option.
-
-You can also set this option to \"Use Default scan Format\" to get the
-same output as you would get if you ran \"scan\" from the shell. If
-you have a format file that you want MH-E to use but not MH, you can
-set this option to \"Specify a scan Format File\" and enter the name
-of your format file.
-
-If you change the format of the scan lines you'll need to tell MH-E
-how to parse the new format. As you will see, quite a lot of variables
-are involved to do that. Use \"\\[apropos] RET mh-scan.*regexp\" to
-obtain a list of these variables. You will also have to call
-`mh-set-cmd-note' if your notations are not in column 4 (columns in
-Emacs start with 0)."
-  :type '(choice (const :tag "Use MH-E scan Format" t)
-                 (const :tag "Use Default scan Format" nil)
-                 (file  :tag "Specify a scan Format File"))
-  :group 'mh-scan-line-formats
-  :set 'mh-scan-format-file-check)
-
-(defcustom mh-scan-prog "scan"
-  "*Program used to scan messages.
-
-The name of the program that generates a listing of one line per
-message is held in this option. Unless this variable contains an
-absolute pathname, it is assumed to be in the `mh-progs'
-directory. You may link another program to `scan' (see
-\"mh-profile(5)\") to produce a different type of listing."
-  :type 'string
-  :group 'mh-scan-line-formats)
-(make-variable-buffer-local 'mh-scan-prog)
-
-
-
-;;; Searching (:group 'mh-search)
-
-(defcustom mh-search-program nil
-  "Search program that MH-E shall use.
-
-The default setting of this option is \"Auto-detect\" which means
-that MH-E will automatically choose one of swish++, swish-e,
-mairix, namazu, pick and grep in that order. If, for example, you
-have both swish++ and mairix installed and you want to use
-mairix, then you can set this option to \"mairix\".
-
-More information about setting up an indexing program to use with
-MH-E can be found in the documentation of `mh-search'."
-  :type '(choice (const :tag "Auto-detect" nil)
-                 (const :tag "swish++" swish++)
-                 (const :tag "swish-e" swish)
-                 (const :tag "mairix" mairix)
-                 (const :tag "namazu" namazu)
-                 (const :tag "pick" pick)
-                 (const :tag "grep" grep))
-  :group 'mh-search)
-
-
-
-;;; Sending Mail (:group 'mh-sending-mail)
-
-(defcustom mh-compose-forward-as-mime-flag t
-  "*Non-nil means that messages are forwarded as attachments.
-
-By default, this option is on which means that the forwarded
-messages are included as attachments. If you would prefer to
-forward your messages verbatim (as text, inline), then turn off
-this option. Forwarding messages verbatim works well for short,
-textual messages, but your recipient won't be able to view any
-non-textual attachments that were in the forwarded message. Be
-aware that if you have \"forw: -mime\" in your MH profile, then
-forwarded messages will always be included as attachments
-regardless of the settings of this option."
-  :type 'boolean
-  :group 'mh-sending-mail)
-
-(defcustom mh-compose-letter-function nil
-  "Invoked when starting a new draft.
-
-However, it is the last function called before you edit your
-message. The consequence of this is that you can write a function
-to write and send the message for you. This function is passed
-three arguments: the contents of the TO, SUBJECT, and CC header
-fields."
-  :type '(choice (const nil) function)
-  :group 'mh-sending-mail)
-
-(defcustom mh-compose-prompt-flag nil
-  "*Non-nil means prompt for header fields when composing a new draft."
-  :type 'boolean
-  :group 'mh-sending-mail)
-
-(defcustom mh-forward-subject-format "%s: %s"
-  "*Format string for forwarded message subject.
-
-This option is a string which includes two escapes (\"%s\"). The
-first \"%s\" is replaced with the sender of the original message,
-and the second one is replaced with the original \"Subject:\"."
-  :type 'string
-  :group 'mh-sending-mail)
-
-(defcustom mh-insert-x-mailer-flag t
-  "*Non-nil means append an \"X-Mailer:\" header field to the header.
-
-This header field includes the version of MH-E and Emacs that you
-are using. If you don't want to participate in our marketing, you
-can turn this option off."
-  :type 'boolean
-  :group 'mh-sending-mail)
-
-(defcustom mh-redist-full-contents-flag nil
-  "*Non-nil means the \"dist\" command needs entire letter for redistribution.
-
-This option must be turned on if \"dist\" requires the whole
-letter for redistribution, which is the case if \"send\" is
-compiled with the BERK option (which many people abhor). If you
-find that MH will not allow you to redistribute a message that
-has been redistributed before, turn off this option."
-  :type 'boolean
-  :group 'mh-sending-mail)
-
-(defcustom mh-reply-default-reply-to nil
-  "*Sets the person or persons to whom a reply will be sent.
-
-This option is set to \"Prompt\" by default so that you are
-prompted for the recipient of a reply. If you find that most of
-the time that you specify \"cc\" when you reply to a message, set
-this option to \"cc\". Other choices include \"from\", \"to\", or
-\"all\". You can always edit the recipients in the draft."
-  :type '(choice (const :tag "Prompt" nil)
-                 (const "from")
-                 (const "to")
-                 (const "cc")
-                 (const "all"))
-  :group 'mh-sending-mail)
-
-(defcustom mh-reply-show-message-flag t
-  "*Non-nil means the MH-Show buffer is displayed when replying.
-
-If you include the message automatically, you can hide the
-MH-Show buffer by turning off this option.
-
-See also `mh-reply'."
-  :type 'boolean
-  :group 'mh-sending-mail)
-
-
-
-;;; Sequences (:group 'mh-sequences)
-
-;; If `mh-unpropagated-sequences' becomes a defcustom, add the following to
-;; the docstring: "Additional sequences that should not to be preserved can be
-;; specified by setting `mh-unpropagated-sequences' appropriately." XXX
-
-(defcustom mh-refile-preserves-sequences-flag t
-  "*Non-nil means that sequences are preserved when messages are refiled.
-
-If a message is in any sequence (except \"Previous-Sequence:\"
-and \"cur\") when it is refiled, then it will still be in those
-sequences in the destination folder. If this behavior is not
-desired, then turn off this option."
-  :type 'boolean
-  :group 'mh-sequences)
-
-(defcustom mh-tick-seq 'tick
-  "The name of the MH sequence for ticked messages.
-
-You can customize this option if you already use the \"tick\"
-sequence for your own use. You can also disable all of the
-ticking functions by choosing the \"Disable Ticking\" item but
-there isn't much advantage to that."
-  :type '(choice (const :tag "Disable Ticking" nil)
-                 symbol)
-  :group 'mh-sequences)
-
-(defcustom mh-update-sequences-after-mh-show-flag t
-  "*Non-nil means flush MH sequences to disk after message is shown\\<mh-folder-mode-map>.
-
-Three sequences are maintained internally by MH-E and pushed out
-to MH when a message is shown. They include the sequence
-specified by your \"Unseen-Sequence:\" profile entry, \"cur\",
-and the sequence listed by the option `mh-tick-seq' which is
-\"tick\" by default. If you do not like this behavior, turn off
-this option. You can then update the state manually with the
-\\[mh-execute-commands], \\[mh-quit], or \\[mh-update-sequences]
-commands."
-  :type 'boolean
-  :group 'mh-sequences)
-
-
-
-;;; Reading Your Mail (:group 'mh-show)
-
-(defcustom mh-bury-show-buffer-flag t
-  "*Non-nil means show buffer is buried.
-
-One advantage of not burying the show buffer is that one can
-delete the show buffer more easily in an electric buffer list
-because of its proximity to its associated MH-Folder buffer. Try
-running \\[electric-buffer-list] to see what I mean."
-  :type 'boolean
-  :group 'mh-show)
-
-(defcustom mh-clean-message-header-flag t
-  "*Non-nil means remove extraneous header fields.
-
-See also `mh-invisible-header-fields-default' and
-`mh-invisible-header-fields'."
-  :type 'boolean
-  :group 'mh-show)
-
-(defcustom mh-decode-mime-flag (not (not (locate-library "mm-decode")))
-  "*Non-nil means attachments are handled\\<mh-folder-mode-map>.
-
-MH-E can handle attachments as well if the Gnus `mm-decode'
-library is present. If so, this option will be on. Otherwise,
-you'll see the MIME body parts rather than text or attachments.
-There isn't much point in turning off this option; however, you
-can inspect it if it appears that the body parts are not being
-interpreted correctly or toggle it with the command
-\\[mh-toggle-mh-decode-mime-flag] to view the raw message.
-
-This option also controls the display of quoted-printable
-messages and other graphical widgets. See the options
-`mh-graphical-smileys-flag' and `mh-graphical-emphasis-flag'."
-  :type 'boolean
-  :group 'mh-show)
-
-(defcustom mh-display-buttons-for-alternatives-flag nil
-  "*Non-nil means display buttons for all alternative attachments.
-
-Sometimes, a mail program will produce multiple alternatives of
-the attachment in increasing degree of faithfulness to the
-original content. By default, only the preferred alternative is
-displayed. If this option is on, then the preferred part is shown
-inline and buttons are shown for each of the other alternatives."
-  :type 'boolean
-  :group 'mh-show)
-
-(defcustom mh-display-buttons-for-inline-parts-flag nil
-  "*Non-nil means display buttons for all inline attachments\\<mh-folder-mode-map>.
-
-The sender can request that attachments should be viewed inline so
-that they do not really appear like an attachment at all to the
-reader. Most of the time, this is desirable, so by default MH-E
-suppresses the buttons for inline attachments. On the other hand, you
-may receive code or HTML which the sender has added to his message as
-inline attachments so that you can read them in MH-E. In this case, it
-is useful to see the buttons so that you know you don't have to cut
-and paste the code into a file; you can simply save the attachment.
-
-If you want to make the buttons visible for inline attachments, you
-can use the command \\[mh-toggle-mime-buttons] to toggle the
-visibility of these buttons. You can turn on these buttons permanently
-by turning on this option.
-
-MH-E cannot display all attachments inline however. It can display
-text (including HTML) and images."
-  :type 'boolean
-  :group 'mh-show)
-
-(defcustom mh-do-not-confirm-flag nil
-  "*Non-nil means non-reversible commands do not prompt for confirmation.
-
-Commands such as `mh-pack-folder' prompt to confirm whether to
-process outstanding moves and deletes or not before continuing.
-Turning on this option means that these actions will be
-performed--which is usually desired but cannot be
-retracted--without question."
-  :type 'boolean
-  :group 'mh-show)
-
-(defcustom mh-fetch-x-image-url nil
-  "*Control fetching of \"X-Image-URL:\" header field image.
-
-Ths option controls the fetching of the \"X-Image-URL:\" header
-field image with the following values:
-
-Ask Before Fetching
-     You are prompted before the image is fetched. MH-E will
-     remember your reply and will either use the already fetched
-     image the next time the same URL is encountered or silently
-     skip it if you didn't fetch it the first time. This is a
-     good setting.
-
-Never Fetch
-     Images are never fetched and only displayed if they are
-     already present in the cache. This is the default.
-
-There isn't a value of \"Always Fetch\" for privacy and DOS (denial of
-service) reasons. For example, fetching a URL can tip off a spammer
-that you've read his email (which is why you shouldn't blindly answer
-yes if you've set this option to \"Ask Before Fetching\"). Someone may
-also flood your network and fill your disk drive by sending a torrent
-of messages, each specifying a unique URL to a very large file.
-
-The cache of images is found in the directory \".mhe-x-image-cache\"
-within your MH directory. You can add your own face to the \"From:\"
-field too. See Info node `(mh-e)Picture'.
-
-This setting only has effect if the option `mh-show-use-xface-flag' is
-turned on."
-
-  :type '(choice (const :tag "Ask Before Fetching" ask)
-                 (const :tag "Never Fetch" nil))
-  :group 'mh-show)
-
-(defcustom mh-graphical-smileys-flag t
-  "*Non-nil means graphical smileys are displayed.
-
-It is a long standing custom to inject body language using a
-cornucopia of punctuation, also known as the \"smileys\". MH-E
-can render these as graphical widgets if this option is turned
-on, which it is by default. Smileys include patterns such as :-)
-and ;-).
-
-This option is disabled if the option `mh-decode-mime-flag' is
-turned off."
-  :type 'boolean
-  :group 'mh-show)
-
-(defcustom mh-graphical-emphasis-flag t
-  "*Non-nil means graphical emphasis is displayed.
-
-A few typesetting features are indicated in ASCII text with
-certain characters. If your terminal supports it, MH-E can render
-these typesetting directives naturally if this option is turned
-on, which it is by default. For example, _underline_ will be
-underlined, *bold* will appear in bold, /italics/ will appear in
-italics, and so on. See the option `gnus-emphasis-alist' for the
-whole list.
-
-This option is disabled if the option `mh-decode-mime-flag' is
-turned off."
-  :type 'boolean
-  :group 'mh-show)
-
-(defcustom mh-highlight-citation-style 'gnus
-  "Style for highlighting citations.
-
-If the sender of the message has cited other messages in his
-message, then MH-E will highlight these citations to emphasize
-the sender's actual response. This option can be customized to
-change the highlighting style. The \"Multicolor\" method uses a
-different color for each indentation while the \"Monochrome\"
-method highlights all citations in red. To disable highlighting
-of citations entirely, choose \"None\"."
-  :type '(choice (const :tag "Multicolor" gnus)
-                 (const :tag "Monochrome" font-lock)
-                 (const :tag "None" nil))
-  :group 'mh-show)
-
-;; Keep fields alphabetized. Mention source, if known.
-(defvar mh-invisible-header-fields-internal
-  '("Approved:"
-    "Autoforwarded:"
-    "Bestservhost:"
-    "Cancel-Lock:"                      ; NNTP posts
-    "Content-"                          ; RFC 2045
-    "Delivered-To:"              ; Egroups/yahoogroups mailing list manager
-    "Delivery-Date:"                    ; MH
-    "Delivery:"
-    "DomainKey-Signature:"              ;http://antispam.yahoo.com/domainkeys
-    "Encoding:"
-    "Envelope-to:"
-    "Errors-To:"
-    "Face:"                             ; Gnus Face header
-    "Forwarded:"                        ; MH
-    "From "                             ; sendmail
-    "Importance:"                       ; MS Outlook
-    "In-Reply-To:"                      ; MH
-    "Lines:"
-    "List-"                             ; Mailman mailing list manager
-    "List-"                             ; Unknown mailing list managers
-    "List-Subscribe:"                   ; Unknown mailing list managers
-    "List-Unsubscribe:"                 ; Unknown mailing list managers
-    "Mail-from:"                        ; MH
-    "Mailing-List:"              ; Egroups/yahoogroups mailing list manager
-    "Message-Id:"                       ; RFC 822
-    "Mime-Version"                      ; RFC 2045
-    "NNTP-"                             ; News
-    "Old-Return-Path:"
-    "Original-Encoded-Information-Types:"  ; X400
-    "Original-Lines:"                   ; mail to news
-    "Original-NNTP-"                    ; mail to news
-    "Original-Newsgroups:"              ; mail to news
-    "Original-Path:"                    ; mail to news
-    "Original-Received:"                ; mail to news
-    "Original-To:"                      ; mail to news
-    "Original-X-"                       ; mail to news
-    "Originator:"
-    "P1-Content-Type:"                  ; X400
-    "P1-Message-Id:"                    ; X400
-    "P1-Recipient:"                     ; X400
-    "Path:"
-    "Precedence:"
-    "Prev-Resent"                       ; MH
-    "Priority:"
-    "Received:"                         ; RFC 822
-    "Received-SPF:"                     ; Gmail
-    "References:"
-    "Remailed-"                         ; MH
-    "Replied:"                          ; MH
-    "Resent"                            ; MH
-    "Return-Path:"                      ; RFC 822
-    "Sensitivity:"                      ; MS Outlook
-    "Status:"                           ; sendmail
-    "Thread-"
-    "Ua-Content-Id:"                    ; X400
-;;  "User-Agent:"                       ; Similar to X-Mailer, so display it.
-    "Via:"                              ; MH
-    "X-Abuse-Info:"
-    "X-Abuse-and-DMCA-"
-    "X-Accept-Language:"
-    "X-Accept-Language:"                ; Netscape/Mozilla
-    "X-Ack:"
-    "X-Administrivia-To:"
-    "X-AntiAbuse:"                      ; cPanel
-    "X-Apparently-From:"                ; MS Outlook
-    "X-Apparently-To:"           ; Egroups/yahoogroups mailing list manager
-    "X-Authentication-Warning:"         ; sendmail
-    "X-Beenthere:"                      ; Mailman mailing list manager
-    "X-Bogosity:"                       ; bogofilter
-    "X-Bugzilla-*"                      ; Bugzilla
-    "X-Complaints-To:"
-    "X-ContentStamp:"                   ; NetZero
-    "X-Cron-Env:"
-    "X-DMCA"
-    "X-Delivered"
-    "X-ELNK-Trace:"                     ; Earthlink mailer
-    "X-Envelope-Date:"                  ; GNU mailutils
-    "X-Envelope-From:"
-    "X-Envelope-Sender:"
-    "X-Envelope-To:"
-    "X-Evolution:"                      ; Evolution mail client
-    "X-Face:"
-    "X-Folder:"                         ; Spam
-    "X-From-Line"
-    "X-Gmail-"                          ; Gmail
-    "X-Gnus-Mail-Source:"               ; gnus
-    "X-Greylist:"                       ; milter-greylist-1.2.1
-    "X-Habeas-SWE-1:"                   ; Spam
-    "X-Habeas-SWE-2:"                   ; Spam
-    "X-Habeas-SWE-3:"                   ; Spam
-    "X-Habeas-SWE-4:"                   ; Spam
-    "X-Habeas-SWE-5:"                   ; Spam
-    "X-Habeas-SWE-6:"                   ; Spam
-    "X-Habeas-SWE-7:"                   ; Spam
-    "X-Habeas-SWE-8:"                   ; Spam
-    "X-Habeas-SWE-9:"                   ; Spam
-    "X-Info:"                           ; NTMail
-    "X-Juno-"                           ; Juno
-    "X-List-Host:"                      ; Unknown mailing list managers
-    "X-List-Subscribe:"                 ; Unknown mailing list managers
-    "X-List-Unsubscribe:"               ; Unknown mailing list managers
-    "X-Listprocessor-"                  ; ListProc(tm) by CREN
-    "X-Listserver:"                     ; Unknown mailing list managers
-    "X-Loop:"                           ; Unknown mailing list managers
-    "X-Lumos-SenderID:"                 ; Roving ConstantContact
-    "X-MAIL-INFO:"                      ; NetZero
-    "X-MHE-Checksum"                    ; Checksum added during index search
-    "X-MIME-Autoconverted:"             ; sendmail
-    "X-MIMETrack:"
-    "X-MS-"                             ; MS Outlook
-    "X-MailScanner"                     ; ListProc(tm) by CREN
-    "X-Mailing-List:"                   ; Unknown mailing list managers
-    "X-Mailman-Version:"                ; Mailman mailing list manager
-    "X-Majordomo:"                      ; Majordomo mailing list manager
-    "X-Message-Id"
-    "X-MessageWall-Score:"              ; Unknown mailing list manager, AUC TeX
-    "X-MimeOLE:"                        ; MS Outlook
-    "X-Mms-"                            ; T-Mobile pictures
-    "X-Mozilla-Status:"                 ; Netscape/Mozilla
-    "X-Msmail-"                         ; MS Outlook
-    "X-NAI-Spam-"                       ; Network Associates Inc. SpamKiller
-    "X-News:"                           ; News
-    "X-No-Archive:"
-    "X-Notes-Item:"                     ; Lotus Notes Domino structured header
-    "X-OperatingSystem:"
-    ;;"X-Operator:"                     ; Similar to X-Mailer, so display it
-    "X-Orcl-Content-Type:"
-    "X-Original-Complaints-To:"
-    "X-Original-Date:"                  ; SourceForge mailing list manager
-    "X-Original-To:"
-    "X-Original-Trace:"
-    "X-OriginalArrivalTime:"            ; Hotmail
-    "X-Originating-IP:"                 ; Hotmail
-    "X-Postfilter:"
-    "X-Priority:"                       ; MS Outlook
-    "X-Qotd-"                           ; User added
-    "X-RM"
-    "X-Received-Date:"
-    "X-Received:"
-    "X-Request-"
-    "X-Return-Path-Hint:"               ; Roving ConstantContact
-    "X-Roving-*"                        ; Roving ConstantContact
-    "X-SBClass:"                        ; Spam
-    "X-SBNote:"                         ; Spam
-    "X-SBPass:"                         ; Spam
-    "X-SBRule:"                         ; Spam
-    "X-SMTP-"
-    "X-Scanned-By"
-    "X-Sender:"
-    "X-Server-Date:"
-    "X-Server-Uuid:"
-    "X-Sieve:"                          ; Sieve filtering
-    "X-Source"
-    "X-Spam-"                           ; Spamassassin
-    "X-SpamBouncer:"                    ; Spam
-    "X-Status"
-    "X-Submissions-To:"
-    "X-Telecom-Digest"
-    "X-Trace:"
-    "X-UID"
-    "X-UIDL:"
-    "X-UNTD-"                           ; NetZero
-    "X-USANET-"                         ; usa.net
-    "X-UserInfo1:"
-    "X-VSMLoop:"                        ; NTMail
-    "X-Virus-Scanned"                   ; amavisd-new
-    "X-Vms-To:"
-    "X-WebTV-Signature:"
-    "X-Wss-Id:"                         ; Worldtalk gateways
-    "X-Yahoo"
-    "X-eGroups-"                 ; Egroups/yahoogroups mailing list manager
-    "X-pgp:"
-    "X-submission-address:"
-    "X400-"                             ; X400
-    "Xref:")
-  "List of default header fields that are not to be shown.
-
-Do not alter this variable directly. Instead, add entries from
-here that you would like to be displayed in
-`mh-invisible-header-fields-default' and add entries to hide in
-`mh-invisible-header-fields'.")
-
-(defvar mh-invisible-header-fields-compiled nil
-  "*Regexp matching lines in a message header that are not to be shown.
-Do not alter this variable directly. Instead, customize
-`mh-invisible-header-fields-default' checking for fields normally
-hidden that you wish to display, and add extra entries to hide in
-`mh-invisible-header-fields'.")
-
-;; Forward definition.
-(defvar mh-invisible-header-fields)
-(defvar mh-invisible-header-fields-default nil)
-
-(defun mh-invisible-headers ()
-  "Make or remake the variable `mh-invisible-header-fields-compiled'.
-Done using `mh-invisible-header-fields-internal' as input, from
-which entries from `mh-invisible-header-fields-default' are
-removed and entries from `mh-invisible-header-fields' are added."
-  (let ((fields mh-invisible-header-fields-internal))
-    (when mh-invisible-header-fields-default
-      ;; Remove entries from `mh-invisible-header-fields-default'
-      (setq fields
-            (loop for x in fields
-                  unless (member x mh-invisible-header-fields-default)
-                  collect x)))
-    (when (and (boundp 'mh-invisible-header-fields)
-               mh-invisible-header-fields)
-      (dolist (x mh-invisible-header-fields)
-        (unless (member x fields) (setq fields (cons x fields)))))
-    (if fields
-        (setq mh-invisible-header-fields-compiled
-              (concat
-               "^"
-               ;; workaround for insufficient default
-               (let ((max-specpdl-size 1000))
-                 (regexp-opt fields t))))
-      (setq mh-invisible-header-fields-compiled nil))))
-
-(defcustom mh-invisible-header-fields nil
-  "*Additional header fields to hide.
-
-Header fields that you would like to hide that aren't listed in
-`mh-invisible-header-fields-default' can be added to this option
-with a couple of caveats. Regular expressions are not allowed.
-Unique fields should have a \":\" suffix; otherwise, the element
-can be used to render invisible an entire class of fields that
-start with the same prefix. If you think a header field should be
-generally ignored, report a bug (see URL
-`https://sourceforge.net/tracker/?group_id=13357&atid=113357').
-
-See also `mh-clean-message-header-flag'."
-
-  :type '(repeat (string :tag "Header field"))
-  :set (lambda (symbol value)
-         (set-default symbol value)
-         (mh-invisible-headers))
-  :group 'mh-show)
-
-;; Update forward definition above if default changes.
-(defcustom mh-invisible-header-fields-default nil
-  "*List of hidden header fields.
-
-The header fields listed in this option are hidden, although you
-can check off any field that you would like to see.
-
-Header fields that you would like to hide that aren't listed can
-be added to the option `mh-invisible-header-fields'.
-
-See also `mh-clean-message-header-flag'."
-  :type `(set ,@(mapcar (lambda (x) `(const ,x))
-                        mh-invisible-header-fields-internal))
-  :set (lambda (symbol value)
-         (set-default symbol value)
-         (mh-invisible-headers))
-  :group 'mh-show)
-
-(defcustom mh-lpr-command-format "lpr -J '%s'"
-  "*Command used to print\\<mh-folder-mode-map>.
-
-This option contains the Unix command line which performs the
-actual printing for the \\[mh-print-msg] command. The string can
-contain one escape, \"%s\", which is replaced by the name of the
-folder and the message number and is useful for print job names.
-I use \"mpage -h'%s' -b Letter -H1of -mlrtb -P\" which produces a
-nice header and adds a bit of margin so the text fits within my
-printer's margins.
-
-This options is not used by the commands \\[mh-ps-print-msg] or
-\\[mh-ps-print-msg-file]."
-  :type 'string
-  :group 'mh-show)
-
-(defcustom mh-max-inline-image-height nil
-  "*Maximum inline image height if \"Content-Disposition:\" is not present.
-
-Some older mail programs do not insert this needed plumbing to
-tell MH-E whether to display the attachments inline or not. If
-this is the case, MH-E will display these images inline if they
-are smaller than the window. However, you might want to allow
-larger images to be displayed inline. To do this, you can change
-the options `mh-max-inline-image-width' and
-`mh-max-inline-image-height' from their default value of zero to
-a large number. The size of your screen is a good choice for
-these numbers."
-  :type '(choice (const nil) integer)
-  :group 'mh-show)
-
-(defcustom mh-max-inline-image-width nil
-  "*Maximum inline image width if \"Content-Disposition:\" is not present.
-
-Some older mail programs do not insert this needed plumbing to
-tell MH-E whether to display the attachments inline or not. If
-this is the case, MH-E will display these images inline if they
-are smaller than the window. However, you might want to allow
-larger images to be displayed inline. To do this, you can change
-the options `mh-max-inline-image-width' and
-`mh-max-inline-image-height' from their default value of zero to
-a large number. The size of your screen is a good choice for
-these numbers."
-  :type '(choice (const nil) integer)
-  :group 'mh-show)
-
-(defcustom mh-mhl-format-file nil
-  "*Specifies the format file to pass to the \"mhl\" program.
-
-Normally MH-E takes care of displaying messages itself (rather than
-calling an MH program to do the work). If you'd rather have \"mhl\"
-display the message (within MH-E), change this option from its default
-value of \"Use Default mhl Format (Printing Only)\".
-
-You can set this option to \"Use Default mhl Format\" to get the same
-output as you would get if you ran \"mhl\" from the shell.
-
-If you have a format file that you want MH-E to use, you can set this
-option to \"Specify an mhl Format File\" and enter the name of your
-format file. Your format file should specify a non-zero value for
-\"overflowoffset\" to allow MH-E to parse the header. Note that
-\"mhl\" is always used for printing and forwarding; in this case, the
-value of this option is consulted if you have specified a format
-file."
-  :type '(choice (const :tag "Use Default mhl Format (Printing Only)" nil)
-                 (const :tag "Use Default mhl Format" t)
-                 (file :tag "Specify an mhl Format File"))
-  :group 'mh-show)
-
-(defcustom mh-mime-save-parts-default-directory t
-  "Default directory to use for \\<mh-folder-mode-map>\\[mh-mime-save-parts].
-
-The default value for this option is \"Prompt Always\" so that
-you are always prompted for the directory in which to save the
-attachments. However, if you usually use the same directory
-within a session, then you can set this option to \"Prompt the
-First Time\" to avoid the prompt each time. you can make this
-directory permanent by choosing \"Directory\" and entering the
-directory's name."
-  :type '(choice (const :tag "Prompt the First Time" nil)
-                 (const :tag "Prompt Always" t)
-                 directory)
-  :group 'mh-show)
-
-(defcustom mh-print-background-flag nil
-  "*Non-nil means messages should be printed in the background\\<mh-folder-mode-map>.
-
-Normally messages are printed in the foreground. If this is slow on
-your system, you may elect to turn off this option to print in the
-background.
-
-WARNING: If you do this, do not delete the message until it is printed
-or else the output may be truncated.
-
-This option is not used by the commands \\[mh-ps-print-msg] or
-\\[mh-ps-print-msg-file]."
-  :type 'boolean
-  :group 'mh-show)
-
-(defcustom mh-show-maximum-size 0
-  "*Maximum size of message (in bytes) to display automatically.
-
-This option provides an opportunity to skip over large messages
-which may be slow to load. The default value of 0 means that all
-message are shown regardless of size."
-  :type 'integer
-  :group 'mh-show)
-
-(defcustom mh-show-use-goto-addr-flag (and (boundp 'goto-address-highlight-p)
-                                           goto-address-highlight-p)
-  "*Non-nil means highlight URLs and email addresses\\<goto-address-highlight-keymap>.
-
-To send a message using the highlighted email address or to view
-the web page for the highlighted URL, use the middle mouse button
-or \\[goto-address-at-point].
-
-See Info node `(mh-e)Sending Mail' to see how to configure Emacs
-to send the message using MH-E.
-
-The default value of this option comes from the value of
-`goto-address-highlight-p'."
-  :type 'boolean
-  :group 'mh-show)
-
-(defcustom mh-show-use-xface-flag (>= emacs-major-version 21)
-  "*Non-nil means display face images in MH-show buffers.
-
-MH-E can display the content of \"Face:\", \"X-Face:\", and
-\"X-Image-URL:\" header fields. If any of these fields occur in the
-header of your message, the sender's face will appear in the \"From:\"
-header field. If more than one of these fields appear, then the first
-field found in the order \"Face:\", \"X-Face:\", and \"X-Image-URL:\"
-will be used.
-
-The option `mh-show-use-xface-flag' is used to turn this feature on
-and off. This feature will be turned on by default if your system
-supports it.
-
-The first header field used, if present, is the Gnus-specific
-\"Face:\" field. The \"Face:\" field appeared in GNU Emacs 21 and
-XEmacs. For more information, see URL
-`http://quimby.gnus.org/circus/face/'. Next is the traditional
-\"X-Face:\" header field. The display of this field requires the
-\"uncompface\" program (see URL
-`ftp://ftp.cs.indiana.edu/pub/faces/compface/compface.tar.z'). Recent
-versions of XEmacs have internal support for \"X-Face:\" images. If
-your version of XEmacs does not, then you'll need both \"uncompface\"
-and the x-face package (see URL `ftp://ftp.jpl.org/pub/elisp/').
-
-Finally, MH-E will display images referenced by the \"X-Image-URL:\"
-header field if neither the \"Face:\" nor the \"X-Face:\" fields are
-present. The display of the images requires \"wget\" (see URL
-`http://www.gnu.org/software/wget/wget.html'), \"fetch\", or \"curl\"
-to fetch the image and the \"convert\" program from the ImageMagick
-suite (see URL `http://www.imagemagick.org/'). Of the three header
-fields this is the most efficient in terms of network usage since the
-image doesn't need to be transmitted with every single mail.
-
-The option `mh-fetch-x-image-url' controls the fetching of the
-\"X-Image-URL:\" header field image."
-  :type 'boolean
-  :group 'mh-show)
-
-(defcustom mh-store-default-directory nil
-  "*Default directory for \\<mh-folder-mode-map>\\[mh-store-msg].
-
-If you would like to change the initial default directory,
-customize this option, change the value from \"Current\" to
-\"Directory\", and then enter the name of the directory for storing
-the content of these messages."
-  :type '(choice (const :tag "Current" nil)
-                 directory)
-  :group 'mh-show)
-
-(defcustom mh-summary-height nil
-  "*Number of lines in MH-Folder buffer (including the mode line).
-
-The default value of this option is \"Automatic\" which means
-that the MH-Folder buffer will maintain the same proportional
-size if the frame is resized. If you'd prefer a fixed height,
-then choose the \"Fixed Size\" option and enter the number of
-lines you'd like to see."
-  :type '(choice (const :tag "Automatic" nil)
-                 (integer :tag "Fixed Size"))
-  :group 'mh-show)
-
-
-
-;;; The Speedbar (:group 'mh-speedbar)
-
-(defcustom mh-speed-update-interval 60
-  "Time between speedbar updates in seconds.
-Set to 0 to disable automatic update."
-  :type 'integer
-  :group 'mh-speedbar)
-
-
-
-;;; Threading (:group 'mh-thread)
-
-(defcustom mh-show-threads-flag nil
-  "*Non-nil means new folders start in threaded mode.
-
-Threading large number of messages can be time consuming so this
-option is turned off by default. If you turn this option on, then
-threading will be done only if the number of messages being
-threaded is less than `mh-large-folder'."
-  :type 'boolean
-  :group 'mh-thread)
-
-
-
-;;; The Tool Bar (:group 'mh-tool-bar)
-
-(defcustom mh-tool-bar-search-function 'mh-search
-  "*Function called by the tool bar search button.
-
-By default, this is set to `mh-search'. You can also choose
-\"Other Function\" from the \"Value Menu\" and enter a function
-of your own choosing."
-  :type '(choice (const mh-search)
-                 (function :tag "Other Function"))
-  :group 'mh-tool-bar)
-
-;; Functions called from the tool bar
-(defun mh-tool-bar-search (&optional arg)
-  "Interactively call `mh-tool-bar-search-function'.
-Optional argument ARG is not used."
-  (interactive "P")
-  (call-interactively mh-tool-bar-search-function))
-
-(defun mh-tool-bar-customize ()
-  "Call `mh-customize' from the tool bar."
-  (interactive)
-  (mh-customize t))
-
-(defun mh-tool-bar-folder-help ()
-  "Visit \"(mh-e)Top\"."
-  (interactive)
-  (info "(mh-e)Top")
-  (delete-other-windows))
-
-(defun mh-tool-bar-letter-help ()
-  "Visit \"(mh-e)Editing Drafts\"."
-  (interactive)
-  (info "(mh-e)Editing Drafts")
-  (delete-other-windows))
-
-(defmacro mh-tool-bar-reply-generator (function recipient folder-buffer-flag)
-  "Generate FUNCTION that replies to RECIPIENT.
-If FOLDER-BUFFER-FLAG is nil then the function generated...
-When INCLUDE-FLAG is non-nil, include message body being replied to."
-  `(defun ,function (&optional arg)
-     ,(format "Reply to \"%s\".\nWhen ARG is non-nil include message in reply."
-              recipient)
-     (interactive "P")
-     ,(if folder-buffer-flag nil '(set-buffer mh-show-folder-buffer))
-     (mh-reply (mh-get-msg-num nil) ,recipient arg)))
-
-(mh-tool-bar-reply-generator mh-tool-bar-reply-from "from" t)
-(mh-tool-bar-reply-generator mh-show-tool-bar-reply-from "from" nil)
-(mh-tool-bar-reply-generator mh-tool-bar-reply-to "to" t)
-(mh-tool-bar-reply-generator mh-show-tool-bar-reply-to "to" nil)
-(mh-tool-bar-reply-generator mh-tool-bar-reply-all "all" t)
-(mh-tool-bar-reply-generator mh-show-tool-bar-reply-all "all" nil)
-
-;; XEmacs has a couple of extra customizations...
-(mh-do-in-xemacs
-  (defcustom mh-xemacs-use-tool-bar-flag mh-xemacs-has-tool-bar-flag
-    "*If non-nil, use tool bar.
-
-This option controls whether to show the MH-E icons at all. By
-default, this option is turned on if the window system supports
-tool bars. If your system doesn't support tool bars, then you
-won't be able to turn on this option."
-    :type 'boolean
-    :group 'mh-tool-bar
-    :set (lambda (symbol value)
-           (if (and (eq value t)
-                    (not mh-xemacs-has-tool-bar-flag))
-               (error "Tool bar not supported"))
-           (set-default symbol value)))
-
-  (defcustom mh-xemacs-tool-bar-position nil
-    "*Tool bar location.
-
-This option controls the placement of the tool bar along the four
-edges of the frame. You can choose from one of \"Same As Default
-Tool Bar\", \"Top\", \"Bottom\", \"Left\", or \"Right\". If this
-variable is set to anything other than \"Same As Default Tool
-Bar\" and the default tool bar is in a different location, then
-two tool bars will be displayed: the MH-E tool bar and the
-default tool bar."
-    :type '(radio (const :tag "Same As Default Tool Bar" :value nil)
-                  (const :tag "Top" :value top)
-                  (const :tag "Bottom" :value bottom)
-                  (const :tag "Left" :value left)
-                  (const :tag "Right" :value right))
-    :group 'mh-tool-bar))
-
-(defun mh-buffer-exists-p (mode)
-  "Test whether a buffer with major mode MODE is present."
-  (loop for buf in (buffer-list)
-        when (save-excursion
-               (set-buffer buf)
-               (eq major-mode mode))
-        return t))
-
-(defmacro mh-tool-bar-define (defaults &rest buttons)
-  "Define a tool bar for MH-E.
-DEFAULTS is the list of buttons that are present by default. It
-is a list of lists where the sublists are of the following form:
-
-  (:KEYWORD FUNC1 FUNC2 FUNC3 ...)
-
-Here :KEYWORD is one of :folder or :letter. If it is :folder then
-the default buttons in the folder and show mode buffers are being
-specified. If it is :letter then the default buttons in the
-letter mode are listed. FUNC1, FUNC2, FUNC3, ... are the names of
-the functions that the buttons would execute.
-
-Each element of BUTTONS is a list consisting of four mandatory
-items and one optional item as follows:
-
-  (FUNCTION MODES ICON DOC &optional ENABLE-EXPR)
-
-where,
-
-  FUNCTION is the name of the function that will be executed when
-  the button is clicked.
-
-  MODES is a list of symbols. List elements must be from \"folder\",
-  \"letter\" and \"sequence\". If \"folder\" is present then the button is
-  available in the folder and show buffer. If the name of FUNCTION is
-  of the form \"mh-foo\", where foo is some arbitrary string, then we
-  check if the function `mh-show-foo' exists. If it exists then that
-  function is used in the show buffer. Otherwise the original function
-  `mh-foo' is used in the show buffer as well. Presence of \"sequence\"
-  is handled similar to the above. The only difference is that the
-  button is shown only when the folder is narrowed to a sequence. If
-  \"letter\" is present in MODES, then the button is available during
-  draft editing and runs FUNCTION when clicked.
-
-  ICON is the icon that is drawn in the button.
-
-  DOC is the documentation for the button. It is used in tool-tips and
-  in providing other help to the user. GNU Emacs uses only the first
-  line of the string. So the DOC should be formatted such that the
-  first line is useful and complete without the rest of the string.
-
-  Optional item ENABLE-EXPR is an arbitrary lisp expression. If it
-  evaluates to nil, then the button is deactivated, otherwise it is
-  active. If it isn't present then the button is always active."
-  ;; The following variable names have been carefully chosen to make code
-  ;; generation easier. Modifying the names should be done carefully.
-  (let (folder-buttons folder-docs folder-button-setter sequence-button-setter
-                       show-buttons show-button-setter show-seq-button-setter
-                       letter-buttons letter-docs letter-button-setter
-                       folder-defaults letter-defaults
-                       folder-vectors show-vectors letter-vectors)
-    (dolist (x defaults)
-      (cond ((eq (car x) :folder) (setq folder-defaults (cdr x)))
-            ((eq (car x) :letter) (setq letter-defaults (cdr x)))))
-    (dolist (button buttons)
-      (unless (and (listp button)
-                   (or (equal (length button) 4) (equal (length button) 5)))
-        (error "Incorrect MH-E tool-bar button specification: %s" button))
-      (let* ((name (nth 0 button))
-             (name-str (symbol-name name))
-             (icon (nth 2 button))
-             (xemacs-icon (mh-do-in-xemacs
-                            (cdr (assoc (intern icon) mh-xemacs-icon-map))))
-             (full-doc (nth 3 button))
-             (doc (if (string-match "\\(.*\\)\n" full-doc)
-                      (match-string 1 full-doc)
-                    full-doc))
-             (enable-expr (or (nth 4 button) t))
-             (modes (nth 1 button))
-             functions show-sym)
-        (when (memq 'letter modes) (setq functions `(:letter ,name)))
-        (when (or (memq 'folder modes) (memq 'sequence modes))
-          (setq functions
-                (append `(,(if (memq 'folder modes) :folder :sequence) ,name)
-                        functions))
-          (setq show-sym
-                (if (string-match "^mh-\\(.*\\)$" name-str)
-                    (intern (concat "mh-show-" (match-string 1 name-str)))
-                  name))
-          (setq functions
-                (append `(,(if (memq 'folder modes) :show :show-seq)
-                          ,(if (fboundp show-sym) show-sym name))
-                        functions)))
-        (do ((functions functions (cddr functions)))
-            ((null functions))
-          (let* ((type (car functions))
-                 (function (cadr functions))
-                 (type1 (substring (symbol-name type) 1))
-                 (vector-list (cond ((eq type :show) 'show-vectors)
-                                    ((eq type :show-seq) 'show-vectors)
-                                    ((eq type :letter) 'letter-vectors)
-                                    (t 'folder-vectors)))
-                 (list (cond ((eq type :letter) 'mh-tool-bar-letter-buttons)
-                             (t 'mh-tool-bar-folder-buttons)))
-                 (key (intern (concat "mh-" type1 "tool-bar-" name-str)))
-                 (setter (intern (concat type1 "-button-setter")))
-                 (mbuttons (cond ((eq type :letter) 'letter-buttons)
-                                 ((eq type :show) 'show-buttons)
-                                 ((eq type :show-seq) 'show-buttons)
-                                 (t 'folder-buttons)))
-                 (docs (cond ((eq mbuttons 'letter-buttons) 'letter-docs)
-                             ((eq mbuttons 'folder-buttons) 'folder-docs))))
-            (add-to-list vector-list `[,xemacs-icon ,function t ,full-doc])
-            (add-to-list
-             setter `(when (member ',name ,list)
-                       (mh-funcall-if-exists
-                        tool-bar-add-item ,icon ',function ',key
-                        :help ,doc :enable ',enable-expr)))
-            (add-to-list mbuttons name)
-            (if docs (add-to-list docs doc))))))
-    (setq folder-buttons (nreverse folder-buttons)
-          letter-buttons (nreverse letter-buttons)
-          show-buttons (nreverse show-buttons)
-          letter-docs (nreverse letter-docs)
-          folder-docs (nreverse folder-docs)
-          folder-vectors (nreverse folder-vectors)
-          show-vectors (nreverse show-vectors)
-          letter-vectors (nreverse letter-vectors))
-    (dolist (x folder-defaults)
-      (unless (memq x folder-buttons)
-        (error "Folder defaults contains unknown button '%s'" x)))
-    (dolist (x letter-defaults)
-      (unless (memq x letter-buttons)
-        (error "Letter defaults contains unknown button '%s'" x)))
-    `(eval-when (compile load eval)
-       (defvar mh-folder-tool-bar-map nil)
-       (defvar mh-folder-seq-tool-bar-map nil)
-       (defvar mh-show-tool-bar-map nil)
-       (defvar mh-show-seq-tool-bar-map nil)
-       (defvar mh-letter-tool-bar-map nil)
-       ;; GNU Emacs tool bar specific code
-       (mh-do-in-gnu-emacs
-         ;; Tool bar initialization functions
-         (defun mh-tool-bar-folder-buttons-init ()
-           (when (mh-buffer-exists-p 'mh-folder-mode)
-             (mh-image-load-path)
-             (setq mh-folder-tool-bar-map
-                   (let ((tool-bar-map (make-sparse-keymap)))
-                     ,@(nreverse folder-button-setter)
-                     tool-bar-map))
-             (setq mh-show-tool-bar-map
-                   (let ((tool-bar-map (make-sparse-keymap)))
-                     ,@(nreverse show-button-setter)
-                     tool-bar-map))
-             (setq mh-show-seq-tool-bar-map
-                   (let ((tool-bar-map (copy-keymap mh-show-tool-bar-map)))
-                     ,@(nreverse show-seq-button-setter)
-                     tool-bar-map))
-             (setq mh-folder-seq-tool-bar-map
-                   (let ((tool-bar-map (copy-keymap mh-folder-tool-bar-map)))
-                     ,@(nreverse sequence-button-setter)
-                     tool-bar-map))))
-         (defun mh-tool-bar-letter-buttons-init ()
-           (when (mh-buffer-exists-p 'mh-letter-mode)
-             (mh-image-load-path)
-             (setq mh-letter-tool-bar-map
-                   (let ((tool-bar-map (make-sparse-keymap)))
-                     ,@(nreverse letter-button-setter)
-                     tool-bar-map))))
-         ;; Custom setter functions
-         (defun mh-tool-bar-folder-buttons-set (symbol value)
-           "Construct tool bar for `mh-folder-mode' and `mh-show-mode'."
-           (set-default symbol value)
-           (mh-tool-bar-folder-buttons-init))
-         (defun mh-tool-bar-letter-buttons-set (symbol value)
-           "Construct tool bar for `mh-letter-mode'."
-           (set-default symbol value)
-           (mh-tool-bar-letter-buttons-init)))
-       ;; XEmacs specific code
-       (mh-do-in-xemacs
-         (defvar mh-tool-bar-folder-vector-map
-           ',(loop for button in folder-buttons
-                   for vector in folder-vectors
-                   collect (cons button vector)))
-         (defvar mh-tool-bar-show-vector-map
-           ',(loop for button in show-buttons
-                   for vector in show-vectors
-                   collect (cons button vector)))
-         (defvar mh-tool-bar-letter-vector-map
-           ',(loop for button in letter-buttons
-                   for vector in letter-vectors
-                   collect (cons button vector)))
-         (defvar mh-tool-bar-folder-buttons nil)
-         (defvar mh-tool-bar-show-buttons nil)
-         (defvar mh-tool-bar-letter-buttons nil)
-         ;; Custom setter functions
-         (defun mh-tool-bar-letter-buttons-set (symbol value)
-           (set-default symbol value)
-           (when mh-xemacs-has-tool-bar-flag
-             (setq mh-tool-bar-letter-buttons
-                   (loop for b in value
-                         collect (cdr (assoc b mh-tool-bar-letter-vector-map))))))
-         (defun mh-tool-bar-folder-buttons-set (symbol value)
-           (set-default symbol value)
-           (when mh-xemacs-has-tool-bar-flag
-             (setq mh-tool-bar-folder-buttons
-                   (loop for b in value
-                         collect (cdr (assoc b mh-tool-bar-folder-vector-map))))
-             (setq mh-tool-bar-show-buttons
-                   (loop for b in value
-                         collect (cdr (assoc b mh-tool-bar-show-vector-map))))))
-         (defun mh-tool-bar-init (mode)
-           "Install tool bar in MODE."
-           (let ((tool-bar (cond ((eq mode :folder) mh-tool-bar-folder-buttons)
-                                ((eq mode :letter) mh-tool-bar-letter-buttons)
-                                ((eq mode :show) mh-tool-bar-show-buttons)))
-                 (height 37)
-                 (width 40)
-                 (buffer (current-buffer)))
-             (when mh-xemacs-use-tool-bar-flag
-               (cond
-                ((eq mh-xemacs-tool-bar-position 'top)
-                 (set-specifier top-toolbar tool-bar buffer)
-                 (set-specifier top-toolbar-visible-p t)
-                 (set-specifier top-toolbar-height height))
-                ((eq mh-xemacs-tool-bar-position 'bottom)
-                 (set-specifier bottom-toolbar tool-bar buffer)
-                 (set-specifier bottom-toolbar-visible-p t)
-                 (set-specifier bottom-toolbar-height height))
-                ((eq mh-xemacs-tool-bar-position 'left)
-                 (set-specifier left-toolbar tool-bar buffer)
-                 (set-specifier left-toolbar-visible-p t)
-                 (set-specifier left-toolbar-width width))
-                ((eq mh-xemacs-tool-bar-position 'right)
-                 (set-specifier right-toolbar tool-bar buffer)
-                 (set-specifier right-toolbar-visible-p t)
-                 (set-specifier right-toolbar-width width))
-                (t (set-specifier default-toolbar tool-bar buffer)))))))
-       ;; Declare customizable tool bars
-       (custom-declare-variable
-        'mh-tool-bar-folder-buttons
-        '(list ,@(mapcar (lambda (x) `(quote ,x)) folder-defaults))
-        "List of buttons to include in MH-Folder tool bar."
-        :group 'mh-tool-bar :set 'mh-tool-bar-folder-buttons-set
-        :type '(set ,@(loop for x in folder-buttons
-                            for y in folder-docs
-                            collect `(const :tag ,y ,x))))
-       (custom-declare-variable
-        'mh-tool-bar-letter-buttons
-        '(list ,@(mapcar (lambda (x) `(quote ,x)) letter-defaults))
-        "List of buttons to include in MH-Letter tool bar."
-        :group 'mh-tool-bar :set 'mh-tool-bar-letter-buttons-set
-        :type '(set ,@(loop for x in letter-buttons
-                            for y in letter-docs
-                            collect `(const :tag ,y ,x)))))))
-
-(mh-tool-bar-define
-    ((:folder mh-inc-folder mh-mime-save-parts mh-previous-undeleted-msg
-              mh-page-msg  mh-next-undeleted-msg mh-delete-msg mh-refile-msg
-              mh-undo mh-execute-commands mh-toggle-tick mh-reply
-              mh-alias-grab-from-field mh-send mh-rescan-folder
-              mh-tool-bar-search mh-visit-folder
-              mh-tool-bar-customize mh-tool-bar-folder-help mh-widen)
-     (:letter mh-send-letter mh-compose-insertion ispell-message save-buffer
-              undo kill-region menu-bar-kill-ring-save yank mh-fully-kill-draft
-              mh-tool-bar-customize mh-tool-bar-letter-help))
-  ;; Folder/Show buffer buttons
-  (mh-inc-folder (folder) "mail"
-    "Incorporate new mail in Inbox
-This button runs `mh-inc-folder' which drags any
-new mail into your Inbox folder.")
-  (mh-mime-save-parts (folder) "attach"
-    "Save MIME parts from this message
-This button runs `mh-mime-save-parts' which saves a message's
-different parts into separate files.")
-  (mh-previous-undeleted-msg (folder) "left-arrow"
-    "Go to the previous undeleted message
-This button runs `mh-previous-undeleted-msg'")
-  (mh-page-msg (folder) "page-down"
-    "Page the current message forwards\nThis button runs `mh-page-msg'")
-  (mh-next-undeleted-msg (folder) "right-arrow"
-    "Go to the next undeleted message\nThe button runs `mh-next-undeleted-msg'")
-  (mh-delete-msg (folder) "close"
-    "Mark this message for deletion\nThis button runs `mh-delete-msg'")
-  (mh-refile-msg (folder) "mail/refile"
-    "Refile this message\nThis button runs `mh-refile-msg'")
-  (mh-undo (folder) "undo" "Undo last operation\nThis button runs `undo'"
-    (mh-outstanding-commands-p))
-  (mh-execute-commands (folder) "execute"
-    "Perform moves and deletes\nThis button runs `mh-execute-commands'"
-    (mh-outstanding-commands-p))
-  (mh-toggle-tick (folder) "highlight"
-    "Toggle tick mark\nThis button runs `mh-toggle-tick'")
-  (mh-toggle-showing (folder) "show"
-    "Toggle showing message\nThis button runs `mh-toggle-showing'")
-  (mh-tool-bar-reply-from (folder) "mail/reply-from" "Reply to \"from\"")
-  (mh-tool-bar-reply-to (folder) "mail/reply-to" "Reply to \"to\"")
-  (mh-tool-bar-reply-all (folder) "mail/reply-all" "Reply to \"all\"")
-  (mh-reply (folder) "mail/reply"
-    "Reply to this message\nThis button runs `mh-reply'")
-  (mh-alias-grab-from-field (folder) "mail/alias"
-    "Grab From alias\nThis button runs `mh-alias-grab-from-field'"
-    (and (mh-extract-from-header-value) (not (mh-alias-for-from-p))))
-  (mh-send (folder) "mail/compose"
-    "Compose new message\nThis button runs `mh-send'")
-  (mh-rescan-folder (folder) "refresh"
-    "Rescan this folder\nThis button runs `mh-rescan-folder'")
-  (mh-pack-folder (folder) "mail/repack"
-    "Repack this folder\nThis button runs `mh-pack-folder'")
-  (mh-tool-bar-search (folder) "search"
-    "Search\nThis button runs `mh-tool-bar-search-function'")
-  (mh-visit-folder (folder) "fld-open"
-    "Visit other folder\nThis button runs `mh-visit-folder'")
-  ;; Letter buffer buttons
-  (mh-send-letter (letter) "mail/send" "Send this letter")
-  (mh-compose-insertion (letter) "attach" "Insert attachment")
-  (ispell-message (letter) "spell" "Check spelling")
-  (save-buffer (letter) "save" "Save current buffer to its file"
-    (buffer-modified-p))
-  (undo (letter) "undo" "Undo last operation")
-  (kill-region (letter) "cut"
-    "Cut (kill) text in region between mark and current position")
-  (menu-bar-kill-ring-save (letter) "copy"
-    "Copy text in region between mark and current position")
-  (yank (letter) "paste" "Paste (yank) text cut or copied earlier")
-  (mh-fully-kill-draft (letter) "close" "Kill this draft")
-  ;; Common buttons
-  (mh-tool-bar-customize (folder letter) "preferences" "MH-E Preferences")
-  (mh-tool-bar-folder-help (folder) "help"
-    "Help! (general help)\nThis button runs `info'")
-  (mh-tool-bar-letter-help (letter) "help"
-    "Help! (general help)\nThis button runs `info'")
-  ;; Folder narrowed to sequence buttons
-  (mh-widen (sequence) "widen"
-    "Widen from the sequence\nThis button runs `mh-widen'"))
-
-
-
-;;; Hooks (:group 'mh-hooks + group where hook described)
-
-(defcustom mh-after-commands-processed-hook nil
-  "Hook run by \\<mh-folder-mode-map>\\[mh-execute-commands] after performing outstanding requests.
-
-Variables that are useful in this hook include
-`mh-folders-changed', which lists which folders were affected by
-deletes and refiles. This list will always include the current
-folder, which is also available in `mh-current-folder'."
-  :type 'hook
-  :group 'mh-hooks
-  :group 'mh-folder)
-
-(defcustom mh-alias-reloaded-hook nil
-  "Hook run by `mh-alias-reload' after loading aliases."
-  :type 'hook
-  :group 'mh-hooks
-  :group 'mh-alias)
-
-(defcustom mh-before-commands-processed-hook nil
-  "Hook run by \\<mh-folder-mode-map>\\[mh-execute-commands] before performing outstanding requests.
-
-Variables that are useful in this hook include `mh-delete-list'
-and `mh-refile-list' which can be used to see which changes will
-be made to the current folder, `mh-current-folder'."
-  :type 'hook
-  :group 'mh-hooks
-  :group 'mh-folder)
-
-(defcustom mh-before-quit-hook nil
-  "Hook run by \\<mh-folder-mode-map>\\[mh-quit] before quitting MH-E.
-
-This hook is called before the quit occurs, so you might use it
-to perform any MH-E operations; you could perform some query and
-abort the quit or call `mh-execute-commands', for example.
-
-See also `mh-quit-hook'."
-  :type 'hook
-  :group 'mh-hooks
-  :group 'mh-folder)
-
-(defcustom mh-before-send-letter-hook nil
-  "Hook run at the beginning of the \\<mh-letter-mode-map>\\[mh-send-letter] command.
-
-For example, if you want to check your spelling in your message
-before sending, add the `ispell-message' function."
-  :type 'hook
-  :options '(ispell-message)
-  :group 'mh-hooks
-  :group 'mh-letter)
-
-(defcustom mh-delete-msg-hook nil
-  "Hook run by \\<mh-letter-mode-map>\\[mh-delete-msg] after marking each message for deletion.
-
-For example, a past maintainer of MH-E used this once when he
-kept statistics on his mail usage."
-  :type 'hook
-  :group 'mh-hooks
-  :group 'mh-show)
-
-(defcustom mh-find-path-hook nil
-  "Hook run by `mh-find-path' after reading the user's MH profile.
-
-This hook can be used the change the value of the variables that
-`mh-find-path' sets if you need to run with different values
-between MH and MH-E."
-  :type 'hook
-  :group 'mh-hooks
-  :group 'mh-e)
-
-(defcustom mh-folder-mode-hook nil
-  "Hook run by `mh-folder-mode' when visiting a new folder."
-  :type 'hook
-  :group 'mh-hooks
-  :group 'mh-folder)
-
-(defcustom mh-forward-hook nil
-  "Hook run by `mh-forward' on a forwarded letter."
-  :type 'hook
-  :group 'mh-hooks
-  :group 'mh-sending-mail)
-
-(defcustom mh-inc-folder-hook nil
-  "Hook run by \\<mh-folder-mode-map>\\[mh-inc-folder] after incorporating mail into a folder."
-  :type 'hook
-  :group 'mh-hooks
-  :group 'mh-inc)
-
-(defcustom mh-insert-signature-hook nil
-  "Hook run by \\<mh-letter-mode-map>\\[mh-insert-signature] after signature has been inserted.
-
-Hook functions may access the actual name of the file or the
-function used to insert the signature with
-`mh-signature-file-name'."
-  :type 'hook
-  :group 'mh-hooks
-  :group 'mh-letter)
-
-(defcustom mh-kill-folder-suppress-prompt-hooks '(mh-search-p)
-  "Abnormal hook run at the beginning of \\<mh-folder-mode-map>\\[mh-kill-folder].
-
-The hook functions are called with no arguments and should return
-a non-nil value to suppress the normal prompt when you remove a
-folder. This is useful for folders that are easily regenerated.
-
-The default value of `mh-search-p' suppresses the prompt on
-folders generated by searching.
-
-WARNING: Use this hook with care. If there is a bug in your hook
-which returns t on \"+inbox\" and you hit \\[mh-kill-folder] by
-accident in the \"+inbox\" folder, you will not be happy."
-  :type 'hook
-  :group 'mh-hooks
-  :group 'mh-folder)
-
-(defcustom mh-letter-mode-hook nil
-  "Hook run by `mh-letter-mode' on a new letter.
-
-This hook allows you to do some processing before editing a
-letter. For example, you may wish to modify the header after
-\"repl\" has done its work, or you may have a complicated
-\"components\" file and need to tell MH-E where the cursor should
-go."
-  :type 'hook
-  :group 'mh-hooks
-  :group 'mh-sending-mail)
-
-(defcustom mh-mh-to-mime-hook nil
-  "Hook run on the formatted letter by \\<mh-letter-mode-map>\\[mh-mh-to-mime]."
-  :type 'hook
-  :group 'mh-hooks
-  :group 'mh-letter)
-
-(defcustom mh-search-mode-hook nil
-  "Hook run upon entry to `mh-search-mode'\\<mh-folder-mode-map>.
-
-If you find that you do the same thing over and over when editing
-the search template, you may wish to bind some shortcuts to keys.
-This can be done with this hook which is called when
-\\[mh-search] is run on a new pattern."
-  :type 'hook
-  :group 'mh-hooks
-  :group 'mh-search)
-
-(defcustom mh-quit-hook nil
-  "Hook run by \\<mh-folder-mode-map>\\[mh-quit] after quitting MH-E.
-
-This hook is not run in an MH-E context, so you might use it to
-modify the window setup.
-
-See also `mh-before-quit-hook'."
-  :type 'hook
-  :group 'mh-hooks
-  :group 'mh-folder)
-
-(defcustom mh-refile-msg-hook nil
-  "Hook run by \\<mh-folder-mode-map>\\[mh-refile-msg] after marking each message for refiling."
-  :type 'hook
-  :group 'mh-hooks
-  :group 'mh-folder)
-
-(defcustom mh-show-hook nil
-  "Hook run after \\<mh-folder-mode-map>\\[mh-show] shows a message.
-
-It is the last thing called after messages are displayed. It's
-used to affect the behavior of MH-E in general or when
-`mh-show-mode-hook' is too early. See `mh-show-mode-hook'."
-  :type 'hook
-  :group 'mh-hooks
-  :group 'mh-show)
-
-(defcustom mh-show-mode-hook nil
-  "Hook run upon entry to `mh-show-mode'.
-
-This hook is called early on in the process of the message
-display. It is usually used to perform some action on the
-message's content. See `mh-show-hook'."
-  :type 'hook
-  :group 'mh-hooks
-  :group 'mh-show)
-
-(defcustom mh-unseen-updated-hook nil
-  "Hook run after the unseen sequence has been updated.
-
-The variable `mh-seen-list' can be used by this hook to obtain
-the list of messages which were removed from the unseen
-sequence."
-  :type 'hook
-  :group 'mh-hooks
-  :group 'mh-sequences)
-
-
-
-;;; Faces (:group 'mh-faces + group where faces described)
-
-(if (boundp 'facemenu-unlisted-faces)
-    (add-to-list 'facemenu-unlisted-faces "^mh-"))
-
-(defface mh-folder-address '((t (:inherit mh-folder-subject)))
-  "Recipient face."
-  :group 'mh-faces
-  :group 'mh-folder)
-
-(defface mh-folder-body
-  '((((class color))
-     (:inherit mh-folder-msg-number))
-    (t
-     (:inherit mh-folder-msg-number :italic t)))
-  "Body text face."
-  :group 'mh-faces
-  :group 'mh-folder)
-
-(defface mh-folder-cur-msg-number
-  '((t
-     (:inherit mh-folder-msg-number :bold t)))
-  "Current message number face."
-  :group 'mh-faces
-  :group 'mh-folder)
-
-(defface mh-folder-date '((t (:inherit mh-folder-msg-number)))
-  "Date face."
-  :group 'mh-faces
-  :group 'mh-folder)
-
-(defface mh-folder-deleted '((t (:inherit mh-folder-msg-number)))
-  "Deleted message face."
-  :group 'mh-faces
-  :group 'mh-folder)
-
-(defface mh-folder-followup
-  '((((class color) (background light))
-     (:foreground "blue3"))
-    (((class color) (background dark))
-     (:foreground "LightGoldenRod"))
-    (t
-     (:bold t)))
-  "\"Re:\" face."
-  :group 'mh-faces
-  :group 'mh-folder)
-
-(defface mh-folder-msg-number
-  (mh-defface-compat
-   '((((class color) (min-colors 88) (background light))
-      (:foreground "snow4"))
-     (((class color) (min-colors 88) (background dark))
-      (:foreground "snow3"))
-     (((class color))
-      (:foreground "cyan"))))
-
-  "Message number face."
-  :group 'mh-faces
-  :group 'mh-folder)
-
-(defface mh-folder-refiled
-  (mh-defface-compat
-   '((((class color) (min-colors 88) (background light))
-      (:foreground "DarkGoldenrod"))
-     (((class color) (min-colors 88) (background dark))
-      (:foreground "LightGoldenrod"))
-     (((class color))
-      (:foreground "yellow" :weight light))
-     (((class grayscale) (background light))
-      (:foreground "Gray90" :bold t :italic t))
-     (((class grayscale) (background dark))
-      (:foreground "DimGray" :bold t :italic t))
-     (t
-      (:bold t :italic t))))
-  "Refiled message face."
-  :group 'mh-faces
-  :group 'mh-folder)
-
-(defface mh-folder-sent-to-me-hint '((t (:inherit mh-folder-date)))
-  "Fontification hint face in messages sent directly to us.
-The detection of messages sent to us is governed by the scan
-format `mh-scan-format-nmh' and the regular expression
-`mh-scan-sent-to-me-sender-regexp'."
-  :group 'mh-faces
-  :group 'mh-folder)
-
-(defface mh-folder-sent-to-me-sender '((t (:inherit mh-folder-followup)))
-  "Sender face in messages sent directly to us.
-The detection of messages sent to us is governed by the scan
-format `mh-scan-format-nmh' and the regular expression
-`mh-scan-sent-to-me-sender-regexp'."
-  :group 'mh-faces
-  :group 'mh-folder)
-
-(defface mh-folder-subject
-  '((((class color) (background light))
-     (:foreground "blue4"))
-    (((class color) (background dark))
-     (:foreground "yellow"))
-    (t
-     (:bold t)))
-  "Subject face."
-  :group 'mh-faces
-  :group 'mh-folder)
-
-(defface mh-folder-tick
-  '((((class color) (background dark))
-     (:background "#dddf7e"))
-    (((class color) (background light))
-     (:background "#dddf7e"))
-    (t
-     (:underline t)))
-  "Ticked message face."
-  :group 'mh-faces
-  :group 'mh-folder)
-
-(defface mh-folder-to
-  (mh-defface-compat
-   '((((class color) (min-colors 88) (background light))
-      (:foreground "RosyBrown"))
-     (((class color) (min-colors 88) (background dark))
-      (:foreground "LightSalmon"))
-     (((class color))
-      (:foreground "green"))
-     (((class grayscale) (background light))
-      (:foreground "DimGray" :italic t))
-     (((class grayscale) (background dark))
-      (:foreground "LightGray" :italic t))
-     (t
-      (:italic t))))
-  "\"To:\" face."
-  :group 'mh-faces
-  :group 'mh-folder)
-
-(defface mh-search-folder
-  '((((class color) (background light))
-     (:foreground "dark green" :bold t))
-    (((class color) (background dark))
-     (:foreground "indian red" :bold t))
-    (t
-     (:bold t)))
-  "Folder heading face in MH-Folder buffers created by searches."
-  :group 'mh-faces
-  :group 'mh-search)
-
-(defface mh-letter-header-field
-  '((((class color) (background light))
-     (:background "gray90"))
-    (((class color) (background dark))
-     (:background "gray10"))
-    (t
-     (:bold t)))
-  "Editable header field value face in draft buffers."
-  :group 'mh-faces
-  :group 'mh-letter)
-
-(defface mh-show-cc
-  (mh-defface-compat
-   '((((class color) (min-colors 88) (background light))
-      (:foreground "DarkGoldenrod"))
-     (((class color) (min-colors 88) (background dark))
-      (:foreground "LightGoldenrod"))
-     (((class color))
-      (:foreground "yellow" :weight light))
-     (((class grayscale) (background light))
-      (:foreground "Gray90" :bold t :italic t))
-     (((class grayscale) (background dark))
-      (:foreground "DimGray" :bold t :italic t))
-     (t
-      (:bold t :italic t))))
-  "Face used to highlight \"cc:\" header fields."
-  :group 'mh-faces
-  :group 'mh-show)
-
-(defface mh-show-date
-  (mh-defface-compat
-   '((((class color) (min-colors 88) (background light))
-      (:foreground "ForestGreen"))
-     (((class color) (min-colors 88) (background dark))
-      (:foreground "PaleGreen"))
-     (((class color))
-      (:foreground "green"))
-     (((class grayscale) (background light))
-      (:foreground "Gray90" :bold t))
-     (((class grayscale) (background dark))
-      (:foreground "DimGray" :bold t))
-     (t
-      (:bold t :underline t))))
-  "Face used to highlight \"Date:\" header fields."
-  :group 'mh-faces
-  :group 'mh-show)
-
-(defface mh-show-from
-  '((((class color) (background light))
-     (:foreground "red3"))
-    (((class color) (background dark))
-     (:foreground "cyan"))
-    (t
-     (:bold t)))
-  "Face used to highlight \"From:\" header fields."
-  :group 'mh-faces
-  :group 'mh-show)
-
-(defface mh-show-header
-  (mh-defface-compat
-   '((((class color) (min-colors 88) (background light))
-      (:foreground "RosyBrown"))
-     (((class color) (min-colors 88) (background dark))
-      (:foreground "LightSalmon"))
-     (((class color))
-      (:foreground "green"))
-     (((class grayscale) (background light))
-      (:foreground "DimGray" :italic t))
-     (((class grayscale) (background dark))
-      (:foreground "LightGray" :italic t))
-     (t
-      (:italic t))))
-  "Face used to deemphasize less interesting header fields."
-  :group 'mh-faces
-  :group 'mh-show)
-
-(defface mh-show-pgg-bad '((t (:bold t :foreground "DeepPink1")))
-  "Bad PGG signature face."
-  :group 'mh-faces
-  :group 'mh-show)
-
-(defface mh-show-pgg-good '((t (:bold t :foreground "LimeGreen")))
-  "Good PGG signature face."
-  :group 'mh-faces
-  :group 'mh-show)
-
-(defface mh-show-pgg-unknown '((t (:bold t :foreground "DarkGoldenrod2")))
-  "Unknown or untrusted PGG signature face."
-  :group 'mh-faces
-  :group 'mh-show)
-
-(defface mh-show-signature '((t (:italic t)))
-  "Signature face."
-  :group 'mh-faces
-  :group 'mh-show)
-
-(defface mh-show-subject '((t (:inherit mh-folder-subject)))
-  "Face used to highlight \"Subject:\" header fields."
-  :group 'mh-faces
-  :group 'mh-show)
-
-(defface mh-show-to
-  '((((class color) (background light))
-     (:foreground "SaddleBrown"))
-    (((class color) (background dark))
-     (:foreground "burlywood"))
-    (((class grayscale) (background light))
-     (:foreground "DimGray" :underline t))
-    (((class grayscale) (background dark))
-     (:foreground "LightGray" :underline t))
-    (t (:underline t)))
-  "Face used to highlight \"To:\" header fields."
-  :group 'mh-faces
-  :group 'mh-show)
-
-(defface mh-show-xface '((t (:inherit (mh-show-from highlight))))
-  "X-Face image face.
-The background and foreground are used in the image."
-  :group 'mh-faces
-  :group 'mh-show)
-
-(defface mh-speedbar-folder
-  '((((class color) (background light))
-     (:foreground "blue4"))
-    (((class color) (background dark))
-     (:foreground "light blue")))
-  "Basic folder face."
-  :group 'mh-faces
-  :group 'mh-speedbar)
-
-(defface mh-speedbar-folder-with-unseen-messages
-  '((t
-     (:inherit mh-speedbar-folder :bold t)))
-  "Folder face when folder contains unread messages."
-  :group 'mh-faces
-  :group 'mh-speedbar)
-
-(defface mh-speedbar-selected-folder
-  '((((class color) (background light))
-     (:foreground "red1" :underline t))
-    (((class color) (background dark))
-     (:foreground "red1" :underline t))
-    (t
-     (:underline t)))
-  "Selected folder face."
-  :group 'mh-faces
-  :group 'mh-speedbar)
-
-(defface mh-speedbar-selected-folder-with-unseen-messages
-  '((t
-     (:inherit mh-speedbar-selected-folder :bold t)))
-  "Selected folder face when folder contains unread messages."
-  :group 'mh-faces
-  :group 'mh-speedbar)
-
-;;; XXX Temporary function for comparing old and new faces. Delete
-;;; when everybody is happy.
-(defvar bw-face-generation 'new)
-
-(defun bw-toggle-faces ()
-  "Toggle between old and new faces."
-  (interactive)
-  (cond ((eq bw-face-generation 'new)
-         (message "Going from new to old...")
-         (bw-new-face-to-old)
-         (message "Going from new to old...done")
-         (setq bw-face-generation 'old))
-        ((eq bw-face-generation 'old)
-         (message "Going from old to new...")
-         (bw-old-face-to-new)
-         (message "Going from old to new...done")
-         (setq bw-face-generation 'new))))
-
-(defun bw-new-face-to-old ()
-  "Set old faces."
-  (face-spec-set 'mh-folder-body
-    (mh-defface-compat
-     '((((class color) (min-colors 88) (background light))
-        (:foreground "RosyBrown"))
-       (((class color) (min-colors 88) (background dark))
-        (:foreground "LightSalmon"))
-       (((class color))
-        (:foreground "green"))
-       (((class grayscale) (background light))
-        (:foreground "DimGray" :italic t))
-       (((class grayscale) (background dark))
-        (:foreground "LightGray" :italic t))
-       (t
-        (:italic t)))))
-
-  (face-spec-set 'mh-folder-msg-number
-    '((((class color) (background light))
-       (:foreground "snow4"))
-      (((class color) (background dark))
-       (:foreground "snow3"))
-      (t
-       (:bold t))))
-
-  (face-spec-set 'mh-folder-cur-msg-number
-    (mh-defface-compat
-     '((((class color) (min-colors 88) (background light))
-        (:foreground "Purple"))
-       (((class color) (min-colors 88) (background dark))
-        (:foreground "Cyan"))
-       (((class color))
-        (:foreground "cyan" :weight bold))
-       (((class grayscale) (background light))
-        (:foreground "LightGray" :bold t))
-       (((class grayscale) (background dark))
-        (:foreground "DimGray" :bold t))
-       (t
-        (:bold t)))))
-
-  (face-spec-set 'mh-folder-date
-    '((((class color) (background light))
-       (:foreground "snow4"))
-      (((class color) (background dark))
-       (:foreground "snow3"))
-      (t
-       (:bold t))))
-
-  (face-spec-set 'mh-folder-msg-number
-    '((((class color) (background light))
-       (:foreground "snow4"))
-      (((class color) (background dark))
-       (:foreground "snow3"))
-      (t
-       (:bold t)))))
-
-(defun bw-old-face-to-new ()
-  "Set new faces."
-  (face-spec-set 'mh-folder-body
-    '((((class color))
-       (:inherit mh-folder-msg-number))
-      (t
-       (:inherit mh-folder-msg-number :italic t))))
-
-  (face-spec-set 'mh-folder-cur-msg-number
-    '((t
-       (:inherit mh-folder-msg-number :bold t))))
-
-  (face-spec-set 'mh-folder-date '((t (:inherit mh-folder-msg-number))))
-
-  (face-spec-set 'mh-folder-msg-number
-    '((((class color) (background light))
-       (:foreground "snow4"))
-      (((class color) (background dark))
-       (:foreground "snow3"))
-      (((class color))
-       (:foreground "cyan")))))
-
-;; Local Variables:
-;; indent-tabs-mode: nil
-;; sentence-end-double-space: nil
-;; End:
-
-;; arch-tag: 778d2a20-82e2-4276-be9d-309386776a68
-;;; mh-customize.el ends here
--- a/lisp/mh-e/mh-e.el	Thu Jan 26 02:23:05 2006 +0000
+++ b/lisp/mh-e/mh-e.el	Wed Feb 01 10:07:17 2006 +0000
@@ -28,16 +28,22 @@
 
 ;;; Commentary:
 
-;; How to Use:
+;; How to use:
 ;;   M-x mh-rmail to read mail.  Type C-h m there for a list of commands.
 ;;   C-u M-x mh-rmail to visit any folder.
-;;   M-x mh-smail to send mail.  From within the mail reader, "m" works, too.
+;;   M-x mh-smail to send mail.  From within the mail reader, "s" works, too.
 
 ;; Your .emacs might benefit from these bindings:
 ;;   (global-set-key "\C-cr" 'mh-rmail)
 ;;   (global-set-key "\C-xm" 'mh-smail)
 ;;   (global-set-key "\C-x4m" 'mh-smail-other-window)
 
+;; If Emacs can't find mh-rmail or mh-smail, add the following to ~/.emacs:
+;;   (require 'mh-autoloads)
+
+;; If you want to customize MH-E before explicitly loading it, add this:
+;;   (require 'mh-cus-load)
+
 ;; MH (Message Handler) is a powerful mail reader.
 
 ;; The MH newsgroup is comp.mail.mh; the mailing list is mh-users@ics.uci.edu
@@ -59,17 +65,18 @@
 ;;   mh-e-users@lists.sourceforge.net
 ;;   mh-e-announce@lists.sourceforge.net
 ;;   mh-e-devel@lists.sourceforge.net
-;;
+
 ;;   Subscribe by sending a "subscribe" message to
 ;;   <list>-request@lists.sourceforge.net, or by using the web interface at
 ;;   https://sourceforge.net/mail/?group_id=13357
 
 ;; Bug Reports:
 ;;   https://sourceforge.net/tracker/?group_id=13357&atid=113357
-;;   Include the output of M-x mh-version in any bug report.
+;;   Include the output of M-x mh-version in the bug report unless
+;;   you're 110% sure we won't ask for it.
 
 ;; Feature Requests:
-;;   https://sourceforge.net/tracker/?atid=363357&group_id=13357&func=browse
+;;   https://sourceforge.net/tracker/?group_id=13357&atid=363357
 
 ;; Support:
 ;;   https://sourceforge.net/tracker/?group_id=13357&atid=213357
@@ -85,1236 +92,283 @@
 
 ;;; Code:
 
-;;(message "> mh-e")
-(provide 'mh-e)
-
-(eval-when-compile (require 'mh-acros))
+;; Provide functions to the rest of MH-E. However, mh-e.el must not
+;; use any definitions in files that require mh-e from mh-loaddefs,
+;; for if it does it will introduce a require loop.
+(require 'mh-loaddefs)
+
 (mh-require-cl)
 
-(require 'easymenu)
-(require 'gnus-util)
+(eval-and-compile
+  (defvar mh-xemacs-flag (featurep 'xemacs)
+    "Non-nil means the current Emacs is XEmacs."))
+(mh-do-in-xemacs
+  (require 'mh-xemacs))
+
 (require 'mh-buffers)
-(require 'mh-seq)
-(require 'mh-utils)
-;;(message "< mh-e")
-
-(defconst mh-version "7.85+cvs" "Version number of MH-E.")
-
-(defvar mh-partial-folder-mode-line-annotation "select"
-  "Annotation when displaying part of a folder.
-The string is displayed after the folder's name. nil for no
-annotation.")
+(require 'mh-compat)
 
 
 
-;;; Scan Line Formats
-
-;; Parameterize MH-E to work with different scan formats.  The defaults work
-;; with the standard MH scan listings, in which the first 4 characters on
-;; the line are the message number, followed by two places for notations.
-
-;; The following scan formats are passed to the scan program if the setting of
-;; `mh-scan-format-file' is t. They are identical except the later one makes
-;; use of the nmh `decode' function to decode RFC 2047 encodings. If you just
-;; want to change the column of the notations, use the `mh-set-cmd-note'
-;; function.
-
-(defvar mh-scan-format-mh
-  (concat
-   "%4(msg)"
-   "%<(cur)+%| %>"
-   "%<{replied}-"
-   "%?(nonnull(comp{to}))%<(mymbox{to})t%>"
-   "%?(nonnull(comp{cc}))%<(mymbox{cc})c%>"
-   "%?(nonnull(comp{bcc}))%<(mymbox{bcc})b%>"
-   "%?(nonnull(comp{newsgroups}))n%>"
-   "%<(zero) %>"
-   "%02(mon{date})/%02(mday{date})%<{date} %|*%>"
-   "%<(mymbox{from})%<{to}To:%14(friendly{to})%>%>"
-   "%<(zero)%17(friendly{from})%>  "
-   "%{subject}%<{body}<<%{body}%>")
-  "*Scan format string for MH.
-This string is passed to the scan program via the -format
-argument. This format is identical to the default except that
-additional hints for fontification have been added to the fifth
-column (remember that in Emacs, the first column is 0).
-
-The values of the fifth column, in priority order, are: \"-\" if
-the message has been replied to, t if an address on the To: line
-matches one of the mailboxes of the current user, \"c\" if the Cc:
-line matches, \"b\" if the Bcc: line matches, and \"n\" if a
-non-empty Newsgroups: header is present.")
-
-(defvar mh-scan-format-nmh
-  (concat
-   "%4(msg)"
-   "%<(cur)+%| %>"
-   "%<{replied}-"
-   "%?(nonnull(comp{to}))%<(mymbox{to})t%>"
-   "%?(nonnull(comp{cc}))%<(mymbox{cc})c%>"
-   "%?(nonnull(comp{bcc}))%<(mymbox{bcc})b%>"
-   "%?(nonnull(comp{newsgroups}))n%>"
-   "%<(zero) %>"
-   "%02(mon{date})/%02(mday{date})%<{date} %|*%>"
-   "%<(mymbox{from})%<{to}To:%14(decode(friendly{to}))%>%>"
-   "%<(zero)%17(decode(friendly{from}))%>  "
-   "%(decode{subject})%<{body}<<%{body}%>")
-  "*Scan format string for nmh.
-This string is passed to the scan program via the -format arg.
-This format is identical to the default except that additional
-hints for fontification have been added to the fifth
-column (remember that in Emacs, the first column is 0).
-
-The values of the fifth column, in priority order, are: \"-\" if
-the message has been replied to, t if an address on the To: field
-matches one of the mailboxes of the current user, \"c\" if the Cc:
-field matches, \"b\" if the Bcc: field matches, and \"n\" if a
-non-empty Newsgroups: field is present.")
-
-(defvar mh-note-deleted ?D
-  "Messages that have been deleted are marked by this character.
-See also `mh-scan-deleted-msg-regexp'.")
-
-(defvar mh-note-refiled ?^
-  "Messages that have been refiled are marked by this character.
-See also `mh-scan-refiled-msg-regexp'.")
-
-(defvar mh-note-cur ?+
-  "The current message (in MH, not in MH-E) is marked by this character.
-See also `mh-scan-cur-msg-number-regexp'.")
-
-(defvar mh-scan-good-msg-regexp  "^\\( *[0-9]+\\)[^D^0-9]"
-  "This regular expression matches \"good\" messages.
-
-It must match from the beginning of the line. Note that the
-default setting of `mh-folder-font-lock-keywords' expects this
-expression to contain at least one parenthesized expression which
-matches the message number as in the default of
-
-  \"^\\\\( *[0-9]+\\\\)[^D^0-9]\".
-
-This expression includes the leading space within the parenthesis
-since it looks better to highlight it as well. The highlighting
-is done with the face `mh-folder-msg-number'. This regular
-expression should be correct as it is needed by non-fontification
-functions.")
-
-(defvar mh-scan-deleted-msg-regexp "^\\( *[0-9]+\\)D"
-  "This regular expression matches deleted messages.
-
-It must match from the beginning of the line. Note that the
-default setting of `mh-folder-font-lock-keywords' expects this
-expression to contain at least one parenthesized expression which
-matches the message number as in the default of
-
-  \"^\\\\( *[0-9]+\\\\)D\".
-
-This expression includes the leading space within the parenthesis
-since it looks better to highlight it as well. The highlighting
-is done with the face `mh-folder-deleted'. This regular
-expression should be correct as it is needed by non-fontification
-functions. See also `mh-note-deleted'.")
-
-(defvar mh-scan-refiled-msg-regexp  "^\\( *[0-9]+\\)\\^"
-  "This regular expression matches refiled messages.
-
-It must match from the beginning of the line. Note that the
-default setting of `mh-folder-font-lock-keywords' expects this
-expression to contain at least one parenthesized expression which
-matches the message number as in the default of
-
-  \"^\\\\( *[0-9]+\\\\)\\\\^\".
-
-This expression includes the leading space within the parenthesis
-since it looks better to highlight it as well. The highlighting
-is done with the face `mh-folder-refiled'. This regular
-expression should be correct as it is needed by non-fontification
-functions. See also `mh-note-refiled'.")
-
-(defvar mh-scan-valid-regexp "^ *[0-9]"
-  "This regular expression describes a valid scan line.
-
-This is used to eliminate error messages that are occasionally
-produced by \"inc\".")
-
-(defvar mh-scan-cur-msg-number-regexp "^\\( *[0-9]+\\+\\).*"
-  "This regular expression matches the current message.
-
-It must match from the beginning of the line. Note that the
-default setting of `mh-folder-font-lock-keywords' expects this
-expression to contain at least one parenthesized expression which
-matches the message number as in the default of
-
-  \"^\\\\( *[0-9]+\\\\+\\\\).*\".
-
-This expression includes the leading space and current message
-marker \"+\" within the parenthesis since it looks better to
-highlight these items as well. The highlighting is done with the
-face `mh-folder-cur-msg-number'. This regular expression should
-be correct as it is needed by non-fontification functions. See
-also `mh-note-cur'.")
-
-(defvar mh-scan-date-regexp "\\([0-9][0-9]/[0-9][0-9]\\)"
-  "This regular expression matches a valid date.
-
-It must not be anchored to the beginning or the end of the line.
-Note that the default setting of `mh-folder-font-lock-keywords'
-expects this expression to contain only one parenthesized
-expression which matches the date field as in the default of
-\"\\\\([0-9][0-9]/[0-9][0-9]\\\\)\"}. If this regular expression
-is not correct, the date will not be highlighted with the face
-`mh-folder-date'.")
-
-(defvar mh-scan-rcpt-regexp  "\\(To:\\)\\(..............\\)"
-  "This regular expression specifies the recipient in messages you sent.
-
-Note that the default setting of `mh-folder-font-lock-keywords'
-expects this expression to contain two parenthesized expressions.
-The first is expected to match the \"To:\" that the default scan
-format file generates. The second is expected to match the
-recipient's name as in the default of
-\"\\\\(To:\\\\)\\\\(..............\\\\)\". If this regular
-expression is not correct, the \"To:\" string will not be
-highlighted with the face `mh-folder-to' and the recipient will
-not be highlighted with the face `mh-folder-address'")
-
-(defvar mh-scan-body-regexp "\\(<<\\([^\n]+\\)?\\)"
-  "This regular expression matches the message body fragment.
-
-Note that the default setting of `mh-folder-font-lock-keywords'
-expects this expression to contain at least one parenthesized
-expression which matches the body text as in the default of
-\"\\\\(<<\\\\([^\\n]+\\\\)?\\\\)\". If this regular expression is
-not correct, the body fragment will not be highlighted with the
-face `mh-folder-body'.")
-
-(defvar mh-scan-subject-regexp
-  "^ *[0-9]+........[ ]*...................\\([Rr][Ee]\\(\\[[0-9]+\\]\\)?:\\s-*\\)*\\([^<\n]*\\)"
-  "This regular expression matches the subject.
-
-It must match from the beginning of the line. Note that the
-default setting of `mh-folder-font-lock-keywords' expects this
-expression to contain at least three parenthesized expressions.
-The first is expected to match the \"Re:\" string, if any, and is
-highlighted with the face `mh-folder-followup'. The second
-matches an optional bracketed number after \"Re:\", such as in
-\"Re[2]:\" (and is thus a sub-expression of the first expression)
-and the third is expected to match the subject line itself which
-is highlighted with the face `mh-folder-subject'. For example,
-the default (broken on multiple lines for readability) is
-
-  ^ *[0-9]+........[ ]*...................
-  \\\\([Rr][Ee]\\\\(\\\\\\=[[0-9]+\\\\]\\\\)?:\\\\s-*\\\\)*
-  \\\\([^<\\n]*\\\\)
-
-This regular expression should be correct as it is needed by
-non-fontification functions.")
-
-(defvar mh-scan-sent-to-me-sender-regexp
-  "^ *[0-9]+.\\([bct]\\).....[ ]*\\(..................\\)"
-  "This regular expression matches messages sent to us.
-
-Note that the default setting of `mh-folder-font-lock-keywords'
-expects this expression to contain at least two parenthesized
-expressions. The first should match the fontification hint (see
-`mh-scan-format-nmh') and the second should match the user name
-as in the default of
-
-  ^ *[0-9]+.\\\\([bct]\\\\).....[ ]*\\\\(..................\\\\)
-
-If this regular expression is not correct, the notation hints
-will not be highlighted with the face
-`mh-mh-folder-sent-to-me-hint' and the sender will not be
-highlighted with the face `mh-folder-sent-to-me-sender'.")
-
-
-
-(defvar mh-folder-font-lock-keywords
-  (list
-   ;; Folders when displaying index buffer
-   (list "^\\+.*"
-         '(0 'mh-search-folder))
-   ;; Marked for deletion
-   (list (concat mh-scan-deleted-msg-regexp ".*")
-         '(0 'mh-folder-deleted))
-   ;; Marked for refile
-   (list (concat mh-scan-refiled-msg-regexp ".*")
-         '(0 'mh-folder-refiled))
-   ;; After subject
-   (list mh-scan-body-regexp
-         '(1 'mh-folder-body nil t))
-   ;; Subject
-   '(mh-folder-font-lock-subject
-     (1 'mh-folder-followup append t)
-     (2 'mh-folder-subject append t))
-   ;; Current message number
-   (list mh-scan-cur-msg-number-regexp
-         '(1 'mh-folder-cur-msg-number))
-   ;; Message number
-   (list mh-scan-good-msg-regexp
-         '(1 'mh-folder-msg-number))
-   ;; Date
-   (list mh-scan-date-regexp
-         '(1 'mh-folder-date))
-   ;; Messages from me (To:)
-   (list mh-scan-rcpt-regexp
-         '(1 'mh-folder-to)
-         '(2 'mh-folder-address))
-   ;; Messages to me
-   (list mh-scan-sent-to-me-sender-regexp
-         '(1 'mh-folder-sent-to-me-hint)
-         '(2 'mh-folder-sent-to-me-sender)))
-  "Keywords (regular expressions) used to fontify the MH-Folder buffer.")
-
-(defvar mh-scan-cmd-note-width 1
-  "Number of columns consumed by the cmd-note field in `mh-scan-format'.
-
-This column will have one of the values: \" \", \"D\", \"^\", \"+\" and
-where \" \" is the default value,
-
-  \"D\" is the `mh-note-deleted' character,
-  \"^\" is the `mh-note-refiled' character, and
-  \"+\" is the `mh-note-cur' character.")
-
-(defvar mh-scan-destination-width 1
-  "Number of columns consumed by the destination field in `mh-scan-format'.
-
-This column will have one of \" \", \"%\", \"-\", \"t\", \"c\", \"b\", or \"n\"
-in it.
-
-  \" \" blank space is the default character.
-  \"%\" indicates that the message in in a named MH sequence.
-  \"-\" indicates that the message has been annotated with a replied field.
-  \"t\" indicates that the message contains mymbox in the To: field.
-  \"c\" indicates that the message contains mymbox in the Cc: field.
-  \"b\" indicates that the message contains mymbox in the Bcc: field.
-  \"n\" indicates that the message contains a Newsgroups: field.")
-
-(defvar mh-scan-date-width 5
-  "Number of columns consumed by the date field in `mh-scan-format'.
-This column will typically be of the form mm/dd.")
-
-(defvar mh-scan-date-flag-width 1
-  "Number of columns consumed to flag (in)valid dates in `mh-scan-format'.
-This column will have \" \" for valid and \"*\" for invalid or
-missing dates.")
-
-(defvar mh-scan-from-mbox-width 17
-  "Number of columns consumed with the \"From:\" line in `mh-scan-format'.
-This column will have a friendly name or e-mail address of the
-originator, or a \"To: address\" for outgoing e-mail messages.")
-
-(defvar mh-scan-from-mbox-sep-width 2
-  "Number of columns consumed by whitespace after from-mbox in `mh-scan-format'.
-This column will only ever have spaces in it.")
-
-(defvar mh-scan-field-destination-offset
-  (+ mh-scan-cmd-note-width)
-  "The offset from the `mh-cmd-note' for the destination column.")
-
-(defvar mh-scan-field-from-start-offset
-  (+ mh-scan-cmd-note-width
-     mh-scan-destination-width
-     mh-scan-date-width
-     mh-scan-date-flag-width)
-  "The offset from the `mh-cmd-note' to find the start of \"From:\" address.")
-
-(defvar mh-scan-field-from-end-offset
-  (+ mh-scan-field-from-start-offset mh-scan-from-mbox-width)
-  "The offset from the `mh-cmd-note' to find the end of \"From:\" address.")
-
-(defvar mh-scan-field-subject-start-offset
-  (+ mh-scan-cmd-note-width
-     mh-scan-destination-width
-     mh-scan-date-width
-     mh-scan-date-flag-width
-     mh-scan-from-mbox-width
-     mh-scan-from-mbox-sep-width)
-  "The offset from the `mh-cmd-note' to find the start of the subject.")
-
-(defun mh-folder-font-lock-subject (limit)
-  "Return MH-E scan subject strings to font-lock between point and LIMIT."
-  (if (not (re-search-forward mh-scan-subject-regexp limit t))
-      nil
-    (if (match-beginning 1)
-        (set-match-data (list (match-beginning 1) (match-end 3)
-                              (match-beginning 1) (match-end 3) nil nil))
-      (set-match-data (list (match-beginning 3) (match-end 3)
-                            nil nil (match-beginning 3) (match-end 3))))
-    t))
-
-
-
-;; Fontifify unseen mesages in bold.
-
-(defmacro mh-generate-sequence-font-lock (seq prefix face)
-  "Generate the appropriate code to fontify messages in SEQ.
-PREFIX is used to generate unique names for the variables and
-functions defined by the macro. So a different prefix should be
-provided for every invocation.
-FACE is the font-lock face used to display the matching scan lines."
-  (let ((cache (intern (format "mh-folder-%s-seq-cache" prefix)))
-        (func (intern (format "mh-folder-font-lock-%s" prefix))))
-    `(progn
-       (defvar ,cache nil
-         "Internal cache variable used for font-lock in MH-E.
-Should only be non-nil through font-lock stepping, and nil once
-font-lock is done highlighting.")
-       (make-variable-buffer-local ',cache)
-
-       (defun ,func (limit)
-         "Return unseen message lines to font-lock between point and LIMIT."
-         (if (not ,cache) (setq ,cache (mh-seq-msgs (mh-find-seq ,seq))))
-         (let ((cur-msg (mh-get-msg-num nil)))
-           (cond ((not ,cache)
-                  nil)
-                 ((>= (point) limit)              ;Presumably at end of buffer
-                  (setq ,cache nil)
-                  nil)
-                 ((member cur-msg ,cache)
-                  (let ((bpoint (progn (beginning-of-line)(point)))
-                        (epoint (progn (forward-line 1)(point))))
-                    (if (<= limit (point)) (setq  ,cache nil))
-                    (set-match-data (list bpoint epoint bpoint epoint))
-                    t))
-                 (t
-                  ;; move forward one line at a time, checking each message
-                  (while (and (= 0 (forward-line 1))
-                              (> limit (point))
-                              (not (member (mh-get-msg-num nil) ,cache))))
-                  ;; Examine how we must have exited the loop...
-                  (let ((cur-msg (mh-get-msg-num nil)))
-                    (cond ((or (<= limit (point))
-                               (not (member cur-msg ,cache)))
-                           (setq ,cache nil)
-                           nil)
-                          ((member cur-msg ,cache)
-                           (let ((bpoint (progn (beginning-of-line) (point)))
-                                 (epoint (progn (forward-line 1) (point))))
-                             (if (<= limit (point)) (setq ,cache nil))
-                             (set-match-data
-                              (list bpoint epoint bpoint epoint))
-                             t))))))))
-
-       (setq mh-folder-font-lock-keywords
-             (append mh-folder-font-lock-keywords
-                     (list (list ',func (list 1 '',face 'prepend t))))))))
-
-(mh-generate-sequence-font-lock mh-unseen-seq unseen bold)
-(mh-generate-sequence-font-lock mh-tick-seq tick mh-folder-tick)
-
-
-
-;;; Internal variables:
-
-(defvar mh-last-destination nil
-  "Destination of last refile or write command.")
-
-(defvar mh-last-destination-folder nil
-  "Destination of last refile command.")
-
-(defvar mh-last-destination-write nil
-  "Destination of last write command.")
+;;; Global Variables
+
+;; Try to keep variables local to a single file. Provide accessors if
+;; variables are shared. Use this section as a last resort.
+
+(defconst mh-version "7.85+sans-entropy" "Version number of MH-E.")
+
+;; Variants
+
+(defvar mh-sys-path
+  '("/usr/local/nmh/bin"                ; nmh default
+    "/usr/local/bin/mh/"
+    "/usr/local/mh/"
+    "/usr/bin/mh/"                      ; Ultrix 4.2, Linux
+    "/usr/new/mh/"                      ; Ultrix < 4.2
+    "/usr/contrib/mh/bin/"              ; BSDI
+    "/usr/pkg/bin/"                     ; NetBSD
+    "/usr/local/bin/"
+    "/usr/local/bin/mu-mh/"             ; GNU mailutils - default
+    "/usr/bin/mu-mh/")                  ; GNU mailutils - packaged
+  "List of directories to search for variants of the MH variant.
+The list `exec-path' is searched in addition to this list.
+There's no need for users to modify this list. Instead add extra
+directories to the customizable variable `mh-path'.")
+
+(defvar mh-variants nil
+  "List describing known MH variants.
+Do not access this variable directly as it may not have yet been initialized.
+Use the function `mh-variants' instead.")
+
+(defvar mh-variant-in-use nil
+  "The MH variant currently in use; a string with variant and version number.
+This differs from `mh-variant' when the latter is set to
+\"autodetect\".")
+
+(defvar mh-progs nil
+  "Directory containing MH commands, such as inc, repl, and rmm.")
+
+;;;###autoload
+(put 'mh-progs 'risky-local-variable t)
+
+(defvar mh-lib nil
+  "Directory containing the MH library.
+This directory contains, among other things, the components file.")
+
+;;;###autoload
+(put 'mh-lib 'risky-local-variable t)
+
+(defvar mh-lib-progs nil
+  "Directory containing MH helper programs.
+This directory contains, among other things, the mhl program.")
+
+;;;###autoload
+(put 'mh-lib-progs 'risky-local-variable t)
+
+;; Profile Components
+
+(defvar mh-draft-folder nil
+  "Cached value of the \"Draft-Folder:\" MH profile component.
+Name of folder containing draft messages.
+Nil means do not use a draft folder.")
+
+(defvar mh-inbox nil
+  "Cached value of the \"Inbox:\" MH profile component.
+Set to \"+inbox\" if no such component.
+Name of the Inbox folder.")
+
+(defvar mh-user-path nil
+  "Cached value of the \"Path:\" MH profile component.
+User's mail folder directory.")
+
+;; Maps declared here so that they can be used in docstrings.
 
 (defvar mh-folder-mode-map (make-keymap)
-  "Keymap for MH folders.")
+  "Keymap for MH-Folder mode.")
+
+(defvar mh-folder-seq-tool-bar-map nil
+  "Keymap for MH-Folder tool bar.")
+
+(defvar mh-folder-tool-bar-map nil
+  "Keymap for MH-Folder tool bar.")
+
+(defvar mh-inc-spool-map (make-sparse-keymap)
+  "Keymap for MH-E's mh-inc-spool commands.")
+
+(defvar mh-letter-mode-map (copy-keymap text-mode-map)
+  "Keymap for MH-Letter mode.")
+
+(defvar mh-letter-tool-bar-map nil
+  "Keymap for MH-Letter tool bar.")
+
+(defvar mh-search-mode-map (make-sparse-keymap)
+  "Keymap for MH-Search mode.")
+
+(defvar mh-show-mode-map (make-sparse-keymap)
+  "Keymap MH-Show mode.")
+
+(defvar mh-show-seq-tool-bar-map nil
+  "Keymap for MH-Show tool bar.")
+
+(defvar mh-show-tool-bar-map nil
+  "Keymap for MH-Show tool bar.")
+
+;; MH-Folder Locals (alphabetical)
 
 (defvar mh-arrow-marker nil
   "Marker for arrow display in fringe.")
 
+(defvar mh-colors-available-flag nil
+  "Non-nil means colors are available.")
+
+(defvar mh-current-folder nil
+  "Name of current folder, a string.")
+
 (defvar mh-delete-list nil
   "List of message numbers to delete.
 This variable can be used by
 `mh-before-commands-processed-hook'.")
 
-(defvar mh-refile-list nil
-  "List of folder names in `mh-seq-list'.
-This variable can be used by
-`mh-before-commands-processed-hook'.")
-
-(defvar mh-folders-changed nil
-  "Lists which folders were affected by deletes and refiles.
-This list will always include the current folder
-`mh-current-folder'. This variable can be used by
-`mh-after-commands-processed-hook'.")
-
-(defvar mh-next-direction 'forward
-  "Direction to move to next message.")
-
-(defvar mh-view-ops ()
-  "Stack of operations that change the folder view.
-These operations include narrowing or threading.")
-
-(defvar mh-folder-view-stack ()
+(defvar mh-folder-view-stack nil
   "Stack of previous folder views.")
 
 (defvar mh-index-data nil
   "Info about index search results.")
 
 (defvar mh-index-previous-search nil)
+
 (defvar mh-index-msg-checksum-map nil)
+
 (defvar mh-index-checksum-origin-map nil)
+
 (defvar mh-index-sequence-search-flag nil)
 
-(defvar mh-first-msg-num nil
-  "Number of first message in buffer.")
-
-(defvar mh-last-msg-num nil
-  "Number of last msg in buffer.")
-
 (defvar mh-mode-line-annotation nil
   "Message range displayed in buffer.")
 
+(defvar mh-next-direction 'forward
+  "Direction to move to next message.")
+
+(defvar mh-previous-window-config nil
+  "Window configuration before MH-E command.")
+
+(defvar mh-refile-list nil
+  "List of folder names in `mh-seq-list'.
+This variable can be used by
+`mh-before-commands-processed-hook'.")
+
+(defvar mh-seen-list nil
+  "List of displayed messages to be removed from the \"Unseen\" sequence.")
+
+(defvar mh-seq-list nil
+  "Alist of this folder's sequences.
+Elements have the form (SEQUENCE . MESSAGES).")
+
 (defvar mh-sequence-notation-history nil
   "Remember original notation that is overwritten by `mh-note-seq'.")
 
-(defvar mh-colors-available-flag nil
-  "Non-nil means colors are available.")
-
-
-
-;;; Macros and generic functions:
-
-(defun mh-mapc (function list)
-  "Apply FUNCTION to each element of LIST for side effects only."
-  (while list
-    (funcall function (car list))
-    (setq list (cdr list))))
-
-(defun mh-scan-format ()
-  "Return the output format argument for the scan program."
-  (if (equal mh-scan-format-file t)
-      (list "-format" (if (mh-variant-p 'nmh 'mu-mh)
-                          (list (mh-update-scan-format
-                                 mh-scan-format-nmh mh-cmd-note))
-                        (list (mh-update-scan-format
-                               mh-scan-format-mh mh-cmd-note))))
-    (if (not (equal mh-scan-format-file nil))
-        (list "-form" mh-scan-format-file))))
-
-
-
-;;; Entry points:
-
-;;;###autoload
-(defun mh-rmail (&optional arg)
-  "Incorporate new mail with MH.
-Scan an MH folder if ARG is non-nil.
-
-This function is an entry point to MH-E, the Emacs interface to
-the MH mail system."
-  (interactive "P")
-  (mh-find-path)
-  (if arg
-      (call-interactively 'mh-visit-folder)
-    (unless (get-buffer mh-inbox)
-      (mh-visit-folder mh-inbox (symbol-name mh-unseen-seq)))
-    (mh-inc-folder)))
-
-;;;###autoload
-(defun mh-nmail (&optional arg)
-  "Check for new mail in inbox folder.
-Scan an MH folder if ARG is non-nil.
-
-This function is an entry point to MH-E, the Emacs interface to
-the MH mail system."
-  (interactive "P")
-  (mh-find-path)                        ; init mh-inbox
-  (if arg
-      (call-interactively 'mh-visit-folder)
-    (mh-visit-folder mh-inbox)))
+(defvar mh-show-buffer nil
+  "Buffer that displays message for this folder.")
+
+(defvar mh-showing-mode nil
+  "If non-nil, show the message in a separate window.")
+
+(defvar mh-view-ops nil
+  "Stack of operations that change the folder view.
+These operations include narrowing or threading.")
+
+;; MH-Show Locals (alphabetical)
+
+(defvar mh-globals-hash (make-hash-table)
+  "Keeps track of MIME data on a per buffer basis.")
+
+(defvar mh-show-folder-buffer nil
+  "Keeps track of folder whose message is being displayed.")
+
+;; MH-Letter Locals
+
+(defvar mh-folders-changed nil
+  "Lists which folders were affected by deletes and refiles.
+This list will always include the current folder
+`mh-current-folder'. This variable can be used by
+`mh-after-commands-processed-hook'.")
+
+(defvar mh-mail-header-separator "--------"
+  "*Line used by MH to separate headers from text in messages being composed.
+
+This variable should not be used directly in programs. Programs
+should use `mail-header-separator' instead.
+`mail-header-separator' is initialized to
+`mh-mail-header-separator' in `mh-letter-mode'; in other
+contexts, you may have to perform this initialization yourself.
+
+Do not make this a regular expression as it may be the argument
+to `insert' and it is passed through `regexp-quote' before being
+used by functions like `re-search-forward'.")
+
+(defvar mh-sent-from-folder nil
+  "Folder of msg assoc with this letter.")
+
+(defvar mh-sent-from-msg nil
+  "Number of msg assoc with this letter.")
+
+;; Sequences
+
+(defvar mh-unseen-seq nil
+  "Cached value of the \"Unseen-Sequence:\" MH profile component.
+Name of the Unseen sequence.")
+
+(defvar mh-previous-seq nil
+  "Cached value of the \"Previous-Sequence:\" MH profile component.
+Name of the Previous sequence.")
+
+;; Etc. (alphabetical)
+
+(defvar mh-flists-present-flag nil
+  "Non-nil means that we have \"flists\".")
+
+(defvar mh-index-data-file ".mhe_index"
+  "MH-E specific file where index seach info is stored.")
+
+(defvar mh-letter-header-field-regexp "^\\([A-Za-z][A-Za-z0-9-]*\\):")
+
+(defvar mh-page-to-next-msg-flag nil
+  "Non-nil means next SPC or whatever goes to next undeleted message.")
+
+(defvar mh-pgp-support-flag (not (not (locate-library "mml2015")))
+  "Non-nil means PGP support is available.")
+
+(defvar mh-signature-separator "-- \n"
+  "Text of a signature separator.
+
+A signature separator is used to separate the body of a message
+from the signature. This can be used by user agents such as MH-E
+to render the signature differently or to suppress the inclusion
+of the signature in a reply. Use `mh-signature-separator-regexp'
+when searching for a separator.")
+
+(defvar mh-signature-separator-regexp "^-- $"
+  "This regular expression matches the signature separator.
+See `mh-signature-separator'.")
+
+(defvar mh-thread-scan-line-map nil
+  "Map of message index to various parts of the scan line.")
+(make-variable-buffer-local 'mh-thread-scan-line-map)
+
+(defvar mh-thread-scan-line-map-stack nil
+  "Old map of message index to various parts of the scan line.
+This is the original map that is stored when the folder is
+narrowed.")
+(make-variable-buffer-local 'mh-thread-scan-line-map-stack)
+
+(defvar mh-x-mailer-string nil
+  "*String containing the contents of the X-Mailer header field.
+If nil, this variable is initialized to show the version of MH-E,
+Emacs, and MH the first time a message is composed.")
 
 
 
-;;; User executable MH-E commands:
-
-(defun mh-delete-msg (range)
-  "Delete RANGE\\<mh-folder-mode-map>.
-
-To mark a message for deletion, use this command. A \"D\" is
-placed by the message in the scan window, and the next undeleted
-message is displayed. If the previous command had been
-\\[mh-previous-undeleted-msg], then the next message displayed is
-the first undeleted message previous to the message just deleted.
-Use \\[mh-next-undeleted-msg] to force subsequent
-\\[mh-delete-msg] commands to move forward to the next undeleted
-message after deleting the message under the cursor.
-
-The hook `mh-delete-msg-hook' is called after you mark a message
-for deletion. For example, a past maintainer of MH-E used this
-once when he kept statistics on his mail usage.
-
-Check the documentation of `mh-interactive-range' to see how
-RANGE is read in interactive use."
-  (interactive (list (mh-interactive-range "Delete")))
-  (mh-delete-msg-no-motion range)
-  (if (looking-at mh-scan-deleted-msg-regexp)
-      (mh-next-msg)))
-
-(defun mh-delete-msg-no-motion (range)
-  "Delete RANGE, don't move to next message.
-
-This command marks the RANGE for deletion but leaves the cursor
-at the current message in case you wish to perform other
-operations on the message.
-
-Check the documentation of `mh-interactive-range' to see how
-RANGE is read in interactive use."
-  (interactive (list (mh-interactive-range "Delete")))
-  (mh-iterate-on-range () range
-    (mh-delete-a-msg nil)))
-
-(defun mh-execute-commands ()
-  "Process outstanding delete and refile requests\\<mh-folder-mode-map>.
-
-If you've marked messages to be deleted or refiled and you want
-to go ahead and delete or refile the messages, use this command.
-Many MH-E commands that may affect the numbering of the
-messages (such as \\[mh-rescan-folder] or \\[mh-pack-folder])
-will ask if you want to process refiles or deletes first and then
-either run this command for you or undo the pending refiles and
-deletes, which are lost.
-
-This function runs `mh-before-commands-processed-hook' before the
-commands are processed and `mh-after-commands-processed-hook'
-after the commands are processed."
-  (interactive)
-  (if mh-folder-view-stack (mh-widen t))
-  (mh-process-commands mh-current-folder)
-  (mh-set-scan-mode)
-  (mh-goto-cur-msg)                    ; after mh-set-scan-mode for efficiency
-  (mh-make-folder-mode-line)
-  t)                                    ; return t for write-file-functions
-
-(defun mh-first-msg ()
-  "Display first message."
-  (interactive)
-  (goto-char (point-min))
-  (while (and (not (eobp)) (not (looking-at mh-scan-valid-regexp)))
-    (forward-line 1)))
-
-(defun mh-header-display ()
-  "Display message with all header fields\\<mh-folder-mode-map>.
-
-Use the command \\[mh-show] to show the message normally again."
-  (interactive)
-  (and (not mh-showing-with-headers)
-       (or mh-mhl-format-file mh-clean-message-header-flag)
-       (mh-invalidate-show-buffer))
-  (let ((mh-decode-mime-flag nil)
-        (mh-mhl-format-file nil)
-        (mh-clean-message-header-flag nil))
-    (mh-show-msg nil)
-    (mh-in-show-buffer (mh-show-buffer)
-      (goto-char (point-min))
-      (mh-recenter 0))
-    (setq mh-showing-with-headers t)))
-
-(defun mh-inc-folder (&optional file folder)
-  "Incorporate new mail into a folder.
-
-You can incorporate mail from any file into the current folder by
-specifying a prefix argument; you'll be prompted for the name of
-the FILE to use as well as the destination FOLDER
-
-The hook `mh-inc-folder-hook' is run after incorporating new
-mail.
-
-Do not call this function from outside MH-E; use \\[mh-rmail]
-instead."
-  (interactive (list (if current-prefix-arg
-                         (expand-file-name
-                          (read-file-name "inc mail from file: "
-                                          mh-user-path)))
-                     (if current-prefix-arg
-                         (mh-prompt-for-folder "inc mail into" mh-inbox t))))
-  (if (not folder)
-      (setq folder mh-inbox))
-  (let ((threading-needed-flag nil))
-    (let ((config (current-window-configuration)))
-      (when (and mh-show-buffer (get-buffer mh-show-buffer))
-        (delete-windows-on mh-show-buffer))
-      (cond ((not (get-buffer folder))
-             (mh-make-folder folder)
-             (setq threading-needed-flag mh-show-threads-flag)
-             (setq mh-previous-window-config config))
-            ((not (eq (current-buffer) (get-buffer folder)))
-             (switch-to-buffer folder)
-             (setq mh-previous-window-config config))))
-    (mh-get-new-mail file)
-    (when (and threading-needed-flag
-               (save-excursion
-                 (goto-char (point-min))
-                 (or (null mh-large-folder)
-                     (not (equal (forward-line (1+ mh-large-folder)) 0))
-                     (and (message "Not threading since the number of messages exceeds `mh-large-folder'")
-                          nil))))
-      (mh-toggle-threads))
-    (beginning-of-line)
-    (if (and mh-showing-mode (looking-at mh-scan-valid-regexp)) (mh-show))
-    (run-hooks 'mh-inc-folder-hook)))
-
-(defun mh-last-msg ()
-  "Display last message."
-  (interactive)
-  (goto-char (point-max))
-  (while (and (not (bobp)) (not (looking-at mh-scan-valid-regexp)))
-    (forward-line -1))
-  (mh-recenter nil))
-
-(defun mh-next-undeleted-msg (&optional count wait-after-complaining-flag)
-  "Display next message.
-
-This command can be given a prefix argument COUNT to specify how
-many unread messages to skip.
-
-In a program, pause for a second after printing message if we are
-at the last undeleted message and optional argument
-WAIT-AFTER-COMPLAINING-FLAG is non-nil."
-  (interactive "p")
-  (setq mh-next-direction 'forward)
-  (forward-line 1)
-  (cond ((re-search-forward mh-scan-good-msg-regexp nil t count)
-         (beginning-of-line)
-         (mh-maybe-show))
-        (t (forward-line -1)
-           (message "No more undeleted messages")
-           (if wait-after-complaining-flag (sit-for 1)))))
-
-(defun mh-folder-from-address ()
-  "Derive folder name from sender.
-
-The name of the folder is derived as follows:
-
-  a) The folder name associated with the first address found in
-     the list `mh-default-folder-list' is used. Each element in
-     this list contains a \"Check Recipient\" item. If this item is
-     turned on, then the address is checked against the recipient
-     instead of the sender. This is useful for mailing lists.
-
-  b) An alias prefixed by `mh-default-folder-prefix'
-     corresponding to the address is used. The prefix is used to
-     prevent clutter in your mail directory.
-
-Return nil if a folder name was not derived, or if the variable
-`mh-default-folder-must-exist-flag' is t and the folder does not
-exist."
-  ;; Loop for all entries in mh-default-folder-list
-  (save-restriction
-    (goto-char (point-min))
-    (re-search-forward "\n\n" nil 'limit)
-    (narrow-to-region (point-min) (point))
-    (let ((to/cc (concat (or (message-fetch-field "to") "") ", "
-                         (or (message-fetch-field "cc") "")))
-          (from (or (message-fetch-field "from") ""))
-          folder-name)
-      (setq folder-name
-            (loop for list in mh-default-folder-list
-                  when (string-match (nth 0 list) (if (nth 2 list) to/cc from))
-                  return (nth 1 list)
-                  finally return nil))
-
-      ;; Make sure a result from `mh-default-folder-list' begins with "+"
-      ;; since 'mh-expand-file-name below depends on it
-      (when (and folder-name (not (eq (aref folder-name 0) ?+)))
-        (setq folder-name (concat "+" folder-name)))
-
-      ;; If not, is there an alias for the address?
-      (when (not folder-name)
-        (let* ((from-header (mh-extract-from-header-value))
-               (address (and from-header
-                             (nth 1 (mail-extract-address-components
-                                     from-header))))
-               (alias (and address (mh-alias-address-to-alias address))))
-          (when alias
-            (setq folder-name
-                  (and alias (concat "+" mh-default-folder-prefix alias))))))
-
-      ;; If mh-default-folder-must-exist-flag set, check that folder exists.
-      (if (and folder-name
-               (or (not mh-default-folder-must-exist-flag)
-                   (file-exists-p (mh-expand-file-name folder-name))))
-          folder-name))))
-
-(defun mh-prompt-for-refile-folder ()
-  "Prompt the user for a folder in which the message should be filed.
-The folder is returned as a string.
-
-The default folder name is generated by the option
-`mh-default-folder-for-message-function' if it is non-nil or
-`mh-folder-from-address'."
-  (mh-prompt-for-folder
-   "Destination"
-   (let ((refile-file (ignore-errors (mh-msg-filename (mh-get-msg-num t)))))
-     (if (null refile-file) ""
-       (save-excursion
-         (set-buffer (get-buffer-create mh-temp-buffer))
-         (erase-buffer)
-         (insert-file-contents refile-file)
-         (or (and mh-default-folder-for-message-function
-                  (let ((buffer-file-name refile-file))
-                    (funcall mh-default-folder-for-message-function)))
-             (mh-folder-from-address)
-             (and (eq 'refile (car mh-last-destination-folder))
-                  (symbol-name (cdr mh-last-destination-folder)))
-             ""))))
-   t))
-
-(defun mh-refile-msg (range folder &optional dont-update-last-destination-flag)
-  "Refile (output) RANGE into FOLDER.
-
-You are prompted for the folder name. Note that this command can also
-be used to create folders. If you specify a folder that does not
-exist, you will be prompted to create it.
-
-The hook `mh-refile-msg-hook' is called after a message is marked to
-be refiled.
-
-Check the documentation of `mh-interactive-range' to see how RANGE is
-read in interactive use.
-
-In a program, the variables `mh-last-destination' and
-`mh-last-destination-folder' are not updated if
-DONT-UPDATE-LAST-DESTINATION-FLAG is non-nil."
-  (interactive (list (mh-interactive-range "Refile")
-                     (intern (mh-prompt-for-refile-folder))))
-  (unless dont-update-last-destination-flag
-    (setq mh-last-destination (cons 'refile folder)
-          mh-last-destination-folder mh-last-destination))
-  (mh-iterate-on-range () range
-    (mh-refile-a-msg nil folder))
-  (when (looking-at mh-scan-refiled-msg-regexp) (mh-next-msg)))
-
-(defun mh-refile-or-write-again (range &optional interactive-flag)
-  "Repeat last output command.
-
-If you are refiling several messages into the same folder, you
-can use this command to repeat the last
-refile (\\[mh-refile-msg]) or write (\\[mh-write-msg-to-file]).
-You can use a range.
-
-Check the documentation of `mh-interactive-range' to see how RANGE is
-read in interactive use.
-
-In a program, a non-nil INTERACTIVE-FLAG means that the function was
-called interactively."
-  (interactive (list (mh-interactive-range "Redo") t))
-  (if (null mh-last-destination)
-      (error "No previous refile or write"))
-  (cond ((eq (car mh-last-destination) 'refile)
-         (mh-refile-msg range (cdr mh-last-destination))
-         (message "Destination folder: %s" (cdr mh-last-destination)))
-        (t
-         (mh-iterate-on-range msg range
-           (apply 'mh-write-msg-to-file msg (cdr mh-last-destination)))
-         (mh-next-msg interactive-flag))))
-
-(defun mh-quit ()
-  "Quit the current MH-E folder.
-
-When you want to quit using MH-E and go back to editing, you can use
-this command. This buries the buffers of the current MH-E folder and
-restores the buffers that were present when you first ran
-\\[mh-rmail]. It also removes any MH-E working buffers whose name
-begins with \" *mh-\" or \"*MH-E \". You can later restore your MH-E
-session by selecting the \"+inbox\" buffer or by running \\[mh-rmail]
-again.
-
-The two hooks `mh-before-quit-hook' and `mh-quit-hook' are called by
-this function. The former one is called before the quit occurs, so you
-might use it to perform any MH-E operations; you could perform some
-query and abort the quit or call `mh-execute-commands', for example.
-The latter is not run in an MH-E context, so you might use it to
-modify the window setup."
-  (interactive)
-  (run-hooks 'mh-before-quit-hook)
-  (let ((show-buffer (get-buffer mh-show-buffer)))
-    (when show-buffer
-      (kill-buffer show-buffer)))
-  (mh-update-sequences)
-  (mh-destroy-postponed-handles)
-  (bury-buffer (current-buffer))
-
-  ;; Delete all MH-E temporary and working buffers.
-  (dolist (buffer (buffer-list))
-    (when (or (string-match "^ \\*mh-" (buffer-name buffer))
-              (string-match "^\\*MH-E " (buffer-name buffer)))
-      (kill-buffer buffer)))
-
-  (if mh-previous-window-config
-      (set-window-configuration mh-previous-window-config))
-  (run-hooks 'mh-quit-hook))
-
-(defun mh-page-msg (&optional lines)
-  "Display next page in message.
-
-You can give this command a prefix argument that specifies the
-number of LINES to scroll. This command will also show the next
-undeleted message if it is used at the bottom of a message."
-  (interactive "P")
-  (if mh-showing-mode
-      (if mh-page-to-next-msg-flag
-          (if (equal mh-next-direction 'backward)
-              (mh-previous-undeleted-msg)
-            (mh-next-undeleted-msg))
-        (if (mh-in-show-buffer (mh-show-buffer)
-              (pos-visible-in-window-p (point-max)))
-            (progn
-              (message
-               "End of message (Type %s to read %s undeleted message)"
-               (single-key-description last-input-event)
-               (if (equal mh-next-direction 'backward)
-                   "previous"
-                 "next"))
-              (setq mh-page-to-next-msg-flag t))
-          (scroll-other-window lines)))
-    (mh-show)))
-
-(defun mh-previous-page (&optional lines)
-  "Display next page in message.
-
-You can give this command a prefix argument that specifies the
-number of LINES to scroll."
-  (interactive "P")
-  (mh-in-show-buffer (mh-show-buffer)
-    (scroll-down lines)))
-
-(defun mh-previous-undeleted-msg (&optional count wait-after-complaining-flag)
-  "Display previous message.
-
-This command can be given a prefix argument COUNT to specify how
-many unread messages to skip.
-
-In a program, pause for a second after printing message if we are
-at the last undeleted message and optional argument
-WAIT-AFTER-COMPLAINING-FLAG is non-nil."
-  (interactive "p")
-  (setq mh-next-direction 'backward)
-  (beginning-of-line)
-  (cond ((re-search-backward mh-scan-good-msg-regexp nil t count)
-         (mh-maybe-show))
-        (t (message "No previous undeleted message")
-           (if wait-after-complaining-flag (sit-for 1)))))
-
-(defun mh-previous-unread-msg (&optional count)
-  "Display previous unread message.
-
-This command can be given a prefix argument COUNT to specify how
-many unread messages to skip."
-  (interactive "p")
-  (unless (> count 0)
-    (error "The function `mh-previous-unread-msg' expects positive argument"))
-  (setq count (1- count))
-  (let ((unread-sequence (cdr (assoc mh-unseen-seq mh-seq-list)))
-        (cur-msg (mh-get-msg-num nil)))
-    (cond ((and (not cur-msg) (not (bobp))
-                ;; If we are at the end of the buffer back up one line and go
-                ;; to unread message after that.
-                (progn
-                  (forward-line -1)
-                  (setq cur-msg (mh-get-msg-num nil)))
-                nil))
-          ((or (null unread-sequence) (not cur-msg))
-           ;; No unread message or there aren't any messages in buffer...
-           (message "No more unread messages"))
-          ((progn
-             ;; Skip count messages...
-             (while (and unread-sequence (>= (car unread-sequence) cur-msg))
-               (setq unread-sequence (cdr unread-sequence)))
-             (while (> count 0)
-               (setq unread-sequence (cdr unread-sequence))
-               (setq count (1- count)))
-             (not (car unread-sequence)))
-           (message "No more unread messages"))
-          (t (loop for msg in unread-sequence
-                   when (mh-goto-msg msg t) return nil
-                   finally (message "No more unread messages"))))))
-
-(defun mh-goto-next-button (backward-flag &optional criterion)
-  "Search for next button satisfying criterion.
-
-If BACKWARD-FLAG is non-nil search backward in the buffer for a mime
-button.
-If CRITERION is a function or a symbol which has a function binding
-then that function must return non-nil at the button we stop."
-  (unless (or (and (symbolp criterion) (fboundp criterion))
-              (functionp criterion))
-    (setq criterion (lambda (x) t)))
-  ;; Move to the next button in the buffer satisfying criterion
-  (goto-char (or (save-excursion
-                   (beginning-of-line)
-                   ;; Find point before current button
-                   (let ((point-before-current-button
-                          (save-excursion
-                            (while (get-text-property (point) 'mh-data)
-                              (unless (= (forward-line
-                                          (if backward-flag 1 -1))
-                                         0)
-                                (if backward-flag
-                                    (goto-char (point-min))
-                                  (goto-char (point-max)))))
-                            (point))))
-                     ;; Skip over current button
-                     (while (and (get-text-property (point) 'mh-data)
-                                 (not (if backward-flag (bobp) (eobp))))
-                       (forward-line (if backward-flag -1 1)))
-                     ;; Stop at next MIME button if any exists.
-                     (block loop
-                       (while (/= (progn
-                                    (unless (= (forward-line
-                                                (if backward-flag -1 1))
-                                               0)
-                                      (if backward-flag
-                                          (goto-char (point-max))
-                                        (goto-char (point-min)))
-                                      (beginning-of-line))
-                                    (point))
-                                  point-before-current-button)
-                         (when (and (get-text-property (point) 'mh-data)
-                                    (funcall criterion (point)))
-                           (return-from loop (point))))
-                       nil)))
-                 (point))))
-
-(defun mh-next-button (&optional backward-flag)
-  "Go to the next button.
-
-If the end of the buffer is reached then the search wraps over to
-the start of the buffer.
-
-If an optional prefix argument BACKWARD-FLAG is given, the cursor
-will move to the previous button."
-  (interactive (list current-prefix-arg))
-  (unless mh-showing-mode
-    (mh-show))
-  (mh-in-show-buffer (mh-show-buffer)
-    (mh-goto-next-button backward-flag)))
-
-(defun mh-prev-button ()
-  "Go to the previous button.
-
-If the beginning of the buffer is reached then the search wraps
-over to the end of the buffer."
-  (interactive)
-  (mh-next-button t))
-
-(defun mh-folder-mime-action (part-index action include-security-flag)
-  "Go to PART-INDEX and carry out ACTION.
-
-If PART-INDEX is nil then go to the next part in the buffer. The
-search for the next buffer wraps around if end of buffer is reached.
-If argument INCLUDE-SECURITY-FLAG is non-nil then include security
-info buttons when searching for a suitable parts."
-  (unless mh-showing-mode
-    (mh-show))
-  (mh-in-show-buffer (mh-show-buffer)
-    (let ((criterion
-           (cond (part-index
-                  (lambda (p)
-                    (let ((part (get-text-property p 'mh-part)))
-                      (and (integerp part) (= part part-index)))))
-                 (t (lambda (p)
-                      (if include-security-flag
-                          (get-text-property p 'mh-data)
-                        (integerp (get-text-property p 'mh-part)))))))
-          (point (point)))
-      (cond ((and (get-text-property point 'mh-part)
-                  (or (null part-index)
-                      (= (get-text-property point 'mh-part) part-index)))
-             (funcall action))
-            ((and (get-text-property point 'mh-data)
-                  include-security-flag
-                  (null part-index))
-             (funcall action))
-            (t
-             (mh-goto-next-button nil criterion)
-             (if (= (point) point)
-                 (message "No matching MIME part found")
-               (funcall action)))))))
-
-(defun mh-folder-toggle-mime-part (part-index)
-  "View attachment.
-
-This command displays (or hides) the attachment associated with
-the button under the cursor. If the cursor is not located over a
-button, then the cursor first moves to the next button, wrapping
-to the beginning of the message if necessary. This command has
-the advantage over related commands of working from the MH-Folder
-buffer.
-
-You can also provide a numeric prefix argument PART-INDEX to view
-the attachment labeled with that number. If Emacs does not know
-how to display the attachment, then Emacs offers to save the
-attachment in a file."
-  (interactive "P")
-  (when (consp part-index) (setq part-index (car part-index)))
-  (mh-folder-mime-action part-index #'mh-press-button t))
-
-(defun mh-folder-inline-mime-part (part-index)
-  "Show attachment verbatim.
-
-You can view the raw contents of an attachment with this command.
-This command displays (or hides) the contents of the attachment
-associated with the button under the cursor verbatim. If the
-cursor is not located over a button, then the cursor first moves
-to the next button, wrapping to the beginning of the message if
-necessary.
-
-You can also provide a numeric prefix argument PART-INDEX to view
-the attachment labeled with that number."
-  (interactive "P")
-  (when (consp part-index) (setq part-index (car part-index)))
-  (mh-folder-mime-action part-index #'mh-mime-inline-part nil))
-
-(defun mh-folder-save-mime-part (part-index)
-  "Save (output) attachment.
-
-This command saves the attachment associated with the button under the
-cursor. If the cursor is not located over a button, then the cursor
-first moves to the next button, wrapping to the beginning of the
-message if necessary.
-
-You can also provide a numeric prefix argument PART-INDEX to save the
-attachment labeled with that number.
-
-This command prompts you for a filename and suggests a specific name
-if it is available."
-  (interactive "P")
-  (when (consp part-index) (setq part-index (car part-index)))
-  (mh-folder-mime-action part-index #'mh-mime-save-part nil))
-
-(defun mh-reset-threads-and-narrowing ()
-  "Reset all variables pertaining to threads and narrowing.
-Also removes all content from the folder buffer."
-  (setq mh-view-ops ())
-  (setq mh-folder-view-stack ())
-  (setq mh-thread-scan-line-map-stack ())
-  (let ((buffer-read-only nil)) (erase-buffer)))
-
-(defun mh-rescan-folder (&optional range dont-exec-pending)
-  "Rescan folder\\<mh-folder-mode-map>.
-
-This command is useful to grab all messages in your \"+inbox\" after
-processing your new mail for the first time. If you don't want to
-rescan the entire folder, this command will accept a RANGE. Check the
-documentation of `mh-interactive-range' to see how RANGE is read in
-interactive use.
-
-This command will ask if you want to process refiles or deletes first
-and then either run \\[mh-execute-commands] for you or undo the
-pending refiles and deletes, which are lost.
-
-In a program, the processing of outstanding commands is not performed
-if DONT-EXEC-PENDING is non-nil."
-  (interactive (list (if current-prefix-arg
-                         (mh-read-range "Rescan" mh-current-folder t nil t
-                                        mh-interpret-number-as-range-flag)
-                       nil)))
-  (setq mh-next-direction 'forward)
-  (let ((threaded-flag (memq 'unthread mh-view-ops))
-        (msg-num (mh-get-msg-num nil)))
-    (mh-scan-folder mh-current-folder (or range "all") dont-exec-pending)
-    ;; If there isn't a cur sequence, mh-scan-folder goes to the first message.
-    ;; Try to stay where we were.
-    (if (null (car (mh-seq-to-msgs 'cur)))
-        (mh-goto-msg msg-num t t))
-    (cond (threaded-flag (mh-toggle-threads))
-          (mh-index-data (mh-index-insert-folder-headers)))))
-
-(defun mh-write-msg-to-file (message file no-header)
-  "Append MESSAGE to end of FILE\\<mh-folder-mode-map>.
-
-You are prompted for the filename. If the file already exists,
-the message is appended to it. You can also write the message to
-the file without the header by specifying a prefix argument
-NO-HEADER. Subsequent writes to the same file can be made with
-the command \\[mh-refile-or-write-again]."
-  (interactive
-   (list (mh-get-msg-num t)
-         (let ((default-dir (if (eq 'write (car mh-last-destination-write))
-                                (file-name-directory
-                                 (car (cdr mh-last-destination-write)))
-                              default-directory)))
-           (read-file-name (format "Save message%s in file: "
-                                   (if current-prefix-arg " body" ""))
-                           default-dir
-                           (if (eq 'write (car mh-last-destination-write))
-                               (car (cdr mh-last-destination-write))
-                             (expand-file-name "mail.out" default-dir))))
-         current-prefix-arg))
-  (let ((msg-file-to-output (mh-msg-filename message))
-        (output-file (mh-expand-file-name file)))
-    (setq mh-last-destination (list 'write file (if no-header 'no-header))
-          mh-last-destination-write mh-last-destination)
-    (save-excursion
-      (set-buffer (get-buffer-create mh-temp-buffer))
-      (erase-buffer)
-      (insert-file-contents msg-file-to-output)
-      (goto-char (point-min))
-      (if no-header (search-forward "\n\n"))
-      (append-to-file (point) (point-max) output-file))))
-
-(defun mh-toggle-showing ()
-  "Toggle between MH-Folder and MH-Folder Show modes.
-
-This command switches between MH-Folder mode and MH-Folder Show
-mode. MH-Folder mode turns off the associated show buffer so that
-you can perform operations on the messages quickly without
-reading them. This is an excellent way to prune out your junk
-mail or to refile a group of messages to another folder for later
-examination."
-  (interactive)
-  (if mh-showing-mode
-      (mh-set-scan-mode)
-    (mh-show)))
-
-(defun mh-undo (range)
-  "Undo pending deletes or refiles in RANGE.
-
-If you've deleted a message or refiled it, but changed your mind,
-you can cancel the action before you've executed it. Use this
-command to undo a refile on or deletion of a single message. You
-can also undo refiles and deletes for messages that are found in
-a given RANGE.
-
-Check the documentation of `mh-interactive-range' to see how
-RANGE is read in interactive use."
-  (interactive (list (mh-interactive-range "Undo")))
-  (cond ((numberp range)
-         (let ((original-position (point)))
-           (beginning-of-line)
-           (while (not (or (looking-at mh-scan-deleted-msg-regexp)
-                           (looking-at mh-scan-refiled-msg-regexp)
-                           (and (eq mh-next-direction 'forward) (bobp))
-                           (and (eq mh-next-direction 'backward)
-                                (save-excursion (forward-line) (eobp)))))
-             (forward-line (if (eq mh-next-direction 'forward) -1 1)))
-           (if (or (looking-at mh-scan-deleted-msg-regexp)
-                   (looking-at mh-scan-refiled-msg-regexp))
-               (progn
-                 (mh-undo-msg (mh-get-msg-num t))
-                 (mh-maybe-show))
-             (goto-char original-position)
-             (error "Nothing to undo"))))
-        (t (mh-iterate-on-range () range
-             (mh-undo-msg nil))))
-  (if (not (mh-outstanding-commands-p))
-      (mh-set-folder-modified-p nil)))
-
-(defun mh-folder-line-matches-show-buffer-p ()
-  "Return t if the message under point in folder-mode is in the show buffer.
-Return nil in any other circumstance (no message under point, no
-show buffer, the message in the show buffer doesn't match."
-  (and (eq major-mode 'mh-folder-mode)
-       (mh-get-msg-num nil)
-       mh-show-buffer
-       (get-buffer mh-show-buffer)
-       (buffer-file-name (get-buffer mh-show-buffer))
-       (string-match ".*/\\([0-9]+\\)$"
-                     (buffer-file-name (get-buffer mh-show-buffer)))
-       (string-equal
-        (match-string 1 (buffer-file-name (get-buffer mh-show-buffer)))
-        (int-to-string (mh-get-msg-num nil)))))
+;;; MH-E Entry Points
 
 (eval-when-compile (require 'gnus))
 
@@ -1362,1489 +416,2870 @@
   (goto-char (point-min))
   (display-buffer mh-info-buffer))
 
-(defun mh-parse-flist-output-line (line &optional current-folder)
-  "Parse LINE to generate folder name, unseen messages and total messages.
-If CURRENT-FOLDER is non-nil then it contains the current folder
-name and it is used to avoid problems in corner cases involving
-folders whose names end with a '+' character."
-  (with-temp-buffer
-    (insert line)
-    (goto-char (point-max))
-    (let (folder unseen total p)
-      (when (search-backward " out of " (point-min) t)
-        (setq total (string-to-number
-                     (buffer-substring-no-properties
-                      (match-end 0) (line-end-position))))
-        (when (search-backward " in sequence " (point-min) t)
-          (setq p (point))
-          (when (search-backward " has " (point-min) t)
-            (setq unseen (string-to-number (buffer-substring-no-properties
-                                            (match-end 0) p)))
-            (while (eq (char-after) ? )
-              (backward-char))
-            (setq folder (buffer-substring-no-properties
-                          (point-min) (1+ (point))))
-            (when (and (equal (aref folder (1- (length folder))) ?+)
-                       (equal current-folder folder))
-              (setq folder (substring folder 0 (1- (length folder)))))
-            (values (format "+%s" folder) unseen total)))))))
-
-(defun mh-folder-size-folder (folder)
-  "Find size of FOLDER using \"folder\"."
-  (with-temp-buffer
-    (let ((u (length (cdr (assoc mh-unseen-seq
-                                 (mh-read-folder-sequences folder nil))))))
-      (call-process (expand-file-name "folder" mh-progs) nil t nil
-                    "-norecurse" folder)
-      (goto-char (point-min))
-      (if (re-search-forward " has \\([0-9]+\\) " nil t)
-          (values (string-to-number (match-string 1)) u folder)
-        (values 0 u folder)))))
-
-(defun mh-folder-size-flist (folder)
-  "Find size of FOLDER using \"flist\"."
-  (with-temp-buffer
-    (call-process (expand-file-name "flist" mh-progs) nil t nil "-showzero"
-                  "-norecurse" folder "-sequence" (symbol-name mh-unseen-seq))
-    (goto-char (point-min))
-    (multiple-value-bind (folder unseen total)
-        (mh-parse-flist-output-line
-         (buffer-substring (point) (line-end-position)))
-      (values total unseen folder))))
-
-(defun mh-folder-size (folder)
-  "Find size of FOLDER."
-  (if mh-flists-present-flag
-      (mh-folder-size-flist folder)
-    (mh-folder-size-folder folder)))
-
-(defun mh-visit-folder (folder &optional range index-data)
-  "Visit FOLDER.
-
-When you want to read the messages that you have refiled into folders,
-use this command to visit the folder. You are prompted for the folder
-name.
-
-The folder buffer will show just unseen messages if there are any;
-otherwise, it will show all the messages in the buffer as long there
-are fewer than `mh-large-folder' messages. If there are more, then you
-are prompted for a range of messages to scan.
-
-You can provide a prefix argument in order to specify a RANGE of
-messages to show when you visit the folder. In this case, regions are
-not used to specify the range and `mh-large-folder' is ignored. Check
-the documentation of `mh-interactive-range' to see how RANGE is read
-in interactive use.
-
-Note that this command can also be used to create folders. If you
-specify a folder that does not exist, you will be prompted to create
-it.
-
-Do not call this function from outside MH-E; use \\[mh-rmail] instead.
-
-If, in a program, RANGE is nil (the default), then all messages in
-FOLDER are displayed. If an index buffer is being created then
-INDEX-DATA is used to initialize the index buffer specific data
-structures."
-  (interactive (let ((folder-name (mh-prompt-for-folder "Visit" mh-inbox t)))
-                 (list folder-name
-                       (mh-read-range "Scan" folder-name t nil
-                                      current-prefix-arg
-                                      mh-interpret-number-as-range-flag))))
-  (let ((config (current-window-configuration))
-        (current-buffer (current-buffer))
-        (threaded-view-flag mh-show-threads-flag))
-    (delete-other-windows)
-    (save-excursion
-      (when (get-buffer folder)
-        (set-buffer folder)
-        (setq threaded-view-flag (memq 'unthread mh-view-ops))))
-    (when index-data
-      (mh-make-folder folder)
-      (setq mh-index-data (car index-data)
-            mh-index-msg-checksum-map (make-hash-table :test #'equal)
-            mh-index-checksum-origin-map (make-hash-table :test #'equal))
-      (mh-index-update-maps folder (cadr index-data))
-      (mh-index-create-sequences))
-    (mh-scan-folder folder (or range "all"))
-    (cond ((and threaded-view-flag
-                (save-excursion
-                  (goto-char (point-min))
-                  (or (null mh-large-folder)
-                      (not (equal (forward-line (1+ mh-large-folder)) 0))
-                      (and (message "Not threading since the number of messages exceeds `mh-large-folder'")
-                           nil))))
-           (mh-toggle-threads))
-          (mh-index-data
-           (mh-index-insert-folder-headers)))
-    (unless (eq current-buffer (current-buffer))
-      (setq mh-previous-window-config config)))
-  nil)
-
-(defun mh-update-sequences ()
-  "Flush MH-E's state out to MH.
-
-This function updates the sequence specified by your
-\"Unseen-Sequence:\" profile component, \"cur\", and the sequence
-listed by the `mh-tick-seq' option which is \"tick\" by default.
-The message at the cursor is used for \"cur\"."
-  (interactive)
-  ;; mh-update-sequences is the opposite of mh-read-folder-sequences,
-  ;; which updates MH-E's state from MH.
-  (let ((folder-set (mh-update-unseen))
-        (new-cur (mh-get-msg-num nil)))
-    (if new-cur
-        (let ((seq-entry (mh-find-seq 'cur)))
-          (mh-remove-cur-notation)
-          (setcdr seq-entry
-                  (list new-cur))       ;delete-seq-locally, add-msgs-to-seq
-          (mh-define-sequence 'cur (list new-cur))
-          (beginning-of-line)
-          (if (looking-at mh-scan-good-msg-regexp)
-              (mh-notate-cur)))
-      (or folder-set
-          (save-excursion
-            ;; psg - mh-current-folder is nil if mh-summary-height < 4 !
-            ;;       So I added this sanity check.
-            (if (stringp mh-current-folder)
-                (mh-exec-cmd-quiet t "folder" mh-current-folder "-fast")
-              (mh-exec-cmd-quiet t "folder" "-fast")))))))
+
+
+;;; Support Routines
+
+(defun mh-list-to-string (l)
+  "Flatten the list L and make every element of the new list into a string."
+  (nreverse (mh-list-to-string-1 l)))
+
+(defun mh-list-to-string-1 (l)
+  "Flatten the list L and make every element of the new list into a string."
+  (let ((new-list nil))
+    (while l
+      (cond ((null (car l)))
+            ((symbolp (car l))
+             (setq new-list (cons (symbol-name (car l)) new-list)))
+            ((numberp (car l))
+             (setq new-list (cons (int-to-string (car l)) new-list)))
+            ((equal (car l) ""))
+            ((stringp (car l)) (setq new-list (cons (car l) new-list)))
+            ((listp (car l))
+             (setq new-list (nconc (mh-list-to-string-1 (car l))
+                                   new-list)))
+            (t (error "Bad element in `mh-list-to-string': %s" (car l))))
+      (setq l (cdr l)))
+    new-list))
 
 
 
-;;; Support routines.
-
-(defun mh-delete-a-msg (message)
-  "Delete MESSAGE.
-If MESSAGE is nil then the message at point is deleted.
-The hook `mh-delete-msg-hook' is called after you mark a message
-for deletion. For example, a past maintainer of MH-E used this
-once when he kept statistics on his mail usage."
-  (save-excursion
-    (if (numberp message)
-        (mh-goto-msg message nil t)
-      (beginning-of-line)
-      (setq message (mh-get-msg-num t)))
-    (if (looking-at mh-scan-refiled-msg-regexp)
-        (error "Message %d is refiled; undo refile before deleting" message))
-    (if (looking-at mh-scan-deleted-msg-regexp)
-        nil
-      (mh-set-folder-modified-p t)
-      (setq mh-delete-list (cons message mh-delete-list))
-      (mh-notate nil mh-note-deleted mh-cmd-note)
-      (run-hooks 'mh-delete-msg-hook))))
-
-(defun mh-refile-a-msg (message folder)
-  "Refile MESSAGE in FOLDER.
-If MESSAGE is nil then the message at point is refiled.
-Folder is a symbol, not a string.
-The hook `mh-refile-msg-hook' is called after a message is marked to
-be refiled."
+;;; MH-E Process Support
+
+(defvar mh-index-max-cmdline-args 500
+  "Maximum number of command line args.")
+
+(defun mh-xargs (cmd &rest args)
+  "Partial imitation of xargs.
+The current buffer contains a list of strings, one on each line.
+The function will execute CMD with ARGS and pass the first
+`mh-index-max-cmdline-args' strings to it. This is repeated till
+all the strings have been used."
+  (goto-char (point-min))
+  (let ((current-buffer (current-buffer)))
+    (with-temp-buffer
+      (let ((out (current-buffer)))
+        (set-buffer current-buffer)
+        (while (not (eobp))
+          (let ((arg-list (reverse args))
+                (count 0))
+            (while (and (not (eobp)) (< count mh-index-max-cmdline-args))
+              (push (buffer-substring-no-properties (point) (line-end-position))
+                    arg-list)
+              (incf count)
+              (forward-line))
+            (apply #'call-process cmd nil (list out nil) nil
+                   (nreverse arg-list))))
+        (erase-buffer)
+        (insert-buffer-substring out)))))
+
+;; XXX This should be applied anywhere MH-E calls out to /bin/sh.
+(defun mh-quote-for-shell (string)
+  "Quote STRING for /bin/sh.
+Adds double-quotes around entire string and quotes the characters
+\\, `, and $ with a backslash."
+  (concat "\""
+          (loop for x across string
+                concat (format (if (memq x '(?\\ ?` ?$)) "\\%c" "%c") x))
+          "\""))
+
+(defun mh-exec-cmd (command &rest args)
+  "Execute mh-command COMMAND with ARGS.
+The side effects are what is desired. Any output is assumed to be
+an error and is shown to the user. The output is not read or
+parsed by MH-E."
   (save-excursion
-    (if (numberp message)
-        (mh-goto-msg message nil t)
-      (beginning-of-line)
-      (setq message (mh-get-msg-num t)))
-    (cond ((looking-at mh-scan-deleted-msg-regexp)
-           (error "Message %d is deleted; undo delete before moving" message))
-          ((looking-at mh-scan-refiled-msg-regexp)
-           (if (y-or-n-p
-                (format "Message %d already refiled; copy to %s as well? "
-                        message folder))
-               (mh-exec-cmd "refile" (mh-get-msg-num t) "-link"
-                            "-src" mh-current-folder
-                            (symbol-name folder))
-             (message "Message not copied")))
-          (t
-           (mh-set-folder-modified-p t)
-           (cond ((null (assoc folder mh-refile-list))
-                  (push (list folder message) mh-refile-list))
-                 ((not (member message (cdr (assoc folder mh-refile-list))))
-                  (push message (cdr (assoc folder mh-refile-list)))))
-           (mh-notate nil mh-note-refiled mh-cmd-note)
-           (run-hooks 'mh-refile-msg-hook)))))
-
-(defun mh-next-msg (&optional wait-after-complaining-flag)
-  "Move backward or forward to the next undeleted message in the buffer.
-If optional argument WAIT-AFTER-COMPLAINING-FLAG is non-nil and
-we are at the last message, then wait for a second after telling
-the user that there aren't any more unread messages."
-  (if (eq mh-next-direction 'forward)
-      (mh-next-undeleted-msg 1 wait-after-complaining-flag)
-    (mh-previous-undeleted-msg 1 wait-after-complaining-flag)))
-
-(defun mh-next-unread-msg (&optional count)
-  "Display next unread message.
-
-This command can be given a prefix argument COUNT to specify how
-many unread messages to skip."
-  (interactive "p")
-  (unless (> count 0)
-    (error "The function `mh-next-unread-msg' expects positive argument"))
-  (setq count (1- count))
-  (let ((unread-sequence (reverse (cdr (assoc mh-unseen-seq mh-seq-list))))
-        (cur-msg (mh-get-msg-num nil)))
-    (cond ((and (not cur-msg) (not (bobp))
-                ;; If we are at the end of the buffer back up one line and go
-                ;; to unread message after that.
-                (progn
-                  (forward-line -1)
-                  (setq cur-msg (mh-get-msg-num nil)))
-                nil))
-          ((or (null unread-sequence) (not cur-msg))
-           ;; No unread message or there aren't any messages in buffer...
-           (message "No more unread messages"))
-          ((progn
-             ;; Skip messages
-             (while (and unread-sequence (>= cur-msg (car unread-sequence)))
-               (setq unread-sequence (cdr unread-sequence)))
-             (while (> count 0)
-               (setq unread-sequence (cdr unread-sequence))
-               (setq count (1- count)))
-             (not (car unread-sequence)))
-           (message "No more unread messages"))
-          (t (loop for msg in unread-sequence
-                   when (mh-goto-msg msg t) return nil
-                   finally (message "No more unread messages"))))))
-
-(defun mh-set-scan-mode ()
-  "Display the scan listing buffer, but do not show a message."
-  (if (get-buffer mh-show-buffer)
-      (delete-windows-on mh-show-buffer))
-  (mh-showing-mode 0)
-  (force-mode-line-update)
-  (if mh-recenter-summary-flag
-      (mh-recenter nil)))
-
-(defun mh-undo-msg (msg)
-  "Undo the deletion or refile of one MSG.
-If MSG is nil then act on the message at point"
+    (set-buffer (get-buffer-create mh-log-buffer))
+    (let* ((initial-size (mh-truncate-log-buffer))
+           (start (point))
+           (args (mh-list-to-string args)))
+      (apply 'call-process (expand-file-name command mh-progs) nil t nil args)
+      (when (> (buffer-size) initial-size)
+        (save-excursion
+          (goto-char start)
+          (insert "Errors when executing: " command)
+          (loop for arg in args do (insert " " arg))
+          (insert "\n"))
+        (save-window-excursion
+          (switch-to-buffer-other-window mh-log-buffer)
+          (sit-for 5))))))
+
+(defun mh-exec-cmd-error (env command &rest args)
+  "In environment ENV, execute mh-command COMMAND with ARGS.
+ENV is nil or a string of space-separated \"var=value\" elements.
+Signals an error if process does not complete successfully."
   (save-excursion
-    (if (numberp msg)
-        (mh-goto-msg msg t t)
-      (beginning-of-line)
-      (setq msg (mh-get-msg-num t)))
-    (cond ((memq msg mh-delete-list)
-           (setq mh-delete-list (delq msg mh-delete-list)))
-          (t
-           (dolist (folder-msg-list mh-refile-list)
-             (setf (cdr folder-msg-list) (remove msg (cdr folder-msg-list))))
-           (setq mh-refile-list (loop for x in mh-refile-list
-                                      unless (null (cdr x)) collect x))))
-    (mh-notate nil ?  mh-cmd-note)))
-
-
-
-;;; The folder data abstraction.
-
-(defvar mh-index-data-file ".mhe_index"
-  "MH-E specific file where index seach info is stored.")
-
-(defun mh-make-folder (name)
-  "Create a new mail folder called NAME.
-Make it the current folder."
-  (switch-to-buffer name)
-  (setq buffer-read-only nil)
+    (set-buffer (get-buffer-create mh-temp-buffer))
+    (erase-buffer)
+    (let ((process-environment process-environment))
+      ;; XXX: We should purge the list that split-string returns of empty
+      ;;  strings. This can happen in XEmacs if leading or trailing spaces
+      ;;  are present.
+      (dolist (elem (if (stringp env) (split-string env " ") ()))
+        (push elem process-environment))
+      (mh-handle-process-error
+       command (apply #'call-process (expand-file-name command mh-progs)
+                      nil t nil (mh-list-to-string args))))))
+
+(defun mh-exec-cmd-daemon (command filter &rest args)
+  "Execute MH command COMMAND in the background.
+
+If FILTER is non-nil then it is used to process the output
+otherwise the default filter `mh-process-daemon' is used. See
+`set-process-filter' for more details of FILTER.
+
+ARGS are passed to COMMAND as command line arguments."
+  (save-excursion
+    (set-buffer (get-buffer-create mh-log-buffer))
+    (mh-truncate-log-buffer))
+  (let* ((process-connection-type nil)
+         (process (apply 'start-process
+                         command nil
+                         (expand-file-name command mh-progs)
+                         (mh-list-to-string args))))
+    (set-process-filter process (or filter 'mh-process-daemon))
+    process))
+
+(defun mh-exec-cmd-env-daemon (env command filter &rest args)
+  "In ennvironment ENV, execute mh-command COMMAND in the background.
+
+ENV is nil or a string of space-separated \"var=value\" elements.
+Signals an error if process does not complete successfully.
+
+If FILTER is non-nil then it is used to process the output
+otherwise the default filter `mh-process-daemon' is used. See
+`set-process-filter' for more details of FILTER.
+
+ARGS are passed to COMMAND as command line arguments."
+  (let ((process-environment process-environment))
+    (dolist (elem (if (stringp env) (split-string env " ") ()))
+      (push elem process-environment))
+    (apply #'mh-exec-cmd-daemon command filter args)))
+
+(defun mh-process-daemon (process output)
+  "PROCESS daemon that puts OUTPUT into a temporary buffer.
+Any output from the process is displayed in an asynchronous
+pop-up window."
+  (with-current-buffer (get-buffer-create mh-log-buffer)
+    (insert-before-markers output)
+    (display-buffer mh-log-buffer)))
+
+(defun mh-exec-cmd-quiet (raise-error command &rest args)
+  "Signal RAISE-ERROR if COMMAND with ARGS fails.
+Execute MH command COMMAND with ARGS. ARGS is a list of strings.
+Return at start of mh-temp buffer, where output can be parsed and
+used.
+Returns value of `call-process', which is 0 for success, unless
+RAISE-ERROR is non-nil, in which case an error is signaled if
+`call-process' returns non-0."
+  (set-buffer (get-buffer-create mh-temp-buffer))
   (erase-buffer)
-  (if mh-adaptive-cmd-note-flag
-      (mh-set-cmd-note (mh-msg-num-width-to-column (mh-msg-num-width name))))
-  (setq buffer-read-only t)
-  (mh-folder-mode)
-  (mh-set-folder-modified-p nil)
-  (setq buffer-file-name mh-folder-filename)
-  (when (and (not mh-index-data)
-             (file-exists-p (concat buffer-file-name mh-index-data-file)))
-    (mh-index-read-data))
-  (mh-make-folder-mode-line))
-
-;; Ensure new buffers won't get this mode if default-major-mode is nil.
-(put 'mh-folder-mode 'mode-class 'special)
-
-
-
-;;; Build mh-folder-mode menu
-
-;; Menu extracted from mh-menubar.el V1.1 (31 July 2001)
-;; Menus for folder mode: folder, message, sequence (in that order)
-;; folder-mode "Sequence" menu
-(easy-menu-define
-  mh-folder-sequence-menu mh-folder-mode-map "Menu for MH-E folder-sequence."
-  '("Sequence"
-    ["Add Message to Sequence..."       mh-put-msg-in-seq (mh-get-msg-num nil)]
-    ["List Sequences for Message"       mh-msg-is-in-seq (mh-get-msg-num nil)]
-    ["Delete Message from Sequence..."  mh-delete-msg-from-seq
-     (mh-get-msg-num nil)]
-    ["List Sequences in Folder..."      mh-list-sequences t]
-    ["Delete Sequence..."               mh-delete-seq t]
-    ["Narrow to Sequence..."            mh-narrow-to-seq t]
-    ["Widen from Sequence"              mh-widen mh-folder-view-stack]
-    "--"
-    ["Narrow to Subject Sequence"       mh-narrow-to-subject t]
-    ["Narrow to Tick Sequence"          mh-narrow-to-tick
-     (and mh-tick-seq (mh-seq-msgs (mh-find-seq mh-tick-seq)))]
-    ["Delete Rest of Same Subject"      mh-delete-subject t]
-    ["Toggle Tick Mark"                 mh-toggle-tick t]
-    "--"
-    ["Push State Out to MH"             mh-update-sequences t]))
-
-;; folder-mode "Message" menu
-(easy-menu-define
-  mh-folder-message-menu mh-folder-mode-map "Menu for MH-E folder-message."
-  '("Message"
-    ["Show Message"                     mh-show (mh-get-msg-num nil)]
-    ["Show Message with Header"         mh-header-display (mh-get-msg-num nil)]
-    ["Next Message"                     mh-next-undeleted-msg t]
-    ["Previous Message"                 mh-previous-undeleted-msg t]
-    ["Go to First Message"              mh-first-msg t]
-    ["Go to Last Message"               mh-last-msg t]
-    ["Go to Message by Number..."       mh-goto-msg t]
-    ["Modify Message"                   mh-modify t]
-    ["Delete Message"                   mh-delete-msg (mh-get-msg-num nil)]
-    ["Refile Message"                   mh-refile-msg (mh-get-msg-num nil)]
-    ["Undo Delete/Refile"               mh-undo (mh-outstanding-commands-p)]
-    ["Execute Delete/Refile"            mh-execute-commands
-     (mh-outstanding-commands-p)]
-    "--"
-    ["Compose a New Message"            mh-send t]
-    ["Reply to Message..."              mh-reply (mh-get-msg-num nil)]
-    ["Forward Message..."               mh-forward (mh-get-msg-num nil)]
-    ["Redistribute Message..."          mh-redistribute (mh-get-msg-num nil)]
-    ["Edit Message Again"               mh-edit-again (mh-get-msg-num nil)]
-    ["Re-edit a Bounced Message"        mh-extract-rejected-mail t]
-    "--"
-    ["Copy Message to Folder..."        mh-copy-msg (mh-get-msg-num nil)]
-    ["Print Message"                    mh-print-msg (mh-get-msg-num nil)]
-    ["Write Message to File..."         mh-write-msg-to-file
-     (mh-get-msg-num nil)]
-    ["Pipe Message to Command..."       mh-pipe-msg (mh-get-msg-num nil)]
-    ["Unpack Uuencoded Message..."      mh-store-msg (mh-get-msg-num nil)]
-    ["Burst Digest Message"             mh-burst-digest (mh-get-msg-num nil)]))
-
-;; folder-mode "Folder" menu
-(easy-menu-define
-  mh-folder-folder-menu mh-folder-mode-map  "Menu for MH-E folder."
-  '("Folder"
-    ["Incorporate New Mail"             mh-inc-folder t]
-    ["Toggle Show/Folder"               mh-toggle-showing t]
-    ["Execute Delete/Refile"            mh-execute-commands
-     (mh-outstanding-commands-p)]
-    ["Rescan Folder"                    mh-rescan-folder t]
-    ["Thread Folder"                    mh-toggle-threads
-     (not (memq 'unthread mh-view-ops))]
-    ["Pack Folder"                      mh-pack-folder t]
-    ["Sort Folder"                      mh-sort-folder t]
-    "--"
-    ["List Folders"                     mh-list-folders t]
-    ["Visit a Folder..."                mh-visit-folder t]
-    ["View New Messages"                mh-index-new-messages t]
-    ["Search..."                        mh-search t]
-    "--"
-    ["Quit MH-E"                        mh-quit t]))
-
-
-
-(defmacro mh-remove-xemacs-horizontal-scrollbar ()
-  "Get rid of the horizontal scrollbar that XEmacs insists on putting in."
-  (when mh-xemacs-flag
-    `(if (and (featurep 'scrollbar)
-              (fboundp 'set-specifier))
-         (set-specifier horizontal-scrollbar-visible-p nil
-                        (cons (current-buffer) nil)))))
-
-(defmacro mh-write-file-functions-compat ()
-  "Return `write-file-functions' if it exists.
-Otherwise return `local-write-file-hooks'. This macro exists
-purely for compatibility. The former symbol is used in Emacs 21.4
-onward while the latter is used in previous versions and XEmacs."
-  (if (boundp 'write-file-functions)
-      ''write-file-functions            ;Emacs 21.4
-    ''local-write-file-hooks))          ;XEmacs
-
-;; Register mh-folder-mode as supporting which-function-mode...
-(load "which-func" t t)
-(when (and (boundp 'which-func-modes)
-           (not (member 'mh-folder-mode which-func-modes)))
-  (push 'mh-folder-mode which-func-modes))
+  (let ((value
+         (apply 'call-process
+                (expand-file-name command mh-progs) nil t nil
+                args)))
+    (goto-char (point-min))
+    (if raise-error
+        (mh-handle-process-error command value)
+      value)))
+
+(defun mh-exec-cmd-output (command display &rest args)
+  "Execute MH command COMMAND with DISPLAY flag and ARGS.
+Put the output into buffer after point.
+Set mark after inserted text.
+Output is expected to be shown to user, not parsed by MH-E."
+  (push-mark (point) t)
+  (apply 'call-process
+         (expand-file-name command mh-progs) nil t display
+         (mh-list-to-string args))
+
+  ;; The following is used instead of 'exchange-point-and-mark because the
+  ;; latter activates the current region (between point and mark), which
+  ;; turns on highlighting.  So prior to this bug fix, doing "inc" would
+  ;; highlight a region containing the new messages, which is undesirable.
+  ;; The bug wasn't seen in emacs21 but still occurred in XEmacs21.4.
+  (mh-exchange-point-and-mark-preserving-active-mark))
 
 ;; Shush compiler.
-(eval-when-compile
-  (defvar desktop-save-buffer)
-  (defvar font-lock-auto-fontify))
-
-(defvar mh-folder-buttons-init-flag nil)
-
-;; Autoload cookie needed by desktop.el
-;;;###autoload
-(define-derived-mode mh-folder-mode fundamental-mode "MH-Folder"
-  "Major MH-E mode for \"editing\" an MH folder scan listing.\\<mh-folder-mode-map>
-
-You can show the message the cursor is pointing to, and step through
-the messages. Messages can be marked for deletion or refiling into
-another folder; these commands are executed all at once with a
-separate command.
-
-Options that control this mode can be changed with
-\\[customize-group]; specify the \"mh\" group. In particular, please
-see the `mh-scan-format-file' option if you wish to modify scan's
-format.
-
-When a folder is visited, the hook `mh-folder-mode-hook' is run.
-
-Ranges
-======
-Many commands that operate on individual messages, such as
-`mh-forward' or `mh-refile-msg' take a RANGE argument. This argument
-can be used in several ways.
-
-If you provide the prefix argument (\\[universal-argument]) to
-these commands, then you will be prompted for the message range.
-This can be any valid MH range which can include messages,
-sequences, and the abbreviations (described in the mh(1) man
-page):
-
-<num1>-<num2>
-    Indicates all messages in the range <num1> to <num2>, inclusive.
-    The range must be nonempty.
-
-<num>:N
-<num>:+N
-<num>:-N
-    Up to N messages beginning with (or ending with) message num. Num
-    may be any of the predefined symbols: first, prev, cur, next or
-    last.
-
-first:N
-prev:N
-next:N
-last:N
-    The first, previous, next or last messages, if they exist.
-
-all
-    All of the messages.
-
-For example, a range that shows all of these things is `1 2 3
-5-10 last:5 unseen'.
-
-If the option `transient-mark-mode' is set to t and you set a
-region in the MH-Folder buffer, then the MH-E command will
-perform the operation on all messages in that region.
-
-\\{mh-folder-mode-map}"
-  (mh-do-in-gnu-emacs
-   (unless mh-folder-buttons-init-flag
-     (mh-tool-bar-folder-buttons-init)
-     (setq mh-folder-buttons-init-flag t)))
-  (make-local-variable 'font-lock-defaults)
-  (setq font-lock-defaults '(mh-folder-font-lock-keywords t))
-  (make-local-variable 'desktop-save-buffer)
-  (setq desktop-save-buffer t)
-  (mh-make-local-vars
-   'mh-colors-available-flag (mh-colors-available-p)
-                                        ; Do we have colors available
-   'mh-current-folder (buffer-name)     ; Name of folder, a string
-   'mh-show-buffer (format "show-%s" (buffer-name)) ; Buffer that displays msgs
-   'mh-folder-filename                  ; e.g. "/usr/foobar/Mail/inbox/"
-   (file-name-as-directory (mh-expand-file-name (buffer-name)))
-   'mh-display-buttons-for-inline-parts-flag
-   mh-display-buttons-for-inline-parts-flag ; Allow for display of buttons to
-                                        ; be  toggled.
-   'mh-arrow-marker (make-marker)       ; Marker where arrow is displayed
-   'overlay-arrow-position nil          ; Allow for simultaneous display in
-   'overlay-arrow-string ">"            ;  different MH-E buffers.
-   'mh-showing-mode nil                 ; Show message also?
-   'mh-delete-list nil                  ; List of msgs nums to delete
-   'mh-refile-list nil                  ; List of folder names in mh-seq-list
-   'mh-seq-list nil                     ; Alist of (seq . msgs) nums
-   'mh-seen-list nil                    ; List of displayed messages
-   'mh-next-direction 'forward          ; Direction to move to next message
-   'mh-view-ops ()                      ; Stack that keeps track of the order
-                                        ; in which narrowing/threading has been
-                                        ; carried out.
-   'mh-folder-view-stack ()             ; Stack of previous views of the
-                                        ; folder.
-   'mh-index-data nil                   ; If the folder was created by a call
-                                        ; to mh-search, this contains info
-                                        ; about the search results.
-   'mh-index-previous-search nil        ; folder, indexer, search-regexp
-   'mh-index-msg-checksum-map nil       ; msg -> checksum map
-   'mh-index-checksum-origin-map nil    ; checksum -> ( orig-folder, orig-msg )
-   'mh-index-sequence-search-flag nil   ; folder resulted from sequence search
-   'mh-first-msg-num nil                ; Number of first msg in buffer
-   'mh-last-msg-num nil                 ; Number of last msg in buffer
-   'mh-msg-count nil                    ; Number of msgs in buffer
-   'mh-mode-line-annotation nil         ; Indicates message range
-   'mh-sequence-notation-history (make-hash-table)
-                                        ; Remember what is overwritten by
-                                        ; mh-note-seq.
-   'imenu-create-index-function 'mh-index-create-imenu-index
-                                        ; Setup imenu support
-   'mh-previous-window-config nil)      ; Previous window configuration
-  (mh-remove-xemacs-horizontal-scrollbar)
-  (setq truncate-lines t)
-  (auto-save-mode -1)
-  (setq buffer-offer-save t)
-  (mh-make-local-hook (mh-write-file-functions-compat))
-  (add-hook (mh-write-file-functions-compat) 'mh-execute-commands nil t)
-  (make-local-variable 'revert-buffer-function)
-  (make-local-variable 'hl-line-mode)   ; avoid pollution
-  (mh-funcall-if-exists hl-line-mode 1)
-  (setq revert-buffer-function 'mh-undo-folder)
-  (or (assq 'mh-showing-mode minor-mode-alist)
-      (setq minor-mode-alist
-            (cons '(mh-showing-mode " Show") minor-mode-alist)))
-  (easy-menu-add mh-folder-sequence-menu)
-  (easy-menu-add mh-folder-message-menu)
-  (easy-menu-add mh-folder-folder-menu)
-  (set (make-local-variable 'tool-bar-map) mh-folder-tool-bar-map)
-  (mh-funcall-if-exists mh-tool-bar-init :folder)
-  (if (and mh-xemacs-flag
-           font-lock-auto-fontify)
-      (turn-on-font-lock)))             ; Force font-lock in XEmacs.
-
-(defun mh-toggle-mime-buttons ()
-  "Toggle option `mh-display-buttons-for-inline-parts-flag'."
-  (interactive)
-  (setq mh-display-buttons-for-inline-parts-flag
-        (not mh-display-buttons-for-inline-parts-flag))
-  (mh-show nil t))
-
-(defun mh-colors-available-p ()
-  "Check if colors are available in the Emacs being used."
-  (or mh-xemacs-flag
-      (let ((color-cells (display-color-cells)))
-        (and (numberp color-cells) (>= color-cells 8)))))
-
-(defun mh-colors-in-use-p ()
-  "Check if colors are being used in the folder buffer."
-  (and mh-colors-available-flag font-lock-mode))
-
-(defun mh-make-local-vars (&rest pairs)
-  "Initialize local variables according to the variable-value PAIRS."
-
-  (while pairs
-    (set (make-local-variable (car pairs)) (car (cdr pairs)))
-    (setq pairs (cdr (cdr pairs)))))
-
-(defun mh-restore-desktop-buffer (desktop-buffer-file-name
-                                  desktop-buffer-name
-                                  desktop-buffer-misc)
-  "Restore an MH folder buffer specified in a desktop file.
-When desktop creates a buffer, DESKTOP-BUFFER-FILE-NAME holds the
-file name to visit, DESKTOP-BUFFER-NAME holds the desired buffer
-name, and DESKTOP-BUFFER-MISC holds a list of miscellaneous info
-used by the `desktop-buffer-handlers' functions."
-  (mh-find-path)
-  (mh-visit-folder desktop-buffer-name)
-  (current-buffer))
-
-;; desktop-buffer-mode-handlers appeared in Emacs 22.
-(if (fboundp 'desktop-buffer-mode-handlers)
-    (add-to-list 'desktop-buffer-mode-handlers
-                 '(mh-folder-mode . mh-restore-desktop-buffer)))
-
-(defun mh-scan-folder (folder range &optional dont-exec-pending)
-  "Scan FOLDER over RANGE.
-
-After the scan is performed, switch to the buffer associated with
-FOLDER.
-
-Check the documentation of `mh-interactive-range' to see how RANGE is
-read in interactive use.
-
-The processing of outstanding commands is not performed if
-DONT-EXEC-PENDING is non-nil."
-  (when (stringp range)
-    (setq range (delete "" (split-string range "[ \t\n]"))))
-  (cond ((null (get-buffer folder))
-         (mh-make-folder folder))
-        (t
-         (unless dont-exec-pending
-           (mh-process-or-undo-commands folder)
-           (mh-reset-threads-and-narrowing))
-         (switch-to-buffer folder)))
-  (mh-regenerate-headers range)
-  (if (zerop (buffer-size))
-      (if (equal range "all")
-          (message "Folder %s is empty" folder)
-        (message "No messages in %s, range %s" folder range))
-    (mh-goto-cur-msg))
-  (when (mh-outstanding-commands-p)
-    (mh-notate-deleted-and-refiled)))
-
-(defun mh-msg-num-width-to-column (width)
-  "Return the column for notations given message number WIDTH.
-Note that columns in Emacs start with 0.
-
-If `mh-scan-format-file' is set to \"Use MH-E scan Format\" this
-means that either `mh-scan-format-mh' or `mh-scan-format-nmh' are
-in use. This function therefore assumes that the first column is
-empty (to provide room for the cursor), the following WIDTH
-columns contain the message number, and the column for notations
-comes after that."
-  (if (eq mh-scan-format-file t)
-      (max (1+ width) 2)
-    (error "%s %s" "Can't call `mh-msg-num-width-to-column' when"
-           "`mh-scan-format-file' is not set to \"Use MH-E scan Format\"")))
-
-(defun mh-set-cmd-note (column)
-  "Set `mh-cmd-note' to COLUMN.
-Note that columns in Emacs start with 0."
-  (setq mh-cmd-note column))
-
-(defun mh-regenerate-headers (range &optional update)
-  "Scan folder over RANGE.
-If UPDATE, append the scan lines, otherwise replace."
-  (let ((folder mh-current-folder)
-        (range (if (and range (atom range)) (list range) range))
-        scan-start)
-    (message "Scanning %s..." folder)
-    (mh-remove-all-notation)
-    (with-mh-folder-updating (nil)
-      (if update
-          (goto-char (point-max))
-        (delete-region (point-min) (point-max))
-        (if mh-adaptive-cmd-note-flag
-            (mh-set-cmd-note (mh-msg-num-width-to-column (mh-msg-num-width
-                                                          folder)))))
-      (setq scan-start (point))
-      (apply #'mh-exec-cmd-output
-             mh-scan-prog nil
-             (mh-scan-format)
-             "-noclear" "-noheader"
-             "-width" (window-width)
-             folder range)
-      (goto-char scan-start)
-      (cond ((looking-at "scan: no messages in")
-             (keep-lines mh-scan-valid-regexp)) ; Flush random scan lines
-            ((looking-at (if (mh-variant-p 'mu-mh)
-                             "scan: message set .* does not exist"
-                           "scan: bad message list "))
-             (keep-lines mh-scan-valid-regexp))
-            ((looking-at "scan: "))     ; Keep error messages
-            (t
-             (keep-lines mh-scan-valid-regexp))) ; Flush random scan lines
-      (setq mh-seq-list (mh-read-folder-sequences folder nil))
-      (mh-notate-user-sequences)
-      (or update
-          (setq mh-mode-line-annotation
-                (if (equal range '("all"))
-                    nil
-                  mh-partial-folder-mode-line-annotation)))
-      (mh-make-folder-mode-line))
-    (message "Scanning %s...done" folder)))
-
-(defun mh-generate-new-cmd-note (folder)
-  "Fix the `mh-cmd-note' value for this FOLDER.
-
-After doing an `mh-get-new-mail' operation in this FOLDER, at least
-one line that looks like a truncated message number was found.
-
-Remove the text added by the last `mh-inc' command. It should be the
-messages cur-last. Call `mh-set-cmd-note', adjusting the notation
-column with the width of the largest message number in FOLDER.
-
-Reformat the message number width on each line in the buffer and trim
-the line length to fit in the window.
-
-Rescan the FOLDER in the range cur-last in order to display the
-messages that were removed earlier. They should all fit in the scan
-line now with no message truncation."
+(eval-when-compile (mh-do-in-xemacs (defvar mark-active)))
+
+(defun mh-exchange-point-and-mark-preserving-active-mark ()
+  "Put the mark where point is now, and point where the mark is now.
+This command works even when the mark is not active, and
+preserves whether the mark is active or not."
+  (interactive nil)
+  (let ((is-active (and (boundp 'mark-active) mark-active)))
+    (let ((omark (mark t)))
+      (if (null omark)
+          (error "No mark set in this buffer"))
+      (set-mark (point))
+      (goto-char omark)
+      (if (boundp 'mark-active)
+          (setq mark-active is-active))
+      nil)))
+
+(defun mh-exec-lib-cmd-output (command &rest args)
+  "Execute MH library command COMMAND with ARGS.
+Put the output into buffer after point.
+Set mark after inserted text."
+  (apply 'mh-exec-cmd-output (expand-file-name command mh-lib-progs) nil args))
+
+(defun mh-handle-process-error (command status)
+  "Raise error if COMMAND returned non-zero STATUS, otherwise return STATUS."
+  (if (equal status 0)
+      status
+    (goto-char (point-min))
+    (insert (if (integerp status)
+                (format "%s: exit code %d\n" command status)
+              (format "%s: %s\n" command status)))
+    (save-excursion
+      (let ((error-message (buffer-substring (point-min) (point-max))))
+        (set-buffer (get-buffer-create mh-log-buffer))
+        (mh-truncate-log-buffer)
+        (insert error-message)))
+    (error "%s failed, check buffer %s for error message"
+           command mh-log-buffer)))
+
+
+
+;;; Variant Support
+
+(defcustom mh-path nil
+  "*Additional list of directories to search for MH.
+See `mh-variant'."
+  :group 'mh-e
+  :type '(repeat (directory)))
+
+(defun mh-variants ()
+  "Return a list of installed variants of MH on the system.
+This function looks for MH in `mh-sys-path', `mh-path' and
+`exec-path'. The format of the list of variants that is returned
+is described by the variable `mh-variants'."
+  (if mh-variants
+      mh-variants
+    (let ((list-unique))
+      ;; Make a unique list of directories, keeping the given order.
+      ;; We don't want the same MH variant to be listed multiple times.
+      (loop for dir in (append mh-path mh-sys-path exec-path) do
+            (setq dir (file-chase-links (directory-file-name dir)))
+            (add-to-list 'list-unique dir))
+      (loop for dir in (nreverse list-unique) do
+            (when (and dir (file-directory-p dir) (file-readable-p dir))
+              (let ((variant (mh-variant-info dir)))
+                (if variant
+                    (add-to-list 'mh-variants variant)))))
+      mh-variants)))
+
+(defun mh-variant-info (dir)
+  "Return MH variant found in DIR, or nil if none present."
   (save-excursion
-    (let ((maxcol (1- (window-width)))
-          (old-cmd-note mh-cmd-note)
-          mh-cmd-note-fmt
-          msgnum)
-      ;; Nuke all of the lines just added by the last inc
-      (delete-char (- (point-max) (point)))
-      ;; Update the current buffer to reflect the new mh-cmd-note
-      ;; value needed to display messages.
-      (mh-set-cmd-note (mh-msg-num-width-to-column (mh-msg-num-width folder)))
-      (setq mh-cmd-note-fmt (concat "%" (format "%d" mh-cmd-note) "d"))
-      ;; Cleanup the messages that are in the buffer right now
+    (let ((tmp-buffer (get-buffer-create mh-temp-buffer)))
+      (set-buffer tmp-buffer)
+      (cond
+       ((mh-variant-mh-info dir))
+       ((mh-variant-nmh-info dir))
+       ((mh-variant-mu-mh-info dir))))))
+
+(defun mh-variant-mh-info (dir)
+  "Return info for MH variant in DIR assuming a temporary buffer is setup."
+  ;; MH does not have the -version option.
+  ;; Its version number is included in the output of "-help" as:
+  ;;
+  ;; version: MH 6.8.4 #2[UCI] (burrito) of Fri Jan 15 20:01:39 EST 1999
+  ;; options: [ATHENA] [BIND] [DUMB] [LIBLOCKFILE] [LOCALE] [MAILGROUP] [MHE]
+  ;;          [MHRC] [MIME] [MORE='"/usr/bin/sensible-pager"'] [NLINK_HACK]
+  ;;          [NORUSERPASS] [OVERHEAD] [POP] [POPSERVICE='"pop-3"'] [RENAME]
+  ;;          [RFC1342] [RPATHS] [RPOP] [SENDMTS] [SMTP] [SOCKETS]
+  ;;          [SPRINTFTYPE=int] [SVR4] [SYS5] [SYS5DIR] [TERMINFO]
+  ;;          [TYPESIG=void] [UNISTD] [UTK] [VSPRINTF]
+  (let ((mhparam (expand-file-name "mhparam" dir)))
+    (when (mh-file-command-p mhparam)
+      (erase-buffer)
+      (call-process mhparam nil '(t nil) nil "-help")
+      (goto-char (point-min))
+      (when (search-forward-regexp "version: MH \\(\\S +\\)" nil t)
+        (let ((version (format "MH %s" (match-string 1))))
+          (erase-buffer)
+          (call-process mhparam nil '(t nil) nil "libdir")
+          (goto-char (point-min))
+          (when (search-forward-regexp "^.*$" nil t)
+            (let ((libdir (match-string 0)))
+              `(,version
+                (variant        mh)
+                (mh-lib-progs   ,libdir)
+                (mh-lib         ,libdir)
+                (mh-progs       ,dir)
+                (flists         nil)))))))))
+
+(defun mh-variant-mu-mh-info (dir)
+  "Return info for GNU mailutils variant in DIR.
+This assumes that a temporary buffer is setup."
+  ;; 'mhparam -version' output:
+  ;; mhparam (GNU mailutils 0.3.2)
+  (let ((mhparam (expand-file-name "mhparam" dir)))
+    (when (mh-file-command-p mhparam)
+      (erase-buffer)
+      (call-process mhparam nil '(t nil) nil "-version")
+      (goto-char (point-min))
+      (when (search-forward-regexp "mhparam (\\(GNU [Mm]ailutils \\S +\\))"
+                                   nil t)
+        (let ((version (match-string 1))
+              (mh-progs dir))
+          `(,version
+            (variant        mu-mh)
+            (mh-lib-progs   ,(mh-profile-component "libdir"))
+            (mh-lib         ,(mh-profile-component "etcdir"))
+            (mh-progs       ,dir)
+            (flists         ,(file-exists-p
+                              (expand-file-name "flists" dir)))))))))
+
+(defun mh-variant-nmh-info (dir)
+  "Return info for nmh variant in DIR assuming a temporary buffer is setup."
+  ;; `mhparam -version' outputs:
+  ;; mhparam -- nmh-1.1-RC1 [compiled on chaak at Fri Jun 20 11:03:28 PDT 2003]
+  (let ((mhparam (expand-file-name "mhparam" dir)))
+    (when (mh-file-command-p mhparam)
+      (erase-buffer)
+      (call-process mhparam nil '(t nil) nil "-version")
       (goto-char (point-min))
-      (cond ((memq 'unthread mh-view-ops)
-             (mh-thread-add-spaces (- mh-cmd-note old-cmd-note)))
-            (t (while (re-search-forward mh-scan-msg-number-regexp nil 0 1)
-                 ;; reformat the number to fix in mh-cmd-note columns
-                 (setq msgnum (string-to-number
-                               (buffer-substring
-                                (match-beginning 1) (match-end 1))))
-                 (replace-match (format mh-cmd-note-fmt msgnum))
-                 ;; trim the line to fix in the window
-                 (end-of-line)
-                 (let ((eol (point)))
-                   (move-to-column maxcol)
-                   (if (<= (point) eol)
-                       (delete-char (- eol (point))))))))
-      ;; now re-read the lost messages
-      (goto-char (point-max))
-      (prog1 (point)
-        (mh-regenerate-headers "cur-last" t)))))
-
-(defun mh-get-new-mail (maildrop-name)
-  "Read new mail from MAILDROP-NAME into the current buffer.
-Return in the current buffer."
-  (let ((point-before-inc (point))
-        (folder mh-current-folder)
-        (new-mail-flag nil))
-    (with-mh-folder-updating (t)
-      (if maildrop-name
-          (message "inc %s -file %s..." folder maildrop-name)
-        (message "inc %s..." folder))
-      (setq mh-next-direction 'forward)
-      (goto-char (point-max))
-      (mh-remove-cur-notation)
-      (let ((start-of-inc (point)))
-        (if maildrop-name
-            ;; I think MH 5 used "-ms-file" instead of "-file",
-            ;; which would make inc'ing from maildrops fail.
-            (mh-exec-cmd-output mh-inc-prog nil folder
-                                (mh-scan-format)
-                                "-file" (expand-file-name maildrop-name)
-                                "-width" (window-width)
-                                "-truncate")
-          (mh-exec-cmd-output mh-inc-prog nil
-                              (mh-scan-format)
-                              "-width" (window-width)))
-        (if maildrop-name
-            (message "inc %s -file %s...done" folder maildrop-name)
-          (message "inc %s...done" folder))
-        (goto-char start-of-inc)
-        (cond ((save-excursion
-                 (re-search-forward "^inc: no mail" nil t))
-               (message "No new mail%s%s" (if maildrop-name " in " "")
-                        (if maildrop-name maildrop-name "")))
-              ((and (when mh-folder-view-stack
-                      (let ((saved-text (buffer-substring-no-properties
-                                         start-of-inc (point-max))))
-                        (delete-region start-of-inc (point-max))
-                        (unwind-protect (mh-widen t)
-                          (mh-remove-cur-notation)
-                          (goto-char (point-max))
-                          (setq start-of-inc (point))
-                          (insert saved-text)
-                          (goto-char start-of-inc))))
-                    nil))
-              ((re-search-forward "^inc:" nil t) ; Error messages
-               (error "Error incorporating mail"))
-              ((and
-                (equal mh-scan-format-file t)
-                mh-adaptive-cmd-note-flag
-                ;; Have we reached an edge condition?
-                (save-excursion
-                  (re-search-forward mh-scan-msg-overflow-regexp nil 0 1))
-                (setq start-of-inc (mh-generate-new-cmd-note folder))
-                nil))
-              (t
-               (setq new-mail-flag t)))
-        (keep-lines mh-scan-valid-regexp) ; Flush random scan lines
-        (let* ((sequences (mh-read-folder-sequences folder t))
-               (new-cur (assoc 'cur sequences))
-               (new-unseen (assoc mh-unseen-seq sequences)))
-          (unless (assoc 'cur mh-seq-list)
-            (push (list 'cur) mh-seq-list))
-          (unless (assoc mh-unseen-seq mh-seq-list)
-            (push (list mh-unseen-seq) mh-seq-list))
-          (setcdr (assoc 'cur mh-seq-list) (cdr new-cur))
-          (setcdr (assoc mh-unseen-seq mh-seq-list) (cdr new-unseen)))
-        (when (equal (point-max) start-of-inc)
-          (mh-notate-cur))
-        (if new-mail-flag
-            (progn
-              (mh-make-folder-mode-line)
-              (when (mh-speed-flists-active-p)
-                (mh-speed-flists t mh-current-folder))
-              (when (memq 'unthread mh-view-ops)
-                (mh-thread-inc folder start-of-inc))
-              (mh-goto-cur-msg))
-          (goto-char point-before-inc))
-        (mh-notate-user-sequences (cons start-of-inc (point-max)))))))
-
-(defun mh-make-folder-mode-line (&optional ignored)
-  "Set the fields of the mode line for a folder buffer.
-The optional argument is now obsolete and IGNORED. It used to be
-used to pass in what is now stored in the buffer-local variable
-`mh-mode-line-annotation'."
+      (when (search-forward-regexp "mhparam -- nmh-\\(\\S +\\)" nil t)
+        (let ((version (format "nmh %s" (match-string 1)))
+              (mh-progs dir))
+          `(,version
+            (variant        nmh)
+            (mh-lib-progs   ,(mh-profile-component "libdir"))
+            (mh-lib         ,(mh-profile-component "etcdir"))
+            (mh-progs       ,dir)
+            (flists         ,(file-exists-p
+                              (expand-file-name "flists" dir)))))))))
+
+(defun mh-file-command-p (file)
+  "Return t if file FILE is the name of a executable regular file."
+  (and (file-regular-p file) (file-executable-p file)))
+
+(defun mh-variant-set-variant (variant)
+  "Setup the system variables for the MH variant named VARIANT.
+If VARIANT is a string, use that key in the alist returned by the
+function `mh-variants'.
+If VARIANT is a symbol, select the first entry that matches that
+variant."
+  (cond
+   ((stringp variant)                   ;e.g. "nmh 1.1-RC1"
+    (when (assoc variant (mh-variants))
+      (let* ((alist (cdr (assoc variant (mh-variants))))
+             (lib-progs (cadr (assoc 'mh-lib-progs alist)))
+             (lib       (cadr (assoc 'mh-lib       alist)))
+             (progs     (cadr (assoc 'mh-progs     alist)))
+             (flists    (cadr (assoc 'flists       alist))))
+        ;;(set-default mh-variant variant)
+        (setq mh-x-mailer-string     nil
+              mh-flists-present-flag flists
+              mh-lib-progs           lib-progs
+              mh-lib                 lib
+              mh-progs               progs
+              mh-variant-in-use      variant))))
+   ((symbolp variant)                   ;e.g. 'nmh (pick the first match)
+    (loop for variant-list in (mh-variants)
+          when (eq variant (cadr (assoc 'variant (cdr variant-list))))
+          return (let* ((version   (car variant-list))
+                        (alist (cdr variant-list))
+                        (lib-progs (cadr (assoc 'mh-lib-progs alist)))
+                        (lib       (cadr (assoc 'mh-lib       alist)))
+                        (progs     (cadr (assoc 'mh-progs     alist)))
+                        (flists    (cadr (assoc 'flists       alist))))
+                   ;;(set-default mh-variant flavor)
+                   (setq mh-x-mailer-string     nil
+                         mh-flists-present-flag flists
+                         mh-lib-progs           lib-progs
+                         mh-lib                 lib
+                         mh-progs               progs
+                         mh-variant-in-use      version)
+                   t)))))
+
+(defun mh-variant-p (&rest variants)
+  "Return t if variant is any of VARIANTS.
+Currently known variants are 'MH, 'nmh, and 'mu-mh."
+  (let ((variant-in-use
+         (cadr (assoc 'variant (assoc mh-variant-in-use (mh-variants))))))
+    (not (null (member variant-in-use variants)))))
+
+(defun mh-profile-component (component)
+  "Return COMPONENT value from mhparam, or nil if unset."
   (save-excursion
-    (save-window-excursion
-      (mh-first-msg)
-      (let ((new-first-msg-num (mh-get-msg-num nil)))
-        (when (or (not (memq 'unthread mh-view-ops))
-                  (null mh-first-msg-num)
-                  (null new-first-msg-num)
-                  (< new-first-msg-num mh-first-msg-num))
-          (setq mh-first-msg-num new-first-msg-num)))
-      (mh-last-msg)
-      (let ((new-last-msg-num (mh-get-msg-num nil)))
-        (when (or (not (memq 'unthread mh-view-ops))
-                  (null mh-last-msg-num)
-                  (null new-last-msg-num)
-                  (> new-last-msg-num mh-last-msg-num))
-          (setq mh-last-msg-num new-last-msg-num)))
-      (setq mh-msg-count (if mh-first-msg-num
-                             (count-lines (point-min) (point-max))
-                           0))
-      (setq mode-line-buffer-identification
-            (list (format "    {%%b%s} %s msg%s"
-                          (if mh-mode-line-annotation
-                              (format "/%s" mh-mode-line-annotation)
-                            "")
-                          (if (zerop mh-msg-count)
-                              "no"
-                            (format "%d" mh-msg-count))
-                          (if (zerop mh-msg-count)
-                              "s"
-                            (cond ((> mh-msg-count 1)
-                                   (format "s (%d-%d)" mh-first-msg-num
-                                           mh-last-msg-num))
-                                  (mh-first-msg-num
-                                   (format " (%d)" mh-first-msg-num))
-                                  (""))))))
-      (mh-logo-display))))
-
-(defun mh-add-sequence-notation (msg internal-seq-flag)
-  "Add sequence notation to the MSG on the current line.
-If INTERNAL-SEQ-FLAG is non-nil, then refontify the scan line if
-font-lock is turned on."
-  (with-mh-folder-updating (t)
-    (save-excursion
-      (beginning-of-line)
-      (if internal-seq-flag
-          (progn
-            ;; Change the buffer so that if transient-mark-mode is active
-            ;; and there is an active region it will get deactivated as in
-            ;; the case of user sequences.
-            (mh-notate nil nil mh-cmd-note)
-            (when font-lock-mode
-              (font-lock-fontify-region (point) (line-end-position))))
-        (forward-char (+ mh-cmd-note mh-scan-field-destination-offset))
-        (let ((stack (gethash msg mh-sequence-notation-history)))
-          (setf (gethash msg mh-sequence-notation-history)
-                (cons (char-after) stack)))
-        (mh-notate nil mh-note-seq
-                   (+ mh-cmd-note mh-scan-field-destination-offset))))))
-
-(defun mh-remove-sequence-notation (msg internal-seq-flag &optional all)
-  "Remove sequence notation from the MSG on the current line.
-If INTERNAL-SEQ-FLAG is non-nil, then `font-lock' was used to
-highlight the sequence. In that case, no notation needs to be removed.
-Otherwise the effect of inserting `mh-note-seq' needs to be reversed.
-If ALL is non-nil, then all sequence marks on the scan line are
-removed."
-  (with-mh-folder-updating (t)
-    ;; This takes care of internal sequences...
-    (mh-notate nil nil mh-cmd-note)
-    (unless internal-seq-flag
-      ;; ... and this takes care of user sequences.
-      (let ((stack (gethash msg mh-sequence-notation-history)))
-        (while (and all (cdr stack))
-          (setq stack (cdr stack)))
-        (when stack
-          (save-excursion
-            (beginning-of-line)
-            (forward-char (+ mh-cmd-note mh-scan-field-destination-offset))
-            (delete-char 1)
-            (insert (car stack))))
-        (setf (gethash msg mh-sequence-notation-history) (cdr stack))))))
-
-(defun mh-remove-cur-notation ()
-  "Remove old cur notation."
-  (let ((cur-msg (car (mh-seq-to-msgs 'cur))))
-    (save-excursion
-      (when (and cur-msg
-                 (mh-goto-msg cur-msg t t)
-                 (looking-at mh-scan-cur-msg-number-regexp))
-        (mh-notate nil ?  mh-cmd-note)
-        (setq overlay-arrow-position nil)))))
-
-(defun mh-remove-all-notation ()
-  "Remove all notations on all scan lines that MH-E introduces."
-  (save-excursion
-    (setq overlay-arrow-position nil)
+    (mh-exec-cmd-quiet nil "mhparam" "-components" component)
+    (mh-profile-component-value component)))
+
+(defun mh-profile-component-value (component)
+  "Find and return the value of COMPONENT in the current buffer.
+Returns nil if the component is not in the buffer."
+  (let ((case-fold-search t))
     (goto-char (point-min))
-    (mh-iterate-on-range msg (cons (point-min) (point-max))
-      (mh-notate nil ?  mh-cmd-note)
-      (mh-remove-sequence-notation msg nil t))
-    (clrhash mh-sequence-notation-history)))
-
-(defun mh-goto-cur-msg (&optional minimal-changes-flag)
-  "Position the cursor at the current message.
-When optional argument MINIMAL-CHANGES-FLAG is non-nil, the
-function doesn't recenter the folder buffer."
-  (let ((cur-msg (car (mh-seq-to-msgs 'cur))))
-    (cond ((and cur-msg
-                (mh-goto-msg cur-msg t t))
-           (unless minimal-changes-flag
-             (mh-notate-cur)
-             (mh-recenter 0)
-             (mh-maybe-show cur-msg)))
+    (cond ((not (re-search-forward (format "^%s:" component) nil t)) nil)
+          ((looking-at "[\t ]*$") nil)
           (t
-           (setq overlay-arrow-position nil)
-           (message "No current message")))))
-
-(defun mh-process-or-undo-commands (folder)
-  "If FOLDER has outstanding commands, then either process or discard them.
-Called by functions like `mh-sort-folder', so also invalidate
-show buffer."
-  (set-buffer folder)
-  (if (mh-outstanding-commands-p)
-      (if (or mh-do-not-confirm-flag
-              (y-or-n-p
-               "Process outstanding deletes and refiles? "))
-          (mh-process-commands folder)
-        (set-buffer folder)
-        (mh-undo-folder)))
-  (mh-update-unseen)
-  (mh-invalidate-show-buffer))
-
-(defun mh-process-commands (folder)
-  "Process outstanding commands for FOLDER.
-
-This function runs `mh-before-commands-processed-hook' before the
-commands are processed and `mh-after-commands-processed-hook'
-after the commands are processed."
-  (message "Processing deletes and refiles for %s..." folder)
-  (set-buffer folder)
-  (with-mh-folder-updating (nil)
-    ;; Run the before hook -- the refile and delete lists are still valid
-    (run-hooks 'mh-before-commands-processed-hook)
-
-    ;; Update the unseen sequence if it exists
-    (mh-update-unseen)
-
-    (let ((redraw-needed-flag mh-index-data)
-          (folders-changed (list mh-current-folder))
-          (seq-map (and mh-refile-list mh-refile-preserves-sequences-flag
-                        (mh-create-sequence-map mh-seq-list)))
-          (dest-map (and mh-refile-list mh-refile-preserves-sequences-flag
-                         (make-hash-table))))
-      ;; Remove invalid scan lines if we are in an index folder and then remove
-      ;; the real messages
-      (when mh-index-data
-        (mh-index-delete-folder-headers)
-        (setq folders-changed
-              (append folders-changed (mh-index-execute-commands))))
-
-      ;; Then refile messages
-      (mh-mapc #'(lambda (folder-msg-list)
-                   (let* ((dest-folder (symbol-name (car folder-msg-list)))
-                          (last (car (mh-translate-range dest-folder "last")))
-                          (msgs (cdr folder-msg-list)))
-                     (push dest-folder folders-changed)
-                     (setq redraw-needed-flag t)
-                     (apply #'mh-exec-cmd
-                            "refile" "-src" folder dest-folder
-                            (mh-coalesce-msg-list msgs))
-                     (mh-delete-scan-msgs msgs)
-                     ;; Preserve sequences in destination folder...
-                     (when mh-refile-preserves-sequences-flag
-                       (clrhash dest-map)
-                       (loop for i from (1+ (or last 0))
-                             for msg in (sort (copy-sequence msgs) #'<)
-                             do (loop for seq-name in (gethash msg seq-map)
-                                      do (push i (gethash seq-name dest-map))))
-                       (maphash
-                        #'(lambda (seq msgs)
-                            ;; Can't be run in the background, since the
-                            ;; current folder is changed by mark this could
-                            ;; lead to a race condition with the next refile.
-                            (apply #'mh-exec-cmd "mark"
-                                   "-sequence" (symbol-name seq) dest-folder
-                                   "-add" (mapcar #'(lambda (x) (format "%s" x))
-                                                  (mh-coalesce-msg-list msgs))))
-                        dest-map))))
-               mh-refile-list)
-      (setq mh-refile-list ())
-
-      ;; Now delete messages
-      (cond (mh-delete-list
-             (setq redraw-needed-flag t)
-             (apply 'mh-exec-cmd "rmm" folder
-                    (mh-coalesce-msg-list mh-delete-list))
-             (mh-delete-scan-msgs mh-delete-list)
-             (setq mh-delete-list nil)))
-
-      ;; Don't need to remove sequences since delete and refile do so.
-      ;; Mark cur message
-      (if (> (buffer-size) 0)
-          (mh-define-sequence 'cur (list (or (mh-get-msg-num nil) "last"))))
-
-      ;; Redraw folder buffer if needed
-      (when (and redraw-needed-flag)
-        (when (mh-speed-flists-active-p)
-          (apply #'mh-speed-flists t folders-changed))
-        (cond ((memq 'unthread mh-view-ops) (mh-thread-inc folder (point-max)))
-              (mh-index-data (mh-index-insert-folder-headers))))
-
-      (and (buffer-file-name (get-buffer mh-show-buffer))
-           (not (file-exists-p (buffer-file-name (get-buffer mh-show-buffer))))
-           ;; If "inc" were to put a new msg in this file,
-           ;; we would not notice, so mark it invalid now.
-           (mh-invalidate-show-buffer))
-
-      (setq mh-seq-list (mh-read-folder-sequences mh-current-folder nil))
-      (mh-remove-all-notation)
-      (mh-notate-user-sequences)
-
-      ;; Run the after hook -- now folders-changed is valid,
-      ;; but not the lists of specific messages.
-      (let ((mh-folders-changed folders-changed))
-        (run-hooks 'mh-after-commands-processed-hook)))
-
-    (message "Processing deletes and refiles for %s...done" folder)))
-
-(defun mh-update-unseen ()
-  "Synchronize the unseen sequence with MH.
-Return non-nil iff the MH folder was set.
-The hook `mh-unseen-updated-hook' is called after the unseen sequence
-is updated."
-  (if mh-seen-list
-      (let* ((unseen-seq (mh-find-seq mh-unseen-seq))
-             (unseen-msgs (mh-seq-msgs unseen-seq)))
-        (if unseen-msgs
-            (progn
-              (mh-undefine-sequence mh-unseen-seq mh-seen-list)
-              (run-hooks 'mh-unseen-updated-hook)
-              (while mh-seen-list
-                (setq unseen-msgs (delq (car mh-seen-list) unseen-msgs))
-                (setq mh-seen-list (cdr mh-seen-list)))
-              (setcdr unseen-seq unseen-msgs)
-              t)                        ;since we set the folder
-          (setq mh-seen-list nil)))))
-
-(defun mh-delete-scan-msgs (msgs)
-  "Delete the scan listing lines for MSGS."
-  (save-excursion
-    (while msgs
-      (when (mh-goto-msg (car msgs) t t)
-        (when (memq 'unthread mh-view-ops)
-          (mh-thread-forget-message (car msgs)))
-        (mh-delete-line 1))
-      (setq msgs (cdr msgs)))))
-
-(defun mh-outstanding-commands-p ()
-  "Return non-nil if there are outstanding deletes or refiles."
-  (save-excursion
-    (when (eq major-mode 'mh-show-mode)
-      (set-buffer mh-show-folder-buffer))
-    (or mh-delete-list mh-refile-list)))
-
-(defun mh-coalesce-msg-list (messages)
-  "Given a list of MESSAGES, return a list of message number ranges.
-This is the inverse of `mh-read-msg-list', which expands ranges.
-Message lists passed to MH programs should be processed by this
-function to avoid exceeding system command line argument limits."
-  (let ((msgs (sort (copy-sequence messages) 'mh-greaterp))
-        (range-high nil)
-        (prev -1)
-        (ranges nil))
-    (while prev
-      (if range-high
-          (if (or (not (numberp prev))
-                  (not (equal (car msgs) (1- prev))))
-              (progn                    ;non-sequential, flush old range
-                (if (eq prev range-high)
-                    (setq ranges (cons range-high ranges))
-                  (setq ranges (cons (format "%s-%s" prev range-high) ranges)))
-                (setq range-high nil))))
-      (or range-high
-          (setq range-high (car msgs))) ;start new or first range
-      (setq prev (car msgs))
-      (setq msgs (cdr msgs)))
-    ranges))
-
-(defun mh-greaterp (msg1 msg2)
-  "Return the greater of two message indicators MSG1 and MSG2.
-Strings are \"smaller\" than numbers.
-Valid values are things like \"cur\", \"last\", 1, and 1820."
-  (if (numberp msg1)
-      (if (numberp msg2)
-          (> msg1 msg2)
-        t)
-    (if (numberp msg2)
-        nil
-      (string-lessp msg2 msg1))))
-
-(defun mh-lessp (msg1 msg2)
-  "Return the lesser of two message indicators MSG1 and MSG2.
-Strings are \"smaller\" than numbers.
-Valid values are things like \"cur\", \"last\", 1, and 1820."
-  (not (mh-greaterp msg1 msg2)))
+           (re-search-forward "[\t ]*\\([^\t \n].*\\)$" nil t)
+           (let ((start (match-beginning 1)))
+             (end-of-line)
+             (buffer-substring start (point)))))))
+
+(defun mh-variant-set (variant)
+  "Set the MH variant to VARIANT.
+Sets `mh-progs', `mh-lib', `mh-lib-progs' and
+`mh-flists-present-flag'.
+If the VARIANT is \"autodetect\", then first try nmh, then MH and
+finally GNU mailutils."
+  (interactive
+   (list (completing-read
+          "MH variant: "
+          (mapcar (lambda (x) (list (car x))) (mh-variants))
+          nil t)))
+  (let ((valid-list (mapcar (lambda (x) (car x)) (mh-variants))))
+    (cond
+     ((eq variant 'none))
+     ((eq variant 'autodetect)
+      (cond
+       ((mh-variant-set-variant 'nmh)
+        (message "%s installed as MH variant" mh-variant-in-use))
+       ((mh-variant-set-variant 'mh)
+        (message "%s installed as MH variant" mh-variant-in-use))
+       ((mh-variant-set-variant 'mu-mh)
+        (message "%s installed as MH variant" mh-variant-in-use))
+       (t
+        (message "No MH variant found on the system"))))
+     ((member variant valid-list)
+      (when (not (mh-variant-set-variant variant))
+        (message "Warning: %s variant not found. Autodetecting..." variant)
+        (mh-variant-set 'autodetect)))
+     (t
+      (message "Unknown variant; use %s"
+               (mapconcat '(lambda (x) (format "%s" (car x)))
+                          (mh-variants) " or "))))))
+
+(defcustom mh-variant 'autodetect
+  "*Specifies the variant used by MH-E.
+
+The default setting of this option is \"Auto-detect\" which means
+that MH-E will automatically choose the first of nmh, MH, or GNU
+mailutils that it finds in the directories listed in
+`mh-path' (which you can customize), `mh-sys-path', and
+`exec-path'. If, for example, you have both nmh and mailutils
+installed and `mh-variant-in-use' was initialized to nmh but you
+want to use mailutils, then you can set this option to
+\"mailutils\".
+
+When this variable is changed, MH-E resets `mh-progs', `mh-lib',
+`mh-lib-progs', `mh-flists-present-flag', and `mh-variant-in-use'
+accordingly."
+  :type `(radio
+          (const :tag "Auto-detect" autodetect)
+          ,@(mapcar (lambda (x) `(const ,(car x))) (mh-variants)))
+  :set (lambda (symbol value)
+         (set-default symbol value)     ;Done in mh-variant-set-variant!
+         (mh-variant-set value))
+  :group 'mh-e)
+
+
+
+;;; MH-E Customization
+
+;; All of the defgroups, defcustoms, and deffaces in MH-E are found
+;; here. This makes it possible to customize modules that aren't
+;; loaded yet. It also makes it easier to organize the customization
+;; groups.
+
+;; This section contains the following sub-sections:
+
+;; 1. MH-E Customization Groups
+
+;;    These are the customization group definitions. Every group has a
+;;    associated manual node. The ordering is alphabetical, except for
+;;    the groups mh-faces and mh-hooks which are last .
+
+;; 2. MH-E Customization
+
+;;    These are the actual customization variables. There is a
+;;    sub-section for each group in the MH-E Customization Groups
+;;    section, in the same order, separated by page breaks. Within
+;;    each section, variables are sorted alphabetically.
+
+;; 3. Hooks
+
+;;    All hooks must be placed in the mh-hook group; in addition, add
+;;    the group associated with the manual node in which the hook is
+;;    described. Since the mh-hook group appears near the end of this
+;;    section, the hooks will appear at the end of these other groups.
+
+;; 4. Faces
+
+;;    All faces must be placed in the mh-faces group; in addition, add
+;;    the group associated with the manual node in which the face is
+;;    described. Since the mh-faces group appears near the end of this
+;;    section, the faces will appear at the end of these other groups.
+
+(defun mh-customize (&optional delete-other-windows-flag)
+  "Customize MH-E variables.
+If optional argument DELETE-OTHER-WINDOWS-FLAG is non-nil, other
+windows in the frame are removed."
+  (interactive "P")
+  (customize-group 'mh-e)
+  (when delete-other-windows-flag
+    (delete-other-windows)))
+
+
+
+;;; MH-E Customization Groups
+
+(defgroup mh-e nil
+  "Emacs interface to the MH mail system.
+MH is the Rand Mail Handler. Other implementations include nmh
+and GNU mailutils."
+  :link '(custom-manual "(mh-e)Top")
+  :group 'mail)
+
+(defgroup mh-alias nil
+  "Aliases."
+  :link '(custom-manual "(mh-e)Aliases")
+  :prefix "mh-alias-"
+  :group 'mh-e)
+
+(defgroup mh-folder nil
+  "Organizing your mail with folders."
+  :prefix "mh-"
+  :link '(custom-manual "(mh-e)Folders")
+  :group 'mh-e)
+
+(defgroup mh-folder-selection nil
+  "Folder selection."
+  :prefix "mh-"
+  :link '(custom-manual "(mh-e)Folder Selection")
+  :group 'mh-e)
+
+(defgroup mh-identity nil
+  "Identities."
+  :link '(custom-manual "(mh-e)Identities")
+  :prefix "mh-identity-"
+  :group 'mh-e)
+
+(defgroup mh-inc nil
+  "Incorporating your mail."
+  :prefix "mh-inc-"
+  :link '(custom-manual "(mh-e)Incorporating Mail")
+  :group 'mh-e)
+
+(defgroup mh-junk nil
+  "Dealing with junk mail."
+  :link '(custom-manual "(mh-e)Junk")
+  :prefix "mh-junk-"
+  :group 'mh-e)
+
+(defgroup mh-letter nil
+  "Editing a draft."
+  :prefix "mh-"
+  :link '(custom-manual "(mh-e)Editing Drafts")
+  :group 'mh-e)
+
+(defgroup mh-ranges nil
+  "Ranges."
+  :prefix "mh-"
+  :link '(custom-manual "(mh-e)Ranges")
+  :group 'mh-e)
+
+(defgroup mh-scan-line-formats nil
+  "Scan line formats."
+  :link '(custom-manual "(mh-e)Scan Line Formats")
+  :prefix "mh-"
+  :group 'mh-e)
+
+(defgroup mh-search nil
+  "Searching."
+  :link '(custom-manual "(mh-e)Searching")
+  :prefix "mh-search-"
+  :group 'mh-e)
+
+(defgroup mh-sending-mail nil
+  "Sending mail."
+  :prefix "mh-"
+  :link '(custom-manual "(mh-e)Sending Mail")
+  :group 'mh-e)
+
+(defgroup mh-sequences nil
+  "Sequences."
+  :prefix "mh-"
+  :link '(custom-manual "(mh-e)Sequences")
+  :group 'mh-e)
+
+(defgroup mh-show nil
+  "Reading your mail."
+  :prefix "mh-"
+  :link '(custom-manual "(mh-e)Reading Mail")
+  :group 'mh-e)
+
+(defgroup mh-speedbar nil
+  "The speedbar."
+  :prefix "mh-speed-"
+  :link '(custom-manual "(mh-e)Speedbar")
+  :group 'mh-e)
+
+(defgroup mh-thread nil
+  "Threading."
+  :prefix "mh-thread-"
+  :link '(custom-manual "(mh-e)Threading")
+  :group 'mh-e)
+
+(defgroup mh-tool-bar nil
+  "The tool bar"
+  :link '(custom-manual "(mh-e)Tool Bar")
+  :prefix "mh-"
+  :group 'mh-e)
+
+(defgroup mh-hooks nil
+  "MH-E hooks."
+  :link '(custom-manual "(mh-e)Top")
+  :prefix "mh-"
+  :group 'mh-e)
+
+(defgroup mh-faces nil
+  "Faces used in MH-E."
+  :link '(custom-manual "(mh-e)Top")
+  :prefix "mh-"
+  :group 'faces
+  :group 'mh-e)
+
+
+
+;;; Emacs Interface to the MH Mail System (:group mh-e)
+
+;; See Variant Support, above.
+
+;;; Aliases (:group 'mh-alias)
+
+(defcustom mh-alias-completion-ignore-case-flag t
+  "*Non-nil means don't consider case significant in MH alias completion.
+
+As MH ignores case in the aliases, so too does MH-E. However, you
+may turn off this option to make case significant which can be
+used to segregate completion of your aliases. You might use
+lowercase for mailing lists and uppercase for people."
+  :type 'boolean
+  :group 'mh-alias)
+
+(defcustom mh-alias-expand-aliases-flag nil
+  "*Non-nil means to expand aliases entered in the minibuffer.
+
+In other words, aliases entered in the minibuffer will be
+expanded to the full address in the message draft. By default,
+this expansion is not performed."
+  :type 'boolean
+  :group 'mh-alias)
+
+(defcustom mh-alias-flash-on-comma t
+  "*Specify whether to flash address or warn on translation.
+
+This option controls the behavior when a [comma] is pressed while
+entering aliases or addresses. The default setting flashes the
+address associated with an address in the minibuffer briefly, but
+does not display a warning if the alias is not found."
+  :type '(choice (const :tag "Flash but Don't Warn If No Alias" t)
+                 (const :tag "Flash and Warn If No Alias" 1)
+                 (const :tag "Don't Flash Nor Warn If No Alias" nil))
+  :group 'mh-alias)
+
+(defcustom mh-alias-insert-file nil
+  "*Filename used to store a new MH-E alias.
+
+The default setting of this option is \"Use Aliasfile Profile
+Component\". This option can also hold the name of a file or a
+list a file names. If this option is set to a list of file names,
+or the \"Aliasfile:\" profile component contains more than one file
+name, MH-E will prompt for one of them when MH-E adds an alias."
+  :type '(choice (const :tag "Use Aliasfile Profile Component" nil)
+                 (file :tag "Alias File")
+                 (repeat :tag "List of Alias Files" file))
+  :group 'mh-alias)
+
+(defcustom mh-alias-insertion-location 'sorted
+  "Specifies where new aliases are entered in alias files.
+
+This option is set to \"Alphabetical\" by default. If you organize
+your alias file in other ways, then adding aliases to the \"Top\"
+or \"Bottom\" of your alias file might be more appropriate."
+  :type '(choice (const :tag "Alphabetical" sorted)
+                 (const :tag "Top" top)
+                 (const :tag "Bottom" bottom))
+  :group 'mh-alias)
+
+(defcustom mh-alias-local-users t
+  "*If on, local users are added to alias completion.
+
+Aliases are created from \"/etc/passwd\" entries with a user ID
+larger than a magical number, typically 200. This can be a handy
+tool on a machine where you and co-workers exchange messages.
+These aliases have the form \"local.first.last\" if a real name is
+present in the password file. Otherwise, the alias will have the
+form \"local.login\".
+
+If you're on a system with thousands of users you don't know, and
+the loading of local aliases slows MH-E down noticeably, then
+turn this option off.
+
+This option also takes a string which is executed to generate the
+password file. For example, use \"ypcat passwd\" to obtain the
+NIS password file."
+  :type '(choice (boolean) (string))
+  :group 'mh-alias)
+
+(defcustom mh-alias-local-users-prefix "local."
+  "*String prefixed to the real names of users from the password file.
+This option can also be set to \"Use Login\".
+
+For example, consider the following password file entry:
+
+    psg:x:1000:1000:Peter S Galbraith,,,:/home/psg:/bin/tcsh
+
+The following settings of this option will produce the associated
+aliases:
+
+    \"local.\"                  local.peter.galbraith
+    \"\"                        peter.galbraith
+    Use Login                   psg
+
+This option has no effect if variable `mh-alias-local-users' is
+turned off."
+  :type '(choice (const :tag "Use Login" nil)
+                 (string))
+  :group 'mh-alias)
+
+(defcustom mh-alias-passwd-gecos-comma-separator-flag t
+  "*Non-nil means the gecos field in the password file uses a comma separator.
+
+In the example in `mh-alias-local-users-prefix', commas are used
+to separate different values within the so-called gecos field.
+This is a fairly common usage. However, in the rare case that the
+gecos field in your password file is not separated by commas and
+whose contents may contain commas, you can turn this option off."
+  :type 'boolean
+  :group 'mh-alias)
+
+
+
+;;; Organizing Your Mail with Folders (:group 'mh-folder)
+
+(defcustom mh-new-messages-folders t
+  "Folders searched for the \"unseen\" sequence.
+
+Set this option to \"Inbox\" to search the \"+inbox\" folder or
+\"All\" to search all of the top level folders. Otherwise, list
+the folders that should be searched with the \"Choose Folders\"
+menu item.
+
+See also `mh-recursive-folders-flag'."
+  :type '(choice (const :tag "Inbox" t)
+                 (const :tag "All" nil)
+                 (repeat :tag "Choose Folders" (string :tag "Folder")))
+  :group 'mh-folder)
+
+(defcustom mh-ticked-messages-folders t
+  "Folders searched for `mh-tick-seq'.
+
+Set this option to \"Inbox\" to search the \"+inbox\" folder or
+\"All\" to search all of the top level folders. Otherwise, list
+the folders that should be searched with the \"Choose Folders\"
+menu item.
+
+See also `mh-recursive-folders-flag'."
+  :type '(choice (const :tag "Inbox" t)
+                 (const :tag "All" nil)
+                 (repeat :tag "Choose Folders" (string :tag "Folder")))
+  :group 'mh-folder)
+
+(defcustom mh-large-folder 200
+  "The number of messages that indicates a large folder.
+
+If a folder is deemed to be large, that is the number of messages
+in it exceed this value, then confirmation is needed when it is
+visited. Even when `mh-show-threads-flag' is non-nil, the folder
+is not automatically threaded, if it is large. If set to nil all
+folders are treated as if they are small."
+  :type '(choice (const :tag "No Limit") integer)
+  :group 'mh-folder)
+
+(defcustom mh-recenter-summary-flag nil
+  "*Non-nil means to recenter the summary window.
+
+If this option is turned on, recenter the summary window when the
+show window is toggled off."
+  :type 'boolean
+  :group 'mh-folder)
+
+(defcustom mh-recursive-folders-flag nil
+  "*Non-nil means that commands which operate on folders do so recursively."
+  :type 'boolean
+  :group 'mh-folder)
+
+(defcustom mh-sortm-args nil
+  "*Additional arguments for \"sortm\"\\<mh-folder-mode-map>.
+
+This option is consulted when a prefix argument is used with
+\\[mh-sort-folder]. Normally default arguments to \"sortm\" are
+specified in the MH profile. This option may be used to provide
+an alternate view. For example, \"'(\"-nolimit\" \"-textfield\"
+\"subject\")\" is a useful setting."
+  :type 'string
+  :group 'mh-folder)
+
+
+
+;;; Folder Selection (:group 'mh-folder-selection)
+
+(defcustom mh-default-folder-for-message-function nil
+  "Function to select a default folder for refiling or \"Fcc:\".
+
+The current buffer is set to the message being refiled with point
+at the start of the message. This function should return the
+default folder as a string with a leading \"+\" sign. It can also
+return nil so that the last folder name is used as the default,
+or an empty string to suppress the default entirely."
+  :type 'function
+  :group 'mh-folder-selection)
+
+(defcustom mh-default-folder-list nil
+  "*List of addresses and folders.
+
+The folder name associated with the first address found in this
+list is used as the default for `mh-refile-msg' and similar
+functions. Each element in this list contains a \"Check Recipient\"
+item. If this item is turned on, then the address is checked
+against the recipient instead of the sender. This is useful for
+mailing lists.
+
+See `mh-prompt-for-refile-folder' and `mh-folder-from-address'
+for more information."
+  :type '(repeat (list (regexp :tag "Address")
+                       (string :tag "Folder")
+                       (boolean :tag "Check Recipient")))
+  :group 'mh-folder-selection)
+
+(defcustom mh-default-folder-must-exist-flag t
+  "*Non-nil means guessed folder name must exist to be used.
+
+If the derived folder does not exist, and this option is on, then
+the last folder name used is suggested. This is useful if you get
+mail from various people for whom you have an alias, but file
+them all in the same project folder.
+
+See `mh-prompt-for-refile-folder' and `mh-folder-from-address'
+for more information."
+  :type 'boolean
+  :group 'mh-folder-selection)
+
+(defcustom mh-default-folder-prefix ""
+  "*Prefix used for folder names generated from aliases.
+The prefix is used to prevent clutter in your mail directory.
+
+See `mh-prompt-for-refile-folder' and `mh-folder-from-address'
+for more information."
+  :type 'string
+  :group 'mh-folder-selection)
+
+
+
+;;; Identities (:group 'mh-identity)
+
+(eval-and-compile
+  (unless (fboundp 'mh-identity-make-menu-no-autoload)
+    (defun mh-identity-make-menu-no-autoload ()
+      "Temporary definition.
+Real definition will take effect when mh-identity is loaded."
+      nil)))
+
+(defcustom mh-identity-list nil
+  "*List of identities.
+
+To customize this option, click on the \"INS\" button and enter a label
+such as \"Home\" or \"Work\". Then click on the \"INS\" button with the
+label \"Add at least one item below\". Then choose one of the items in
+the \"Value Menu\".
+
+You can specify an alternate \"From:\" header field using the \"From
+Field\" menu item. You must include a valid email address. A standard
+format is \"First Last <login@@host.domain>\". If you use an initial
+with a period, then you must quote your name as in '\"First I. Last\"
+<login@@host.domain>'. People usually list the name of the company
+where they work using the \"Organization Field\" menu item. Set any
+arbitrary header field and value in the \"Other Field\" menu item.
+Unless the header field is a standard one, precede the name of your
+field's label with \"X-\", as in \"X-Fruit-of-the-Day:\". The value of
+\"Attribution Verb\" overrides the setting of
+`mh-extract-from-attribution-verb'. Set your signature with the
+\"Signature\" menu item. You can specify the contents of
+`mh-signature-file-name', a file, or a function. Specify a different
+key to sign or encrypt messages with the \"GPG Key ID\" menu item.
+
+You can select the identities you have added via the menu called
+\"Identity\" in the MH-Letter buffer. You can also use
+\\[mh-insert-identity]. To clear the fields and signature added by the
+identity, select the \"None\" identity.
+
+The \"Identity\" menu contains two other items to save you from having
+to set the identity on every message. The menu item \"Set Default for
+Session\" can be used to set the default identity to the current
+identity until you exit Emacs. The menu item \"Save as Default\" sets
+the option `mh-identity-default' to the current identity setting. You
+can also customize the `mh-identity-default' option in the usual
+fashion."
+  :type '(repeat (list :tag ""
+                       (string :tag "Label")
+                       (repeat :tag "Add at least one item below"
+                               (choice
+                                (cons :tag "From Field"
+                                      (const "From")
+                                      (string :tag "Value"))
+                                (cons :tag "Organization Field"
+                                      (const "Organization")
+                                      (string :tag "Value"))
+                                (cons :tag "Other Field"
+                                      (string :tag "Field")
+                                      (string :tag "Value"))
+                                (cons :tag "Attribution Verb"
+                                      (const ":attribution-verb")
+                                      (string :tag "Value"))
+                                (cons :tag "Signature"
+                                      (const :tag "Signature"
+                                             ":signature")
+                                      (choice
+                                       (const :tag "mh-signature-file-name"
+                                              nil)
+                                       (file)
+                                       (function)))
+                                (cons :tag "GPG Key ID"
+                                      (const :tag "GPG Key ID"
+                                             ":pgg-default-user-id")
+                                      (string :tag "Value"))))))
+  :set (lambda (symbol value)
+         (set-default symbol value)
+         (mh-identity-make-menu-no-autoload))
+  :group 'mh-identity)
+
+(defcustom mh-auto-fields-list nil
+  "List of recipients for which header lines are automatically inserted.
+
+This option can be used to set the identity depending on the
+recipient. To customize this option, click on the \"INS\" button and
+enter a regular expression for the recipient's address. Click on the
+\"INS\" button with the \"Add at least one item below\" label. Then choose
+one of the items in the \"Value Menu\".
+
+The \"Identity\" menu item is used to select an identity from those
+configured in `mh-identity-list'. All of the information for that
+identity will be added if the recipient matches. The \"Fcc Field\" menu
+item is used to select a folder that is used in the \"Fcc:\" header.
+When you send the message, MH will put a copy of your message in this
+folder. The \"Mail-Followup-To Field\" menu item is used to insert an
+\"Mail-Followup-To:\" header field with the recipients you provide. If
+the recipient's mail user agent supports this header field (as nmh
+does), then their replies will go to the addresses listed. This is
+useful if their replies go both to the list and to you and you don't
+have a mechanism to suppress duplicates. If you reply to someone not
+on the list, you must either remove the \"Mail-Followup-To:\" field, or
+ensure the recipient is also listed there so that he receives replies
+to your reply. Other header fields may be added using the \"Other
+Field\" menu item.
+
+These fields can only be added after the recipient is known. Once the
+header contains one or more recipients, run the
+\\[mh-insert-auto-fields] command or choose the \"Identity -> Insert
+Auto Fields\" menu item to insert these fields manually. However, you
+can just send the message and the fields will be added automatically.
+You are given a chance to see these fields and to confirm them before
+the message is actually sent. You can do away with this confirmation
+by turning off the option `mh-auto-fields-prompt-flag'.
+
+You should avoid using the same header field in `mh-auto-fields-list'
+and `mh-identity-list' definitions that may apply to the same message
+as the result is undefined."
+  :type `(repeat
+          (list :tag ""
+                (string :tag "Recipient")
+                (repeat :tag "Add at least one item below"
+                        (choice
+                         (cons :tag "Identity"
+                               (const ":identity")
+                               ,(append
+                                 '(radio)
+                                 (mapcar
+                                  (function (lambda (arg) `(const ,arg)))
+                                  (mapcar 'car mh-identity-list))))
+                         (cons :tag "Fcc Field"
+                               (const "fcc")
+                               (string :tag "Value"))
+                         (cons :tag "Mail-Followup-To Field"
+                               (const "Mail-Followup-To")
+                               (string :tag "Value"))
+                         (cons :tag "Other Field"
+                                 (string :tag "Field")
+                                 (string :tag "Value"))))))
+  :group 'mh-identity)
+
+(defcustom mh-auto-fields-prompt-flag t
+  "*Non-nil means to prompt before sending if fields inserted.
+See `mh-auto-fields-list'."
+  :type 'boolean
+  :group 'mh-identity)
+
+(defcustom mh-identity-default nil
+  "Default identity to use when `mh-letter-mode' is called.
+See `mh-identity-list'."
+  :type (append
+         '(radio)
+         (cons '(const :tag "None" nil)
+               (mapcar (function (lambda (arg) `(const ,arg)))
+                       (mapcar 'car mh-identity-list))))
+  :group 'mh-identity)
+
+(defcustom mh-identity-handlers
+  '(("From" . mh-identity-handler-top)
+    (":default" . mh-identity-handler-bottom)
+    (":attribution-verb" . mh-identity-handler-attribution-verb)
+    (":signature" . mh-identity-handler-signature)
+    (":pgg-default-user-id" . mh-identity-handler-gpg-identity))
+  "Handler functions for fields in `mh-identity-list'.
+
+This option is used to change the way that fields, signatures,
+and attributions in `mh-identity-list' are added. To customize
+`mh-identity-handlers', replace the name of an existing handler
+function associated with the field you want to change with the
+name of a function you have written. You can also click on an
+\"INS\" button and insert a field of your choice and the name of
+the function you have written to handle it.
+
+The \"Field\" field can be any field that you've used in your
+`mh-identity-list'. The special fields \":attribution-verb\",
+\":signature\", or \":pgg-default-user-id\" are used for the
+`mh-identity-list' choices \"Attribution Verb\", \"Signature\", and
+\"GPG Key ID\" respectively.
+
+The handler associated with the \":default\" field is used when no
+other field matches.
+
+The handler functions are passed two or three arguments: the
+FIELD itself (for example, \"From\"), or one of the special
+fields (for example, \":signature\"), and the ACTION 'remove or
+'add. If the action is 'add, an additional argument
+containing the VALUE for the field is given."
+  :type '(repeat (cons (string :tag "Field") function))
+  :group 'mh-identity)
+
+
+
+;;; Incorporating Your Mail (:group 'mh-inc)
+
+(defcustom mh-inc-prog "inc"
+  "*Program to incorporate new mail into a folder.
+
+This program generates a one-line summary for each of the new
+messages. Unless it is an absolute pathname, the file is assumed
+to be in the `mh-progs' directory. You may also link a file to
+\"inc\" that uses a different format. You'll then need to modify
+several scan line format variables appropriately."
+  :type 'string
+  :group 'mh-inc)
+
+(eval-and-compile
+  (unless (fboundp 'mh-inc-spool-make-no-autoload)
+    (defun mh-inc-spool-make-no-autoload ()
+      "Temporary definition.
+Real definition will take effect when mh-inc is loaded."
+      nil)))
+
+(defcustom mh-inc-spool-list nil
+  "*Alternate spool files.
+
+You can use the `mh-inc-spool-list' variable to direct MH-E to
+retrieve mail from arbitrary spool files other than your system
+mailbox, file it in folders other than your \"+inbox\", and assign
+key bindings to incorporate this mail.
+
+Suppose you are subscribed to the \"mh-e-devel\" mailing list and
+you use \"procmail\" to filter this mail into \"~/mail/mh-e\" with
+the following recipe in \".procmailrc\":
+
+    MAILDIR=$HOME/mail
+    :0:
+    * ^From mh-e-devel-admin@stop.mail-abuse.org
+    mh-e
+
+In order to incorporate \"~/mail/mh-e\" into \"+mh-e\" with an
+\"I m\" (mh-inc-spool-mh-e) command, customize this option, and click
+on the \"INS\" button. Enter a \"Spool File\" of \"~/mail/mh-e\", a
+\"Folder\" of \"mh-e\", and a \"Key Binding\" of \"m\".
+
+You can use \"xbuffy\" to automate the incorporation of this mail
+using the \"gnudoit\" command in the \"gnuserv\" package as follows:
+
+    box ~/mail/mh-e
+        title mh-e
+        origMode
+        polltime 10
+        headertime 0
+        command gnudoit -q '(mh-inc-spool-mh-e)'"
+  :type '(repeat (list (file :tag "Spool File")
+                       (string :tag "Folder")
+                       (character :tag "Key Binding")))
+  :set (lambda (symbol value)
+         (set-default symbol value)
+         (mh-inc-spool-make-no-autoload))
+  :group 'mh-inc)
+
+
+
+;;; Dealing with Junk Mail (:group 'mh-junk)
+
+(defvar mh-junk-choice nil
+  "Chosen spam fighting program.")
+
+;; Available spam filter interfaces
+(defvar mh-junk-function-alist
+  '((spamassassin mh-spamassassin-blacklist mh-spamassassin-whitelist)
+    (bogofilter mh-bogofilter-blacklist mh-bogofilter-whitelist)
+    (spamprobe mh-spamprobe-blacklist mh-spamprobe-whitelist))
+  "Available choices of spam programs to use.
+
+This is an alist. For each element there are functions that
+blacklist a message as spam and whitelist a message incorrectly
+classified as spam.")
+
+(defun mh-junk-choose (symbol value)
+  "Choose spam program to use.
+
+The function is always called with SYMBOL bound to
+`mh-junk-program' and VALUE bound to the new value of
+`mh-junk-program'. The function sets the variable
+`mh-junk-choice' in addition to `mh-junk-program'."
+  (set symbol value)                    ;XXX shouldn't this be set-default?
+  (setq mh-junk-choice
+        (or value
+            (loop for element in mh-junk-function-alist
+                  until (executable-find (symbol-name (car element)))
+                  finally return (car element)))))
+
+(defcustom mh-junk-background nil
+  "If on, spam programs are run in background.
+
+By default, the programs are run in the foreground, but this can
+be slow when junking large numbers of messages. If you have
+enough memory or don't junk that many messages at the same time,
+you might try turning on this option."
+  :type '(choice (const :tag "Off" nil)
+                 (const :tag "On" 0))
+  :group 'mh-junk)
+
+(defcustom mh-junk-disposition nil
+  "Disposition of junk mail."
+  :type '(choice (const :tag "Delete Spam" nil)
+                 (string :tag "Spam Folder"))
+  :group 'mh-junk)
+
+(defcustom mh-junk-program nil
+  "Spam program that MH-E should use.
+
+The default setting of this option is \"Auto-detect\" which means
+that MH-E will automatically choose one of SpamAssassin,
+bogofilter, or SpamProbe in that order. If, for example, you have
+both SpamAssassin and bogofilter installed and you want to use
+bogofilter, then you can set this option to \"Bogofilter\"."
+  :type '(choice (const :tag "Auto-detect" nil)
+                 (const :tag "SpamAssassin" spamassassin)
+                 (const :tag "Bogofilter" bogofilter)
+                 (const :tag "SpamProbe" spamprobe))
+  :set 'mh-junk-choose
+  :group 'mh-junk)
+
+
+
+;;; Editing a Draft (:group 'mh-letter)
+
+(defcustom mh-compose-insertion (if (locate-library "mml") 'mml 'mh)
+  "Type of tags used when composing MIME messages.
+
+In addition to MH-style directives, MH-E also supports MML (MIME
+Meta Language) tags. (see Info node `(emacs-mime)Composing').
+This option can be used to choose between them. By default, this
+option is set to \"MML\" if it is supported since it provides a
+lot more functionality. This option can also be set to \"MH\" if
+MH-style directives are preferred."
+  :type '(choice (const :tag "MML" mml)
+                 (const :tag "MH"  mh))
+  :group 'mh-letter)
+
+(defcustom mh-compose-skipped-header-fields
+  '("From" "Organization" "References" "In-Reply-To"
+    "X-Face" "Face" "X-Image-URL" "X-Mailer")
+  "List of header fields to skip over when navigating in draft."
+  :type '(repeat (string :tag "Field"))
+  :group 'mh-letter)
+
+(defcustom mh-compose-space-does-completion-flag nil
+  "*Non-nil means \\<mh-letter-mode-map>\\[mh-letter-complete-or-space] does completion in message header."
+  :type 'boolean
+  :group 'mh-letter)
+
+(defcustom mh-delete-yanked-msg-window-flag nil
+  "*Non-nil means delete any window displaying the message.
+
+This deletes the window containing the original message after
+yanking it with \\<mh-letter-mode-map>\\[mh-yank-cur-msg] to make
+more room on your screen for your reply."
+  :type 'boolean
+  :group 'mh-letter)
+
+(defcustom mh-extract-from-attribution-verb "wrote:"
+  "*Verb to use for attribution when a message is yanked by \\<mh-letter-mode-map>\\[mh-yank-cur-msg].
+
+The attribution consists of the sender's name and email address
+followed by the content of this option. This option can be set to
+\"wrote:\", \"a écrit:\", and \"schrieb:\". You can also use the
+\"Custom String\" menu item to enter your own verb."
+  :type '(choice (const "wrote:")
+                 (const "a écrit:")
+                 (const "schrieb:")
+                 (string :tag "Custom String"))
+  :group 'mh-letter)
+
+(defcustom mh-ins-buf-prefix "> "
+  "*String to put before each line of a yanked or inserted message.
+
+The prefix \"> \" is the default setting of this option. I
+suggest that you not modify this option since it is used by many
+mailers and news readers: messages are far easier to read if
+several included messages have all been indented by the same
+string.
+
+This prefix is not inserted if you use one of the supercite
+flavors of `mh-yank-behavior' or you have added a
+`mail-citation-hook'."
+  :type 'string
+  :group 'mh-letter)
+
+(defcustom mh-letter-complete-function 'ispell-complete-word
+  "*Function to call when completing outside of address or folder fields.
+
+In the body of the message,
+\\<mh-letter-mode-map>\\[mh-letter-complete] runs this function,
+which is set to \"ispell-complete-word\" by default."
+  :type '(choice function (const nil))
+  :group 'mh-letter)
+
+(defcustom mh-letter-fill-column 72
+  "*Fill column to use in MH Letter mode.
+
+By default, this option is 72 to allow others to quote your
+message without line wrapping."
+  :type 'integer
+  :group 'mh-letter)
+
+(defcustom mh-mml-method-default (if mh-pgp-support-flag "pgpmime" "none")
+  "Default method to use in security tags.
+
+This option is used to select between a variety of mail security
+mechanisms. The default is \"PGP (MIME)\" if it is supported\;
+otherwise, the default is \"None\". Other mechanisms include
+vanilla \"PGP\" and \"S/MIME\".
+
+The `pgg' customization group may have some settings which may
+interest you (see Info node `(pgg)').
+
+In particular, I turn on the option `pgg-encrypt-for-me' so that
+all messages I encrypt are encrypted with my public key as well.
+If you keep a copy of all of your outgoing mail with a \"Fcc:\"
+header field, this setting is vital so that you can read the mail
+you write!"
+  :type '(choice (const :tag "PGP (MIME)" "pgpmime")
+                 (const :tag "PGP" "pgp")
+                 (const :tag "S/MIME" "smime")
+                 (const :tag "None" "none"))
+  :group 'mh-letter)
+
+(defcustom mh-signature-file-name "~/.signature"
+  "*Source of user's signature.
+
+By default, the text of your signature is taken from the file
+\"~/.signature\". You can read from other sources by changing this
+option. This file may contain a vCard in which case an attachment is
+added with the vCard.
+
+This option may also be a symbol, in which case that function is
+called. You may not want a signature separator to be added for you;
+instead you may want to insert one yourself. Options that you may find
+useful to do this include `mh-signature-separator' (when inserting a
+signature separator) and `mh-signature-separator-regexp' (for finding
+said separator). The function `mh-signature-separator-p', which
+reports t if the buffer contains a separator, may be useful as well.
+
+The signature is inserted into your message with the command
+\\<mh-letter-mode-map>\\[mh-insert-signature] or with the option
+`mh-identity-list'."
+  :type 'file
+  :group 'mh-letter)
+
+(defcustom mh-signature-separator-flag t
+  "*Non-nil means a signature separator should be inserted.
+
+It is not recommended that you change this option since various
+mail user agents, including MH-E, use the separator to present
+the signature differently, and to suppress the signature when
+replying or yanking a letter into a draft."
+  :type 'boolean
+  :group 'mh-letter)
+
+(defcustom mh-x-face-file "~/.face"
+  "*File containing face header field to insert in outgoing mail.
+
+If the file starts with either of the strings \"X-Face:\", \"Face:\"
+or \"X-Image-URL:\" then the contents are added to the message header
+verbatim. Otherwise it is assumed that the file contains the value of
+the \"X-Face:\" header field.
+
+The \"X-Face:\" header field, which is a low-resolution, black and
+white image, can be generated using the \"compface\" command (see URL
+`ftp://ftp.cs.indiana.edu/pub/faces/compface/compface.tar.Z'). The
+\"Online X-Face Converter\" is a useful resource for quick conversion
+of images into \"X-Face:\" header fields (see URL
+`http://www.dairiki.org/xface/').
+
+Use the \"make-face\" script to convert a JPEG image to the higher
+resolution, color, \"Face:\" header field (see URL
+`http://quimby.gnus.org/circus/face/make-face').
+
+The URL of any image can be used for the \"X-Image-URL:\" field and no
+processing of the image is required.
+
+To prevent the setting of any of these header fields, either set
+`mh-x-face-file' to nil, or simply ensure that the file defined by
+this option doesn't exist."
+  :type 'file
+  :group 'mh-letter)
+
+(defcustom mh-yank-behavior 'attribution
+  "*Controls which part of a message is yanked by \\<mh-letter-mode-map>\\[mh-yank-cur-msg].
+
+To include the entire message, including the entire header, use
+\"Body and Header\". Use \"Body\" to yank just the body without
+the header. To yank only the portion of the message following the
+point, set this option to \"Below Point\".
+
+Choose \"Invoke supercite\" to pass the entire message and header
+through supercite.
+
+If the \"Body With Attribution\" setting is used, then the
+message minus the header is yanked and a simple attribution line
+is added at the top using the value of the option
+`mh-extract-from-attribution-verb'. This is the default.
+
+If the \"Invoke supercite\" or \"Body With Attribution\" settings
+are used, the \"-noformat\" argument is passed to the \"repl\"
+program to override a \"-filter\" or \"-format\" argument. These
+settings also have \"Automatically\" variants that perform the
+action automatically when you reply so that you don't need to use
+\\[mh-yank-cur-msg] at all. Note that this automatic action is
+only performed if the show buffer matches the message being
+replied to. People who use the automatic variants tend to turn on
+the option `mh-delete-yanked-msg-window-flag' as well so that the
+show window is never displayed.
+
+If the show buffer has a region, the option `mh-yank-behavior' is
+ignored unless its value is one of Attribution variants in which
+case the attribution is added to the yanked region.
+
+If this option is set to one of the supercite flavors, the hook
+`mail-citation-hook' is ignored and `mh-ins-buf-prefix' is not
+inserted."
+  :type '(choice (const :tag "Body and Header" t)
+                 (const :tag "Body" body)
+                 (const :tag "Below Point" nil)
+                 (const :tag "Invoke supercite" supercite)
+                 (const :tag "Invoke supercite, Automatically" autosupercite)
+                 (const :tag "Body With Attribution" attribution)
+                 (const :tag "Body With Attribution, Automatically"
+                        autoattrib))
+  :group 'mh-letter)
+
+
+
+;;; Ranges (:group 'mh-ranges)
+
+(defcustom mh-interpret-number-as-range-flag t
+  "*Non-nil means interpret a number as a range.
+
+Since one of the most frequent ranges used is \"last:N\", MH-E
+will interpret input such as \"200\" as \"last:200\" if this
+option is on (which is the default). If you need to scan just the
+message 200, then use the range \"200:200\"."
+  :type 'boolean
+  :group 'mh-ranges)
+
+
+
+;;; Scan Line Formats (:group 'mh-scan-line-formats)
+
+(eval-and-compile
+  (unless (fboundp 'mh-adaptive-cmd-note-flag-check)
+    (defun mh-adaptive-cmd-note-flag-check (symbol value)
+      "Temporary definition.
+Real definition, below, uses variables that aren't defined yet."
+      (set-default symbol value))))
+
+(defcustom mh-adaptive-cmd-note-flag t
+  "*Non-nil means that the message number width is determined dynamically.
+
+If you've created your own format to handle long message numbers,
+you'll be pleased to know you no longer need it since MH-E adapts its
+internal format based upon the largest message number if this option
+is on (the default). This option may only be turned on when
+`mh-scan-format-file' is set to \"Use MH-E scan Format\".
+
+If you prefer fixed-width message numbers, turn off this option and
+call `mh-set-cmd-note' with the width specified by your format file
+\(see `mh-scan-format-file'). For example, the default width is 4, so
+you would use \"(mh-set-cmd-note 4)\"."
+  :type 'boolean
+  :group 'mh-scan-line-formats
+  :set 'mh-adaptive-cmd-note-flag-check)
+
+(defun mh-scan-format-file-check (symbol value)
+  "Check if desired setting is legal.
+Throw an error if user tries to set `mh-scan-format-file' to
+anything but t when `mh-adaptive-cmd-note-flag' is on. Otherwise,
+set SYMBOL to VALUE."
+  (if (and (not (eq value t))
+           mh-adaptive-cmd-note-flag)
+      (error "%s %s" "You must turn off `mh-adaptive-cmd-note-flag'"
+             "unless you use \"Use MH-E scan Format\"")
+    (set-default symbol value)))
+
+(defcustom mh-scan-format-file t
+  "Specifies the format file to pass to the scan program.
+
+The default setting for this option is \"Use MH-E scan Format\". This
+means that the format string will be taken from the either
+`mh-scan-format-mh' or `mh-scan-format-nmh' depending on whether MH or
+nmh (or GNU mailutils) is in use. This setting also enables you to
+turn on the `mh-adaptive-cmd-note-flag' option.
+
+You can also set this option to \"Use Default scan Format\" to get the
+same output as you would get if you ran \"scan\" from the shell. If
+you have a format file that you want MH-E to use but not MH, you can
+set this option to \"Specify a scan Format File\" and enter the name
+of your format file.
+
+If you change the format of the scan lines you'll need to tell MH-E
+how to parse the new format. As you will see, quite a lot of variables
+are involved to do that. Use \"\\[apropos] RET mh-scan.*regexp\" to
+obtain a list of these variables. You will also have to call
+`mh-set-cmd-note' if your notations are not in column 4 (columns in
+Emacs start with 0)."
+  :type '(choice (const :tag "Use MH-E scan Format" t)
+                 (const :tag "Use Default scan Format" nil)
+                 (file  :tag "Specify a scan Format File"))
+  :group 'mh-scan-line-formats
+  :set 'mh-scan-format-file-check)
+
+(defun mh-adaptive-cmd-note-flag-check (symbol value)
+  "Check if desired setting is legal.
+Throw an error if user tries to turn on
+`mh-adaptive-cmd-note-flag' when `mh-scan-format-file' isn't t.
+Otherwise, set SYMBOL to VALUE."
+  (if (and value
+           (not (eq mh-scan-format-file t)))
+      (error "%s %s" "Can't turn on unless `mh-scan-format-file'"
+             "is set to \"Use MH-E scan Format\"")
+    (set-default symbol value)))
+
+(defcustom mh-scan-prog "scan"
+  "*Program used to scan messages.
+
+The name of the program that generates a listing of one line per
+message is held in this option. Unless this variable contains an
+absolute pathname, it is assumed to be in the `mh-progs'
+directory. You may link another program to `scan' (see
+\"mh-profile(5)\") to produce a different type of listing."
+  :type 'string
+  :group 'mh-scan-line-formats)
+(make-variable-buffer-local 'mh-scan-prog)
+
+
+
+;;; Searching (:group 'mh-search)
+
+(defcustom mh-search-program nil
+  "Search program that MH-E shall use.
+
+The default setting of this option is \"Auto-detect\" which means
+that MH-E will automatically choose one of swish++, swish-e,
+mairix, namazu, pick and grep in that order. If, for example, you
+have both swish++ and mairix installed and you want to use
+mairix, then you can set this option to \"mairix\".
+
+More information about setting up an indexing program to use with
+MH-E can be found in the documentation of `mh-search'."
+  :type '(choice (const :tag "Auto-detect" nil)
+                 (const :tag "swish++" swish++)
+                 (const :tag "swish-e" swish)
+                 (const :tag "mairix" mairix)
+                 (const :tag "namazu" namazu)
+                 (const :tag "pick" pick)
+                 (const :tag "grep" grep))
+  :group 'mh-search)
 
 
 
-;;; Basic sequence handling
-
-(defun mh-delete-seq-locally (seq)
-  "Remove MH-E's record of SEQ."
-  (let ((entry (mh-find-seq seq)))
-    (setq mh-seq-list (delq entry mh-seq-list))))
-
-(defun mh-read-folder-sequences (folder save-refiles)
-  "Read and return the predefined sequences for a FOLDER.
-If SAVE-REFILES is non-nil, then keep the sequences
-that note messages to be refiled."
-  (let ((seqs ()))
-    (cond (save-refiles
-           (mh-mapc (function (lambda (seq) ; Save the refiling sequences
-                                (if (mh-folder-name-p (mh-seq-name seq))
-                                    (setq seqs (cons seq seqs)))))
-                    mh-seq-list)))
-    (save-excursion
-      (if (eq 0 (mh-exec-cmd-quiet nil "mark" folder "-list"))
-          (progn
-            ;; look for name in line of form "cur: 4" or "myseq (private): 23"
-            (while (re-search-forward "^[^: ]+" nil t)
-              (setq seqs (cons (mh-make-seq (intern (buffer-substring
-                                                     (match-beginning 0)
-                                                     (match-end 0)))
-                                            (mh-read-msg-list))
-                               seqs)))
-            (delete-region (point-min) (point))))) ; avoid race with
-                                        ; mh-process-daemon
-    seqs))
-
-(defun mh-read-msg-list ()
-  "Return a list of message numbers from point to the end of the line.
-Expands ranges into set of individual numbers."
-  (let ((msgs ())
-        (end-of-line (save-excursion (end-of-line) (point)))
-        num)
-    (while (re-search-forward "[0-9]+" end-of-line t)
-      (setq num (string-to-number (buffer-substring (match-beginning 0)
-                                                    (match-end 0))))
-      (cond ((looking-at "-")           ; Message range
-             (forward-char 1)
-             (re-search-forward "[0-9]+" end-of-line t)
-             (let ((num2 (string-to-number
-                          (buffer-substring (match-beginning 0)
-                                            (match-end 0)))))
-               (if (< num2 num)
-                   (error "Bad message range: %d-%d" num num2))
-               (while (<= num num2)
-                 (setq msgs (cons num msgs))
-                 (setq num (1+ num)))))
-            ((not (zerop num))          ;"pick" outputs "0" to mean no match
-             (setq msgs (cons num msgs)))))
-    msgs))
-
-(defun mh-notate-user-sequences (&optional range)
-  "Mark user-defined sequences in RANGE.
-
-Check the documentation of `mh-interactive-range' to see how
-RANGE is read in interactive use; if nil all messages are
-notated."
-  (unless range
-    (setq range (cons (point-min) (point-max))))
-  (let ((seqs mh-seq-list)
-        (msg-hash (make-hash-table)))
-    (dolist (seq seqs)
-      (dolist (msg (mh-seq-msgs seq))
-        (push (car seq) (gethash msg msg-hash))))
-    (mh-iterate-on-range msg range
-      (loop for seq in (gethash msg msg-hash)
-            do (mh-add-sequence-notation msg (mh-internal-seq seq))))))
-
-(defvar mh-internal-seqs '(answered cur deleted forwarded printed))
-
-(defun mh-internal-seq (name)
-  "Return non-nil if NAME is the name of an internal MH-E sequence."
-  (or (memq name mh-internal-seqs)
-      (eq name mh-unseen-seq)
-      (and (mh-colors-in-use-p) mh-tick-seq (eq name mh-tick-seq))
-      (eq name mh-previous-seq)
-      (mh-folder-name-p name)))
-
-(defun mh-valid-seq-p (name)
-  "Return non-nil if NAME is a valid MH sequence name."
-  (and (symbolp name)
-       (string-match "^[a-zA-Z][a-zA-Z0-9]*$" (symbol-name name))))
-
-(defun mh-delete-msg-from-seq (range sequence &optional internal-flag)
-  "Delete RANGE from SEQUENCE.
-
-Check the documentation of `mh-interactive-range' to see how
-RANGE is read in interactive use.
-
-In a program, non-nil INTERNAL-FLAG means do not inform MH of the
-change."
-  (interactive (list (mh-interactive-range "Delete")
-                     (mh-read-seq-default "Delete from" t)
-                     nil))
-  (let ((entry (mh-find-seq sequence))
-        (user-sequence-flag (not (mh-internal-seq sequence)))
-        (folders-changed (list mh-current-folder))
-        (msg-list ()))
-    (when entry
-      (mh-iterate-on-range msg range
-        (push msg msg-list)
-        ;; Calling "mark" repeatedly takes too long. So we will pretend here
-        ;; that we are just modifying an internal sequence...
-        (when (memq msg (cdr entry))
-          (mh-remove-sequence-notation msg (not user-sequence-flag)))
-        (mh-delete-a-msg-from-seq msg sequence t))
-      ;; ... and here we will "mark" all the messages at one go.
-      (unless internal-flag (mh-undefine-sequence sequence msg-list))
-      (when (and mh-index-data (not internal-flag))
-        (setq folders-changed
-              (append folders-changed
-                      (mh-index-delete-from-sequence sequence msg-list))))
-      (when (and (eq sequence mh-unseen-seq) (mh-speed-flists-active-p))
-        (apply #'mh-speed-flists t folders-changed)))))
-
-(defun mh-catchup (range)
-  "Delete RANGE from the \"unseen\" sequence.
-
-Check the documentation of `mh-interactive-range' to see how
-RANGE is read in interactive use."
-  (interactive (list (mh-interactive-range "Catchup"
-                                           (cons (point-min) (point-max)))))
-  (mh-delete-msg-from-seq range mh-unseen-seq))
-
-(defun mh-delete-a-msg-from-seq (msg sequence internal-flag)
-  "Delete MSG from SEQUENCE.
-If INTERNAL-FLAG is non-nil, then do not inform MH of the
-change."
-  (let ((entry (mh-find-seq sequence)))
-    (when (and entry (memq msg (mh-seq-msgs entry)))
-      (if (not internal-flag)
-          (mh-undefine-sequence sequence (list msg)))
-      (setcdr entry (delq msg (mh-seq-msgs entry))))))
-
-(defun mh-undefine-sequence (seq msgs)
-  "Remove from the SEQ the list of MSGS."
-  (when (and (mh-valid-seq-p seq) msgs)
-    (apply #'mh-exec-cmd "mark" mh-current-folder "-delete"
-           "-sequence" (symbol-name seq) (mh-coalesce-msg-list msgs))))
-
-(defun mh-define-sequence (seq msgs)
-  "Define the SEQ to contain the list of MSGS.
-Do not mark pseudo-sequences or empty sequences.
-Signals an error if SEQ is an invalid name."
-  (if (and msgs
-           (mh-valid-seq-p seq)
-           (not (mh-folder-name-p seq)))
-      (save-excursion
-        (mh-exec-cmd-error nil "mark" mh-current-folder "-add" "-zero"
-                           "-sequence" (symbol-name seq)
-                           (mh-coalesce-msg-list msgs)))))
-
-(defun mh-seq-containing-msg (msg &optional include-internal-flag)
-  "Return a list of the sequences containing MSG.
-If INCLUDE-INTERNAL-FLAG non-nil, include MH-E internal sequences
-in list."
-  (let ((l mh-seq-list)
-        (seqs ()))
-    (while l
-      (and (memq msg (mh-seq-msgs (car l)))
-           (or include-internal-flag
-               (not (mh-internal-seq (mh-seq-name (car l)))))
-           (setq seqs (cons (mh-seq-name (car l)) seqs)))
-      (setq l (cdr l)))
-    seqs))
+;;; Sending Mail (:group 'mh-sending-mail)
+
+(defcustom mh-compose-forward-as-mime-flag t
+  "*Non-nil means that messages are forwarded as attachments.
+
+By default, this option is on which means that the forwarded
+messages are included as attachments. If you would prefer to
+forward your messages verbatim (as text, inline), then turn off
+this option. Forwarding messages verbatim works well for short,
+textual messages, but your recipient won't be able to view any
+non-textual attachments that were in the forwarded message. Be
+aware that if you have \"forw: -mime\" in your MH profile, then
+forwarded messages will always be included as attachments
+regardless of the settings of this option."
+  :type 'boolean
+  :group 'mh-sending-mail)
+
+(defcustom mh-compose-letter-function nil
+  "Invoked when starting a new draft.
+
+However, it is the last function called before you edit your
+message. The consequence of this is that you can write a function
+to write and send the message for you. This function is passed
+three arguments: the contents of the TO, SUBJECT, and CC header
+fields."
+  :type '(choice (const nil) function)
+  :group 'mh-sending-mail)
+
+(defcustom mh-compose-prompt-flag nil
+  "*Non-nil means prompt for header fields when composing a new draft."
+  :type 'boolean
+  :group 'mh-sending-mail)
+
+(defcustom mh-forward-subject-format "%s: %s"
+  "*Format string for forwarded message subject.
+
+This option is a string which includes two escapes (\"%s\"). The
+first \"%s\" is replaced with the sender of the original message,
+and the second one is replaced with the original \"Subject:\"."
+  :type 'string
+  :group 'mh-sending-mail)
+
+(defcustom mh-insert-x-mailer-flag t
+  "*Non-nil means append an \"X-Mailer:\" header field to the header.
+
+This header field includes the version of MH-E and Emacs that you
+are using. If you don't want to participate in our marketing, you
+can turn this option off."
+  :type 'boolean
+  :group 'mh-sending-mail)
+
+(defcustom mh-redist-full-contents-flag nil
+  "*Non-nil means the \"dist\" command needs entire letter for redistribution.
+
+This option must be turned on if \"dist\" requires the whole
+letter for redistribution, which is the case if \"send\" is
+compiled with the BERK option (which many people abhor). If you
+find that MH will not allow you to redistribute a message that
+has been redistributed before, turn off this option."
+  :type 'boolean
+  :group 'mh-sending-mail)
+
+(defcustom mh-reply-default-reply-to nil
+  "*Sets the person or persons to whom a reply will be sent.
+
+This option is set to \"Prompt\" by default so that you are
+prompted for the recipient of a reply. If you find that most of
+the time that you specify \"cc\" when you reply to a message, set
+this option to \"cc\". Other choices include \"from\", \"to\", or
+\"all\". You can always edit the recipients in the draft."
+  :type '(choice (const :tag "Prompt" nil)
+                 (const "from")
+                 (const "to")
+                 (const "cc")
+                 (const "all"))
+  :group 'mh-sending-mail)
+
+(defcustom mh-reply-show-message-flag t
+  "*Non-nil means the MH-Show buffer is displayed when replying.
+
+If you include the message automatically, you can hide the
+MH-Show buffer by turning off this option.
+
+See also `mh-reply'."
+  :type 'boolean
+  :group 'mh-sending-mail)
+
+
+
+;;; Sequences (:group 'mh-sequences)
+
+;; If `mh-unpropagated-sequences' becomes a defcustom, add the following to
+;; the docstring: "Additional sequences that should not to be preserved can be
+;; specified by setting `mh-unpropagated-sequences' appropriately." XXX
+
+(defcustom mh-refile-preserves-sequences-flag t
+  "*Non-nil means that sequences are preserved when messages are refiled.
+
+If a message is in any sequence (except \"Previous-Sequence:\"
+and \"cur\") when it is refiled, then it will still be in those
+sequences in the destination folder. If this behavior is not
+desired, then turn off this option."
+  :type 'boolean
+  :group 'mh-sequences)
+
+(defcustom mh-tick-seq 'tick
+  "The name of the MH sequence for ticked messages.
+
+You can customize this option if you already use the \"tick\"
+sequence for your own use. You can also disable all of the
+ticking functions by choosing the \"Disable Ticking\" item but
+there isn't much advantage to that."
+  :type '(choice (const :tag "Disable Ticking" nil)
+                 symbol)
+  :group 'mh-sequences)
+
+(defcustom mh-update-sequences-after-mh-show-flag t
+  "*Non-nil means flush MH sequences to disk after message is shown\\<mh-folder-mode-map>.
+
+Three sequences are maintained internally by MH-E and pushed out
+to MH when a message is shown. They include the sequence
+specified by your \"Unseen-Sequence:\" profile entry, \"cur\",
+and the sequence listed by the option `mh-tick-seq' which is
+\"tick\" by default. If you do not like this behavior, turn off
+this option. You can then update the state manually with the
+\\[mh-execute-commands], \\[mh-quit], or \\[mh-update-sequences]
+commands."
+  :type 'boolean
+  :group 'mh-sequences)
 
 
 
-;;; Build mh-folder-mode keymap:
-
-(suppress-keymap mh-folder-mode-map)
-
-;; Use defalias to make sure the documented primary key bindings
-;; appear in menu lists.
-(defalias 'mh-alt-show 'mh-show)
-(defalias 'mh-alt-refile-msg 'mh-refile-msg)
-(defalias 'mh-alt-send 'mh-send)
-(defalias 'mh-alt-visit-folder 'mh-visit-folder)
-
-;; Save the "b" binding for a future `back'. Maybe?
-(gnus-define-keys  mh-folder-mode-map
-  " "           mh-page-msg
-  "!"           mh-refile-or-write-again
-  "'"           mh-toggle-tick
-  ","           mh-header-display
-  "."           mh-alt-show
-  ";"           mh-toggle-mh-decode-mime-flag
-  ">"           mh-write-msg-to-file
-  "?"           mh-help
-  "E"           mh-extract-rejected-mail
-  "M"           mh-modify
-  "\177"        mh-previous-page
-  "\C-d"        mh-delete-msg-no-motion
-  "\t"          mh-index-next-folder
-  [backtab]     mh-index-previous-folder
-  "\M-\t"       mh-index-previous-folder
-  "\e<"         mh-first-msg
-  "\e>"         mh-last-msg
-  "\ed"         mh-redistribute
-  "\r"          mh-show
-  "^"           mh-alt-refile-msg
-  "c"           mh-copy-msg
-  "d"           mh-delete-msg
-  "e"           mh-edit-again
-  "f"           mh-forward
-  "g"           mh-goto-msg
-  "i"           mh-inc-folder
-  "k"           mh-delete-subject-or-thread
-  "m"           mh-alt-send
-  "n"           mh-next-undeleted-msg
-  "\M-n"        mh-next-unread-msg
-  "o"           mh-refile-msg
-  "p"           mh-previous-undeleted-msg
-  "\M-p"        mh-previous-unread-msg
-  "q"           mh-quit
-  "r"           mh-reply
-  "s"           mh-send
-  "t"           mh-toggle-showing
-  "u"           mh-undo
-  "v"           mh-index-visit-folder
-  "x"           mh-execute-commands
-  "|"           mh-pipe-msg)
-
-(gnus-define-keys (mh-folder-map "F" mh-folder-mode-map)
-  "?"           mh-prefix-help
-  "'"           mh-index-ticked-messages
-  "S"           mh-sort-folder
-  "c"           mh-catchup
-  "f"           mh-alt-visit-folder
-  "k"           mh-kill-folder
-  "l"           mh-list-folders
-  "n"           mh-index-new-messages
-  "o"           mh-alt-visit-folder
-  "p"           mh-pack-folder
-  "q"           mh-index-sequenced-messages
-  "r"           mh-rescan-folder
-  "s"           mh-search
-  "u"           mh-undo-folder
-  "v"           mh-visit-folder)
-
-(define-key mh-folder-mode-map "I" mh-inc-spool-map)
-
-(gnus-define-keys (mh-junk-map "J" mh-folder-mode-map)
-  "?"           mh-prefix-help
-  "b"           mh-junk-blacklist
-  "w"           mh-junk-whitelist)
-
-(gnus-define-keys (mh-ps-print-map "P" mh-folder-mode-map)
-  "?"           mh-prefix-help
-  "C"           mh-ps-print-toggle-color
-  "F"           mh-ps-print-toggle-faces
-  "f"           mh-ps-print-msg-file
-  "l"		mh-print-msg
-  "p"           mh-ps-print-msg)
-
-(gnus-define-keys (mh-sequence-map "S" mh-folder-mode-map)
-  "'"           mh-narrow-to-tick
-  "?"           mh-prefix-help
-  "d"           mh-delete-msg-from-seq
-  "k"           mh-delete-seq
-  "l"           mh-list-sequences
-  "n"           mh-narrow-to-seq
-  "p"           mh-put-msg-in-seq
-  "s"           mh-msg-is-in-seq
-  "w"           mh-widen)
-
-(gnus-define-keys (mh-thread-map "T" mh-folder-mode-map)
-  "?"           mh-prefix-help
-  "u"           mh-thread-ancestor
-  "p"           mh-thread-previous-sibling
-  "n"           mh-thread-next-sibling
-  "t"           mh-toggle-threads
-  "d"           mh-thread-delete
-  "o"           mh-thread-refile)
-
-(gnus-define-keys (mh-limit-map "/" mh-folder-mode-map)
-  "'"           mh-narrow-to-tick
-  "?"           mh-prefix-help
-  "c"           mh-narrow-to-cc
-  "g"           mh-narrow-to-range
-  "m"           mh-narrow-to-from
-  "s"           mh-narrow-to-subject
-  "t"           mh-narrow-to-to
-  "w"           mh-widen)
-
-(gnus-define-keys (mh-extract-map "X" mh-folder-mode-map)
-  "?"           mh-prefix-help
-  "s"           mh-store-msg            ;shar
-  "u"           mh-store-msg)           ;uuencode
-
-(gnus-define-keys (mh-digest-map "D" mh-folder-mode-map)
-  " "           mh-page-digest
-  "?"           mh-prefix-help
-  "\177"        mh-page-digest-backwards
-  "b"           mh-burst-digest)
-
-(gnus-define-keys (mh-mime-map "K" mh-folder-mode-map)
-  "?"           mh-prefix-help
-  "a"           mh-mime-save-parts
-  "e"           mh-display-with-external-viewer
-  "i"           mh-folder-inline-mime-part
-  "o"           mh-folder-save-mime-part
-  "t"           mh-toggle-mime-buttons
-  "v"           mh-folder-toggle-mime-part
-  "\t"          mh-next-button
-  [backtab]     mh-prev-button
-  "\M-\t"       mh-prev-button)
-
-(cond
- (mh-xemacs-flag
-  (define-key mh-folder-mode-map [button2] 'mh-show-mouse))
- (t
-  (define-key mh-folder-mode-map [mouse-2] 'mh-show-mouse)))
-
-;; "C-c /" prefix is used in mh-folder-mode by pgp.el and mailcrypt
+;;; Reading Your Mail (:group 'mh-show)
+
+(defcustom mh-bury-show-buffer-flag t
+  "*Non-nil means show buffer is buried.
+
+One advantage of not burying the show buffer is that one can
+delete the show buffer more easily in an electric buffer list
+because of its proximity to its associated MH-Folder buffer. Try
+running \\[electric-buffer-list] to see what I mean."
+  :type 'boolean
+  :group 'mh-show)
+
+(defcustom mh-clean-message-header-flag t
+  "*Non-nil means remove extraneous header fields.
+
+See also `mh-invisible-header-fields-default' and
+`mh-invisible-header-fields'."
+  :type 'boolean
+  :group 'mh-show)
+
+(defcustom mh-decode-mime-flag (not (not (locate-library "mm-decode")))
+  "*Non-nil means attachments are handled\\<mh-folder-mode-map>.
+
+MH-E can handle attachments as well if the Gnus `mm-decode'
+library is present. If so, this option will be on. Otherwise,
+you'll see the MIME body parts rather than text or attachments.
+There isn't much point in turning off this option; however, you
+can inspect it if it appears that the body parts are not being
+interpreted correctly or toggle it with the command
+\\[mh-toggle-mh-decode-mime-flag] to view the raw message.
+
+This option also controls the display of quoted-printable
+messages and other graphical widgets. See the options
+`mh-graphical-smileys-flag' and `mh-graphical-emphasis-flag'."
+  :type 'boolean
+  :group 'mh-show)
+
+(defcustom mh-display-buttons-for-alternatives-flag nil
+  "*Non-nil means display buttons for all alternative attachments.
+
+Sometimes, a mail program will produce multiple alternatives of
+the attachment in increasing degree of faithfulness to the
+original content. By default, only the preferred alternative is
+displayed. If this option is on, then the preferred part is shown
+inline and buttons are shown for each of the other alternatives."
+  :type 'boolean
+  :group 'mh-show)
+
+(defcustom mh-display-buttons-for-inline-parts-flag nil
+  "*Non-nil means display buttons for all inline attachments\\<mh-folder-mode-map>.
+
+The sender can request that attachments should be viewed inline so
+that they do not really appear like an attachment at all to the
+reader. Most of the time, this is desirable, so by default MH-E
+suppresses the buttons for inline attachments. On the other hand, you
+may receive code or HTML which the sender has added to his message as
+inline attachments so that you can read them in MH-E. In this case, it
+is useful to see the buttons so that you know you don't have to cut
+and paste the code into a file; you can simply save the attachment.
+
+If you want to make the buttons visible for inline attachments, you
+can use the command \\[mh-toggle-mime-buttons] to toggle the
+visibility of these buttons. You can turn on these buttons permanently
+by turning on this option.
+
+MH-E cannot display all attachments inline however. It can display
+text (including HTML) and images."
+  :type 'boolean
+  :group 'mh-show)
+
+(defcustom mh-do-not-confirm-flag nil
+  "*Non-nil means non-reversible commands do not prompt for confirmation.
+
+Commands such as `mh-pack-folder' prompt to confirm whether to
+process outstanding moves and deletes or not before continuing.
+Turning on this option means that these actions will be
+performed--which is usually desired but cannot be
+retracted--without question."
+  :type 'boolean
+  :group 'mh-show)
+
+(defcustom mh-fetch-x-image-url nil
+  "*Control fetching of \"X-Image-URL:\" header field image.
+
+Ths option controls the fetching of the \"X-Image-URL:\" header
+field image with the following values:
+
+Ask Before Fetching
+     You are prompted before the image is fetched. MH-E will
+     remember your reply and will either use the already fetched
+     image the next time the same URL is encountered or silently
+     skip it if you didn't fetch it the first time. This is a
+     good setting.
+
+Never Fetch
+     Images are never fetched and only displayed if they are
+     already present in the cache. This is the default.
+
+There isn't a value of \"Always Fetch\" for privacy and DOS (denial of
+service) reasons. For example, fetching a URL can tip off a spammer
+that you've read his email (which is why you shouldn't blindly answer
+yes if you've set this option to \"Ask Before Fetching\"). Someone may
+also flood your network and fill your disk drive by sending a torrent
+of messages, each specifying a unique URL to a very large file.
+
+The cache of images is found in the directory \".mhe-x-image-cache\"
+within your MH directory. You can add your own face to the \"From:\"
+field too. See Info node `(mh-e)Picture'.
+
+This setting only has effect if the option `mh-show-use-xface-flag' is
+turned on."
+
+  :type '(choice (const :tag "Ask Before Fetching" ask)
+                 (const :tag "Never Fetch" nil))
+  :group 'mh-show)
+
+(defcustom mh-graphical-smileys-flag t
+  "*Non-nil means graphical smileys are displayed.
+
+It is a long standing custom to inject body language using a
+cornucopia of punctuation, also known as the \"smileys\". MH-E
+can render these as graphical widgets if this option is turned
+on, which it is by default. Smileys include patterns such as :-)
+and ;-).
+
+This option is disabled if the option `mh-decode-mime-flag' is
+turned off."
+  :type 'boolean
+  :group 'mh-show)
+
+(defcustom mh-graphical-emphasis-flag t
+  "*Non-nil means graphical emphasis is displayed.
+
+A few typesetting features are indicated in ASCII text with
+certain characters. If your terminal supports it, MH-E can render
+these typesetting directives naturally if this option is turned
+on, which it is by default. For example, _underline_ will be
+underlined, *bold* will appear in bold, /italics/ will appear in
+italics, and so on. See the option `gnus-emphasis-alist' for the
+whole list.
+
+This option is disabled if the option `mh-decode-mime-flag' is
+turned off."
+  :type 'boolean
+  :group 'mh-show)
+
+(defcustom mh-highlight-citation-style 'gnus
+  "Style for highlighting citations.
+
+If the sender of the message has cited other messages in his
+message, then MH-E will highlight these citations to emphasize
+the sender's actual response. This option can be customized to
+change the highlighting style. The \"Multicolor\" method uses a
+different color for each indentation while the \"Monochrome\"
+method highlights all citations in red. To disable highlighting
+of citations entirely, choose \"None\"."
+  :type '(choice (const :tag "Multicolor" gnus)
+                 (const :tag "Monochrome" font-lock)
+                 (const :tag "None" nil))
+  :group 'mh-show)
+
+;; Keep fields alphabetized. Mention source, if known.
+(defvar mh-invisible-header-fields-internal
+  '("Approved:"
+    "Autoforwarded:"
+    "Bestservhost:"
+    "Cancel-Lock:"                      ; NNTP posts
+    "Content-"                          ; RFC 2045
+    "Delivered-To:"              ; Egroups/yahoogroups mailing list manager
+    "Delivery-Date:"                    ; MH
+    "Delivery:"
+    "DomainKey-Signature:"              ;http://antispam.yahoo.com/domainkeys
+    "Encoding:"
+    "Envelope-to:"
+    "Errors-To:"
+    "Face:"                             ; Gnus Face header
+    "Forwarded:"                        ; MH
+    "From "                             ; sendmail
+    "Importance:"                       ; MS Outlook
+    "In-Reply-To:"                      ; MH
+    "Lines:"
+    "List-"                             ; Mailman mailing list manager
+    "List-"                             ; Unknown mailing list managers
+    "List-Subscribe:"                   ; Unknown mailing list managers
+    "List-Unsubscribe:"                 ; Unknown mailing list managers
+    "Mail-from:"                        ; MH
+    "Mailing-List:"              ; Egroups/yahoogroups mailing list manager
+    "Message-Id:"                       ; RFC 822
+    "Mime-Version"                      ; RFC 2045
+    "NNTP-"                             ; News
+    "Old-Return-Path:"
+    "Original-Encoded-Information-Types:"  ; X400
+    "Original-Lines:"                   ; mail to news
+    "Original-NNTP-"                    ; mail to news
+    "Original-Newsgroups:"              ; mail to news
+    "Original-Path:"                    ; mail to news
+    "Original-Received:"                ; mail to news
+    "Original-To:"                      ; mail to news
+    "Original-X-"                       ; mail to news
+    "Originator:"
+    "P1-Content-Type:"                  ; X400
+    "P1-Message-Id:"                    ; X400
+    "P1-Recipient:"                     ; X400
+    "Path:"
+    "Precedence:"
+    "Prev-Resent"                       ; MH
+    "Priority:"
+    "Received:"                         ; RFC 822
+    "Received-SPF:"                     ; Gmail
+    "References:"
+    "Remailed-"                         ; MH
+    "Replied:"                          ; MH
+    "Resent"                            ; MH
+    "Return-Path:"                      ; RFC 822
+    "Sensitivity:"                      ; MS Outlook
+    "Status:"                           ; sendmail
+    "Thread-"
+    "Ua-Content-Id:"                    ; X400
+;;  "User-Agent:"                       ; Similar to X-Mailer, so display it.
+    "Via:"                              ; MH
+    "X-Abuse-Info:"
+    "X-Abuse-and-DMCA-"
+    "X-Accept-Language:"
+    "X-Accept-Language:"                ; Netscape/Mozilla
+    "X-Ack:"
+    "X-Administrivia-To:"
+    "X-AntiAbuse:"                      ; cPanel
+    "X-Apparently-From:"                ; MS Outlook
+    "X-Apparently-To:"           ; Egroups/yahoogroups mailing list manager
+    "X-Authentication-Warning:"         ; sendmail
+    "X-Beenthere:"                      ; Mailman mailing list manager
+    "X-Bogosity:"                       ; bogofilter
+    "X-Bugzilla-*"                      ; Bugzilla
+    "X-Complaints-To:"
+    "X-ContentStamp:"                   ; NetZero
+    "X-Cron-Env:"
+    "X-DMCA"
+    "X-Delivered"
+    "X-ELNK-Trace:"                     ; Earthlink mailer
+    "X-Envelope-Date:"                  ; GNU mailutils
+    "X-Envelope-From:"
+    "X-Envelope-Sender:"
+    "X-Envelope-To:"
+    "X-Evolution:"                      ; Evolution mail client
+    "X-Face:"
+    "X-Folder:"                         ; Spam
+    "X-From-Line"
+    "X-Gmail-"                          ; Gmail
+    "X-Gnus-Mail-Source:"               ; gnus
+    "X-Greylist:"                       ; milter-greylist-1.2.1
+    "X-Habeas-SWE-1:"                   ; Spam
+    "X-Habeas-SWE-2:"                   ; Spam
+    "X-Habeas-SWE-3:"                   ; Spam
+    "X-Habeas-SWE-4:"                   ; Spam
+    "X-Habeas-SWE-5:"                   ; Spam
+    "X-Habeas-SWE-6:"                   ; Spam
+    "X-Habeas-SWE-7:"                   ; Spam
+    "X-Habeas-SWE-8:"                   ; Spam
+    "X-Habeas-SWE-9:"                   ; Spam
+    "X-Info:"                           ; NTMail
+    "X-Juno-"                           ; Juno
+    "X-List-Host:"                      ; Unknown mailing list managers
+    "X-List-Subscribe:"                 ; Unknown mailing list managers
+    "X-List-Unsubscribe:"               ; Unknown mailing list managers
+    "X-Listprocessor-"                  ; ListProc(tm) by CREN
+    "X-Listserver:"                     ; Unknown mailing list managers
+    "X-Loop:"                           ; Unknown mailing list managers
+    "X-Lumos-SenderID:"                 ; Roving ConstantContact
+    "X-MAIL-INFO:"                      ; NetZero
+    "X-MHE-Checksum"                    ; Checksum added during index search
+    "X-MIME-Autoconverted:"             ; sendmail
+    "X-MIMETrack:"
+    "X-MS-"                             ; MS Outlook
+    "X-MailScanner"                     ; ListProc(tm) by CREN
+    "X-Mailing-List:"                   ; Unknown mailing list managers
+    "X-Mailman-Version:"                ; Mailman mailing list manager
+    "X-Majordomo:"                      ; Majordomo mailing list manager
+    "X-Message-Id"
+    "X-MessageWall-Score:"              ; Unknown mailing list manager, AUC TeX
+    "X-MimeOLE:"                        ; MS Outlook
+    "X-Mms-"                            ; T-Mobile pictures
+    "X-Mozilla-Status:"                 ; Netscape/Mozilla
+    "X-Msmail-"                         ; MS Outlook
+    "X-NAI-Spam-"                       ; Network Associates Inc. SpamKiller
+    "X-News:"                           ; News
+    "X-No-Archive:"
+    "X-Notes-Item:"                     ; Lotus Notes Domino structured header
+    "X-OperatingSystem:"
+    ;;"X-Operator:"                     ; Similar to X-Mailer, so display it
+    "X-Orcl-Content-Type:"
+    "X-Original-Complaints-To:"
+    "X-Original-Date:"                  ; SourceForge mailing list manager
+    "X-Original-To:"
+    "X-Original-Trace:"
+    "X-OriginalArrivalTime:"            ; Hotmail
+    "X-Originating-IP:"                 ; Hotmail
+    "X-Postfilter:"
+    "X-Priority:"                       ; MS Outlook
+    "X-Qotd-"                           ; User added
+    "X-RM"
+    "X-Received-Date:"
+    "X-Received:"
+    "X-Request-"
+    "X-Return-Path-Hint:"               ; Roving ConstantContact
+    "X-Roving-*"                        ; Roving ConstantContact
+    "X-SBClass:"                        ; Spam
+    "X-SBNote:"                         ; Spam
+    "X-SBPass:"                         ; Spam
+    "X-SBRule:"                         ; Spam
+    "X-SMTP-"
+    "X-Scanned-By"
+    "X-Sender:"
+    "X-Server-Date:"
+    "X-Server-Uuid:"
+    "X-Sieve:"                          ; Sieve filtering
+    "X-Source"
+    "X-Spam-"                           ; Spamassassin
+    "X-SpamBouncer:"                    ; Spam
+    "X-Status"
+    "X-Submissions-To:"
+    "X-Telecom-Digest"
+    "X-Trace:"
+    "X-UID"
+    "X-UIDL:"
+    "X-UNTD-"                           ; NetZero
+    "X-USANET-"                         ; usa.net
+    "X-UserInfo1:"
+    "X-VSMLoop:"                        ; NTMail
+    "X-Virus-Scanned"                   ; amavisd-new
+    "X-Vms-To:"
+    "X-WebTV-Signature:"
+    "X-Wss-Id:"                         ; Worldtalk gateways
+    "X-Yahoo"
+    "X-eGroups-"                 ; Egroups/yahoogroups mailing list manager
+    "X-pgp:"
+    "X-submission-address:"
+    "X400-"                             ; X400
+    "Xref:")
+  "List of default header fields that are not to be shown.
+
+Do not alter this variable directly. Instead, add entries from
+here that you would like to be displayed in
+`mh-invisible-header-fields-default' and add entries to hide in
+`mh-invisible-header-fields'.")
+
+(eval-and-compile
+  (unless (fboundp 'mh-invisible-headers)
+    (defun mh-invisible-headers ()
+      "Temporary definition.
+Real definition, below, uses variables that aren't defined yet."
+      nil)))
+
+(defvar mh-delay-invisible-header-generation-flag t
+  "Non-nil means to delay the generation of invisible header fields.
+Because the function `mh-invisible-headers' uses both
+`mh-invisible-header-fields' and `mh-invisible-header-fields', it
+cannot be run until both variables have been initialized.")
+
+(defcustom mh-invisible-header-fields nil
+  "*Additional header fields to hide.
+
+Header fields that you would like to hide that aren't listed in
+`mh-invisible-header-fields-default' can be added to this option
+with a couple of caveats. Regular expressions are not allowed.
+Unique fields should have a \":\" suffix; otherwise, the element
+can be used to render invisible an entire class of fields that
+start with the same prefix. If you think a header field should be
+generally ignored, report a bug (see URL
+`https://sourceforge.net/tracker/?group_id=13357&atid=113357').
+
+See also `mh-clean-message-header-flag'."
+
+  :type '(repeat (string :tag "Header field"))
+  :set (lambda (symbol value)
+         (set-default symbol value)
+         (mh-invisible-headers))
+  :group 'mh-show)
+
+(defcustom mh-invisible-header-fields-default nil
+  "*List of hidden header fields.
+
+The header fields listed in this option are hidden, although you
+can check off any field that you would like to see.
+
+Header fields that you would like to hide that aren't listed can
+be added to the option `mh-invisible-header-fields'.
+
+See also `mh-clean-message-header-flag'."
+  :type `(set ,@(mapcar (lambda (x) `(const ,x))
+                        mh-invisible-header-fields-internal))
+  :set (lambda (symbol value)
+         (set-default symbol value)
+         (mh-invisible-headers))
+  :group 'mh-show)
+
+(defvar mh-invisible-header-fields-compiled nil
+  "*Regexp matching lines in a message header that are not to be shown.
+Do not alter this variable directly. Instead, customize
+`mh-invisible-header-fields-default' checking for fields normally
+hidden that you wish to display, and add extra entries to hide in
+`mh-invisible-header-fields'.")
+
+(defun mh-invisible-headers ()
+  "Make or remake the variable `mh-invisible-header-fields-compiled'.
+Done using `mh-invisible-header-fields-internal' as input, from
+which entries from `mh-invisible-header-fields-default' are
+removed and entries from `mh-invisible-header-fields' are added."
+  (let ((fields mh-invisible-header-fields-internal))
+    (when mh-invisible-header-fields-default
+      ;; Remove entries from `mh-invisible-header-fields-default'
+      (setq fields
+            (loop for x in fields
+                  unless (member x mh-invisible-header-fields-default)
+                  collect x)))
+    (when (and (boundp 'mh-invisible-header-fields)
+               mh-invisible-header-fields)
+      (dolist (x mh-invisible-header-fields)
+        (unless (member x fields) (setq fields (cons x fields)))))
+    (if fields
+        (setq mh-invisible-header-fields-compiled
+              (concat
+               "^"
+               ;; workaround for insufficient default
+               (let ((max-specpdl-size 1000))
+                 (regexp-opt fields t))))
+      (setq mh-invisible-header-fields-compiled nil))))
+
+;; Compile invisible header fields.
+(mh-invisible-headers)
+
+(defcustom mh-lpr-command-format "lpr -J '%s'"
+  "*Command used to print\\<mh-folder-mode-map>.
+
+This option contains the Unix command line which performs the
+actual printing for the \\[mh-print-msg] command. The string can
+contain one escape, \"%s\", which is replaced by the name of the
+folder and the message number and is useful for print job names.
+I use \"mpage -h'%s' -b Letter -H1of -mlrtb -P\" which produces a
+nice header and adds a bit of margin so the text fits within my
+printer's margins.
+
+This options is not used by the commands \\[mh-ps-print-msg] or
+\\[mh-ps-print-msg-file]."
+  :type 'string
+  :group 'mh-show)
+
+(defcustom mh-max-inline-image-height nil
+  "*Maximum inline image height if \"Content-Disposition:\" is not present.
+
+Some older mail programs do not insert this needed plumbing to
+tell MH-E whether to display the attachments inline or not. If
+this is the case, MH-E will display these images inline if they
+are smaller than the window. However, you might want to allow
+larger images to be displayed inline. To do this, you can change
+the options `mh-max-inline-image-width' and
+`mh-max-inline-image-height' from their default value of zero to
+a large number. The size of your screen is a good choice for
+these numbers."
+  :type '(choice (const nil) integer)
+  :group 'mh-show)
+
+(defcustom mh-max-inline-image-width nil
+  "*Maximum inline image width if \"Content-Disposition:\" is not present.
+
+Some older mail programs do not insert this needed plumbing to
+tell MH-E whether to display the attachments inline or not. If
+this is the case, MH-E will display these images inline if they
+are smaller than the window. However, you might want to allow
+larger images to be displayed inline. To do this, you can change
+the options `mh-max-inline-image-width' and
+`mh-max-inline-image-height' from their default value of zero to
+a large number. The size of your screen is a good choice for
+these numbers."
+  :type '(choice (const nil) integer)
+  :group 'mh-show)
+
+(defcustom mh-mhl-format-file nil
+  "*Specifies the format file to pass to the \"mhl\" program.
+
+Normally MH-E takes care of displaying messages itself (rather than
+calling an MH program to do the work). If you'd rather have \"mhl\"
+display the message (within MH-E), change this option from its default
+value of \"Use Default mhl Format (Printing Only)\".
+
+You can set this option to \"Use Default mhl Format\" to get the same
+output as you would get if you ran \"mhl\" from the shell.
+
+If you have a format file that you want MH-E to use, you can set this
+option to \"Specify an mhl Format File\" and enter the name of your
+format file. Your format file should specify a non-zero value for
+\"overflowoffset\" to allow MH-E to parse the header. Note that
+\"mhl\" is always used for printing and forwarding; in this case, the
+value of this option is consulted if you have specified a format
+file."
+  :type '(choice (const :tag "Use Default mhl Format (Printing Only)" nil)
+                 (const :tag "Use Default mhl Format" t)
+                 (file :tag "Specify an mhl Format File"))
+  :group 'mh-show)
+
+(defcustom mh-mime-save-parts-default-directory t
+  "Default directory to use for \\<mh-folder-mode-map>\\[mh-mime-save-parts].
+
+The default value for this option is \"Prompt Always\" so that
+you are always prompted for the directory in which to save the
+attachments. However, if you usually use the same directory
+within a session, then you can set this option to \"Prompt the
+First Time\" to avoid the prompt each time. you can make this
+directory permanent by choosing \"Directory\" and entering the
+directory's name."
+  :type '(choice (const :tag "Prompt the First Time" nil)
+                 (const :tag "Prompt Always" t)
+                 directory)
+  :group 'mh-show)
+
+(defcustom mh-print-background-flag nil
+  "*Non-nil means messages should be printed in the background\\<mh-folder-mode-map>.
+
+Normally messages are printed in the foreground. If this is slow on
+your system, you may elect to turn off this option to print in the
+background.
+
+WARNING: If you do this, do not delete the message until it is printed
+or else the output may be truncated.
+
+This option is not used by the commands \\[mh-ps-print-msg] or
+\\[mh-ps-print-msg-file]."
+  :type 'boolean
+  :group 'mh-show)
+
+(defcustom mh-show-maximum-size 0
+  "*Maximum size of message (in bytes) to display automatically.
+
+This option provides an opportunity to skip over large messages
+which may be slow to load. The default value of 0 means that all
+message are shown regardless of size."
+  :type 'integer
+  :group 'mh-show)
+
+(defcustom mh-show-use-goto-addr-flag (and (boundp 'goto-address-highlight-p)
+                                           goto-address-highlight-p)
+  "*Non-nil means highlight URLs and email addresses\\<goto-address-highlight-keymap>.
+
+To send a message using the highlighted email address or to view
+the web page for the highlighted URL, use the middle mouse button
+or \\[goto-address-at-point].
+
+See Info node `(mh-e)Sending Mail' to see how to configure Emacs
+to send the message using MH-E.
+
+The default value of this option comes from the value of
+`goto-address-highlight-p'."
+  :type 'boolean
+  :group 'mh-show)
+
+(defcustom mh-show-use-xface-flag (>= emacs-major-version 21)
+  "*Non-nil means display face images in MH-show buffers.
+
+MH-E can display the content of \"Face:\", \"X-Face:\", and
+\"X-Image-URL:\" header fields. If any of these fields occur in the
+header of your message, the sender's face will appear in the \"From:\"
+header field. If more than one of these fields appear, then the first
+field found in the order \"Face:\", \"X-Face:\", and \"X-Image-URL:\"
+will be used.
+
+The option `mh-show-use-xface-flag' is used to turn this feature on
+and off. This feature will be turned on by default if your system
+supports it.
+
+The first header field used, if present, is the Gnus-specific
+\"Face:\" field. The \"Face:\" field appeared in GNU Emacs 21 and
+XEmacs. For more information, see URL
+`http://quimby.gnus.org/circus/face/'. Next is the traditional
+\"X-Face:\" header field. The display of this field requires the
+\"uncompface\" program (see URL
+`ftp://ftp.cs.indiana.edu/pub/faces/compface/compface.tar.z'). Recent
+versions of XEmacs have internal support for \"X-Face:\" images. If
+your version of XEmacs does not, then you'll need both \"uncompface\"
+and the x-face package (see URL `ftp://ftp.jpl.org/pub/elisp/').
+
+Finally, MH-E will display images referenced by the \"X-Image-URL:\"
+header field if neither the \"Face:\" nor the \"X-Face:\" fields are
+present. The display of the images requires \"wget\" (see URL
+`http://www.gnu.org/software/wget/wget.html'), \"fetch\", or \"curl\"
+to fetch the image and the \"convert\" program from the ImageMagick
+suite (see URL `http://www.imagemagick.org/'). Of the three header
+fields this is the most efficient in terms of network usage since the
+image doesn't need to be transmitted with every single mail.
+
+The option `mh-fetch-x-image-url' controls the fetching of the
+\"X-Image-URL:\" header field image."
+  :type 'boolean
+  :group 'mh-show)
+
+(defcustom mh-store-default-directory nil
+  "*Default directory for \\<mh-folder-mode-map>\\[mh-store-msg].
+
+If you would like to change the initial default directory,
+customize this option, change the value from \"Current\" to
+\"Directory\", and then enter the name of the directory for storing
+the content of these messages."
+  :type '(choice (const :tag "Current" nil)
+                 directory)
+  :group 'mh-show)
+
+(defcustom mh-summary-height nil
+  "*Number of lines in MH-Folder buffer (including the mode line).
+
+The default value of this option is \"Automatic\" which means
+that the MH-Folder buffer will maintain the same proportional
+size if the frame is resized. If you'd prefer a fixed height,
+then choose the \"Fixed Size\" option and enter the number of
+lines you'd like to see."
+  :type '(choice (const :tag "Automatic" nil)
+                 (integer :tag "Fixed Size"))
+  :group 'mh-show)
 
 
 
-;;; Help Messages
-
-;; If you add a new prefix, add appropriate text to the nil key.
-;;
-;; In general, messages are grouped logically. Taking the main commands for
-;; example, the first line is "ways to view messages," the second line is
-;; "things you can do with messages", and the third is "composing" messages.
-;;
-;; When adding a new prefix, ensure that the help message contains "what" the
-;; prefix is for. For example, if the word "folder" were not present in the
-;; "F" entry, it would not be clear what these commands operated upon.
-(defvar mh-help-messages
-  '((nil "[i]nc, [.]show, [,]show all, [n]ext, [p]revious,\n"
-         "[d]elete, [o]refile, e[x]ecute,\n"
-         "[s]end, [r]eply,\n"
-         "[;]toggle MIME decoding.\n"
-         "Prefix characters:\n [F]older, [S]equence, [J]unk, MIME [K]eys,"
-         "\n [T]hread, [/]limit, e[X]tract, [D]igest, [I]nc spools.")
-
-    (?F "[l]ist; [v]isit folder;\n"
-        "[n]ew messages; [']ticked messages; [s]earch;\n"
-        "[p]ack; [S]ort; [r]escan; [k]ill")
-    (?P "[p]rint message to [f]ile; old-style [l]pr printing;\n"
-        "Toggle printing of [C]olors, [F]aces")
-    (?S "[p]ut message in sequence, [n]arrow, [']narrow to ticked, [w]iden,\n"
-        "[s]equences, [l]ist,\n"
-        "[d]elete message from sequence, [k]ill sequence")
-    (?T "[t]oggle, [d]elete, [o]refile thread")
-    (?/ "Limit to [c]c, ran[g]e, fro[m], [s]ubject, [t]o; [w]iden")
-    (?X "un[s]har, [u]udecode message")
-    (?D "[b]urst digest")
-    (?K "[v]iew, [i]nline, [o]utput/save MIME part; save [a]ll parts; \n"
-        "[TAB] next; [SHIFT-TAB] previous")
-    (?J "[b]lacklist, [w]hitelist message"))
-  "Key binding cheat sheet.
-
-This is an associative array which is used to show the most common commands.
-The key is a prefix char. The value is one or more strings which are
-concatenated together and displayed in the minibuffer if ? is pressed after
-the prefix character. The special key nil is used to display the
-non-prefixed commands.
-
-The substitutions described in `substitute-command-keys' are performed as
-well.")
+;;; The Speedbar (:group 'mh-speedbar)
+
+(defcustom mh-speed-update-interval 60
+  "Time between speedbar updates in seconds.
+Set to 0 to disable automatic update."
+  :type 'integer
+  :group 'mh-speedbar)
+
+
+
+;;; Threading (:group 'mh-thread)
+
+(defcustom mh-show-threads-flag nil
+  "*Non-nil means new folders start in threaded mode.
+
+Threading large number of messages can be time consuming so this
+option is turned off by default. If you turn this option on, then
+threading will be done only if the number of messages being
+threaded is less than `mh-large-folder'."
+  :type 'boolean
+  :group 'mh-thread)
+
+
+
+;;; The Tool Bar (:group 'mh-tool-bar)
+
+;; mh-tool-bar-folder-buttons and mh-tool-bar-letter-buttons defined
+;; dynamically in mh-tool-bar.el.
+
+(defcustom mh-tool-bar-search-function 'mh-search
+  "*Function called by the tool bar search button.
+
+By default, this is set to `mh-search'. You can also choose
+\"Other Function\" from the \"Value Menu\" and enter a function
+of your own choosing."
+  :type '(choice (const mh-search)
+                 (function :tag "Other Function"))
+  :group 'mh-tool-bar)
+
+;; XEmacs has a couple of extra customizations...
+(mh-do-in-xemacs
+  (defcustom mh-xemacs-use-tool-bar-flag mh-xemacs-has-tool-bar-flag
+    "*If non-nil, use tool bar.
+
+This option controls whether to show the MH-E icons at all. By
+default, this option is turned on if the window system supports
+tool bars. If your system doesn't support tool bars, then you
+won't be able to turn on this option."
+    :type 'boolean
+    :group 'mh-tool-bar
+    :set (lambda (symbol value)
+           (if (and (eq value t)
+                    (not mh-xemacs-has-tool-bar-flag))
+               (error "Tool bar not supported"))
+           (set-default symbol value)))
+
+  (defcustom mh-xemacs-tool-bar-position nil
+    "*Tool bar location.
+
+This option controls the placement of the tool bar along the four
+edges of the frame. You can choose from one of \"Same As Default
+Tool Bar\", \"Top\", \"Bottom\", \"Left\", or \"Right\". If this
+variable is set to anything other than \"Same As Default Tool
+Bar\" and the default tool bar is in a different location, then
+two tool bars will be displayed: the MH-E tool bar and the
+default tool bar."
+    :type '(radio (const :tag "Same As Default Tool Bar" :value nil)
+                  (const :tag "Top" :value top)
+                  (const :tag "Bottom" :value bottom)
+                  (const :tag "Left" :value left)
+                  (const :tag "Right" :value right))
+    :group 'mh-tool-bar))
+
+
+
+;;; Hooks (:group 'mh-hooks + group where hook described)
+
+(defcustom mh-after-commands-processed-hook nil
+  "Hook run by \\<mh-folder-mode-map>\\[mh-execute-commands] after performing outstanding refile and delete requests.
+
+Variables that are useful in this hook include
+`mh-folders-changed', which lists which folders were affected by
+deletes and refiles. This list will always include the current
+folder, which is also available in `mh-current-folder'."
+  :type 'hook
+  :group 'mh-hooks
+  :group 'mh-folder)
+
+(defcustom mh-alias-reloaded-hook nil
+  "Hook run by `mh-alias-reload' after loading aliases."
+  :type 'hook
+  :group 'mh-hooks
+  :group 'mh-alias)
+
+(defcustom mh-before-commands-processed-hook nil
+  "Hook run by \\<mh-folder-mode-map>\\[mh-execute-commands] before performing outstanding refile and delete requests.
+
+Variables that are useful in this hook include `mh-delete-list'
+and `mh-refile-list' which can be used to see which changes will
+be made to the current folder, `mh-current-folder'."
+  :type 'hook
+  :group 'mh-hooks
+  :group 'mh-folder)
+
+(defcustom mh-before-quit-hook nil
+  "Hook run by \\<mh-folder-mode-map>\\[mh-quit] before quitting MH-E.
+
+This hook is called before the quit occurs, so you might use it
+to perform any MH-E operations; you could perform some query and
+abort the quit or call `mh-execute-commands', for example.
+
+See also `mh-quit-hook'."
+  :type 'hook
+  :group 'mh-hooks
+  :group 'mh-folder)
+
+(defcustom mh-before-send-letter-hook nil
+  "Hook run at the beginning of the \\<mh-letter-mode-map>\\[mh-send-letter] command.
+
+For example, if you want to check your spelling in your message
+before sending, add the `ispell-message' function."
+  :type 'hook
+  :options '(ispell-message)
+  :group 'mh-hooks
+  :group 'mh-letter)
+
+(defcustom mh-delete-msg-hook nil
+  "Hook run by \\<mh-letter-mode-map>\\[mh-delete-msg] after marking each message for deletion.
+
+For example, a past maintainer of MH-E used this once when he
+kept statistics on his mail usage."
+  :type 'hook
+  :group 'mh-hooks
+  :group 'mh-show)
+
+(defcustom mh-find-path-hook nil
+  "Hook run by `mh-find-path' after reading the user's MH profile.
+
+This hook can be used the change the value of the variables that
+`mh-find-path' sets if you need to run with different values
+between MH and MH-E."
+  :type 'hook
+  :group 'mh-hooks
+  :group 'mh-e)
+
+(defcustom mh-folder-mode-hook nil
+  "Hook run by `mh-folder-mode' when visiting a new folder."
+  :type 'hook
+  :group 'mh-hooks
+  :group 'mh-folder)
+
+(defcustom mh-forward-hook nil
+  "Hook run by `mh-forward' on a forwarded letter."
+  :type 'hook
+  :group 'mh-hooks
+  :group 'mh-sending-mail)
+
+(defcustom mh-inc-folder-hook nil
+  "Hook run by \\<mh-folder-mode-map>\\[mh-inc-folder] after incorporating mail into a folder."
+  :type 'hook
+  :group 'mh-hooks
+  :group 'mh-inc)
+
+(defcustom mh-insert-signature-hook nil
+  "Hook run by \\<mh-letter-mode-map>\\[mh-insert-signature] after signature has been inserted.
+
+Hook functions may access the actual name of the file or the
+function used to insert the signature with
+`mh-signature-file-name'."
+  :type 'hook
+  :group 'mh-hooks
+  :group 'mh-letter)
+
+(defcustom mh-kill-folder-suppress-prompt-hooks '(mh-search-p)
+  "Abnormal hook run at the beginning of \\<mh-folder-mode-map>\\[mh-kill-folder].
+
+The hook functions are called with no arguments and should return
+a non-nil value to suppress the normal prompt when you remove a
+folder. This is useful for folders that are easily regenerated.
+
+The default value of `mh-search-p' suppresses the prompt on
+folders generated by searching.
+
+WARNING: Use this hook with care. If there is a bug in your hook
+which returns t on \"+inbox\" and you hit \\[mh-kill-folder] by
+accident in the \"+inbox\" folder, you will not be happy."
+  :type 'hook
+  :group 'mh-hooks
+  :group 'mh-folder)
+
+(defcustom mh-letter-mode-hook nil
+  "Hook run by `mh-letter-mode' on a new letter.
+
+This hook allows you to do some processing before editing a
+letter. For example, you may wish to modify the header after
+\"repl\" has done its work, or you may have a complicated
+\"components\" file and need to tell MH-E where the cursor should
+go."
+  :type 'hook
+  :group 'mh-hooks
+  :group 'mh-sending-mail)
+
+(defcustom mh-mh-to-mime-hook nil
+  "Hook run on the formatted letter by \\<mh-letter-mode-map>\\[mh-mh-to-mime]."
+  :type 'hook
+  :group 'mh-hooks
+  :group 'mh-letter)
+
+(defcustom mh-search-mode-hook nil
+  "Hook run upon entry to `mh-search-mode'\\<mh-folder-mode-map>.
+
+If you find that you do the same thing over and over when editing
+the search template, you may wish to bind some shortcuts to keys.
+This can be done with this hook which is called when
+\\[mh-search] is run on a new pattern."
+  :type 'hook
+  :group 'mh-hooks
+  :group 'mh-search)
+
+(defcustom mh-quit-hook nil
+  "Hook run by \\<mh-folder-mode-map>\\[mh-quit] after quitting MH-E.
+
+This hook is not run in an MH-E context, so you might use it to
+modify the window setup.
+
+See also `mh-before-quit-hook'."
+  :type 'hook
+  :group 'mh-hooks
+  :group 'mh-folder)
+
+(defcustom mh-refile-msg-hook nil
+  "Hook run by \\<mh-folder-mode-map>\\[mh-refile-msg] after marking each message for refiling."
+  :type 'hook
+  :group 'mh-hooks
+  :group 'mh-folder)
+
+(defcustom mh-show-hook nil
+  "Hook run after \\<mh-folder-mode-map>\\[mh-show] shows a message.
+
+It is the last thing called after messages are displayed. It's
+used to affect the behavior of MH-E in general or when
+`mh-show-mode-hook' is too early. See `mh-show-mode-hook'."
+  :type 'hook
+  :group 'mh-hooks
+  :group 'mh-show)
+
+(defcustom mh-show-mode-hook nil
+  "Hook run upon entry to `mh-show-mode'.
+
+This hook is called early on in the process of the message
+display. It is usually used to perform some action on the
+message's content. See `mh-show-hook'."
+  :type 'hook
+  :group 'mh-hooks
+  :group 'mh-show)
+
+(defcustom mh-unseen-updated-hook nil
+  "Hook run after the unseen sequence has been updated.
+
+The variable `mh-seen-list' can be used by this hook to obtain
+the list of messages which were removed from the unseen
+sequence."
+  :type 'hook
+  :group 'mh-hooks
+  :group 'mh-sequences)
 
 
 
-(dolist (mess '("^Cursor not pointing to message$"
-                "^There is no other window$"))
-  (add-to-list 'debug-ignored-errors mess))
+;;; Faces (:group 'mh-faces + group where faces described)
+
+(if (boundp 'facemenu-unlisted-faces)
+    (add-to-list 'facemenu-unlisted-faces "^mh-"))
+
+(defvar mh-min-colors-defined-flag (and (not mh-xemacs-flag)
+                                        (>= emacs-major-version 22))
+  "Non-nil means defface supports min-colors display requirement.")
+
+(defun mh-defface-compat (spec)
+  "Convert SPEC for defface if necessary to run on older platforms.
+Modifies SPEC in place and returns it. See `defface' for the spec definition.
+
+When `mh-min-colors-defined-flag' is nil, this function finds
+display entries with \"min-colors\" requirements and either
+removes the \"min-colors\" requirement or strips the display
+entirely if the display does not support the number of specified
+colors."
+  (if mh-min-colors-defined-flag
+      spec
+    (let ((cells (display-color-cells))
+          new-spec)
+      ;; Remove entries with min-colors, or delete them if we have fewer colors
+      ;; than they specify.
+      (loop for entry in (reverse spec) do
+            (let ((requirement (if (eq (car entry) t)
+                                   nil
+                                 (assoc 'min-colors (car entry)))))
+              (if requirement
+                  (when (>= cells (nth 1 requirement))
+                    (setq new-spec (cons (cons (delq requirement (car entry))
+                                               (cdr entry))
+                                         new-spec)))
+                (setq new-spec (cons entry new-spec)))))
+      new-spec)))
+
+(defface mh-folder-address '((t (:inherit mh-folder-subject)))
+  "Recipient face."
+  :group 'mh-faces
+  :group 'mh-folder)
+
+(defface mh-folder-body
+  '((((class color))
+     (:inherit mh-folder-msg-number))
+    (t
+     (:inherit mh-folder-msg-number :italic t)))
+  "Body text face."
+  :group 'mh-faces
+  :group 'mh-folder)
+
+(defface mh-folder-cur-msg-number
+  '((t
+     (:inherit mh-folder-msg-number :bold t)))
+  "Current message number face."
+  :group 'mh-faces
+  :group 'mh-folder)
+
+(defface mh-folder-date '((t (:inherit mh-folder-msg-number)))
+  "Date face."
+  :group 'mh-faces
+  :group 'mh-folder)
+
+(defface mh-folder-deleted '((t (:inherit mh-folder-msg-number)))
+  "Deleted message face."
+  :group 'mh-faces
+  :group 'mh-folder)
+
+(defface mh-folder-followup
+  '((((class color) (background light))
+     (:foreground "blue3"))
+    (((class color) (background dark))
+     (:foreground "LightGoldenRod"))
+    (t
+     (:bold t)))
+  "\"Re:\" face."
+  :group 'mh-faces
+  :group 'mh-folder)
+
+(defface mh-folder-msg-number
+  (mh-defface-compat
+   '((((class color) (min-colors 88) (background light))
+      (:foreground "snow4"))
+     (((class color) (min-colors 88) (background dark))
+      (:foreground "snow3"))
+     (((class color))
+      (:foreground "cyan"))))
+
+  "Message number face."
+  :group 'mh-faces
+  :group 'mh-folder)
+
+(defface mh-folder-refiled
+  (mh-defface-compat
+   '((((class color) (min-colors 88) (background light))
+      (:foreground "DarkGoldenrod"))
+     (((class color) (min-colors 88) (background dark))
+      (:foreground "LightGoldenrod"))
+     (((class color))
+      (:foreground "yellow" :weight light))
+     (((class grayscale) (background light))
+      (:foreground "Gray90" :bold t :italic t))
+     (((class grayscale) (background dark))
+      (:foreground "DimGray" :bold t :italic t))
+     (t
+      (:bold t :italic t))))
+  "Refiled message face."
+  :group 'mh-faces
+  :group 'mh-folder)
+
+(defface mh-folder-sent-to-me-hint '((t (:inherit mh-folder-date)))
+  "Fontification hint face in messages sent directly to us.
+The detection of messages sent to us is governed by the scan
+format `mh-scan-format-nmh' and the regular expression
+`mh-scan-sent-to-me-sender-regexp'."
+  :group 'mh-faces
+  :group 'mh-folder)
+
+(defface mh-folder-sent-to-me-sender '((t (:inherit mh-folder-followup)))
+  "Sender face in messages sent directly to us.
+The detection of messages sent to us is governed by the scan
+format `mh-scan-format-nmh' and the regular expression
+`mh-scan-sent-to-me-sender-regexp'."
+  :group 'mh-faces
+  :group 'mh-folder)
+
+(defface mh-folder-subject
+  '((((class color) (background light))
+     (:foreground "blue4"))
+    (((class color) (background dark))
+     (:foreground "yellow"))
+    (t
+     (:bold t)))
+  "Subject face."
+  :group 'mh-faces
+  :group 'mh-folder)
+
+(defface mh-folder-tick
+  '((((class color) (background dark))
+     (:background "#dddf7e"))
+    (((class color) (background light))
+     (:background "#dddf7e"))
+    (t
+     (:underline t)))
+  "Ticked message face."
+  :group 'mh-faces
+  :group 'mh-folder)
+
+(defface mh-folder-to
+  (mh-defface-compat
+   '((((class color) (min-colors 88) (background light))
+      (:foreground "RosyBrown"))
+     (((class color) (min-colors 88) (background dark))
+      (:foreground "LightSalmon"))
+     (((class color))
+      (:foreground "green"))
+     (((class grayscale) (background light))
+      (:foreground "DimGray" :italic t))
+     (((class grayscale) (background dark))
+      (:foreground "LightGray" :italic t))
+     (t
+      (:italic t))))
+  "\"To:\" face."
+  :group 'mh-faces
+  :group 'mh-folder)
+
+(defface mh-search-folder
+  '((((class color) (background light))
+     (:foreground "dark green" :bold t))
+    (((class color) (background dark))
+     (:foreground "indian red" :bold t))
+    (t
+     (:bold t)))
+  "Folder heading face in MH-Folder buffers created by searches."
+  :group 'mh-faces
+  :group 'mh-search)
+
+(defface mh-letter-header-field
+  '((((class color) (background light))
+     (:background "gray90"))
+    (((class color) (background dark))
+     (:background "gray10"))
+    (t
+     (:bold t)))
+  "Editable header field value face in draft buffers."
+  :group 'mh-faces
+  :group 'mh-letter)
+
+(defface mh-show-cc
+  (mh-defface-compat
+   '((((class color) (min-colors 88) (background light))
+      (:foreground "DarkGoldenrod"))
+     (((class color) (min-colors 88) (background dark))
+      (:foreground "LightGoldenrod"))
+     (((class color))
+      (:foreground "yellow" :weight light))
+     (((class grayscale) (background light))
+      (:foreground "Gray90" :bold t :italic t))
+     (((class grayscale) (background dark))
+      (:foreground "DimGray" :bold t :italic t))
+     (t
+      (:bold t :italic t))))
+  "Face used to highlight \"cc:\" header fields."
+  :group 'mh-faces
+  :group 'mh-show)
+
+(defface mh-show-date
+  (mh-defface-compat
+   '((((class color) (min-colors 88) (background light))
+      (:foreground "ForestGreen"))
+     (((class color) (min-colors 88) (background dark))
+      (:foreground "PaleGreen"))
+     (((class color))
+      (:foreground "green"))
+     (((class grayscale) (background light))
+      (:foreground "Gray90" :bold t))
+     (((class grayscale) (background dark))
+      (:foreground "DimGray" :bold t))
+     (t
+      (:bold t :underline t))))
+  "Face used to highlight \"Date:\" header fields."
+  :group 'mh-faces
+  :group 'mh-show)
+
+(defface mh-show-from
+  '((((class color) (background light))
+     (:foreground "red3"))
+    (((class color) (background dark))
+     (:foreground "cyan"))
+    (t
+     (:bold t)))
+  "Face used to highlight \"From:\" header fields."
+  :group 'mh-faces
+  :group 'mh-show)
+
+(defface mh-show-header
+  (mh-defface-compat
+   '((((class color) (min-colors 88) (background light))
+      (:foreground "RosyBrown"))
+     (((class color) (min-colors 88) (background dark))
+      (:foreground "LightSalmon"))
+     (((class color))
+      (:foreground "green"))
+     (((class grayscale) (background light))
+      (:foreground "DimGray" :italic t))
+     (((class grayscale) (background dark))
+      (:foreground "LightGray" :italic t))
+     (t
+      (:italic t))))
+  "Face used to deemphasize less interesting header fields."
+  :group 'mh-faces
+  :group 'mh-show)
+
+(defface mh-show-pgg-bad '((t (:bold t :foreground "DeepPink1")))
+  "Bad PGG signature face."
+  :group 'mh-faces
+  :group 'mh-show)
+
+(defface mh-show-pgg-good '((t (:bold t :foreground "LimeGreen")))
+  "Good PGG signature face."
+  :group 'mh-faces
+  :group 'mh-show)
+
+(defface mh-show-pgg-unknown '((t (:bold t :foreground "DarkGoldenrod2")))
+  "Unknown or untrusted PGG signature face."
+  :group 'mh-faces
+  :group 'mh-show)
+
+(defface mh-show-signature '((t (:italic t)))
+  "Signature face."
+  :group 'mh-faces
+  :group 'mh-show)
+
+(defface mh-show-subject '((t (:inherit mh-folder-subject)))
+  "Face used to highlight \"Subject:\" header fields."
+  :group 'mh-faces
+  :group 'mh-show)
+
+(defface mh-show-to
+  '((((class color) (background light))
+     (:foreground "SaddleBrown"))
+    (((class color) (background dark))
+     (:foreground "burlywood"))
+    (((class grayscale) (background light))
+     (:foreground "DimGray" :underline t))
+    (((class grayscale) (background dark))
+     (:foreground "LightGray" :underline t))
+    (t (:underline t)))
+  "Face used to highlight \"To:\" header fields."
+  :group 'mh-faces
+  :group 'mh-show)
+
+(defface mh-show-xface '((t (:inherit (mh-show-from highlight))))
+  "X-Face image face.
+The background and foreground are used in the image."
+  :group 'mh-faces
+  :group 'mh-show)
+
+(defface mh-speedbar-folder
+  '((((class color) (background light))
+     (:foreground "blue4"))
+    (((class color) (background dark))
+     (:foreground "light blue")))
+  "Basic folder face."
+  :group 'mh-faces
+  :group 'mh-speedbar)
+
+(defface mh-speedbar-folder-with-unseen-messages
+  '((t
+     (:inherit mh-speedbar-folder :bold t)))
+  "Folder face when folder contains unread messages."
+  :group 'mh-faces
+  :group 'mh-speedbar)
+
+(defface mh-speedbar-selected-folder
+  '((((class color) (background light))
+     (:foreground "red1" :underline t))
+    (((class color) (background dark))
+     (:foreground "red1" :underline t))
+    (t
+     (:underline t)))
+  "Selected folder face."
+  :group 'mh-faces
+  :group 'mh-speedbar)
+
+(defface mh-speedbar-selected-folder-with-unseen-messages
+  '((t
+     (:inherit mh-speedbar-selected-folder :bold t)))
+  "Selected folder face when folder contains unread messages."
+  :group 'mh-faces
+  :group 'mh-speedbar)
 
 (provide 'mh-e)
 
--- a/lisp/mh-e/mh-exec.el	Thu Jan 26 02:23:05 2006 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,264 +0,0 @@
-;;; mh-exec.el --- MH-E process support
-
-;; Copyright (C) 1993, 1995, 1997,
-;;  2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
-
-;; Author: Bill Wohler <wohler@newt.com>
-;; Maintainer: Bill Wohler <wohler@newt.com>
-;; Keywords: mail
-;; See: mh-e.el
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING.  If not, write to the
-;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
-;; Boston, MA 02110-1301, USA.
-
-;;; Commentary:
-
-;; Issue shell and MH commands
-
-;;; Change Log:
-
-;;; Code:
-
-(eval-when-compile (require 'mh-acros))
-(mh-require-cl)
-
-(require 'mh-buffers)
-(require 'mh-utils)
-
-(defvar mh-progs nil
-  "Directory containing MH commands, such as inc, repl, and rmm.")
-
-;;;###autoload
-(put 'mh-progs 'risky-local-variable t)
-
-(defvar mh-lib nil
-  "Directory containing the MH library.
-This directory contains, among other things, the components file.")
-
-;;;###autoload
-(put 'mh-lib 'risky-local-variable t)
-
-(defvar mh-lib-progs nil
-  "Directory containing MH helper programs.
-This directory contains, among other things, the mhl program.")
-
-;;;###autoload
-(put 'mh-lib-progs 'risky-local-variable t)
-
-(defvar mh-index-max-cmdline-args 500
-  "Maximum number of command line args.")
-
-(defun mh-xargs (cmd &rest args)
-  "Partial imitation of xargs.
-The current buffer contains a list of strings, one on each line.
-The function will execute CMD with ARGS and pass the first
-`mh-index-max-cmdline-args' strings to it. This is repeated till
-all the strings have been used."
-  (goto-char (point-min))
-  (let ((current-buffer (current-buffer)))
-    (with-temp-buffer
-      (let ((out (current-buffer)))
-        (set-buffer current-buffer)
-        (while (not (eobp))
-          (let ((arg-list (reverse args))
-                (count 0))
-            (while (and (not (eobp)) (< count mh-index-max-cmdline-args))
-              (push (buffer-substring-no-properties (point) (line-end-position))
-                    arg-list)
-              (incf count)
-              (forward-line))
-            (apply #'call-process cmd nil (list out nil) nil
-                   (nreverse arg-list))))
-        (erase-buffer)
-        (insert-buffer-substring out)))))
-
-;; XXX This should be applied anywhere MH-E calls out to /bin/sh.
-(defun mh-quote-for-shell (string)
-  "Quote STRING for /bin/sh.
-Adds double-quotes around entire string and quotes the characters
-\\, `, and $ with a backslash."
-  (concat "\""
-          (loop for x across string
-                concat (format (if (memq x '(?\\ ?` ?$)) "\\%c" "%c") x))
-          "\""))
-
-(defun mh-exec-cmd (command &rest args)
-  "Execute mh-command COMMAND with ARGS.
-The side effects are what is desired. Any output is assumed to be
-an error and is shown to the user. The output is not read or
-parsed by MH-E."
-  (save-excursion
-    (set-buffer (get-buffer-create mh-log-buffer))
-    (let* ((initial-size (mh-truncate-log-buffer))
-           (start (point))
-           (args (mh-list-to-string args)))
-      (apply 'call-process (expand-file-name command mh-progs) nil t nil args)
-      (when (> (buffer-size) initial-size)
-        (save-excursion
-          (goto-char start)
-          (insert "Errors when executing: " command)
-          (loop for arg in args do (insert " " arg))
-          (insert "\n"))
-        (save-window-excursion
-          (switch-to-buffer-other-window mh-log-buffer)
-          (sit-for 5))))))
-
-(defun mh-exec-cmd-error (env command &rest args)
-  "In environment ENV, execute mh-command COMMAND with ARGS.
-ENV is nil or a string of space-separated \"var=value\" elements.
-Signals an error if process does not complete successfully."
-  (save-excursion
-    (set-buffer (get-buffer-create mh-temp-buffer))
-    (erase-buffer)
-    (let ((process-environment process-environment))
-      ;; XXX: We should purge the list that split-string returns of empty
-      ;;  strings. This can happen in XEmacs if leading or trailing spaces
-      ;;  are present.
-      (dolist (elem (if (stringp env) (split-string env " ") ()))
-        (push elem process-environment))
-      (mh-handle-process-error
-       command (apply #'call-process (expand-file-name command mh-progs)
-                      nil t nil (mh-list-to-string args))))))
-
-(defun mh-exec-cmd-daemon (command filter &rest args)
-  "Execute MH command COMMAND in the background.
-
-If FILTER is non-nil then it is used to process the output
-otherwise the default filter `mh-process-daemon' is used. See
-`set-process-filter' for more details of FILTER.
-
-ARGS are passed to COMMAND as command line arguments."
-  (save-excursion
-    (set-buffer (get-buffer-create mh-log-buffer))
-    (mh-truncate-log-buffer))
-  (let* ((process-connection-type nil)
-         (process (apply 'start-process
-                         command nil
-                         (expand-file-name command mh-progs)
-                         (mh-list-to-string args))))
-    (set-process-filter process (or filter 'mh-process-daemon))
-    process))
-
-(defun mh-exec-cmd-env-daemon (env command filter &rest args)
-  "In ennvironment ENV, execute mh-command COMMAND in the background.
-
-ENV is nil or a string of space-separated \"var=value\" elements.
-Signals an error if process does not complete successfully.
-
-If FILTER is non-nil then it is used to process the output
-otherwise the default filter `mh-process-daemon' is used. See
-`set-process-filter' for more details of FILTER.
-
-ARGS are passed to COMMAND as command line arguments."
-  (let ((process-environment process-environment))
-    (dolist (elem (if (stringp env) (split-string env " ") ()))
-      (push elem process-environment))
-    (apply #'mh-exec-cmd-daemon command filter args)))
-
-(defun mh-process-daemon (process output)
-  "PROCESS daemon that puts OUTPUT into a temporary buffer.
-Any output from the process is displayed in an asynchronous
-pop-up window."
-  (with-current-buffer (get-buffer-create mh-log-buffer)
-    (insert-before-markers output)
-    (display-buffer mh-log-buffer)))
-
-(defun mh-exec-cmd-quiet (raise-error command &rest args)
-  "Signal RAISE-ERROR if COMMAND with ARGS fails.
-Execute MH command COMMAND with ARGS. ARGS is a list of strings.
-Return at start of mh-temp buffer, where output can be parsed and
-used.
-Returns value of `call-process', which is 0 for success, unless
-RAISE-ERROR is non-nil, in which case an error is signaled if
-`call-process' returns non-0."
-  (set-buffer (get-buffer-create mh-temp-buffer))
-  (erase-buffer)
-  (let ((value
-         (apply 'call-process
-                (expand-file-name command mh-progs) nil t nil
-                args)))
-    (goto-char (point-min))
-    (if raise-error
-        (mh-handle-process-error command value)
-      value)))
-
-;; Shush compiler.
-(eval-when-compile (defvar mark-active))
-
-(defun mh-exec-cmd-output (command display &rest args)
-  "Execute MH command COMMAND with DISPLAY flag and ARGS.
-Put the output into buffer after point.
-Set mark after inserted text.
-Output is expected to be shown to user, not parsed by MH-E."
-  (push-mark (point) t)
-  (apply 'call-process
-         (expand-file-name command mh-progs) nil t display
-         (mh-list-to-string args))
-
-  ;; The following is used instead of 'exchange-point-and-mark because the
-  ;; latter activates the current region (between point and mark), which
-  ;; turns on highlighting.  So prior to this bug fix, doing "inc" would
-  ;; highlight a region containing the new messages, which is undesirable.
-  ;; The bug wasn't seen in emacs21 but still occurred in XEmacs21.4.
-  (mh-exchange-point-and-mark-preserving-active-mark))
-
-(defun mh-exchange-point-and-mark-preserving-active-mark ()
-  "Put the mark where point is now, and point where the mark is now.
-This command works even when the mark is not active, and
-preserves whether the mark is active or not."
-  (interactive nil)
-  (let ((is-active (and (boundp 'mark-active) mark-active)))
-    (let ((omark (mark t)))
-      (if (null omark)
-          (error "No mark set in this buffer"))
-      (set-mark (point))
-      (goto-char omark)
-      (if (boundp 'mark-active)
-          (setq mark-active is-active))
-      nil)))
-
-(defun mh-exec-lib-cmd-output (command &rest args)
-  "Execute MH library command COMMAND with ARGS.
-Put the output into buffer after point.
-Set mark after inserted text."
-  (apply 'mh-exec-cmd-output (expand-file-name command mh-lib-progs) nil args))
-
-(defun mh-handle-process-error (command status)
-  "Raise error if COMMAND returned non-zero STATUS, otherwise return STATUS."
-  (if (equal status 0)
-      status
-    (goto-char (point-min))
-    (insert (if (integerp status)
-                (format "%s: exit code %d\n" command status)
-              (format "%s: %s\n" command status)))
-    (save-excursion
-      (let ((error-message (buffer-substring (point-min) (point-max))))
-        (set-buffer (get-buffer-create mh-log-buffer))
-        (mh-truncate-log-buffer)
-        (insert error-message)))
-    (error "%s failed, check buffer %s for error message"
-           command mh-log-buffer)))
-
-(provide 'mh-exec)
-
-;; Local Variables:
-;; indent-tabs-mode: nil
-;; sentence-end-double-space: nil
-;; End:
-
-;; arch-tag: 2857996c-e624-46b2-a58d-979cd279d288
-;;; mh-utils.el ends here
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lisp/mh-e/mh-folder.el	Wed Feb 01 10:07:17 2006 +0000
@@ -0,0 +1,1979 @@
+;;; mh-folder.el --- MH-Folder mode
+
+;; Copyright (C) 2002, 2003, 2005, 2006 Free Software Foundation, Inc.
+
+;; Author: Bill Wohler <wohler@newt.com>
+;; Maintainer: Bill Wohler <wohler@newt.com>
+;; Keywords: mail
+;; See: mh-e.el
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
+
+;;; Commentary:
+
+;; Mode for browsing folders
+
+;;; Change Log:
+
+;;; Code:
+
+(require 'mh-e)
+(require 'mh-scan)
+(mh-require-cl)
+
+;; Dynamically-created function not found in mh-loaddefs.el.
+(autoload 'mh-tool-bar-folder-buttons-init "mh-tool-bar")
+
+(require 'gnus-util)
+(autoload 'message-fetch-field "message")
+
+
+
+;;; MH-E Entry Points
+
+;;;###autoload
+(defun mh-rmail (&optional arg)
+  "Incorporate new mail with MH.
+Scan an MH folder if ARG is non-nil.
+
+This function is an entry point to MH-E, the Emacs interface to
+the MH mail system."
+  (interactive "P")
+  (mh-find-path)
+  (if arg
+      (call-interactively 'mh-visit-folder)
+    (unless (get-buffer mh-inbox)
+      (mh-visit-folder mh-inbox (symbol-name mh-unseen-seq)))
+    (mh-inc-folder)))
+
+;;;###autoload
+(defun mh-nmail (&optional arg)
+  "Check for new mail in inbox folder.
+Scan an MH folder if ARG is non-nil.
+
+This function is an entry point to MH-E, the Emacs interface to
+the MH mail system."
+  (interactive "P")
+  (mh-find-path)                        ; init mh-inbox
+  (if arg
+      (call-interactively 'mh-visit-folder)
+    (mh-visit-folder mh-inbox)))
+
+
+;;; Desktop Integration
+
+;; desktop-buffer-mode-handlers appeared in Emacs 22.
+(if (fboundp 'desktop-buffer-mode-handlers)
+    (add-to-list 'desktop-buffer-mode-handlers
+                 '(mh-folder-mode . mh-restore-desktop-buffer)))
+
+(defun mh-restore-desktop-buffer (desktop-buffer-file-name
+                                  desktop-buffer-name
+                                  desktop-buffer-misc)
+  "Restore an MH folder buffer specified in a desktop file.
+When desktop creates a buffer, DESKTOP-BUFFER-FILE-NAME holds the
+file name to visit, DESKTOP-BUFFER-NAME holds the desired buffer
+name, and DESKTOP-BUFFER-MISC holds a list of miscellaneous info
+used by the `desktop-buffer-handlers' functions."
+  (mh-find-path)
+  (mh-visit-folder desktop-buffer-name)
+  (current-buffer))
+
+
+
+;;; Variables
+
+(defvar mh-folder-filename nil
+  "Full path of directory for this folder.")
+
+(defvar mh-partial-folder-mode-line-annotation "select"
+  "Annotation when displaying part of a folder.
+The string is displayed after the folder's name. nil for no
+annotation.")
+
+(defvar mh-last-destination nil
+  "Destination of last refile or write command.")
+
+(defvar mh-last-destination-folder nil
+  "Destination of last refile command.")
+
+(defvar mh-last-destination-write nil
+  "Destination of last write command.")
+
+(defvar mh-first-msg-num nil
+  "Number of first message in buffer.")
+
+(defvar mh-last-msg-num nil
+  "Number of last msg in buffer.")
+
+(defvar mh-msg-count nil
+  "Number of msgs in buffer.")
+
+
+
+;;; Sequence Menu
+
+(easy-menu-define
+  mh-folder-sequence-menu mh-folder-mode-map "Menu for MH-E folder-sequence."
+  '("Sequence"
+    ["Add Message to Sequence..."       mh-put-msg-in-seq (mh-get-msg-num nil)]
+    ["List Sequences for Message"       mh-msg-is-in-seq (mh-get-msg-num nil)]
+    ["Delete Message from Sequence..."  mh-delete-msg-from-seq
+     (mh-get-msg-num nil)]
+    ["List Sequences in Folder..."      mh-list-sequences t]
+    ["Delete Sequence..."               mh-delete-seq t]
+    ["Narrow to Sequence..."            mh-narrow-to-seq t]
+    ["Widen from Sequence"              mh-widen mh-folder-view-stack]
+    "--"
+    ["Narrow to Subject Sequence"       mh-narrow-to-subject t]
+    ["Narrow to Tick Sequence"          mh-narrow-to-tick
+     (and mh-tick-seq (mh-seq-msgs (mh-find-seq mh-tick-seq)))]
+    ["Delete Rest of Same Subject"      mh-delete-subject t]
+    ["Toggle Tick Mark"                 mh-toggle-tick t]
+    "--"
+    ["Push State Out to MH"             mh-update-sequences t]))
+
+;;; Message Menu
+
+(easy-menu-define
+  mh-folder-message-menu mh-folder-mode-map "Menu for MH-E folder-message."
+  '("Message"
+    ["Show Message"                     mh-show (mh-get-msg-num nil)]
+    ["Show Message with Header"         mh-header-display (mh-get-msg-num nil)]
+    ["Next Message"                     mh-next-undeleted-msg t]
+    ["Previous Message"                 mh-previous-undeleted-msg t]
+    ["Go to First Message"              mh-first-msg t]
+    ["Go to Last Message"               mh-last-msg t]
+    ["Go to Message by Number..."       mh-goto-msg t]
+    ["Modify Message"                   mh-modify t]
+    ["Delete Message"                   mh-delete-msg (mh-get-msg-num nil)]
+    ["Refile Message"                   mh-refile-msg (mh-get-msg-num nil)]
+    ["Undo Delete/Refile"               mh-undo (mh-outstanding-commands-p)]
+    ["Execute Delete/Refile"            mh-execute-commands
+     (mh-outstanding-commands-p)]
+    "--"
+    ["Compose a New Message"            mh-send t]
+    ["Reply to Message..."              mh-reply (mh-get-msg-num nil)]
+    ["Forward Message..."               mh-forward (mh-get-msg-num nil)]
+    ["Redistribute Message..."          mh-redistribute (mh-get-msg-num nil)]
+    ["Edit Message Again"               mh-edit-again (mh-get-msg-num nil)]
+    ["Re-edit a Bounced Message"        mh-extract-rejected-mail t]
+    "--"
+    ["Copy Message to Folder..."        mh-copy-msg (mh-get-msg-num nil)]
+    ["Print Message"                    mh-print-msg (mh-get-msg-num nil)]
+    ["Write Message to File..."         mh-write-msg-to-file
+     (mh-get-msg-num nil)]
+    ["Pipe Message to Command..."       mh-pipe-msg (mh-get-msg-num nil)]
+    ["Unpack Uuencoded Message..."      mh-store-msg (mh-get-msg-num nil)]
+    ["Burst Digest Message"             mh-burst-digest (mh-get-msg-num nil)]))
+
+;;; Folder Menu
+
+(easy-menu-define
+  mh-folder-folder-menu mh-folder-mode-map  "Menu for MH-E folder."
+  '("Folder"
+    ["Incorporate New Mail"             mh-inc-folder t]
+    ["Toggle Show/Folder"               mh-toggle-showing t]
+    ["Execute Delete/Refile"            mh-execute-commands
+     (mh-outstanding-commands-p)]
+    ["Rescan Folder"                    mh-rescan-folder t]
+    ["Thread Folder"                    mh-toggle-threads
+     (not (memq 'unthread mh-view-ops))]
+    ["Pack Folder"                      mh-pack-folder t]
+    ["Sort Folder"                      mh-sort-folder t]
+    "--"
+    ["List Folders"                     mh-list-folders t]
+    ["Visit a Folder..."                mh-visit-folder t]
+    ["View New Messages"                mh-index-new-messages t]
+    ["Search..."                        mh-search t]
+    "--"
+    ["Quit MH-E"                        mh-quit t]))
+
+
+
+;;; MH-Folder Keys
+
+(suppress-keymap mh-folder-mode-map)
+
+;; Use defalias to make sure the documented primary key bindings
+;; appear in menu lists.
+(defalias 'mh-alt-show 'mh-show)
+(defalias 'mh-alt-refile-msg 'mh-refile-msg)
+(defalias 'mh-alt-send 'mh-send)
+(defalias 'mh-alt-visit-folder 'mh-visit-folder)
+
+;; Save the "b" binding for a future `back'. Maybe?
+(gnus-define-keys  mh-folder-mode-map
+  " "           mh-page-msg
+  "!"           mh-refile-or-write-again
+  "'"           mh-toggle-tick
+  ","           mh-header-display
+  "."           mh-alt-show
+  ";"           mh-toggle-mh-decode-mime-flag
+  ">"           mh-write-msg-to-file
+  "?"           mh-help
+  "E"           mh-extract-rejected-mail
+  "M"           mh-modify
+  "\177"        mh-previous-page
+  "\C-d"        mh-delete-msg-no-motion
+  "\t"          mh-index-next-folder
+  [backtab]     mh-index-previous-folder
+  "\M-\t"       mh-index-previous-folder
+  "\e<"         mh-first-msg
+  "\e>"         mh-last-msg
+  "\ed"         mh-redistribute
+  "\r"          mh-show
+  "^"           mh-alt-refile-msg
+  "c"           mh-copy-msg
+  "d"           mh-delete-msg
+  "e"           mh-edit-again
+  "f"           mh-forward
+  "g"           mh-goto-msg
+  "i"           mh-inc-folder
+  "k"           mh-delete-subject-or-thread
+  "m"           mh-alt-send
+  "n"           mh-next-undeleted-msg
+  "\M-n"        mh-next-unread-msg
+  "o"           mh-refile-msg
+  "p"           mh-previous-undeleted-msg
+  "\M-p"        mh-previous-unread-msg
+  "q"           mh-quit
+  "r"           mh-reply
+  "s"           mh-send
+  "t"           mh-toggle-showing
+  "u"           mh-undo
+  "v"           mh-index-visit-folder
+  "x"           mh-execute-commands
+  "|"           mh-pipe-msg)
+
+(gnus-define-keys (mh-folder-map "F" mh-folder-mode-map)
+  "?"           mh-prefix-help
+  "'"           mh-index-ticked-messages
+  "S"           mh-sort-folder
+  "c"           mh-catchup
+  "f"           mh-alt-visit-folder
+  "k"           mh-kill-folder
+  "l"           mh-list-folders
+  "n"           mh-index-new-messages
+  "o"           mh-alt-visit-folder
+  "p"           mh-pack-folder
+  "q"           mh-index-sequenced-messages
+  "r"           mh-rescan-folder
+  "s"           mh-search
+  "u"           mh-undo-folder
+  "v"           mh-visit-folder)
+
+(define-key mh-folder-mode-map "I" mh-inc-spool-map)
+
+(gnus-define-keys (mh-junk-map "J" mh-folder-mode-map)
+  "?"           mh-prefix-help
+  "b"           mh-junk-blacklist
+  "w"           mh-junk-whitelist)
+
+(gnus-define-keys (mh-ps-print-map "P" mh-folder-mode-map)
+  "?"           mh-prefix-help
+  "C"           mh-ps-print-toggle-color
+  "F"           mh-ps-print-toggle-faces
+  "f"           mh-ps-print-msg-file
+  "l"           mh-print-msg
+  "p"           mh-ps-print-msg)
+
+(gnus-define-keys (mh-sequence-map "S" mh-folder-mode-map)
+  "'"           mh-narrow-to-tick
+  "?"           mh-prefix-help
+  "d"           mh-delete-msg-from-seq
+  "k"           mh-delete-seq
+  "l"           mh-list-sequences
+  "n"           mh-narrow-to-seq
+  "p"           mh-put-msg-in-seq
+  "s"           mh-msg-is-in-seq
+  "w"           mh-widen)
+
+(gnus-define-keys (mh-thread-map "T" mh-folder-mode-map)
+  "?"           mh-prefix-help
+  "u"           mh-thread-ancestor
+  "p"           mh-thread-previous-sibling
+  "n"           mh-thread-next-sibling
+  "t"           mh-toggle-threads
+  "d"           mh-thread-delete
+  "o"           mh-thread-refile)
+
+(gnus-define-keys (mh-limit-map "/" mh-folder-mode-map)
+  "'"           mh-narrow-to-tick
+  "?"           mh-prefix-help
+  "c"           mh-narrow-to-cc
+  "g"           mh-narrow-to-range
+  "m"           mh-narrow-to-from
+  "s"           mh-narrow-to-subject
+  "t"           mh-narrow-to-to
+  "w"           mh-widen)
+
+(gnus-define-keys (mh-extract-map "X" mh-folder-mode-map)
+  "?"           mh-prefix-help
+  "s"           mh-store-msg            ;shar
+  "u"           mh-store-msg)           ;uuencode
+
+(gnus-define-keys (mh-digest-map "D" mh-folder-mode-map)
+  " "           mh-page-digest
+  "?"           mh-prefix-help
+  "\177"        mh-page-digest-backwards
+  "b"           mh-burst-digest)
+
+(gnus-define-keys (mh-mime-map "K" mh-folder-mode-map)
+  "?"           mh-prefix-help
+  "a"           mh-mime-save-parts
+  "e"           mh-display-with-external-viewer
+  "i"           mh-folder-inline-mime-part
+  "o"           mh-folder-save-mime-part
+  "t"           mh-toggle-mime-buttons
+  "v"           mh-folder-toggle-mime-part
+  "\t"          mh-next-button
+  [backtab]     mh-prev-button
+  "\M-\t"       mh-prev-button)
+
+(cond
+ (mh-xemacs-flag
+  (define-key mh-folder-mode-map [button2] 'mh-show-mouse))
+ (t
+  (define-key mh-folder-mode-map [mouse-2] 'mh-show-mouse)))
+
+;; "C-c /" prefix is used in mh-folder-mode by pgp.el and mailcrypt
+
+
+
+;;; MH-Folder Help Messages
+
+;; If you add a new prefix, add appropriate text to the nil key.
+
+;; In general, messages are grouped logically. Taking the main commands for
+;; example, the first line is "ways to view messages," the second line is
+;; "things you can do with messages", and the third is "composing" messages.
+
+;; When adding a new prefix, ensure that the help message contains "what" the
+;; prefix is for. For example, if the word "folder" were not present in the
+;; "F" entry, it would not be clear what these commands operated upon.
+(defvar mh-folder-mode-help-messages
+  '((nil "[i]nc, [.]show, [,]show all, [n]ext, [p]revious,\n"
+         "[d]elete, [o]refile, e[x]ecute,\n"
+         "[s]end, [r]eply,\n"
+         "[;]toggle MIME decoding.\n"
+         "Prefix characters:\n [F]older, [S]equence, [J]unk, MIME [K]eys,"
+         "\n [T]hread, [/]limit, e[X]tract, [D]igest, [I]nc spools.")
+
+    (?F "[l]ist; [v]isit folder;\n"
+        "[n]ew messages; [']ticked messages; [s]earch;\n"
+        "[p]ack; [S]ort; [r]escan; [k]ill")
+    (?P "[p]rint message to [f]ile; old-style [l]pr printing;\n"
+        "Toggle printing of [C]olors, [F]aces")
+    (?S "[p]ut message in sequence, [n]arrow, [']narrow to ticked, [w]iden,\n"
+        "[s]equences, [l]ist,\n"
+        "[d]elete message from sequence, [k]ill sequence")
+    (?T "[t]oggle, [d]elete, [o]refile thread")
+    (?/ "Limit to [c]c, ran[g]e, fro[m], [s]ubject, [t]o; [w]iden")
+    (?X "un[s]har, [u]udecode message")
+    (?D "[b]urst digest")
+    (?K "[v]iew, [i]nline, [o]utput/save MIME part; save [a]ll parts; \n"
+        "[TAB] next; [SHIFT-TAB] previous")
+    (?J "[b]lacklist, [w]hitelist message"))
+  "Key binding cheat sheet.
+See `mh-set-help'.")
+
+
+
+;;; MH-Folder Font Lock
+
+(defvar mh-folder-font-lock-keywords
+  (list
+   ;; Folders when displaying index buffer
+   (list "^\\+.*"
+         '(0 'mh-search-folder))
+   ;; Marked for deletion
+   (list (concat mh-scan-deleted-msg-regexp ".*")
+         '(0 'mh-folder-deleted))
+   ;; Marked for refile
+   (list (concat mh-scan-refiled-msg-regexp ".*")
+         '(0 'mh-folder-refiled))
+   ;; After subject
+   (list mh-scan-body-regexp
+         '(1 'mh-folder-body nil t))
+   ;; Subject
+   '(mh-folder-font-lock-subject
+     (1 'mh-folder-followup append t)
+     (2 'mh-folder-subject append t))
+   ;; Current message number
+   (list mh-scan-cur-msg-number-regexp
+         '(1 'mh-folder-cur-msg-number))
+   ;; Message number
+   (list mh-scan-good-msg-regexp
+         '(1 'mh-folder-msg-number))
+   ;; Date
+   (list mh-scan-date-regexp
+         '(1 'mh-folder-date))
+   ;; Messages from me (To:)
+   (list mh-scan-rcpt-regexp
+         '(1 'mh-folder-to)
+         '(2 'mh-folder-address))
+   ;; Messages to me
+   (list mh-scan-sent-to-me-sender-regexp
+         '(1 'mh-folder-sent-to-me-hint)
+         '(2 'mh-folder-sent-to-me-sender)))
+  "Keywords (regular expressions) used to fontify the MH-Folder buffer.")
+
+(defun mh-folder-font-lock-subject (limit)
+  "Return MH-E scan subject strings to font-lock between point and LIMIT."
+  (if (not (re-search-forward mh-scan-subject-regexp limit t))
+      nil
+    (if (match-beginning 1)
+        (set-match-data (list (match-beginning 1) (match-end 3)
+                              (match-beginning 1) (match-end 3) nil nil))
+      (set-match-data (list (match-beginning 3) (match-end 3)
+                            nil nil (match-beginning 3) (match-end 3))))
+    t))
+
+;; Fontify unseen messages in bold.
+
+(defmacro mh-generate-sequence-font-lock (seq prefix face)
+  "Generate the appropriate code to fontify messages in SEQ.
+PREFIX is used to generate unique names for the variables and
+functions defined by the macro. So a different prefix should be
+provided for every invocation.
+FACE is the font-lock face used to display the matching scan lines."
+  (let ((cache (intern (format "mh-folder-%s-seq-cache" prefix)))
+        (func (intern (format "mh-folder-font-lock-%s" prefix))))
+    `(progn
+       (defvar ,cache nil
+         "Internal cache variable used for font-lock in MH-E.
+Should only be non-nil through font-lock stepping, and nil once
+font-lock is done highlighting.")
+       (make-variable-buffer-local ',cache)
+
+       (defun ,func (limit)
+         "Return unseen message lines to font-lock between point and LIMIT."
+         (if (not ,cache) (setq ,cache (mh-seq-msgs (mh-find-seq ,seq))))
+         (let ((cur-msg (mh-get-msg-num nil)))
+           (cond ((not ,cache)
+                  nil)
+                 ((>= (point) limit)              ;Presumably at end of buffer
+                  (setq ,cache nil)
+                  nil)
+                 ((member cur-msg ,cache)
+                  (let ((bpoint (progn (beginning-of-line)(point)))
+                        (epoint (progn (forward-line 1)(point))))
+                    (if (<= limit (point)) (setq  ,cache nil))
+                    (set-match-data (list bpoint epoint bpoint epoint))
+                    t))
+                 (t
+                  ;; move forward one line at a time, checking each message
+                  (while (and (= 0 (forward-line 1))
+                              (> limit (point))
+                              (not (member (mh-get-msg-num nil) ,cache))))
+                  ;; Examine how we must have exited the loop...
+                  (let ((cur-msg (mh-get-msg-num nil)))
+                    (cond ((or (<= limit (point))
+                               (not (member cur-msg ,cache)))
+                           (setq ,cache nil)
+                           nil)
+                          ((member cur-msg ,cache)
+                           (let ((bpoint (progn (beginning-of-line) (point)))
+                                 (epoint (progn (forward-line 1) (point))))
+                             (if (<= limit (point)) (setq ,cache nil))
+                             (set-match-data
+                              (list bpoint epoint bpoint epoint))
+                             t))))))))
+
+       (setq mh-folder-font-lock-keywords
+             (append mh-folder-font-lock-keywords
+                     (list (list ',func (list 1 '',face 'prepend t))))))))
+
+(mh-generate-sequence-font-lock mh-unseen-seq unseen bold)
+(mh-generate-sequence-font-lock mh-tick-seq tick mh-folder-tick)
+
+
+
+;;; MH-Folder Mode
+
+(defmacro mh-remove-xemacs-horizontal-scrollbar ()
+  "Get rid of the horizontal scrollbar that XEmacs insists on putting in."
+  (when mh-xemacs-flag
+    `(if (and (featurep 'scrollbar)
+              (fboundp 'set-specifier))
+         (set-specifier horizontal-scrollbar-visible-p nil
+                        (cons (current-buffer) nil)))))
+
+;; Register mh-folder-mode as supporting which-function-mode...
+(require 'which-func nil t)
+(when (boundp 'which-func-modes)
+  (add-to-list 'which-func-modes 'mh-folder-mode))
+
+;; Shush compiler.
+(eval-when-compile
+  (defvar desktop-save-buffer)
+  (defvar font-lock-auto-fontify)
+  (mh-do-in-xemacs (defvar font-lock-defaults)))
+
+(defvar mh-folder-buttons-init-flag nil)
+
+;; Ensure new buffers won't get this mode if default-major-mode is nil.
+(put 'mh-folder-mode 'mode-class 'special)
+
+;; Autoload cookie needed by desktop.el
+;;;###autoload
+(define-derived-mode mh-folder-mode fundamental-mode "MH-Folder"
+  "Major MH-E mode for \"editing\" an MH folder scan listing.\\<mh-folder-mode-map>
+
+You can show the message the cursor is pointing to, and step through
+the messages. Messages can be marked for deletion or refiling into
+another folder; these commands are executed all at once with a
+separate command.
+
+Options that control this mode can be changed with
+\\[customize-group]; specify the \"mh\" group. In particular, please
+see the `mh-scan-format-file' option if you wish to modify scan's
+format.
+
+When a folder is visited, the hook `mh-folder-mode-hook' is run.
+
+Ranges
+======
+Many commands that operate on individual messages, such as
+`mh-forward' or `mh-refile-msg' take a RANGE argument. This argument
+can be used in several ways.
+
+If you provide the prefix argument (\\[universal-argument]) to
+these commands, then you will be prompted for the message range.
+This can be any valid MH range which can include messages,
+sequences, and the abbreviations (described in the mh(1) man
+page):
+
+<num1>-<num2>
+    Indicates all messages in the range <num1> to <num2>, inclusive.
+    The range must be nonempty.
+
+<num>:N
+<num>:+N
+<num>:-N
+    Up to N messages beginning with (or ending with) message num. Num
+    may be any of the predefined symbols: first, prev, cur, next or
+    last.
+
+first:N
+prev:N
+next:N
+last:N
+    The first, previous, next or last messages, if they exist.
+
+all
+    All of the messages.
+
+For example, a range that shows all of these things is `1 2 3
+5-10 last:5 unseen'.
+
+If the option `transient-mark-mode' is set to t and you set a
+region in the MH-Folder buffer, then the MH-E command will
+perform the operation on all messages in that region.
+
+\\{mh-folder-mode-map}"
+  (mh-do-in-gnu-emacs
+   (unless mh-folder-buttons-init-flag
+     (mh-tool-bar-folder-buttons-init)
+     (setq mh-folder-buttons-init-flag t)))
+  (make-local-variable 'font-lock-defaults)
+  (setq font-lock-defaults '(mh-folder-font-lock-keywords t))
+  (make-local-variable 'desktop-save-buffer)
+  (setq desktop-save-buffer t)
+  (mh-make-local-vars
+   'mh-colors-available-flag (mh-colors-available-p)
+                                        ; Do we have colors available
+   'mh-current-folder (buffer-name)     ; Name of folder, a string
+   'mh-show-buffer (format "show-%s" (buffer-name)) ; Buffer that displays msgs
+   'mh-folder-filename                  ; e.g. "/usr/foobar/Mail/inbox/"
+   (file-name-as-directory (mh-expand-file-name (buffer-name)))
+   'mh-display-buttons-for-inline-parts-flag
+   mh-display-buttons-for-inline-parts-flag ; Allow for display of buttons to
+                                        ; be  toggled.
+   'mh-arrow-marker (make-marker)       ; Marker where arrow is displayed
+   'overlay-arrow-position nil          ; Allow for simultaneous display in
+   'overlay-arrow-string ">"            ;  different MH-E buffers.
+   'mh-showing-mode nil                 ; Show message also?
+   'mh-delete-list nil                  ; List of msgs nums to delete
+   'mh-refile-list nil                  ; List of folder names in mh-seq-list
+   'mh-seq-list nil                     ; Alist of (seq . msgs) nums
+   'mh-seen-list nil                    ; List of displayed messages
+   'mh-next-direction 'forward          ; Direction to move to next message
+   'mh-view-ops ()                      ; Stack that keeps track of the order
+                                        ; in which narrowing/threading has been
+                                        ; carried out.
+   'mh-folder-view-stack ()             ; Stack of previous views of the
+                                        ; folder.
+   'mh-index-data nil                   ; If the folder was created by a call
+                                        ; to mh-search, this contains info
+                                        ; about the search results.
+   'mh-index-previous-search nil        ; folder, indexer, search-regexp
+   'mh-index-msg-checksum-map nil       ; msg -> checksum map
+   'mh-index-checksum-origin-map nil    ; checksum -> ( orig-folder, orig-msg )
+   'mh-index-sequence-search-flag nil   ; folder resulted from sequence search
+   'mh-first-msg-num nil                ; Number of first msg in buffer
+   'mh-last-msg-num nil                 ; Number of last msg in buffer
+   'mh-msg-count nil                    ; Number of msgs in buffer
+   'mh-mode-line-annotation nil         ; Indicates message range
+   'mh-sequence-notation-history (make-hash-table)
+                                        ; Remember what is overwritten by
+                                        ; mh-note-seq.
+   'imenu-create-index-function 'mh-index-create-imenu-index
+                                        ; Setup imenu support
+   'mh-previous-window-config nil)      ; Previous window configuration
+  (mh-remove-xemacs-horizontal-scrollbar)
+  (setq truncate-lines t)
+  (auto-save-mode -1)
+  (setq buffer-offer-save t)
+  (mh-make-local-hook (mh-write-file-functions))
+  (add-hook (mh-write-file-functions) 'mh-execute-commands nil t)
+  (make-local-variable 'revert-buffer-function)
+  (make-local-variable 'hl-line-mode)   ; avoid pollution
+  (mh-funcall-if-exists hl-line-mode 1)
+  (setq revert-buffer-function 'mh-undo-folder)
+  (add-to-list 'minor-mode-alist '(mh-showing-mode " Show"))
+  (easy-menu-add mh-folder-sequence-menu)
+  (easy-menu-add mh-folder-message-menu)
+  (easy-menu-add mh-folder-folder-menu)
+  (mh-inc-spool-make)
+  (set (make-local-variable 'tool-bar-map) mh-folder-tool-bar-map)
+  (mh-funcall-if-exists mh-tool-bar-init :folder)
+  (mh-set-help mh-folder-mode-help-messages)
+  (if (and mh-xemacs-flag
+           font-lock-auto-fontify)
+      (turn-on-font-lock)))             ; Force font-lock in XEmacs.
+
+
+
+;;; MH-Folder Commands
+
+;; Alphabetical.
+;; See also mh-comp.el, mh-junk.el, mh-mime.el, mh-print.el,
+;; mh-search.el, and mh-seq.el.
+
+;;;###mh-autoload
+(defun mh-delete-msg (range)
+  "Delete RANGE\\<mh-folder-mode-map>.
+
+To mark a message for deletion, use this command. A \"D\" is
+placed by the message in the scan window, and the next undeleted
+message is displayed. If the previous command had been
+\\[mh-previous-undeleted-msg], then the next message displayed is
+the first undeleted message previous to the message just deleted.
+Use \\[mh-next-undeleted-msg] to force subsequent
+\\[mh-delete-msg] commands to move forward to the next undeleted
+message after deleting the message under the cursor.
+
+The hook `mh-delete-msg-hook' is called after you mark a message
+for deletion. For example, a past maintainer of MH-E used this
+once when he kept statistics on his mail usage.
+
+Check the documentation of `mh-interactive-range' to see how
+RANGE is read in interactive use."
+  (interactive (list (mh-interactive-range "Delete")))
+  (mh-delete-msg-no-motion range)
+  (if (looking-at mh-scan-deleted-msg-regexp)
+      (mh-next-msg)))
+
+;;;###mh-autoload
+(defun mh-delete-msg-no-motion (range)
+  "Delete RANGE, don't move to next message.
+
+This command marks the RANGE for deletion but leaves the cursor
+at the current message in case you wish to perform other
+operations on the message.
+
+Check the documentation of `mh-interactive-range' to see how
+RANGE is read in interactive use."
+  (interactive (list (mh-interactive-range "Delete")))
+  (mh-iterate-on-range () range
+    (mh-delete-a-msg nil)))
+
+;;;###mh-autoload
+(defun mh-execute-commands ()
+  "Process outstanding delete and refile requests\\<mh-folder-mode-map>.
+
+If you've marked messages to be deleted or refiled and you want
+to go ahead and delete or refile the messages, use this command.
+Many MH-E commands that may affect the numbering of the
+messages (such as \\[mh-rescan-folder] or \\[mh-pack-folder])
+will ask if you want to process refiles or deletes first and then
+either run this command for you or undo the pending refiles and
+deletes, which are lost.
+
+This function runs `mh-before-commands-processed-hook' before the
+commands are processed and `mh-after-commands-processed-hook'
+after the commands are processed."
+  (interactive)
+  (if mh-folder-view-stack (mh-widen t))
+  (mh-process-commands mh-current-folder)
+  (mh-set-scan-mode)
+  (mh-goto-cur-msg)                    ; after mh-set-scan-mode for efficiency
+  (mh-make-folder-mode-line)
+  t)                                    ; return t for write-file-functions
+
+;;;###mh-autoload
+(defun mh-first-msg ()
+  "Display first message."
+  (interactive)
+  (goto-char (point-min))
+  (while (and (not (eobp)) (not (looking-at mh-scan-valid-regexp)))
+    (forward-line 1)))
+
+;;;###mh-autoload
+(defun mh-goto-msg (number &optional no-error-if-no-message dont-show)
+  "Go to a message\\<mh-folder-mode-map>.
+
+You can enter the message NUMBER either before or after typing
+\\[mh-goto-msg]. In the latter case, Emacs prompts you.
+
+In a program, optional non-nil second argument NO-ERROR-IF-NO-MESSAGE
+means return nil instead of signaling an error if message does not
+exist\; in this case, the cursor is positioned near where the message
+would have been. Non-nil third argument DONT-SHOW means not to show
+the message."
+  (interactive "NGo to message: ")
+  (setq number (prefix-numeric-value number))
+  (let ((point (point))
+        (return-value t))
+    (goto-char (point-min))
+    (unless (re-search-forward (format (mh-scan-msg-search-regexp) number)
+                               nil t)
+      (goto-char point)
+      (unless no-error-if-no-message
+        (error "No message %d" number))
+      (setq return-value nil))
+    (beginning-of-line)
+    (or dont-show (not return-value) (mh-maybe-show number))
+    return-value))
+
+;;;###mh-autoload
+(defun mh-inc-folder (&optional file folder)
+  "Incorporate new mail into a folder.
+
+You can incorporate mail from any file into the current folder by
+specifying a prefix argument; you'll be prompted for the name of
+the FILE to use as well as the destination FOLDER
+
+The hook `mh-inc-folder-hook' is run after incorporating new
+mail.
+
+Do not call this function from outside MH-E; use \\[mh-rmail]
+instead."
+  (interactive (list (if current-prefix-arg
+                         (expand-file-name
+                          (read-file-name "inc mail from file: "
+                                          mh-user-path)))
+                     (if current-prefix-arg
+                         (mh-prompt-for-folder "inc mail into" mh-inbox t))))
+  (if (not folder)
+      (setq folder mh-inbox))
+  (let ((threading-needed-flag nil))
+    (let ((config (current-window-configuration)))
+      (when (and mh-show-buffer (get-buffer mh-show-buffer))
+        (delete-windows-on mh-show-buffer))
+      (cond ((not (get-buffer folder))
+             (mh-make-folder folder)
+             (setq threading-needed-flag mh-show-threads-flag)
+             (setq mh-previous-window-config config))
+            ((not (eq (current-buffer) (get-buffer folder)))
+             (switch-to-buffer folder)
+             (setq mh-previous-window-config config))))
+    (mh-get-new-mail file)
+    (when (and threading-needed-flag
+               (save-excursion
+                 (goto-char (point-min))
+                 (or (null mh-large-folder)
+                     (not (equal (forward-line (1+ mh-large-folder)) 0))
+                     (and (message "Not threading since the number of messages exceeds `mh-large-folder'")
+                          nil))))
+      (mh-toggle-threads))
+    (beginning-of-line)
+    (if (and mh-showing-mode (looking-at mh-scan-valid-regexp)) (mh-show))
+    (run-hooks 'mh-inc-folder-hook)))
+
+;;;###mh-autoload
+(defun mh-last-msg ()
+  "Display last message."
+  (interactive)
+  (goto-char (point-max))
+  (while (and (not (bobp)) (not (looking-at mh-scan-valid-regexp)))
+    (forward-line -1))
+  (mh-recenter nil))
+
+;;;###mh-autoload
+(defun mh-modify (&optional message)
+  "Edit message.
+
+There are times when you need to edit a message. For example, you
+may need to fix a broken Content-Type header field. You can do
+this with this command. It displays the raw message in an
+editable buffer. When you are done editing, save and kill the
+buffer as you would any other.
+
+From a program, edit MESSAGE; nil means edit current message."
+  (interactive)
+  (let* ((message (or message (mh-get-msg-num t)))
+         (msg-filename (mh-msg-filename message))
+         edit-buffer)
+    (when (not (file-exists-p msg-filename))
+      (error "Message %d does not exist" message))
+
+    ;; Invalidate the show buffer if it is showing the same message that is
+    ;; to be edited.
+    (when (and (buffer-live-p (get-buffer mh-show-buffer))
+               (equal (save-excursion (set-buffer mh-show-buffer)
+                                      buffer-file-name)
+                      msg-filename))
+      (mh-invalidate-show-buffer))
+
+    ;; Edit message
+    (find-file msg-filename)
+    (setq edit-buffer (current-buffer))
+
+    ;; Set buffer properties
+    (mh-letter-mode)
+    (use-local-map text-mode-map)
+
+    ;; Just show the edit buffer...
+    (delete-other-windows)
+    (switch-to-buffer edit-buffer)))
+
+;;;###mh-autoload
+(defun mh-next-button (&optional backward-flag)
+  "Go to the next button.
+
+If the end of the buffer is reached then the search wraps over to
+the start of the buffer.
+
+If an optional prefix argument BACKWARD-FLAG is given, the cursor
+will move to the previous button."
+  (interactive (list current-prefix-arg))
+  (unless mh-showing-mode
+    (mh-show))
+  (mh-in-show-buffer (mh-show-buffer)
+    (mh-goto-next-button backward-flag)))
+
+;;;###mh-autoload
+(defun mh-next-undeleted-msg (&optional count wait-after-complaining-flag)
+  "Display next message.
+
+This command can be given a prefix argument COUNT to specify how
+many unread messages to skip.
+
+In a program, pause for a second after printing message if we are
+at the last undeleted message and optional argument
+WAIT-AFTER-COMPLAINING-FLAG is non-nil."
+  (interactive "p")
+  (setq mh-next-direction 'forward)
+  (forward-line 1)
+  (cond ((re-search-forward mh-scan-good-msg-regexp nil t count)
+         (beginning-of-line)
+         (mh-maybe-show))
+        (t (forward-line -1)
+           (message "No more undeleted messages")
+           (if wait-after-complaining-flag (sit-for 1)))))
+
+;;;###mh-autoload
+(defun mh-next-unread-msg (&optional count)
+  "Display next unread message.
+
+This command can be given a prefix argument COUNT to specify how
+many unread messages to skip."
+  (interactive "p")
+  (unless (> count 0)
+    (error "The function `mh-next-unread-msg' expects positive argument"))
+  (setq count (1- count))
+  (let ((unread-sequence (reverse (cdr (assoc mh-unseen-seq mh-seq-list))))
+        (cur-msg (mh-get-msg-num nil)))
+    (cond ((and (not cur-msg) (not (bobp))
+                ;; If we are at the end of the buffer back up one line and go
+                ;; to unread message after that.
+                (progn
+                  (forward-line -1)
+                  (setq cur-msg (mh-get-msg-num nil)))
+                nil))
+          ((or (null unread-sequence) (not cur-msg))
+           ;; No unread message or there aren't any messages in buffer...
+           (message "No more unread messages"))
+          ((progn
+             ;; Skip messages
+             (while (and unread-sequence (>= cur-msg (car unread-sequence)))
+               (setq unread-sequence (cdr unread-sequence)))
+             (while (> count 0)
+               (setq unread-sequence (cdr unread-sequence))
+               (setq count (1- count)))
+             (not (car unread-sequence)))
+           (message "No more unread messages"))
+          (t (loop for msg in unread-sequence
+                   when (mh-goto-msg msg t) return nil
+                   finally (message "No more unread messages"))))))
+
+;;;###mh-autoload
+(defun mh-page-msg (&optional lines)
+  "Display next page in message.
+
+You can give this command a prefix argument that specifies the
+number of LINES to scroll. This command will also show the next
+undeleted message if it is used at the bottom of a message."
+  (interactive "P")
+  (if mh-showing-mode
+      (if mh-page-to-next-msg-flag
+          (if (equal mh-next-direction 'backward)
+              (mh-previous-undeleted-msg)
+            (mh-next-undeleted-msg))
+        (if (mh-in-show-buffer (mh-show-buffer)
+              (pos-visible-in-window-p (point-max)))
+            (progn
+              (message
+               "End of message (Type %s to read %s undeleted message)"
+               (single-key-description last-input-event)
+               (if (equal mh-next-direction 'backward)
+                   "previous"
+                 "next"))
+              (setq mh-page-to-next-msg-flag t))
+          (scroll-other-window lines)))
+    (mh-show)))
+
+;;;###mh-autoload
+(defun mh-prev-button ()
+  "Go to the previous button.
+
+If the beginning of the buffer is reached then the search wraps
+over to the end of the buffer."
+  (interactive)
+  (mh-next-button t))
+
+;;;###mh-autoload
+(defun mh-previous-page (&optional lines)
+  "Display next page in message.
+
+You can give this command a prefix argument that specifies the
+number of LINES to scroll."
+  (interactive "P")
+  (mh-in-show-buffer (mh-show-buffer)
+    (scroll-down lines)))
+
+;;;###mh-autoload
+(defun mh-previous-undeleted-msg (&optional count wait-after-complaining-flag)
+  "Display previous message.
+
+This command can be given a prefix argument COUNT to specify how
+many unread messages to skip.
+
+In a program, pause for a second after printing message if we are
+at the last undeleted message and optional argument
+WAIT-AFTER-COMPLAINING-FLAG is non-nil."
+  (interactive "p")
+  (setq mh-next-direction 'backward)
+  (beginning-of-line)
+  (cond ((re-search-backward mh-scan-good-msg-regexp nil t count)
+         (mh-maybe-show))
+        (t (message "No previous undeleted message")
+           (if wait-after-complaining-flag (sit-for 1)))))
+
+;;;###mh-autoload
+(defun mh-previous-unread-msg (&optional count)
+  "Display previous unread message.
+
+This command can be given a prefix argument COUNT to specify how
+many unread messages to skip."
+  (interactive "p")
+  (unless (> count 0)
+    (error "The function `mh-previous-unread-msg' expects positive argument"))
+  (setq count (1- count))
+  (let ((unread-sequence (cdr (assoc mh-unseen-seq mh-seq-list)))
+        (cur-msg (mh-get-msg-num nil)))
+    (cond ((and (not cur-msg) (not (bobp))
+                ;; If we are at the end of the buffer back up one line and go
+                ;; to unread message after that.
+                (progn
+                  (forward-line -1)
+                  (setq cur-msg (mh-get-msg-num nil)))
+                nil))
+          ((or (null unread-sequence) (not cur-msg))
+           ;; No unread message or there aren't any messages in buffer...
+           (message "No more unread messages"))
+          ((progn
+             ;; Skip count messages...
+             (while (and unread-sequence (>= (car unread-sequence) cur-msg))
+               (setq unread-sequence (cdr unread-sequence)))
+             (while (> count 0)
+               (setq unread-sequence (cdr unread-sequence))
+               (setq count (1- count)))
+             (not (car unread-sequence)))
+           (message "No more unread messages"))
+          (t (loop for msg in unread-sequence
+                   when (mh-goto-msg msg t) return nil
+                   finally (message "No more unread messages"))))))
+
+;;;###mh-autoload
+(defun mh-quit ()
+  "Quit the current MH-E folder.
+
+When you want to quit using MH-E and go back to editing, you can use
+this command. This buries the buffers of the current MH-E folder and
+restores the buffers that were present when you first ran
+\\[mh-rmail]. It also removes any MH-E working buffers whose name
+begins with \" *mh-\" or \"*MH-E \". You can later restore your MH-E
+session by selecting the \"+inbox\" buffer or by running \\[mh-rmail]
+again.
+
+The two hooks `mh-before-quit-hook' and `mh-quit-hook' are called by
+this function. The former one is called before the quit occurs, so you
+might use it to perform any MH-E operations; you could perform some
+query and abort the quit or call `mh-execute-commands', for example.
+The latter is not run in an MH-E context, so you might use it to
+modify the window setup."
+  (interactive)
+  (run-hooks 'mh-before-quit-hook)
+  (let ((show-buffer (get-buffer mh-show-buffer)))
+    (when show-buffer
+      (kill-buffer show-buffer)))
+  (mh-update-sequences)
+  (mh-destroy-postponed-handles)
+  (bury-buffer (current-buffer))
+
+  ;; Delete all MH-E temporary and working buffers.
+  (dolist (buffer (buffer-list))
+    (when (or (string-match "^ \\*mh-" (buffer-name buffer))
+              (string-match "^\\*MH-E " (buffer-name buffer)))
+      (kill-buffer buffer)))
+
+  (if mh-previous-window-config
+      (set-window-configuration mh-previous-window-config))
+  (run-hooks 'mh-quit-hook))
+
+;;;###mh-autoload
+(defun mh-refile-msg (range folder &optional dont-update-last-destination-flag)
+  "Refile (output) RANGE into FOLDER.
+
+You are prompted for the folder name. Note that this command can also
+be used to create folders. If you specify a folder that does not
+exist, you will be prompted to create it.
+
+The hook `mh-refile-msg-hook' is called after a message is marked to
+be refiled.
+
+Check the documentation of `mh-interactive-range' to see how RANGE is
+read in interactive use.
+
+In a program, the variables `mh-last-destination' and
+`mh-last-destination-folder' are not updated if
+DONT-UPDATE-LAST-DESTINATION-FLAG is non-nil."
+  (interactive (list (mh-interactive-range "Refile")
+                     (intern (mh-prompt-for-refile-folder))))
+  (unless dont-update-last-destination-flag
+    (setq mh-last-destination (cons 'refile folder)
+          mh-last-destination-folder mh-last-destination))
+  (mh-iterate-on-range () range
+    (mh-refile-a-msg nil folder))
+  (when (looking-at mh-scan-refiled-msg-regexp) (mh-next-msg)))
+
+;;;###mh-autoload
+(defun mh-refile-or-write-again (range &optional interactive-flag)
+  "Repeat last output command.
+
+If you are refiling several messages into the same folder, you
+can use this command to repeat the last
+refile (\\[mh-refile-msg]) or write (\\[mh-write-msg-to-file]).
+You can use a range.
+
+Check the documentation of `mh-interactive-range' to see how RANGE is
+read in interactive use.
+
+In a program, a non-nil INTERACTIVE-FLAG means that the function was
+called interactively."
+  (interactive (list (mh-interactive-range "Redo") t))
+  (if (null mh-last-destination)
+      (error "No previous refile or write"))
+  (cond ((eq (car mh-last-destination) 'refile)
+         (mh-refile-msg range (cdr mh-last-destination))
+         (message "Destination folder: %s" (cdr mh-last-destination)))
+        (t
+         (mh-iterate-on-range msg range
+           (apply 'mh-write-msg-to-file msg (cdr mh-last-destination)))
+         (mh-next-msg interactive-flag))))
+
+;;;###mh-autoload
+(defun mh-rescan-folder (&optional range dont-exec-pending)
+  "Rescan folder\\<mh-folder-mode-map>.
+
+This command is useful to grab all messages in your \"+inbox\" after
+processing your new mail for the first time. If you don't want to
+rescan the entire folder, this command will accept a RANGE. Check the
+documentation of `mh-interactive-range' to see how RANGE is read in
+interactive use.
+
+This command will ask if you want to process refiles or deletes first
+and then either run \\[mh-execute-commands] for you or undo the
+pending refiles and deletes, which are lost.
+
+In a program, the processing of outstanding commands is not performed
+if DONT-EXEC-PENDING is non-nil."
+  (interactive (list (if current-prefix-arg
+                         (mh-read-range "Rescan" mh-current-folder t nil t
+                                        mh-interpret-number-as-range-flag)
+                       nil)))
+  (setq mh-next-direction 'forward)
+  (let ((threaded-flag (memq 'unthread mh-view-ops))
+        (msg-num (mh-get-msg-num nil)))
+    (mh-scan-folder mh-current-folder (or range "all") dont-exec-pending)
+    ;; If there isn't a cur sequence, mh-scan-folder goes to the first message.
+    ;; Try to stay where we were.
+    (if (null (car (mh-seq-to-msgs 'cur)))
+        (mh-goto-msg msg-num t t))
+    (cond (threaded-flag (mh-toggle-threads))
+          (mh-index-data (mh-index-insert-folder-headers)))))
+
+(defun mh-show-mouse (event)
+  "Move point to mouse EVENT and show message."
+  (interactive "e")
+  (mouse-set-point event)
+  (mh-show))
+
+;;;###mh-autoload
+(defun mh-toggle-showing ()
+  "Toggle between MH-Folder and MH-Folder Show modes.
+
+This command switches between MH-Folder mode and MH-Folder Show
+mode. MH-Folder mode turns off the associated show buffer so that
+you can perform operations on the messages quickly without
+reading them. This is an excellent way to prune out your junk
+mail or to refile a group of messages to another folder for later
+examination."
+  (interactive)
+  (if mh-showing-mode
+      (mh-set-scan-mode)
+    (mh-show)))
+
+;;;###mh-autoload
+(defun mh-undo (range)
+  "Undo pending deletes or refiles in RANGE.
+
+If you've deleted a message or refiled it, but changed your mind,
+you can cancel the action before you've executed it. Use this
+command to undo a refile on or deletion of a single message. You
+can also undo refiles and deletes for messages that are found in
+a given RANGE.
+
+Check the documentation of `mh-interactive-range' to see how
+RANGE is read in interactive use."
+  (interactive (list (mh-interactive-range "Undo")))
+  (cond ((numberp range)
+         (let ((original-position (point)))
+           (beginning-of-line)
+           (while (not (or (looking-at mh-scan-deleted-msg-regexp)
+                           (looking-at mh-scan-refiled-msg-regexp)
+                           (and (eq mh-next-direction 'forward) (bobp))
+                           (and (eq mh-next-direction 'backward)
+                                (save-excursion (forward-line) (eobp)))))
+             (forward-line (if (eq mh-next-direction 'forward) -1 1)))
+           (if (or (looking-at mh-scan-deleted-msg-regexp)
+                   (looking-at mh-scan-refiled-msg-regexp))
+               (progn
+                 (mh-undo-msg (mh-get-msg-num t))
+                 (mh-maybe-show))
+             (goto-char original-position)
+             (error "Nothing to undo"))))
+        (t (mh-iterate-on-range () range
+             (mh-undo-msg nil))))
+  (if (not (mh-outstanding-commands-p))
+      (mh-set-folder-modified-p nil)))
+
+;;;###mh-autoload
+(defun mh-visit-folder (folder &optional range index-data)
+  "Visit FOLDER.
+
+When you want to read the messages that you have refiled into folders,
+use this command to visit the folder. You are prompted for the folder
+name.
+
+The folder buffer will show just unseen messages if there are any;
+otherwise, it will show all the messages in the buffer as long there
+are fewer than `mh-large-folder' messages. If there are more, then you
+are prompted for a range of messages to scan.
+
+You can provide a prefix argument in order to specify a RANGE of
+messages to show when you visit the folder. In this case, regions are
+not used to specify the range and `mh-large-folder' is ignored. Check
+the documentation of `mh-interactive-range' to see how RANGE is read
+in interactive use.
+
+Note that this command can also be used to create folders. If you
+specify a folder that does not exist, you will be prompted to create
+it.
+
+Do not call this function from outside MH-E; use \\[mh-rmail] instead.
+
+If, in a program, RANGE is nil (the default), then all messages in
+FOLDER are displayed. If an index buffer is being created then
+INDEX-DATA is used to initialize the index buffer specific data
+structures."
+  (interactive (let ((folder-name (mh-prompt-for-folder "Visit" mh-inbox t)))
+                 (list folder-name
+                       (mh-read-range "Scan" folder-name t nil
+                                      current-prefix-arg
+                                      mh-interpret-number-as-range-flag))))
+  (let ((config (current-window-configuration))
+        (current-buffer (current-buffer))
+        (threaded-view-flag mh-show-threads-flag))
+    (delete-other-windows)
+    (save-excursion
+      (when (get-buffer folder)
+        (set-buffer folder)
+        (setq threaded-view-flag (memq 'unthread mh-view-ops))))
+    (when index-data
+      (mh-make-folder folder)
+      (setq mh-index-data (car index-data)
+            mh-index-msg-checksum-map (make-hash-table :test #'equal)
+            mh-index-checksum-origin-map (make-hash-table :test #'equal))
+      (mh-index-update-maps folder (cadr index-data))
+      (mh-index-create-sequences))
+    (mh-scan-folder folder (or range "all"))
+    (cond ((and threaded-view-flag
+                (save-excursion
+                  (goto-char (point-min))
+                  (or (null mh-large-folder)
+                      (not (equal (forward-line (1+ mh-large-folder)) 0))
+                      (and (message "Not threading since the number of messages exceeds `mh-large-folder'")
+                           nil))))
+           (mh-toggle-threads))
+          (mh-index-data
+           (mh-index-insert-folder-headers)))
+    (unless (eq current-buffer (current-buffer))
+      (setq mh-previous-window-config config)))
+  nil)
+
+;;;###mh-autoload
+(defun mh-write-msg-to-file (message file no-header)
+  "Append MESSAGE to end of FILE\\<mh-folder-mode-map>.
+
+You are prompted for the filename. If the file already exists,
+the message is appended to it. You can also write the message to
+the file without the header by specifying a prefix argument
+NO-HEADER. Subsequent writes to the same file can be made with
+the command \\[mh-refile-or-write-again]."
+  (interactive
+   (list (mh-get-msg-num t)
+         (let ((default-dir (if (eq 'write (car mh-last-destination-write))
+                                (file-name-directory
+                                 (car (cdr mh-last-destination-write)))
+                              default-directory)))
+           (read-file-name (format "Save message%s in file: "
+                                   (if current-prefix-arg " body" ""))
+                           default-dir
+                           (if (eq 'write (car mh-last-destination-write))
+                               (car (cdr mh-last-destination-write))
+                             (expand-file-name "mail.out" default-dir))))
+         current-prefix-arg))
+  (let ((msg-file-to-output (mh-msg-filename message))
+        (output-file (mh-expand-file-name file)))
+    (setq mh-last-destination (list 'write file (if no-header 'no-header))
+          mh-last-destination-write mh-last-destination)
+    (save-excursion
+      (set-buffer (get-buffer-create mh-temp-buffer))
+      (erase-buffer)
+      (insert-file-contents msg-file-to-output)
+      (goto-char (point-min))
+      (if no-header (search-forward "\n\n"))
+      (append-to-file (point) (point-max) output-file))))
+
+;;;###mh-autoload
+(defun mh-update-sequences ()
+  "Flush MH-E's state out to MH.
+
+This function updates the sequence specified by your
+\"Unseen-Sequence:\" profile component, \"cur\", and the sequence
+listed by the `mh-tick-seq' option which is \"tick\" by default.
+The message at the cursor is used for \"cur\"."
+  (interactive)
+  ;; mh-update-sequences is the opposite of mh-read-folder-sequences,
+  ;; which updates MH-E's state from MH.
+  (let ((folder-set (mh-update-unseen))
+        (new-cur (mh-get-msg-num nil)))
+    (if new-cur
+        (let ((seq-entry (mh-find-seq 'cur)))
+          (mh-remove-cur-notation)
+          (setcdr seq-entry
+                  (list new-cur))       ;delete-seq-locally, add-msgs-to-seq
+          (mh-define-sequence 'cur (list new-cur))
+          (beginning-of-line)
+          (if (looking-at mh-scan-good-msg-regexp)
+              (mh-notate-cur)))
+      (or folder-set
+          (save-excursion
+            ;; psg - mh-current-folder is nil if mh-summary-height < 4 !
+            ;;       So I added this sanity check.
+            (if (stringp mh-current-folder)
+                (mh-exec-cmd-quiet t "folder" mh-current-folder "-fast")
+              (mh-exec-cmd-quiet t "folder" "-fast")))))))
+
+
+
+;;; Support Routines
+
+(defun mh-get-new-mail (maildrop-name)
+  "Read new mail from MAILDROP-NAME into the current buffer.
+Return in the current buffer."
+  (let ((point-before-inc (point))
+        (folder mh-current-folder)
+        (new-mail-flag nil))
+    (with-mh-folder-updating (t)
+      (if maildrop-name
+          (message "inc %s -file %s..." folder maildrop-name)
+        (message "inc %s..." folder))
+      (setq mh-next-direction 'forward)
+      (goto-char (point-max))
+      (mh-remove-cur-notation)
+      (let ((start-of-inc (point)))
+        (if maildrop-name
+            ;; I think MH 5 used "-ms-file" instead of "-file",
+            ;; which would make inc'ing from maildrops fail.
+            (mh-exec-cmd-output mh-inc-prog nil folder
+                                (mh-scan-format)
+                                "-file" (expand-file-name maildrop-name)
+                                "-width" (window-width)
+                                "-truncate")
+          (mh-exec-cmd-output mh-inc-prog nil
+                              (mh-scan-format)
+                              "-width" (window-width)))
+        (if maildrop-name
+            (message "inc %s -file %s...done" folder maildrop-name)
+          (message "inc %s...done" folder))
+        (goto-char start-of-inc)
+        (cond ((save-excursion
+                 (re-search-forward "^inc: no mail" nil t))
+               (message "No new mail%s%s" (if maildrop-name " in " "")
+                        (if maildrop-name maildrop-name "")))
+              ((and (when mh-folder-view-stack
+                      (let ((saved-text (buffer-substring-no-properties
+                                         start-of-inc (point-max))))
+                        (delete-region start-of-inc (point-max))
+                        (unwind-protect (mh-widen t)
+                          (mh-remove-cur-notation)
+                          (goto-char (point-max))
+                          (setq start-of-inc (point))
+                          (insert saved-text)
+                          (goto-char start-of-inc))))
+                    nil))
+              ((re-search-forward "^inc:" nil t) ; Error messages
+               (error "Error incorporating mail"))
+              ((and
+                (equal mh-scan-format-file t)
+                mh-adaptive-cmd-note-flag
+                ;; Have we reached an edge condition?
+                (save-excursion
+                  (re-search-forward mh-scan-msg-overflow-regexp nil 0 1))
+                (setq start-of-inc (mh-generate-new-cmd-note folder))
+                nil))
+              (t
+               (setq new-mail-flag t)))
+        (keep-lines mh-scan-valid-regexp) ; Flush random scan lines
+        (let* ((sequences (mh-read-folder-sequences folder t))
+               (new-cur (assoc 'cur sequences))
+               (new-unseen (assoc mh-unseen-seq sequences)))
+          (unless (assoc 'cur mh-seq-list)
+            (push (list 'cur) mh-seq-list))
+          (unless (assoc mh-unseen-seq mh-seq-list)
+            (push (list mh-unseen-seq) mh-seq-list))
+          (setcdr (assoc 'cur mh-seq-list) (cdr new-cur))
+          (setcdr (assoc mh-unseen-seq mh-seq-list) (cdr new-unseen)))
+        (when (equal (point-max) start-of-inc)
+          (mh-notate-cur))
+        (if new-mail-flag
+            (progn
+              (mh-make-folder-mode-line)
+              (when (mh-speed-flists-active-p)
+                (mh-speed-flists t mh-current-folder))
+              (when (memq 'unthread mh-view-ops)
+                (mh-thread-inc folder start-of-inc))
+              (mh-goto-cur-msg))
+          (goto-char point-before-inc))
+        (mh-notate-user-sequences (cons start-of-inc (point-max)))))))
+
+(defun mh-generate-new-cmd-note (folder)
+  "Fix the `mh-cmd-note' value for this FOLDER.
+
+After doing an `mh-get-new-mail' operation in this FOLDER, at least
+one line that looks like a truncated message number was found.
+
+Remove the text added by the last `mh-inc' command. It should be the
+messages cur-last. Call `mh-set-cmd-note', adjusting the notation
+column with the width of the largest message number in FOLDER.
+
+Reformat the message number width on each line in the buffer and trim
+the line length to fit in the window.
+
+Rescan the FOLDER in the range cur-last in order to display the
+messages that were removed earlier. They should all fit in the scan
+line now with no message truncation."
+  (save-excursion
+    (let ((maxcol (1- (window-width)))
+          (old-cmd-note mh-cmd-note)
+          mh-cmd-note-fmt
+          msgnum)
+      ;; Nuke all of the lines just added by the last inc
+      (delete-char (- (point-max) (point)))
+      ;; Update the current buffer to reflect the new mh-cmd-note
+      ;; value needed to display messages.
+      (mh-set-cmd-note (mh-msg-num-width-to-column (mh-msg-num-width folder)))
+      (setq mh-cmd-note-fmt (concat "%" (format "%d" mh-cmd-note) "d"))
+      ;; Cleanup the messages that are in the buffer right now
+      (goto-char (point-min))
+      (cond ((memq 'unthread mh-view-ops)
+             (mh-thread-add-spaces (- mh-cmd-note old-cmd-note)))
+            (t (while (re-search-forward (mh-scan-msg-number-regexp) nil 0 1)
+                 ;; reformat the number to fix in mh-cmd-note columns
+                 (setq msgnum (string-to-number
+                               (buffer-substring
+                                (match-beginning 1) (match-end 1))))
+                 (replace-match (format mh-cmd-note-fmt msgnum))
+                 ;; trim the line to fix in the window
+                 (end-of-line)
+                 (let ((eol (point)))
+                   (move-to-column maxcol)
+                   (if (<= (point) eol)
+                       (delete-char (- eol (point))))))))
+      ;; now re-read the lost messages
+      (goto-char (point-max))
+      (prog1 (point)
+        (mh-regenerate-headers "cur-last" t)))))
+
+;;;###mh-autoload
+(defun mh-goto-cur-msg (&optional minimal-changes-flag)
+  "Position the cursor at the current message.
+When optional argument MINIMAL-CHANGES-FLAG is non-nil, the
+function doesn't recenter the folder buffer."
+  (let ((cur-msg (car (mh-seq-to-msgs 'cur))))
+    (cond ((and cur-msg
+                (mh-goto-msg cur-msg t t))
+           (unless minimal-changes-flag
+             (mh-notate-cur)
+             (mh-recenter 0)
+             (mh-maybe-show cur-msg)))
+          (t
+           (setq overlay-arrow-position nil)
+           (message "No current message")))))
+
+;;;###mh-autoload
+(defun mh-recenter (arg)
+  "Like recenter but with three improvements:
+
+- At the end of the buffer it tries to show fewer empty lines.
+
+- operates only if the current buffer is in the selected window.
+  (Commands like `save-some-buffers' can make this false.)
+
+- nil ARG means recenter as if prefix argument had been given."
+  (cond ((not (eq (get-buffer-window (current-buffer)) (selected-window)))
+         nil)
+        ((= (point-max) (save-excursion
+                          (forward-line (- (/ (window-height) 2) 2))
+                          (point)))
+         (let ((lines-from-end 2))
+           (save-excursion
+             (while (> (point-max) (progn (forward-line) (point)))
+               (incf lines-from-end)))
+           (recenter (- lines-from-end))))
+        ;; '(4) is the same as C-u prefix argument.
+        (t (recenter (or arg '(4))))))
+
+(defun mh-update-unseen ()
+  "Synchronize the unseen sequence with MH.
+Return non-nil iff the MH folder was set.
+The hook `mh-unseen-updated-hook' is called after the unseen sequence
+is updated."
+  (if mh-seen-list
+      (let* ((unseen-seq (mh-find-seq mh-unseen-seq))
+             (unseen-msgs (mh-seq-msgs unseen-seq)))
+        (if unseen-msgs
+            (progn
+              (mh-undefine-sequence mh-unseen-seq mh-seen-list)
+              (run-hooks 'mh-unseen-updated-hook)
+              (while mh-seen-list
+                (setq unseen-msgs (delq (car mh-seen-list) unseen-msgs))
+                (setq mh-seen-list (cdr mh-seen-list)))
+              (setcdr unseen-seq unseen-msgs)
+              t)                        ;since we set the folder
+          (setq mh-seen-list nil)))))
+
+;;;###mh-autoload
+(defun mh-outstanding-commands-p ()
+  "Return non-nil if there are outstanding deletes or refiles."
+  (save-excursion
+    (when (eq major-mode 'mh-show-mode)
+      (set-buffer mh-show-folder-buffer))
+    (or mh-delete-list mh-refile-list)))
+
+;;;###mh-autoload
+(defun mh-set-folder-modified-p (flag)
+  "Mark current folder as modified or unmodified according to FLAG."
+  (set-buffer-modified-p flag))
+
+(defun mh-process-commands (folder)
+  "Process outstanding commands for FOLDER.
+
+This function runs `mh-before-commands-processed-hook' before the
+commands are processed and `mh-after-commands-processed-hook'
+after the commands are processed."
+  (message "Processing deletes and refiles for %s..." folder)
+  (set-buffer folder)
+  (with-mh-folder-updating (nil)
+    ;; Run the before hook -- the refile and delete lists are still valid
+    (run-hooks 'mh-before-commands-processed-hook)
+
+    ;; Update the unseen sequence if it exists
+    (mh-update-unseen)
+
+    (let ((redraw-needed-flag mh-index-data)
+          (folders-changed (list mh-current-folder))
+          (seq-map (and mh-refile-list mh-refile-preserves-sequences-flag
+                        (mh-create-sequence-map mh-seq-list)))
+          (dest-map (and mh-refile-list mh-refile-preserves-sequences-flag
+                         (make-hash-table))))
+      ;; Remove invalid scan lines if we are in an index folder and then remove
+      ;; the real messages
+      (when mh-index-data
+        (mh-index-delete-folder-headers)
+        (setq folders-changed
+              (append folders-changed (mh-index-execute-commands))))
+
+      ;; Then refile messages
+      (mh-mapc #'(lambda (folder-msg-list)
+                   (let* ((dest-folder (symbol-name (car folder-msg-list)))
+                          (last (car (mh-translate-range dest-folder "last")))
+                          (msgs (cdr folder-msg-list)))
+                     (push dest-folder folders-changed)
+                     (setq redraw-needed-flag t)
+                     (apply #'mh-exec-cmd
+                            "refile" "-src" folder dest-folder
+                            (mh-coalesce-msg-list msgs))
+                     (mh-delete-scan-msgs msgs)
+                     ;; Preserve sequences in destination folder...
+                     (when mh-refile-preserves-sequences-flag
+                       (clrhash dest-map)
+                       (loop for i from (1+ (or last 0))
+                             for msg in (sort (copy-sequence msgs) #'<)
+                             do (loop for seq-name in (gethash msg seq-map)
+                                      do (push i (gethash seq-name dest-map))))
+                       (maphash
+                        #'(lambda (seq msgs)
+                            ;; Can't be run in the background, since the
+                            ;; current folder is changed by mark this could
+                            ;; lead to a race condition with the next refile.
+                            (apply #'mh-exec-cmd "mark"
+                                   "-sequence" (symbol-name seq) dest-folder
+                                   "-add" (mapcar #'(lambda (x) (format "%s" x))
+                                                  (mh-coalesce-msg-list msgs))))
+                        dest-map))))
+               mh-refile-list)
+      (setq mh-refile-list ())
+
+      ;; Now delete messages
+      (cond (mh-delete-list
+             (setq redraw-needed-flag t)
+             (apply 'mh-exec-cmd "rmm" folder
+                    (mh-coalesce-msg-list mh-delete-list))
+             (mh-delete-scan-msgs mh-delete-list)
+             (setq mh-delete-list nil)))
+
+      ;; Don't need to remove sequences since delete and refile do so.
+      ;; Mark cur message
+      (if (> (buffer-size) 0)
+          (mh-define-sequence 'cur (list (or (mh-get-msg-num nil) "last"))))
+
+      ;; Redraw folder buffer if needed
+      (when (and redraw-needed-flag)
+        (when (mh-speed-flists-active-p)
+          (apply #'mh-speed-flists t folders-changed))
+        (cond ((memq 'unthread mh-view-ops) (mh-thread-inc folder (point-max)))
+              (mh-index-data (mh-index-insert-folder-headers))))
+
+      (and (buffer-file-name (get-buffer mh-show-buffer))
+           (not (file-exists-p (buffer-file-name (get-buffer mh-show-buffer))))
+           ;; If "inc" were to put a new msg in this file,
+           ;; we would not notice, so mark it invalid now.
+           (mh-invalidate-show-buffer))
+
+      (setq mh-seq-list (mh-read-folder-sequences mh-current-folder nil))
+      (mh-remove-all-notation)
+      (mh-notate-user-sequences)
+
+      ;; Run the after hook -- now folders-changed is valid,
+      ;; but not the lists of specific messages.
+      (let ((mh-folders-changed folders-changed))
+        (run-hooks 'mh-after-commands-processed-hook)))
+
+    (message "Processing deletes and refiles for %s...done" folder)))
+
+(defun mh-delete-scan-msgs (msgs)
+  "Delete the scan listing lines for MSGS."
+  (save-excursion
+    (while msgs
+      (when (mh-goto-msg (car msgs) t t)
+        (when (memq 'unthread mh-view-ops)
+          (mh-thread-forget-message (car msgs)))
+        (mh-delete-line 1))
+      (setq msgs (cdr msgs)))))
+
+(defun mh-set-scan-mode ()
+  "Display the scan listing buffer, but do not show a message."
+  (if (get-buffer mh-show-buffer)
+      (delete-windows-on mh-show-buffer))
+  (mh-showing-mode 0)
+  (force-mode-line-update)
+  (if mh-recenter-summary-flag
+      (mh-recenter nil)))
+
+;;;###mh-autoload
+(defun mh-make-folder-mode-line (&optional ignored)
+  "Set the fields of the mode line for a folder buffer.
+The optional argument is now obsolete and IGNORED. It used to be
+used to pass in what is now stored in the buffer-local variable
+`mh-mode-line-annotation'."
+  (save-excursion
+    (save-window-excursion
+      (mh-first-msg)
+      (let ((new-first-msg-num (mh-get-msg-num nil)))
+        (when (or (not (memq 'unthread mh-view-ops))
+                  (null mh-first-msg-num)
+                  (null new-first-msg-num)
+                  (< new-first-msg-num mh-first-msg-num))
+          (setq mh-first-msg-num new-first-msg-num)))
+      (mh-last-msg)
+      (let ((new-last-msg-num (mh-get-msg-num nil)))
+        (when (or (not (memq 'unthread mh-view-ops))
+                  (null mh-last-msg-num)
+                  (null new-last-msg-num)
+                  (> new-last-msg-num mh-last-msg-num))
+          (setq mh-last-msg-num new-last-msg-num)))
+      (setq mh-msg-count (if mh-first-msg-num
+                             (count-lines (point-min) (point-max))
+                           0))
+      (setq mode-line-buffer-identification
+            (list (format "    {%%b%s} %s msg%s"
+                          (if mh-mode-line-annotation
+                              (format "/%s" mh-mode-line-annotation)
+                            "")
+                          (if (zerop mh-msg-count)
+                              "no"
+                            (format "%d" mh-msg-count))
+                          (if (zerop mh-msg-count)
+                              "s"
+                            (cond ((> mh-msg-count 1)
+                                   (format "s (%d-%d)" mh-first-msg-num
+                                           mh-last-msg-num))
+                                  (mh-first-msg-num
+                                   (format " (%d)" mh-first-msg-num))
+                                  (""))))))
+      (mh-logo-display))))
+
+;;;###mh-autoload
+(defun mh-scan-folder (folder range &optional dont-exec-pending)
+  "Scan FOLDER over RANGE.
+
+After the scan is performed, switch to the buffer associated with
+FOLDER.
+
+Check the documentation of `mh-interactive-range' to see how RANGE is
+read in interactive use.
+
+The processing of outstanding commands is not performed if
+DONT-EXEC-PENDING is non-nil."
+  (when (stringp range)
+    (setq range (delete "" (split-string range "[ \t\n]"))))
+  (cond ((null (get-buffer folder))
+         (mh-make-folder folder))
+        (t
+         (unless dont-exec-pending
+           (mh-process-or-undo-commands folder)
+           (mh-reset-threads-and-narrowing))
+         (switch-to-buffer folder)))
+  (mh-regenerate-headers range)
+  (if (zerop (buffer-size))
+      (if (equal range "all")
+          (message "Folder %s is empty" folder)
+        (message "No messages in %s, range %s" folder range))
+    (mh-goto-cur-msg))
+  (when (mh-outstanding-commands-p)
+    (mh-notate-deleted-and-refiled)))
+
+;;;###mh-autoload
+(defun mh-process-or-undo-commands (folder)
+  "If FOLDER has outstanding commands, then either process or discard them.
+Called by functions like `mh-sort-folder', so also invalidate
+show buffer."
+  (set-buffer folder)
+  (if (mh-outstanding-commands-p)
+      (if (or mh-do-not-confirm-flag
+              (y-or-n-p
+               "Process outstanding deletes and refiles? "))
+          (mh-process-commands folder)
+        (set-buffer folder)
+        (mh-undo-folder)))
+  (mh-update-unseen)
+  (mh-invalidate-show-buffer))
+
+;;;###mh-autoload
+(defun mh-regenerate-headers (range &optional update)
+  "Scan folder over RANGE.
+If UPDATE, append the scan lines, otherwise replace."
+  (let ((folder mh-current-folder)
+        (range (if (and range (atom range)) (list range) range))
+        scan-start)
+    (message "Scanning %s..." folder)
+    (mh-remove-all-notation)
+    (with-mh-folder-updating (nil)
+      (if update
+          (goto-char (point-max))
+        (delete-region (point-min) (point-max))
+        (if mh-adaptive-cmd-note-flag
+            (mh-set-cmd-note (mh-msg-num-width-to-column (mh-msg-num-width
+                                                          folder)))))
+      (setq scan-start (point))
+      (apply #'mh-exec-cmd-output
+             mh-scan-prog nil
+             (mh-scan-format)
+             "-noclear" "-noheader"
+             "-width" (window-width)
+             folder range)
+      (goto-char scan-start)
+      (cond ((looking-at "scan: no messages in")
+             (keep-lines mh-scan-valid-regexp)) ; Flush random scan lines
+            ((looking-at (if (mh-variant-p 'mu-mh)
+                             "scan: message set .* does not exist"
+                           "scan: bad message list "))
+             (keep-lines mh-scan-valid-regexp))
+            ((looking-at "scan: "))     ; Keep error messages
+            (t
+             (keep-lines mh-scan-valid-regexp))) ; Flush random scan lines
+      (setq mh-seq-list (mh-read-folder-sequences folder nil))
+      (mh-notate-user-sequences)
+      (or update
+          (setq mh-mode-line-annotation
+                (if (equal range '("all"))
+                    nil
+                  mh-partial-folder-mode-line-annotation)))
+      (mh-make-folder-mode-line))
+    (message "Scanning %s...done" folder)))
+
+;;;###mh-autoload
+(defun mh-reset-threads-and-narrowing ()
+  "Reset all variables pertaining to threads and narrowing.
+Also removes all content from the folder buffer."
+  (setq mh-view-ops ())
+  (setq mh-folder-view-stack ())
+  (setq mh-thread-scan-line-map-stack ())
+  (let ((buffer-read-only nil)) (erase-buffer)))
+
+(defun mh-make-folder (name)
+  "Create a new mail folder called NAME.
+Make it the current folder."
+  (switch-to-buffer name)
+  (setq buffer-read-only nil)
+  (erase-buffer)
+  (if mh-adaptive-cmd-note-flag
+      (mh-set-cmd-note (mh-msg-num-width-to-column (mh-msg-num-width name))))
+  (setq buffer-read-only t)
+  (mh-folder-mode)
+  (mh-set-folder-modified-p nil)
+  (setq buffer-file-name mh-folder-filename)
+  (when (and (not mh-index-data)
+             (file-exists-p (concat buffer-file-name mh-index-data-file)))
+    (mh-index-read-data))
+  (mh-make-folder-mode-line))
+
+;;;###mh-autoload
+(defun mh-next-msg (&optional wait-after-complaining-flag)
+  "Move backward or forward to the next undeleted message in the buffer.
+If optional argument WAIT-AFTER-COMPLAINING-FLAG is non-nil and
+we are at the last message, then wait for a second after telling
+the user that there aren't any more unread messages."
+  (if (eq mh-next-direction 'forward)
+      (mh-next-undeleted-msg 1 wait-after-complaining-flag)
+    (mh-previous-undeleted-msg 1 wait-after-complaining-flag)))
+
+;;;###mh-autoload
+(defun mh-prompt-for-refile-folder ()
+  "Prompt the user for a folder in which the message should be filed.
+The folder is returned as a string.
+
+The default folder name is generated by the option
+`mh-default-folder-for-message-function' if it is non-nil or
+`mh-folder-from-address'."
+  (mh-prompt-for-folder
+   "Destination"
+   (let ((refile-file (ignore-errors (mh-msg-filename (mh-get-msg-num t)))))
+     (if (null refile-file) ""
+       (save-excursion
+         (set-buffer (get-buffer-create mh-temp-buffer))
+         (erase-buffer)
+         (insert-file-contents refile-file)
+         (or (and mh-default-folder-for-message-function
+                  (let ((buffer-file-name refile-file))
+                    (funcall mh-default-folder-for-message-function)))
+             (mh-folder-from-address)
+             (and (eq 'refile (car mh-last-destination-folder))
+                  (symbol-name (cdr mh-last-destination-folder)))
+             ""))))
+   t))
+
+;;;###mh-autoload
+(defun mh-folder-from-address ()
+  "Derive folder name from sender.
+
+The name of the folder is derived as follows:
+
+  a) The folder name associated with the first address found in
+     the list `mh-default-folder-list' is used. Each element in
+     this list contains a \"Check Recipient\" item. If this item is
+     turned on, then the address is checked against the recipient
+     instead of the sender. This is useful for mailing lists.
+
+  b) An alias prefixed by `mh-default-folder-prefix'
+     corresponding to the address is used. The prefix is used to
+     prevent clutter in your mail directory.
+
+Return nil if a folder name was not derived, or if the variable
+`mh-default-folder-must-exist-flag' is t and the folder does not
+exist."
+  ;; Loop for all entries in mh-default-folder-list
+  (save-restriction
+    (goto-char (point-min))
+    (re-search-forward "\n\n" nil 'limit)
+    (narrow-to-region (point-min) (point))
+    (let ((to/cc (concat (or (message-fetch-field "to") "") ", "
+                         (or (message-fetch-field "cc") "")))
+          (from (or (message-fetch-field "from") ""))
+          folder-name)
+      (setq folder-name
+            (loop for list in mh-default-folder-list
+                  when (string-match (nth 0 list) (if (nth 2 list) to/cc from))
+                  return (nth 1 list)
+                  finally return nil))
+
+      ;; Make sure a result from `mh-default-folder-list' begins with "+"
+      ;; since 'mh-expand-file-name below depends on it
+      (when (and folder-name (not (eq (aref folder-name 0) ?+)))
+        (setq folder-name (concat "+" folder-name)))
+
+      ;; If not, is there an alias for the address?
+      (when (not folder-name)
+        (let* ((from-header (mh-extract-from-header-value))
+               (address (and from-header
+                             (nth 1 (mail-extract-address-components
+                                     from-header))))
+               (alias (and address (mh-alias-address-to-alias address))))
+          (when alias
+            (setq folder-name
+                  (and alias (concat "+" mh-default-folder-prefix alias))))))
+
+      ;; If mh-default-folder-must-exist-flag set, check that folder exists.
+      (if (and folder-name
+               (or (not mh-default-folder-must-exist-flag)
+                   (file-exists-p (mh-expand-file-name folder-name))))
+          folder-name))))
+
+;;;###mh-autoload
+(defun mh-delete-a-msg (message)
+  "Delete MESSAGE.
+If MESSAGE is nil then the message at point is deleted.
+The hook `mh-delete-msg-hook' is called after you mark a message
+for deletion. For example, a past maintainer of MH-E used this
+once when he kept statistics on his mail usage."
+  (save-excursion
+    (if (numberp message)
+        (mh-goto-msg message nil t)
+      (beginning-of-line)
+      (setq message (mh-get-msg-num t)))
+    (if (looking-at mh-scan-refiled-msg-regexp)
+        (error "Message %d is refiled; undo refile before deleting" message))
+    (if (looking-at mh-scan-deleted-msg-regexp)
+        nil
+      (mh-set-folder-modified-p t)
+      (setq mh-delete-list (cons message mh-delete-list))
+      (mh-notate nil mh-note-deleted mh-cmd-note)
+      (run-hooks 'mh-delete-msg-hook))))
+
+;;;###mh-autoload
+(defun mh-refile-a-msg (message folder)
+  "Refile MESSAGE in FOLDER.
+If MESSAGE is nil then the message at point is refiled.
+Folder is a symbol, not a string.
+The hook `mh-refile-msg-hook' is called after a message is marked to
+be refiled."
+  (save-excursion
+    (if (numberp message)
+        (mh-goto-msg message nil t)
+      (beginning-of-line)
+      (setq message (mh-get-msg-num t)))
+    (cond ((looking-at mh-scan-deleted-msg-regexp)
+           (error "Message %d is deleted; undo delete before moving" message))
+          ((looking-at mh-scan-refiled-msg-regexp)
+           (if (y-or-n-p
+                (format "Message %d already refiled; copy to %s as well? "
+                        message folder))
+               (mh-exec-cmd "refile" (mh-get-msg-num t) "-link"
+                            "-src" mh-current-folder
+                            (symbol-name folder))
+             (message "Message not copied")))
+          (t
+           (mh-set-folder-modified-p t)
+           (cond ((null (assoc folder mh-refile-list))
+                  (push (list folder message) mh-refile-list))
+                 ((not (member message (cdr (assoc folder mh-refile-list))))
+                  (push message (cdr (assoc folder mh-refile-list)))))
+           (mh-notate nil mh-note-refiled mh-cmd-note)
+           (run-hooks 'mh-refile-msg-hook)))))
+
+(defun mh-undo-msg (msg)
+  "Undo the deletion or refile of one MSG.
+If MSG is nil then act on the message at point"
+  (save-excursion
+    (if (numberp msg)
+        (mh-goto-msg msg t t)
+      (beginning-of-line)
+      (setq msg (mh-get-msg-num t)))
+    (cond ((memq msg mh-delete-list)
+           (setq mh-delete-list (delq msg mh-delete-list)))
+          (t
+           (dolist (folder-msg-list mh-refile-list)
+             (setf (cdr folder-msg-list) (remove msg (cdr folder-msg-list))))
+           (setq mh-refile-list (loop for x in mh-refile-list
+                                      unless (null (cdr x)) collect x))))
+    (mh-notate nil ?  mh-cmd-note)))
+
+;;;###mh-autoload
+(defun mh-msg-filename (msg &optional folder)
+  "Return the file name of MSG in FOLDER (default current folder)."
+  (expand-file-name (int-to-string msg)
+                    (if folder
+                        (mh-expand-file-name folder)
+                      mh-folder-filename)))
+
+(provide 'mh-folder)
+
+;; Local Variables:
+;; indent-tabs-mode: nil
+;; sentence-end-double-space: nil
+;; End:
+
+;; arch-tag: aa97b758-d4f6-4c86-bc5a-1950921da1e7
+;;; mh-folder.el ends here
--- a/lisp/mh-e/mh-funcs.el	Thu Jan 26 02:23:05 2006 +0000
+++ b/lisp/mh-e/mh-funcs.el	Wed Feb 01 10:07:17 2006 +0000
@@ -27,34 +27,19 @@
 
 ;;; Commentary:
 
-;; Internal support for MH-E package.
 ;; Putting these functions in a separate file lets MH-E start up faster,
 ;; since less Lisp code needs to be loaded all at once.
 
+;; Please add the functions in alphabetical order. If only one or two
+;; small support routines are needed, place them with the function;
+;; otherwise, create a separate section for them.
+
 ;;; Change Log:
 
 ;;; Code:
 
-;;(message "> mh-funcs")
-(eval-when-compile (require 'mh-acros))
-(mh-require-cl)
-(require 'mh-buffers)
 (require 'mh-e)
-;;(message "< mh-funcs")
-
-
-
-;;; Scan Line Formats
-
-(defvar mh-note-copied "C"
-  "Messages that have been copied are marked by this character.")
-
-(defvar mh-note-printed "P"
-  "Messages that have been printed are marked by this character.")
-
-
-
-;;; Functions
+(require 'mh-scan)
 
 ;;;###mh-autoload
 (defun mh-burst-digest ()
@@ -213,27 +198,6 @@
   (mh-regenerate-headers range))
 
 ;;;###mh-autoload
-(defun mh-pipe-msg (command include-header)
-  "Pipe message through shell command COMMAND.
-
-You are prompted for the Unix command through which you wish to
-run your message. If you give a prefix argument INCLUDE-HEADER to
-this command, the message header is included in the text passed
-to the command."
-  (interactive
-   (list (read-string "Shell command on message: ") current-prefix-arg))
-  (let ((msg-file-to-pipe (mh-msg-filename (mh-get-msg-num t)))
-        (message-directory default-directory))
-    (save-excursion
-      (set-buffer (get-buffer-create mh-temp-buffer))
-      (erase-buffer)
-      (insert-file-contents msg-file-to-pipe)
-      (goto-char (point-min))
-      (if (not include-header) (search-forward "\n\n"))
-      (let ((default-directory message-directory))
-        (shell-command-on-region (point) (point-max) command nil)))))
-
-;;;###mh-autoload
 (defun mh-page-digest ()
   "Display next message in digest."
   (interactive)
@@ -268,6 +232,27 @@
     (mh-recenter 0)))
 
 ;;;###mh-autoload
+(defun mh-pipe-msg (command include-header)
+  "Pipe message through shell command COMMAND.
+
+You are prompted for the Unix command through which you wish to
+run your message. If you give a prefix argument INCLUDE-HEADER to
+this command, the message header is included in the text passed
+to the command."
+  (interactive
+   (list (read-string "Shell command on message: ") current-prefix-arg))
+  (let ((msg-file-to-pipe (mh-msg-filename (mh-get-msg-num t)))
+        (message-directory default-directory))
+    (save-excursion
+      (set-buffer (get-buffer-create mh-temp-buffer))
+      (erase-buffer)
+      (insert-file-contents msg-file-to-pipe)
+      (goto-char (point-min))
+      (if (not include-header) (search-forward "\n\n"))
+      (let ((default-directory message-directory))
+        (shell-command-on-region (point) (point-max) command nil)))))
+
+;;;###mh-autoload
 (defun mh-sort-folder (&optional extra-args)
   "Sort folder.
 
@@ -289,21 +274,6 @@
           (mh-index-data (mh-index-insert-folder-headers)))))
 
 ;;;###mh-autoload
-(defun mh-undo-folder ()
-  "Undo all refiles and deletes in the current folder."
-  (interactive)
-  (cond ((or mh-do-not-confirm-flag
-             (yes-or-no-p "Undo all commands in folder? "))
-         (setq mh-delete-list nil
-               mh-refile-list nil
-               mh-seq-list nil
-               mh-next-direction 'forward)
-         (with-mh-folder-updating (nil)
-           (mh-remove-all-notation)))
-        (t
-         (message "Commands not undone"))))
-
-;;;###mh-autoload
 (defun mh-store-msg (directory)
   "Unpack message created with \"uudecode\" or \"shar\".
 
@@ -326,7 +296,6 @@
       (insert-file-contents msg-file-to-store)
       (mh-store-buffer directory))))
 
-;;;###mh-autoload
 (defun mh-store-buffer (directory)
   "Unpack buffer created with \"uudecode\" or \"shar\".
 
@@ -383,48 +352,20 @@
             (insert "\n(mh-store finished)\n"))
         (error "Error occurred during execution of %s" command)))))
 
-
-
-;;; Help Functions
-
 ;;;###mh-autoload
-(defun mh-ephem-message (string)
-  "Display STRING in the minibuffer momentarily."
-  (message "%s" string)
-  (sit-for 5)
-  (message ""))
-
-;;;###mh-autoload
-(defun mh-help ()
-  "Display cheat sheet for the MH-E commands."
+(defun mh-undo-folder ()
+  "Undo all refiles and deletes in the current folder."
   (interactive)
-  (with-electric-help
-   (function
-    (lambda ()
-      (insert
-       (substitute-command-keys
-        (mapconcat 'identity (cdr (assoc nil mh-help-messages)) ""))))
-    mh-help-buffer)))
-
-;;;###mh-autoload
-(defun mh-prefix-help ()
-  "Display cheat sheet for the commands of the current prefix in minibuffer."
-  (interactive)
-  ;; We got here because the user pressed a "?", but he pressed a prefix key
-  ;; before that. Since the the key vector starts at index 0, the index of the
-  ;; last keystroke is length-1 and thus the second to last keystroke is at
-  ;; length-2. We use that information to obtain a suitable prefix character
-  ;; from the recent keys.
-  (let* ((keys (recent-keys))
-         (prefix-char (elt keys (- (length keys) 2))))
-    (with-electric-help
-     (function
-      (lambda ()
-        (insert
-         (substitute-command-keys
-          (mapconcat 'identity
-                     (cdr (assoc prefix-char mh-help-messages)) "")))))
-     mh-help-buffer)))
+  (cond ((or mh-do-not-confirm-flag
+             (yes-or-no-p "Undo all commands in folder? "))
+         (setq mh-delete-list nil
+               mh-refile-list nil
+               mh-seq-list nil
+               mh-next-direction 'forward)
+         (with-mh-folder-updating (nil)
+           (mh-remove-all-notation)))
+        (t
+         (message "Commands not undone"))))
 
 (provide 'mh-funcs)
 
--- a/lisp/mh-e/mh-gnus.el	Thu Jan 26 02:23:05 2006 +0000
+++ b/lisp/mh-e/mh-gnus.el	Wed Feb 01 10:07:17 2006 +0000
@@ -1,4 +1,4 @@
-;;; mh-gnus.el --- Make MH-E compatible with installed version of Gnus.
+;;; mh-gnus.el --- make MH-E compatible with various versions of Gnus
 
 ;; Copyright (C) 2003, 2004, 2006 Free Software Foundation, Inc.
 
@@ -30,72 +30,70 @@
 
 ;;; Code:
 
-;;(message "> mh-gnus")
-(eval-when-compile (require 'mh-acros))
-;;(message "< mh-gnus")
+(require 'mh-e)
 
-;; Load libraries in a non-fatal way in order to see if certain functions are
-;; pre-defined.
-(load "mailabbrev" t t)
-(load "mailcap" t t)
-(load "mm-decode" t t)
-(load "mm-uu" t t)
-(load "mml" t t)
-(load "smiley" t t)
+(require 'gnus-util nil t)
+(require 'mm-bodies nil t)
+(require 'mm-decode nil t)
+(require 'mm-view nil t)
+(require 'mml nil t)
 
 ;; Copy of function from gnus-util.el.
-(mh-defun-compat gnus-local-map-property (map)
+(mh-defun-compat mh-gnus-local-map-property gnus-local-map-property (map)
   "Return a list suitable for a text property list specifying keymap MAP."
   (cond (mh-xemacs-flag (list 'keymap map))
         ((>= emacs-major-version 21) (list 'keymap map))
         (t (list 'local-map map))))
 
 ;; Copy of function from mm-decode.el.
-(mh-defun-compat mm-merge-handles (handles1 handles2)
+(mh-defun-compat mh-mm-merge-handles mm-merge-handles (handles1 handles2)
   (append (if (listp (car handles1)) handles1 (list handles1))
           (if (listp (car handles2)) handles2 (list handles2))))
 
 ;; Copy of function from mm-decode.el.
-(mh-defun-compat mm-set-handle-multipart-parameter (handle parameter value)
+(mh-defun-compat mh-mm-set-handle-multipart-parameter
+  mm-set-handle-multipart-parameter (handle parameter value)
   ;; HANDLE could be a CTL.
   (if handle
       (put-text-property 0 (length (car handle)) parameter value
                          (car handle))))
 
 ;; Copy of function from mm-view.el.
-(mh-defun-compat mm-inline-text-vcard (handle)
+(mh-defun-compat mh-mm-inline-text-vcard mm-inline-text-vcard (handle)
   (let (buffer-read-only)
     (mm-insert-inline
      handle
      (concat "\n-- \n"
-	     (ignore-errors
-	       (if (fboundp 'vcard-pretty-print)
-		   (vcard-pretty-print (mm-get-part handle))
-		 (vcard-format-string
-		  (vcard-parse-string (mm-get-part handle)
-				      'vcard-standard-filter))))))))
+             (ignore-errors
+               (if (fboundp 'vcard-pretty-print)
+                   (vcard-pretty-print (mm-get-part handle))
+                 (vcard-format-string
+                  (vcard-parse-string (mm-get-part handle)
+                                      'vcard-standard-filter))))))))
 
 ;; Function from mm-decode.el used in PGP messages. Just define it with older
 ;; Gnus to avoid compiler warning.
-(mh-defun-compat mm-possibly-verify-or-decrypt (parts ctl)
+(mh-defun-compat mh-mm-possibly-verify-or-decrypt
+  mm-possibly-verify-or-decrypt (parts ctl)
   nil)
 
 ;; Copy of macro in mm-decode.el.
-(mh-defmacro-compat mm-handle-multipart-ctl-parameter (handle parameter)
+(mh-defmacro-compat mh-mm-handle-multipart-ctl-parameter
+  mm-handle-multipart-ctl-parameter (handle parameter)
   `(get-text-property 0 ,parameter (car ,handle)))
 
 ;; Copy of function in mm-decode.el.
-(mh-defun-compat mm-readable-p (handle)
+(mh-defun-compat mh-mm-readable-p mm-readable-p (handle)
   "Say whether the content of HANDLE is readable."
   (and (< (with-current-buffer (mm-handle-buffer handle)
             (buffer-size)) 10000)
        (mm-with-unibyte-buffer
          (mm-insert-part handle)
          (and (eq (mm-body-7-or-8) '7bit)
-              (not (mm-long-lines-p 76))))))
+              (not (mh-mm-long-lines-p 76))))))
 
 ;; Copy of function in mm-bodies.el.
-(mh-defun-compat mm-long-lines-p (length)
+(mh-defun-compat mh-mm-long-lines-p mm-long-lines-p (length)
   "Say whether any of the lines in the buffer is longer than LENGTH."
   (save-excursion
     (goto-char (point-min))
@@ -107,17 +105,22 @@
     (and (> (current-column) length)
          (current-column))))
 
-(mh-defun-compat mm-keep-viewer-alive-p (handle)
+(mh-defun-compat mh-mm-keep-viewer-alive-p mm-keep-viewer-alive-p (handle)
   ;; Released Gnus doesn't keep handles associated with externally displayed
   ;; MIME parts. So this will always return nil.
   nil)
 
-(mh-defun-compat mm-destroy-parts (list)
+(mh-defun-compat mh-mm-destroy-parts mm-destroy-parts (list)
   "Older versions of Emacs don't have this function."
   nil)
 
+(mh-defun-compat mh-mm-uu-dissect-text-parts mm-uu-dissect-text-parts (handles)
+  "Emacs 21 and XEmacs don't have this function."
+  nil)
+
 ;; Copy of function in mml.el.
-(mh-defun-compat mml-minibuffer-read-disposition (type &optional default)
+(mh-defun-compat mh-mml-minibuffer-read-disposition
+  mml-minibuffer-read-disposition (type &optional default)
   (unless default (setq default
                         (if (and (string-match "\\`text/" type)
                                  (not (string-match "\\`text/rtf\\'" type)))
@@ -128,7 +131,7 @@
                       '(("attachment") ("inline") (""))
                       nil t nil nil default)))
     (if (not (equal disposition ""))
-	disposition
+        disposition
       default)))
 
 ;; This is mm-save-part from Gnus 5.10 since that function in emacs21.2 is
@@ -158,11 +161,6 @@
   (or (and (boundp 'mm-inline-text-html-renderer) mm-inline-text-html-renderer)
       (and (boundp 'mm-text-html-renderer) mm-text-html-renderer)))
 
-(defun mh-mail-abbrev-make-syntax-table ()
-  "Call `mail-abbrev-make-syntax-table' if available."
-  (when (fboundp 'mail-abbrev-make-syntax-table)
-    (mail-abbrev-make-syntax-table)))
-
 (provide 'mh-gnus)
 
 ;; Local Variables:
--- a/lisp/mh-e/mh-identity.el	Thu Jan 26 02:23:05 2006 +0000
+++ b/lisp/mh-e/mh-identity.el	Wed Feb 01 10:07:17 2006 +0000
@@ -1,4 +1,4 @@
-;;; mh-identity.el --- Multiple identify support for MH-E.
+;;; mh-identity.el --- multiple identify support for MH-E
 
 ;; Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
 
@@ -27,23 +27,19 @@
 ;;; Commentary:
 
 ;; Multiple identity support for MH-E.
-;;
-;; Used to easily set different fields such as From and Organization, as
-;; well as different signature files.
-;;
-;; Customize the variable `mh-identity-list' and an Identity menu will
-;; appear in mh-letter-mode.  The command 'mh-insert-identity can be used
-;; from the command line.
+
+;; Used to easily set different fields such as From and Organization,
+;; as well as different signature files.
+
+;; Customize the variable `mh-identity-list' and see the Identity menu
+;; in MH-Letter mode. The command `mh-insert-identity' can be used
+;; to manually insert an identity.
 
 ;;; Change Log:
 
 ;;; Code:
 
-;;(message "> mh-identity")
-(eval-when-compile (require 'mh-acros))
-
-(require 'mh-comp)
-;;(message "< mh-identity")
+(require 'mh-e)
 
 (autoload 'mml-insert-tag "mml")
 
@@ -53,11 +49,17 @@
 `mh-identity-list'.")
 (make-variable-buffer-local 'mh-identity-pgg-default-user-id)
 
+(defvar mh-identity-menu nil
+  "The Identity menu.")
+
+(defalias 'mh-identity-make-menu-no-autoload 'mh-identity-make-menu)
+
 ;;;###mh-autoload
 (defun mh-identity-make-menu ()
   "Build the Identity menu.
 This should be called any time `mh-identity-list' or
-`mh-auto-fields-list' change."
+`mh-auto-fields-list' change.
+See `mh-identity-add-menu'."
   (easy-menu-define mh-identity-menu mh-letter-mode-map
     "MH-E identity menu"
     (append
@@ -88,13 +90,11 @@
        ))))
 
 ;;;###mh-autoload
-(defun mh-identity-list-set (symbol value)
-  "Update the `mh-identity-list' variable, and rebuild the menu.
-Sets the default for SYMBOL (for example, `mh-identity-list') to
-VALUE (as set in customization). This is called after 'customize
-is used to alter `mh-identity-list'."
-  (set-default symbol value)
-  (mh-identity-make-menu))
+(defun mh-identity-add-menu ()
+  "Add the current Identity menu.
+See `mh-identity-make-menu'."
+  (if mh-identity-menu
+      (easy-menu-add mh-identity-menu)))
 
 (defvar mh-identity-local nil
   "Buffer-local variable that holds the identity currently in use.")
@@ -127,15 +127,20 @@
 character \":\", then it must have a special handler defined in
 `mh-identity-handlers', else return an error since it is not a
 valid header field."
-  (or (cdr (assoc-string field mh-identity-handlers t))
+  (or (cdr (mh-assoc-string field mh-identity-handlers t))
       (and (eq (aref field 0) ?:)
            (error "Field %s not found in `mh-identity-handlers'" field))
       (cdr (assoc ":default" mh-identity-handlers))
       'mh-identity-handler-default))
 
 ;;;###mh-autoload
-(defun mh-insert-identity (identity)
+(defun mh-insert-identity (identity &optional maybe-insert)
   "Insert fields specified by given IDENTITY.
+
+In a program, do not insert fields if MAYBE-INSERT is non-nil,
+`mh-identity-default' is non-nil, and fields have already been
+inserted.
+
 See `mh-identity-list'."
   (interactive
    (list (completing-read
@@ -144,29 +149,35 @@
               (cons '("None")
                     (mapcar 'list (mapcar 'car mh-identity-list)))
             (mapcar 'list (mapcar 'car mh-identity-list)))
-          nil t)))
-  (save-excursion
-    ;;First remove old settings, if any.
-    (when mh-identity-local
-      (let ((pers-list (cadr (assoc mh-identity-local mh-identity-list))))
-        (while pers-list
-          (let* ((field (caar pers-list))
-                 (handler (mh-identity-field-handler field)))
-            (funcall handler field 'remove))
-          (setq pers-list (cdr pers-list)))))
-    ;; Then insert the replacement
-    (when (not (equal "None" identity))
-      (let ((pers-list (cadr (assoc identity mh-identity-list))))
-        (while pers-list
-          (let* ((field (caar pers-list))
-                 (value (cdar pers-list))
-                 (handler (mh-identity-field-handler field)))
-            (funcall handler field 'add value))
-          (setq pers-list (cdr pers-list))))))
-  ;; Remember what is in use in this buffer
-  (if (equal "None" identity)
-      (setq mh-identity-local nil)
-    (setq mh-identity-local identity)))
+          nil t)
+         nil))
+
+  (when (or (not maybe-insert)
+            (and (boundp 'mh-identity-default)
+                 mh-identity-default
+                 (not mh-identity-local)))
+    (save-excursion
+      ;;First remove old settings, if any.
+      (when mh-identity-local
+        (let ((pers-list (cadr (assoc mh-identity-local mh-identity-list))))
+          (while pers-list
+            (let* ((field (caar pers-list))
+                   (handler (mh-identity-field-handler field)))
+              (funcall handler field 'remove))
+            (setq pers-list (cdr pers-list)))))
+      ;; Then insert the replacement
+      (when (not (equal "None" identity))
+        (let ((pers-list (cadr (assoc identity mh-identity-list))))
+          (while pers-list
+            (let* ((field (caar pers-list))
+                   (value (cdar pers-list))
+                   (handler (mh-identity-field-handler field)))
+              (funcall handler field 'add value))
+            (setq pers-list (cdr pers-list))))))
+    ;; Remember what is in use in this buffer
+    (if (equal "None" identity)
+        (setq mh-identity-local nil)
+      (setq mh-identity-local identity))))
 
 ;;;###mh-autoload
 (defun mh-identity-handler-gpg-identity (field action &optional value)
@@ -268,7 +279,7 @@
        (t
         (goto-char (point-min))
         (if (not top)
-	    (mh-goto-header-end 0))
+            (mh-goto-header-end 0))
         (insert field-colon " " value "\n")))))))
 
 ;;;###mh-autoload
--- a/lisp/mh-e/mh-inc.el	Thu Jan 26 02:23:05 2006 +0000
+++ b/lisp/mh-e/mh-inc.el	Wed Feb 01 10:07:17 2006 +0000
@@ -1,5 +1,5 @@
 ;;; mh-inc.el --- MH-E "inc" and separate mail spool handling
-;;
+
 ;; Copyright (C) 2003, 2004, 2006 Free Software Foundation, Inc.
 
 ;; Author: Peter S. Galbraith <psg@debian.org>
@@ -26,33 +26,42 @@
 
 ;;; Commentary:
 
-;;  Support for inc. In addition to reading from the system mailbox, inc can
-;;  also be used to incorporate mail from multiple spool files into separate
-;;  folders. See "C-h v mh-inc-spool-list".
+;; Support for inc. In addition to reading from the system mailbox,
+;; inc can also be used to incorporate mail from multiple spool files
+;; into separate folders. See "C-h v mh-inc-spool-list".
 
 ;;; Change Log:
 
 ;;; Code:
 
-;;(message "> mh-inc")
-(eval-when-compile (require 'mh-acros))
+(require 'mh-e)
 (mh-require-cl)
-;;(message "< mh-inc")
-
-(defvar mh-inc-spool-map (make-sparse-keymap)
-  "Keymap for MH-E's mh-inc-spool commands.")
 
 (defvar mh-inc-spool-map-help nil
-  "Help text to for `mh-inc-spool-map'.")
+  "Help text for `mh-inc-spool-map'.")
 
 (define-key mh-inc-spool-map "?"
   '(lambda ()
      (interactive)
      (if mh-inc-spool-map-help
-         (let ((mh-help-messages (list (list nil mh-inc-spool-map-help))))
-           (mh-help))
+         (mh-help mh-inc-spool-map-help)
        (mh-ephem-message
-        "There are no keys defined yet.  Customize `mh-inc-spool-list'"))))
+        "There are no keys defined yet; customize `mh-inc-spool-list'"))))
+
+;;;###mh-autoload
+(defun mh-inc-spool-make ()
+  "Make all commands and defines keys for contents of `mh-inc-spool-list'."
+  (setq mh-inc-spool-map-help nil)
+  (when mh-inc-spool-list
+    (loop for elem in mh-inc-spool-list
+          do (let ((spool (nth 0 elem))
+                   (folder (nth 1 elem))
+                   (key (nth 2 elem)))
+               (progn
+                 (mh-inc-spool-generator folder spool)
+                 (mh-inc-spool-def-key key folder))))))
+
+(defalias 'mh-inc-spool-make-no-autoload 'mh-inc-spool-make)
 
 (defun mh-inc-spool-generator (folder spool)
   "Create a command to inc into FOLDER from SPOOL file."
@@ -62,7 +71,7 @@
     (set spool1 spool)
     (setf (symbol-function (intern (concat "mh-inc-spool-" folder)))
           `(lambda ()
-             ,(format "Inc spool file %s into folder %s" spool folder)
+             ,(format "Inc spool file %s into folder %s." spool folder)
              (interactive)
              (mh-inc-folder ,spool1 (concat "+" ,folder1))))))
 
@@ -71,32 +80,9 @@
   (when (not (= 0 key))
     (define-key mh-inc-spool-map (format "%c" key)
        (intern (concat "mh-inc-spool-" folder)))
-    (setq mh-inc-spool-map-help (concat mh-inc-spool-map-help "["
-                                        (char-to-string key)
-                                        "] inc " folder " folder\n"))))
-
-;; Shush compiler.
-(eval-when-compile (defvar mh-inc-spool-list))
-
-(defun mh-inc-spool-make ()
-  "Make all commands and defines keys for contents of `mh-inc-spool-list'."
-  (when mh-inc-spool-list
-    (setq mh-inc-spool-map-help nil)
-    (loop for elem in mh-inc-spool-list
-          do (let ((spool (nth 0 elem))
-                   (folder (nth 1 elem))
-                   (key (nth 2 elem)))
-               (progn
-                 (mh-inc-spool-generator folder spool)
-                 (mh-inc-spool-def-key key folder))))))
-
-;;;###mh-autoload
-(defun mh-inc-spool-list-set (symbol value)
-  "Set-default SYMBOL to VALUE to update the `mh-inc-spool-list' variable.
-Also rebuilds the user commands.
-This is called after 'customize is used to alter `mh-inc-spool-list'."
-  (set-default symbol value)
-  (mh-inc-spool-make))
+    (add-to-list 'mh-inc-spool-map-help
+                 (concat "[" (char-to-string key) "] inc " folder " folder\n")
+                 t)))
 
 (provide 'mh-inc)
 
--- a/lisp/mh-e/mh-init.el	Thu Jan 26 02:23:05 2006 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,441 +0,0 @@
-;;; mh-init.el --- MH-E initialization
-
-;; Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
-
-;; Author: Peter S. Galbraith <psg@debian.org>
-;; Maintainer: Bill Wohler <wohler@newt.com>
-;; Keywords: mail
-;; See: mh-e.el
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING.  If not, write to the
-;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
-;; Boston, MA 02110-1301, USA.
-
-;;; Commentary:
-
-;; Sets up the MH variant (currently nmh, MH, or GNU mailutils).
-;;
-;; Users may customize `mh-variant' to switch between available variants.
-;; Available MH variants are returned by the function `mh-variants'.
-;; Developers may check which variant is currently in use with the
-;; variable `mh-variant-in-use' or the function `mh-variant-p'.
-;;
-;; Also contains code that is used at load or initialization time only.
-
-;;; Change Log:
-
-;;; Code:
-
-;;(message "> mh-init")
-(eval-when-compile (require 'mh-acros))
-(mh-require-cl)
-(require 'mh-buffers)
-(require 'mh-exec)
-;;(message "< mh-init")
-
-(defvar mh-sys-path
-  '("/usr/local/nmh/bin"                ; nmh default
-    "/usr/local/bin/mh/"
-    "/usr/local/mh/"
-    "/usr/bin/mh/"                      ; Ultrix 4.2, Linux
-    "/usr/new/mh/"                      ; Ultrix < 4.2
-    "/usr/contrib/mh/bin/"              ; BSDI
-    "/usr/pkg/bin/"                     ; NetBSD
-    "/usr/local/bin/"
-    "/usr/local/bin/mu-mh/"             ; GNU mailutils - default
-    "/usr/bin/mu-mh/")                  ; GNU mailutils - packaged
-  "List of directories to search for variants of the MH variant.
-The list `exec-path' is searched in addition to this list.
-There's no need for users to modify this list. Instead add extra
-directories to the customizable variable `mh-path'.")
-
-;; Set for local environment:
-;; mh-progs and mh-lib used to be set in paths.el, which tried to
-;; figure out at build time which of several possible directories MH
-;; was installed into.  But if you installed MH after building Emacs,
-;; this would almost certainly be wrong, so now we do it at run time.
-
-(defvar mh-flists-present-flag nil
-  "Non-nil means that we have \"flists\".")
-
-(defvar mh-variants nil
-  "List describing known MH variants.
-Do not access this variable directly as it may not have yet been initialized.
-Use the function `mh-variants' instead.")
-
-;;;###mh-autoload
-(defun mh-variants ()
-  "Return a list of installed variants of MH on the system.
-This function looks for MH in `mh-sys-path', `mh-path' and
-`exec-path'. The format of the list of variants that is returned
-is described by the variable `mh-variants'."
-  (if mh-variants
-      mh-variants
-    (let ((list-unique))
-      ;; Make a unique list of directories, keeping the given order.
-      ;; We don't want the same MH variant to be listed multiple times.
-      (loop for dir in (append mh-path mh-sys-path exec-path) do
-            (setq dir (file-chase-links (directory-file-name dir)))
-            (add-to-list 'list-unique dir))
-      (loop for dir in (nreverse list-unique) do
-            (when (and dir (file-directory-p dir) (file-readable-p dir))
-              (let ((variant (mh-variant-info dir)))
-                (if variant
-                    (add-to-list 'mh-variants variant)))))
-      mh-variants)))
-
-(defun mh-variant-info (dir)
-  "Return MH variant found in DIR, or nil if none present."
-  (save-excursion
-    (let ((tmp-buffer (get-buffer-create mh-temp-buffer)))
-      (set-buffer tmp-buffer)
-      (cond
-       ((mh-variant-mh-info dir))
-       ((mh-variant-nmh-info dir))
-       ((mh-variant-mu-mh-info dir))))))
-
-(defun mh-variant-mh-info (dir)
-  "Return info for MH variant in DIR assuming a temporary buffer is setup."
-  ;; MH does not have the -version option.
-  ;; Its version number is included in the output of "-help" as:
-  ;;
-  ;; version: MH 6.8.4 #2[UCI] (burrito) of Fri Jan 15 20:01:39 EST 1999
-  ;; options: [ATHENA] [BIND] [DUMB] [LIBLOCKFILE] [LOCALE] [MAILGROUP] [MHE]
-  ;;          [MHRC] [MIME] [MORE='"/usr/bin/sensible-pager"'] [NLINK_HACK]
-  ;;          [NORUSERPASS] [OVERHEAD] [POP] [POPSERVICE='"pop-3"'] [RENAME]
-  ;;          [RFC1342] [RPATHS] [RPOP] [SENDMTS] [SMTP] [SOCKETS]
-  ;;          [SPRINTFTYPE=int] [SVR4] [SYS5] [SYS5DIR] [TERMINFO]
-  ;;          [TYPESIG=void] [UNISTD] [UTK] [VSPRINTF]
-  (let ((mhparam (expand-file-name "mhparam" dir)))
-    (when (mh-file-command-p mhparam)
-      (erase-buffer)
-      (call-process mhparam nil '(t nil) nil "-help")
-      (goto-char (point-min))
-      (when (search-forward-regexp "version: MH \\(\\S +\\)" nil t)
-        (let ((version (format "MH %s" (match-string 1))))
-          (erase-buffer)
-          (call-process mhparam nil '(t nil) nil "libdir")
-          (goto-char (point-min))
-          (when (search-forward-regexp "^.*$" nil t)
-            (let ((libdir (match-string 0)))
-              `(,version
-                (variant        mh)
-                (mh-lib-progs   ,libdir)
-                (mh-lib         ,libdir)
-                (mh-progs       ,dir)
-                (flists         nil)))))))))
-
-(defun mh-variant-mu-mh-info (dir)
-  "Return info for GNU mailutils variant in DIR.
-This assumes that a temporary buffer is setup."
-  ;; 'mhparam -version' output:
-  ;; mhparam (GNU mailutils 0.3.2)
-  (let ((mhparam (expand-file-name "mhparam" dir)))
-    (when (mh-file-command-p mhparam)
-      (erase-buffer)
-      (call-process mhparam nil '(t nil) nil "-version")
-      (goto-char (point-min))
-      (when (search-forward-regexp "mhparam (\\(GNU [Mm]ailutils \\S +\\))"
-                                   nil t)
-        (let ((version (match-string 1))
-              (mh-progs dir))
-          `(,version
-            (variant        mu-mh)
-            (mh-lib-progs   ,(mh-profile-component "libdir"))
-            (mh-lib         ,(mh-profile-component "etcdir"))
-            (mh-progs       ,dir)
-            (flists         ,(file-exists-p
-                              (expand-file-name "flists" dir)))))))))
-
-(defun mh-variant-nmh-info (dir)
-  "Return info for nmh variant in DIR assuming a temporary buffer is setup."
-  ;; `mhparam -version' outputs:
-  ;; mhparam -- nmh-1.1-RC1 [compiled on chaak at Fri Jun 20 11:03:28 PDT 2003]
-  (let ((mhparam (expand-file-name "mhparam" dir)))
-    (when (mh-file-command-p mhparam)
-      (erase-buffer)
-      (call-process mhparam nil '(t nil) nil "-version")
-      (goto-char (point-min))
-      (when (search-forward-regexp "mhparam -- nmh-\\(\\S +\\)" nil t)
-        (let ((version (format "nmh %s" (match-string 1)))
-              (mh-progs dir))
-          `(,version
-            (variant        nmh)
-            (mh-lib-progs   ,(mh-profile-component "libdir"))
-            (mh-lib         ,(mh-profile-component "etcdir"))
-            (mh-progs       ,dir)
-            (flists         ,(file-exists-p
-                              (expand-file-name "flists" dir)))))))))
-
-(defun mh-file-command-p (file)
-  "Return t if file FILE is the name of a executable regular file."
-  (and (file-regular-p file) (file-executable-p file)))
-
-(defvar mh-variant-in-use nil
-  "The MH variant currently in use; a string with variant and version number.
-This differs from `mh-variant' when the latter is set to
-\"autodetect\".")
-
-;;;###mh-autoload
-(defun mh-variant-set (variant)
-  "Set the MH variant to VARIANT.
-Sets `mh-progs', `mh-lib', `mh-lib-progs' and
-`mh-flists-present-flag'.
-If the VARIANT is \"autodetect\", then first try nmh, then MH and
-finally GNU mailutils."
-  (interactive
-   (list (completing-read
-          "MH variant: "
-          (mapcar (lambda (x) (list (car x))) (mh-variants))
-          nil t)))
-  (let ((valid-list (mapcar (lambda (x) (car x)) (mh-variants))))
-    (cond
-     ((eq variant 'none))
-     ((eq variant 'autodetect)
-      (cond
-       ((mh-variant-set-variant 'nmh)
-        (message "%s installed as MH variant" mh-variant-in-use))
-       ((mh-variant-set-variant 'mh)
-        (message "%s installed as MH variant" mh-variant-in-use))
-       ((mh-variant-set-variant 'mu-mh)
-        (message "%s installed as MH variant" mh-variant-in-use))
-       (t
-        (message "No MH variant found on the system"))))
-     ((member variant valid-list)
-      (when (not (mh-variant-set-variant variant))
-        (message "Warning: %s variant not found. Autodetecting..." variant)
-        (mh-variant-set 'autodetect)))
-     (t
-      (message "Unknown variant; use %s"
-               (mapconcat '(lambda (x) (format "%s" (car x)))
-                          (mh-variants) " or "))))))
-
-(defun mh-variant-set-variant (variant)
-  "Setup the system variables for the MH variant named VARIANT.
-If VARIANT is a string, use that key in the alist returned by the
-function `mh-variants'.
-If VARIANT is a symbol, select the first entry that matches that
-variant."
-  (cond
-   ((stringp variant)                   ;e.g. "nmh 1.1-RC1"
-    (when (assoc variant (mh-variants))
-      (let* ((alist (cdr (assoc variant (mh-variants))))
-             (lib-progs (cadr (assoc 'mh-lib-progs alist)))
-             (lib       (cadr (assoc 'mh-lib       alist)))
-             (progs     (cadr (assoc 'mh-progs     alist)))
-             (flists    (cadr (assoc 'flists       alist))))
-        ;;(set-default mh-variant variant)
-        (setq mh-x-mailer-string     nil
-              mh-flists-present-flag flists
-              mh-lib-progs           lib-progs
-              mh-lib                 lib
-              mh-progs               progs
-              mh-variant-in-use      variant))))
-   ((symbolp variant)                   ;e.g. 'nmh (pick the first match)
-    (loop for variant-list in (mh-variants)
-          when (eq variant (cadr (assoc 'variant (cdr variant-list))))
-          return (let* ((version   (car variant-list))
-                        (alist (cdr variant-list))
-                        (lib-progs (cadr (assoc 'mh-lib-progs alist)))
-                        (lib       (cadr (assoc 'mh-lib       alist)))
-                        (progs     (cadr (assoc 'mh-progs     alist)))
-                        (flists    (cadr (assoc 'flists       alist))))
-                   ;;(set-default mh-variant flavor)
-                   (setq mh-x-mailer-string     nil
-                         mh-flists-present-flag flists
-                         mh-lib-progs           lib-progs
-                         mh-lib                 lib
-                         mh-progs               progs
-                         mh-variant-in-use      version)
-                   t)))))
-
-;;;###mh-autoload
-(defun mh-variant-p (&rest variants)
-  "Return t if variant is any of VARIANTS.
-Currently known variants are 'MH, 'nmh, and 'mu-mh."
-  (let ((variant-in-use
-         (cadr (assoc 'variant (assoc mh-variant-in-use (mh-variants))))))
-    (not (null (member variant-in-use variants)))))
-
-
-
-;;; Read MH Profile
-
-(defvar mh-find-path-run nil
-  "Non-nil if `mh-find-path' has been run already.
-Do not access this variable; `mh-find-path' already uses it to
-avoid running more than once.")
-
-(defun mh-find-path ()
-  "Set variables from user's MH profile.
-
-This function sets `mh-user-path' from your \"Path:\" MH profile
-component (but defaults to \"Mail\" if one isn't present),
-`mh-draft-folder' from \"Draft-Folder:\", `mh-unseen-seq' from
-\"Unseen-Sequence:\", `mh-previous-seq' from
-\"Previous-Sequence:\", and `mh-inbox' from \"Inbox:\" (defaults
-to \"+inbox\").
-
-The hook `mh-find-path-hook' is run after these variables have
-been set. This hook can be used the change the value of these
-variables if you need to run with different values between MH and
-MH-E."
-  (unless mh-find-path-run
-    ;; Sanity checks.
-    (if (and (getenv "MH")
-             (not (file-readable-p (getenv "MH"))))
-        (error "MH environment variable contains unreadable file %s"
-               (getenv "MH")))
-    (if (null (mh-variants))
-        (error "Install MH and run install-mh before running MH-E"))
-    (let ((profile "~/.mh_profile"))
-      (if (not (file-readable-p profile))
-          (error "Run install-mh before running MH-E")))
-    ;; Read MH profile.
-    (setq mh-user-path (mh-profile-component "Path"))
-    (if (not mh-user-path)
-        (setq mh-user-path "Mail"))
-    (setq mh-user-path
-          (file-name-as-directory
-           (expand-file-name mh-user-path (expand-file-name "~"))))
-    (unless mh-x-image-cache-directory
-      (setq mh-x-image-cache-directory
-            (expand-file-name ".mhe-x-image-cache" mh-user-path)))
-    (setq mh-draft-folder (mh-profile-component "Draft-Folder"))
-    (if mh-draft-folder
-        (progn
-          (if (not (mh-folder-name-p mh-draft-folder))
-              (setq mh-draft-folder (format "+%s" mh-draft-folder)))
-          (if (not (file-exists-p (mh-expand-file-name mh-draft-folder)))
-              (error
-               "Draft folder \"%s\" not found; create it and try again"
-               (mh-expand-file-name mh-draft-folder)))))
-    (setq mh-inbox (mh-profile-component "Inbox"))
-    (cond ((not mh-inbox)
-           (setq mh-inbox "+inbox"))
-          ((not (mh-folder-name-p mh-inbox))
-           (setq mh-inbox (format "+%s" mh-inbox))))
-    (setq mh-unseen-seq (mh-profile-component "Unseen-Sequence"))
-    (if mh-unseen-seq
-        (setq mh-unseen-seq (intern mh-unseen-seq))
-      (setq mh-unseen-seq 'unseen))     ;old MH default?
-    (setq mh-previous-seq (mh-profile-component "Previous-Sequence"))
-    (if mh-previous-seq
-        (setq mh-previous-seq (intern mh-previous-seq)))
-    (run-hooks 'mh-find-path-hook)
-    (mh-collect-folder-names)
-    (setq mh-find-path-run t)))
-
-
-
-;;; MH profile
-
-(defun mh-profile-component (component)
-  "Return COMPONENT value from mhparam, or nil if unset."
-  (save-excursion
-    (mh-exec-cmd-quiet nil "mhparam" "-components" component)
-    (mh-profile-component-value component)))
-
-(defun mh-profile-component-value (component)
-  "Find and return the value of COMPONENT in the current buffer.
-Returns nil if the component is not in the buffer."
-  (let ((case-fold-search t))
-    (goto-char (point-min))
-    (cond ((not (re-search-forward (format "^%s:" component) nil t)) nil)
-          ((looking-at "[\t ]*$") nil)
-          (t
-           (re-search-forward "[\t ]*\\([^\t \n].*\\)$" nil t)
-           (let ((start (match-beginning 1)))
-             (end-of-line)
-             (buffer-substring start (point)))))))
-
-
-
-;;; MH-E images
-
-;; Shush compiler.
-(eval-when-compile (defvar image-load-path))
-
-(defvar mh-image-load-path-called-flag nil)
-
-;;;###mh-autoload
-(defun mh-image-load-path ()
-  "Ensure that the MH-E images are accessible by `find-image'.
-Images for MH-E are found in ../../etc/images relative to the
-files in \"lisp/mh-e\". If `image-load-path' exists (since Emacs
-22), then the images directory is added to it if isn't already
-there. Otherwise, the images directory is added to the
-`load-path' if it isn't already there."
-  (unless mh-image-load-path-called-flag
-    (let (mh-library-name mh-image-load-path)
-      ;; First, find mh-e in the load-path.
-      (setq mh-library-name (locate-library "mh-e"))
-      (if (not mh-library-name)
-        (error "Can not find MH-E in load-path"))
-      (setq mh-image-load-path
-            (expand-file-name (concat (file-name-directory mh-library-name)
-                                      "../../etc/images")))
-      (if (not (file-exists-p mh-image-load-path))
-          (error "Can not find image directory %s" mh-image-load-path))
-      (if (boundp 'image-load-path)
-          (add-to-list 'image-load-path mh-image-load-path)
-        (add-to-list 'load-path mh-image-load-path)))
-    (setq mh-image-load-path-called-flag t)))
-
-
-
-;;; Support routines for mh-customize.el
-
-(defvar mh-min-colors-defined-flag (and (not mh-xemacs-flag)
-                                        (>= emacs-major-version 22))
-  "Non-nil means defface supports min-colors display requirement.")
-
-(defun mh-defface-compat (spec)
-  "Convert SPEC for defface if necessary to run on older platforms.
-Modifies SPEC in place and returns it. See `defface' for the spec definition.
-
-When `mh-min-colors-defined-flag' is nil, this function finds
-display entries with \"min-colors\" requirements and either
-removes the \"min-colors\" requirement or strips the display
-entirely if the display does not support the number of specified
-colors."
-  (if mh-min-colors-defined-flag
-      spec
-    (let ((cells (display-color-cells))
-          new-spec)
-      ;; Remove entries with min-colors, or delete them if we have fewer colors
-      ;; than they specify.
-      (loop for entry in (reverse spec) do
-            (let ((requirement (if (eq (car entry) t)
-                                   nil
-                                 (assoc 'min-colors (car entry)))))
-              (if requirement
-                  (when (>= cells (nth 1 requirement))
-                    (setq new-spec (cons (cons (delq requirement (car entry))
-                                               (cdr entry))
-                                         new-spec)))
-                (setq new-spec (cons entry new-spec)))))
-      new-spec)))
-
-(provide 'mh-init)
-
-;; Local Variables:
-;; indent-tabs-mode: nil
-;; sentence-end-double-space: nil
-;; End:
-
-;; arch-tag: e8372aeb-d803-42b1-9c95-3c93ad22f63c
-;;; mh-init.el ends here
--- a/lisp/mh-e/mh-junk.el	Thu Jan 26 02:23:05 2006 +0000
+++ b/lisp/mh-e/mh-junk.el	Wed Feb 01 10:07:17 2006 +0000
@@ -1,4 +1,4 @@
-;;; mh-junk.el --- Interface to anti-spam measures
+;;; mh-junk.el --- MH-E interface to anti-spam measures
 
 ;; Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
 
@@ -32,14 +32,10 @@
 
 ;;; Code:
 
-;;(message "< mh-junk")
-(eval-when-compile (require 'mh-acros))
+(require 'mh-e)
+(require 'mh-scan)
 (mh-require-cl)
-(require 'mh-buffers)
-(require 'mh-e)
-;;(message "> mh-junk")
 
-;; Interactive functions callable from the folder buffer
 ;;;###mh-autoload
 (defun mh-junk-blacklist (range)
   "Blacklist RANGE as spam.
@@ -108,6 +104,7 @@
 (defvar mh-spamassassin-executable (executable-find "spamassassin"))
 (defvar mh-sa-learn-executable (executable-find "sa-learn"))
 
+;;;###mh-autoload
 (defun mh-spamassassin-blacklist (msg)
   "Blacklist MSG with SpamAssassin.
 
@@ -189,7 +186,7 @@
 will need to run \"sa-learn --rebuild\" periodically. This can be
 done by adding the following to your crontab:
 
-    0 * * * *	sa-learn --rebuild > /dev/null 2>&1"
+    0 * * * *   sa-learn --rebuild > /dev/null 2>&1"
   (unless mh-spamassassin-executable
     (error "Unable to find the spamassassin executable"))
   (let ((current-folder mh-current-folder)
@@ -220,6 +217,7 @@
             (message "Blacklisting message %d...done" msg))
         (message "Blacklisting message %d...not done (from my address)" msg)))))
 
+;;;###mh-autoload
 (defun mh-spamassassin-whitelist (msg)
   "Whitelist MSG with SpamAssassin.
 
@@ -273,6 +271,7 @@
       (if (not buffer-exists)
           (kill-buffer nil)))))
 
+;;;###mh-autoload
 (defun mh-spamassassin-identify-spammers ()
   "Identify spammers who are repeat offenders.
 
@@ -322,6 +321,7 @@
 
 (defvar mh-bogofilter-executable (executable-find "bogofilter"))
 
+;;;###mh-autoload
 (defun mh-bogofilter-blacklist (msg)
   "Blacklist MSG with bogofilter.
 
@@ -375,6 +375,7 @@
     (call-process mh-bogofilter-executable msg-file mh-junk-background
                   nil "-s")))
 
+;;;###mh-autoload
 (defun mh-bogofilter-whitelist (msg)
   "Whitelist MSG with bogofilter.
 
@@ -391,6 +392,7 @@
 
 (defvar mh-spamprobe-executable (executable-find "spamprobe"))
 
+;;;###mh-autoload
 (defun mh-spamprobe-blacklist (msg)
   "Blacklist MSG with SpamProbe.
 
@@ -421,6 +423,7 @@
     (call-process mh-spamprobe-executable msg-file mh-junk-background
                   nil "spam")))
 
+;;;###mh-autoload
 (defun mh-spamprobe-whitelist (msg)
   "Whitelist MSG with SpamProbe.
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lisp/mh-e/mh-letter.el	Wed Feb 01 10:07:17 2006 +0000
@@ -0,0 +1,966 @@
+;;; mh-letter.el --- MH-Letter mode
+
+;; Copyright (C) 1993, 1995, 1997,
+;;  2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+
+;; Author: Bill Wohler <wohler@newt.com>
+;; Maintainer: Bill Wohler <wohler@newt.com>
+;; Keywords: mail
+;; See: mh-e.el
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
+
+;;; Commentary:
+
+;; Mode for composing and sending a draft message.
+
+;; Functions that would ordinarily be in here that are needed by
+;; mh-show.el should be placed in the Message Utilities section in
+;; mh-utils.el. That will help prevent the loading of this file until
+;; a message is actually composed.
+
+;;; Change Log:
+
+;;; Code:
+
+(require 'mh-e)
+
+(require 'gnus-util)
+
+;; Dynamically-created function not found in mh-loaddefs.el.
+(autoload 'mh-tool-bar-letter-buttons-init "mh-tool-bar")
+
+(autoload 'mml-insert-tag "mml")
+
+;;; Variables
+
+(defvar mh-letter-complete-function-alist
+  '((bcc . mh-alias-letter-expand-alias)
+    (cc . mh-alias-letter-expand-alias)
+    (dcc . mh-alias-letter-expand-alias)
+    (fcc . mh-folder-expand-at-point)
+    (from . mh-alias-letter-expand-alias)
+    (mail-followup-to . mh-alias-letter-expand-alias)
+    (mail-reply-to . mh-alias-letter-expand-alias)
+    (reply-to . mh-alias-letter-expand-alias)
+    (to . mh-alias-letter-expand-alias))
+  "Alist of header fields and completion functions to use.")
+
+(defvar mh-yank-hooks nil
+  "Obsolete hook for modifying a citation just inserted in the mail buffer.
+
+Each hook function can find the citation between point and mark.
+And each hook function should leave point and mark around the
+citation text as modified.
+
+This is a normal hook, misnamed for historical reasons. It is
+semi-obsolete and is only used if `mail-citation-hook' is nil.")
+
+
+
+;;; Letter Menu
+
+(easy-menu-define
+  mh-letter-menu mh-letter-mode-map "Menu for MH-E letter mode."
+  '("Letter"
+    ["Send This Draft"          mh-send-letter t]
+    ["Split Current Line"       mh-open-line t]
+    ["Check Recipient"          mh-check-whom t]
+    ["Yank Current Message"     mh-yank-cur-msg t]
+    ["Insert a Message..."      mh-insert-letter t]
+    ["Insert Signature"         mh-insert-signature t]
+    ("Encrypt/Sign Message"
+     ["Sign Message"
+      mh-mml-secure-message-sign mh-pgp-support-flag]
+     ["Encrypt Message"
+      mh-mml-secure-message-encrypt mh-pgp-support-flag]
+     ["Sign+Encrypt Message"
+      mh-mml-secure-message-signencrypt mh-pgp-support-flag]
+     ["Disable Security"
+      mh-mml-unsecure-message mh-pgp-support-flag]
+     "--"
+     "Security Method"
+     ["PGP (MIME)" (setq mh-mml-method-default "pgpmime")
+      :style radio
+      :selected (equal mh-mml-method-default "pgpmime")]
+     ["PGP" (setq mh-mml-method-default "pgp")
+      :style radio
+      :selected (equal mh-mml-method-default "pgp")]
+     ["S/MIME" (setq mh-mml-method-default "smime")
+      :style radio
+      :selected (equal mh-mml-method-default "smime")]
+     "--"
+     ["Save Method as Default"
+      (customize-save-variable 'mh-mml-method-default mh-mml-method-default) t]
+     )
+    ["Compose Insertion..."      mh-compose-insertion t]
+    ["Compose Compressed tar (MH)..."
+     mh-mh-compose-external-compressed-tar t]
+    ["Compose Get File (MH)..."       mh-mh-compose-anon-ftp t]
+    ["Compose Forward..."        mh-compose-forward t]
+    ;; The next two will have to be merged. But I also need to make sure the
+    ;; user can't mix tags of both types.
+    ["Pull in All Compositions (MH)"
+     mh-mh-to-mime (mh-mh-directive-present-p)]
+    ["Pull in All Compositions (MML)"
+     mh-mml-to-mime (mh-mml-tag-present-p)]
+    ["Revert to Non-MIME Edit (MH)"
+     mh-mh-to-mime-undo (equal mh-compose-insertion 'mh)]
+    ["Kill This Draft"          mh-fully-kill-draft t]))
+
+
+
+;;; MH-Letter Keys
+
+;; If this changes, modify mh-letter-mode-help-messages accordingly, above.
+(gnus-define-keys  mh-letter-mode-map
+  " "                   mh-letter-complete-or-space
+  ","                   mh-letter-confirm-address
+  "\C-c?"               mh-help
+  "\C-c\C-\\"           mh-fully-kill-draft ;if no C-q
+  "\C-c\C-^"            mh-insert-signature ;if no C-s
+  "\C-c\C-c"            mh-send-letter
+  "\C-c\C-d"            mh-insert-identity
+  "\C-c\C-e"            mh-mh-to-mime
+  "\C-c\C-f\C-a"        mh-to-field
+  "\C-c\C-f\C-b"        mh-to-field
+  "\C-c\C-f\C-c"        mh-to-field
+  "\C-c\C-f\C-d"        mh-to-field
+  "\C-c\C-f\C-f"        mh-to-fcc
+  "\C-c\C-f\C-l"        mh-to-field
+  "\C-c\C-f\C-m"        mh-to-field
+  "\C-c\C-f\C-r"        mh-to-field
+  "\C-c\C-f\C-s"        mh-to-field
+  "\C-c\C-f\C-t"        mh-to-field
+  "\C-c\C-fa"           mh-to-field
+  "\C-c\C-fb"           mh-to-field
+  "\C-c\C-fc"           mh-to-field
+  "\C-c\C-fd"           mh-to-field
+  "\C-c\C-ff"           mh-to-fcc
+  "\C-c\C-fl"           mh-to-field
+  "\C-c\C-fm"           mh-to-field
+  "\C-c\C-fr"           mh-to-field
+  "\C-c\C-fs"           mh-to-field
+  "\C-c\C-ft"           mh-to-field
+  "\C-c\C-i"            mh-insert-letter
+  "\C-c\C-m\C-e"        mh-mml-secure-message-encrypt
+  "\C-c\C-m\C-f"        mh-compose-forward
+  "\C-c\C-m\C-g"        mh-mh-compose-anon-ftp
+  "\C-c\C-m\C-i"        mh-compose-insertion
+  "\C-c\C-m\C-m"        mh-mml-to-mime
+  "\C-c\C-m\C-n"        mh-mml-unsecure-message
+  "\C-c\C-m\C-s"        mh-mml-secure-message-sign
+  "\C-c\C-m\C-t"        mh-mh-compose-external-compressed-tar
+  "\C-c\C-m\C-u"        mh-mh-to-mime-undo
+  "\C-c\C-m\C-x"        mh-mh-compose-external-type
+  "\C-c\C-mee"          mh-mml-secure-message-encrypt
+  "\C-c\C-mes"          mh-mml-secure-message-signencrypt
+  "\C-c\C-mf"           mh-compose-forward
+  "\C-c\C-mg"           mh-mh-compose-anon-ftp
+  "\C-c\C-mi"           mh-compose-insertion
+  "\C-c\C-mm"           mh-mml-to-mime
+  "\C-c\C-mn"           mh-mml-unsecure-message
+  "\C-c\C-mse"          mh-mml-secure-message-signencrypt
+  "\C-c\C-mss"          mh-mml-secure-message-sign
+  "\C-c\C-mt"           mh-mh-compose-external-compressed-tar
+  "\C-c\C-mu"           mh-mh-to-mime-undo
+  "\C-c\C-mx"           mh-mh-compose-external-type
+  "\C-c\C-o"            mh-open-line
+  "\C-c\C-q"            mh-fully-kill-draft
+  "\C-c\C-s"            mh-insert-signature
+  "\C-c\C-t"            mh-letter-toggle-header-field-display
+  "\C-c\C-w"            mh-check-whom
+  "\C-c\C-y"            mh-yank-cur-msg
+  "\C-c\M-d"            mh-insert-auto-fields
+  "\M-\t"               mh-letter-complete
+  "\t"                  mh-letter-next-header-field-or-indent
+  [backtab]             mh-letter-previous-header-field)
+
+;; "C-c /" prefix is used in mh-letter-mode by pgp.el and mailcrypt.el.
+
+
+
+;;; MH-Letter Help Messages
+
+;; Group messages logically, more or less.
+(defvar mh-letter-mode-help-messages
+  '((nil
+     "Send letter: \\[mh-send-letter]    "
+     "Open line:        \\[mh-open-line]\n"
+     "Kill letter: \\[mh-fully-kill-draft]    "
+     "Check recipients: \\[mh-check-whom]\n\n"
+     "Insert:\n"
+     "  Current message:      \\[mh-yank-cur-msg]\n"
+     "  Attachment:           \\[mh-compose-insertion]\n"
+     "  Message to forward:   \\[mh-compose-forward]\n"
+     "  Signature:            \\[mh-insert-signature]\n\n"
+     "Security:\n"
+     "  Encrypt message:      \\[mh-mml-secure-message-encrypt]\n"
+     "  Sign message:         \\[mh-mml-secure-message-sign]\n"
+     "  Sign+Encrypt message: \\[mh-mml-secure-message-signencrypt]"))
+  "Key binding cheat sheet.
+
+This is an associative array which is used to show the most
+common commands. The key is a prefix char. The value is one or
+more strings which are concatenated together and displayed in the
+minibuffer if ? is pressed after the prefix character. The
+special key nil is used to display the non-prefixed commands.
+
+The substitutions described in `substitute-command-keys' are
+performed as well.")
+
+
+
+;;; MH-Letter Font Lock
+
+(defvar mh-letter-font-lock-keywords
+  `(,@(mh-show-font-lock-keywords-with-cite)
+    (mh-font-lock-field-data
+     (1 'mh-letter-header-field prepend t)))
+  "Additional expressions to highlight in MH-Letter buffers.")
+
+(defun mh-font-lock-field-data (limit)
+  "Find header field region between point and LIMIT."
+  (and (< (point) (mh-letter-header-end))
+       (< (point) limit)
+       (let ((end (min limit (mh-letter-header-end)))
+             (point (point))
+             data-end data-begin field)
+         (end-of-line)
+         (setq data-end (if (re-search-forward "^[^ \t]" end t)
+                            (match-beginning 0)
+                          end))
+         (goto-char (1- data-end))
+         (if (not (re-search-backward "\\(^[^ \t][^:]*\\):[ \t]*" nil t))
+             (setq data-begin (point-min))
+           (setq data-begin (match-end 0))
+           (setq field (match-string 1)))
+         (setq data-begin (max point data-begin))
+         (goto-char (if (equal point data-end) (1+ data-end) data-end))
+         (cond ((and field (mh-letter-skipped-header-field-p field))
+                (set-match-data nil)
+                nil)
+               (t (set-match-data
+                   (list data-begin data-end data-begin data-end))
+                  t)))))
+
+(defun mh-letter-header-end ()
+  "Find the end of the message header.
+This function is to be used only for font locking. It works by
+searching for `mh-mail-header-separator' in the buffer."
+  (save-excursion
+    (goto-char (point-min))
+    (cond ((equal mh-mail-header-separator "") (point-min))
+          ((search-forward (format "\n%s\n" mh-mail-header-separator) nil t)
+           (line-beginning-position 0))
+          (t (point-min)))))
+
+
+
+;;; MH-Letter Mode
+
+(defvar mh-letter-buttons-init-flag nil)
+
+;; Shush compiler.
+(eval-when-compile (mh-do-in-xemacs (defvar font-lock-defaults)))
+
+;; Ensure new buffers won't get this mode if default-major-mode is nil.
+(put 'mh-letter-mode 'mode-class 'special)
+
+;;;###mh-autoload
+(define-derived-mode mh-letter-mode mail-mode "MH-Letter"
+  "Mode for composing letters in MH-E\\<mh-letter-mode-map>.
+
+When you have finished composing, type \\[mh-send-letter] to send
+the message using the MH mail handling system.
+
+There are two types of tags used by MH-E when composing MIME
+messages: MML and MH. The option `mh-compose-insertion' controls
+what type of tags are inserted by MH-E commands. These tags can
+be converted to MIME body parts by running \\[mh-mh-to-mime] for
+MH-style directives or \\[mh-mml-to-mime] for MML tags.
+
+Options that control this mode can be changed with
+\\[customize-group]; specify the \"mh-compose\" group.
+
+When a message is composed, the hooks `text-mode-hook',
+`mail-mode-hook', and `mh-letter-mode-hook' are run (in that
+order).
+
+\\{mh-letter-mode-map}"
+  (mh-find-path)
+  (make-local-variable 'mh-send-args)
+  (make-local-variable 'mh-annotate-char)
+  (make-local-variable 'mh-annotate-field)
+  (make-local-variable 'mh-previous-window-config)
+  (make-local-variable 'mh-sent-from-folder)
+  (make-local-variable 'mh-sent-from-msg)
+  (mh-do-in-gnu-emacs
+   (unless mh-letter-buttons-init-flag
+     (mh-tool-bar-letter-buttons-init)
+     (setq mh-letter-buttons-init-flag t)))
+  ;; Set the local value of mh-mail-header-separator according to what is
+  ;; present in the buffer...
+  (set (make-local-variable 'mh-mail-header-separator)
+       (save-excursion
+         (goto-char (mh-mail-header-end))
+         (buffer-substring-no-properties (point) (line-end-position))))
+  (make-local-variable 'mail-header-separator)
+  (setq mail-header-separator mh-mail-header-separator) ;override sendmail.el
+  (mh-set-help mh-letter-mode-help-messages)
+  (setq buffer-invisibility-spec '((vanish . t) t))
+  (set (make-local-variable 'line-move-ignore-invisible) t)
+
+  ;; Enable undo since a show-mode buffer might have been reused.
+  (buffer-enable-undo)
+  (set (make-local-variable 'tool-bar-map) mh-letter-tool-bar-map)
+  (mh-funcall-if-exists mh-tool-bar-init :letter)
+  (make-local-variable 'font-lock-defaults)
+  (cond
+   ((or (equal mh-highlight-citation-style 'font-lock)
+        (equal mh-highlight-citation-style 'gnus))
+    ;; Let's use font-lock even if gnus is used in show-mode.  The reason
+    ;; is that gnus uses static text properties which are not appropriate
+    ;; for a buffer that will be edited.  So the choice here is either fontify
+    ;; the citations and header...
+    (setq font-lock-defaults '(mh-letter-font-lock-keywords t)))
+   (t
+    ;; ...or the header only
+    (setq font-lock-defaults '((mh-show-font-lock-keywords) t))))
+  (easy-menu-add mh-letter-menu)
+  ;; Maybe we want to use the existing Mail menu from mail-mode in
+  ;; 9.0; in the mean time, let's remove it since the redundancy will
+  ;; only produce confusion.
+  (define-key mh-letter-mode-map [menu-bar mail] 'undefined)
+  (mh-do-in-xemacs (easy-menu-remove mail-menubar-menu))
+  (setq fill-column mh-letter-fill-column)
+  ;; If text-mode-hook turned on auto-fill, tune it for messages
+  (when auto-fill-function
+    (make-local-variable 'auto-fill-function)
+    (setq auto-fill-function 'mh-auto-fill-for-letter)))
+
+
+
+;;; MH-Letter Commands
+
+;; Alphabetical.
+;; See also mh-comp.el and mh-mime.el.
+
+(defun mh-check-whom ()
+  "Verify recipients, showing expansion of any aliases.
+
+This command expands aliases so you can check the actual address(es)
+in the alias. A new buffer named \"*MH-E Recipients*\" is created with
+the output of \"whom\"."
+  (interactive)
+  (let ((file-name buffer-file-name))
+    (save-buffer)
+    (message "Checking recipients...")
+    (mh-in-show-buffer (mh-recipients-buffer)
+      (bury-buffer (current-buffer))
+      (erase-buffer)
+      (mh-exec-cmd-output "whom" t file-name))
+    (message "Checking recipients...done")))
+
+(defun mh-insert-letter (folder message verbatim)
+  "Insert a message.
+
+This command prompts you for the FOLDER and MESSAGE number, which
+defaults to the current message in that folder. It then inserts
+the message, indented by `mh-ins-buf-prefix' (\"> \") unless
+`mh-yank-behavior' is set to one of the supercite flavors in
+which case supercite is used to format the message. Certain
+undesirable header fields (see
+`mh-invisible-header-fields-compiled') are removed before
+insertion.
+
+If given a prefix argument VERBATIM, the header is left intact, the
+message is not indented, and \"> \" is not inserted before each line.
+This command leaves the mark before the letter and point after it."
+  (interactive
+   (let* ((folder
+           (mh-prompt-for-folder "Message from"
+                                 mh-sent-from-folder nil))
+          (default
+            (if (and (equal folder mh-sent-from-folder)
+                     (numberp mh-sent-from-msg))
+                mh-sent-from-msg
+              (nth 0 (mh-translate-range folder "cur"))))
+          (message
+           (read-string (concat "Message number"
+                                (or (and default
+                                         (format " (default %d): " default))
+                                    ": ")))))
+     (list folder message current-prefix-arg)))
+  (save-restriction
+    (narrow-to-region (point) (point))
+    (let ((start (point-min)))
+      (if (and (equal message "") (numberp mh-sent-from-msg))
+          (setq message (int-to-string mh-sent-from-msg)))
+      (insert-file-contents
+       (expand-file-name message (mh-expand-file-name folder)))
+      (when (not verbatim)
+        (mh-clean-msg-header start mh-invisible-header-fields-compiled nil)
+        (goto-char (point-max))         ;Needed for sc-cite-original
+        (push-mark)                     ;Needed for sc-cite-original
+        (goto-char (point-min))         ;Needed for sc-cite-original
+        (mh-insert-prefix-string mh-ins-buf-prefix)))))
+
+;;;###mh-autoload
+(defun mh-insert-signature (&optional file)
+  "Insert signature in message.
+
+This command inserts your signature at the current cursor location.
+
+By default, the text of your signature is taken from the file
+\"~/.signature\". You can read from other sources by changing the
+option `mh-signature-file-name'.
+
+A signature separator (\"-- \") will be added if the signature block
+does not contain one and `mh-signature-separator-flag' is on.
+
+The hook `mh-insert-signature-hook' is run after the signature is
+inserted. Hook functions may access the actual name of the file or the
+function used to insert the signature with `mh-signature-file-name'.
+
+The signature can also be inserted using Identities (see
+`mh-identity-list').
+
+In a program, you can pass in a signature FILE."
+  (interactive)
+  (save-excursion
+    (insert "\n")
+    (let ((mh-signature-file-name (or file mh-signature-file-name))
+          (mh-mh-p (mh-mh-directive-present-p))
+          (mh-mml-p (mh-mml-tag-present-p)))
+      (save-restriction
+        (narrow-to-region (point) (point))
+        (cond
+         ((mh-file-is-vcard-p mh-signature-file-name)
+          (if (equal mh-compose-insertion 'mml)
+              (insert "<#part type=\"text/x-vcard\" filename=\""
+                      mh-signature-file-name
+                      "\" disposition=inline description=VCard>\n<#/part>")
+            (insert "#text/x-vcard; name=\""
+                    (file-name-nondirectory mh-signature-file-name)
+                    "\" [VCard] " (expand-file-name mh-signature-file-name))))
+         (t
+          (cond
+           (mh-mh-p
+            (insert "#\n" "Content-Description: Signature\n"))
+           (mh-mml-p
+            (mml-insert-tag 'part 'type "text/plain" 'disposition "inline"
+                            'description "Signature")))
+          (cond ((null mh-signature-file-name))
+                ((and (stringp mh-signature-file-name)
+                      (file-readable-p mh-signature-file-name))
+                 (insert-file-contents mh-signature-file-name))
+                ((functionp mh-signature-file-name)
+                 (funcall mh-signature-file-name)))))
+        (save-restriction
+          (widen)
+          (run-hooks 'mh-insert-signature-hook))
+        (goto-char (point-min))
+        (when (and (not (mh-file-is-vcard-p mh-signature-file-name))
+                   mh-signature-separator-flag
+                   (> (point-max) (point-min))
+                   (not (mh-signature-separator-p)))
+          (cond (mh-mh-p
+                 (forward-line 2))
+                (mh-mml-p
+                 (forward-line 1)))
+          (insert mh-signature-separator))
+        (if (not (> (point-max) (point-min)))
+            (message "No signature found")))))
+  (force-mode-line-update))
+
+(defun mh-letter-complete (arg)
+  "Perform completion on header field or word preceding point.
+
+If the field contains addresses (for example, \"To:\" or \"Cc:\")
+or folders (for example, \"Fcc:\") then this command will provide
+alias completion. In the body of the message, this command runs
+`mh-letter-complete-function' instead, which is set to
+`ispell-complete-word' by default. This command takes a prefix
+argument ARG that is passed to the
+`mh-letter-complete-function'."
+  (interactive "P")
+  (let ((func nil))
+    (cond ((not (mh-in-header-p))
+           (funcall mh-letter-complete-function arg))
+          ((setq func (cdr (assoc (mh-letter-header-field-at-point)
+                                  mh-letter-complete-function-alist)))
+           (funcall func))
+          (t (funcall mh-letter-complete-function arg)))))
+
+(defun mh-letter-complete-or-space (arg)
+  "Perform completion or insert space.
+
+Turn on the option `mh-compose-space-does-completion-flag' to use
+this command to perform completion in the header. Otherwise, a
+space is inserted; use a prefix argument ARG to specify more than
+one space."
+  (interactive "p")
+  (let ((func nil)
+        (end-of-prev (save-excursion
+                       (goto-char (mh-beginning-of-word))
+                       (mh-beginning-of-word -1))))
+    (cond ((not mh-compose-space-does-completion-flag)
+           (self-insert-command arg))
+          ((not (mh-in-header-p)) (self-insert-command arg))
+          ((> (point) end-of-prev) (self-insert-command arg))
+          ((setq func (cdr (assoc (mh-letter-header-field-at-point)
+                                  mh-letter-complete-function-alist)))
+           (funcall func))
+          (t (self-insert-command arg)))))
+
+(defun mh-letter-confirm-address ()
+  "Flash alias expansion.
+
+Addresses are separated by a comma\; when you press the comma,
+this command flashes the alias expansion in the minibuffer if
+`mh-alias-flash-on-comma' is turned on."
+  (interactive)
+  (cond ((not (mh-in-header-p)) (self-insert-command 1))
+        ((eq (cdr (assoc (mh-letter-header-field-at-point)
+                         mh-letter-complete-function-alist))
+             'mh-alias-letter-expand-alias)
+         (mh-alias-reload-maybe)
+         (mh-alias-minibuffer-confirm-address))
+        (t (self-insert-command 1))))
+
+(defun mh-letter-next-header-field-or-indent (arg)
+  "Cycle to next field.
+
+Within the header of the message, this command moves between
+fields that are highlighted with the face
+`mh-letter-header-field', skipping those fields listed in
+`mh-compose-skipped-header-fields'. After the last field, this
+command then moves point to the message body before cycling back
+to the first field. If point is already past the first line of
+the message body, then this command indents by calling
+`indent-relative' with the given prefix argument ARG."
+  (interactive "P")
+  (let ((header-end (save-excursion
+                      (goto-char (mh-mail-header-end))
+                      (forward-line)
+                      (point))))
+    (if (> (point) header-end)
+        (indent-relative arg)
+      (mh-letter-next-header-field))))
+
+(defun mh-letter-previous-header-field ()
+  "Cycle to the previous header field.
+
+This command moves backwards between the fields and cycles to the
+body of the message after the first field. Unlike the command
+\\[mh-letter-next-header-field-or-indent], it will always take
+point to the last field from anywhere in the body."
+  (interactive)
+  (let ((header-end (mh-mail-header-end)))
+    (if (>= (point) header-end)
+        (goto-char header-end)
+      (mh-header-field-beginning))
+    (cond ((re-search-backward mh-letter-header-field-regexp nil t)
+           (if (mh-letter-skipped-header-field-p (match-string 1))
+               (mh-letter-previous-header-field)
+           (goto-char (match-end 0))
+           (mh-letter-skip-leading-whitespace-in-header-field)))
+          (t (goto-char header-end)
+             (forward-line)))))
+
+(defun mh-open-line ()
+  "Insert a newline and leave point before it.
+
+This command is similar to the command \\[open-line] in that it
+inserts a newline after point. It differs in that it also inserts
+the right number of quoting characters and spaces so that the
+next line begins in the same column as it was. This is useful
+when breaking up paragraphs in replies."
+  (interactive)
+  (let ((column (current-column))
+        (prefix (mh-current-fill-prefix)))
+    (if (> (length prefix) column)
+        (message "Sorry, point seems to be within the line prefix")
+      (newline 2)
+      (insert prefix)
+      (while (> column (current-column))
+        (insert " "))
+      (forward-line -1))))
+
+(defun mh-to-fcc (&optional folder)
+  "Move to \"Fcc:\" header field.
+
+This command will prompt you for the FOLDER name in which to file
+a copy of the draft."
+  (interactive (list (mh-prompt-for-folder
+                      "Fcc"
+                      (or (and mh-default-folder-for-message-function
+                               (save-excursion
+                                 (goto-char (point-min))
+                                 (funcall
+                                  mh-default-folder-for-message-function)))
+                          "")
+                      t)))
+  (let ((last-input-char ?\C-f))
+    (expand-abbrev)
+    (save-excursion
+      (mh-to-field)
+      (insert (if (mh-folder-name-p folder)
+                  (substring folder 1)
+                folder)))))
+
+(defvar mh-to-field-choices '(("a" . "Mail-Reply-To:")
+                              ("b" . "Bcc:")
+                              ("c" . "Cc:")
+                              ("d" . "Dcc:")
+                              ("f" . "Fcc:")
+                              ("l" . "Mail-Followup-To:")
+                              ("m" . "From:")
+                              ("r" . "Reply-To:")
+                              ("s" . "Subject:")
+                              ("t" . "To:"))
+  "Alist of (final-character . field-name) choices for `mh-to-field'.")
+
+(defun mh-to-field ()
+  "Move to specified header field.
+
+The field is indicated by the previous keystroke (the last
+keystroke of the command) according to the list in the variable
+`mh-to-field-choices'.
+Create the field if it does not exist.
+Set the mark to point before moving."
+  (interactive)
+  (expand-abbrev)
+  (let ((target (cdr (or (assoc (char-to-string (logior last-input-char ?`))
+                                mh-to-field-choices)
+                         ;; also look for a char for version 4 compat
+                         (assoc (logior last-input-char ?`)
+                                mh-to-field-choices))))
+        (case-fold-search t))
+    (push-mark)
+    (cond ((mh-position-on-field target)
+           (let ((eol (point)))
+             (skip-chars-backward " \t")
+             (delete-region (point) eol))
+           (if (and (not (eq (logior last-input-char ?`) ?s))
+                    (save-excursion
+                      (backward-char 1)
+                      (not (looking-at "[:,]"))))
+               (insert ", ")
+             (insert " ")))
+          (t
+           (if (mh-position-on-field "To:")
+               (forward-line 1))
+           (insert (format "%s \n" target))
+           (backward-char 1)))))
+
+;;;###mh-autoload
+(defun mh-yank-cur-msg ()
+  "Insert the current message into the draft buffer.
+
+It is often useful to insert a snippet of text from a letter that
+someone mailed to provide some context for your reply. This
+command does this by adding an attribution, yanking a portion of
+text from the message to which you're replying, and inserting
+`mh-ins-buf-prefix' (`> ') before each line.
+
+The attribution consists of the sender's name and email address
+followed by the content of the option
+`mh-extract-from-attribution-verb'.
+
+You can also turn on the option
+`mh-delete-yanked-msg-window-flag' to delete the window
+containing the original message after yanking it to make more
+room on your screen for your reply.
+
+You can control how the message to which you are replying is
+yanked into your reply using `mh-yank-behavior'.
+
+If this isn't enough, you can gain full control over the
+appearance of the included text by setting `mail-citation-hook'
+to a function that modifies it. For example, if you set this hook
+to `trivial-cite' (which is NOT part of Emacs), set
+`mh-yank-behavior' to \"Body and Header\" (see URL
+`http://shasta.cs.uiuc.edu/~lrclause/tc.html').
+
+Note that if `mail-citation-hook' is set, `mh-ins-buf-prefix' is
+not inserted. If the option `mh-yank-behavior' is set to one of
+the supercite flavors, the hook `mail-citation-hook' is ignored
+and `mh-ins-buf-prefix' is not inserted."
+  (interactive)
+  (if (and mh-sent-from-folder
+           (save-excursion (set-buffer mh-sent-from-folder) mh-show-buffer)
+           (save-excursion (set-buffer mh-sent-from-folder)
+                           (get-buffer mh-show-buffer))
+           mh-sent-from-msg)
+      (let ((to-point (point))
+            (to-buffer (current-buffer)))
+        (set-buffer mh-sent-from-folder)
+        (if mh-delete-yanked-msg-window-flag
+            (delete-windows-on mh-show-buffer))
+        (set-buffer mh-show-buffer)     ; Find displayed message
+        (let* ((from-attr (mh-extract-from-attribution))
+               (yank-region (mh-mark-active-p nil))
+               (mh-ins-str
+                (cond ((and yank-region
+                            (or (eq 'supercite mh-yank-behavior)
+                                (eq 'autosupercite mh-yank-behavior)
+                                (eq t mh-yank-behavior)))
+                       ;; supercite needs the full header
+                       (concat
+                        (buffer-substring (point-min) (mh-mail-header-end))
+                        "\n"
+                        (buffer-substring (region-beginning) (region-end))))
+                      (yank-region
+                       (buffer-substring (region-beginning) (region-end)))
+                      ((or (eq 'body mh-yank-behavior)
+                           (eq 'attribution mh-yank-behavior)
+                           (eq 'autoattrib mh-yank-behavior))
+                       (buffer-substring
+                        (save-excursion
+                          (goto-char (point-min))
+                          (mh-goto-header-end 1)
+                          (point))
+                        (point-max)))
+                      ((or (eq 'supercite mh-yank-behavior)
+                           (eq 'autosupercite mh-yank-behavior)
+                           (eq t mh-yank-behavior))
+                       (buffer-substring (point-min) (point-max)))
+                      (t
+                       (buffer-substring (point) (point-max))))))
+          (set-buffer to-buffer)
+          (save-restriction
+            (narrow-to-region to-point to-point)
+            (insert (mh-filter-out-non-text mh-ins-str))
+            (goto-char (point-max))     ;Needed for sc-cite-original
+            (push-mark)                 ;Needed for sc-cite-original
+            (goto-char (point-min))     ;Needed for sc-cite-original
+            (mh-insert-prefix-string mh-ins-buf-prefix)
+            (when (or (eq 'attribution mh-yank-behavior)
+                      (eq 'autoattrib mh-yank-behavior))
+              (insert from-attr)
+              (mh-identity-insert-attribution-verb nil)
+              (insert "\n\n"))
+            ;; If the user has selected a region, he has already "edited" the
+            ;; text, so leave the cursor at the end of the yanked text. In
+            ;; either case, leave a mark at the opposite end of the included
+            ;; text to make it easy to jump or delete to the other end of the
+            ;; text.
+            (push-mark)
+            (goto-char (point-max))
+            (if (null yank-region)
+                (mh-exchange-point-and-mark-preserving-active-mark)))))
+    (error "There is no current message")))
+
+
+
+;;; Support Routines
+
+(defun mh-auto-fill-for-letter ()
+  "Perform auto-fill for message.
+Header is treated specially by inserting a tab before continuation
+lines."
+  (if (mh-in-header-p)
+      (let ((fill-prefix "\t"))
+        (do-auto-fill))
+    (do-auto-fill)))
+
+(defun mh-filter-out-non-text (string)
+  "Return STRING but without adornments such as MIME buttons and smileys."
+  (with-temp-buffer
+    ;; Insert the string to filter
+    (insert string)
+    (goto-char (point-min))
+
+    ;; Remove the MIME buttons
+    (let ((can-move-forward t)
+          (in-button nil))
+      (while can-move-forward
+        (cond ((and (not (get-text-property (point) 'mh-data))
+                    in-button)
+               (delete-region (1- (point)) (point))
+               (setq in-button nil))
+              ((get-text-property (point) 'mh-data)
+               (delete-region (point)
+                              (save-excursion (forward-line) (point)))
+               (setq in-button t))
+              (t (setq can-move-forward (= (forward-line) 0))))))
+
+    ;; Return the contents without properties... This gets rid of emphasis
+    ;; and smileys
+    (buffer-substring-no-properties (point-min) (point-max))))
+
+(defun mh-current-fill-prefix ()
+  "Return the `fill-prefix' on the current line as a string."
+  (save-excursion
+    (beginning-of-line)
+    ;; This assumes that the major-mode sets up adaptive-fill-regexp
+    ;; correctly such as mh-letter-mode or sendmail.el's mail-mode.  But
+    ;; perhaps I should use the variable and simply inserts its value here,
+    ;; and set it locally in a let scope.  --psg
+    (if (re-search-forward adaptive-fill-regexp nil t)
+        (match-string 0)
+      "")))
+
+;;;###mh-autoload
+(defun mh-letter-next-header-field ()
+  "Cycle to the next header field.
+If we are at the last header field go to the start of the message
+body."
+  (let ((header-end (mh-mail-header-end)))
+    (cond ((>= (point) header-end) (goto-char (point-min)))
+          ((< (point) (progn
+                        (beginning-of-line)
+                        (re-search-forward mh-letter-header-field-regexp
+                                           (line-end-position) t)
+                        (point)))
+           (beginning-of-line))
+          (t (end-of-line)))
+    (cond ((re-search-forward mh-letter-header-field-regexp header-end t)
+           (if (mh-letter-skipped-header-field-p (match-string 1))
+               (mh-letter-next-header-field)
+             (mh-letter-skip-leading-whitespace-in-header-field)))
+          (t (goto-char header-end)
+             (forward-line)))))
+
+;;;###mh-autoload
+(defun mh-position-on-field (field &optional ignored)
+  "Move to the end of the FIELD in the header.
+Move to end of entire header if FIELD not found.
+Returns non-nil iff FIELD was found.
+The optional second arg is for pre-version 4 compatibility and is
+IGNORED."
+  (cond ((mh-goto-header-field field)
+         (mh-header-field-end)
+         t)
+        ((mh-goto-header-end 0)
+         nil)))
+
+(defun mh-letter-header-field-at-point ()
+  "Return the header field name at point.
+A symbol is returned whose name is the string obtained by
+downcasing the field name."
+  (save-excursion
+    (end-of-line)
+    (and (re-search-backward mh-letter-header-field-regexp nil t)
+         (intern (downcase (match-string 1))))))
+
+(defun mh-folder-expand-at-point ()
+  "Do folder name completion in Fcc header field."
+  (let* ((end (point))
+         (beg (mh-beginning-of-word))
+         (folder (buffer-substring beg end))
+         (leading-plus (and (> (length folder) 0) (equal (aref folder 0) ?+)))
+         (last-slash (mh-search-from-end ?/ folder))
+         (prefix (and last-slash (substring folder 0 last-slash)))
+         (choices (mapcar #'(lambda (x)
+                              (list (cond (prefix (format "%s/%s" prefix x))
+                                          (leading-plus (format "+%s" x))
+                                          (t x))))
+                          (mh-folder-completion-function folder nil t))))
+    (mh-complete-word folder choices beg end)))
+
+;;;###mh-autoload
+(defun mh-complete-word (word choices begin end)
+  "Complete WORD at from CHOICES.
+Any match found replaces the text from BEGIN to END."
+  (let ((completion (try-completion word choices))
+        (completions-buffer "*Completions*"))
+    (cond ((eq completion t)
+           (ignore-errors
+             (kill-buffer completions-buffer))
+           (message "Completed: %s" word))
+          ((null completion)
+           (ignore-errors
+             (kill-buffer completions-buffer))
+           (message "No completion for %s" word))
+          ((stringp completion)
+           (if (equal word completion)
+               (with-output-to-temp-buffer completions-buffer
+                 (mh-display-completion-list (all-completions word choices)
+                                             word))
+             (ignore-errors
+               (kill-buffer completions-buffer))
+             (delete-region begin end)
+             (insert completion))))))
+
+(defun mh-file-is-vcard-p (file)
+  "Return t if FILE is a .vcf vcard."
+  (let ((case-fold-search t))
+    (and (stringp file)
+         (file-exists-p file)
+         (or (and (not (mh-have-file-command))
+                  (not (null (string-match "\.vcf$" file))))
+             (string-equal "text/x-vcard" (mh-file-mime-type file))))))
+
+;;;###mh-autoload
+(defun mh-letter-toggle-header-field-display-button (event)
+  "Toggle header field display at location of EVENT.
+This function does the same thing as
+`mh-letter-toggle-header-field-display' except that it is
+callable from a mouse button."
+  (interactive "e")
+  (mh-do-at-event-location event
+    (mh-letter-toggle-header-field-display nil)))
+
+(defun mh-extract-from-attribution ()
+  "Extract phrase or comment from From header field."
+  (save-excursion
+    (if (not (mh-goto-header-field "From: "))
+        nil
+      (skip-chars-forward " ")
+      (cond
+       ((looking-at "\"\\([^\"\n]+\\)\" \\(<.+>\\)")
+        (format "%s %s " (match-string 1)(match-string 2)))
+       ((looking-at "\\([^<\n]+<.+>\\)$")
+        (format "%s " (match-string 1)))
+       ((looking-at "\\([^ ]+@[^ ]+\\) +(\\(.+\\))$")
+        (format "%s <%s> " (match-string 2)(match-string 1)))
+       ((looking-at " *\\(.+\\)$")
+        (format "%s " (match-string 1)))))))
+
+(defun mh-insert-prefix-string (mh-ins-string)
+  "Insert prefix string before each line in buffer.
+The inserted letter is cited using `sc-cite-original' if
+`mh-yank-behavior' is one of 'supercite or 'autosupercite.
+Otherwise, simply insert MH-INS-STRING before each line."
+  (goto-char (point-min))
+  (cond ((or (eq mh-yank-behavior 'supercite)
+             (eq mh-yank-behavior 'autosupercite))
+         (sc-cite-original))
+        (mail-citation-hook
+         (run-hooks 'mail-citation-hook))
+        (mh-yank-hooks                  ;old hook name
+         (run-hooks 'mh-yank-hooks))
+        (t
+         (or (bolp) (forward-line 1))
+         (while (< (point) (point-max))
+           (insert mh-ins-string)
+           (forward-line 1))
+         (goto-char (point-min)))))     ;leave point like sc-cite-original
+
+(provide 'mh-letter)
+
+;; Local Variables:
+;; indent-tabs-mode: nil
+;; sentence-end-double-space: nil
+;; End:
+
+;; arch-tag: 0548632c-aadb-4e3b-bb80-bbd62ff90bf3
+;;; mh-letter.el ends here
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lisp/mh-e/mh-limit.el	Wed Feb 01 10:07:17 2006 +0000
@@ -0,0 +1,330 @@
+;;; mh-limit.el --- MH-E display limits
+
+;; Copyright (C) 2001, 2002, 2003, 2006 Free Software Foundation, Inc.
+
+;; Author: Peter S. Galbraith <psg@debian.org>
+;; Maintainer: Bill Wohler <wohler@newt.com>
+;; Keywords: mail
+;; See: mh-e.el
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
+
+;;; Commentary:
+
+;; "Poor man's threading" by psg.
+
+;;; Change Log:
+
+;;; Code:
+
+(require 'mh-e)
+(mh-require-cl)
+(require 'mh-scan)
+
+(autoload 'message-fetch-field "message")
+
+
+
+;;; MH-Folder Commands
+
+;; Alphabetical.
+
+;;;###mh-autoload
+(defun mh-delete-subject ()
+  "Delete messages with same subject\\<mh-folder-mode-map>.
+
+To delete messages faster, you can use this command to delete all
+the messages with the same subject as the current message. This
+command puts these messages in a sequence named \"subject\". You
+can undo this action by using \\[mh-undo] with a prefix argument
+and then specifying the \"subject\" sequence."
+  (interactive)
+  (let ((count (mh-subject-to-sequence nil)))
+    (cond
+     ((not count)                       ; No subject line, delete msg anyway
+      (mh-delete-msg (mh-get-msg-num t)))
+     ((= 0 count)                       ; No other msgs, delete msg anyway.
+      (message "No other messages with same Subject following this one")
+      (mh-delete-msg (mh-get-msg-num t)))
+     (t                                 ; We have a subject sequence.
+      (message "Marked %d messages for deletion" count)
+      (mh-delete-msg 'subject)))))
+
+;;;###mh-autoload
+(defun mh-delete-subject-or-thread ()
+  "Delete messages with same subject or thread\\<mh-folder-mode-map>.
+
+To delete messages faster, you can use this command to delete all
+the messages with the same subject as the current message. This
+command puts these messages in a sequence named \"subject\". You
+can undo this action by using \\[mh-undo] with a prefix argument
+and then specifying the \"subject\" sequence.
+
+However, if the buffer is displaying a threaded view of the
+folder then this command behaves like \\[mh-thread-delete]."
+  (interactive)
+  (if (memq 'unthread mh-view-ops)
+      (mh-thread-delete)
+    (mh-delete-subject)))
+
+;;;###mh-autoload
+(defun mh-narrow-to-cc (&optional pick-expr)
+  "Limit to messages with the same \"Cc:\" field.
+With a prefix argument, edit PICK-EXPR.
+
+Use \\<mh-folder-mode-map>\\[mh-widen] to undo this command."
+  (interactive
+   (list (mh-edit-pick-expr (mh-current-message-header-field 'cc))))
+  (mh-narrow-to-header-field 'cc pick-expr))
+
+;;;###mh-autoload
+(defun mh-narrow-to-from (&optional pick-expr)
+  "Limit to messages with the same \"From:\" field.
+With a prefix argument, edit PICK-EXPR.
+
+Use \\<mh-folder-mode-map>\\[mh-widen] to undo this command."
+  (interactive
+   (list (mh-edit-pick-expr (mh-current-message-header-field 'from))))
+  (mh-narrow-to-header-field 'from pick-expr))
+
+;;;###mh-autoload
+(defun mh-narrow-to-range (range)
+  "Limit to RANGE.
+
+Check the documentation of `mh-interactive-range' to see how
+RANGE is read in interactive use.
+
+Use \\<mh-folder-mode-map>\\[mh-widen] to undo this command."
+  (interactive (list (mh-interactive-range "Narrow to")))
+  (when (assoc 'range mh-seq-list) (mh-delete-seq 'range))
+  (mh-add-msgs-to-seq (mh-range-to-msg-list range) 'range)
+  (mh-narrow-to-seq 'range))
+
+;;;###mh-autoload
+(defun mh-narrow-to-subject (&optional pick-expr)
+  "Limit to messages with same subject.
+With a prefix argument, edit PICK-EXPR.
+
+Use \\<mh-folder-mode-map>\\[mh-widen] to undo this command."
+  (interactive
+   (list (mh-edit-pick-expr (mh-current-message-header-field 'subject))))
+  (mh-narrow-to-header-field 'subject pick-expr))
+
+;;;###mh-autoload
+(defun mh-narrow-to-to (&optional pick-expr)
+  "Limit to messages with the same \"To:\" field.
+With a prefix argument, edit PICK-EXPR.
+
+Use \\<mh-folder-mode-map>\\[mh-widen] to undo this command."
+  (interactive
+   (list (mh-edit-pick-expr (mh-current-message-header-field 'to))))
+  (mh-narrow-to-header-field 'to pick-expr))
+
+
+
+;;; Support Routines
+
+(defun mh-subject-to-sequence (all)
+  "Put all following messages with same subject in sequence 'subject.
+If arg ALL is t, move to beginning of folder buffer to collect all
+messages.
+If arg ALL is nil, collect only messages fron current one on forward.
+
+Return number of messages put in the sequence:
+
+ nil -> there was no subject line.
+
+ 0   -> there were no later messages with the same
+        subject (sequence not made)
+
+ >1  -> the total number of messages including current one."
+  (if (memq 'unthread mh-view-ops)
+      (mh-subject-to-sequence-threaded all)
+    (mh-subject-to-sequence-unthreaded all)))
+
+(defun mh-subject-to-sequence-threaded (all)
+  "Put all messages with the same subject in the 'subject sequence.
+
+This function works when the folder is threaded. In this
+situation the subject could get truncated and so the normal
+matching doesn't work.
+
+The parameter ALL is non-nil then all the messages in the buffer
+are considered, otherwise only the messages after the current one
+are taken into account."
+  (let* ((cur (mh-get-msg-num nil))
+         (subject (mh-thread-find-msg-subject cur))
+         region msgs)
+    (if (null subject)
+        (and (message "No subject line") nil)
+      (setq region (cons (if all (point-min) (point)) (point-max)))
+      (mh-iterate-on-range msg region
+        (when (eq (mh-thread-find-msg-subject msg) subject)
+          (push msg msgs)))
+      (setq msgs (sort msgs #'mh-lessp))
+      (if (null msgs)
+          0
+        (when (assoc 'subject mh-seq-list)
+          (mh-delete-seq 'subject))
+        (mh-add-msgs-to-seq msgs 'subject)
+        (length msgs)))))
+
+(defvar mh-limit-max-subject-size 41
+  "Maximum size of the subject part.
+It would be desirable to avoid hard-coding this.")
+
+(defun mh-subject-to-sequence-unthreaded (all)
+  "Put all following messages with same subject in sequence 'subject.
+
+This function only works with an unthreaded folder. If arg ALL is
+t, move to beginning of folder buffer to collect all messages. If
+arg ALL is nil, collect only messages fron current one on
+forward.
+
+Return number of messages put in the sequence:
+
+ nil -> there was no subject line.
+ 0   -> there were no later messages with the same
+        subject (sequence not made)
+ >1  -> the total number of messages including current one."
+  (if (not (eq major-mode 'mh-folder-mode))
+      (error "Not in a folder buffer"))
+  (save-excursion
+    (beginning-of-line)
+    (if (or (not (looking-at mh-scan-subject-regexp))
+            (not (match-string 3))
+            (string-equal "" (match-string 3)))
+        (progn (message "No subject line")
+               nil)
+      (let ((subject (match-string-no-properties 3))
+            (list))
+        (if (> (length subject) mh-limit-max-subject-size)
+            (setq subject (substring subject 0 mh-limit-max-subject-size)))
+        (save-excursion
+          (if all
+              (goto-char (point-min)))
+          (while (re-search-forward mh-scan-subject-regexp nil t)
+            (let ((this-subject (match-string-no-properties 3)))
+              (if (> (length this-subject) mh-limit-max-subject-size)
+                  (setq this-subject (substring this-subject
+                                                0 mh-limit-max-subject-size)))
+              (if (string-equal this-subject subject)
+                  (setq list (cons (mh-get-msg-num t) list))))))
+        (cond
+         (list
+          ;; If we created a new sequence, add the initial message to it too.
+          (if (not (member (mh-get-msg-num t) list))
+              (setq list (cons (mh-get-msg-num t) list)))
+          (if (assoc 'subject mh-seq-list) (mh-delete-seq 'subject))
+          ;; sort the result into a sequence
+          (let ((sorted-list (sort (copy-sequence list) 'mh-lessp)))
+            (while sorted-list
+              (mh-add-msgs-to-seq (car sorted-list) 'subject nil)
+              (setq sorted-list (cdr sorted-list)))
+            (safe-length list)))
+         (t
+          0))))))
+
+(defun mh-edit-pick-expr (default)
+  "With prefix arg edit a pick expression.
+If no prefix arg is given, then return DEFAULT."
+  (let ((default-string (loop for x in default concat (format " %s" x))))
+    (if (or current-prefix-arg (equal default-string ""))
+        (mh-pick-args-list (read-string "Pick expression: "
+                                        default-string))
+      default)))
+
+(defun mh-pick-args-list (s)
+  "Form list by grouping elements in string S suitable for pick arguments.
+For example, the string \"-subject a b c -from Joe User
+<user@domain.com>\" is converted to (\"-subject\" \"a b c\"
+\"-from\" \"Joe User <user@domain.com>\""
+  (let ((full-list (split-string s))
+        current-arg collection arg-list)
+    (while full-list
+      (setq current-arg (car full-list))
+      (if (null (string-match "^-" current-arg))
+          (setq collection
+                (if (null collection)
+                    current-arg
+                  (format "%s %s" collection current-arg)))
+        (when collection
+          (setq arg-list (append arg-list (list collection)))
+          (setq collection nil))
+        (setq arg-list (append arg-list (list current-arg))))
+      (setq full-list (cdr full-list)))
+    (when collection
+      (setq arg-list (append arg-list (list collection))))
+    arg-list))
+
+(defun mh-current-message-header-field (header-field)
+  "Return a pick regexp to match HEADER-FIELD of the message at point."
+  (let ((num (mh-get-msg-num nil)))
+    (when num
+      (let ((folder mh-current-folder))
+        (with-temp-buffer
+          (insert-file-contents-literally (mh-msg-filename num folder))
+          (goto-char (point-min))
+          (when (search-forward "\n\n" nil t)
+            (narrow-to-region (point-min) (point)))
+          (let* ((field (or (message-fetch-field (format "%s" header-field))
+                            ""))
+                 (field-option (format "-%s" header-field))
+                 (patterns (loop for x in (split-string  field "[ ]*,[ ]*")
+                                 unless (equal x "")
+                                 collect (if (string-match "<\\(.*@.*\\)>" x)
+                                             (match-string 1 x)
+                                           x))))
+            (when patterns
+              (loop with accum = `(,field-option ,(car patterns))
+                    for e in (cdr patterns)
+                    do (setq accum `(,field-option ,e "-or" ,@accum))
+                    finally return accum))))))))
+
+(defun mh-narrow-to-header-field (header-field pick-expr)
+  "Limit to messages whose HEADER-FIELD match PICK-EXPR.
+The MH command pick is used to do the match."
+  (let ((folder mh-current-folder)
+        (original (mh-coalesce-msg-list
+                   (mh-range-to-msg-list (cons (point-min) (point-max)))))
+        (msg-list ()))
+    (with-temp-buffer
+      (apply #'mh-exec-cmd-output "pick" nil folder
+             (append original (list "-list") pick-expr))
+      (goto-char (point-min))
+      (while (not (eobp))
+        (let ((num (ignore-errors
+                     (string-to-number
+                      (buffer-substring (point) (line-end-position))))))
+          (when num (push num msg-list))
+          (forward-line))))
+    (if (null msg-list)
+        (message "No matches")
+      (when (assoc 'header mh-seq-list) (mh-delete-seq 'header))
+      (mh-add-msgs-to-seq msg-list 'header)
+      (mh-narrow-to-seq 'header))))
+
+(provide 'mh-limit)
+
+;; Local Variables:
+;; indent-tabs-mode: nil
+;; sentence-end-double-space: nil
+;; End:
+
+;; arch-tag: b0d24378-1234-4c42-aa3f-7abad25b40a1
+;;; mh-limit.el ends here
--- a/lisp/mh-e/mh-mime.el	Thu Jan 26 02:23:05 2006 +0000
+++ b/lisp/mh-e/mh-mime.el	Wed Feb 01 10:07:17 2006 +0000
@@ -1,4 +1,4 @@
-;;; mh-mime.el --- MH-E support for composing MIME messages
+;;; mh-mime.el --- MH-E MIME support
 
 ;; Copyright (C) 1993, 1995,
 ;;  2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
@@ -27,53 +27,1151 @@
 
 ;;; Commentary:
 
-;; Internal support for MH-E package.
-;; Support for generating MH-style directives for mhn or mhbuild as well as
-;; MML (MIME Meta Language) tags. MH-style directives are supported by MH 6.8
-;; or later.
+;; Message composition of MIME message is done with either MH-style
+;; directives for mhn or mhbuild (MH 6.8 or later) or MML (MIME Meta
+;; Language) tags.
+
+;; TODO:
+;;   Paragraph code should not fill # lines if MIME enabled.
+;;   Implement mh-auto-mh-to-mime (if non-nil, \\[mh-send-letter]
+;;      invokes mh-mh-to-mime automatically before sending.)
+;;      Actually, instead of mh-auto-mh-to-mime,
+;;      should read automhnproc from profile.
+;;   MIME option to mh-forward command to move to content-description
+;;   insertion point.
 
 ;;; Change Log:
 
 ;;; Code:
 
-;;(message "> mh-mime")
-(eval-when-compile (require 'mh-acros))
-(mh-require-cl)
+(require 'mh-e)
+(require 'mh-gnus)                      ;needed because mh-gnus.el not compiled
 
+(require 'font-lock)
 (require 'gnus-util)
-(require 'mh-buffers)
-(require 'mh-comp)
-(require 'mh-gnus)
-;;(message "< mh-mime")
+(require 'mailcap)
+(require 'mm-decode)
+(require 'mm-view)
+(require 'mml)
 
 (autoload 'article-emphasize "gnus-art")
-(autoload 'gnus-article-goto-header "gnus-art")
 (autoload 'gnus-eval-format "gnus-spec")
-(autoload 'gnus-get-buffer-create "gnus")
+(autoload 'mail-content-type-get "mail-parse")
+(autoload 'mail-decode-encoded-word-string "mail-parse")
+(autoload 'mail-header-parse-content-type "mail-parse")
+(autoload 'mail-header-strip "mail-parse")
 (autoload 'message-options-set-recipient "message")
+(autoload 'mm-decode-body "mm-bodies")
 (autoload 'mm-uu-dissect "mm-uu")
 (autoload 'mml-unsecure-message "mml-sec")
 (autoload 'rfc2047-decode-region "rfc2047")
 (autoload 'widget-convert-button "wid-edit")
 
+
+
+;;; Variables
+
+;; This has to be a macro, since we do: (setf (mh-buffer-data) ...)
 ;;;###mh-autoload
-(defun mh-compose-insertion (&optional inline)
-  "Add tag to include a file such as an image or sound.
+(defmacro mh-buffer-data ()
+  "Convenience macro to get the MIME data structures of the current buffer."
+  `(gethash (current-buffer) mh-globals-hash))
+
+;; Structure to keep track of MIME handles on a per buffer basis.
+(mh-defstruct (mh-buffer-data (:conc-name mh-mime-)
+                              (:constructor mh-make-buffer-data))
+  (handles ())                          ; List of MIME handles
+  (handles-cache (make-hash-table))     ; Cache to avoid multiple decodes of
+                                        ; nested messages
+  (parts-count 0)                       ; The button number is generated from
+                                        ; this number
+  (part-index-hash (make-hash-table)))  ; Avoid incrementing the part number
+                                        ; for nested messages
+
+(defvar mh-mm-inline-media-tests
+  `(("image/jpeg"
+     mm-inline-image
+     (lambda (handle)
+       (mm-valid-and-fit-image-p 'jpeg handle)))
+    ("image/png"
+     mm-inline-image
+     (lambda (handle)
+       (mm-valid-and-fit-image-p 'png handle)))
+    ("image/gif"
+     mm-inline-image
+     (lambda (handle)
+       (mm-valid-and-fit-image-p 'gif handle)))
+    ("image/tiff"
+     mm-inline-image
+     (lambda (handle)
+       (mm-valid-and-fit-image-p 'tiff handle)) )
+    ("image/xbm"
+     mm-inline-image
+     (lambda (handle)
+       (mm-valid-and-fit-image-p 'xbm handle)))
+    ("image/x-xbitmap"
+     mm-inline-image
+     (lambda (handle)
+       (mm-valid-and-fit-image-p 'xbm handle)))
+    ("image/xpm"
+     mm-inline-image
+     (lambda (handle)
+       (mm-valid-and-fit-image-p 'xpm handle)))
+    ("image/x-pixmap"
+     mm-inline-image
+     (lambda (handle)
+       (mm-valid-and-fit-image-p 'xpm handle)))
+    ("image/bmp"
+     mm-inline-image
+     (lambda (handle)
+       (mm-valid-and-fit-image-p 'bmp handle)))
+    ("image/x-portable-bitmap"
+     mm-inline-image
+     (lambda (handle)
+       (mm-valid-and-fit-image-p 'pbm handle)))
+    ("text/plain" mm-inline-text identity)
+    ("text/enriched" mm-inline-text identity)
+    ("text/richtext" mm-inline-text identity)
+    ("text/x-patch" mm-display-patch-inline
+     (lambda (handle)
+       (locate-library "diff-mode")))
+    ("application/emacs-lisp" mm-display-elisp-inline identity)
+    ("application/x-emacs-lisp" mm-display-elisp-inline identity)
+    ("text/html"
+     ,(if (fboundp 'mm-inline-text-html) 'mm-inline-text-html 'mm-inline-text)
+     (lambda (handle)
+       (or (and (boundp 'mm-inline-text-html-renderer)
+                mm-inline-text-html-renderer)
+           (and (boundp 'mm-text-html-renderer) mm-text-html-renderer))))
+    ("text/x-vcard"
+     mh-mm-inline-text-vcard
+     (lambda (handle)
+       (or (featurep 'vcard)
+           (locate-library "vcard"))))
+    ("message/delivery-status" mm-inline-text identity)
+    ("message/rfc822" mh-mm-inline-message identity)
+    ;;("message/partial" mm-inline-partial identity)
+    ;;("message/external-body" mm-inline-external-body identity)
+    ("text/.*" mm-inline-text identity)
+    ("audio/wav" mm-inline-audio
+     (lambda (handle)
+       (and (or (featurep 'nas-sound) (featurep 'native-sound))
+            (device-sound-enabled-p))))
+    ("audio/au"
+     mm-inline-audio
+     (lambda (handle)
+       (and (or (featurep 'nas-sound) (featurep 'native-sound))
+            (device-sound-enabled-p))))
+    ("application/pgp-signature" ignore identity)
+    ("application/x-pkcs7-signature" ignore identity)
+    ("application/pkcs7-signature" ignore identity)
+    ("application/x-pkcs7-mime" ignore identity)
+    ("application/pkcs7-mime" ignore identity)
+    ("multipart/alternative" ignore identity)
+    ("multipart/mixed" ignore identity)
+    ("multipart/related" ignore identity)
+    ;; Disable audio and image
+    ("audio/.*" ignore ignore)
+    ("image/.*" ignore ignore)
+    ;; Default to displaying as text
+    (".*" mm-inline-text mh-mm-readable-p))
+  "Alist of media types/tests saying whether types can be displayed inline.")
+
+(defvar mh-mime-save-parts-directory nil
+  "Default to use for `mh-mime-save-parts-default-directory'.
+Set from last use.")
+
+;; Copied from gnus-art.el (should be checked for other cool things that can
+;; be added to the buttons)
+(defvar mh-mime-button-commands
+  '((mh-press-button "\r" "Toggle Display")))
+(defvar mh-mime-button-map
+  (let ((map (make-sparse-keymap)))
+    (unless (>= (string-to-number emacs-version) 21)
+      ;; XEmacs doesn't care.
+      (set-keymap-parent map mh-show-mode-map))
+    (mh-do-in-gnu-emacs
+     (define-key map [mouse-2] 'mh-push-button))
+    (mh-do-in-xemacs
+     (define-key map '(button2) 'mh-push-button))
+    (dolist (c mh-mime-button-commands)
+      (define-key map (cadr c) (car c)))
+    map))
+(defvar mh-mime-button-line-format-alist
+  '((?T long-type ?s)
+    (?d description ?s)
+    (?p index ?s)
+    (?e dots ?s)))
+(defvar mh-mime-button-line-format "%{%([%p. %d%T]%)%}%e\n")
+(defvar mh-mime-security-button-pressed nil)
+(defvar mh-mime-security-button-line-format "%{%([[%t:%i]%D]%)%}\n")
+(defvar mh-mime-security-button-end-line-format "%{%([[End of %t]%D]%)%}\n")
+(defvar mh-mime-security-button-line-format-alist
+  '((?t type ?s)
+    (?i info ?s)
+    (?d details ?s)
+    (?D pressed-details ?s)))
+(defvar mh-mime-security-button-map
+  (let ((map (make-sparse-keymap)))
+    (unless (>= (string-to-number emacs-version) 21)
+      (set-keymap-parent map mh-show-mode-map))
+    (define-key map "\r" 'mh-press-button)
+    (mh-do-in-gnu-emacs
+     (define-key map [mouse-2] 'mh-push-button))
+    (mh-do-in-xemacs
+     (define-key map '(button2) 'mh-push-button))
+    map))
+
+
+
+;;; MH-Folder Commands
+
+;; Alphabetical.
+
+;;;###mh-autoload
+(defun mh-display-with-external-viewer (part-index)
+  "View attachment externally.
+
+If Emacs does not know how to view an attachment, you could save
+it into a file and then run some program to open it. It is
+easier, however, to launch the program directly from MH-E with
+this command. While you'll most likely use this to view
+spreadsheets and documents, it is also useful to use your browser
+to view HTML attachments with higher fidelity than what Emacs can
+provide.
+
+This command displays the attachment associated with the button
+under the cursor. If the cursor is not located over a button,
+then the cursor first moves to the next button, wrapping to the
+beginning of the message if necessary. You can provide a numeric
+prefix argument PART-INDEX to view the attachment labeled with
+that number.
+
+This command tries to provide a reasonable default for the viewer
+by calling the Emacs function `mailcap-mime-info'. This function
+usually reads the file \"/etc/mailcap\"."
+  (interactive "P")
+  (when (consp part-index) (setq part-index (car part-index)))
+  (mh-folder-mime-action
+   part-index
+   #'(lambda ()
+       (let* ((part (get-text-property (point) 'mh-data))
+              (type (mm-handle-media-type part))
+              (methods (mapcar (lambda (x) (list (cdr (assoc 'viewer x))))
+                               (mailcap-mime-info type 'all)))
+              (def (caar methods))
+              (prompt (format "Viewer%s: " (if def
+                                               (format " (default %s)" def)
+                                             "")))
+              (method (completing-read prompt methods nil nil nil nil def))
+              (folder mh-show-folder-buffer)
+              (buffer-read-only nil))
+         (when (string-match "^[^% \t]+$" method)
+           (setq method (concat method " %s")))
+         (flet ((mm-handle-set-external-undisplayer (handle function)
+                  (mh-handle-set-external-undisplayer folder handle function)))
+           (unwind-protect (mm-display-external part method)
+             (set-buffer-modified-p nil)))))
+   nil))
+
+;;;###mh-autoload
+(defun mh-folder-inline-mime-part (part-index)
+  "Show attachment verbatim.
+
+You can view the raw contents of an attachment with this command.
+This command displays (or hides) the contents of the attachment
+associated with the button under the cursor verbatim. If the
+cursor is not located over a button, then the cursor first moves
+to the next button, wrapping to the beginning of the message if
+necessary.
+
+You can also provide a numeric prefix argument PART-INDEX to view
+the attachment labeled with that number."
+  (interactive "P")
+  (when (consp part-index) (setq part-index (car part-index)))
+  (mh-folder-mime-action part-index #'mh-mime-inline-part nil))
+
+(defun mh-mime-inline-part ()
+  "Toggle display of the raw MIME part."
+  (interactive)
+  (let* ((buffer-read-only nil)
+         (data (get-text-property (point) 'mh-data))
+         (inserted-flag (get-text-property (point) 'mh-mime-inserted))
+         (displayed-flag (mm-handle-displayed-p data))
+         (point (point))
+         start end)
+    (cond ((and data (not inserted-flag) (not displayed-flag))
+           (let ((contents (mm-get-part data)))
+             (add-text-properties (line-beginning-position) (line-end-position)
+                                  '(mh-mime-inserted t))
+             (setq start (point-marker))
+             (forward-line 1)
+             (mm-insert-inline data contents)
+             (setq end (point-marker))
+             (add-text-properties
+              start (progn (goto-char start) (line-end-position))
+              `(mh-region (,start . ,end)))))
+          ((and data (or inserted-flag displayed-flag))
+           (mh-press-button)
+           (message "MIME part already inserted")))
+    (goto-char point)
+    (set-buffer-modified-p nil)))
+
+;;;###mh-autoload
+(defun mh-folder-save-mime-part (part-index)
+  "Save (output) attachment.
+
+This command saves the attachment associated with the button under the
+cursor. If the cursor is not located over a button, then the cursor
+first moves to the next button, wrapping to the beginning of the
+message if necessary.
+
+You can also provide a numeric prefix argument PART-INDEX to save the
+attachment labeled with that number.
+
+This command prompts you for a filename and suggests a specific name
+if it is available."
+  (interactive "P")
+  (when (consp part-index) (setq part-index (car part-index)))
+  (mh-folder-mime-action part-index #'mh-mime-save-part nil))
 
-You are prompted for the filename containing the object, the
-media type if it cannot be determined automatically, and a
-content description. If you're using MH-style directives, you
-will also be prompted for additional attributes.
+(defun mh-mime-save-part ()
+  "Save MIME part at point."
+  (interactive)
+  (let ((data (get-text-property (point) 'mh-data)))
+    (when data
+      (let ((mm-default-directory
+             (file-name-as-directory (or mh-mime-save-parts-directory
+                                         default-directory))))
+        (mh-mm-save-part data)
+        (setq mh-mime-save-parts-directory mm-default-directory)))))
+
+;;;###mh-autoload
+(defun mh-folder-toggle-mime-part (part-index)
+  "View attachment.
+
+This command displays (or hides) the attachment associated with
+the button under the cursor. If the cursor is not located over a
+button, then the cursor first moves to the next button, wrapping
+to the beginning of the message if necessary. This command has
+the advantage over related commands of working from the MH-Folder
+buffer.
+
+You can also provide a numeric prefix argument PART-INDEX to view
+the attachment labeled with that number. If Emacs does not know
+how to display the attachment, then Emacs offers to save the
+attachment in a file."
+  (interactive "P")
+  (when (consp part-index) (setq part-index (car part-index)))
+  (mh-folder-mime-action part-index #'mh-press-button t))
+
+;;;###mh-autoload
+(defun mh-mime-save-parts (prompt)
+  "Save attachments.
+
+You can save all of the attachments at once with this command.
+The attachments are saved in the directory specified by the
+option `mh-mime-save-parts-default-directory' unless you use a
+prefix argument PROMPT in which case you are prompted for the
+directory. These directories may be superseded by MH profile
+components, since this function calls on \"mhstore\" (\"mhn\") to
+do the work."
+  (interactive "P")
+  (let ((msg (if (eq major-mode 'mh-show-mode)
+                 (mh-show-buffer-message-number)
+               (mh-get-msg-num t)))
+        (folder (if (eq major-mode 'mh-show-mode)
+                    mh-show-folder-buffer
+                  mh-current-folder))
+        (command (if (mh-variant-p 'nmh) "mhstore" "mhn"))
+        (directory
+         (cond
+          ((and (or prompt
+                    (equal nil mh-mime-save-parts-default-directory)
+                    (equal t mh-mime-save-parts-default-directory))
+                (not mh-mime-save-parts-directory))
+           (read-file-name "Store in directory: " nil nil t nil))
+          ((and (or prompt
+                    (equal t mh-mime-save-parts-default-directory))
+                mh-mime-save-parts-directory)
+           (read-file-name (format
+                            "Store in directory (default %s): "
+                            mh-mime-save-parts-directory)
+                           "" mh-mime-save-parts-directory t ""))
+          ((stringp mh-mime-save-parts-default-directory)
+           mh-mime-save-parts-default-directory)
+          (t
+           mh-mime-save-parts-directory))))
+    (if (and (equal directory "") mh-mime-save-parts-directory)
+        (setq directory mh-mime-save-parts-directory))
+    (if (not (file-directory-p directory))
+        (message "No directory specified")
+      (if (equal nil mh-mime-save-parts-default-directory)
+          (setq mh-mime-save-parts-directory directory))
+      (save-excursion
+        (set-buffer (get-buffer-create mh-log-buffer))
+        (cd directory)
+        (setq mh-mime-save-parts-directory directory)
+        (let ((initial-size (mh-truncate-log-buffer)))
+          (apply 'call-process
+                 (expand-file-name command mh-progs) nil t nil
+                 (mh-list-to-string (list folder msg "-auto")))
+          (if (> (buffer-size) initial-size)
+              (save-window-excursion
+                (switch-to-buffer-other-window mh-log-buffer)
+                (sit-for 3))))))))
+
+;;;###mh-autoload
+(defun mh-toggle-mh-decode-mime-flag ()
+  "Toggle the value of `mh-decode-mime-flag'."
+  (interactive)
+  (setq mh-decode-mime-flag (not mh-decode-mime-flag))
+  (mh-show nil t)
+  (message "%s" (if mh-decode-mime-flag
+                    "Processing attachments normally"
+                  "Displaying raw message")))
+
+;;;###mh-autoload
+(defun mh-toggle-mime-buttons ()
+  "Toggle option `mh-display-buttons-for-inline-parts-flag'."
+  (interactive)
+  (setq mh-display-buttons-for-inline-parts-flag
+        (not mh-display-buttons-for-inline-parts-flag))
+  (mh-show nil t))
+
+
+
+;;; MIME Display Routines
+
+(defun mh-mm-inline-message (handle)
+  "Display message, HANDLE.
+The function decodes the message and displays it. It avoids
+decoding the same message multiple times."
+  (let ((b (point))
+        (clean-message-header mh-clean-message-header-flag)
+        (invisible-headers mh-invisible-header-fields-compiled)
+        (visible-headers nil))
+    (save-excursion
+      (save-restriction
+        (narrow-to-region b b)
+        (mm-insert-part handle)
+        (mh-mime-display
+         (or (gethash handle (mh-mime-handles-cache (mh-buffer-data)))
+             (setf (gethash handle (mh-mime-handles-cache (mh-buffer-data)))
+                   (let ((handles (mm-dissect-buffer nil)))
+                     (if handles
+                         (mh-mm-uu-dissect-text-parts handles)
+                       (setq handles (mm-uu-dissect)))
+                     (setf (mh-mime-handles (mh-buffer-data))
+                           (mh-mm-merge-handles
+                            handles (mh-mime-handles (mh-buffer-data))))
+                     handles))))
+
+        (goto-char (point-min))
+        (mh-show-xface)
+        (cond (clean-message-header
+               (mh-clean-msg-header (point-min)
+                                    invisible-headers
+                                    visible-headers)
+               (goto-char (point-min)))
+              (t
+               (mh-start-of-uncleaned-message)))
+        (mh-decode-message-header)
+        (mh-show-addr)
+        ;; The other highlighting types don't need anything special
+        (when (eq mh-highlight-citation-style 'gnus)
+          (mh-gnus-article-highlight-citation))
+        (goto-char (point-min))
+        (insert "\n------- Forwarded Message\n\n")
+        (mh-display-smileys)
+        (mh-display-emphasis)
+        (mm-handle-set-undisplayer
+         handle
+         `(lambda ()
+            (let (buffer-read-only)
+              (if (fboundp 'remove-specifier)
+                  ;; This is only valid on XEmacs.
+                  (mapcar (lambda (prop)
+                            (remove-specifier
+                             (face-property 'default prop) (current-buffer)))
+                          '(background background-pixmap foreground)))
+              (delete-region ,(point-min-marker) ,(point-max-marker)))))))))
+
+;;;###mh-autoload
+(defun mh-decode-message-header ()
+  "Decode RFC2047 encoded message header fields."
+  (when mh-decode-mime-flag
+    (let ((buffer-read-only nil))
+      (rfc2047-decode-region (point-min) (mh-mail-header-end)))))
+
+;;;###mh-autoload
+(defun mh-mime-display (&optional pre-dissected-handles)
+  "Display (and possibly decode) MIME handles.
+Optional argument, PRE-DISSECTED-HANDLES is a list of MIME
+handles. If present they are displayed otherwise the buffer is
+parsed and then displayed."
+  (let ((handles ())
+        (folder mh-show-folder-buffer)
+        (raw-message-data (buffer-string)))
+    (flet ((mm-handle-set-external-undisplayer
+            (handle function)
+            (mh-handle-set-external-undisplayer folder handle function)))
+      (goto-char (point-min))
+      (unless (search-forward "\n\n" nil t)
+        (goto-char (point-max))
+        (insert "\n\n"))
+
+      (condition-case err
+          (progn
+            ;; If needed dissect the current buffer
+            (if pre-dissected-handles
+                (setq handles pre-dissected-handles)
+              (if (setq handles (mm-dissect-buffer nil))
+                  (mh-mm-uu-dissect-text-parts handles)
+                (setq handles (mm-uu-dissect)))
+              (setf (mh-mime-handles (mh-buffer-data))
+                    (mh-mm-merge-handles handles
+                                         (mh-mime-handles (mh-buffer-data))))
+              (unless handles
+                (mh-decode-message-body)))
+
+            (cond ((and handles
+                        (or (not (stringp (car handles)))
+                            (cdr handles)))
+                   ;; Go to start of message body
+                   (goto-char (point-min))
+                   (or (search-forward "\n\n" nil t)
+                       (goto-char (point-max)))
+
+                   ;; Delete the body
+                   (delete-region (point) (point-max))
+
+                   ;; Display the MIME handles
+                   (mh-mime-display-part handles))
+                  (t
+                   (mh-signature-highlight))))
+        (error
+         (message "Could not display body: %s" (error-message-string err))
+         (delete-region (point-min) (point-max))
+         (insert raw-message-data))))))
+
+(defun mh-decode-message-body ()
+  "Decode message based on charset.
+If message has been encoded for transfer take that into account."
+  (let (ct charset cte)
+    (goto-char (point-min))
+    (re-search-forward "\n\n" nil t)
+    (save-restriction
+      (narrow-to-region (point-min) (point))
+      (setq ct (ignore-errors (mail-header-parse-content-type
+                               (message-fetch-field "Content-Type" t)))
+            charset (mail-content-type-get ct 'charset)
+            cte (message-fetch-field "Content-Transfer-Encoding")))
+    (when (stringp cte) (setq cte (mail-header-strip cte)))
+    (when (or (not ct) (equal (car ct) "text/plain"))
+      (save-restriction
+        (narrow-to-region (min (1+ (mh-mail-header-end)) (point-max))
+                          (point-max))
+        (mm-decode-body charset
+                        (and cte (intern (downcase
+                                          (gnus-strip-whitespace cte))))
+                        (car ct))))))
+
+(defun mh-mime-display-part (handle)
+  "Decides the viewer to call based on the type of HANDLE."
+  (cond ((null handle)
+         nil)
+        ((not (stringp (car handle)))
+         (mh-mime-display-single handle))
+        ((equal (car handle) "multipart/alternative")
+         (mh-mime-display-alternative (cdr handle)))
+        ((and mh-pgp-support-flag
+              (or (equal (car handle) "multipart/signed")
+                  (equal (car handle) "multipart/encrypted")))
+         (mh-mime-display-security handle))
+        (t
+         (mh-mime-display-mixed (cdr handle)))))
+
+(defun mh-mime-display-mixed (handles)
+  "Display the list of MIME parts, HANDLES recursively."
+  (mapcar #'mh-mime-display-part handles))
+
+(defun mh-mime-display-alternative (handles)
+  "Choose among the alternatives, HANDLES the part that will be displayed.
+If no part is preferred then all the parts are displayed."
+  (let* ((preferred (mm-preferred-alternative handles))
+         (others (loop for x in handles unless (eq x preferred) collect x)))
+    (cond ((and preferred
+                (stringp (car preferred)))
+           (mh-mime-display-part preferred)
+           (mh-mime-maybe-display-alternatives others))
+          (preferred
+           (save-restriction
+             (narrow-to-region (point) (if (eobp) (point) (1+ (point))))
+             (mh-mime-display-single preferred)
+             (mh-mime-maybe-display-alternatives others)
+             (goto-char (point-max))))
+          (t
+           (mh-mime-display-mixed handles)))))
 
-The option `mh-compose-insertion' controls what type of tags are
-inserted. Optional argument INLINE means make it an inline
-attachment."
-  (interactive "P")
-  (if (equal mh-compose-insertion 'mml)
-      (if inline
-          (mh-mml-attach-file "inline")
-        (mh-mml-attach-file))
-    (call-interactively 'mh-mh-attach-file)))
+(defun mh-mime-maybe-display-alternatives (alternatives)
+  "Show buttons for ALTERNATIVES.
+If `mh-mime-display-alternatives-flag' is non-nil then display
+buttons for alternative parts that are usually suppressed."
+  (when (and mh-display-buttons-for-alternatives-flag alternatives)
+    (insert "\n----------------------------------------------------\n")
+    (insert "Alternatives:\n")
+    (dolist (x alternatives)
+      (insert "\n")
+      (mh-insert-mime-button x (mh-mime-part-index x) nil))
+    (insert "\n----------------------------------------------------\n")))
+
+(defun mh-mime-display-security (handle)
+  "Display PGP encrypted/signed message, HANDLE."
+  (save-restriction
+    (narrow-to-region (point) (point))
+    (insert "\n")
+    (mh-insert-mime-security-button handle)
+    (mh-mime-display-mixed (cdr handle))
+    (insert "\n")
+    (let ((mh-mime-security-button-line-format
+           mh-mime-security-button-end-line-format))
+      (mh-insert-mime-security-button handle))
+    (mh-mm-set-handle-multipart-parameter
+     handle 'mh-region (cons (point-min-marker) (point-max-marker)))))
+
+(defun mh-mime-display-single (handle)
+  "Display a leaf node, HANDLE in the MIME tree."
+  (let* ((type (mm-handle-media-type handle))
+         (small-image-flag (mh-small-image-p handle))
+         (attachmentp (equal (car (mm-handle-disposition handle))
+                             "attachment"))
+         (inlinep (and (equal (car (mm-handle-disposition handle)) "inline")
+                       (mm-inlinable-p handle)
+                       (mm-inlined-p handle)))
+         (displayp (or inlinep                   ; show if inline OR
+                       (mh-inline-vcard-p handle);      inline vcard OR
+                       (and (not attachmentp)    ;      if not an attachment
+                            (or small-image-flag ;        and small image
+                                                 ;        and user wants inline
+                                (and (not (equal
+                                           (mm-handle-media-supertype handle)
+                                           "image"))
+                                     (mm-inlinable-p handle)
+                                     (mm-inlined-p handle)))))))
+    (save-restriction
+      (narrow-to-region (point) (if (eobp) (point) (1+ (point))))
+      (cond ((and mh-pgp-support-flag
+                  (equal type "application/pgp-signature"))
+             nil)             ; skip signatures as they are already handled...
+            ((not displayp)
+             (insert "\n")
+             (mh-insert-mime-button handle (mh-mime-part-index handle) nil))
+            ((and displayp
+                  (not mh-display-buttons-for-inline-parts-flag))
+             (or (mm-display-part handle)
+                 (mm-display-part handle))
+             (mh-signature-highlight handle))
+            ((and displayp
+                  mh-display-buttons-for-inline-parts-flag)
+             (insert "\n")
+             (mh-insert-mime-button handle (mh-mime-part-index handle) nil)
+             (forward-line -1)
+             (mh-mm-display-part handle)))
+      (goto-char (point-max)))))
+
+;; There is a bug in Gnus inline image display due to which an extra line
+;; gets inserted every time it is viewed. To work around that problem we are
+;; using an extra property 'mh-region to remember the region that is added
+;; when the button is clicked. The region is then deleted to make sure that
+;; no extra lines get inserted.
+(defun mh-mm-display-part (handle)
+  "Toggle display of button for MIME part, HANDLE."
+  (beginning-of-line)
+  (let ((id (get-text-property (point) 'mh-part))
+        (point (point))
+        (window (selected-window))
+        (mail-parse-charset 'nil)
+        (mail-parse-ignored-charsets nil)
+        region buffer-read-only)
+    (save-excursion
+      (unwind-protect
+          (let ((win (get-buffer-window (current-buffer) t)))
+            (when win
+              (select-window win))
+            (goto-char point)
+
+            (if (mm-handle-displayed-p handle)
+                ;; This will remove the part.
+                (progn
+                  ;; Delete the button and displayed part (if any)
+                  (let ((region (get-text-property point 'mh-region)))
+                    (when region
+                      (mh-funcall-if-exists
+                       remove-images (car region) (cdr region)))
+                    (mm-display-part handle)
+                    (when region
+                      (delete-region (car region) (cdr region))))
+                  ;; Delete button (if it still remains). This happens for
+                  ;; externally displayed parts where the previous step does
+                  ;; nothing.
+                  (unless (eolp)
+                    (delete-region (point) (progn (forward-line) (point)))))
+              (save-restriction
+                (delete-region (point) (progn (forward-line 1) (point)))
+                (narrow-to-region (point) (point))
+                ;; Maybe we need another unwind-protect here.
+                (when (equal (mm-handle-media-supertype handle) "image")
+                  (insert "\n"))
+                (when (and (not (eq (ignore-errors (mm-display-part handle))
+                                    'inline))
+                           (equal (mm-handle-media-supertype handle)
+                                  "image"))
+                  (goto-char (point-min))
+                  (delete-char 1))
+                (when (equal (mm-handle-media-supertype handle) "text")
+                  (when (eq mh-highlight-citation-style 'gnus)
+                    (mh-gnus-article-highlight-citation))
+                  (mh-display-smileys)
+                  (mh-display-emphasis)
+                  (mh-signature-highlight handle))
+                (setq region (cons (progn (goto-char (point-min))
+                                          (point-marker))
+                                   (progn (goto-char (point-max))
+                                          (point-marker)))))))
+        (when (window-live-p window)
+          (select-window window))
+        (goto-char point)
+        (beginning-of-line)
+        (mh-insert-mime-button handle id (mm-handle-displayed-p handle))
+        (goto-char point)
+        (when region
+          (add-text-properties (line-beginning-position) (line-end-position)
+                               `(mh-region ,region)))))))
+
+(defun mh-mime-part-index (handle)
+  "Generate the button number for MIME part, HANDLE.
+Notice that a hash table is used to display the same number when
+buttons need to be displayed multiple times (for instance when
+nested messages are opened)."
+  (or (gethash handle (mh-mime-part-index-hash (mh-buffer-data)))
+      (setf (gethash handle (mh-mime-part-index-hash (mh-buffer-data)))
+            (incf (mh-mime-parts-count (mh-buffer-data))))))
+
+(defun mh-small-image-p (handle)
+  "Decide whether HANDLE is a \"small\" image that can be displayed inline.
+This is only useful if a Content-Disposition header is not present."
+  (let ((media-test (caddr (assoc (car (mm-handle-type handle))
+                                  mh-mm-inline-media-tests)))
+        (mm-inline-large-images t))
+    (and media-test
+         (equal (mm-handle-media-supertype handle) "image")
+         (funcall media-test handle) ; Since mm-inline-large-images is T,
+                                        ; this only tells us if the image is
+                                        ; something that emacs can display
+         (let* ((image (mm-get-image handle)))
+           (or (mh-do-in-xemacs
+                 (and (mh-funcall-if-exists glyphp image)
+                      (< (glyph-width image)
+                         (or mh-max-inline-image-width (window-pixel-width)))
+                      (< (glyph-height image)
+                         (or mh-max-inline-image-height
+                             (window-pixel-height)))))
+               (mh-do-in-gnu-emacs
+                 (let ((size (mh-funcall-if-exists image-size image)))
+                   (and size
+                        (< (cdr size) (or mh-max-inline-image-height
+                                          (1- (window-height))))
+                        (< (car size) (or mh-max-inline-image-width
+                                          (window-width)))))))))))
+
+(defun mh-inline-vcard-p (handle)
+  "Decide if HANDLE is a vcard that must be displayed inline."
+  (let ((type (mm-handle-type handle)))
+    (and (or (featurep 'vcard) (fboundp 'vcard-pretty-print))
+         (consp type)
+         (equal (car type) "text/x-vcard")
+         (save-excursion
+           (save-restriction
+             (widen)
+             (goto-char (point-min))
+             (not (mh-signature-separator-p)))))))
+
+(defun mh-signature-highlight (&optional handle)
+  "Highlight message signature in HANDLE.
+The optional argument, HANDLE is a MIME handle if the function is
+being used to highlight the signature in a MIME part."
+  (let ((regexp
+         (cond ((not handle) "^-- $")
+               ((not (and (equal (mm-handle-media-supertype handle) "text")
+                          (equal (mm-handle-media-subtype handle) "html")))
+                "^-- $")
+               ((eq (mh-mm-text-html-renderer) 'lynx) "^   --$")
+               (t "^--$"))))
+    (save-excursion
+      (goto-char (point-max))
+      (when (re-search-backward regexp nil t)
+        (mh-do-in-gnu-emacs
+          (let ((ov (make-overlay (point) (point-max))))
+            (overlay-put ov 'face 'mh-show-signature)
+            (overlay-put ov 'evaporate t)))
+        (mh-do-in-xemacs
+          (set-extent-property (make-extent (point) (point-max))
+                               'face 'mh-show-signature))))))
+
+
+
+;;; Button Display
+
+;; Shush compiler.
+(eval-when-compile (mh-do-in-xemacs (defvar dots) (defvar type) (defvar ov)))
+
+(defun mh-insert-mime-button (handle index displayed)
+  "Insert MIME button for HANDLE.
+INDEX is the part number that will be DISPLAYED. It is also used
+by commands like \"K v\" which operate on individual MIME parts."
+  ;; The button could be displayed by a previous decode. In that case
+  ;; undisplay it if we need a hidden button.
+  (when (and (mm-handle-displayed-p handle) (not displayed))
+    (mm-display-part handle))
+  (let ((name (or (mail-content-type-get (mm-handle-type handle) 'name)
+                  (mail-content-type-get (mm-handle-disposition handle)
+                                         'filename)
+                  (mail-content-type-get (mm-handle-type handle) 'url)
+                  ""))
+        (type (mm-handle-media-type handle))
+        (description (mail-decode-encoded-word-string
+                      (or (mm-handle-description handle) "")))
+        (dots (if (or displayed (mm-handle-displayed-p handle)) "   " "..."))
+        long-type begin end)
+    (if (string-match ".*/" name) (setq name (substring name (match-end 0))))
+    (setq long-type (concat type (and (not (equal name ""))
+                                      (concat "; " name))))
+    (unless (equal description "")
+      (setq long-type (concat " --- " long-type)))
+    (unless (bolp) (insert "\n"))
+    (setq begin (point))
+    (gnus-eval-format
+     mh-mime-button-line-format mh-mime-button-line-format-alist
+     `(,@(mh-gnus-local-map-property mh-mime-button-map)
+         mh-callback mh-mm-display-part
+         mh-part ,index
+         mh-data ,handle))
+    (setq end (point))
+    (widget-convert-button
+     'link begin end
+     :mime-handle handle
+     :action 'mh-widget-press-button
+     :button-keymap mh-mime-button-map
+     :help-echo
+     "Mouse-2 click or press RET (in show buffer) to toggle display")
+    (dolist (ov (mh-funcall-if-exists overlays-in begin end))
+      (mh-funcall-if-exists overlay-put ov 'evaporate t))))
+
+;; Shush compiler.
+(eval-when-compile
+  (when (< emacs-major-version 22)
+    (defvar  mm-verify-function-alist)
+    (defvar  mm-decrypt-function-alist))
+  (mh-do-in-xemacs
+    (defvar pressed-details)))
+
+(defun mh-insert-mime-security-button (handle)
+  "Display buttons for PGP message, HANDLE."
+  (let* ((protocol (mh-mm-handle-multipart-ctl-parameter handle 'protocol))
+         (crypto-type (or (nth 2 (assoc protocol mm-verify-function-alist))
+                          (nth 2 (assoc protocol mm-decrypt-function-alist))
+                          "Unknown"))
+         (type (concat crypto-type
+                       (if (equal (car handle) "multipart/signed")
+                           " Signed" " Encrypted")
+                       " Part"))
+         (info (or (mh-mm-handle-multipart-ctl-parameter handle 'gnus-info)
+                   "Undecided"))
+         (details (mh-mm-handle-multipart-ctl-parameter handle 'gnus-details))
+         pressed-details begin end face)
+    (setq details (if details (concat "\n" details) ""))
+    (setq pressed-details (if mh-mime-security-button-pressed details ""))
+    (setq face (mh-mime-security-button-face info))
+    (unless (bolp) (insert "\n"))
+    (setq begin (point))
+    (gnus-eval-format
+     mh-mime-security-button-line-format
+     mh-mime-security-button-line-format-alist
+     `(,@(mh-gnus-local-map-property mh-mime-security-button-map)
+         mh-button-pressed ,mh-mime-security-button-pressed
+         mh-callback mh-mime-security-press-button
+         mh-line-format ,mh-mime-security-button-line-format
+         mh-data ,handle))
+    (setq end (point))
+    (widget-convert-button 'link begin end
+                           :mime-handle handle
+                           :action 'mh-widget-press-button
+                           :button-keymap mh-mime-security-button-map
+                           :button-face face
+                           :help-echo "Mouse-2 click or press RET (in show buffer) to see security details.")
+    (dolist (ov (mh-funcall-if-exists overlays-in begin end))
+      (mh-funcall-if-exists overlay-put ov 'evaporate t))
+    (when (equal info "Failed")
+      (let* ((type (if (equal (car handle) "multipart/signed")
+                       "verification" "decryption"))
+             (warning (if (equal type "decryption")
+                          "(passphrase may be incorrect)" "")))
+        (message "%s %s failed %s" crypto-type type warning)))))
+
+(defun mh-mime-security-button-face (info)
+  "Return the button face to use for encrypted/signed mail based on INFO."
+  (cond ((string-match "OK" info)       ;Decrypted mail
+         'mh-show-pgg-good)
+        ((string-match "Failed" info)   ;Decryption failed or signature invalid
+         'mh-show-pgg-bad)
+        ((string-match "Undecided" info);Unprocessed mail
+         'mh-show-pgg-unknown)
+        ((string-match "Untrusted" info);Key not trusted
+         'mh-show-pgg-unknown)
+        (t
+         'mh-show-pgg-good)))
+
+
+
+;;; Button Handlers
+
+(defun mh-folder-mime-action (part-index action include-security-flag)
+  "Go to PART-INDEX and carry out ACTION.
+
+If PART-INDEX is nil then go to the next part in the buffer. The
+search for the next buffer wraps around if end of buffer is reached.
+If argument INCLUDE-SECURITY-FLAG is non-nil then include security
+info buttons when searching for a suitable parts."
+  (unless mh-showing-mode
+    (mh-show))
+  (mh-in-show-buffer (mh-show-buffer)
+    (let ((criterion
+           (cond (part-index
+                  (lambda (p)
+                    (let ((part (get-text-property p 'mh-part)))
+                      (and (integerp part) (= part part-index)))))
+                 (t (lambda (p)
+                      (if include-security-flag
+                          (get-text-property p 'mh-data)
+                        (integerp (get-text-property p 'mh-part)))))))
+          (point (point)))
+      (cond ((and (get-text-property point 'mh-part)
+                  (or (null part-index)
+                      (= (get-text-property point 'mh-part) part-index)))
+             (funcall action))
+            ((and (get-text-property point 'mh-data)
+                  include-security-flag
+                  (null part-index))
+             (funcall action))
+            (t
+             (mh-goto-next-button nil criterion)
+             (if (= (point) point)
+                 (message "No matching MIME part found")
+               (funcall action)))))))
+
+;;;###mh-autoload
+(defun mh-goto-next-button (backward-flag &optional criterion)
+  "Search for next button satisfying criterion.
+
+If BACKWARD-FLAG is non-nil search backward in the buffer for a mime
+button.
+If CRITERION is a function or a symbol which has a function binding
+then that function must return non-nil at the button we stop."
+  (unless (or (and (symbolp criterion) (fboundp criterion))
+              (functionp criterion))
+    (setq criterion (lambda (x) t)))
+  ;; Move to the next button in the buffer satisfying criterion
+  (goto-char (or (save-excursion
+                   (beginning-of-line)
+                   ;; Find point before current button
+                   (let ((point-before-current-button
+                          (save-excursion
+                            (while (get-text-property (point) 'mh-data)
+                              (unless (= (forward-line
+                                          (if backward-flag 1 -1))
+                                         0)
+                                (if backward-flag
+                                    (goto-char (point-min))
+                                  (goto-char (point-max)))))
+                            (point))))
+                     ;; Skip over current button
+                     (while (and (get-text-property (point) 'mh-data)
+                                 (not (if backward-flag (bobp) (eobp))))
+                       (forward-line (if backward-flag -1 1)))
+                     ;; Stop at next MIME button if any exists.
+                     (block loop
+                       (while (/= (progn
+                                    (unless (= (forward-line
+                                                (if backward-flag -1 1))
+                                               0)
+                                      (if backward-flag
+                                          (goto-char (point-max))
+                                        (goto-char (point-min)))
+                                      (beginning-of-line))
+                                    (point))
+                                  point-before-current-button)
+                         (when (and (get-text-property (point) 'mh-data)
+                                    (funcall criterion (point)))
+                           (return-from loop (point))))
+                       nil)))
+                 (point))))
+
+(defun mh-widget-press-button (widget el)
+  "Callback for widget, WIDGET.
+Parameter EL is unused."
+  (goto-char (widget-get widget :from))
+  (mh-press-button))
+
+(defun mh-press-button ()
+  "View contents of button.
+
+This command is a toggle so if you use it again on the same
+attachment, the attachment is hidden."
+  (interactive)
+  (let ((mm-inline-media-tests mh-mm-inline-media-tests)
+        (data (get-text-property (point) 'mh-data))
+        (function (get-text-property (point) 'mh-callback))
+        (buffer-read-only nil)
+        (folder mh-show-folder-buffer))
+    (flet ((mm-handle-set-external-undisplayer
+            (handle function)
+            (mh-handle-set-external-undisplayer folder handle function)))
+      (when (and function (eolp))
+        (backward-char))
+      (unwind-protect (and function (funcall function data))
+        (set-buffer-modified-p nil)))))
+
+(defun mh-push-button (event)
+  "Click MIME button for EVENT.
+
+If the MIME part is visible then it is removed. Otherwise the
+part is displayed. This function is called when the mouse is used
+to click the MIME button."
+  (interactive "e")
+  (mh-do-at-event-location event
+    (let ((folder mh-show-folder-buffer)
+          (mm-inline-media-tests mh-mm-inline-media-tests)
+          (data (get-text-property (point) 'mh-data))
+          (function (get-text-property (point) 'mh-callback)))
+      (flet ((mm-handle-set-external-undisplayer (handle func)
+               (mh-handle-set-external-undisplayer folder handle func)))
+        (and function (funcall function data))))))
+
+(defun mh-handle-set-external-undisplayer (folder handle function)
+  "Replacement for `mm-handle-set-external-undisplayer'.
+
+This is only called in recent versions of Gnus. The MIME handles
+are stored in data structures corresponding to MH-E folder buffer
+FOLDER instead of in Gnus (as in the original). The MIME part,
+HANDLE is associated with the undisplayer FUNCTION."
+  (if (mh-mm-keep-viewer-alive-p handle)
+      (let ((new-handle (copy-sequence handle)))
+        (mm-handle-set-undisplayer new-handle function)
+        (mm-handle-set-undisplayer handle nil)
+        (save-excursion
+          (set-buffer folder)
+          (push new-handle (mh-mime-handles (mh-buffer-data)))))
+    (mm-handle-set-undisplayer handle function)))
+
+(defun mh-mime-security-press-button (handle)
+  "Callback from security button for part HANDLE."
+  (if (mh-mm-handle-multipart-ctl-parameter handle 'gnus-info)
+      (mh-mime-security-show-details handle)
+    (let ((region (mh-mm-handle-multipart-ctl-parameter handle 'mh-region))
+          point)
+      (setq point (point))
+      (goto-char (car region))
+      (delete-region (car region) (cdr region))
+      (with-current-buffer (mh-mm-handle-multipart-ctl-parameter handle 'buffer)
+        (let* ((mm-verify-option 'known)
+               (mm-decrypt-option 'known)
+               (new (mh-mm-possibly-verify-or-decrypt (cdr handle) handle)))
+          (unless (eq new (cdr handle))
+            (mh-mm-destroy-parts (cdr handle))
+            (setcdr handle new))))
+      (mh-mime-display-security handle)
+      (goto-char point))))
+
+;; I rewrote the security part because Gnus doesn't seem to ever minimize
+;; the button. That is once the mime-security button is pressed there seems
+;; to be no way of getting rid of the inserted text.
+(defun mh-mime-security-show-details (handle)
+  "Toggle display of detailed security info for HANDLE."
+  (let ((details (mh-mm-handle-multipart-ctl-parameter handle 'gnus-details)))
+    (when details
+      (let ((mh-mime-security-button-pressed
+             (not (get-text-property (point) 'mh-button-pressed)))
+            (mh-mime-security-button-line-format
+             (get-text-property (point) 'mh-line-format)))
+        (forward-char -1)
+        (while (eq (get-text-property (point) 'mh-line-format)
+                   mh-mime-security-button-line-format)
+          (forward-char -1))
+        (forward-char)
+        (save-restriction
+          (narrow-to-region (point) (point))
+          (mh-insert-mime-security-button handle))
+        (delete-region
+         (point)
+         (or (text-property-not-all
+              (point) (point-max)
+              'mh-line-format mh-mime-security-button-line-format)
+             (point-max)))
+        (forward-line -1)))))
+
+
+
+;;; Miscellaneous Article Washing
+
+;;;###mh-autoload
+(defun mh-add-missing-mime-version-header ()
+  "Some mail programs don't put a MIME-Version header.
+I have seen this only in spam, so maybe we shouldn't fix
+this ;-)"
+  (save-excursion
+    (goto-char (point-min))
+    (re-search-forward "\n\n" nil t)
+    (save-restriction
+      (narrow-to-region (point-min) (point))
+      (when (and (message-fetch-field "content-type")
+                 (not (message-fetch-field "mime-version")))
+        (goto-char (point-min))
+        (insert "MIME-Version: 1.0\n")))))
+
+;;;###mh-autoload
+(defun mh-display-smileys ()
+  "Display smileys."
+  (when (and mh-graphical-smileys-flag (mh-small-show-buffer-p))
+    (mh-funcall-if-exists smiley-region (point-min) (point-max))))
+
+;;;###mh-autoload
+(defun mh-display-emphasis ()
+  "Display graphical emphasis."
+  (when (and mh-graphical-emphasis-flag (mh-small-show-buffer-p))
+    (flet ((article-goto-body ()))      ; shadow this function to do nothing
+      (save-excursion
+        (goto-char (point-min))
+        (article-emphasize)))))
+
+(defun mh-small-show-buffer-p ()
+  "Check if show buffer is small.
+This is used to decide if smileys and graphical emphasis should be
+displayed."
+  (let ((max nil))
+    (when (and (boundp 'font-lock-maximum-size) font-lock-maximum-size)
+      (cond ((numberp font-lock-maximum-size)
+             (setq max font-lock-maximum-size))
+            ((listp font-lock-maximum-size)
+             (setq max (cdr (or (assoc 'mh-show-mode font-lock-maximum-size)
+                                (assoc t font-lock-maximum-size)))))))
+    (or (not (numberp max)) (>= (/ max 8) (buffer-size)))))
+
+
+
+;;; MH-Letter Commands
+
+;; MH-E commands are alphabetical; specific support routines follow command.
 
 ;;;###mh-autoload
 (defun mh-compose-forward (&optional description folder range)
@@ -110,144 +1208,98 @@
           (mh-mml-forward-message description folder (format "%s" message))
         (mh-mh-forward-message description folder (format "%s" message))))))
 
-;; To do:
-;; paragraph code should not fill # lines if MIME enabled.
-;; implement mh-auto-mh-to-mime (if non-nil, \\[mh-send-letter]
-;;      invokes mh-mh-to-mime automatically before sending.)
-;;      actually, instead of mh-auto-mh-to-mime,
-;;      should read automhnproc from profile
-;; MIME option to mh-forward
-;; command to move to content-description insertion point
+;;;###mh-autoload
+(defun mh-mml-forward-message (description folder message)
+  "Forward a message as attachment.
 
-(defvar mh-mh-to-mime-args nil
-  "Extra arguments for \\[mh-mh-to-mime] to pass to the \"mhbuild\" command.
-The arguments are passed to \"mhbuild\" if \\[mh-mh-to-mime] is
-given a prefix argument. Normally default arguments to
-\"mhbuild\" are specified in the MH profile.")
-
-(defvar mh-media-type-regexp
-  (concat (regexp-opt '("text" "image" "audio" "video" "application"
-                        "multipart" "message") t)
-          "/[-.+a-zA-Z0-9]+")
-  "Regexp matching valid media types used in MIME attachment compositions.")
-
-(defvar mh-have-file-command 'undefined
-  "Cached value of function `mh-have-file-command'.
-Do not reference this variable directly as it might not have been
-initialized. Always use the command `mh-have-file-command'.")
+The function will prompt the user for a DESCRIPTION, a FOLDER and
+MESSAGE number."
+  (let ((msg (if (and (equal message "") (numberp mh-sent-from-msg))
+                 mh-sent-from-msg
+               (string-to-number message))))
+    (cond ((integerp msg)
+           (if (string= "" description)
+               ;; Rationale: mml-attach-file constructs a malformed composition
+               ;; if the description string is empty.  This fixes SF #625168.
+               (mml-attach-file (format "%s%s/%d"
+                                        mh-user-path (substring folder 1) msg)
+                                "message/rfc822")
+             (mml-attach-file (format "%s%s/%d"
+                                      mh-user-path (substring folder 1) msg)
+                              "message/rfc822"
+                              description)))
+          (t (error "The message number, %s, is not a integer" msg)))))
 
-;;;###mh-autoload
-(defun mh-have-file-command ()
-  "Return t if 'file' command is on the system.
-'file -i' is used to get MIME type of composition insertion."
-  (when (eq mh-have-file-command 'undefined)
-    (setq mh-have-file-command
-          (and (fboundp 'executable-find)
-               (executable-find "file") ; file command exists
-                                        ;   and accepts -i and -b args.
-               (zerop (call-process "file" nil nil nil "-i" "-b"
-                                    (expand-file-name "inc" mh-progs))))))
-  mh-have-file-command)
+(defun mh-mh-forward-message (&optional description folder messages)
+  "Add tag to forward a message.
+You are prompted for a content DESCRIPTION, the name of the
+FOLDER in which the messages to forward are located, and the
+MESSAGES' numbers.
 
-(defvar mh-file-mime-type-substitutions
-  '(("application/msword" "\.xls" "application/ms-excel")
-    ("application/msword" "\.ppt" "application/ms-powerpoint")
-    ("text/plain" "\.vcf" "text/x-vcard"))
-  "Substitutions to make for Content-Type returned from file command.
-The first element is the Content-Type returned by the file command.
-The second element is a regexp matching the file name, usually the
-extension.
-The third element is the Content-Type to replace with.")
-
-(defun mh-file-mime-type-substitute (content-type filename)
-  "Return possibly changed CONTENT-TYPE on the FILENAME.
-Substitutions are made from the `mh-file-mime-type-substitutions'
-variable."
-  (let ((subst mh-file-mime-type-substitutions)
-        (type) (match) (answer content-type)
-        (case-fold-search t))
-    (while subst
-      (setq type (car (car subst))
-            match (elt (car subst) 1))
-      (if (and (string-equal content-type type)
-               (string-match match filename))
-          (setq answer (elt (car subst) 2)
-                subst nil)
-        (setq subst (cdr subst))))
-    answer))
+See also \\[mh-mh-to-mime]."
+  (interactive (list
+                (mml-minibuffer-read-description)
+                (mh-prompt-for-folder "Message from" mh-sent-from-folder nil)
+                (read-string (concat "Messages"
+                                     (if (numberp mh-sent-from-msg)
+                                         (format " (default %d): "
+                                                 mh-sent-from-msg)
+                                       ": ")))))
+  (beginning-of-line)
+  (insert "#forw [")
+  (and description
+       (not (string= description ""))
+       (insert description))
+  (insert "]")
+  (and folder
+       (not (string= folder ""))
+       (insert " " folder))
+  (if (and messages
+           (not (string= messages "")))
+      (let ((start (point)))
+        (insert " " messages)
+        (subst-char-in-region start (point) ?, ? ))
+    (if (numberp mh-sent-from-msg)
+        (insert " " (int-to-string mh-sent-from-msg))))
+  (insert "\n"))
 
 ;;;###mh-autoload
-(defun mh-file-mime-type (filename)
-  "Return MIME type of FILENAME from file command.
-Returns nil if file command not on system."
-  (cond
-   ((not (mh-have-file-command))
-    nil)                                ;no file command, exit now
-   ((not (and (file-exists-p filename)
-              (file-readable-p filename)))
-    nil)                               ;no file or not readable, ditto
-   (t
-    (save-excursion
-      (let ((tmp-buffer (get-buffer-create mh-temp-buffer)))
-        (set-buffer tmp-buffer)
-        (unwind-protect
-            (progn
-              (call-process "file" nil '(t nil) nil "-b" "-i"
-                            (expand-file-name filename))
-              (goto-char (point-min))
-              (if (not (re-search-forward mh-media-type-regexp nil t))
-                  nil
-                (mh-file-mime-type-substitute (match-string 0) filename)))
-          (kill-buffer tmp-buffer)))))))
+(defun mh-compose-insertion (&optional inline)
+  "Add tag to include a file such as an image or sound.
+
+You are prompted for the filename containing the object, the
+media type if it cannot be determined automatically, and a
+content description. If you're using MH-style directives, you
+will also be prompted for additional attributes.
+
+The option `mh-compose-insertion' controls what type of tags are
+inserted. Optional argument INLINE means make it an inline
+attachment."
+  (interactive "P")
+  (if (equal mh-compose-insertion 'mml)
+      (if inline
+          (mh-mml-attach-file "inline")
+        (mh-mml-attach-file))
+    (call-interactively 'mh-mh-attach-file)))
 
-(defun mh-minibuffer-read-type (filename &optional default)
-  "Return the content type associated with the given FILENAME.
-If the \"file\" command exists and recognizes the given file,
-then its value is returned\; otherwise, the user is prompted for
-a type (see `mailcap-mime-types' and for Emacs 20,
-`mh-mime-content-types').
-Optional argument DEFAULT is returned if a type isn't entered."
-  (mailcap-parse-mimetypes)
-  (let* ((default (or default
-                      (mm-default-file-encoding filename)
-                      "application/octet-stream"))
-         (probed-type (mh-file-mime-type filename))
-         (type (or (and (not (equal probed-type "application/octet-stream"))
-                        probed-type)
-                   (completing-read
-                    (format "Content type (default %s): " default)
-                    (mapcar 'list (mailcap-mime-types))))))
-    (if (not (equal type ""))
-        type
-      default)))
+(defun mh-mml-attach-file (&optional disposition)
+  "Add a tag to insert a MIME message part from a file.
+
+You are prompted for the filename containing the object, the
+media type if it cannot be determined automatically, a content
+description and the DISPOSITION of the attachment.
 
-;; RFC 2045 - Multipurpose Internet Mail Extensions (MIME) Part One:
-;;            Format of Internet Message Bodies.
-;; RFC 2046 - Multipurpose Internet Mail Extensions (MIME) Part Two:
-;;            Media Types.
-;; RFC 2049 - Multipurpose Internet Mail Extensions (MIME) Part Five:
-;;            Conformance Criteria and Examples.
-;; RFC 2017 - Definition of the URL MIME External-Body Access-Type
-;; RFC 1738 - Uniform Resource Locators (URL)
-(defvar mh-access-types
-  '(("anon-ftp")        ; RFC2046 Anonymous File Transfer Protocol
-    ("file")            ; RFC1738 Host-specific file names
-    ("ftp")             ; RFC2046 File Transfer Protocol
-    ("gopher")          ; RFC1738 The Gopher Protocol
-    ("http")            ; RFC1738 Hypertext Transfer Protocol
-    ("local-file")      ; RFC2046 Local file access
-    ("mail-server")     ; RFC2046 mail-server Electronic mail address
-    ("mailto")          ; RFC1738 Electronic mail address
-    ("news")            ; RFC1738 Usenet news
-    ("nntp")            ; RFC1738 Usenet news using NNTP access
-    ("propspero")       ; RFC1738 Prospero Directory Service
-    ("telnet")          ; RFC1738 Telnet
-    ("tftp")            ; RFC2046 Trivial File Transfer Protocol
-    ("url")             ; RFC2017 URL scheme MIME access-type Protocol
-    ("wais"))           ; RFC1738 Wide Area Information Servers
-  "Valid MIME access-type values.")
+This is basically `mml-attach-file' from Gnus, modified such that a prefix
+argument yields an \"inline\" disposition and Content-Type is determined
+automatically."
+  (let* ((file (mml-minibuffer-read-file "Attach file: "))
+         (type (mh-minibuffer-read-type file))
+         (description (mml-minibuffer-read-description))
+         (dispos (or disposition
+                     (mh-mml-minibuffer-read-disposition type))))
+    (mml-insert-empty-tag 'part 'type type 'filename file
+                          'disposition dispos 'description description)))
 
-;;;###mh-autoload
 (defun mh-mh-attach-file (filename type description attributes)
   "Add a tag to insert a MIME message part from a file.
 You are prompted for the FILENAME containing the object, the
@@ -322,6 +1374,32 @@
                                "type=tar; conversions=x-compress"
                                "mode=image"))
 
+;; RFC 2045 - Multipurpose Internet Mail Extensions (MIME) Part One:
+;;            Format of Internet Message Bodies.
+;; RFC 2046 - Multipurpose Internet Mail Extensions (MIME) Part Two:
+;;            Media Types.
+;; RFC 2049 - Multipurpose Internet Mail Extensions (MIME) Part Five:
+;;            Conformance Criteria and Examples.
+;; RFC 2017 - Definition of the URL MIME External-Body Access-Type
+;; RFC 1738 - Uniform Resource Locators (URL)
+(defvar mh-access-types
+  '(("anon-ftp")        ; RFC2046 Anonymous File Transfer Protocol
+    ("file")            ; RFC1738 Host-specific file names
+    ("ftp")             ; RFC2046 File Transfer Protocol
+    ("gopher")          ; RFC1738 The Gopher Protocol
+    ("http")            ; RFC1738 Hypertext Transfer Protocol
+    ("local-file")      ; RFC2046 Local file access
+    ("mail-server")     ; RFC2046 mail-server Electronic mail address
+    ("mailto")          ; RFC1738 Electronic mail address
+    ("news")            ; RFC1738 Usenet news
+    ("nntp")            ; RFC1738 Usenet news using NNTP access
+    ("propspero")       ; RFC1738 Prospero Directory Service
+    ("telnet")          ; RFC1738 Telnet
+    ("tftp")            ; RFC2046 Trivial File Transfer Protocol
+    ("url")             ; RFC2017 URL scheme MIME access-type Protocol
+    ("wais"))           ; RFC1738 Wide Area Information Servers
+  "Valid MIME access-type values.")
+
 ;;;###mh-autoload
 (defun mh-mh-compose-external-type (access-type host filename type
                                                 &optional description
@@ -366,39 +1444,11 @@
        (insert "; " parameters))
   (insert "\n"))
 
-;;;###mh-autoload
-(defun mh-mh-forward-message (&optional description folder messages)
-  "Add tag to forward a message.
-You are prompted for a content DESCRIPTION, the name of the
-FOLDER in which the messages to forward are located, and the
-MESSAGES' numbers.
-
-See also \\[mh-mh-to-mime]."
-  (interactive (list
-                (mml-minibuffer-read-description)
-                (mh-prompt-for-folder "Message from" mh-sent-from-folder nil)
-                (read-string (concat "Messages"
-                                     (if (numberp mh-sent-from-msg)
-                                         (format " (default %d): "
-                                                 mh-sent-from-msg)
-                                       ": ")))))
-  (beginning-of-line)
-  (insert "#forw [")
-  (and description
-       (not (string= description ""))
-       (insert description))
-  (insert "]")
-  (and folder
-       (not (string= folder ""))
-       (insert " " folder))
-  (if (and messages
-           (not (string= messages "")))
-      (let ((start (point)))
-        (insert " " messages)
-        (subst-char-in-region start (point) ?, ? ))
-    (if (numberp mh-sent-from-msg)
-        (insert " " (int-to-string mh-sent-from-msg))))
-  (insert "\n"))
+(defvar mh-mh-to-mime-args nil
+  "Extra arguments for \\[mh-mh-to-mime] to pass to the \"mhbuild\" command.
+The arguments are passed to \"mhbuild\" if \\[mh-mh-to-mime] is
+given a prefix argument. Normally default arguments to
+\"mhbuild\" are specified in the MH profile.")
 
 ;;;###mh-autoload
 (defun mh-mh-to-mime (&optional extra-args)
@@ -485,81 +1535,44 @@
       (insert-file-contents backup-file))
     (after-find-file nil)))
 
+;; Shush compiler.
+(eval-when-compile (defvar mh-identity-pgg-default-user-id))
+
 ;;;###mh-autoload
-(defun mh-mh-directive-present-p (&optional begin end)
-  "Check if the text between BEGIN and END might be a MH-style directive.
-The optional argument BEGIN defaults to the beginning of the
-buffer, while END defaults to the the end of the buffer."
-  (unless begin (setq begin (point-min)))
-  (unless end (setq end (point-max)))
-  (save-excursion
-    (block 'search-for-mh-directive
-      (goto-char begin)
-      (while (re-search-forward "^#" end t)
-        (let ((s (buffer-substring-no-properties (point) (line-end-position))))
-          (cond ((equal s ""))
-                ((string-match "^forw[ \t\n]+" s)
-                 (return-from 'search-for-mh-directive t))
-                (t (let ((first-token (car (split-string s "[ \t;@]"))))
-                     (when (and first-token
-                                (string-match mh-media-type-regexp
-                                              first-token))
-                       (return-from 'search-for-mh-directive t)))))))
-      nil)))
+(defun mh-mml-secure-message-encrypt (method)
+  "Add tag to encrypt the message.
 
-
-
-;;; MIME composition functions
+A proper multipart message is created for you when you send the
+message. Use the command \\[mh-mml-unsecure-message] to remove
+this tag. Use a prefix argument METHOD to be prompted for one of
+the possible security methods (see `mh-mml-method-default')."
+  (interactive (list (mh-mml-query-cryptographic-method)))
+  (mh-secure-message method "encrypt" mh-identity-pgg-default-user-id))
 
 ;;;###mh-autoload
-(defun mh-mml-to-mime ()
-  "Compose MIME message from MML tags.
-
-Typically, you send a message with attachments just like any
-other message. However, you may take a sneak preview of the MIME
-encoding if you wish by running this command.
+(defun mh-mml-secure-message-sign (method)
+  "Add tag to sign the message.
 
-This action can be undone by running \\[undo]."
-  (interactive)
-  (require 'message)
-  (when mh-pgp-support-flag ;; This is only needed for PGP
-    (message-options-set-recipient))
-  (let ((saved-text (buffer-string))
-        (buffer (current-buffer))
-        (modified-flag (buffer-modified-p)))
-    (condition-case err (mml-to-mime)
-      (error
-       (with-current-buffer buffer
-         (delete-region (point-min) (point-max))
-         (insert saved-text)
-         (set-buffer-modified-p modified-flag))
-       (error (error-message-string err))))))
+A proper multipart message is created for you when you send the
+message. Use the command \\[mh-mml-unsecure-message] to remove
+this tag. Use a prefix argument METHOD to be prompted for one of
+the possible security methods (see `mh-mml-method-default')."
+  (interactive (list (mh-mml-query-cryptographic-method)))
+  (mh-secure-message method "sign" mh-identity-pgg-default-user-id))
 
 ;;;###mh-autoload
-(defun mh-mml-forward-message (description folder message)
-  "Forward a message as attachment.
+(defun mh-mml-secure-message-signencrypt (method)
+  "Add tag to encrypt and sign the message.
 
-The function will prompt the user for a DESCRIPTION, a FOLDER and
-MESSAGE number."
-  (let ((msg (if (and (equal message "") (numberp mh-sent-from-msg))
-                 mh-sent-from-msg
-               (string-to-number message))))
-    (cond ((integerp msg)
-           (if (string= "" description)
-               ;; Rationale: mml-attach-file constructs a malformed composition
-               ;; if the description string is empty.  This fixes SF #625168.
-               (mml-attach-file (format "%s%s/%d"
-                                        mh-user-path (substring folder 1) msg)
-                                "message/rfc822")
-             (mml-attach-file (format "%s%s/%d"
-                                      mh-user-path (substring folder 1) msg)
-                              "message/rfc822"
-                              description)))
-          (t (error "The message number, %s, is not a integer" msg)))))
+A proper multipart message is created for you when you send the
+message. Use the command \\[mh-mml-unsecure-message] to remove
+this tag. Use a prefix argument METHOD to be prompted for one of
+the possible security methods (see `mh-mml-method-default')."
+  (interactive (list (mh-mml-query-cryptographic-method)))
+  (mh-secure-message method "signencrypt" mh-identity-pgg-default-user-id))
 
 (defvar mh-mml-cryptographic-method-history ())
 
-;;;###mh-autoload
 (defun mh-mml-query-cryptographic-method ()
   "Read the cryptographic method to use."
   (if current-prefix-arg
@@ -570,28 +1583,6 @@
                          nil t nil 'mh-mml-cryptographic-method-history def))
     mh-mml-method-default))
 
-;;;###mh-autoload
-(defun mh-mml-attach-file (&optional disposition)
-  "Add a tag to insert a MIME message part from a file.
-
-You are prompted for the filename containing the object, the
-media type if it cannot be determined automatically, a content
-description and the DISPOSITION of the attachment.
-
-This is basically `mml-attach-file' from Gnus, modified such that a prefix
-argument yields an \"inline\" disposition and Content-Type is determined
-automatically."
-  (let* ((file (mml-minibuffer-read-file "Attach file: "))
-         (type (mh-minibuffer-read-type file))
-         (description (mml-minibuffer-read-description))
-         (dispos (or disposition
-                     (mml-minibuffer-read-disposition type))))
-    (mml-insert-empty-tag 'part 'type type 'filename file
-                          'disposition dispos 'description description)))
-
-;; Shush compiler.
-(eval-when-compile (defvar mh-identity-pgg-default-user-id))
-
 (defun mh-secure-message (method mode &optional identity)
   "Add tag to encrypt or sign message.
 
@@ -618,6 +1609,30 @@
             (mml-insert-tag 'secure 'method method 'mode mode)))))))
 
 ;;;###mh-autoload
+(defun mh-mml-to-mime ()
+  "Compose MIME message from MML tags.
+
+Typically, you send a message with attachments just like any
+other message. However, you may take a sneak preview of the MIME
+encoding if you wish by running this command.
+
+This action can be undone by running \\[undo]."
+  (interactive)
+  (require 'message)
+  (when mh-pgp-support-flag ;; This is only needed for PGP
+    (message-options-set-recipient))
+  (let ((saved-text (buffer-string))
+        (buffer (current-buffer))
+        (modified-flag (buffer-modified-p)))
+    (condition-case err (mml-to-mime)
+      (error
+       (with-current-buffer buffer
+         (delete-region (point-min) (point-max))
+         (insert saved-text)
+         (set-buffer-modified-p modified-flag))
+       (error (error-message-string err))))))
+
+;;;###mh-autoload
 (defun mh-mml-unsecure-message ()
   "Remove any secure message tags."
   (interactive)
@@ -625,38 +1640,9 @@
       (error "Your version of Gnus does not support PGP/GPG")
     (mml-unsecure-message)))
 
-;;;###mh-autoload
-(defun mh-mml-secure-message-sign (method)
-  "Add tag to sign the message.
-
-A proper multipart message is created for you when you send the
-message. Use the command \\[mh-mml-unsecure-message] to remove
-this tag. Use a prefix argument METHOD to be prompted for one of
-the possible security methods (see `mh-mml-method-default')."
-  (interactive (list (mh-mml-query-cryptographic-method)))
-  (mh-secure-message method "sign" mh-identity-pgg-default-user-id))
-
-;;;###mh-autoload
-(defun mh-mml-secure-message-encrypt (method)
-  "Add tag to encrypt the message.
+
 
-A proper multipart message is created for you when you send the
-message. Use the command \\[mh-mml-unsecure-message] to remove
-this tag. Use a prefix argument METHOD to be prompted for one of
-the possible security methods (see `mh-mml-method-default')."
-  (interactive (list (mh-mml-query-cryptographic-method)))
-  (mh-secure-message method "encrypt" mh-identity-pgg-default-user-id))
-
-;;;###mh-autoload
-(defun mh-mml-secure-message-signencrypt (method)
-  "Add tag to encrypt and sign the message.
-
-A proper multipart message is created for you when you send the
-message. Use the command \\[mh-mml-unsecure-message] to remove
-this tag. Use a prefix argument METHOD to be prompted for one of
-the possible security methods (see `mh-mml-method-default')."
-  (interactive (list (mh-mml-query-cryptographic-method)))
-  (mh-secure-message method "signencrypt" mh-identity-pgg-default-user-id))
+;;; Support Routines for MH-Letter Commands
 
 ;;;###mh-autoload
 (defun mh-mml-tag-present-p ()
@@ -669,9 +1655,127 @@
       "^<#secure.+>$\\)")
      nil t)))
 
+(defvar mh-media-type-regexp
+  (concat (regexp-opt '("text" "image" "audio" "video" "application"
+                        "multipart" "message") t)
+          "/[-.+a-zA-Z0-9]+")
+  "Regexp matching valid media types used in MIME attachment compositions.")
+
+;;;###mh-autoload
+(defun mh-mh-directive-present-p (&optional begin end)
+  "Check if the text between BEGIN and END might be a MH-style directive.
+The optional argument BEGIN defaults to the beginning of the
+buffer, while END defaults to the the end of the buffer."
+  (unless begin (setq begin (point-min)))
+  (unless end (setq end (point-max)))
+  (save-excursion
+    (block 'search-for-mh-directive
+      (goto-char begin)
+      (while (re-search-forward "^#" end t)
+        (let ((s (buffer-substring-no-properties (point) (line-end-position))))
+          (cond ((equal s ""))
+                ((string-match "^forw[ \t\n]+" s)
+                 (return-from 'search-for-mh-directive t))
+                (t (let ((first-token (car (split-string s "[ \t;@]"))))
+                     (when (and first-token
+                                (string-match mh-media-type-regexp
+                                              first-token))
+                       (return-from 'search-for-mh-directive t)))))))
+      nil)))
+
+(defun mh-minibuffer-read-type (filename &optional default)
+  "Return the content type associated with the given FILENAME.
+If the \"file\" command exists and recognizes the given file,
+then its value is returned\; otherwise, the user is prompted for
+a type (see `mailcap-mime-types' and for Emacs 20,
+`mh-mime-content-types').
+Optional argument DEFAULT is returned if a type isn't entered."
+  (mailcap-parse-mimetypes)
+  (let* ((default (or default
+                      (mm-default-file-encoding filename)
+                      "application/octet-stream"))
+         (probed-type (mh-file-mime-type filename))
+         (type (or (and (not (equal probed-type "application/octet-stream"))
+                        probed-type)
+                   (completing-read
+                    (format "Content type (default %s): " default)
+                    (mapcar 'list (mailcap-mime-types))))))
+    (if (not (equal type ""))
+        type
+      default)))
+
+;;;###mh-autoload
+(defun mh-file-mime-type (filename)
+  "Return MIME type of FILENAME from file command.
+Returns nil if file command not on system."
+  (cond
+   ((not (mh-have-file-command))
+    nil)                                ;no file command, exit now
+   ((not (and (file-exists-p filename)
+              (file-readable-p filename)))
+    nil)                               ;no file or not readable, ditto
+   (t
+    (save-excursion
+      (let ((tmp-buffer (get-buffer-create mh-temp-buffer)))
+        (set-buffer tmp-buffer)
+        (unwind-protect
+            (progn
+              (call-process "file" nil '(t nil) nil "-b" "-i"
+                            (expand-file-name filename))
+              (goto-char (point-min))
+              (if (not (re-search-forward mh-media-type-regexp nil t))
+                  nil
+                (mh-file-mime-type-substitute (match-string 0) filename)))
+          (kill-buffer tmp-buffer)))))))
+
+(defvar mh-file-mime-type-substitutions
+  '(("application/msword" "\.xls" "application/ms-excel")
+    ("application/msword" "\.ppt" "application/ms-powerpoint")
+    ("text/plain" "\.vcf" "text/x-vcard"))
+  "Substitutions to make for Content-Type returned from file command.
+The first element is the Content-Type returned by the file command.
+The second element is a regexp matching the file name, usually the
+extension.
+The third element is the Content-Type to replace with.")
+
+(defun mh-file-mime-type-substitute (content-type filename)
+  "Return possibly changed CONTENT-TYPE on the FILENAME.
+Substitutions are made from the `mh-file-mime-type-substitutions'
+variable."
+  (let ((subst mh-file-mime-type-substitutions)
+        (type) (match) (answer content-type)
+        (case-fold-search t))
+    (while subst
+      (setq type (car (car subst))
+            match (elt (car subst) 1))
+      (if (and (string-equal content-type type)
+               (string-match match filename))
+          (setq answer (elt (car subst) 2)
+                subst nil)
+        (setq subst (cdr subst))))
+    answer))
+
+(defvar mh-have-file-command 'undefined
+  "Cached value of function `mh-have-file-command'.
+Do not reference this variable directly as it might not have been
+initialized. Always use the command `mh-have-file-command'.")
+
+;;;###mh-autoload
+(defun mh-have-file-command ()
+  "Return t if 'file' command is on the system.
+'file -i' is used to get MIME type of composition insertion."
+  (when (eq mh-have-file-command 'undefined)
+    (setq mh-have-file-command
+          (and (fboundp 'executable-find)
+               (executable-find "file") ; file command exists
+                                        ;   and accepts -i and -b args.
+               (zerop (call-process "file" nil nil nil "-i" "-b"
+                                    (expand-file-name "inc" mh-progs))))))
+  mh-have-file-command)
+
 
 
-;;; MIME cleanup
+;;; MIME Cleanup
 
 ;;;###mh-autoload
 (defun mh-mime-cleanup ()
@@ -680,7 +1784,7 @@
     ;; This is for Emacs, what about XEmacs?
     (mh-funcall-if-exists remove-images (point-min) (point-max))
     (when mime-data
-      (mm-destroy-parts (mh-mime-handles mime-data))
+      (mh-mm-destroy-parts (mh-mime-handles mime-data))
       (remhash (current-buffer) mh-globals-hash))))
 
 ;;;###mh-autoload
@@ -688,838 +1792,9 @@
   "Free MIME data for externally displayed MIME parts."
   (let ((mime-data (mh-buffer-data)))
     (when mime-data
-      (mm-destroy-parts (mh-mime-handles mime-data)))
+      (mh-mm-destroy-parts (mh-mime-handles mime-data)))
     (remhash (current-buffer) mh-globals-hash)))
 
-(defun mh-handle-set-external-undisplayer (folder handle function)
-  "Replacement for `mm-handle-set-external-undisplayer'.
-
-This is only called in recent versions of Gnus. The MIME handles
-are stored in data structures corresponding to MH-E folder buffer
-FOLDER instead of in Gnus (as in the original). The MIME part,
-HANDLE is associated with the undisplayer FUNCTION."
-  (if (mm-keep-viewer-alive-p handle)
-      (let ((new-handle (copy-sequence handle)))
-        (mm-handle-set-undisplayer new-handle function)
-        (mm-handle-set-undisplayer handle nil)
-        (save-excursion
-          (set-buffer folder)
-          (push new-handle (mh-mime-handles (mh-buffer-data)))))
-    (mm-handle-set-undisplayer handle function)))
-
-
-
-;;; MIME transformations
-(eval-when-compile (require 'font-lock))
-
-;;;###mh-autoload
-(defun mh-add-missing-mime-version-header ()
-  "Some mail programs don't put a MIME-Version header.
-I have seen this only in spam, so maybe we shouldn't fix
-this ;-)"
-  (save-excursion
-    (goto-char (point-min))
-    (re-search-forward "\n\n" nil t)
-    (save-restriction
-      (narrow-to-region (point-min) (point))
-      (when (and (message-fetch-field "content-type")
-                 (not (message-fetch-field "mime-version")))
-        (goto-char (point-min))
-        (insert "MIME-Version: 1.0\n")))))
-
-(defun mh-small-show-buffer-p ()
-  "Check if show buffer is small.
-This is used to decide if smileys and graphical emphasis will be
-displayed."
-  (let ((max nil))
-    (when (and (boundp 'font-lock-maximum-size) font-lock-maximum-size)
-      (cond ((numberp font-lock-maximum-size)
-             (setq max font-lock-maximum-size))
-            ((listp font-lock-maximum-size)
-             (setq max (cdr (or (assoc 'mh-show-mode font-lock-maximum-size)
-                                (assoc t font-lock-maximum-size)))))))
-    (or (not (numberp max)) (>= (/ max 8) (buffer-size)))))
-
-;;;###mh-autoload
-(defun mh-display-smileys ()
-  "Display smileys."
-  (when (and mh-graphical-smileys-flag (mh-small-show-buffer-p))
-    (mh-funcall-if-exists smiley-region (point-min) (point-max))))
-
-;;;###mh-autoload
-(defun mh-display-emphasis ()
-  "Display graphical emphasis."
-  (when (and mh-graphical-emphasis-flag (mh-small-show-buffer-p))
-    (flet ((article-goto-body ()))      ; shadow this function to do nothing
-      (save-excursion
-        (goto-char (point-min))
-        (article-emphasize)))))
-
-;; Copied from gnus-art.el (should be checked for other cool things that can
-;; be added to the buttons)
-(defvar mh-mime-button-commands
-  '((mh-press-button "\r" "Toggle Display")))
-(defvar mh-mime-button-map
-  (let ((map (make-sparse-keymap)))
-    (unless (>= (string-to-number emacs-version) 21)
-      ;; XEmacs doesn't care.
-      (set-keymap-parent map mh-show-mode-map))
-    (mh-do-in-gnu-emacs
-     (define-key map [mouse-2] 'mh-push-button))
-    (mh-do-in-xemacs
-     (define-key map '(button2) 'mh-push-button))
-    (dolist (c mh-mime-button-commands)
-      (define-key map (cadr c) (car c)))
-    map))
-(defvar mh-mime-button-line-format-alist
-  '((?T long-type ?s)
-    (?d description ?s)
-    (?p index ?s)
-    (?e dots ?s)))
-(defvar mh-mime-button-line-format "%{%([%p. %d%T]%)%}%e\n")
-(defvar mh-mime-security-button-pressed nil)
-(defvar mh-mime-security-button-line-format "%{%([[%t:%i]%D]%)%}\n")
-(defvar mh-mime-security-button-end-line-format "%{%([[End of %t]%D]%)%}\n")
-(defvar mh-mime-security-button-line-format-alist
-  '((?t type ?s)
-    (?i info ?s)
-    (?d details ?s)
-    (?D pressed-details ?s)))
-(defvar mh-mime-security-button-map
-  (let ((map (make-sparse-keymap)))
-    (unless (>= (string-to-number emacs-version) 21)
-      (set-keymap-parent map mh-show-mode-map))
-    (define-key map "\r" 'mh-press-button)
-    (mh-do-in-gnu-emacs
-     (define-key map [mouse-2] 'mh-push-button))
-    (mh-do-in-xemacs
-     (define-key map '(button2) 'mh-push-button))
-    map))
-
-(defvar mh-mime-save-parts-directory nil
-  "Default to use for `mh-mime-save-parts-default-directory'.
-Set from last use.")
-
-;;;###mh-autoload
-(defun mh-mime-save-parts (prompt)
-  "Save attachments.
-
-You can save all of the attachments at once with this command.
-The attachments are saved in the directory specified by the
-option `mh-mime-save-parts-default-directory' unless you use a
-prefix argument PROMPT in which case you are prompted for the
-directory. These directories may be superseded by MH profile
-components, since this function calls on \"mhstore\" (\"mhn\") to
-do the work."
-  (interactive "P")
-  (let ((msg (if (eq major-mode 'mh-show-mode)
-                 (mh-show-buffer-message-number)
-               (mh-get-msg-num t)))
-        (folder (if (eq major-mode 'mh-show-mode)
-                    mh-show-folder-buffer
-                  mh-current-folder))
-        (command (if (mh-variant-p 'nmh) "mhstore" "mhn"))
-        (directory
-         (cond
-          ((and (or prompt
-                    (equal nil mh-mime-save-parts-default-directory)
-                    (equal t mh-mime-save-parts-default-directory))
-                (not mh-mime-save-parts-directory))
-           (read-file-name "Store in directory: " nil nil t nil))
-          ((and (or prompt
-                    (equal t mh-mime-save-parts-default-directory))
-                mh-mime-save-parts-directory)
-           (read-file-name (format
-                            "Store in directory (default %s): "
-                            mh-mime-save-parts-directory)
-                           "" mh-mime-save-parts-directory t ""))
-          ((stringp mh-mime-save-parts-default-directory)
-           mh-mime-save-parts-default-directory)
-          (t
-           mh-mime-save-parts-directory))))
-    (if (and (equal directory "") mh-mime-save-parts-directory)
-        (setq directory mh-mime-save-parts-directory))
-    (if (not (file-directory-p directory))
-        (message "No directory specified")
-      (if (equal nil mh-mime-save-parts-default-directory)
-          (setq mh-mime-save-parts-directory directory))
-      (save-excursion
-        (set-buffer (get-buffer-create mh-log-buffer))
-        (cd directory)
-        (setq mh-mime-save-parts-directory directory)
-        (let ((initial-size (mh-truncate-log-buffer)))
-          (apply 'call-process
-                 (expand-file-name command mh-progs) nil t nil
-                 (mh-list-to-string (list folder msg "-auto")))
-          (if (> (buffer-size) initial-size)
-              (save-window-excursion
-                (switch-to-buffer-other-window mh-log-buffer)
-                (sit-for 3))))))))
-
-;; Avoid errors if gnus-sum isn't loaded yet...
-(defvar gnus-newsgroup-charset nil)
-(defvar gnus-newsgroup-name nil)
-
-(defun mh-decode-message-body ()
-  "Decode message based on charset.
-If message has been encoded for transfer take that into account."
-  (let (ct charset cte)
-    (goto-char (point-min))
-    (re-search-forward "\n\n" nil t)
-    (save-restriction
-      (narrow-to-region (point-min) (point))
-      (setq ct (ignore-errors (mail-header-parse-content-type
-                               (message-fetch-field "Content-Type" t)))
-            charset (mail-content-type-get ct 'charset)
-            cte (message-fetch-field "Content-Transfer-Encoding")))
-    (when (stringp cte) (setq cte (mail-header-strip cte)))
-    (when (or (not ct) (equal (car ct) "text/plain"))
-      (save-restriction
-        (narrow-to-region (min (1+ (mh-mail-header-end)) (point-max))
-                          (point-max))
-        (mm-decode-body charset
-                        (and cte (intern (downcase
-                                          (gnus-strip-whitespace cte))))
-                        (car ct))))))
-
-;;;###mh-autoload
-(defun mh-toggle-mh-decode-mime-flag ()
-  "Toggle the value of `mh-decode-mime-flag'."
-  (interactive)
-  (setq mh-decode-mime-flag (not mh-decode-mime-flag))
-  (mh-show nil t)
-  (message "%s" (if mh-decode-mime-flag
-                    "Processing attachments normally"
-                  "Displaying raw message")))
-
-;;;###mh-autoload
-(defun mh-decode-message-header ()
-  "Decode RFC2047 encoded message header fields."
-  (when mh-decode-mime-flag
-    (let ((buffer-read-only nil))
-      (rfc2047-decode-region (point-min) (mh-mail-header-end)))))
-
-;;;###mh-autoload
-(defun mh-mime-display (&optional pre-dissected-handles)
-  "Display (and possibly decode) MIME handles.
-Optional argument, PRE-DISSECTED-HANDLES is a list of MIME
-handles. If present they are displayed otherwise the buffer is
-parsed and then displayed."
-  (let ((handles ())
-        (folder mh-show-folder-buffer)
-        (raw-message-data (buffer-string)))
-    (flet ((mm-handle-set-external-undisplayer
-            (handle function)
-            (mh-handle-set-external-undisplayer folder handle function)))
-      (goto-char (point-min))
-      (unless (search-forward "\n\n" nil t)
-        (goto-char (point-max))
-        (insert "\n\n"))
-
-      (condition-case err
-          (progn
-            ;; If needed dissect the current buffer
-            (if pre-dissected-handles
-                (setq handles pre-dissected-handles)
-              (if (setq handles (mm-dissect-buffer nil))
-                  (when (fboundp 'mm-uu-dissect-text-parts)
-                    (mm-uu-dissect-text-parts handles))
-                (setq handles (mm-uu-dissect)))
-              (setf (mh-mime-handles (mh-buffer-data))
-                    (mm-merge-handles handles
-                                      (mh-mime-handles (mh-buffer-data))))
-              (unless handles (mh-decode-message-body)))
-
-            (cond ((and handles
-                        (or (not (stringp (car handles))) (cdr handles)))
-                   ;; Goto start of message body
-                   (goto-char (point-min))
-                   (or (search-forward "\n\n" nil t) (goto-char (point-max)))
-
-                   ;; Delete the body
-                   (delete-region (point) (point-max))
-
-                   ;; Display the MIME handles
-                   (mh-mime-display-part handles))
-                  (t (mh-signature-highlight))))
-        (error
-         (message "Could not display body: %s" (error-message-string err))
-         (delete-region (point-min) (point-max))
-         (insert raw-message-data))))))
-
-(defun mh-mime-display-part (handle)
-  "Decides the viewer to call based on the type of HANDLE."
-  (cond ((null handle) nil)
-        ((not (stringp (car handle)))
-         (mh-mime-display-single handle))
-        ((equal (car handle) "multipart/alternative")
-         (mh-mime-display-alternative (cdr handle)))
-        ((and mh-pgp-support-flag
-              (or (equal (car handle) "multipart/signed")
-                  (equal (car handle) "multipart/encrypted")))
-         (mh-mime-display-security handle))
-        (t (mh-mime-display-mixed (cdr handle)))))
-
-(defun mh-mime-display-alternative (handles)
-  "Choose among the alternatives, HANDLES the part that will be displayed.
-If no part is preferred then all the parts are displayed."
-  (let* ((preferred (mm-preferred-alternative handles))
-         (others (loop for x in handles unless (eq x preferred) collect x)))
-    (cond ((and preferred (stringp (car preferred)))
-           (mh-mime-display-part preferred)
-           (mh-mime-maybe-display-alternatives others))
-          (preferred
-           (save-restriction
-             (narrow-to-region (point) (if (eobp) (point) (1+ (point))))
-             (mh-mime-display-single preferred)
-             (mh-mime-maybe-display-alternatives others)
-             (goto-char (point-max))))
-          (t (mh-mime-display-mixed handles)))))
-
-(defun mh-mime-maybe-display-alternatives (alternatives)
-  "Show buttons for ALTERNATIVES.
-If `mh-mime-display-alternatives-flag' is non-nil then display
-buttons for alternative parts that are usually suppressed."
-  (when (and mh-display-buttons-for-alternatives-flag alternatives)
-    (insert "\n----------------------------------------------------\n")
-    (insert "Alternatives:\n")
-    (dolist (x alternatives)
-      (insert "\n")
-      (mh-insert-mime-button x (mh-mime-part-index x) nil))
-    (insert "\n----------------------------------------------------\n")))
-
-(defun mh-mime-display-mixed (handles)
-  "Display the list of MIME parts, HANDLES recursively."
-  (mapcar #'mh-mime-display-part handles))
-
-(defun mh-mime-part-index (handle)
-  "Generate the button number for MIME part, HANDLE.
-Notice that a hash table is used to display the same number when
-buttons need to be displayed multiple times (for instance when
-nested messages are opened)."
-  (or (gethash handle (mh-mime-part-index-hash (mh-buffer-data)))
-      (setf (gethash handle (mh-mime-part-index-hash (mh-buffer-data)))
-            (incf (mh-mime-parts-count (mh-buffer-data))))))
-
-(defun mh-small-image-p (handle)
-  "Decide whether HANDLE is a \"small\" image that can be displayed inline.
-This is only useful if a Content-Disposition header is not present."
-  (let ((media-test (caddr (assoc (car (mm-handle-type handle))
-                                  mh-mm-inline-media-tests)))
-        (mm-inline-large-images t))
-    (and media-test
-         (equal (mm-handle-media-supertype handle) "image")
-         (funcall media-test handle)    ; Since mm-inline-large-images is T,
-                                        ; this only tells us if the image is
-                                        ; something that emacs can display
-         (let* ((image (mm-get-image handle)))
-           (or (mh-do-in-xemacs
-                 (and (mh-funcall-if-exists glyphp image)
-                      (< (glyph-width image)
-                         (or mh-max-inline-image-width (window-pixel-width)))
-                      (< (glyph-height image)
-                         (or mh-max-inline-image-height
-                             (window-pixel-height)))))
-               (mh-do-in-gnu-emacs
-                 (let ((size (mh-funcall-if-exists image-size image)))
-                   (and size
-                        (< (cdr size) (or mh-max-inline-image-height
-                                          (1- (window-height))))
-                        (< (car size) (or mh-max-inline-image-width
-                                          (window-width)))))))))))
-
-(defun mh-inline-vcard-p (handle)
-  "Decide if HANDLE is a vcard that must be displayed inline."
-  (let ((type (mm-handle-type handle)))
-    (and (or (featurep 'vcard) (fboundp 'vcard-pretty-print))
-         (consp type)
-         (equal (car type) "text/x-vcard")
-         (save-excursion
-           (save-restriction
-             (widen)
-             (goto-char (point-min))
-             (not (mh-signature-separator-p)))))))
-
-(defun mh-mime-display-single (handle)
-  "Display a leaf node, HANDLE in the MIME tree."
-  (let* ((type (mm-handle-media-type handle))
-         (small-image-flag (mh-small-image-p handle))
-         (attachmentp (equal (car (mm-handle-disposition handle))
-                             "attachment"))
-         (inlinep (and (equal (car (mm-handle-disposition handle)) "inline")
-                       (mm-inlinable-p handle)
-                       (mm-inlined-p handle)))
-         (displayp (or inlinep                   ; show if inline OR
-                       (mh-inline-vcard-p handle);      inline vcard OR
-                       (and (not attachmentp)    ;      if not an attachment
-                            (or small-image-flag ;        and small image
-                                                 ;        and user wants inline
-                                (and (not (equal
-                                           (mm-handle-media-supertype handle)
-                                           "image"))
-                                     (mm-inlinable-p handle)
-                                     (mm-inlined-p handle)))))))
-    (save-restriction
-      (narrow-to-region (point) (if (eobp) (point) (1+ (point))))
-      (cond ((and mh-pgp-support-flag
-                  (equal type "application/pgp-signature"))
-             nil)             ; skip signatures as they are already handled...
-            ((not displayp)
-             (insert "\n")
-             (mh-insert-mime-button handle (mh-mime-part-index handle) nil))
-            ((and displayp (not mh-display-buttons-for-inline-parts-flag))
-             (or (mm-display-part handle) (mm-display-part handle))
-             (mh-signature-highlight handle))
-            ((and displayp mh-display-buttons-for-inline-parts-flag)
-             (insert "\n")
-             (mh-insert-mime-button handle (mh-mime-part-index handle) nil)
-             (forward-line -1)
-             (mh-mm-display-part handle)))
-      (goto-char (point-max)))))
-
-(defun mh-signature-highlight (&optional handle)
-  "Highlight message signature in HANDLE.
-The optional argument, HANDLE is a MIME handle if the function is
-being used to highlight the signature in a MIME part."
-  (let ((regexp
-         (cond ((not handle) "^-- $")
-               ((not (and (equal (mm-handle-media-supertype handle) "text")
-                          (equal (mm-handle-media-subtype handle) "html")))
-                "^-- $")
-               ((eq (mh-mm-text-html-renderer) 'lynx) "^   --$")
-               (t "^--$"))))
-    (save-excursion
-      (goto-char (point-max))
-      (when (re-search-backward regexp nil t)
-        (mh-do-in-gnu-emacs
-          (let ((ov (make-overlay (point) (point-max))))
-            (overlay-put ov 'face 'mh-show-signature)
-            (overlay-put ov 'evaporate t)))
-        (mh-do-in-xemacs
-          (set-extent-property (make-extent (point) (point-max))
-                               'face 'mh-show-signature))))))
-
-(mh-do-in-xemacs
- (defvar dots)
- (defvar type))
-
-(defun mh-insert-mime-button (handle index displayed)
-  "Insert MIME button for HANDLE.
-INDEX is the part number that will be DISPLAYED. It is also used
-by commands like \"K v\" which operate on individual MIME parts."
-  ;; The button could be displayed by a previous decode. In that case
-  ;; undisplay it if we need a hidden button.
-  (when (and (mm-handle-displayed-p handle) (not displayed))
-    (mm-display-part handle))
-  (let ((name (or (mail-content-type-get (mm-handle-type handle) 'name)
-                  (mail-content-type-get (mm-handle-disposition handle)
-                                         'filename)
-                  (mail-content-type-get (mm-handle-type handle) 'url)
-                  ""))
-        (type (mm-handle-media-type handle))
-        (description (mail-decode-encoded-word-string
-                      (or (mm-handle-description handle) "")))
-        (dots (if (or displayed (mm-handle-displayed-p handle)) "   " "..."))
-        long-type begin end)
-    (if (string-match ".*/" name) (setq name (substring name (match-end 0))))
-    (setq long-type (concat type (and (not (equal name ""))
-                                      (concat "; " name))))
-    (unless (equal description "")
-      (setq long-type (concat " --- " long-type)))
-    (unless (bolp) (insert "\n"))
-    (setq begin (point))
-    (gnus-eval-format
-     mh-mime-button-line-format mh-mime-button-line-format-alist
-     `(,@(gnus-local-map-property mh-mime-button-map)
-         mh-callback mh-mm-display-part
-         mh-part ,index
-         mh-data ,handle))
-    (setq end (point))
-    (widget-convert-button
-     'link begin end
-     :mime-handle handle
-     :action 'mh-widget-press-button
-     :button-keymap mh-mime-button-map
-     :help-echo
-     "Mouse-2 click or press RET (in show buffer) to toggle display")
-    (dolist (ov (mh-funcall-if-exists overlays-in begin end))
-      (mh-funcall-if-exists overlay-put ov 'evaporate t))))
-
-;; There is a bug in Gnus inline image display due to which an extra line
-;; gets inserted every time it is viewed. To work around that problem we are
-;; using an extra property 'mh-region to remember the region that is added
-;; when the button is clicked. The region is then deleted to make sure that
-;; no extra lines get inserted.
-(defun mh-mm-display-part (handle)
-  "Toggle display of button for MIME part, HANDLE."
-  (beginning-of-line)
-  (let ((id (get-text-property (point) 'mh-part))
-        (point (point))
-        (window (selected-window))
-        (mail-parse-charset 'nil)
-        (mail-parse-ignored-charsets nil)
-        region buffer-read-only)
-    (save-excursion
-      (unwind-protect
-          (let ((win (get-buffer-window (current-buffer) t)))
-            (when win
-              (select-window win))
-            (goto-char point)
-
-            (if (mm-handle-displayed-p handle)
-                ;; This will remove the part.
-                (progn
-                  ;; Delete the button and displayed part (if any)
-                  (let ((region (get-text-property point 'mh-region)))
-                    (when region
-                      (mh-funcall-if-exists
-                       remove-images (car region) (cdr region)))
-                    (mm-display-part handle)
-                    (when region
-                      (delete-region (car region) (cdr region))))
-                  ;; Delete button (if it still remains). This happens for
-                  ;; externally displayed parts where the previous step does
-                  ;; nothing.
-                  (unless (eolp)
-                    (delete-region (point) (progn (forward-line) (point)))))
-              (save-restriction
-                (delete-region (point) (progn (forward-line 1) (point)))
-                (narrow-to-region (point) (point))
-                ;; Maybe we need another unwind-protect here.
-                (when (equal (mm-handle-media-supertype handle) "image")
-                  (insert "\n"))
-                (when (and (not (eq (ignore-errors (mm-display-part handle))
-                                    'inline))
-                           (equal (mm-handle-media-supertype handle)
-                                  "image"))
-                  (goto-char (point-min))
-                  (delete-char 1))
-                (when (equal (mm-handle-media-supertype handle) "text")
-                  (when (eq mh-highlight-citation-style 'gnus)
-                    (mh-gnus-article-highlight-citation))
-                  (mh-display-smileys)
-                  (mh-display-emphasis)
-                  (mh-signature-highlight handle))
-                (setq region (cons (progn (goto-char (point-min))
-                                          (point-marker))
-                                   (progn (goto-char (point-max))
-                                          (point-marker)))))))
-        (when (window-live-p window)
-          (select-window window))
-        (goto-char point)
-        (beginning-of-line)
-        (mh-insert-mime-button handle id (mm-handle-displayed-p handle))
-        (goto-char point)
-        (when region
-          (add-text-properties (line-beginning-position) (line-end-position)
-                               `(mh-region ,region)))))))
-
-;;;###mh-autoload
-(defun mh-press-button ()
-  "View contents of button.
-
-This command is a toggle so if you use it again on the same
-attachment, the attachment is hidden."
-  (interactive)
-  (let ((mm-inline-media-tests mh-mm-inline-media-tests)
-        (data (get-text-property (point) 'mh-data))
-        (function (get-text-property (point) 'mh-callback))
-        (buffer-read-only nil)
-        (folder mh-show-folder-buffer))
-    (flet ((mm-handle-set-external-undisplayer
-            (handle function)
-            (mh-handle-set-external-undisplayer folder handle function)))
-      (when (and function (eolp))
-        (backward-char))
-      (unwind-protect (and function (funcall function data))
-        (set-buffer-modified-p nil)))))
-
-;;;###mh-autoload
-(defun mh-push-button (event)
-  "Click MIME button for EVENT.
-
-If the MIME part is visible then it is removed. Otherwise the
-part is displayed. This function is called when the mouse is used
-to click the MIME button."
-  (interactive "e")
-  (mh-do-at-event-location event
-    (let ((folder mh-show-folder-buffer)
-          (mm-inline-media-tests mh-mm-inline-media-tests)
-          (data (get-text-property (point) 'mh-data))
-          (function (get-text-property (point) 'mh-callback)))
-      (flet ((mm-handle-set-external-undisplayer (handle func)
-               (mh-handle-set-external-undisplayer folder handle func)))
-        (and function (funcall function data))))))
-
-;;;###mh-autoload
-(defun mh-mime-save-part ()
-  "Save MIME part at point."
-  (interactive)
-  (let ((data (get-text-property (point) 'mh-data)))
-    (when data
-      (let ((mm-default-directory
-             (file-name-as-directory (or mh-mime-save-parts-directory
-                                         default-directory))))
-        (mh-mm-save-part data)
-        (setq mh-mime-save-parts-directory mm-default-directory)))))
-
-;;;###mh-autoload
-(defun mh-mime-inline-part ()
-  "Toggle display of the raw MIME part."
-  (interactive)
-  (let* ((buffer-read-only nil)
-         (data (get-text-property (point) 'mh-data))
-         (inserted-flag (get-text-property (point) 'mh-mime-inserted))
-         (displayed-flag (mm-handle-displayed-p data))
-         (point (point))
-         start end)
-    (cond ((and data (not inserted-flag) (not displayed-flag))
-           (let ((contents (mm-get-part data)))
-             (add-text-properties (line-beginning-position) (line-end-position)
-                                  '(mh-mime-inserted t))
-             (setq start (point-marker))
-             (forward-line 1)
-             (mm-insert-inline data contents)
-             (setq end (point-marker))
-             (add-text-properties
-              start (progn (goto-char start) (line-end-position))
-              `(mh-region (,start . ,end)))))
-          ((and data (or inserted-flag displayed-flag))
-           (mh-press-button)
-           (message "MIME part already inserted")))
-    (goto-char point)
-    (set-buffer-modified-p nil)))
-
-;;;###mh-autoload
-(defun mh-display-with-external-viewer (part-index)
-  "View attachment externally.
-
-If Emacs does not know how to view an attachment, you could save
-it into a file and then run some program to open it. It is
-easier, however, to launch the program directly from MH-E with
-this command. While you'll most likely use this to view
-spreadsheets and documents, it is also useful to use your browser
-to view HTML attachments with higher fidelity than what Emacs can
-provide.
-
-This command displays the attachment associated with the button
-under the cursor. If the cursor is not located over a button,
-then the cursor first moves to the next button, wrapping to the
-beginning of the message if necessary. You can provide a numeric
-prefix argument PART-INDEX to view the attachment labeled with
-that number.
-
-This command tries to provide a reasonable default for the viewer
-by calling the Emacs function `mailcap-mime-info'. This function
-usually reads the file \"/etc/mailcap\"."
-  (interactive "P")
-  (when (consp part-index) (setq part-index (car part-index)))
-  (mh-folder-mime-action
-   part-index
-   #'(lambda ()
-       (let* ((part (get-text-property (point) 'mh-data))
-              (type (mm-handle-media-type part))
-              (methods (mapcar (lambda (x) (list (cdr (assoc 'viewer x))))
-                               (mailcap-mime-info type 'all)))
-              (def (caar methods))
-              (prompt (format "Viewer%s: " (if def
-                                               (format " (default %s)" def)
-                                             "")))
-              (method (completing-read prompt methods nil nil nil nil def))
-              (folder mh-show-folder-buffer)
-              (buffer-read-only nil))
-         (when (string-match "^[^% \t]+$" method)
-           (setq method (concat method " %s")))
-         (flet ((mm-handle-set-external-undisplayer (handle function)
-                  (mh-handle-set-external-undisplayer folder handle function)))
-           (unwind-protect (mm-display-external part method)
-             (set-buffer-modified-p nil)))))
-   nil))
-
-(defun mh-widget-press-button (widget el)
-  "Callback for widget, WIDGET.
-Parameter EL is unused."
-  (goto-char (widget-get widget :from))
-  (mh-press-button))
-
-(defun mh-mime-display-security (handle)
-  "Display PGP encrypted/signed message, HANDLE."
-  (save-restriction
-    (narrow-to-region (point) (point))
-    (insert "\n")
-    (mh-insert-mime-security-button handle)
-    (mh-mime-display-mixed (cdr handle))
-    (insert "\n")
-    (let ((mh-mime-security-button-line-format
-           mh-mime-security-button-end-line-format))
-      (mh-insert-mime-security-button handle))
-    (mm-set-handle-multipart-parameter
-     handle 'mh-region (cons (point-min-marker) (point-max-marker)))))
-
-;; I rewrote the security part because Gnus doesn't seem to ever minimize
-;; the button. That is once the mime-security button is pressed there seems
-;; to be no way of getting rid of the inserted text.
-(defun mh-mime-security-show-details (handle)
-  "Toggle display of detailed security info for HANDLE."
-  (let ((details (mm-handle-multipart-ctl-parameter handle 'gnus-details)))
-    (when details
-      (let ((mh-mime-security-button-pressed
-             (not (get-text-property (point) 'mh-button-pressed)))
-            (mh-mime-security-button-line-format
-             (get-text-property (point) 'mh-line-format)))
-        (forward-char -1)
-        (while (eq (get-text-property (point) 'mh-line-format)
-                   mh-mime-security-button-line-format)
-          (forward-char -1))
-        (forward-char)
-        (save-restriction
-          (narrow-to-region (point) (point))
-          (mh-insert-mime-security-button handle))
-        (delete-region
-         (point)
-         (or (text-property-not-all
-              (point) (point-max)
-              'mh-line-format mh-mime-security-button-line-format)
-             (point-max)))
-        (forward-line -1)))))
-
-(defun mh-mime-security-button-face (info)
-  "Return the button face to use for encrypted/signed mail based on INFO."
-  (cond ((string-match "OK" info)       ;Decrypted mail
-         'mh-show-pgg-good)
-        ((string-match "Failed" info)   ;Decryption failed or signature invalid
-         'mh-show-pgg-bad)
-        ((string-match "Undecided" info);Unprocessed mail
-         'mh-show-pgg-unknown)
-        ((string-match "Untrusted" info);Key not trusted
-         'mh-show-pgg-unknown)
-        (t
-         'mh-show-pgg-good)))
-
-(defun mh-mime-security-press-button (handle)
-  "Callback from security button for part HANDLE."
-  (if (mm-handle-multipart-ctl-parameter handle 'gnus-info)
-      (mh-mime-security-show-details handle)
-    (let ((region (mm-handle-multipart-ctl-parameter handle 'mh-region))
-          point)
-      (setq point (point))
-      (goto-char (car region))
-      (delete-region (car region) (cdr region))
-      (with-current-buffer (mm-handle-multipart-ctl-parameter handle 'buffer)
-        (let* ((mm-verify-option 'known)
-               (mm-decrypt-option 'known)
-               (new (mm-possibly-verify-or-decrypt (cdr handle) handle)))
-          (unless (eq new (cdr handle))
-            (mm-destroy-parts (cdr handle))
-            (setcdr handle new))))
-      (mh-mime-display-security handle)
-      (goto-char point))))
-
-;; Shush compiler.
-(eval-when-compile
-  (defvar mm-verify-function-alist nil)
-  (defvar mm-decrypt-function-alist nil))
-
-(defvar pressed-details)
-
-(defun mh-insert-mime-security-button (handle)
-  "Display buttons for PGP message, HANDLE."
-  (let* ((protocol (mm-handle-multipart-ctl-parameter handle 'protocol))
-         (crypto-type (or (nth 2 (assoc protocol mm-verify-function-alist))
-                          (nth 2 (assoc protocol mm-decrypt-function-alist))
-                          "Unknown"))
-         (type (concat crypto-type
-                       (if (equal (car handle) "multipart/signed")
-                           " Signed" " Encrypted")
-                       " Part"))
-         (info (or (mm-handle-multipart-ctl-parameter handle 'gnus-info)
-                   "Undecided"))
-         (details (mm-handle-multipart-ctl-parameter handle 'gnus-details))
-         pressed-details begin end face)
-    (setq details (if details (concat "\n" details) ""))
-    (setq pressed-details (if mh-mime-security-button-pressed details ""))
-    (setq face (mh-mime-security-button-face info))
-    (unless (bolp) (insert "\n"))
-    (setq begin (point))
-    (gnus-eval-format
-     mh-mime-security-button-line-format
-     mh-mime-security-button-line-format-alist
-     `(,@(gnus-local-map-property mh-mime-security-button-map)
-         mh-button-pressed ,mh-mime-security-button-pressed
-         mh-callback mh-mime-security-press-button
-         mh-line-format ,mh-mime-security-button-line-format
-         mh-data ,handle))
-    (setq end (point))
-    (widget-convert-button 'link begin end
-                           :mime-handle handle
-                           :action 'mh-widget-press-button
-                           :button-keymap mh-mime-security-button-map
-                           :button-face face
-                           :help-echo "Mouse-2 click or press RET (in show buffer) to see security details.")
-    (dolist (ov (mh-funcall-if-exists overlays-in begin end))
-      (mh-funcall-if-exists overlay-put ov 'evaporate t))
-    (when (equal info "Failed")
-      (let* ((type (if (equal (car handle) "multipart/signed")
-                       "verification" "decryption"))
-             (warning (if (equal type "decryption")
-                          "(passphrase may be incorrect)" "")))
-        (message "%s %s failed %s" crypto-type type warning)))))
-
-(defun mh-mm-inline-message (handle)
-  "Display message, HANDLE.
-The function decodes the message and displays it. It avoids
-decoding the same message multiple times."
-  (let ((b (point))
-        (clean-message-header mh-clean-message-header-flag)
-        (invisible-headers mh-invisible-header-fields-compiled)
-        (visible-headers nil))
-    (save-excursion
-      (save-restriction
-        (narrow-to-region b b)
-        (mm-insert-part handle)
-        (mh-mime-display
-         (or (gethash handle (mh-mime-handles-cache (mh-buffer-data)))
-             (setf (gethash handle (mh-mime-handles-cache (mh-buffer-data)))
-                   (let ((handles (mm-dissect-buffer nil)))
-                     (if handles
-                         (when (fboundp 'mm-uu-dissect-text-parts)
-                           (mm-uu-dissect-text-parts handles))
-                       (setq handles (mm-uu-dissect)))
-                     (setf (mh-mime-handles (mh-buffer-data))
-                           (mm-merge-handles
-                            handles (mh-mime-handles (mh-buffer-data))))
-                     handles))))
-
-        (goto-char (point-min))
-        (mh-show-xface)
-        (cond (clean-message-header
-               (mh-clean-msg-header (point-min)
-                                    invisible-headers
-                                    visible-headers)
-               (goto-char (point-min)))
-              (t
-               (mh-start-of-uncleaned-message)))
-        (mh-decode-message-header)
-        (mh-show-addr)
-        ;; The other highlighting types don't need anything special
-        (when (eq mh-highlight-citation-style 'gnus)
-          (mh-gnus-article-highlight-citation))
-        (goto-char (point-min))
-        (insert "\n------- Forwarded Message\n\n")
-        (mh-display-smileys)
-        (mh-display-emphasis)
-        (mm-handle-set-undisplayer
-         handle
-         `(lambda ()
-            (let (buffer-read-only)
-              (if (fboundp 'remove-specifier)
-                  ;; This is only valid on XEmacs.
-                  (mapcar (lambda (prop)
-                            (remove-specifier
-                             (face-property 'default prop) (current-buffer)))
-                          '(background background-pixmap foreground)))
-              (delete-region ,(point-min-marker) ,(point-max-marker)))))))))
-
 (provide 'mh-mime)
 
 ;; Local Variables:
--- a/lisp/mh-e/mh-print.el	Thu Jan 26 02:23:05 2006 +0000
+++ b/lisp/mh-e/mh-print.el	Wed Feb 01 10:07:17 2006 +0000
@@ -30,15 +30,10 @@
 
 ;;; Code:
 
-;;(message "> mh-print")
-(eval-when-compile (require 'mh-acros))
-(mh-require-cl)
+(require 'mh-e)
+(require 'mh-scan)
+
 (require 'ps-print)
-(require 'mh-buffers)
-(require 'mh-utils)
-(require 'mh-funcs)
-(eval-when-compile (require 'mh-seq))
-;;(message "< mh-print")
 
 (defvar mh-ps-print-color-option ps-print-color-p
   "Specify how buffer's text color is printed.
@@ -48,7 +43,7 @@
    nil         - Do not print colors.
    t           - Print colors.
    black-white - Print colors on black/white printer.
-		 See also `ps-black-white-faces'.
+                 See also `ps-black-white-faces'.
 
 Any other value is treated as t. This variable is initialized
 from `ps-print-color-p'.")
@@ -59,54 +54,6 @@
 Sensible choices are the functions `ps-spool-buffer' and
 `ps-spool-buffer-with-faces'.")
 
-(defun mh-ps-spool-buffer (buffer)
-  "Spool BUFFER."
-  (save-excursion
-    (set-buffer buffer)
-    (let ((ps-print-color-p mh-ps-print-color-option)
-          (ps-left-header
-           (list
-            (concat "(" (mh-get-header-field "Subject:") ")")
-            (concat "(" (mh-get-header-field "From:") ")")))
-          (ps-right-header
-           (list
-            "/pagenumberstring load"
-            (concat "(" (mh-get-header-field "Date:") ")"))))
-      (funcall mh-ps-print-func))))
-
-(defun mh-ps-spool-msg (msg)
-  "Spool MSG."
-  (let* ((folder mh-current-folder)
-         (buffer (mh-in-show-buffer (mh-show-buffer)
-                   (if (not (equal (mh-msg-filename msg folder)
-                                   buffer-file-name))
-                       (get-buffer-create mh-temp-buffer)))))
-    (unwind-protect
-        (save-excursion
-          (if buffer
-              (let ((mh-show-buffer buffer))
-                (mh-display-msg msg folder)))
-          (mh-ps-spool-buffer (if buffer buffer mh-show-buffer)))
-      (if buffer
-          (kill-buffer buffer)))))
-
-(defun mh-ps-print-range (range file)
-  "Print RANGE to FILE.
-
-This is the function that actually does the work.
-If FILE is nil, then the messages are spooled to the printer."
-  (mh-iterate-on-range msg range
-    (unwind-protect
-        (mh-ps-spool-msg msg))
-    (mh-notate msg mh-note-printed mh-cmd-note))
-  (ps-despool file))
-
-(defun mh-ps-print-preprint (prefix-arg)
-  "Provide a better default file name for `ps-print-preprint'.
-Pass along the PREFIX-ARG to it."
-  (let ((buffer-file-name (format "mh-%s" (substring (buffer-name) 1))))
-    (ps-print-preprint prefix-arg)))
-
 ;;;###mh-autoload
 (defun mh-ps-print-msg (range)
   "Print RANGE\\<mh-folder-mode-map>.
@@ -130,6 +77,48 @@
   (interactive (list (mh-interactive-range "Print")))
   (mh-ps-print-range range nil))
 
+(defun mh-ps-print-range (range file)
+  "Print RANGE to FILE.
+
+This is the function that actually does the work.
+If FILE is nil, then the messages are spooled to the printer."
+  (mh-iterate-on-range msg range
+    (unwind-protect
+        (mh-ps-spool-msg msg))
+    (mh-notate msg mh-note-printed mh-cmd-note))
+  (ps-despool file))
+
+(defun mh-ps-spool-msg (msg)
+  "Spool MSG."
+  (let* ((folder mh-current-folder)
+         (buffer (mh-in-show-buffer (mh-show-buffer)
+                   (if (not (equal (mh-msg-filename msg folder)
+                                   buffer-file-name))
+                       (get-buffer-create mh-temp-buffer)))))
+    (unwind-protect
+        (save-excursion
+          (if buffer
+              (let ((mh-show-buffer buffer))
+                (mh-display-msg msg folder)))
+          (mh-ps-spool-buffer (if buffer buffer mh-show-buffer)))
+      (if buffer
+          (kill-buffer buffer)))))
+
+(defun mh-ps-spool-buffer (buffer)
+  "Spool BUFFER."
+  (save-excursion
+    (set-buffer buffer)
+    (let ((ps-print-color-p mh-ps-print-color-option)
+          (ps-left-header
+           (list
+            (concat "(" (mh-get-header-field "Subject:") ")")
+            (concat "(" (mh-get-header-field "From:") ")")))
+          (ps-right-header
+           (list
+            "/pagenumberstring load"
+            (concat "(" (mh-get-header-field "Date:") ")"))))
+      (funcall mh-ps-print-func))))
+
 ;;;###mh-autoload
 (defun mh-ps-print-msg-file (range file)
   "Print RANGE to FILE\\<mh-folder-mode-map>.
@@ -153,6 +142,12 @@
   (interactive (list (mh-interactive-range "Print") (mh-ps-print-preprint 1)))
   (mh-ps-print-range range file))
 
+(defun mh-ps-print-preprint (prefix-arg)
+  "Provide a better default file name for `ps-print-preprint'.
+Pass along the PREFIX-ARG to it."
+  (let ((buffer-file-name (format "mh-%s" (substring (buffer-name) 1))))
+    (ps-print-preprint prefix-arg)))
+
 ;;;###mh-autoload
 (defun mh-ps-print-toggle-faces ()
  "Toggle whether printing is done with faces or not.
@@ -185,8 +180,8 @@
        (message "Colors will be printed as black & white"))
    (if (eq mh-ps-print-color-option 'black-white)
        (progn
-	 (setq mh-ps-print-color-option t)
-	 (message "Colors will be printed"))
+         (setq mh-ps-print-color-option t)
+         (message "Colors will be printed"))
      (setq mh-ps-print-color-option nil)
      (message "Colors will not be printed"))))
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lisp/mh-e/mh-scan.el	Wed Feb 01 10:07:17 2006 +0000
@@ -0,0 +1,491 @@
+;;; mh-scan.el --- MH-E scan line constants and utilities
+
+;; Copyright (C) 1993, 1995, 1997,
+;;  2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+
+;; Author: Bill Wohler <wohler@newt.com>
+;; Maintainer: Bill Wohler <wohler@newt.com>
+;; Keywords: mail
+;; See: mh-e.el
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
+
+;;; Commentary:
+
+;; This file contains constants and a few functions for interpreting
+;; scan lines.
+
+;;; Change Log:
+
+;;; Code:
+
+(require 'mh-e)
+
+
+
+;;; Scan Formats
+
+;; The following scan formats are passed to the scan program if the setting of
+;; `mh-scan-format-file' is t. They are identical except the later one makes
+;; use of the nmh `decode' function to decode RFC 2047 encodings. If you just
+;; want to change the column of the notations, use the `mh-set-cmd-note'
+;; function.
+
+(defvar mh-scan-format-mh
+  (concat
+   "%4(msg)"
+   "%<(cur)+%| %>"
+   "%<{replied}-"
+   "%?(nonnull(comp{to}))%<(mymbox{to})t%>"
+   "%?(nonnull(comp{cc}))%<(mymbox{cc})c%>"
+   "%?(nonnull(comp{bcc}))%<(mymbox{bcc})b%>"
+   "%?(nonnull(comp{newsgroups}))n%>"
+   "%<(zero) %>"
+   "%02(mon{date})/%02(mday{date})%<{date} %|*%>"
+   "%<(mymbox{from})%<{to}To:%14(friendly{to})%>%>"
+   "%<(zero)%17(friendly{from})%>  "
+   "%{subject}%<{body}<<%{body}%>")
+  "*Scan format string for MH.
+This string is passed to the scan program via the -format
+argument. This format is identical to the default except that
+additional hints for fontification have been added to the fifth
+column (remember that in Emacs, the first column is 0).
+
+The values of the fifth column, in priority order, are: \"-\" if
+the message has been replied to, t if an address on the To: line
+matches one of the mailboxes of the current user, \"c\" if the Cc:
+line matches, \"b\" if the Bcc: line matches, and \"n\" if a
+non-empty Newsgroups: header is present.")
+
+(defvar mh-scan-format-nmh
+  (concat
+   "%4(msg)"
+   "%<(cur)+%| %>"
+   "%<{replied}-"
+   "%?(nonnull(comp{to}))%<(mymbox{to})t%>"
+   "%?(nonnull(comp{cc}))%<(mymbox{cc})c%>"
+   "%?(nonnull(comp{bcc}))%<(mymbox{bcc})b%>"
+   "%?(nonnull(comp{newsgroups}))n%>"
+   "%<(zero) %>"
+   "%02(mon{date})/%02(mday{date})%<{date} %|*%>"
+   "%<(mymbox{from})%<{to}To:%14(decode(friendly{to}))%>%>"
+   "%<(zero)%17(decode(friendly{from}))%>  "
+   "%(decode{subject})%<{body}<<%{body}%>")
+  "*Scan format string for nmh.
+This string is passed to the scan program via the -format arg.
+This format is identical to the default except that additional
+hints for fontification have been added to the fifth
+column (remember that in Emacs, the first column is 0).
+
+The values of the fifth column, in priority order, are: \"-\" if
+the message has been replied to, t if an address on the To: field
+matches one of the mailboxes of the current user, \"c\" if the Cc:
+field matches, \"b\" if the Bcc: field matches, and \"n\" if a
+non-empty Newsgroups: field is present.")
+
+
+
+;;; Regular Expressions
+
+;; Alphabetical.
+
+(defvar mh-scan-body-regexp "\\(<<\\([^\n]+\\)?\\)"
+  "This regular expression matches the message body fragment.
+
+Note that the default setting of `mh-folder-font-lock-keywords'
+expects this expression to contain at least one parenthesized
+expression which matches the body text as in the default of
+\"\\\\(<<\\\\([^\\n]+\\\\)?\\\\)\". If this regular expression is
+not correct, the body fragment will not be highlighted with the
+face `mh-folder-body'.")
+
+(defvar mh-scan-cur-msg-number-regexp "^\\( *[0-9]+\\+\\).*"
+  "This regular expression matches the current message.
+
+It must match from the beginning of the line. Note that the
+default setting of `mh-folder-font-lock-keywords' expects this
+expression to contain at least one parenthesized expression which
+matches the message number as in the default of
+
+  \"^\\\\( *[0-9]+\\\\+\\\\).*\".
+
+This expression includes the leading space and current message
+marker \"+\" within the parenthesis since it looks better to
+highlight these items as well. The highlighting is done with the
+face `mh-folder-cur-msg-number'. This regular expression should
+be correct as it is needed by non-fontification functions. See
+also `mh-note-cur'.")
+
+(defvar mh-scan-date-regexp "\\([0-9][0-9]/[0-9][0-9]\\)"
+  "This regular expression matches a valid date.
+
+It must not be anchored to the beginning or the end of the line.
+Note that the default setting of `mh-folder-font-lock-keywords'
+expects this expression to contain only one parenthesized
+expression which matches the date field as in the default of
+\"\\\\([0-9][0-9]/[0-9][0-9]\\\\)\"}. If this regular expression
+is not correct, the date will not be highlighted with the face
+`mh-folder-date'.")
+
+(defvar mh-scan-deleted-msg-regexp "^\\( *[0-9]+\\)D"
+  "This regular expression matches deleted messages.
+
+It must match from the beginning of the line. Note that the
+default setting of `mh-folder-font-lock-keywords' expects this
+expression to contain at least one parenthesized expression which
+matches the message number as in the default of
+
+  \"^\\\\( *[0-9]+\\\\)D\".
+
+This expression includes the leading space within the parenthesis
+since it looks better to highlight it as well. The highlighting
+is done with the face `mh-folder-deleted'. This regular
+expression should be correct as it is needed by non-fontification
+functions. See also `mh-note-deleted'.")
+
+(defvar mh-scan-good-msg-regexp  "^\\( *[0-9]+\\)[^D^0-9]"
+  "This regular expression matches \"good\" messages.
+
+It must match from the beginning of the line. Note that the
+default setting of `mh-folder-font-lock-keywords' expects this
+expression to contain at least one parenthesized expression which
+matches the message number as in the default of
+
+  \"^\\\\( *[0-9]+\\\\)[^D^0-9]\".
+
+This expression includes the leading space within the parenthesis
+since it looks better to highlight it as well. The highlighting
+is done with the face `mh-folder-msg-number'. This regular
+expression should be correct as it is needed by non-fontification
+functions.")
+
+(defvar mh-scan-msg-format-regexp "%\\([0-9]*\\)(msg)"
+  "This regular expression finds the message number width in a scan format.
+
+Note that the message number must be placed in a parenthesized
+expression as in the default of \"%\\\\([0-9]*\\\\)(msg)\". This
+variable is only consulted if `mh-scan-format-file' is set to
+\"Use MH-E scan Format\".")
+
+(defvar mh-scan-msg-format-string "%d"
+  "This is a format string for width of the message number in a scan format.
+
+Use \"0%d\" for zero-filled message numbers. This variable is only
+consulted if `mh-scan-format-file' is set to \"Use MH-E scan
+Format\".")
+
+(defvar mh-scan-msg-number-regexp "^ *\\([0-9]+\\)"
+  "This regular expression extracts the message number.
+
+It must match from the beginning of the line. Note that the
+message number must be placed in a parenthesized expression as in
+the default of \"^ *\\\\([0-9]+\\\\)\".")
+
+(defvar mh-scan-msg-overflow-regexp "^[?0-9][0-9]"
+  "This regular expression matches overflowed message numbers.")
+
+(defvar mh-scan-msg-search-regexp "^[^0-9]*%d[^0-9]"
+  "This regular expression matches a particular message.
+
+It is a format string; use \"%d\" to represent the location of the
+message number within the expression as in the default of
+\"^[^0-9]*%d[^0-9]\".")
+
+(defvar mh-scan-rcpt-regexp  "\\(To:\\)\\(..............\\)"
+  "This regular expression specifies the recipient in messages you sent.
+
+Note that the default setting of `mh-folder-font-lock-keywords'
+expects this expression to contain two parenthesized expressions.
+The first is expected to match the \"To:\" that the default scan
+format file generates. The second is expected to match the
+recipient's name as in the default of
+\"\\\\(To:\\\\)\\\\(..............\\\\)\". If this regular
+expression is not correct, the \"To:\" string will not be
+highlighted with the face `mh-folder-to' and the recipient will
+not be highlighted with the face `mh-folder-address'")
+
+(defvar mh-scan-refiled-msg-regexp  "^\\( *[0-9]+\\)\\^"
+  "This regular expression matches refiled messages.
+
+It must match from the beginning of the line. Note that the
+default setting of `mh-folder-font-lock-keywords' expects this
+expression to contain at least one parenthesized expression which
+matches the message number as in the default of
+
+  \"^\\\\( *[0-9]+\\\\)\\\\^\".
+
+This expression includes the leading space within the parenthesis
+since it looks better to highlight it as well. The highlighting
+is done with the face `mh-folder-refiled'. This regular
+expression should be correct as it is needed by non-fontification
+functions. See also `mh-note-refiled'.")
+
+(defvar mh-scan-sent-to-me-sender-regexp
+  "^ *[0-9]+.\\([bct]\\).....[ ]*\\(..................\\)"
+  "This regular expression matches messages sent to us.
+
+Note that the default setting of `mh-folder-font-lock-keywords'
+expects this expression to contain at least two parenthesized
+expressions. The first should match the fontification hint (see
+`mh-scan-format-nmh') and the second should match the user name
+as in the default of
+
+  ^ *[0-9]+.\\\\([bct]\\\\).....[ ]*\\\\(..................\\\\)
+
+If this regular expression is not correct, the notation hints
+will not be highlighted with the face
+`mh-mh-folder-sent-to-me-hint' and the sender will not be
+highlighted with the face `mh-folder-sent-to-me-sender'.")
+
+(defvar mh-scan-subject-regexp
+  "^ *[0-9]+........[ ]*...................\\([Rr][Ee]\\(\\[[0-9]+\\]\\)?:\\s-*\\)*\\([^<\n]*\\)"
+  "This regular expression matches the subject.
+
+It must match from the beginning of the line. Note that the
+default setting of `mh-folder-font-lock-keywords' expects this
+expression to contain at least three parenthesized expressions.
+The first is expected to match the \"Re:\" string, if any, and is
+highlighted with the face `mh-folder-followup'. The second
+matches an optional bracketed number after \"Re:\", such as in
+\"Re[2]:\" (and is thus a sub-expression of the first expression)
+and the third is expected to match the subject line itself which
+is highlighted with the face `mh-folder-subject'. For example,
+the default (broken on multiple lines for readability) is
+
+  ^ *[0-9]+........[ ]*...................
+  \\\\([Rr][Ee]\\\\(\\\\\\=[[0-9]+\\\\]\\\\)?:\\\\s-*\\\\)*
+  \\\\([^<\\n]*\\\\)
+
+This regular expression should be correct as it is needed by
+non-fontification functions.")
+
+(defvar mh-scan-valid-regexp "^ *[0-9]"
+  "This regular expression describes a valid scan line.
+
+This is used to eliminate error messages that are occasionally
+produced by \"inc\".")
+
+
+
+;;; Widths, Offsets and Columns
+
+(defvar mh-cmd-note 4
+  "Column for notations.
+
+This variable should be set with the function `mh-set-cmd-note'.
+This variable may be updated dynamically if
+`mh-adaptive-cmd-note-flag' is on.
+
+Note that columns in Emacs start with 0.")
+(make-variable-buffer-local 'mh-cmd-note)
+
+(defvar mh-scan-cmd-note-width 1
+  "Number of columns consumed by the cmd-note field in `mh-scan-format'.
+
+This column will have one of the values: \" \", \"D\", \"^\", \"+\" and
+where \" \" is the default value,
+
+  \"D\" is the `mh-note-deleted' character,
+  \"^\" is the `mh-note-refiled' character, and
+  \"+\" is the `mh-note-cur' character.")
+
+(defvar mh-scan-destination-width 1
+  "Number of columns consumed by the destination field in `mh-scan-format'.
+
+This column will have one of \" \", \"%\", \"-\", \"t\", \"c\", \"b\", or \"n\"
+in it.
+
+  \" \" blank space is the default character.
+  \"%\" indicates that the message in in a named MH sequence.
+  \"-\" indicates that the message has been annotated with a replied field.
+  \"t\" indicates that the message contains mymbox in the To: field.
+  \"c\" indicates that the message contains mymbox in the Cc: field.
+  \"b\" indicates that the message contains mymbox in the Bcc: field.
+  \"n\" indicates that the message contains a Newsgroups: field.")
+
+(defvar mh-scan-date-width 5
+  "Number of columns consumed by the date field in `mh-scan-format'.
+This column will typically be of the form mm/dd.")
+
+(defvar mh-scan-date-flag-width 1
+  "Number of columns consumed to flag (in)valid dates in `mh-scan-format'.
+This column will have \" \" for valid and \"*\" for invalid or
+missing dates.")
+
+(defvar mh-scan-from-mbox-width 17
+  "Number of columns consumed with the \"From:\" line in `mh-scan-format'.
+This column will have a friendly name or e-mail address of the
+originator, or a \"To: address\" for outgoing e-mail messages.")
+
+(defvar mh-scan-from-mbox-sep-width 2
+  "Number of columns consumed by whitespace after from-mbox in `mh-scan-format'.
+This column will only ever have spaces in it.")
+
+(defvar mh-scan-field-destination-offset
+  (+ mh-scan-cmd-note-width)
+  "The offset from the `mh-cmd-note' for the destination column.")
+
+(defvar mh-scan-field-from-start-offset
+  (+ mh-scan-cmd-note-width
+     mh-scan-destination-width
+     mh-scan-date-width
+     mh-scan-date-flag-width)
+  "The offset from the `mh-cmd-note' to find the start of \"From:\" address.")
+
+(defvar mh-scan-field-from-end-offset
+  (+ mh-scan-field-from-start-offset mh-scan-from-mbox-width)
+  "The offset from the `mh-cmd-note' to find the end of \"From:\" address.")
+
+(defvar mh-scan-field-subject-start-offset
+  (+ mh-scan-cmd-note-width
+     mh-scan-destination-width
+     mh-scan-date-width
+     mh-scan-date-flag-width
+     mh-scan-from-mbox-width
+     mh-scan-from-mbox-sep-width)
+  "The offset from the `mh-cmd-note' to find the start of the subject.")
+
+
+
+;;; Notation
+
+;; Alphabetical.
+
+(defvar mh-note-cur ?+
+  "The current message (in MH, not in MH-E) is marked by this character.
+See also `mh-scan-cur-msg-number-regexp'.")
+
+(defvar mh-note-copied ?C
+  "Messages that have been copied are marked by this character.")
+
+(defvar mh-note-deleted ?D
+  "Messages that have been deleted are marked by this character.
+See also `mh-scan-deleted-msg-regexp'.")
+
+(defvar mh-note-dist ?R
+  "Messages that have been redistributed are marked by this character.")
+
+(defvar mh-note-forw ?F
+  "Messages that have been forwarded are marked by this character.")
+
+(defvar mh-note-printed ?P
+  "Messages that have been printed are marked by this character.")
+
+(defvar mh-note-refiled ?^
+  "Messages that have been refiled are marked by this character.
+See also `mh-scan-refiled-msg-regexp'.")
+
+(defvar mh-note-repl ?-
+  "Messages that have been replied to are marked by this character.")
+
+(defvar mh-note-seq ?%
+  "Messages in a user-defined sequence are marked by this character.
+
+Messages in the \"search\" sequence are marked by this character as
+well.")
+
+
+
+;;; Utilities
+
+;;;###mh-autoload
+(defun mh-scan-msg-number-regexp ()
+  "Return value of variable `mh-scan-msg-number-regexp'."
+  mh-scan-msg-number-regexp)
+
+;;;###mh-autoload
+(defun mh-scan-msg-search-regexp ()
+  "Return value of variable `mh-scan-msg-search-regexp'."
+  mh-scan-msg-search-regexp)
+
+;;;###mh-autoload
+(defun mh-set-cmd-note (column)
+  "Set `mh-cmd-note' to COLUMN.
+Note that columns in Emacs start with 0."
+  (setq mh-cmd-note column))
+
+;;;###mh-autoload
+(defun mh-scan-format ()
+  "Return the output format argument for the scan program."
+  (if (equal mh-scan-format-file t)
+      (list "-format" (if (mh-variant-p 'nmh 'mu-mh)
+                          (list (mh-update-scan-format
+                                 mh-scan-format-nmh mh-cmd-note))
+                        (list (mh-update-scan-format
+                               mh-scan-format-mh mh-cmd-note))))
+    (if (not (equal mh-scan-format-file nil))
+        (list "-form" mh-scan-format-file))))
+
+(defun mh-update-scan-format (fmt width)
+  "Return a scan format with the (msg) width in the FMT replaced with WIDTH.
+
+The message number width portion of the format is discovered
+using `mh-scan-msg-format-regexp'. Its replacement is controlled
+with `mh-scan-msg-format-string'."
+  (or (and
+       (string-match mh-scan-msg-format-regexp fmt)
+       (let ((begin (match-beginning 1))
+             (end (match-end 1)))
+         (concat (substring fmt 0 begin)
+                 (format mh-scan-msg-format-string width)
+                 (substring fmt end))))
+      fmt))
+
+;;;###mh-autoload
+(defun mh-msg-num-width (folder)
+  "Return the width of the largest message number in this FOLDER."
+  (or mh-progs (mh-find-path))
+  (let ((tmp-buffer (get-buffer-create mh-temp-buffer))
+        (width 0))
+    (save-excursion
+      (set-buffer tmp-buffer)
+      (erase-buffer)
+      (apply 'call-process
+             (expand-file-name mh-scan-prog mh-progs) nil '(t nil) nil
+             (list folder "last" "-format" "%(msg)"))
+      (goto-char (point-min))
+      (if (re-search-forward mh-scan-msg-number-regexp nil 0 1)
+          (setq width (length (buffer-substring
+                               (match-beginning 1) (match-end 1))))))
+    width))
+
+;;;###mh-autoload
+(defun mh-msg-num-width-to-column (width)
+  "Return the column for notations given message number WIDTH.
+Note that columns in Emacs start with 0.
+
+If `mh-scan-format-file' is set to \"Use MH-E scan Format\" this
+means that either `mh-scan-format-mh' or `mh-scan-format-nmh' are
+in use. This function therefore assumes that the first column is
+empty (to provide room for the cursor), the following WIDTH
+columns contain the message number, and the column for notations
+comes after that."
+  (if (eq mh-scan-format-file t)
+      (max (1+ width) 2)
+    (error "%s %s" "Can't call `mh-msg-num-width-to-column' when"
+           "`mh-scan-format-file' is not set to \"Use MH-E scan Format\"")))
+
+(provide 'mh-scan)
+
+;; Local Variables:
+;; indent-tabs-mode: nil
+;; sentence-end-double-space: nil
+;; End:
+
+;; arch-tag: 5ab35d46-101e-443b-a2b6-5a908cf97528
+;;; mh-scan.el ends here
--- a/lisp/mh-e/mh-search.el	Thu Jan 26 02:23:05 2006 +0000
+++ b/lisp/mh-e/mh-search.el	Wed Feb 01 10:07:17 2006 +0000
@@ -1,4 +1,4 @@
-;;; mh-search  ---  MH-E search
+;;; mh-search  ---  MH-Search mode
 
 ;; Copyright (C) 1993, 1995,
 ;;  2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
@@ -27,6 +27,8 @@
 
 ;;; Commentary:
 
+;; Mode used to compose search criteria.
+
 ;;  (1) The following search engines are supported:
 ;;        swish++
 ;;        swish-e
@@ -34,7 +36,7 @@
 ;;        namazu
 ;;        pick
 ;;        grep
-;;
+
 ;;  (2) To use this package, you first have to build an index. Please
 ;;      read the documentation for `mh-search' to get started. That
 ;;      documentation will direct you to the specific instructions for
@@ -44,14 +46,12 @@
 
 ;;; Code:
 
-;;(message "> mh-search")
-(eval-when-compile (require 'mh-acros))
+(require 'mh-e)
 (mh-require-cl)
 
 (require 'gnus-util)
-(require 'mh-buffers)
-(require 'mh-e)
-;;(message "< mh-search")
+(require 'imenu)
+(require 'which-func nil t)
 
 (defvar mh-searcher nil
   "Cached value of chosen search program.")
@@ -79,7 +79,7 @@
 
 
 
-;;; MH-Search mode
+;;; MH-Folder Commands
 
 ;;;###mh-autoload
 (defun* mh-search (folder search-regexp
@@ -322,6 +322,9 @@
                (loop for msg-hash being hash-values of mh-index-data
                      count (> (hash-table-count msg-hash) 0))))))
 
+;; Shush compiler.
+(eval-when-compile (mh-do-in-xemacs (defvar pick-folder)))
+
 (defun mh-search-folder (folder window-config)
   "Search FOLDER for messages matching a pattern.
 
@@ -363,11 +366,193 @@
   (add-text-properties (point) (1- (line-end-position)) '(read-only t))
   (goto-char (point-max)))
 
+;; Sequence Searches
+
 ;;;###mh-autoload
-(defvar mh-search-mode-map (make-sparse-keymap)
-  "Keymap for searching folder.")
+(defun mh-index-new-messages (folders)
+  "Display unseen messages.
+
+If you use a program such as \"procmail\" to use \"rcvstore\" to file
+your incoming mail automatically, you can display new, unseen,
+messages using this command. All messages in the \"unseen\"
+sequence from the folders in `mh-new-messages-folders' are
+listed.
+
+With a prefix argument, enter a space-separated list of FOLDERS,
+or nothing to search all folders."
+  (interactive
+   (list (if current-prefix-arg
+             (split-string (read-string "Search folder(s) (default all): "))
+           mh-new-messages-folders)))
+  (mh-index-sequenced-messages folders mh-unseen-seq))
+
+;;;###mh-autoload
+(defun mh-index-ticked-messages (folders)
+  "Display ticked messages.
+
+All messages in `mh-tick-seq' from the folders in
+`mh-ticked-messages-folders' are listed.
+
+With a prefix argument, enter a space-separated list of FOLDERS,
+or nothing to search all folders."
+  (interactive
+   (list (if current-prefix-arg
+             (split-string (read-string "Search folder(s) (default all): "))
+           mh-ticked-messages-folders)))
+  (mh-index-sequenced-messages folders mh-tick-seq))
+
+;; Shush compiler.
+(eval-when-compile
+  (mh-do-in-xemacs
+    (defvar mh-mairix-folder)
+    (defvar mh-flists-search-folders)))
 
 ;;;###mh-autoload
+(defun mh-index-sequenced-messages (folders sequence)
+  "Display messages in any sequence.
+
+All messages from the FOLDERS in `mh-new-messages-folders' in the
+SEQUENCE you provide are listed. With a prefix argument, enter a
+space-separated list of folders at the prompt, or nothing to
+search all folders."
+  (interactive
+   (list (if current-prefix-arg
+             (split-string (read-string "Search folder(s) (default all): "))
+           mh-new-messages-folders)
+         (mh-read-seq-default "Search" nil)))
+  (unless sequence (setq sequence mh-unseen-seq))
+  (let* ((mh-flists-search-folders folders)
+         (mh-flists-sequence sequence)
+         (mh-flists-called-flag t)
+         (mh-searcher 'flists)
+         (mh-search-function 'mh-flists-execute)
+         (mh-search-next-result-function 'mh-mairix-next-result)
+         (mh-mairix-folder mh-user-path)
+         (mh-search-regexp-builder nil)
+         (new-folder (format "%s/%s/%s" mh-index-folder
+                             mh-flists-results-folder sequence))
+         (window-config (if (equal new-folder mh-current-folder)
+                            mh-previous-window-config
+                          (current-window-configuration)))
+         (redo-flag nil)
+         message)
+    (cond ((buffer-live-p (get-buffer new-folder))
+           ;; The destination folder is being visited. Trick `mh-search'
+           ;; into thinking that the folder resulted from a previous search.
+           (set-buffer new-folder)
+           (setq mh-index-previous-search (list folders mh-searcher sequence))
+           (setq redo-flag t))
+          ((mh-folder-exists-p new-folder)
+           ;; Folder exists but we don't have it open. That means they are
+           ;; stale results from a old flists search. Clear it out.
+           (mh-exec-cmd-quiet nil "rmf" new-folder)))
+    (setq message (mh-search "+" mh-flists-results-folder
+                             redo-flag window-config)
+          mh-index-sequence-search-flag t
+          mh-index-previous-search (list folders mh-searcher sequence))
+    (mh-index-write-data)
+    (when (stringp message) (message "%s" message))))
+
+(defvar mh-flists-search-folders)
+
+(defun mh-flists-execute (&rest args)
+  "Execute flists.
+Search for messages belonging to `mh-flists-sequence' in the
+folders specified by `mh-flists-search-folders'. If
+`mh-recursive-folders-flag' is t, then the folders are searched
+recursively. All parameters ARGS are ignored."
+  (set-buffer (get-buffer-create mh-temp-index-buffer))
+  (erase-buffer)
+  (unless (executable-find "sh")
+    (error "Didn't find sh"))
+  (with-temp-buffer
+    (let ((seq (symbol-name mh-flists-sequence)))
+      (insert "for folder in `" (expand-file-name "flists" mh-progs) " "
+              (cond ((eq mh-flists-search-folders t)
+                     (mh-quote-for-shell mh-inbox))
+                    ((eq mh-flists-search-folders nil) "")
+                    ((listp mh-flists-search-folders)
+                     (loop for folder in mh-flists-search-folders
+                           concat
+                           (concat " " (mh-quote-for-shell folder)))))
+              (if mh-recursive-folders-flag " -recurse" "")
+              " -sequence " seq " -noshowzero -fast` ; do\n"
+              (expand-file-name "mhpath" mh-progs) " \"+$folder\" " seq "\n"
+              "done\n"))
+    (call-process-region
+     (point-min) (point-max) "sh" nil (get-buffer mh-temp-index-buffer))))
+
+;; Navigation
+
+;;;###mh-autoload
+(defun mh-index-next-folder (&optional backward-flag)
+  "Jump to the next folder marker.
+
+With non-nil optional argument BACKWARD-FLAG, jump to the previous
+group of results."
+  (interactive "P")
+  (if (null mh-index-data)
+      (message "Only applicable in an MH-E index search buffer")
+    (let ((point (point)))
+      (forward-line (if backward-flag 0 1))
+      (cond ((if backward-flag
+                 (re-search-backward "^+" (point-min) t)
+               (re-search-forward "^+" (point-max) t))
+             (beginning-of-line))
+            ((and (if backward-flag
+                      (goto-char (point-max))
+                    (goto-char (point-min)))
+                  nil))
+            ((if backward-flag
+                 (re-search-backward "^+" (point-min) t)
+               (re-search-forward "^+" (point-max) t))
+             (beginning-of-line))
+            (t (goto-char point))))))
+
+;;;###mh-autoload
+(defun mh-index-previous-folder ()
+  "Jump to the previous folder marker."
+  (interactive)
+  (mh-index-next-folder t))
+
+;;;###mh-autoload
+(defun mh-index-visit-folder ()
+  "Visit original folder from where the message at point was found."
+  (interactive)
+  (unless mh-index-data
+    (error "Not in an index folder"))
+  (let (folder msg)
+    (save-excursion
+      (cond ((and (bolp) (eolp))
+             (ignore-errors (forward-line -1))
+             (setq msg (mh-get-msg-num t)))
+            ((equal (char-after (line-beginning-position)) ?+)
+             (setq folder (buffer-substring-no-properties
+                           (line-beginning-position) (line-end-position))))
+            (t (setq msg (mh-get-msg-num t)))))
+    (when (not folder)
+      (setq folder (car (gethash (gethash msg mh-index-msg-checksum-map)
+                                 mh-index-checksum-origin-map))))
+    (when (or (not (get-buffer folder))
+              (y-or-n-p (format "Reuse buffer displaying %s? " folder)))
+      (mh-visit-folder
+       folder (loop for x being the hash-keys of (gethash folder mh-index-data)
+                    when (mh-msg-exists-p x folder) collect x)))))
+
+
+
+;;; Search Menu
+
+(easy-menu-define
+  mh-pick-menu mh-search-mode-map "Menu for MH-E Search"
+  '("Search"
+    ["Perform Search"       mh-index-do-search t]
+    ["Search with pick"     mh-pick-do-search t]))
+
+
+
+;;; MH-Search Keys
+
 ;; If this changes, modify mh-search-mode-help-messages accordingly, below.
 (gnus-define-keys  mh-search-mode-map
   "\C-c?"               mh-help
@@ -375,30 +560,24 @@
   "\C-c\C-p"            mh-pick-do-search
   "\C-c\C-f\C-b"        mh-to-field
   "\C-c\C-f\C-c"        mh-to-field
-  "\C-c\C-f\C-d"        mh-to-field
-  "\C-c\C-f\C-f"        mh-to-field
-  "\C-c\C-f\C-r"        mh-to-field
+  "\C-c\C-f\C-m"        mh-to-field
   "\C-c\C-f\C-s"        mh-to-field
   "\C-c\C-f\C-t"        mh-to-field
   "\C-c\C-fb"           mh-to-field
   "\C-c\C-fc"           mh-to-field
-  "\C-c\C-fd"           mh-to-field
-  "\C-c\C-ff"           mh-to-field
-  "\C-c\C-fr"           mh-to-field
+  "\C-c\C-fm"           mh-to-field
   "\C-c\C-fs"           mh-to-field
   "\C-c\C-ft"           mh-to-field)
 
-(easy-menu-define
-  mh-pick-menu mh-search-mode-map "Menu for MH-E Search"
-  '("Search"
-    ["Perform Search"       mh-index-do-search t]
-    ["Search with pick"     mh-pick-do-search t]))
+
+
+;;; MH-Search Help Messages
 
 ;; Group messages logically, more or less.
 (defvar mh-search-mode-help-messages
   '((nil
-     "Perform search:  \\[mh-index-do-search]\n"
-     "Search with pick:  \\[mh-pick-do-search]\n"
+     "Perform search:   \\[mh-index-do-search]\n"
+     "Search with pick: \\[mh-pick-do-search]\n\n"
      "Move to a field by typing C-c C-f C-<field>\n"
      "where <field> is the first letter of the desired field\n"
      "(except for From: which uses \"m\")."))
@@ -413,6 +592,10 @@
 The substitutions described in `substitute-command-keys' are performed
 as well.")
 
+
+
+;;; MH-Search Mode
+
 (put 'mh-search-mode 'mode-class 'special)
 
 (define-derived-mode mh-search-mode fundamental-mode "MH-Search"
@@ -435,11 +618,13 @@
 
 \\{mh-search-mode-map}"
 
-  (make-local-variable 'mh-help-messages)
   (easy-menu-add mh-pick-menu)
-  (setq mh-help-messages mh-search-mode-help-messages))
+  (mh-set-help mh-search-mode-help-messages))
 
-;;;###mh-autoload
+
+
+;;; MH-Search Commands
+
 (defun mh-index-do-search (&optional searcher)
   "Find messages using `mh-search-program'.
 If optional argument SEARCHER is present, use it instead of
@@ -452,7 +637,6 @@
         (mh-search mh-current-folder pattern nil mh-previous-window-config)
       (error "No search terms"))))
 
-;;;###mh-autoload
 (defun mh-pick-do-search ()
   "Find messages using \"pick\".
 
@@ -490,7 +674,6 @@
         (forward-line))
       pattern-list)))
 
-;;;###mh-autoload
 (defun mh-index-parse-search-regexp (input-string)
   "Construct parse tree for INPUT-STRING.
 All occurrences of &, |, ! and ~ in INPUT-STRING are replaced by
@@ -594,296 +777,7 @@
 
 
 
-;;; Sequence browsing
-
-;;;###mh-autoload
-(defun mh-index-new-messages (folders)
-  "Display unseen messages.
-
-If you use a program such as \"procmail\" to use \"rcvstore\" to file
-your incoming mail automatically, you can display new, unseen,
-messages using this command. All messages in the \"unseen\"
-sequence from the folders in `mh-new-messages-folders' are
-listed.
-
-With a prefix argument, enter a space-separated list of FOLDERS,
-or nothing to search all folders."
-  (interactive
-   (list (if current-prefix-arg
-             (split-string (read-string "Search folder(s) (default all): "))
-           mh-new-messages-folders)))
-  (mh-index-sequenced-messages folders mh-unseen-seq))
-
-;;;###mh-autoload
-(defun mh-index-ticked-messages (folders)
-  "Display ticked messages.
-
-All messages in `mh-tick-seq' from the folders in
-`mh-ticked-messages-folders' are listed.
-
-With a prefix argument, enter a space-separated list of FOLDERS,
-or nothing to search all folders."
-  (interactive
-   (list (if current-prefix-arg
-             (split-string (read-string "Search folder(s) (default all): "))
-           mh-ticked-messages-folders)))
-  (mh-index-sequenced-messages folders mh-tick-seq))
-
-;;;###mh-autoload
-(defun mh-index-sequenced-messages (folders sequence)
-  "Display messages in any sequence.
-
-All messages from the FOLDERS in `mh-new-messages-folders' in the
-SEQUENCE you provide are listed. With a prefix argument, enter a
-space-separated list of folders at the prompt, or nothing to
-search all folders."
-  (interactive
-   (list (if current-prefix-arg
-             (split-string (read-string "Search folder(s) (default all): "))
-           mh-new-messages-folders)
-         (mh-read-seq-default "Search" nil)))
-  (unless sequence (setq sequence mh-unseen-seq))
-  (let* ((mh-flists-search-folders folders)
-         (mh-flists-sequence sequence)
-         (mh-flists-called-flag t)
-         (mh-searcher 'flists)
-         (mh-search-function 'mh-flists-execute)
-         (mh-search-next-result-function 'mh-mairix-next-result)
-         (mh-mairix-folder mh-user-path)
-         (mh-search-regexp-builder nil)
-         (new-folder (format "%s/%s/%s" mh-index-folder
-                             mh-flists-results-folder sequence))
-         (window-config (if (equal new-folder mh-current-folder)
-                            mh-previous-window-config
-                          (current-window-configuration)))
-         (redo-flag nil)
-         message)
-    (cond ((buffer-live-p (get-buffer new-folder))
-           ;; The destination folder is being visited. Trick `mh-search'
-           ;; into thinking that the folder resulted from a previous search.
-           (set-buffer new-folder)
-           (setq mh-index-previous-search (list folders mh-searcher sequence))
-           (setq redo-flag t))
-          ((mh-folder-exists-p new-folder)
-           ;; Folder exists but we don't have it open. That means they are
-           ;; stale results from a old flists search. Clear it out.
-           (mh-exec-cmd-quiet nil "rmf" new-folder)))
-    (setq message (mh-search "+" mh-flists-results-folder
-                             redo-flag window-config)
-          mh-index-sequence-search-flag t
-          mh-index-previous-search (list folders mh-searcher sequence))
-    (mh-index-write-data)
-    (when (stringp message) (message "%s" message))))
-
-(defvar mh-flists-search-folders)
-
-(defun mh-flists-execute (&rest args)
-  "Execute flists.
-Search for messages belonging to `mh-flists-sequence' in the
-folders specified by `mh-flists-search-folders'. If
-`mh-recursive-folders-flag' is t, then the folders are searched
-recursively. All parameters ARGS are ignored."
-  (set-buffer (get-buffer-create mh-temp-index-buffer))
-  (erase-buffer)
-  (unless (executable-find "sh")
-    (error "Didn't find sh"))
-  (with-temp-buffer
-    (let ((seq (symbol-name mh-flists-sequence)))
-      (insert "for folder in `" (expand-file-name "flists" mh-progs) " "
-              (cond ((eq mh-flists-search-folders t)
-                     (mh-quote-for-shell mh-inbox))
-                    ((eq mh-flists-search-folders nil) "")
-                    ((listp mh-flists-search-folders)
-                     (loop for folder in mh-flists-search-folders
-                           concat
-                           (concat " " (mh-quote-for-shell folder)))))
-              (if mh-recursive-folders-flag " -recurse" "")
-              " -sequence " seq " -noshowzero -fast` ; do\n"
-              (expand-file-name "mhpath" mh-progs) " \"+$folder\" " seq "\n"
-              "done\n"))
-    (call-process-region
-     (point-min) (point-max) "sh" nil (get-buffer mh-temp-index-buffer))))
-
-
-
-;;; Folder navigation and utilities
-
-;;;###mh-autoload
-(defun mh-index-group-by-folder ()
-  "Partition the messages based on source folder.
-Returns an alist with the the folder names in the car and the cdr
-being the list of messages originally from that folder."
-  (save-excursion
-    (goto-char (point-min))
-    (let ((result-table (make-hash-table :test #'equal)))
-      (loop for msg being hash-keys of mh-index-msg-checksum-map
-            do (push msg (gethash (car (gethash
-                                        (gethash msg mh-index-msg-checksum-map)
-                                        mh-index-checksum-origin-map))
-                                  result-table)))
-      (loop for x being the hash-keys of result-table
-            collect (cons x (nreverse (gethash x result-table)))))))
-
-;;;###mh-autoload
-(defun mh-index-insert-folder-headers ()
-  "Annotate the search results with original folder names."
-  (let ((cur-msg (mh-get-msg-num nil))
-        (old-buffer-modified-flag (buffer-modified-p))
-        (buffer-read-only nil)
-        current-folder last-folder)
-    (goto-char (point-min))
-    (while (not (eobp))
-      (setq current-folder (car (gethash (gethash (mh-get-msg-num nil)
-                                                  mh-index-msg-checksum-map)
-                                         mh-index-checksum-origin-map)))
-      (when (and current-folder (not (equal current-folder last-folder)))
-        (insert (if last-folder "\n" "") current-folder "\n")
-        (setq last-folder current-folder))
-      (forward-line))
-    (when cur-msg
-      (mh-notate-cur)
-      (mh-goto-msg cur-msg t))
-    (set-buffer-modified-p old-buffer-modified-flag))
-  (mh-index-create-imenu-index))
-
-;;;###mh-autoload
-(defun mh-index-delete-folder-headers ()
-  "Delete the folder headers."
-  (let ((cur-msg (mh-get-msg-num nil))
-        (old-buffer-modified-flag (buffer-modified-p))
-        (buffer-read-only nil))
-    (while (and (not cur-msg) (not (eobp)))
-      (forward-line)
-      (setq cur-msg (mh-get-msg-num nil)))
-    (goto-char (point-min))
-    (while (not (eobp))
-      (if (or (char-equal (char-after) ?+) (char-equal (char-after) 10))
-          (delete-region (point) (progn (forward-line) (point)))
-        (forward-line)))
-    (when cur-msg (mh-goto-msg cur-msg t t))
-    (set-buffer-modified-p old-buffer-modified-flag)))
-
-;;;###mh-autoload
-(defun mh-index-create-imenu-index ()
-  "Create alist of folder names and positions in index folder buffers."
-  (save-excursion
-    (setq which-func-mode t)
-    (let ((alist ()))
-      (goto-char (point-min))
-      (while (re-search-forward "^+" nil t)
-        (save-excursion
-          (beginning-of-line)
-          (push (cons (buffer-substring-no-properties
-                       (point) (line-end-position))
-                      (set-marker (make-marker) (point)))
-                alist)))
-      (setq imenu--index-alist (nreverse alist)))))
-
-;;;###mh-autoload
-(defun mh-index-next-folder (&optional backward-flag)
-  "Jump to the next folder marker.
-
-With non-nil optional argument BACKWARD-FLAG, jump to the previous
-group of results."
-  (interactive "P")
-  (if (null mh-index-data)
-      (message "Only applicable in an MH-E index search buffer")
-    (let ((point (point)))
-      (forward-line (if backward-flag 0 1))
-      (cond ((if backward-flag
-                 (re-search-backward "^+" (point-min) t)
-               (re-search-forward "^+" (point-max) t))
-             (beginning-of-line))
-            ((and (if backward-flag
-                      (goto-char (point-max))
-                    (goto-char (point-min)))
-                  nil))
-            ((if backward-flag
-                 (re-search-backward "^+" (point-min) t)
-               (re-search-forward "^+" (point-max) t))
-             (beginning-of-line))
-            (t (goto-char point))))))
-
-;;;###mh-autoload
-(defun mh-index-previous-folder ()
-  "Jump to the previous folder marker."
-  (interactive)
-  (mh-index-next-folder t))
-
-;;;###mh-autoload
-(defun mh-index-visit-folder ()
-  "Visit original folder from where the message at point was found."
-  (interactive)
-  (unless mh-index-data
-    (error "Not in an index folder"))
-  (let (folder msg)
-    (save-excursion
-      (cond ((and (bolp) (eolp))
-             (ignore-errors (forward-line -1))
-             (setq msg (mh-get-msg-num t)))
-            ((equal (char-after (line-beginning-position)) ?+)
-             (setq folder (buffer-substring-no-properties
-                           (line-beginning-position) (line-end-position))))
-            (t (setq msg (mh-get-msg-num t)))))
-    (when (not folder)
-      (setq folder (car (gethash (gethash msg mh-index-msg-checksum-map)
-                                 mh-index-checksum-origin-map))))
-    (when (or (not (get-buffer folder))
-              (y-or-n-p (format "Reuse buffer displaying %s? " folder)))
-      (mh-visit-folder
-       folder (loop for x being the hash-keys of (gethash folder mh-index-data)
-                    when (mh-msg-exists-p x folder) collect x)))))
-
-;;;###mh-autoload
-(defun mh-search-p ()
-  "Non-nil means that this folder was generated by searching."
-  mh-index-data)
-
-;;;###mh-autoload
-(defun mh-index-execute-commands ()
-  "Delete/refile the actual messages.
-The copies in the searched folder are then deleted/refiled to get
-the desired result. Before deleting the messages we make sure
-that the message being deleted is identical to the one that the
-user has marked in the index buffer."
-  (save-excursion
-    (let ((folders ())
-          (mh-speed-flists-inhibit-flag t))
-      (maphash
-       (lambda (folder msgs)
-         (push folder folders)
-         (if (not (get-buffer folder))
-             ;; If source folder not open, just delete the messages...
-             (apply #'mh-exec-cmd "rmm" folder (mh-coalesce-msg-list msgs))
-           ;; Otherwise delete the messages in the source buffer...
-           (save-excursion
-             (set-buffer folder)
-             (let ((old-refile-list mh-refile-list)
-                   (old-delete-list mh-delete-list))
-               (setq mh-refile-list nil
-                     mh-delete-list msgs)
-               (unwind-protect (mh-execute-commands)
-                 (setq mh-refile-list
-                       (mapcar (lambda (x)
-                                 (cons (car x)
-                                       (loop for y in (cdr x)
-                                             unless (memq y msgs) collect y)))
-                               old-refile-list)
-                       mh-delete-list
-                       (loop for x in old-delete-list
-                             unless (memq x msgs) collect x))
-                 (mh-set-folder-modified-p (mh-outstanding-commands-p))
-                 (when (mh-outstanding-commands-p)
-                   (mh-notate-deleted-and-refiled)))))))
-       (mh-index-matching-source-msgs (append (loop for x in mh-refile-list
-                                                    append (cdr x))
-                                              mh-delete-list)
-                                      t))
-      folders)))
-
-
-
-;;; Indexing functions
+;;; Indexing Functions
 
 ;; Support different search programs
 (defvar mh-search-choices
@@ -930,14 +824,13 @@
             (return mh-searcher))))
       nil)))
 
-;;; Swish++ interface
+;;; Swish++
 
 (defvar mh-swish++-binary (or (executable-find "search++")
                               (executable-find "search")))
 (defvar mh-swish++-directory ".swish++")
 (defvar mh-swish-folder nil)
 
-;;;###mh-autoload
 (defun mh-swish++-execute-search (folder-path search-regexp)
   "Execute swish++.
 
@@ -1012,12 +905,11 @@
                    (symbol-name (car expr))
                    (mh-swish++-print-regexp (caddr expr))))))
 
-;;; Swish interface
+;;; Swish
 
 (defvar mh-swish-binary (executable-find "swish-e"))
 (defvar mh-swish-directory ".swish")
 
-;;;###mh-autoload
 (defun mh-swish-execute-search (folder-path search-regexp)
   "Execute swish-e.
 
@@ -1110,13 +1002,12 @@
                 nil)))
     (forward-line)))
 
-;;; Mairix interface
+;;; Mairix
 
 (defvar mh-mairix-binary (executable-find "mairix"))
 (defvar mh-mairix-directory ".mairix")
 (defvar mh-mairix-folder nil)
 
-;;;###mh-autoload
 (defun mh-mairix-execute-search (folder-path search-regexp-list)
   "Execute mairix.
 
@@ -1244,13 +1135,12 @@
                                                 (cdadr expr)))))
         (t (error "Unreachable: %s" expr))))
 
-;;; Namazu interface
+;;; Namazu
 
 (defvar mh-namazu-binary (executable-find "namazu"))
 (defvar mh-namazu-directory ".namazu")
 (defvar mh-namazu-folder nil)
 
-;;;###mh-autoload
 (defun mh-namazu-execute-search (folder-path search-regexp)
   "Execute namazu.
 
@@ -1317,14 +1207,13 @@
                   nil))))
     (forward-line)))
 
-;;; Pick interface
+;;; Pick
 
 (defvar mh-index-pick-folder)
 (defvar mh-pick-binary "pick")
 (defconst mh-pick-single-dash  '(cc date from subject to)
   "Search components that are supported by single-dash option in pick.")
 
-;;;###mh-autoload
 (defun mh-pick-execute-search (folder-path search-regexp)
   "Execute pick.
 
@@ -1408,11 +1297,10 @@
            "-rbrace"))
         (t (error "Unknown operator %s seen" (car expr)))))
 
-;;; Grep interface
+;;; Grep
 
 (defvar mh-grep-binary (executable-find "grep"))
 
-;;;###mh-autoload
 (defun mh-grep-execute-search (folder-path search-regexp)
   "Execute grep.
 
@@ -1463,7 +1351,132 @@
 
 
 
-;;; Folder support
+;;; Folder Utilities
+
+;;;###mh-autoload
+(defun mh-index-group-by-folder ()
+  "Partition the messages based on source folder.
+Returns an alist with the the folder names in the car and the cdr
+being the list of messages originally from that folder."
+  (save-excursion
+    (goto-char (point-min))
+    (let ((result-table (make-hash-table :test #'equal)))
+      (loop for msg being hash-keys of mh-index-msg-checksum-map
+            do (push msg (gethash (car (gethash
+                                        (gethash msg mh-index-msg-checksum-map)
+                                        mh-index-checksum-origin-map))
+                                  result-table)))
+      (loop for x being the hash-keys of result-table
+            collect (cons x (nreverse (gethash x result-table)))))))
+
+;;;###mh-autoload
+(defun mh-index-insert-folder-headers ()
+  "Annotate the search results with original folder names."
+  (let ((cur-msg (mh-get-msg-num nil))
+        (old-buffer-modified-flag (buffer-modified-p))
+        (buffer-read-only nil)
+        current-folder last-folder)
+    (goto-char (point-min))
+    (while (not (eobp))
+      (setq current-folder (car (gethash (gethash (mh-get-msg-num nil)
+                                                  mh-index-msg-checksum-map)
+                                         mh-index-checksum-origin-map)))
+      (when (and current-folder (not (equal current-folder last-folder)))
+        (insert (if last-folder "\n" "") current-folder "\n")
+        (setq last-folder current-folder))
+      (forward-line))
+    (when cur-msg
+      (mh-notate-cur)
+      (mh-goto-msg cur-msg t))
+    (set-buffer-modified-p old-buffer-modified-flag))
+  (mh-index-create-imenu-index))
+
+;;;###mh-autoload
+(defun mh-index-delete-folder-headers ()
+  "Delete the folder headers."
+  (let ((cur-msg (mh-get-msg-num nil))
+        (old-buffer-modified-flag (buffer-modified-p))
+        (buffer-read-only nil))
+    (while (and (not cur-msg) (not (eobp)))
+      (forward-line)
+      (setq cur-msg (mh-get-msg-num nil)))
+    (goto-char (point-min))
+    (while (not (eobp))
+      (if (or (char-equal (char-after) ?+) (char-equal (char-after) 10))
+          (delete-region (point) (progn (forward-line) (point)))
+        (forward-line)))
+    (when cur-msg (mh-goto-msg cur-msg t t))
+    (set-buffer-modified-p old-buffer-modified-flag)))
+
+;; Shush compiler.
+(eval-when-compile (mh-do-in-xemacs (defvar which-func-mode)))
+
+;;;###mh-autoload
+(defun mh-index-create-imenu-index ()
+  "Create alist of folder names and positions in index folder buffers."
+  (save-excursion
+    (if (boundp 'which-func-mode)
+        (setq which-func-mode t))
+    (let ((alist ()))
+      (goto-char (point-min))
+      (while (re-search-forward "^+" nil t)
+        (save-excursion
+          (beginning-of-line)
+          (push (cons (buffer-substring-no-properties
+                       (point) (line-end-position))
+                      (set-marker (make-marker) (point)))
+                alist)))
+      (setq imenu--index-alist (nreverse alist)))))
+
+;;;###mh-autoload
+(defun mh-search-p ()
+  "Non-nil means that this folder was generated by searching."
+  mh-index-data)
+
+;; Shush compiler
+(eval-when-compile (if mh-xemacs-flag (defvar mh-speed-flists-inhibit-flag)))
+
+;;;###mh-autoload
+(defun mh-index-execute-commands ()
+  "Delete/refile the actual messages.
+The copies in the searched folder are then deleted/refiled to get
+the desired result. Before deleting the messages we make sure
+that the message being deleted is identical to the one that the
+user has marked in the index buffer."
+  (save-excursion
+    (let ((folders ())
+          (mh-speed-flists-inhibit-flag t))
+      (maphash
+       (lambda (folder msgs)
+         (push folder folders)
+         (if (not (get-buffer folder))
+             ;; If source folder not open, just delete the messages...
+             (apply #'mh-exec-cmd "rmm" folder (mh-coalesce-msg-list msgs))
+           ;; Otherwise delete the messages in the source buffer...
+           (save-excursion
+             (set-buffer folder)
+             (let ((old-refile-list mh-refile-list)
+                   (old-delete-list mh-delete-list))
+               (setq mh-refile-list nil
+                     mh-delete-list msgs)
+               (unwind-protect (mh-execute-commands)
+                 (setq mh-refile-list
+                       (mapcar (lambda (x)
+                                 (cons (car x)
+                                       (loop for y in (cdr x)
+                                             unless (memq y msgs) collect y)))
+                               old-refile-list)
+                       mh-delete-list
+                       (loop for x in old-delete-list
+                             unless (memq x msgs) collect x))
+                 (mh-set-folder-modified-p (mh-outstanding-commands-p))
+                 (when (mh-outstanding-commands-p)
+                   (mh-notate-deleted-and-refiled)))))))
+       (mh-index-matching-source-msgs (append (loop for x in mh-refile-list
+                                                    append (cdr x))
+                                              mh-delete-list)
+                                      t))
+      folders)))
 
 (defun mh-index-generate-pretty-name (string)
   "Given STRING generate a name which is suitable for use as a folder name.
@@ -1559,7 +1572,7 @@
 
 
 
-;;; Sequence support
+;;; Sequence Support
 
 ;;;###mh-autoload
 (defun mh-index-create-sequences ()
@@ -1688,7 +1701,7 @@
 
 
 
-;;; Serialization of index data
+;;; Serialization of Index Data
 
 (defun mh-index-write-data ()
   "Write index data to file."
@@ -1756,20 +1769,21 @@
 
 
 
-;;; Checksum routines
+;;; Checksum Routines
 
-;; A few different checksum programs are supported. The supported programs
-;; are:
-;;
+;; A few different checksum programs are supported. The supported
+;; programs are:
+
 ;;   1. md5sum
 ;;   2. md5
 ;;   3. openssl
-;;
-;; To add support for your favorite checksum program add a clause to the cond
-;; statement in mh-checksum-choose. This should set the variable
-;; mh-checksum-cmd to the command line needed to run the checsum program and
-;; should set mh-checksum-parser to a function which returns a cons cell
-;; containing the message number and checksum string.
+
+;; To add support for your favorite checksum program add a clause to
+;; the cond statement in mh-checksum-choose. This should set the
+;; variable mh-checksum-cmd to the command line needed to run the
+;; checsum program and should set mh-checksum-parser to a function
+;; which returns a cons cell containing the message number and
+;; checksum string.
 
 (defvar mh-checksum-cmd)
 (defvar mh-checksum-parser)
--- a/lisp/mh-e/mh-seq.el	Thu Jan 26 02:23:05 2006 +0000
+++ b/lisp/mh-e/mh-seq.el	Wed Feb 01 10:07:17 2006 +0000
@@ -26,128 +26,89 @@
 ;; Boston, MA 02110-1301, USA.
 
 ;;; Commentary:
-;;
-;;   This tries to implement the algorithm described at:
-;;     http://www.jwz.org/doc/threading.html
-;;   It is also a start to implementing the IMAP Threading extension RFC. The
-;;   implementation lacks the reference and subject canonicalization of the
-;;   RFC.
-;;
-;;   In the presentation buffer, children messages are shown indented with
-;;   either [ ] or < > around them. Square brackets ([ ]) denote that the
-;;   algorithm can point out some headers which when taken together implies
-;;   that the unindented message is an ancestor of the indented message. If
-;;   no such proof exists then angles (< >) are used.
-;;
-;;   Some issues and problems are as follows:
-;;
-;;    (1) Scan truncates the fields at length 512. So longer references:
-;;        headers get mutilated. The same kind of MH format string works when
-;;        composing messages. Is there a way to avoid this? My scan command
-;;        is as follows:
-;;          scan +folder -width 10000 \
-;;               -format "%(msg)\n%{message-id}\n%{references}\n%{subject}\n"
-;;        I would really appreciate it if someone would help me with this.
-;;
-;;    (2) Implement heuristics to recognize message identifiers in
-;;        In-Reply-To: header. Right now it just assumes that the last text
-;;        between angles (< and >) is the message identifier. There is the
-;;        chance that this will incorrectly use an email address like a
-;;        message identifier.
-;;
-;;    (3) Error checking of found message identifiers should be done.
-;;
-;;    (4) Since this breaks the assumption that message indices increase as
-;;        one goes down the buffer, the binary search based mh-goto-msg
-;;        doesn't work. I have a simpler replacement which may be less
-;;        efficient.
-;;
-;;    (5) Better canonicalizing for message identifier and subject strings.
-;;
 
-;; Internal support for MH-E package.
+;; Sequences are stored in the alist `mh-seq-list' in the form:
+;;     ((seq-name msgs ...) (seq-name msgs ...) ...)
 
 ;;; Change Log:
 
 ;;; Code:
 
-;;(message "> mh-seq")
-(eval-when-compile (require 'mh-acros))
+(require 'mh-e)
 (mh-require-cl)
-
-(require 'mh-buffers)
-(require 'mh-e)
-;;(message "< mh-seq")
-
-
-
-;;; Data structures (used in message threading)...
+(require 'mh-scan)
 
-(mh-defstruct (mh-thread-message (:conc-name mh-message-)
-                                 (:constructor mh-thread-make-message))
-  (id nil)
-  (references ())
-  (subject "")
-  (subject-re-p nil))
+(require 'font-lock)
 
-(mh-defstruct (mh-thread-container (:conc-name mh-container-)
-                                   (:constructor mh-thread-make-container))
-  message parent children
-  (real-child-p t))
-
-
-
-;;; Internal variables:
+;;; Variables
 
 (defvar mh-last-seq-used nil
   "Name of seq to which a msg was last added.")
 
 (defvar mh-non-seq-mode-line-annotation nil
   "Saved value of `mh-mode-line-annotation' when narrowed to a seq.")
+(make-variable-buffer-local 'mh-non-seq-mode-line-annotation)
+
+(defvar mh-internal-seqs '(answered cur deleted forwarded printed))
+
+;;; Macros
+
+(defmacro mh-make-seq (name msgs)
+  "Create sequence NAME with the given MSGS."
+  (list 'cons name msgs))
+
+(defmacro mh-seq-name (sequence)
+  "Extract sequence name from the given SEQUENCE."
+  (list 'car sequence))
 
 
 
-;;; Maps and hashes...
+;;; MH-Folder Commands
+
+;; Alphabetical.
+
+;;;###mh-autoload
+(defun mh-catchup (range)
+  "Delete RANGE from the \"unseen\" sequence.
+
+Check the documentation of `mh-interactive-range' to see how
+RANGE is read in interactive use."
+  (interactive (list (mh-interactive-range "Catchup"
+                                           (cons (point-min) (point-max)))))
+  (mh-delete-msg-from-seq range mh-unseen-seq))
+
+;;;###mh-autoload
+(defun mh-delete-msg-from-seq (range sequence &optional internal-flag)
+  "Delete RANGE from SEQUENCE.
+
+Check the documentation of `mh-interactive-range' to see how
+RANGE is read in interactive use.
 
-(defvar mh-thread-id-hash nil
-  "Hashtable used to canonicalize message identifiers.")
-(defvar mh-thread-subject-hash nil
-  "Hashtable used to canonicalize subject strings.")
-(defvar mh-thread-id-table nil
-  "Thread ID table maps from message identifiers to message containers.")
-(defvar mh-thread-id-index-map nil
-  "Table to look up message index number from message identifier.")
-(defvar mh-thread-index-id-map nil
-  "Table to look up message identifier from message index.")
-(defvar mh-thread-scan-line-map nil
-  "Map of message index to various parts of the scan line.")
-(defvar mh-thread-scan-line-map-stack nil
-  "Old map of message index to various parts of the scan line.
-This is the original map that is stored when the folder is
-narrowed.")
-(defvar mh-thread-subject-container-hash nil
-  "Hashtable used to group messages by subject.")
-(defvar mh-thread-duplicates nil
-  "Hashtable used to associate messages with the same message identifier.")
-(defvar mh-thread-history ()
-  "Variable to remember the transformations to the thread tree.
-When new messages are added, these transformations are rewound,
-then the links are added from the newly seen messages. Finally
-the transformations are redone to get the new thread tree. This
-makes incremental threading easier.")
-(defvar mh-thread-body-width nil
-  "Width of scan substring that contains subject and body of message.")
-
-(make-variable-buffer-local 'mh-thread-id-hash)
-(make-variable-buffer-local 'mh-thread-subject-hash)
-(make-variable-buffer-local 'mh-thread-id-table)
-(make-variable-buffer-local 'mh-thread-id-index-map)
-(make-variable-buffer-local 'mh-thread-index-id-map)
-(make-variable-buffer-local 'mh-thread-scan-line-map)
-(make-variable-buffer-local 'mh-thread-scan-line-map-stack)
-(make-variable-buffer-local 'mh-thread-subject-container-hash)
-(make-variable-buffer-local 'mh-thread-duplicates)
-(make-variable-buffer-local 'mh-thread-history)
+In a program, non-nil INTERNAL-FLAG means do not inform MH of the
+change."
+  (interactive (list (mh-interactive-range "Delete")
+                     (mh-read-seq-default "Delete from" t)
+                     nil))
+  (let ((entry (mh-find-seq sequence))
+        (user-sequence-flag (not (mh-internal-seq sequence)))
+        (folders-changed (list mh-current-folder))
+        (msg-list ()))
+    (when entry
+      (mh-iterate-on-range msg range
+        (push msg msg-list)
+        ;; Calling "mark" repeatedly takes too long. So we will pretend here
+        ;; that we are just modifying an internal sequence...
+        (when (memq msg (cdr entry))
+          (mh-remove-sequence-notation msg (not user-sequence-flag)))
+        (mh-delete-a-msg-from-seq msg sequence t))
+      ;; ... and here we will "mark" all the messages at one go.
+      (unless internal-flag (mh-undefine-sequence sequence msg-list))
+      (when (and mh-index-data (not internal-flag))
+        (setq folders-changed
+              (append folders-changed
+                      (mh-index-delete-from-sequence sequence msg-list))))
+      (when (and (eq sequence mh-unseen-seq) (mh-speed-flists-active-p))
+        (apply #'mh-speed-flists t folders-changed)))))
 
 ;;;###mh-autoload
 (defun mh-delete-seq (sequence)
@@ -240,12 +201,8 @@
                         (mh-list-to-string (mh-seq-containing-msg message t))
                         " "))))
 
-;; Shush compiler
-(eval-when-compile
-  (defvar tool-bar-map)
-  (defvar tool-bar-mode))
-
-(make-variable-buffer-local 'mh-non-seq-mode-line-annotation)
+;; Shush compiler.
+(eval-when-compile (mh-do-in-xemacs (defvar tool-bar-mode)))
 
 ;;;###mh-autoload
 (defun mh-narrow-to-seq (sequence)
@@ -290,6 +247,23 @@
            (error "No messages in sequence %s" (symbol-name sequence))))))
 
 ;;;###mh-autoload
+(defun mh-narrow-to-tick ()
+  "Limit to ticked messages.
+
+What this command does is show only those messages that are in
+the \"tick\" sequence (which you can customize via the
+`mh-tick-seq' option) in the MH-Folder buffer. In addition, it
+limits further MH-E searches to just those messages. When you
+want to widen the view to all your messages again, use
+\\[mh-widen]."
+  (interactive)
+  (cond ((not mh-tick-seq)
+         (error "Enable ticking by customizing `mh-tick-seq'"))
+        ((null (mh-seq-msgs (mh-find-seq mh-tick-seq)))
+         (message "No messages in %s sequence" mh-tick-seq))
+        (t (mh-narrow-to-seq mh-tick-seq))))
+
+;;;###mh-autoload
 (defun mh-put-msg-in-seq (range sequence)
   "Add RANGE to SEQUENCE\\<mh-folder-mode-map>.
 
@@ -319,12 +293,39 @@
     (when (and (eq sequence mh-unseen-seq) (mh-speed-flists-active-p))
       (apply #'mh-speed-flists t folders))))
 
-(defun mh-valid-view-change-operation-p (op)
-  "Check if the view change operation can be performed.
-OP is one of 'widen and 'unthread."
-  (cond ((eq (car mh-view-ops) op)
-         (pop mh-view-ops))
-        (t nil)))
+;;;###mh-autoload
+(defun mh-toggle-tick (range)
+  "Toggle tick mark of RANGE.
+
+This command adds messages to the \"tick\" sequence (which you can customize
+via the option `mh-tick-seq'). This sequence can be viewed later with the
+\\[mh-index-ticked-messages] command.
+
+Check the documentation of `mh-interactive-range' to see how RANGE is read in
+interactive use."
+  (interactive (list (mh-interactive-range "Tick")))
+  (unless mh-tick-seq
+    (error "Enable ticking by customizing `mh-tick-seq'"))
+  (let* ((tick-seq (mh-find-seq mh-tick-seq))
+         (tick-seq-msgs (mh-seq-msgs tick-seq))
+         (ticked ())
+         (unticked ()))
+    (mh-iterate-on-range msg range
+      (cond ((member msg tick-seq-msgs)
+             (push msg unticked)
+             (setcdr tick-seq (delq msg (cdr tick-seq)))
+             (when (null (cdr tick-seq)) (setq mh-last-seq-used nil))
+             (mh-remove-sequence-notation msg (mh-colors-in-use-p)))
+            (t
+             (push msg ticked)
+             (setq mh-last-seq-used mh-tick-seq)
+             (let ((mh-seq-list (cons `(,mh-tick-seq ,msg) mh-seq-list)))
+               (mh-add-sequence-notation msg (mh-colors-in-use-p))))))
+    (mh-add-msgs-to-seq ticked mh-tick-seq nil t)
+    (mh-undefine-sequence mh-tick-seq unticked)
+    (when mh-index-data
+      (mh-index-add-to-sequence mh-tick-seq ticked)
+      (mh-index-delete-from-sequence mh-tick-seq unticked))))
 
 ;;;###mh-autoload
 (defun mh-widen (&optional all-flag)
@@ -374,32 +375,9 @@
         (set-buffer (get-buffer mh-show-buffer))
         (set (make-local-variable 'tool-bar-map) mh-show-tool-bar-map)))))
 
-;; FIXME?  We may want to clear all notations and add one for current-message
-;;         and process user sequences.
-;;;###mh-autoload
-(defun mh-notate-deleted-and-refiled ()
-  "Notate messages marked for deletion or refiling.
-Messages to be deleted are given by `mh-delete-list' while
-messages to be refiled are present in `mh-refile-list'."
-  (let ((refiled-hash (make-hash-table))
-        (deleted-hash (make-hash-table)))
-    (dolist (msg mh-delete-list)
-      (setf (gethash msg deleted-hash) t))
-    (dolist (dest-msg-list mh-refile-list)
-      (dolist (msg (cdr dest-msg-list))
-        (setf (gethash msg refiled-hash) t)))
-    (mh-iterate-on-messages-in-region msg (point-min) (point-max)
-      (cond ((gethash msg refiled-hash)
-             (mh-notate nil mh-note-refiled mh-cmd-note))
-            ((gethash msg deleted-hash)
-             (mh-notate nil mh-note-deleted mh-cmd-note))))))
-
 
 
-;;; Commands to manipulate sequences.
-
-;; Sequences are stored in an alist of the form:
-;;     ((seq-name msgs ...) (seq-name msgs ...) ...)
+;;; Support Routines
 
 (defvar mh-sequence-history ())
 
@@ -433,38 +411,192 @@
         (error "No messages in sequence %s" seq))
     seq))
 
+(defun mh-internal-seq (name)
+  "Return non-nil if NAME is the name of an internal MH-E sequence."
+  (or (memq name mh-internal-seqs)
+      (eq name mh-unseen-seq)
+      (and (mh-colors-in-use-p) mh-tick-seq (eq name mh-tick-seq))
+      (eq name mh-previous-seq)
+      (mh-folder-name-p name)))
+
+;;;###mh-autoload
+(defun mh-valid-seq-p (name)
+  "Return non-nil if NAME is a valid MH sequence name."
+  (and (symbolp name)
+       (string-match "^[a-zA-Z][a-zA-Z0-9]*$" (symbol-name name))))
+
+;;;###mh-autoload
+(defun mh-find-seq (name)
+  "Return sequence NAME."
+  (assoc name mh-seq-list))
+
+;;;###mh-autoload
+(defun mh-seq-to-msgs (seq)
+  "Return a list of the messages in SEQ."
+  (mh-seq-msgs (mh-find-seq seq)))
+
+(defun mh-seq-containing-msg (msg &optional include-internal-flag)
+  "Return a list of the sequences containing MSG.
+If INCLUDE-INTERNAL-FLAG non-nil, include MH-E internal sequences
+in list."
+  (let ((l mh-seq-list)
+        (seqs ()))
+    (while l
+      (and (memq msg (mh-seq-msgs (car l)))
+           (or include-internal-flag
+               (not (mh-internal-seq (mh-seq-name (car l)))))
+           (setq seqs (cons (mh-seq-name (car l)) seqs)))
+      (setq l (cdr l)))
+    seqs))
+
+;;;###mh-autoload
+(defun mh-define-sequence (seq msgs)
+  "Define the SEQ to contain the list of MSGS.
+Do not mark pseudo-sequences or empty sequences.
+Signals an error if SEQ is an invalid name."
+  (if (and msgs
+           (mh-valid-seq-p seq)
+           (not (mh-folder-name-p seq)))
+      (save-excursion
+        (mh-exec-cmd-error nil "mark" mh-current-folder "-add" "-zero"
+                           "-sequence" (symbol-name seq)
+                           (mh-coalesce-msg-list msgs)))))
+
+;;;###mh-autoload
+(defun mh-undefine-sequence (seq msgs)
+  "Remove from the SEQ the list of MSGS."
+  (when (and (mh-valid-seq-p seq) msgs)
+    (apply #'mh-exec-cmd "mark" mh-current-folder "-delete"
+           "-sequence" (symbol-name seq) (mh-coalesce-msg-list msgs))))
+
+;;;###mh-autoload
+(defun mh-add-msgs-to-seq (msgs seq &optional internal-flag dont-annotate-flag)
+  "Add MSGS to SEQ.
+
+Remove duplicates and keep sequence sorted. If optional
+INTERNAL-FLAG is non-nil, do not mark the message in the scan
+listing or inform MH of the addition.
+
+If DONT-ANNOTATE-FLAG is non-nil then the annotations in the
+folder buffer are not updated."
+  (let ((entry (mh-find-seq seq))
+        (internal-seq-flag (mh-internal-seq seq)))
+    (if (and msgs (atom msgs)) (setq msgs (list msgs)))
+    (if (null entry)
+        (setq mh-seq-list
+              (cons (mh-make-seq seq (mh-canonicalize-sequence msgs))
+                    mh-seq-list))
+      (if msgs (setcdr entry (mh-canonicalize-sequence
+                              (append msgs (mh-seq-msgs entry))))))
+    (unless internal-flag
+      (mh-add-to-sequence seq msgs)
+      (when (not dont-annotate-flag)
+        (mh-iterate-on-range msg msgs
+          (unless (memq msg (cdr entry))
+            (mh-add-sequence-notation msg internal-seq-flag)))))))
+
+(defun mh-add-to-sequence (seq msgs)
+  "The sequence SEQ is augmented with the messages in MSGS."
+  ;; Add to a SEQUENCE each message the list of MSGS.
+  (if (and (mh-valid-seq-p seq) (not (mh-folder-name-p seq)))
+      (if msgs
+          (apply 'mh-exec-cmd "mark" mh-current-folder "-add"
+                 "-sequence" (symbol-name seq)
+                 (mh-coalesce-msg-list msgs)))))
+
+(defun mh-canonicalize-sequence (msgs)
+  "Sort MSGS in decreasing order and remove duplicates."
+  (let* ((sorted-msgs (sort (copy-sequence msgs) '>))
+         (head sorted-msgs))
+    (while (cdr head)
+      (if (= (car head) (cadr head))
+          (setcdr head (cddr head))
+        (setq head (cdr head))))
+    sorted-msgs))
+
+(defun mh-delete-a-msg-from-seq (msg sequence internal-flag)
+  "Delete MSG from SEQUENCE.
+If INTERNAL-FLAG is non-nil, then do not inform MH of the
+change."
+  (let ((entry (mh-find-seq sequence)))
+    (when (and entry (memq msg (mh-seq-msgs entry)))
+      (if (not internal-flag)
+          (mh-undefine-sequence sequence (list msg)))
+      (setcdr entry (delq msg (mh-seq-msgs entry))))))
+
+(defun mh-delete-seq-locally (seq)
+  "Remove MH-E's record of SEQ."
+  (let ((entry (mh-find-seq seq)))
+    (setq mh-seq-list (delq entry mh-seq-list))))
+
+(defun mh-copy-seq-to-eob (seq)
+  "Copy SEQ to the end of the buffer."
+  ;; It is quite involved to write something which will work at any place in
+  ;; the buffer, so we will write something which works only at the end of
+  ;; the buffer. If we ever need to insert sequences in the middle of the
+  ;; buffer, this will need to be fixed.
+  (save-excursion
+    (let* ((msgs (mh-seq-to-msgs seq))
+           (coalesced-msgs (mh-coalesce-msg-list msgs)))
+      (goto-char (point-max))
+      (save-restriction
+        (narrow-to-region (point) (point))
+        (mh-regenerate-headers coalesced-msgs t)
+        (cond ((memq 'unthread mh-view-ops)
+               ;; Populate restricted scan-line map
+               (mh-remove-all-notation)
+               (mh-iterate-on-range msg (cons (point-min) (point-max))
+                 (setf (gethash msg mh-thread-scan-line-map)
+                       (mh-thread-parse-scan-line)))
+               ;; Remove scan lines and read results from pre-computed tree
+               (delete-region (point-min) (point-max))
+               (mh-thread-print-scan-lines
+                (mh-thread-generate mh-current-folder ()))
+               (mh-notate-user-sequences))
+              (mh-index-data
+               (mh-index-insert-folder-headers)))))))
+
+;;;###mh-autoload
+(defun mh-valid-view-change-operation-p (op)
+  "Check if the view change operation can be performed.
+OP is one of 'widen and 'unthread."
+  (cond ((eq (car mh-view-ops) op)
+         (pop mh-view-ops))
+        (t nil)))
+
 
 
-;;; Functions to read ranges with completion...
+;;; Ranges
 
 (defvar mh-range-seq-names)
 (defvar mh-range-history ())
 (defvar mh-range-completion-map (copy-keymap minibuffer-local-completion-map))
 (define-key mh-range-completion-map " " 'self-insert-command)
 
-(defun mh-range-completion-function (string predicate flag)
-  "Programmable completion of message ranges.
-STRING is the user input that is to be completed. PREDICATE if non-nil is a
-function used to filter the possible choices and FLAG determines whether the
-completion is over."
-  (let* ((candidates mh-range-seq-names)
-         (last-char (and (not (equal string ""))
-                         (aref string (1- (length string)))))
-         (last-word (cond ((null last-char) "")
-                          ((memq last-char '(?  ?- ?:)) "")
-                          (t (car (last (split-string string "[ -:]+"))))))
-         (prefix (substring string 0 (- (length string) (length last-word)))))
-    (cond ((eq flag nil)
-           (let ((res (try-completion last-word candidates predicate)))
-             (cond ((null res) nil)
-                   ((eq res t) t)
-                   (t (concat prefix res)))))
-          ((eq flag t)
-           (all-completions last-word candidates predicate))
-          ((eq flag 'lambda)
-           (loop for x in candidates
-                 when (equal x last-word) return t
-                 finally return nil)))))
+;;;###mh-autoload
+(defun mh-interactive-range (range-prompt &optional default)
+  "Return interactive specification for message, sequence, range or region.
+By convention, the name of this argument is RANGE.
+
+If variable `transient-mark-mode' is non-nil and the mark is active,
+then this function returns a cons-cell of the region.
+
+If optional prefix argument is provided, then prompt for message range
+with RANGE-PROMPT. A list of messages in that range is returned.
+
+If a MH range is given, say something like last:20, then a list
+containing the messages in that range is returned.
+
+If DEFAULT non-nil then it is returned.
+
+Otherwise, the message number at point is returned.
+
+This function is usually used with `mh-iterate-on-range' in order to
+provide a uniform interface to MH-E functions."
+  (cond ((mh-mark-active-p t) (cons (region-beginning) (region-end)))
+        (current-prefix-arg (mh-read-range range-prompt nil nil t t))
+        (default default)
+        (t (mh-get-msg-num t))))
 
 ;;;###mh-autoload
 (defun mh-read-range (prompt &optional folder default
@@ -550,6 +682,17 @@
           (t (error "No messages in range %s" input)))))
 
 ;;;###mh-autoload
+(defun mh-range-to-msg-list (range)
+  "Return a list of messages for RANGE.
+
+Check the documentation of `mh-interactive-range' to see how
+RANGE is read in interactive use."
+  (let (msg-list)
+    (mh-iterate-on-range msg range
+      (push msg msg-list))
+    (nreverse msg-list)))
+
+;;;###mh-autoload
 (defun mh-translate-range (folder expr)
   "In FOLDER, translate the string EXPR to a list of messages numbers."
   (save-excursion
@@ -563,23 +706,177 @@
           (push (string-to-number (match-string 1)) result))
         (nreverse result)))))
 
+(defun mh-range-completion-function (string predicate flag)
+  "Programmable completion of message ranges.
+STRING is the user input that is to be completed. PREDICATE if non-nil is a
+function used to filter the possible choices and FLAG determines whether the
+completion is over."
+  (let* ((candidates mh-range-seq-names)
+         (last-char (and (not (equal string ""))
+                         (aref string (1- (length string)))))
+         (last-word (cond ((null last-char) "")
+                          ((memq last-char '(?  ?- ?:)) "")
+                          (t (car (last (split-string string "[ -:]+"))))))
+         (prefix (substring string 0 (- (length string) (length last-word)))))
+    (cond ((eq flag nil)
+           (let ((res (try-completion last-word candidates predicate)))
+             (cond ((null res) nil)
+                   ((eq res t) t)
+                   (t (concat prefix res)))))
+          ((eq flag t)
+           (all-completions last-word candidates predicate))
+          ((eq flag 'lambda)
+           (loop for x in candidates
+                 when (equal x last-word) return t
+                 finally return nil)))))
+
 (defun mh-seq-names (seq-list)
   "Return an alist containing the names of the SEQ-LIST."
   (mapcar (lambda (entry) (list (symbol-name (mh-seq-name entry))))
           seq-list))
 
+(defun mh-folder-size (folder)
+  "Find size of FOLDER."
+  (if mh-flists-present-flag
+      (mh-folder-size-flist folder)
+    (mh-folder-size-folder folder)))
+
+(defun mh-folder-size-flist (folder)
+  "Find size of FOLDER using \"flist\"."
+  (with-temp-buffer
+    (call-process (expand-file-name "flist" mh-progs) nil t nil "-showzero"
+                  "-norecurse" folder "-sequence" (symbol-name mh-unseen-seq))
+    (goto-char (point-min))
+    (multiple-value-bind (folder unseen total)
+        (mh-parse-flist-output-line
+         (buffer-substring (point) (line-end-position)))
+      (values total unseen folder))))
+
+(defun mh-folder-size-folder (folder)
+  "Find size of FOLDER using \"folder\"."
+  (with-temp-buffer
+    (let ((u (length (cdr (assoc mh-unseen-seq
+                                 (mh-read-folder-sequences folder nil))))))
+      (call-process (expand-file-name "folder" mh-progs) nil t nil
+                    "-norecurse" folder)
+      (goto-char (point-min))
+      (if (re-search-forward " has \\([0-9]+\\) " nil t)
+          (values (string-to-number (match-string 1)) u folder)
+        (values 0 u folder)))))
+
 ;;;###mh-autoload
-(defun mh-rename-seq (sequence new-name)
-  "Rename SEQUENCE to have NEW-NAME."
-  (interactive (list (mh-read-seq "Old" t)
-                     (intern (read-string "New sequence name: "))))
-  (let ((old-seq (mh-find-seq sequence)))
-    (or old-seq
-        (error "Sequence %s does not exist" sequence))
-    ;; create new sequence first, since it might raise an error.
-    (mh-define-sequence new-name (mh-seq-msgs old-seq))
-    (mh-undefine-sequence sequence (mh-seq-msgs old-seq))
-    (rplaca old-seq new-name)))
+(defun mh-parse-flist-output-line (line &optional current-folder)
+  "Parse LINE to generate folder name, unseen messages and total messages.
+If CURRENT-FOLDER is non-nil then it contains the current folder
+name and it is used to avoid problems in corner cases involving
+folders whose names end with a '+' character."
+  (with-temp-buffer
+    (insert line)
+    (goto-char (point-max))
+    (let (folder unseen total p)
+      (when (search-backward " out of " (point-min) t)
+        (setq total (string-to-number
+                     (buffer-substring-no-properties
+                      (match-end 0) (line-end-position))))
+        (when (search-backward " in sequence " (point-min) t)
+          (setq p (point))
+          (when (search-backward " has " (point-min) t)
+            (setq unseen (string-to-number (buffer-substring-no-properties
+                                            (match-end 0) p)))
+            (while (eq (char-after) ? )
+              (backward-char))
+            (setq folder (buffer-substring-no-properties
+                          (point-min) (1+ (point))))
+            (when (and (equal (aref folder (1- (length folder))) ?+)
+                       (equal current-folder folder))
+              (setq folder (substring folder 0 (1- (length folder)))))
+            (values (format "+%s" folder) unseen total)))))))
+
+;;;###mh-autoload
+(defun mh-read-folder-sequences (folder save-refiles)
+  "Read and return the predefined sequences for a FOLDER.
+If SAVE-REFILES is non-nil, then keep the sequences
+that note messages to be refiled."
+  (let ((seqs ()))
+    (cond (save-refiles
+           (mh-mapc (function (lambda (seq) ; Save the refiling sequences
+                                (if (mh-folder-name-p (mh-seq-name seq))
+                                    (setq seqs (cons seq seqs)))))
+                    mh-seq-list)))
+    (save-excursion
+      (if (eq 0 (mh-exec-cmd-quiet nil "mark" folder "-list"))
+          (progn
+            ;; look for name in line of form "cur: 4" or "myseq (private): 23"
+            (while (re-search-forward "^[^: ]+" nil t)
+              (setq seqs (cons (mh-make-seq (intern (buffer-substring
+                                                     (match-beginning 0)
+                                                     (match-end 0)))
+                                            (mh-read-msg-list))
+                               seqs)))
+            (delete-region (point-min) (point))))) ; avoid race with
+                                        ; mh-process-daemon
+    seqs))
+
+(defun mh-read-msg-list ()
+  "Return a list of message numbers from point to the end of the line.
+Expands ranges into set of individual numbers."
+  (let ((msgs ())
+        (end-of-line (save-excursion (end-of-line) (point)))
+        num)
+    (while (re-search-forward "[0-9]+" end-of-line t)
+      (setq num (string-to-number (buffer-substring (match-beginning 0)
+                                                    (match-end 0))))
+      (cond ((looking-at "-")           ; Message range
+             (forward-char 1)
+             (re-search-forward "[0-9]+" end-of-line t)
+             (let ((num2 (string-to-number
+                          (buffer-substring (match-beginning 0)
+                                            (match-end 0)))))
+               (if (< num2 num)
+                   (error "Bad message range: %d-%d" num num2))
+               (while (<= num num2)
+                 (setq msgs (cons num msgs))
+                 (setq num (1+ num)))))
+            ((not (zerop num))          ;"pick" outputs "0" to mean no match
+             (setq msgs (cons num msgs)))))
+    msgs))
+
+
+
+;;; Notation
+
+;;;###mh-autoload
+(defun mh-notate (msg notation offset)
+  "Mark MSG with the character NOTATION at position OFFSET.
+Null MSG means the message at cursor.
+If NOTATION is nil then no change in the buffer occurs."
+  (save-excursion
+    (if (or (null msg)
+            (mh-goto-msg msg t t))
+        (with-mh-folder-updating (t)
+          (beginning-of-line)
+          (forward-char offset)
+          (let* ((change-stack-flag
+                  (and (equal offset
+                              (+ mh-cmd-note mh-scan-field-destination-offset))
+                       (not (eq notation mh-note-seq))))
+                 (msg (and change-stack-flag (or msg (mh-get-msg-num nil))))
+                 (stack (and msg (gethash msg mh-sequence-notation-history)))
+                 (notation (or notation (char-after))))
+            (if stack
+                ;; The presence of the stack tells us that we don't need to
+                ;; notate the message, since the notation would be replaced
+                ;; by a sequence notation. So we will just put the notation
+                ;; at the bottom of the stack. If the sequence is deleted,
+                ;; the correct notation will be shown.
+                (setf (gethash msg mh-sequence-notation-history)
+                      (reverse (cons notation (cdr (reverse stack)))))
+              ;; Since we don't have any sequence notations in the way, just
+              ;; notate the scan line.
+              (delete-char 1)
+              (insert notation))
+            (when change-stack-flag
+              (mh-thread-update-scan-line-map msg notation offset)))))))
 
 ;;;###mh-autoload
 (defun mh-notate-cur ()
@@ -596,1207 +893,124 @@
       (setq overlay-arrow-position mh-arrow-marker))))
 
 ;;;###mh-autoload
-(defun mh-add-to-sequence (seq msgs)
-  "The sequence SEQ is augmented with the messages in MSGS."
-  ;; Add to a SEQUENCE each message the list of MSGS.
-  (if (and (mh-valid-seq-p seq) (not (mh-folder-name-p seq)))
-      (if msgs
-          (apply 'mh-exec-cmd "mark" mh-current-folder "-add"
-                 "-sequence" (symbol-name seq)
-                 (mh-coalesce-msg-list msgs)))))
-
-(defvar mh-thread-last-ancestor)
-
-(defun mh-copy-seq-to-eob (seq)
-  "Copy SEQ to the end of the buffer."
-  ;; It is quite involved to write something which will work at any place in
-  ;; the buffer, so we will write something which works only at the end of
-  ;; the buffer. If we ever need to insert sequences in the middle of the
-  ;; buffer, this will need to be fixed.
-  (save-excursion
-    (let* ((msgs (mh-seq-to-msgs seq))
-           (coalesced-msgs (mh-coalesce-msg-list msgs)))
-      (goto-char (point-max))
-      (save-restriction
-        (narrow-to-region (point) (point))
-        (mh-regenerate-headers coalesced-msgs t)
-        (cond ((memq 'unthread mh-view-ops)
-               ;; Populate restricted scan-line map
-               (mh-remove-all-notation)
-               (mh-iterate-on-range msg (cons (point-min) (point-max))
-                 (setf (gethash msg mh-thread-scan-line-map)
-                       (mh-thread-parse-scan-line)))
-               ;; Remove scan lines and read results from pre-computed tree
-               (delete-region (point-min) (point-max))
-               (mh-thread-print-scan-lines
-                (mh-thread-generate mh-current-folder ()))
-               (mh-notate-user-sequences))
-              (mh-index-data
-               (mh-index-insert-folder-headers)))))))
-
-;;;###mh-autoload
-(defmacro mh-iterate-on-messages-in-region (var begin end &rest body)
-  "Iterate over region.
-
-VAR is bound to the message on the current line as we loop
-starting from BEGIN till END. In each step BODY is executed.
+(defun mh-remove-cur-notation ()
+  "Remove old cur notation."
+  (let ((cur-msg (car (mh-seq-to-msgs 'cur))))
+    (save-excursion
+      (when (and cur-msg
+                 (mh-goto-msg cur-msg t t)
+                 (looking-at mh-scan-cur-msg-number-regexp))
+        (mh-notate nil ?  mh-cmd-note)
+        (setq overlay-arrow-position nil)))))
 
-If VAR is nil then the loop is executed without any binding."
-  (unless (symbolp var)
-    (error "Can not bind the non-symbol %s" var))
-  (let ((binding-needed-flag var))
-    `(save-excursion
-       (goto-char ,begin)
-       (beginning-of-line)
-       (while (and (<= (point) ,end) (not (eobp)))
-         (when (looking-at mh-scan-valid-regexp)
-           (let ,(if binding-needed-flag `((,var (mh-get-msg-num t))) ())
-             ,@body))
-         (forward-line 1)))))
-
-(put 'mh-iterate-on-messages-in-region 'lisp-indent-hook 'defun)
-
+;; FIXME?  We may want to clear all notations and add one for current-message
+;;         and process user sequences.
 ;;;###mh-autoload
-(defmacro mh-iterate-on-range (var range &rest body)
-  "Iterate an operation over a region or sequence.
-
-VAR is bound to each message in turn in a loop over RANGE, which
-can be a message number, a list of message numbers, a sequence, a
-region in a cons cell, or a MH range (something like last:20) in
-a string. In each iteration, BODY is executed.
-
-The parameter RANGE is usually created with
-`mh-interactive-range' in order to provide a uniform interface to
-MH-E functions."
-  (unless (symbolp var)
-    (error "Can not bind the non-symbol %s" var))
-  (let ((binding-needed-flag var)
-        (msgs (make-symbol "msgs"))
-        (seq-hash-table (make-symbol "seq-hash-table")))
-    `(cond ((numberp ,range)
-            (when (mh-goto-msg ,range t t)
-              (let ,(if binding-needed-flag `((,var ,range)) ())
-                ,@body)))
-           ((and (consp ,range)
-                 (numberp (car ,range)) (numberp (cdr ,range)))
-            (mh-iterate-on-messages-in-region ,var
-              (car ,range) (cdr ,range)
-              ,@body))
-           (t (let ((,msgs (cond ((and ,range (symbolp ,range))
-                                  (mh-seq-to-msgs ,range))
-                                 ((stringp ,range)
-                                  (mh-translate-range mh-current-folder
-                                                      ,range))
-                                 (t ,range)))
-                    (,seq-hash-table (make-hash-table)))
-                (dolist (msg ,msgs)
-                  (setf (gethash msg ,seq-hash-table) t))
-                (mh-iterate-on-messages-in-region v (point-min) (point-max)
-                  (when (gethash v ,seq-hash-table)
-                    (let ,(if binding-needed-flag `((,var v)) ())
-                      ,@body))))))))
-
-(put 'mh-iterate-on-range 'lisp-indent-hook 'defun)
-
-;;;###mh-autoload
-(defun mh-range-to-msg-list (range)
-  "Return a list of messages for RANGE.
-
-Check the documentation of `mh-interactive-range' to see how
-RANGE is read in interactive use."
-  (let (msg-list)
-    (mh-iterate-on-range msg range
-      (push msg msg-list))
-    (nreverse msg-list)))
+(defun mh-notate-deleted-and-refiled ()
+  "Notate messages marked for deletion or refiling.
+Messages to be deleted are given by `mh-delete-list' while
+messages to be refiled are present in `mh-refile-list'."
+  (let ((refiled-hash (make-hash-table))
+        (deleted-hash (make-hash-table)))
+    (dolist (msg mh-delete-list)
+      (setf (gethash msg deleted-hash) t))
+    (dolist (dest-msg-list mh-refile-list)
+      (dolist (msg (cdr dest-msg-list))
+        (setf (gethash msg refiled-hash) t)))
+    (mh-iterate-on-messages-in-region msg (point-min) (point-max)
+      (cond ((gethash msg refiled-hash)
+             (mh-notate nil mh-note-refiled mh-cmd-note))
+            ((gethash msg deleted-hash)
+             (mh-notate nil mh-note-deleted mh-cmd-note))))))
 
 ;;;###mh-autoload
-(defun mh-interactive-range (range-prompt &optional default)
-  "Return interactive specification for message, sequence, range or region.
-By convention, the name of this argument is RANGE.
-
-If variable `transient-mark-mode' is non-nil and the mark is active,
-then this function returns a cons-cell of the region.
-
-If optional prefix argument is provided, then prompt for message range
-with RANGE-PROMPT. A list of messages in that range is returned.
-
-If a MH range is given, say something like last:20, then a list
-containing the messages in that range is returned.
-
-If DEFAULT non-nil then it is returned.
-
-Otherwise, the message number at point is returned.
-
-This function is usually used with `mh-iterate-on-range' in order to
-provide a uniform interface to MH-E functions."
-  (cond ((mh-mark-active-p t) (cons (region-beginning) (region-end)))
-        (current-prefix-arg (mh-read-range range-prompt nil nil t t))
-        (default default)
-        (t (mh-get-msg-num t))))
-
-
-
-;;; Commands to handle new 'subject sequence ("Poor man's threading" by psg)
+(defun mh-notate-user-sequences (&optional range)
+  "Mark user-defined sequences in RANGE.
 
-;; XXX: The function mh-subject-to-sequence-unthreaded uses the magic number
-;;  41 for the max size of the subject part. Avoiding this would be desirable.
-(defun mh-subject-to-sequence (all)
-  "Put all following messages with same subject in sequence 'subject.
-If arg ALL is t, move to beginning of folder buffer to collect all
-messages.
-If arg ALL is nil, collect only messages fron current one on forward.
-
-Return number of messages put in the sequence:
-
- nil -> there was no subject line.
-
- 0   -> there were no later messages with the same
-        subject (sequence not made)
-
- >1  -> the total number of messages including current one."
-  (if (memq 'unthread mh-view-ops)
-      (mh-subject-to-sequence-threaded all)
-    (mh-subject-to-sequence-unthreaded all)))
-
-(defun mh-subject-to-sequence-unthreaded (all)
-  "Put all following messages with same subject in sequence 'subject.
-
-This function only works with an unthreaded folder. If arg ALL is
-t, move to beginning of folder buffer to collect all messages. If
-arg ALL is nil, collect only messages fron current one on
-forward.
-
-Return number of messages put in the sequence:
+Check the documentation of `mh-interactive-range' to see how
+RANGE is read in interactive use; if nil all messages are
+notated."
+  (unless range
+    (setq range (cons (point-min) (point-max))))
+  (let ((seqs mh-seq-list)
+        (msg-hash (make-hash-table)))
+    (dolist (seq seqs)
+      (dolist (msg (mh-seq-msgs seq))
+        (push (car seq) (gethash msg msg-hash))))
+    (mh-iterate-on-range msg range
+      (loop for seq in (gethash msg msg-hash)
+            do (mh-add-sequence-notation msg (mh-internal-seq seq))))))
 
- nil -> there was no subject line.
- 0   -> there were no later messages with the same
-        subject (sequence not made)
- >1  -> the total number of messages including current one."
-  (if (not (eq major-mode 'mh-folder-mode))
-      (error "Not in a folder buffer"))
-  (save-excursion
-    (beginning-of-line)
-    (if (or (not (looking-at mh-scan-subject-regexp))
-            (not (match-string 3))
-            (string-equal "" (match-string 3)))
-        (progn (message "No subject line")
-               nil)
-      (let ((subject (match-string-no-properties 3))
-            (list))
-        (if (> (length subject) 41)
-            (setq subject (substring subject 0 41)))
-        (save-excursion
-          (if all
-              (goto-char (point-min)))
-          (while (re-search-forward mh-scan-subject-regexp nil t)
-            (let ((this-subject (match-string-no-properties 3)))
-              (if (> (length this-subject) 41)
-                  (setq this-subject (substring this-subject 0 41)))
-              (if (string-equal this-subject subject)
-                  (setq list (cons (mh-get-msg-num t) list))))))
-        (cond
-         (list
-          ;; If we created a new sequence, add the initial message to it too.
-          (if (not (member (mh-get-msg-num t) list))
-              (setq list (cons (mh-get-msg-num t) list)))
-          (if (assoc 'subject mh-seq-list) (mh-delete-seq 'subject))
-          ;; sort the result into a sequence
-          (let ((sorted-list (sort (copy-sequence list) 'mh-lessp)))
-            (while sorted-list
-              (mh-add-msgs-to-seq (car sorted-list) 'subject nil)
-              (setq sorted-list (cdr sorted-list)))
-            (safe-length list)))
-         (t
-          0))))))
-
-(defun mh-subject-to-sequence-threaded (all)
-  "Put all messages with the same subject in the 'subject sequence.
-
-This function works when the folder is threaded. In this
-situation the subject could get truncated and so the normal
-matching doesn't work.
+(defun mh-add-sequence-notation (msg internal-seq-flag)
+  "Add sequence notation to the MSG on the current line.
+If INTERNAL-SEQ-FLAG is non-nil, then refontify the scan line if
+font-lock is turned on."
+  (with-mh-folder-updating (t)
+    (save-excursion
+      (beginning-of-line)
+      (if internal-seq-flag
+          (progn
+            ;; Change the buffer so that if transient-mark-mode is active
+            ;; and there is an active region it will get deactivated as in
+            ;; the case of user sequences.
+            (mh-notate nil nil mh-cmd-note)
+            (when font-lock-mode
+              (font-lock-fontify-region (point) (line-end-position))))
+        (forward-char (+ mh-cmd-note mh-scan-field-destination-offset))
+        (let ((stack (gethash msg mh-sequence-notation-history)))
+          (setf (gethash msg mh-sequence-notation-history)
+                (cons (char-after) stack)))
+        (mh-notate nil mh-note-seq
+                   (+ mh-cmd-note mh-scan-field-destination-offset))))))
 
-The parameter ALL is non-nil then all the messages in the buffer
-are considered, otherwise only the messages after the current one
-are taken into account."
-  (let* ((cur (mh-get-msg-num nil))
-         (subject (mh-thread-find-msg-subject cur))
-         region msgs)
-    (if (null subject)
-        (and (message "No subject line") nil)
-      (setq region (cons (if all (point-min) (point)) (point-max)))
-      (mh-iterate-on-range msg region
-        (when (eq (mh-thread-find-msg-subject msg) subject)
-          (push msg msgs)))
-      (setq msgs (sort msgs #'mh-lessp))
-      (if (null msgs)
-          0
-        (when (assoc 'subject mh-seq-list)
-          (mh-delete-seq 'subject))
-        (mh-add-msgs-to-seq msgs 'subject)
-        (length msgs)))))
-
-(defun mh-thread-find-msg-subject (msg)
-  "Find canonicalized subject of MSG.
-This function can only be used the folder is threaded."
-  (ignore-errors
-    (mh-message-subject
-     (mh-container-message (gethash (gethash msg mh-thread-index-id-map)
-                                    mh-thread-id-table)))))
-
-(defun mh-edit-pick-expr (default)
-  "With prefix arg edit a pick expression.
-If no prefix arg is given, then return DEFAULT."
-  (let ((default-string (loop for x in default concat (format " %s" x))))
-    (if (or current-prefix-arg (equal default-string ""))
-        (mh-pick-args-list (read-string "Pick expression: "
-                                        default-string))
-      default)))
-
-(defun mh-pick-args-list (s)
-  "Form list by grouping elements in string S suitable for pick arguments.
-For example, the string \"-subject a b c -from Joe User
-<user@domain.com>\" is converted to (\"-subject\" \"a b c\"
-\"-from\" \"Joe User <user@domain.com>\""
-  (let ((full-list (split-string s))
-        current-arg collection arg-list)
-    (while full-list
-      (setq current-arg (car full-list))
-      (if (null (string-match "^-" current-arg))
-          (setq collection
-                (if (null collection)
-                    current-arg
-                  (format "%s %s" collection current-arg)))
-        (when collection
-          (setq arg-list (append arg-list (list collection)))
-          (setq collection nil))
-        (setq arg-list (append arg-list (list current-arg))))
-      (setq full-list (cdr full-list)))
-    (when collection
-      (setq arg-list (append arg-list (list collection))))
-    arg-list))
+(defun mh-remove-sequence-notation (msg internal-seq-flag &optional all)
+  "Remove sequence notation from the MSG on the current line.
+If INTERNAL-SEQ-FLAG is non-nil, then `font-lock' was used to
+highlight the sequence. In that case, no notation needs to be removed.
+Otherwise the effect of inserting `mh-note-seq' needs to be reversed.
+If ALL is non-nil, then all sequence marks on the scan line are
+removed."
+  (with-mh-folder-updating (t)
+    ;; This takes care of internal sequences...
+    (mh-notate nil nil mh-cmd-note)
+    (unless internal-seq-flag
+      ;; ... and this takes care of user sequences.
+      (let ((stack (gethash msg mh-sequence-notation-history)))
+        (while (and all (cdr stack))
+          (setq stack (cdr stack)))
+        (when stack
+          (save-excursion
+            (beginning-of-line)
+            (forward-char (+ mh-cmd-note mh-scan-field-destination-offset))
+            (delete-char 1)
+            (insert (car stack))))
+        (setf (gethash msg mh-sequence-notation-history) (cdr stack))))))
 
 ;;;###mh-autoload
-(defun mh-narrow-to-subject (&optional pick-expr)
-  "Limit to messages with same subject.
-With a prefix argument, edit PICK-EXPR.
-
-Use \\<mh-folder-mode-map>\\[mh-widen] to undo this command."
-  (interactive
-   (list (mh-edit-pick-expr (mh-current-message-header-field 'subject))))
-  (mh-narrow-to-header-field 'subject pick-expr))
-
-;;;###mh-autoload
-(defun mh-narrow-to-from (&optional pick-expr)
-  "Limit to messages with the same \"From:\" field.
-With a prefix argument, edit PICK-EXPR.
-
-Use \\<mh-folder-mode-map>\\[mh-widen] to undo this command."
-  (interactive
-   (list (mh-edit-pick-expr (mh-current-message-header-field 'from))))
-  (mh-narrow-to-header-field 'from pick-expr))
-
-;;;###mh-autoload
-(defun mh-narrow-to-cc (&optional pick-expr)
-  "Limit to messages with the same \"Cc:\" field.
-With a prefix argument, edit PICK-EXPR.
-
-Use \\<mh-folder-mode-map>\\[mh-widen] to undo this command."
-  (interactive
-   (list (mh-edit-pick-expr (mh-current-message-header-field 'cc))))
-  (mh-narrow-to-header-field 'cc pick-expr))
-
-;;;###mh-autoload
-(defun mh-narrow-to-to (&optional pick-expr)
-  "Limit to messages with the same \"To:\" field.
-With a prefix argument, edit PICK-EXPR.
-
-Use \\<mh-folder-mode-map>\\[mh-widen] to undo this command."
-  (interactive
-   (list (mh-edit-pick-expr (mh-current-message-header-field 'to))))
-  (mh-narrow-to-header-field 'to pick-expr))
-
-(defun mh-narrow-to-header-field (header-field pick-expr)
-  "Limit to messages whose HEADER-FIELD match PICK-EXPR.
-The MH command pick is used to do the match."
-  (let ((folder mh-current-folder)
-        (original (mh-coalesce-msg-list
-                   (mh-range-to-msg-list (cons (point-min) (point-max)))))
-        (msg-list ()))
-    (with-temp-buffer
-      (apply #'mh-exec-cmd-output "pick" nil folder
-             (append original (list "-list") pick-expr))
-      (goto-char (point-min))
-      (while (not (eobp))
-        (let ((num (ignore-errors
-                     (string-to-number
-                      (buffer-substring (point) (line-end-position))))))
-          (when num (push num msg-list))
-          (forward-line))))
-    (if (null msg-list)
-        (message "No matches")
-      (when (assoc 'header mh-seq-list) (mh-delete-seq 'header))
-      (mh-add-msgs-to-seq msg-list 'header)
-      (mh-narrow-to-seq 'header))))
-
-(defun mh-current-message-header-field (header-field)
-  "Return a pick regexp to match HEADER-FIELD of the message at point."
-  (let ((num (mh-get-msg-num nil)))
-    (when num
-      (let ((folder mh-current-folder))
-        (with-temp-buffer
-          (insert-file-contents-literally (mh-msg-filename num folder))
-          (goto-char (point-min))
-          (when (search-forward "\n\n" nil t)
-            (narrow-to-region (point-min) (point)))
-          (let* ((field (or (message-fetch-field (format "%s" header-field))
-                            ""))
-                 (field-option (format "-%s" header-field))
-                 (patterns (loop for x in (split-string  field "[ ]*,[ ]*")
-                                 unless (equal x "")
-                                 collect (if (string-match "<\\(.*@.*\\)>" x)
-                                             (match-string 1 x)
-                                           x))))
-            (when patterns
-              (loop with accum = `(,field-option ,(car patterns))
-                    for e in (cdr patterns)
-                    do (setq accum `(,field-option ,e "-or" ,@accum))
-                    finally return accum))))))))
-
-;;;###mh-autoload
-(defun mh-narrow-to-range (range)
-  "Limit to RANGE.
-
-Check the documentation of `mh-interactive-range' to see how
-RANGE is read in interactive use.
-
-Use \\<mh-folder-mode-map>\\[mh-widen] to undo this command."
-  (interactive (list (mh-interactive-range "Narrow to")))
-  (when (assoc 'range mh-seq-list) (mh-delete-seq 'range))
-  (mh-add-msgs-to-seq (mh-range-to-msg-list range) 'range)
-  (mh-narrow-to-seq 'range))
-
-
-;;;###mh-autoload
-(defun mh-delete-subject ()
-  "Delete messages with same subject\\<mh-folder-mode-map>.
-
-To delete messages faster, you can use this command to delete all
-the messages with the same subject as the current message. This
-command puts these messages in a sequence named \"subject\". You
-can undo this action by using \\[mh-undo] with a prefix argument
-and then specifying the \"subject\" sequence."
-  (interactive)
-  (let ((count (mh-subject-to-sequence nil)))
-    (cond
-     ((not count)                       ; No subject line, delete msg anyway
-      (mh-delete-msg (mh-get-msg-num t)))
-     ((= 0 count)                       ; No other msgs, delete msg anyway.
-      (message "No other messages with same Subject following this one")
-      (mh-delete-msg (mh-get-msg-num t)))
-     (t                                 ; We have a subject sequence.
-      (message "Marked %d messages for deletion" count)
-      (mh-delete-msg 'subject)))))
-
-;;;###mh-autoload
-(defun mh-delete-subject-or-thread ()
-  "Delete messages with same subject or thread\\<mh-folder-mode-map>.
-
-To delete messages faster, you can use this command to delete all
-the messages with the same subject as the current message. This
-command puts these messages in a sequence named \"subject\". You
-can undo this action by using \\[mh-undo] with a prefix argument
-and then specifying the \"subject\" sequence.
-
-However, if the buffer is displaying a threaded view of the
-folder then this command behaves like \\[mh-thread-delete]."
-  (interactive)
-  (if (memq 'unthread mh-view-ops)
-      (mh-thread-delete)
-    (mh-delete-subject)))
+(defun mh-remove-all-notation ()
+  "Remove all notations on all scan lines that MH-E introduces."
+  (save-excursion
+    (setq overlay-arrow-position nil)
+    (goto-char (point-min))
+    (mh-iterate-on-range msg (cons (point-min) (point-max))
+      (mh-notate nil ?  mh-cmd-note)
+      (mh-remove-sequence-notation msg nil t))
+    (clrhash mh-sequence-notation-history)))
 
 
 
-;;; Message threading:
-
-(defmacro mh-thread-initialize-hash (var test)
-  "Initialize the hash table in VAR.
-TEST is the test to use when creating a new hash table."
-  (unless (symbolp var) (error "Expected a symbol: %s" var))
-  `(if ,var (clrhash ,var) (setq ,var (make-hash-table :test ,test))))
-
-(defun mh-thread-initialize ()
-  "Make new hash tables, or clear them if already present."
-  (mh-thread-initialize-hash mh-thread-id-hash #'equal)
-  (mh-thread-initialize-hash mh-thread-subject-hash #'equal)
-  (mh-thread-initialize-hash mh-thread-id-table #'eq)
-  (mh-thread-initialize-hash mh-thread-id-index-map #'eq)
-  (mh-thread-initialize-hash mh-thread-index-id-map #'eql)
-  (mh-thread-initialize-hash mh-thread-scan-line-map #'eql)
-  (mh-thread-initialize-hash mh-thread-subject-container-hash #'eq)
-  (mh-thread-initialize-hash mh-thread-duplicates #'eq)
-  (setq mh-thread-history ()))
-
-(defsubst mh-thread-id-container (id)
-  "Given ID, return the corresponding container in `mh-thread-id-table'.
-If no container exists then a suitable container is created and
-the id-table is updated."
-  (when (not id)
-    (error "1"))
-  (or (gethash id mh-thread-id-table)
-      (setf (gethash id mh-thread-id-table)
-            (let ((message (mh-thread-make-message :id id)))
-              (mh-thread-make-container :message message)))))
-
-(defsubst mh-thread-remove-parent-link (child)
-  "Remove parent link of CHILD if it exists."
-  (let* ((child-container (if (mh-thread-container-p child)
-                              child (mh-thread-id-container child)))
-         (parent-container (mh-container-parent child-container)))
-    (when parent-container
-      (setf (mh-container-children parent-container)
-            (loop for elem in (mh-container-children parent-container)
-                  unless (eq child-container elem) collect elem))
-      (setf (mh-container-parent child-container) nil))))
-
-(defsubst mh-thread-add-link (parent child &optional at-end-p)
-  "Add links so that PARENT becomes a parent of CHILD.
-Doesn't make any changes if CHILD is already an ancestor of
-PARENT. If optional argument AT-END-P is non-nil, the CHILD is
-added to the end of the children list of PARENT."
-  (let ((parent-container (cond ((null parent) nil)
-                                ((mh-thread-container-p parent) parent)
-                                (t (mh-thread-id-container parent))))
-        (child-container (if (mh-thread-container-p child)
-                             child (mh-thread-id-container child))))
-    (when (and parent-container
-               (not (mh-thread-ancestor-p child-container parent-container))
-               (not (mh-thread-ancestor-p parent-container child-container)))
-      (mh-thread-remove-parent-link child-container)
-      (cond ((not at-end-p)
-             (push child-container (mh-container-children parent-container)))
-            ((null (mh-container-children parent-container))
-             (push child-container (mh-container-children parent-container)))
-            (t (let ((last-child (mh-container-children parent-container)))
-                 (while (cdr last-child)
-                   (setq last-child (cdr last-child)))
-                 (setcdr last-child (cons child-container nil)))))
-      (setf (mh-container-parent child-container) parent-container))
-    (unless parent-container
-      (mh-thread-remove-parent-link child-container))))
-
-(defun mh-thread-ancestor-p (ancestor successor)
-  "Return t if ANCESTOR is really an ancestor of SUCCESSOR and nil otherwise.
-In the limit, the function returns t if ANCESTOR and SUCCESSOR
-are the same containers."
-  (block nil
-    (while successor
-      (when (eq ancestor successor) (return t))
-      (setq successor (mh-container-parent successor)))
-    nil))
-
-(defsubst mh-thread-get-message-container (message)
-  "Return container which has MESSAGE in it.
-If there is no container present then a new container is
-allocated."
-  (let* ((id (mh-message-id message))
-         (container (gethash id mh-thread-id-table)))
-    (cond (container (setf (mh-container-message container) message)
-                     container)
-          (t (setf (gethash id mh-thread-id-table)
-                   (mh-thread-make-container :message message))))))
-
-(defsubst mh-thread-get-message (id subject-re-p subject refs)
-  "Return appropriate message.
-Otherwise update message already present to have the proper ID,
-SUBJECT-RE-P, SUBJECT and REFS fields."
-  (let* ((container (gethash id mh-thread-id-table))
-         (message (if container (mh-container-message container) nil)))
-    (cond (message
-           (setf (mh-message-subject-re-p message) subject-re-p)
-           (setf (mh-message-subject message) subject)
-           (setf (mh-message-id message) id)
-           (setf (mh-message-references message) refs)
-           message)
-          (container
-           (setf (mh-container-message container)
-                 (mh-thread-make-message :id id :references refs
-                                         :subject subject
-                                         :subject-re-p subject-re-p)))
-          (t (let ((message (mh-thread-make-message :id id :references refs
-                                                    :subject-re-p subject-re-p
-                                                    :subject subject)))
-               (prog1 message
-                 (mh-thread-get-message-container message)))))))
-
-(defsubst mh-thread-canonicalize-id (id)
-  "Produce canonical string representation for ID.
-This allows cheap string comparison with EQ."
-  (or (and (equal id "") (copy-sequence ""))
-      (gethash id mh-thread-id-hash)
-      (setf (gethash id mh-thread-id-hash) id)))
-
-(defsubst mh-thread-prune-subject (subject)
-  "Prune leading Re:'s, Fwd:'s etc. and trailing (fwd)'s from SUBJECT.
-If the result after pruning is not the empty string then it is
-canonicalized so that subjects can be tested for equality with
-eq. This is done so that all the messages without a subject are
-not put into a single thread."
-  (let ((case-fold-search t)
-        (subject-pruned-flag nil))
-    ;; Prune subject leader
-    (while (or (string-match "^[ \t]*\\(re\\|fwd?\\)\\(\\[[0-9]*\\]\\)?:[ \t]*"
-                             subject)
-               (string-match "^[ \t]*\\[[^\\]][ \t]*" subject))
-      (setq subject-pruned-flag t)
-      (setq subject (substring subject (match-end 0))))
-    ;; Prune subject trailer
-    (while (or (string-match "(fwd)$" subject)
-               (string-match "[ \t]+$" subject))
-      (setq subject-pruned-flag t)
-      (setq subject (substring subject 0 (match-beginning 0))))
-    ;; Canonicalize subject only if it is non-empty
-    (cond ((equal subject "") (values subject subject-pruned-flag))
-          (t (values
-              (or (gethash subject mh-thread-subject-hash)
-                  (setf (gethash subject mh-thread-subject-hash) subject))
-              subject-pruned-flag)))))
-
-(defun mh-thread-container-subject (container)
-  "Return the subject of CONTAINER.
-If CONTAINER is empty return the subject info of one of its
-children."
-  (cond ((and (mh-container-message container)
-              (mh-message-id (mh-container-message container)))
-         (mh-message-subject (mh-container-message container)))
-        (t (block nil
-             (dolist (kid (mh-container-children container))
-               (when (and (mh-container-message kid)
-                          (mh-message-id (mh-container-message kid)))
-                 (let ((kid-message (mh-container-message kid)))
-                   (return (mh-message-subject kid-message)))))
-             (error "This can't happen")))))
-
-(defun mh-thread-rewind-pruning ()
-  "Restore the thread tree to its state before pruning."
-  (while mh-thread-history
-    (let ((action (pop mh-thread-history)))
-      (cond ((eq (car action) 'DROP)
-             (mh-thread-remove-parent-link (cadr action))
-             (mh-thread-add-link (caddr action) (cadr action)))
-            ((eq (car action) 'PROMOTE)
-             (let ((node (cadr action))
-                   (parent (caddr action))
-                   (children (cdddr action)))
-               (dolist (child children)
-                 (mh-thread-remove-parent-link child)
-                 (mh-thread-add-link node child))
-               (mh-thread-add-link parent node)))
-            ((eq (car action) 'SUBJECT)
-             (let ((node (cadr action)))
-               (mh-thread-remove-parent-link node)
-               (setf (mh-container-real-child-p node) t)))))))
-
-(defun mh-thread-prune-containers (roots)
-  "Prune empty containers in the containers ROOTS."
-  (let ((dfs-ordered-nodes ())
-        (work-list roots))
-    (while work-list
-      (let ((node (pop work-list)))
-        (dolist (child (mh-container-children node))
-          (push child work-list))
-        (push node dfs-ordered-nodes)))
-    (while dfs-ordered-nodes
-      (let ((node (pop dfs-ordered-nodes)))
-        (cond ((gethash (mh-message-id (mh-container-message node))
-                        mh-thread-id-index-map)
-               ;; Keep it
-               (setf (mh-container-children node)
-                     (mh-thread-sort-containers (mh-container-children node))))
-              ((and (mh-container-children node)
-                    (or (null (cdr (mh-container-children node)))
-                        (mh-container-parent node)))
-               ;; Promote kids
-               (let ((children ()))
-                 (dolist (kid (mh-container-children node))
-                   (mh-thread-remove-parent-link kid)
-                   (mh-thread-add-link (mh-container-parent node) kid)
-                   (push kid children))
-                 (push `(PROMOTE ,node ,(mh-container-parent node) ,@children)
-                       mh-thread-history)
-                 (mh-thread-remove-parent-link node)))
-              ((mh-container-children node)
-               ;; Promote the first orphan to parent and add the other kids as
-               ;; his children
-               (setf (mh-container-children node)
-                     (mh-thread-sort-containers (mh-container-children node)))
-               (let ((new-parent (car (mh-container-children node)))
-                     (other-kids (cdr (mh-container-children node))))
-                 (mh-thread-remove-parent-link new-parent)
-                 (dolist (kid other-kids)
-                   (mh-thread-remove-parent-link kid)
-                   (setf (mh-container-real-child-p kid) nil)
-                   (mh-thread-add-link new-parent kid t))
-                 (push `(PROMOTE ,node ,(mh-container-parent node)
-                                 ,new-parent ,@other-kids)
-                       mh-thread-history)
-                 (mh-thread-remove-parent-link node)))
-              (t
-               ;; Drop it
-               (push `(DROP ,node ,(mh-container-parent node))
-                     mh-thread-history)
-               (mh-thread-remove-parent-link node)))))
-    (let ((results ()))
-      (maphash #'(lambda (k v)
-                   (declare (ignore k))
-                   (when (and (null (mh-container-parent v))
-                              (gethash (mh-message-id (mh-container-message v))
-                                       mh-thread-id-index-map))
-                     (push v results)))
-               mh-thread-id-table)
-      (mh-thread-sort-containers results))))
-
-(defun mh-thread-sort-containers (containers)
-  "Sort a list of message CONTAINERS to be in ascending order wrt index."
-  (sort containers
-        #'(lambda (x y)
-            (when (and (mh-container-message x) (mh-container-message y))
-              (let* ((id-x (mh-message-id (mh-container-message x)))
-                     (id-y (mh-message-id (mh-container-message y)))
-                     (index-x (gethash id-x mh-thread-id-index-map))
-                     (index-y (gethash id-y mh-thread-id-index-map)))
-                (and (integerp index-x) (integerp index-y)
-                     (< index-x index-y)))))))
-
-(defsubst mh-thread-group-by-subject (roots)
-  "Group the set of message containers, ROOTS based on subject.
-Bug: Check for and make sure that something without Re: is made
-the parent in preference to something that has it."
-  (clrhash mh-thread-subject-container-hash)
-  (let ((results ()))
-    (dolist (root roots)
-      (let* ((subject (mh-thread-container-subject root))
-             (parent (gethash subject mh-thread-subject-container-hash)))
-        (cond (parent (mh-thread-remove-parent-link root)
-                      (mh-thread-add-link parent root t)
-                      (setf (mh-container-real-child-p root) nil)
-                      (push `(SUBJECT ,root) mh-thread-history))
-              (t
-               (setf (gethash subject mh-thread-subject-container-hash) root)
-               (push root results)))))
-    (nreverse results)))
-
-(defun mh-thread-process-in-reply-to (reply-to-header)
-  "Extract message id's from REPLY-TO-HEADER.
-Ideally this should have some regexp which will try to guess if a
-string between < and > is a message id and not an email address.
-For now it will take the last string inside angles."
-  (let ((end (mh-search-from-end ?> reply-to-header)))
-    (when (numberp end)
-      (let ((begin (mh-search-from-end ?< (substring reply-to-header 0 end))))
-        (when (numberp begin)
-          (list (substring reply-to-header begin (1+ end))))))))
-
-(defun mh-thread-set-tables (folder)
-  "Use the tables of FOLDER in current buffer."
-  (flet ((mh-get-table (symbol)
-                       (save-excursion
-                         (set-buffer folder)
-                         (symbol-value symbol))))
-    (setq mh-thread-id-hash (mh-get-table 'mh-thread-id-hash))
-    (setq mh-thread-subject-hash (mh-get-table 'mh-thread-subject-hash))
-    (setq mh-thread-id-table (mh-get-table 'mh-thread-id-table))
-    (setq mh-thread-id-index-map (mh-get-table 'mh-thread-id-index-map))
-    (setq mh-thread-index-id-map (mh-get-table 'mh-thread-index-id-map))
-    (setq mh-thread-scan-line-map (mh-get-table 'mh-thread-scan-line-map))
-    (setq mh-thread-subject-container-hash
-          (mh-get-table 'mh-thread-subject-container-hash))
-    (setq mh-thread-duplicates (mh-get-table 'mh-thread-duplicates))
-    (setq mh-thread-history (mh-get-table 'mh-thread-history))))
-
-(defsubst mh-thread-update-id-index-maps (id index)
-  "Message with id, ID is the message in INDEX.
-The function also checks for duplicate messages (that is multiple
-messages with the same ID). These messages are put in the
-`mh-thread-duplicates' hash table."
-  (let ((old-index (gethash id mh-thread-id-index-map)))
-    (when old-index (push old-index (gethash id mh-thread-duplicates)))
-    (setf (gethash id mh-thread-id-index-map) index)
-    (setf (gethash index mh-thread-index-id-map) id)))
-
-
-
-;;; Generate Threads...
-
-(defvar mh-message-id-regexp "^<.*@.*>$"
-  "Regexp to recognize whether a string is a message identifier.")
-
-(defun mh-thread-generate (folder msg-list)
-  "Scan FOLDER to get info for threading.
-Only information about messages in MSG-LIST are added to the tree."
-  (with-temp-buffer
-    (mh-thread-set-tables folder)
-    (when msg-list
-      (apply
-       #'call-process (expand-file-name mh-scan-prog mh-progs) nil '(t nil) nil
-       "-width" "10000" "-format"
-       "%(msg)\n%{message-id}\n%{references}\n%{in-reply-to}\n%{subject}\n"
-       folder (mapcar #'(lambda (x) (format "%s" x)) msg-list)))
-    (goto-char (point-min))
-    (let ((roots ())
-          (case-fold-search t))
-      (block nil
-        (while (not (eobp))
-          (block process-message
-            (let* ((index-line
-                    (prog1 (buffer-substring (point) (line-end-position))
-                      (forward-line)))
-                   (index (string-to-number index-line))
-                   (id (prog1 (buffer-substring (point) (line-end-position))
-                         (forward-line)))
-                   (refs (prog1 (buffer-substring (point) (line-end-position))
-                           (forward-line)))
-                   (in-reply-to (prog1 (buffer-substring (point)
-                                                         (line-end-position))
-                                  (forward-line)))
-                   (subject (prog1
-                                (buffer-substring (point) (line-end-position))
-                              (forward-line)))
-                   (subject-re-p nil))
-              (unless (gethash index mh-thread-scan-line-map)
-                (return-from process-message))
-              (unless (integerp index) (return)) ;Error message here
-              (multiple-value-setq (subject subject-re-p)
-                (mh-thread-prune-subject subject))
-              (setq in-reply-to (mh-thread-process-in-reply-to in-reply-to))
-              (setq refs (loop for x in (append (split-string refs) in-reply-to)
-                               when (string-match mh-message-id-regexp x)
-                               collect x))
-              (setq id (mh-thread-canonicalize-id id))
-              (mh-thread-update-id-index-maps id index)
-              (setq refs (mapcar #'mh-thread-canonicalize-id refs))
-              (mh-thread-get-message id subject-re-p subject refs)
-              (do ((ancestors refs (cdr ancestors)))
-                  ((null (cdr ancestors))
-                   (when (car ancestors)
-                     (mh-thread-remove-parent-link id)
-                     (mh-thread-add-link (car ancestors) id)))
-                (mh-thread-add-link (car ancestors) (cadr ancestors)))))))
-      (maphash #'(lambda (k v)
-                   (declare (ignore k))
-                   (when (null (mh-container-parent v))
-                     (push v roots)))
-               mh-thread-id-table)
-      (setq roots (mh-thread-prune-containers roots))
-      (prog1 (setq roots (mh-thread-group-by-subject roots))
-        (let ((history mh-thread-history))
-          (set-buffer folder)
-          (setq mh-thread-history history))))))
-
-;;;###mh-autoload
-(defun mh-thread-inc (folder start-point)
-  "Update thread tree for FOLDER.
-All messages after START-POINT are added to the thread tree."
-  (mh-thread-rewind-pruning)
-  (mh-remove-all-notation)
-  (goto-char start-point)
-  (let ((msg-list ()))
-    (while (not (eobp))
-      (let ((index (mh-get-msg-num nil)))
-        (when (numberp index)
-          (push index msg-list)
-          (setf (gethash index mh-thread-scan-line-map)
-                (mh-thread-parse-scan-line)))
-        (forward-line)))
-    (let ((thread-tree (mh-thread-generate folder msg-list))
-          (buffer-read-only nil)
-          (old-buffer-modified-flag (buffer-modified-p)))
-      (delete-region (point-min) (point-max))
-      (mh-thread-print-scan-lines thread-tree)
-      (mh-notate-user-sequences)
-      (mh-notate-deleted-and-refiled)
-      (mh-notate-cur)
-      (set-buffer-modified-p old-buffer-modified-flag))))
-
-(defun mh-thread-generate-scan-lines (tree level)
-  "Generate scan lines.
-TREE is the hierarchical tree of messages, SCAN-LINE-MAP maps
-message indices to the corresponding scan lines and LEVEL used to
-determine indentation of the message."
-  (cond ((null tree) nil)
-        ((mh-thread-container-p tree)
-         (let* ((message (mh-container-message tree))
-                (id (mh-message-id message))
-                (index (gethash id mh-thread-id-index-map))
-                (duplicates (gethash id mh-thread-duplicates))
-                (new-level (+ level 2))
-                (dupl-flag t)
-                (force-angle-flag nil)
-                (increment-level-flag nil))
-           (dolist (scan-line (mapcar (lambda (x)
-                                        (gethash x mh-thread-scan-line-map))
-                                      (reverse (cons index duplicates))))
-             (when scan-line
-               (when (and dupl-flag (equal level 0)
-                          (mh-thread-ancestor-p mh-thread-last-ancestor tree))
-                 (setq level (+ level 2)
-                       new-level (+ new-level 2)
-                       force-angle-flag t))
-               (when (equal level 0)
-                 (setq mh-thread-last-ancestor tree)
-                 (while (mh-container-parent mh-thread-last-ancestor)
-                   (setq mh-thread-last-ancestor
-                         (mh-container-parent mh-thread-last-ancestor))))
-               (let* ((lev (if dupl-flag level new-level))
-                      (square-flag (or (and (mh-container-real-child-p tree)
-                                            (not force-angle-flag)
-                                            dupl-flag)
-                                       (equal lev 0))))
-                 (insert (car scan-line)
-                         (format (format "%%%ss" lev) "")
-                         (if square-flag "[" "<")
-                         (cadr scan-line)
-                         (if square-flag "]" ">")
-                         (truncate-string-to-width
-                          (caddr scan-line) (- mh-thread-body-width lev))
-                         "\n"))
-               (setq increment-level-flag t)
-               (setq dupl-flag nil)))
-           (unless increment-level-flag (setq new-level level))
-           (dolist (child (mh-container-children tree))
-             (mh-thread-generate-scan-lines child new-level))))
-        (t (let ((nlevel (+ level 2)))
-             (dolist (ch tree)
-               (mh-thread-generate-scan-lines ch nlevel))))))
-
-;; Another and may be better approach would be to generate all the info from
-;; the scan which generates the threading info. For now this will have to do.
-(defun mh-thread-parse-scan-line (&optional string)
-  "Parse a scan line.
-If optional argument STRING is given then that is assumed to be
-the scan line. Otherwise uses the line at point as the scan line
-to parse."
-  (let* ((string (or string
-                     (buffer-substring-no-properties (line-beginning-position)
-                                                     (line-end-position))))
-         (address-start (+ mh-cmd-note mh-scan-field-from-start-offset))
-         (body-start (+ mh-cmd-note mh-scan-field-from-end-offset))
-         (first-string (substring string 0 address-start)))
-    (list first-string
-          (substring string address-start (- body-start 2))
-          (substring string body-start)
-          string)))
-
-;;;###mh-autoload
-(defun mh-thread-update-scan-line-map (msg notation offset)
-  "In threaded view update `mh-thread-scan-line-map'.
-MSG is the message being notated with NOTATION at OFFSET."
-  (let* ((msg (or msg (mh-get-msg-num nil)))
-         (cur-scan-line (and mh-thread-scan-line-map
-                             (gethash msg mh-thread-scan-line-map)))
-         (old-scan-lines (loop for map in mh-thread-scan-line-map-stack
-                               collect (and map (gethash msg map)))))
-    (when cur-scan-line
-      (setf (aref (car cur-scan-line) offset) notation))
-    (dolist (line old-scan-lines)
-      (when line (setf (aref (car line) offset) notation)))))
-
-;;;###mh-autoload
-(defun mh-thread-add-spaces (count)
-  "Add COUNT spaces to each scan line in `mh-thread-scan-line-map'."
-  (let ((spaces (format (format "%%%ss" count) "")))
-    (while (not (eobp))
-      (let* ((msg-num (mh-get-msg-num nil))
-             (old-line (nth 3 (gethash msg-num mh-thread-scan-line-map))))
-        (when (numberp msg-num)
-          (setf (gethash msg-num mh-thread-scan-line-map)
-                (mh-thread-parse-scan-line (format "%s%s" spaces old-line)))))
-      (forward-line 1))))
-
-(defun mh-thread-print-scan-lines (thread-tree)
-  "Print scan lines in THREAD-TREE in threaded mode."
-  (let ((mh-thread-body-width (- (window-width) mh-cmd-note
-                                 (1- mh-scan-field-subject-start-offset)))
-        (mh-thread-last-ancestor nil))
-    (if (null mh-index-data)
-        (mh-thread-generate-scan-lines thread-tree -2)
-      (loop for x in (mh-index-group-by-folder)
-            do (let* ((old-map mh-thread-scan-line-map)
-                      (mh-thread-scan-line-map (make-hash-table)))
-                 (setq mh-thread-last-ancestor nil)
-                 (loop for msg in (cdr x)
-                       do (let ((v (gethash msg old-map)))
-                            (when v
-                              (setf (gethash msg mh-thread-scan-line-map) v))))
-                 (when (> (hash-table-count mh-thread-scan-line-map) 0)
-                   (insert (if (bobp) "" "\n") (car x) "\n")
-                   (mh-thread-generate-scan-lines thread-tree -2))))
-      (mh-index-create-imenu-index))))
-
-(defun mh-thread-folder ()
-  "Generate thread view of folder."
-  (message "Threading %s..." (buffer-name))
-  (mh-thread-initialize)
-  (goto-char (point-min))
-  (mh-remove-all-notation)
-  (let ((msg-list ()))
-    (mh-iterate-on-range msg (cons (point-min) (point-max))
-      (setf (gethash msg mh-thread-scan-line-map) (mh-thread-parse-scan-line))
-      (push msg msg-list))
-    (let* ((range (mh-coalesce-msg-list msg-list))
-           (thread-tree (mh-thread-generate (buffer-name) range)))
-      (delete-region (point-min) (point-max))
-      (mh-thread-print-scan-lines thread-tree)
-      (mh-notate-user-sequences)
-      (mh-notate-deleted-and-refiled)
-      (mh-notate-cur)
-      (message "Threading %s...done" (buffer-name)))))
-
-;;;###mh-autoload
-(defun mh-toggle-threads ()
-  "Toggle threaded view of folder."
-  (interactive)
-  (let ((msg-at-point (mh-get-msg-num nil))
-        (old-buffer-modified-flag (buffer-modified-p))
-        (buffer-read-only nil))
-    (cond ((memq 'unthread mh-view-ops)
-           (unless (mh-valid-view-change-operation-p 'unthread)
-             (error "Can't unthread folder"))
-           (let ((msg-list ()))
-             (goto-char (point-min))
-             (while (not (eobp))
-               (let ((index (mh-get-msg-num nil)))
-                 (when index
-                   (push index msg-list)))
-               (forward-line))
-             (mh-scan-folder mh-current-folder
-                             (mapcar #'(lambda (x) (format "%s" x))
-                                     (mh-coalesce-msg-list msg-list))
-                             t))
-           (when mh-index-data
-             (mh-index-insert-folder-headers)
-             (mh-notate-cur)))
-          (t (mh-thread-folder)
-             (push 'unthread mh-view-ops)))
-    (when msg-at-point (mh-goto-msg msg-at-point t t))
-    (set-buffer-modified-p old-buffer-modified-flag)
-    (mh-recenter nil)))
-
-;;;###mh-autoload
-(defun mh-thread-forget-message (index)
-  "Forget the message INDEX from the threading tables."
-  (let* ((id (gethash index mh-thread-index-id-map))
-         (id-index (gethash id mh-thread-id-index-map))
-         (duplicates (gethash id mh-thread-duplicates)))
-    (remhash index mh-thread-index-id-map)
-    (remhash index mh-thread-scan-line-map)
-    (cond ((and (eql index id-index) (null duplicates))
-           (remhash id mh-thread-id-index-map))
-          ((eql index id-index)
-           (setf (gethash id mh-thread-id-index-map) (car duplicates))
-           (setf (gethash (car duplicates) mh-thread-index-id-map) id)
-           (setf (gethash id mh-thread-duplicates) (cdr duplicates)))
-          (t
-           (setf (gethash id mh-thread-duplicates)
-                 (remove index duplicates))))))
-
-
-
-;;; Operations on threads
-
-(defun mh-thread-current-indentation-level ()
-  "Find the number of spaces by which current message is indented."
-  (save-excursion
-    (let ((address-start-offset (+ mh-cmd-note mh-scan-date-flag-width
-                                   mh-scan-date-width 1))
-          (level 0))
-      (beginning-of-line)
-      (forward-char address-start-offset)
-      (while (char-equal (char-after) ? )
-        (incf level)
-        (forward-char))
-      level)))
-
-;;;###mh-autoload
-(defun mh-thread-next-sibling (&optional previous-flag)
-  "Display next sibling.
-
-With non-nil optional argument PREVIOUS-FLAG jump to the previous
-sibling."
-  (interactive)
-  (cond ((not (memq 'unthread mh-view-ops))
-         (error "Folder isn't threaded"))
-        ((eobp)
-         (error "No message at point")))
-  (beginning-of-line)
-  (let ((point (point))
-        (done nil)
-        (my-level (mh-thread-current-indentation-level)))
-    (while (and (not done)
-                (equal (forward-line (if previous-flag -1 1)) 0)
-                (not (eobp)))
-      (let ((level (mh-thread-current-indentation-level)))
-        (cond ((equal level my-level)
-               (setq done 'success))
-              ((< level my-level)
-               (message "No %s sibling" (if previous-flag "previous" "next"))
-               (setq done 'failure)))))
-    (cond ((eq done 'success) (mh-maybe-show))
-          ((eq done 'failure) (goto-char point))
-          (t (message "No %s sibling" (if previous-flag "previous" "next"))
-             (goto-char point)))))
-
-;;;###mh-autoload
-(defun mh-thread-previous-sibling ()
-  "Display previous sibling."
-  (interactive)
-  (mh-thread-next-sibling t))
-
-(defun mh-thread-immediate-ancestor ()
-  "Jump to immediate ancestor in thread tree."
-  (beginning-of-line)
-  (let ((point (point))
-        (ancestor-level (- (mh-thread-current-indentation-level) 2))
-        (done nil))
-    (if (< ancestor-level 0)
-        nil
-      (while (and (not done) (equal (forward-line -1) 0))
-        (when (equal ancestor-level (mh-thread-current-indentation-level))
-          (setq done t)))
-      (unless done
-        (goto-char point))
-      done)))
-
-;;;###mh-autoload
-(defun mh-thread-ancestor (&optional thread-root-flag)
-  "Display ancestor of current message.
-
-If you do not care for the way a particular thread has turned,
-you can move up the chain of messages with this command. This
-command can also take a prefix argument THREAD-ROOT-FLAG to jump
-to the message that started everything."
-  (interactive "P")
-  (beginning-of-line)
-  (cond ((not (memq 'unthread mh-view-ops))
-         (error "Folder isn't threaded"))
-        ((eobp)
-         (error "No message at point")))
-  (let ((current-level (mh-thread-current-indentation-level)))
-    (cond (thread-root-flag
-           (while (mh-thread-immediate-ancestor))
-           (mh-maybe-show))
-          ((equal current-level 1)
-           (message "Message has no ancestor"))
-          (t (mh-thread-immediate-ancestor)
-             (mh-maybe-show)))))
-
-(defun mh-thread-find-children ()
-  "Return a region containing the current message and its children.
-The result is returned as a list of two elements. The first is
-the point at the start of the region and the second is the point
-at the end."
-  (beginning-of-line)
-  (if (eobp)
-      nil
-    (let ((address-start-offset (+ mh-cmd-note mh-scan-date-flag-width
-                                   mh-scan-date-width 1))
-          (level (mh-thread-current-indentation-level))
-          spaces begin)
-      (setq begin (point))
-      (setq spaces (format (format "%%%ss" (1+ level)) ""))
-      (forward-line)
-      (block nil
-        (while (not (eobp))
-          (forward-char address-start-offset)
-          (unless (equal (string-match spaces (buffer-substring-no-properties
-                                               (point) (line-end-position)))
-                         0)
-            (beginning-of-line)
-            (backward-char)
-            (return))
-          (forward-line)))
-      (list begin (point)))))
-
-;;;###mh-autoload
-(defun mh-thread-delete ()
-  "Delete thread."
-  (interactive)
-  (cond ((not (memq 'unthread mh-view-ops))
-         (error "Folder isn't threaded"))
-        ((eobp)
-         (error "No message at point"))
-        (t (let ((region (mh-thread-find-children)))
-             (mh-iterate-on-messages-in-region () (car region) (cadr region)
-               (mh-delete-a-msg nil))
-             (mh-next-msg)))))
-
-;;;###mh-autoload
-(defun mh-thread-refile (folder)
-  "Refile (output) thread into FOLDER."
-  (interactive (list (intern (mh-prompt-for-refile-folder))))
-  (cond ((not (memq 'unthread mh-view-ops))
-         (error "Folder isn't threaded"))
-        ((eobp)
-         (error "No message at point"))
-        (t (let ((region (mh-thread-find-children)))
-             (mh-iterate-on-messages-in-region () (car region) (cadr region)
-               (mh-refile-a-msg nil folder))
-             (mh-next-msg)))))
-
-
-
-;; Tick mark handling
-
-;;;###mh-autoload
-(defun mh-toggle-tick (range)
-  "Toggle tick mark of RANGE.
-
-This command adds messages to the \"tick\" sequence (which you can customize
-via the option `mh-tick-seq'). This sequence can be viewed later with the
-\\[mh-index-ticked-messages] command.
-
-Check the documentation of `mh-interactive-range' to see how RANGE is read in
-interactive use."
-  (interactive (list (mh-interactive-range "Tick")))
-  (unless mh-tick-seq
-    (error "Enable ticking by customizing `mh-tick-seq'"))
-  (let* ((tick-seq (mh-find-seq mh-tick-seq))
-         (tick-seq-msgs (mh-seq-msgs tick-seq))
-         (ticked ())
-         (unticked ()))
-    (mh-iterate-on-range msg range
-      (cond ((member msg tick-seq-msgs)
-             (push msg unticked)
-             (setcdr tick-seq (delq msg (cdr tick-seq)))
-             (when (null (cdr tick-seq)) (setq mh-last-seq-used nil))
-             (mh-remove-sequence-notation msg (mh-colors-in-use-p)))
-            (t
-             (push msg ticked)
-             (setq mh-last-seq-used mh-tick-seq)
-             (let ((mh-seq-list (cons `(,mh-tick-seq ,msg) mh-seq-list)))
-               (mh-add-sequence-notation msg (mh-colors-in-use-p))))))
-    (mh-add-msgs-to-seq ticked mh-tick-seq nil t)
-    (mh-undefine-sequence mh-tick-seq unticked)
-    (when mh-index-data
-      (mh-index-add-to-sequence mh-tick-seq ticked)
-      (mh-index-delete-from-sequence mh-tick-seq unticked))))
-
-;;;###mh-autoload
-(defun mh-narrow-to-tick ()
-  "Limit to ticked messages.
-
-What this command does is show only those messages that are in
-the \"tick\" sequence (which you can customize via the
-`mh-tick-seq' option) in the MH-Folder buffer. In addition, it
-limits further MH-E searches to just those messages. When you
-want to widen the view to all your messages again, use
-\\[mh-widen]."
-  (interactive)
-  (cond ((not mh-tick-seq)
-         (error "Enable ticking by customizing `mh-tick-seq'"))
-        ((null (mh-seq-msgs (mh-find-seq mh-tick-seq)))
-         (message "No messages in %s sequence" mh-tick-seq))
-        (t (mh-narrow-to-seq mh-tick-seq))))
+;; XXX Unused, delete, or create bind key?
+(defun mh-rename-seq (sequence new-name)
+  "Rename SEQUENCE to have NEW-NAME."
+  (interactive (list (mh-read-seq "Old" t)
+                     (intern (read-string "New sequence name: "))))
+  (let ((old-seq (mh-find-seq sequence)))
+    (or old-seq
+        (error "Sequence %s does not exist" sequence))
+    ;; Create new sequence first, since it might raise an error.
+    (mh-define-sequence new-name (mh-seq-msgs old-seq))
+    (mh-undefine-sequence sequence (mh-seq-msgs old-seq))
+    (rplaca old-seq new-name)))
 
 (provide 'mh-seq)
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lisp/mh-e/mh-show.el	Wed Feb 01 10:07:17 2006 +0000
@@ -0,0 +1,907 @@
+;;; mh-show.el --- MH-Show mode
+
+;; Copyright (C) 1993, 1995, 1997,
+;;  2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+
+;; Author: Bill Wohler <wohler@newt.com>
+;; Maintainer: Bill Wohler <wohler@newt.com>
+;; Keywords: mail
+;; See: mh-e.el
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
+
+;;; Commentary:
+
+;; Mode for showing messages.
+
+;;; Change Log:
+
+;;; Code:
+
+(require 'mh-e)
+(require 'mh-scan)
+
+(require 'gnus-cite)
+(require 'gnus-util)
+
+(autoload 'mh-make-buffer-data "mh-mime") ;can't be automatically generated
+
+(require 'font-lock)
+
+
+
+;;; MH-Folder Commands
+
+(defvar mh-showing-with-headers nil
+  "If non-nil, MH-Show buffer contains message with all header fields.
+If nil, MH-Show buffer contains message processed normally.")
+
+;;;###mh-autoload
+(defun mh-show (&optional message redisplay-flag)
+  "Display message\\<mh-folder-mode-map>.
+
+If the message under the cursor is already displayed, this command
+scrolls to the beginning of the message. MH-E normally hides a lot of
+the superfluous header fields that mailers add to a message, but if
+you wish to see all of them, use the command \\[mh-header-display].
+
+Two hooks can be used to control how messages are displayed. The
+first hook, `mh-show-mode-hook', is called early on in the
+process of the message display. It is usually used to perform
+some action on the message's content. The second hook,
+`mh-show-hook', is the last thing called after messages are
+displayed. It's used to affect the behavior of MH-E in general or
+when `mh-show-mode-hook' is too early.
+
+From a program, optional argument MESSAGE can be used to display an
+alternative message. The optional argument REDISPLAY-FLAG forces the
+redisplay of the message even if the show buffer was already
+displaying the correct message.
+
+See the \"mh-show\" customization group for a litany of options that
+control what displayed messages look like."
+  (interactive (list nil t))
+  (when (or redisplay-flag
+            (and mh-showing-with-headers
+                 (or mh-mhl-format-file mh-clean-message-header-flag)))
+    (mh-invalidate-show-buffer))
+  (mh-show-msg message))
+
+;;;###mh-autoload
+(defun mh-header-display ()
+  "Display message with all header fields\\<mh-folder-mode-map>.
+
+Use the command \\[mh-show] to show the message normally again."
+  (interactive)
+  (and (not mh-showing-with-headers)
+       (or mh-mhl-format-file mh-clean-message-header-flag)
+       (mh-invalidate-show-buffer))
+  (let ((mh-decode-mime-flag nil)
+        (mh-mhl-format-file nil)
+        (mh-clean-message-header-flag nil))
+    (mh-show-msg nil)
+    (mh-in-show-buffer (mh-show-buffer)
+      (goto-char (point-min))
+      (mh-recenter 0))
+    (setq mh-showing-with-headers t)))
+
+
+
+;;; Support Routines for MH-Folder Commands
+
+;;;###mh-autoload
+(defun mh-maybe-show (&optional msg)
+  "Display message at cursor, but only if in show mode.
+If optional arg MSG is non-nil, display that message instead."
+  (if mh-showing-mode (mh-show msg)))
+
+(defun mh-show-msg (msg)
+  "Show MSG.
+
+The hook `mh-show-hook' is called after the message has been
+displayed."
+  (if (not msg)
+      (setq msg (mh-get-msg-num t)))
+  (mh-showing-mode t)
+  (setq mh-page-to-next-msg-flag nil)
+  (let ((folder mh-current-folder)
+        (folders (list mh-current-folder))
+        (clean-message-header mh-clean-message-header-flag)
+        (show-window (get-buffer-window mh-show-buffer))
+        (display-mime-buttons-flag mh-display-buttons-for-inline-parts-flag))
+    (if (not (eq (next-window (minibuffer-window)) (selected-window)))
+        (delete-other-windows))         ; force ourself to the top window
+    (mh-in-show-buffer (mh-show-buffer)
+      (setq mh-display-buttons-for-inline-parts-flag display-mime-buttons-flag)
+      (if (and show-window
+               (equal (mh-msg-filename msg folder) buffer-file-name))
+          (progn                        ;just back up to start
+            (goto-char (point-min))
+            (if (not clean-message-header)
+                (mh-start-of-uncleaned-message)))
+        (mh-display-msg msg folder)))
+    (if (not (= (1+ (window-height)) (frame-height))) ;not horizontally split
+        (shrink-window (- (window-height) (or mh-summary-height
+                                              (mh-summary-height)))))
+    (mh-recenter nil)
+    ;; The following line is a nop which forces update of the scan line so
+    ;; that font-lock will update it (if needed)...
+    (mh-notate nil nil mh-cmd-note)
+    (if (not (memq msg mh-seen-list))
+        (setq mh-seen-list (cons msg mh-seen-list)))
+    (when mh-update-sequences-after-mh-show-flag
+      (mh-update-sequences)
+      (when mh-index-data
+        (setq folders
+              (append (mh-index-delete-from-sequence mh-unseen-seq (list msg))
+                      folders)))
+      (when (mh-speed-flists-active-p)
+        (apply #'mh-speed-flists t folders)))
+    (run-hooks 'mh-show-hook)))
+
+;;;###mh-autoload
+(defun mh-showing-mode (&optional arg)
+  "Change whether messages should be displayed.
+
+With ARG, display messages iff ARG is positive."
+  (setq mh-showing-mode
+        (if (null arg)
+            (not mh-showing-mode)
+          (> (prefix-numeric-value arg) 0))))
+
+;;;###mh-autoload
+(defun mh-start-of-uncleaned-message ()
+  "Position uninteresting headers off the top of the window."
+  (let ((case-fold-search t))
+    (re-search-forward
+     "^To:\\|^Cc:\\|^From:\\|^Subject:\\|^Date:" nil t)
+    (beginning-of-line)
+    (mh-recenter 0)))
+
+(defvar mh-show-buffer-mode-line-buffer-id "    {show-%s} %d"
+  "Format string to produce `mode-line-buffer-identification' for show buffers.
+
+First argument is folder name. Second is message number.")
+
+;;;###mh-autoload
+(defun mh-display-msg (msg-num folder-name)
+  "Display MSG-NUM of FOLDER-NAME.
+Sets the current buffer to the show buffer."
+  (let ((folder (mh-msg-folder folder-name)))
+    (set-buffer folder)
+    ;; When Gnus uses external displayers it has to keep handles longer. So
+    ;; we will delete these handles when mh-quit is called on the folder. It
+    ;; would be nicer if there are weak pointers in emacs lisp, then we could
+    ;; get the garbage collector to do this for us.
+    (unless (mh-buffer-data)
+      (setf (mh-buffer-data) (mh-make-buffer-data)))
+    ;; Bind variables in folder buffer in case they are local
+    (let ((formfile mh-mhl-format-file)
+          (clean-message-header mh-clean-message-header-flag)
+          (invisible-headers mh-invisible-header-fields-compiled)
+          (visible-headers nil)
+          (msg-filename (mh-msg-filename msg-num folder-name))
+          (show-buffer mh-show-buffer)
+          (mm-inline-media-tests mh-mm-inline-media-tests))
+      (if (not (file-exists-p msg-filename))
+          (error "Message %d does not exist" msg-num))
+      (if (and (> mh-show-maximum-size 0)
+               (> (elt (file-attributes msg-filename) 7)
+                  mh-show-maximum-size)
+               (not (y-or-n-p
+                     (format
+                      "Message %d (%d bytes) exceeds %d bytes. Display it? "
+                      msg-num (elt (file-attributes msg-filename) 7)
+                      mh-show-maximum-size))))
+          (error "Message %d not displayed" msg-num))
+      (set-buffer show-buffer)
+      (cond ((not (equal msg-filename buffer-file-name))
+             (mh-unvisit-file)
+             (setq buffer-read-only nil)
+             ;; Cleanup old mime handles
+             (mh-mime-cleanup)
+             (erase-buffer)
+             ;; Changing contents, so this hook needs to be reinitialized.
+             ;; pgp.el uses this.
+             (if (boundp 'write-contents-hooks) ;Emacs 19
+                 (kill-local-variable 'write-contents-hooks))
+             (if formfile
+                 (mh-exec-lib-cmd-output "mhl" "-nobell" "-noclear"
+                                         (if (stringp formfile)
+                                             (list "-form" formfile))
+                                         msg-filename)
+               (insert-file-contents-literally msg-filename))
+             ;; Use mm to display buffer
+             (when (and mh-decode-mime-flag (not formfile))
+               (mh-add-missing-mime-version-header)
+               (setf (mh-buffer-data) (mh-make-buffer-data))
+               (mh-mime-display))
+             (mh-show-mode)
+             ;; Header cleanup
+             (goto-char (point-min))
+             (cond (clean-message-header
+                    (mh-clean-msg-header (point-min)
+                                         invisible-headers
+                                         visible-headers)
+                    (goto-char (point-min)))
+                   (t
+                    (mh-start-of-uncleaned-message)))
+             (mh-decode-message-header)
+             ;; the parts of visiting we want to do (no locking)
+             (or (eq buffer-undo-list t) ;don't save undo info for prev msgs
+                 (setq buffer-undo-list nil))
+             (set-buffer-auto-saved)
+             ;; the parts of set-visited-file-name we want to do (no locking)
+             (setq buffer-file-name msg-filename)
+             (setq buffer-backed-up nil)
+             (auto-save-mode 1)
+             (set-mark nil)
+             (unwind-protect
+                 (when (and mh-decode-mime-flag (not formfile))
+                   (setq buffer-read-only nil)
+                   (mh-display-smileys)
+                   (mh-display-emphasis))
+               (setq buffer-read-only t))
+             (set-buffer-modified-p nil)
+             (setq mh-show-folder-buffer folder)
+             (setq mode-line-buffer-identification
+                   (list (format mh-show-buffer-mode-line-buffer-id
+                                 folder-name msg-num)))
+             (mh-logo-display)
+             (set-buffer folder)
+             (setq mh-showing-with-headers nil))))))
+
+(defun mh-msg-folder (folder-name)
+  "Return the name of the buffer for FOLDER-NAME."
+  folder-name)
+
+;;;###mh-autoload
+(defun mh-clean-msg-header (start invisible-headers visible-headers)
+  "Flush extraneous lines in message header.
+
+Header is cleaned from START to the end of the message header.
+INVISIBLE-HEADERS contains a regular expression specifying lines
+to delete from the header. VISIBLE-HEADERS contains a regular
+expression specifying the lines to display. INVISIBLE-HEADERS is
+ignored if VISIBLE-HEADERS is non-nil."
+  ;; XXX Note that MH-E no longer supports the `mh-visible-headers'
+  ;; variable, so this function could be trimmed of this feature too."
+  (let ((case-fold-search t)
+        (buffer-read-only nil))
+    (save-restriction
+      (goto-char start)
+      (if (search-forward "\n\n" nil 'move)
+          (backward-char 1))
+      (narrow-to-region start (point))
+      (goto-char (point-min))
+      (if visible-headers
+          (while (< (point) (point-max))
+            (cond ((looking-at visible-headers)
+                   (forward-line 1)
+                   (while (looking-at "[ \t]") (forward-line 1)))
+                  (t
+                   (mh-delete-line 1)
+                   (while (looking-at "[ \t]")
+                     (mh-delete-line 1)))))
+        (while (re-search-forward invisible-headers nil t)
+          (beginning-of-line)
+          (mh-delete-line 1)
+          (while (looking-at "[ \t]")
+            (mh-delete-line 1)))))
+    (let ((mh-compose-skipped-header-fields ()))
+      (mh-letter-hide-all-skipped-fields))
+    (unlock-buffer)))
+
+;;;###mh-autoload
+(defun mh-invalidate-show-buffer ()
+  "Invalidate the show buffer so we must update it to use it."
+  (if (get-buffer mh-show-buffer)
+      (save-excursion
+        (set-buffer mh-show-buffer)
+        (mh-unvisit-file))))
+
+(defun mh-unvisit-file ()
+  "Separate current buffer from the message file it was visiting."
+  (or (not (buffer-modified-p))
+      (null buffer-file-name)           ;we've been here before
+      (yes-or-no-p (format "Message %s modified; flush changes? "
+                           (file-name-nondirectory buffer-file-name)))
+      (error "Flushing changes not confirmed"))
+  (clear-visited-file-modtime)
+  (unlock-buffer)
+  (setq buffer-file-name nil))
+
+(defun mh-summary-height ()
+  "Return ideal value for the variable `mh-summary-height'.
+The current frame height is taken into consideration."
+  (or (and (fboundp 'frame-height)
+           (> (frame-height) 24)
+           (min 10 (/ (frame-height) 6)))
+      4))
+
+
+
+;; Infrastructure to generate show-buffer functions from folder functions
+;; XEmacs does not have deactivate-mark? What is the equivalent of
+;; transient-mark-mode for XEmacs? Should we be restoring the mark in the
+;; folder buffer after the operation has been carried out.
+(defmacro mh-defun-show-buffer (function original-function
+                                         &optional dont-return)
+  "Define FUNCTION to run ORIGINAL-FUNCTION in folder buffer.
+If the buffer we start in is still visible and DONT-RETURN is nil
+then switch to it after that."
+  `(defun ,function ()
+     ,(format "Calls %s from the message's folder.\n%s\nSee \"%s\" for more info.\n"
+              original-function
+              (if dont-return ""
+                "When function completes, returns to the show buffer if it is
+still visible.\n")
+              original-function)
+     (interactive)
+     (when (buffer-live-p (get-buffer mh-show-folder-buffer))
+       (let ((config (current-window-configuration))
+             (folder-buffer mh-show-folder-buffer)
+             (normal-exit nil)
+             ,@(if dont-return () '((cur-buffer-name (buffer-name)))))
+         (pop-to-buffer mh-show-folder-buffer nil)
+         (unless (equal (buffer-name
+                         (window-buffer (frame-first-window (selected-frame))))
+                        folder-buffer)
+           (delete-other-windows))
+         (mh-goto-cur-msg t)
+         (mh-funcall-if-exists deactivate-mark)
+         (unwind-protect
+             (prog1 (call-interactively (function ,original-function))
+               (setq normal-exit t))
+           (mh-funcall-if-exists deactivate-mark)
+           (when (eq major-mode 'mh-folder-mode)
+             (mh-funcall-if-exists hl-line-highlight))
+           (cond ((not normal-exit)
+                  (set-window-configuration config))
+                 ,(if dont-return
+                      `(t (setq mh-previous-window-config config))
+                    `((and (get-buffer cur-buffer-name)
+                           (window-live-p (get-buffer-window
+                                           (get-buffer cur-buffer-name))))
+                      (pop-to-buffer (get-buffer cur-buffer-name) nil)))))))))
+
+;; Generate interactive functions for the show buffer from the corresponding
+;; folder functions.
+(mh-defun-show-buffer mh-show-previous-undeleted-msg
+                      mh-previous-undeleted-msg)
+(mh-defun-show-buffer mh-show-next-undeleted-msg
+                      mh-next-undeleted-msg)
+(mh-defun-show-buffer mh-show-quit mh-quit)
+(mh-defun-show-buffer mh-show-delete-msg mh-delete-msg)
+(mh-defun-show-buffer mh-show-refile-msg mh-refile-msg)
+(mh-defun-show-buffer mh-show-undo mh-undo)
+(mh-defun-show-buffer mh-show-execute-commands mh-execute-commands)
+(mh-defun-show-buffer mh-show-reply mh-reply t)
+(mh-defun-show-buffer mh-show-redistribute mh-redistribute)
+(mh-defun-show-buffer mh-show-forward mh-forward t)
+(mh-defun-show-buffer mh-show-header-display mh-header-display)
+(mh-defun-show-buffer mh-show-refile-or-write-again
+                      mh-refile-or-write-again)
+(mh-defun-show-buffer mh-show-show mh-show)
+(mh-defun-show-buffer mh-show-write-message-to-file
+                      mh-write-msg-to-file)
+(mh-defun-show-buffer mh-show-extract-rejected-mail
+                      mh-extract-rejected-mail t)
+(mh-defun-show-buffer mh-show-delete-msg-no-motion
+                      mh-delete-msg-no-motion)
+(mh-defun-show-buffer mh-show-first-msg mh-first-msg)
+(mh-defun-show-buffer mh-show-last-msg mh-last-msg)
+(mh-defun-show-buffer mh-show-copy-msg mh-copy-msg)
+(mh-defun-show-buffer mh-show-edit-again mh-edit-again t)
+(mh-defun-show-buffer mh-show-goto-msg mh-goto-msg)
+(mh-defun-show-buffer mh-show-inc-folder mh-inc-folder)
+(mh-defun-show-buffer mh-show-delete-subject-or-thread
+                      mh-delete-subject-or-thread)
+(mh-defun-show-buffer mh-show-delete-subject mh-delete-subject)
+(mh-defun-show-buffer mh-show-print-msg mh-print-msg)
+(mh-defun-show-buffer mh-show-send mh-send t)
+(mh-defun-show-buffer mh-show-toggle-showing mh-toggle-showing t)
+(mh-defun-show-buffer mh-show-pipe-msg mh-pipe-msg t)
+(mh-defun-show-buffer mh-show-sort-folder mh-sort-folder)
+(mh-defun-show-buffer mh-show-visit-folder mh-visit-folder t)
+(mh-defun-show-buffer mh-show-rescan-folder mh-rescan-folder)
+(mh-defun-show-buffer mh-show-pack-folder mh-pack-folder)
+(mh-defun-show-buffer mh-show-kill-folder mh-kill-folder t)
+(mh-defun-show-buffer mh-show-list-folders mh-list-folders t)
+(mh-defun-show-buffer mh-show-undo-folder mh-undo-folder)
+(mh-defun-show-buffer mh-show-delete-msg-from-seq
+                      mh-delete-msg-from-seq)
+(mh-defun-show-buffer mh-show-delete-seq mh-delete-seq)
+(mh-defun-show-buffer mh-show-list-sequences mh-list-sequences)
+(mh-defun-show-buffer mh-show-narrow-to-seq mh-narrow-to-seq)
+(mh-defun-show-buffer mh-show-put-msg-in-seq mh-put-msg-in-seq)
+(mh-defun-show-buffer mh-show-msg-is-in-seq mh-msg-is-in-seq)
+(mh-defun-show-buffer mh-show-widen mh-widen)
+(mh-defun-show-buffer mh-show-narrow-to-subject mh-narrow-to-subject)
+(mh-defun-show-buffer mh-show-narrow-to-from mh-narrow-to-from)
+(mh-defun-show-buffer mh-show-narrow-to-cc mh-narrow-to-cc)
+(mh-defun-show-buffer mh-show-narrow-to-range mh-narrow-to-range)
+(mh-defun-show-buffer mh-show-narrow-to-to mh-narrow-to-to)
+(mh-defun-show-buffer mh-show-store-msg mh-store-msg)
+(mh-defun-show-buffer mh-show-page-digest mh-page-digest)
+(mh-defun-show-buffer mh-show-page-digest-backwards
+                      mh-page-digest-backwards)
+(mh-defun-show-buffer mh-show-burst-digest mh-burst-digest)
+(mh-defun-show-buffer mh-show-page-msg mh-page-msg)
+(mh-defun-show-buffer mh-show-previous-page mh-previous-page)
+(mh-defun-show-buffer mh-show-modify mh-modify t)
+(mh-defun-show-buffer mh-show-next-button mh-next-button)
+(mh-defun-show-buffer mh-show-prev-button mh-prev-button)
+(mh-defun-show-buffer mh-show-toggle-mime-part mh-folder-toggle-mime-part)
+(mh-defun-show-buffer mh-show-save-mime-part mh-folder-save-mime-part)
+(mh-defun-show-buffer mh-show-inline-mime-part mh-folder-inline-mime-part)
+(mh-defun-show-buffer mh-show-toggle-threads mh-toggle-threads)
+(mh-defun-show-buffer mh-show-thread-delete mh-thread-delete)
+(mh-defun-show-buffer mh-show-thread-refile mh-thread-refile)
+(mh-defun-show-buffer mh-show-update-sequences mh-update-sequences)
+(mh-defun-show-buffer mh-show-next-unread-msg mh-next-unread-msg)
+(mh-defun-show-buffer mh-show-previous-unread-msg mh-previous-unread-msg)
+(mh-defun-show-buffer mh-show-thread-ancestor mh-thread-ancestor)
+(mh-defun-show-buffer mh-show-thread-next-sibling mh-thread-next-sibling)
+(mh-defun-show-buffer mh-show-thread-previous-sibling
+                      mh-thread-previous-sibling)
+(mh-defun-show-buffer mh-show-index-visit-folder mh-index-visit-folder t)
+(mh-defun-show-buffer mh-show-toggle-tick mh-toggle-tick)
+(mh-defun-show-buffer mh-show-narrow-to-tick mh-narrow-to-tick)
+(mh-defun-show-buffer mh-show-junk-blacklist mh-junk-blacklist)
+(mh-defun-show-buffer mh-show-junk-whitelist mh-junk-whitelist)
+(mh-defun-show-buffer mh-show-index-new-messages mh-index-new-messages)
+(mh-defun-show-buffer mh-show-index-ticked-messages mh-index-ticked-messages)
+(mh-defun-show-buffer mh-show-index-sequenced-messages
+                      mh-index-sequenced-messages)
+(mh-defun-show-buffer mh-show-catchup mh-catchup)
+(mh-defun-show-buffer mh-show-ps-print-toggle-color mh-ps-print-toggle-color)
+(mh-defun-show-buffer mh-show-ps-print-toggle-faces mh-ps-print-toggle-faces)
+(mh-defun-show-buffer mh-show-ps-print-msg-file mh-ps-print-msg-file)
+(mh-defun-show-buffer mh-show-ps-print-msg mh-ps-print-msg)
+(mh-defun-show-buffer mh-show-toggle-mime-buttons mh-toggle-mime-buttons)
+(mh-defun-show-buffer mh-show-display-with-external-viewer
+                      mh-display-with-external-viewer)
+
+
+
+;;; Sequence Menu
+
+(easy-menu-define
+  mh-show-sequence-menu mh-show-mode-map "Menu for MH-E folder-sequence."
+  '("Sequence"
+    ["Add Message to Sequence..."       mh-show-put-msg-in-seq t]
+    ["List Sequences for Message"       mh-show-msg-is-in-seq t]
+    ["Delete Message from Sequence..."  mh-show-delete-msg-from-seq t]
+    ["List Sequences in Folder..."      mh-show-list-sequences t]
+    ["Delete Sequence..."               mh-show-delete-seq t]
+    ["Narrow to Sequence..."            mh-show-narrow-to-seq t]
+    ["Widen from Sequence"              mh-show-widen t]
+    "--"
+    ["Narrow to Subject Sequence"       mh-show-narrow-to-subject t]
+    ["Narrow to Tick Sequence"          mh-show-narrow-to-tick
+     (save-excursion
+       (set-buffer mh-show-folder-buffer)
+       (and mh-tick-seq (mh-seq-msgs (mh-find-seq mh-tick-seq))))]
+    ["Delete Rest of Same Subject"      mh-show-delete-subject t]
+    ["Toggle Tick Mark"                 mh-show-toggle-tick t]
+    "--"
+    ["Push State Out to MH"             mh-show-update-sequences t]))
+
+;;; Message Menu
+
+(easy-menu-define
+  mh-show-message-menu mh-show-mode-map "Menu for MH-E folder-message."
+  '("Message"
+    ["Show Message"                     mh-show-show t]
+    ["Show Message with Header"         mh-show-header-display t]
+    ["Next Message"                     mh-show-next-undeleted-msg t]
+    ["Previous Message"                 mh-show-previous-undeleted-msg t]
+    ["Go to First Message"              mh-show-first-msg t]
+    ["Go to Last Message"               mh-show-last-msg t]
+    ["Go to Message by Number..."       mh-show-goto-msg t]
+    ["Modify Message"                   mh-show-modify t]
+    ["Delete Message"                   mh-show-delete-msg t]
+    ["Refile Message"                   mh-show-refile-msg t]
+    ["Undo Delete/Refile"               mh-show-undo t]
+    ["Process Delete/Refile"            mh-show-execute-commands t]
+    "--"
+    ["Compose a New Message"            mh-send t]
+    ["Reply to Message..."              mh-show-reply t]
+    ["Forward Message..."               mh-show-forward t]
+    ["Redistribute Message..."          mh-show-redistribute t]
+    ["Edit Message Again"               mh-show-edit-again t]
+    ["Re-edit a Bounced Message"        mh-show-extract-rejected-mail t]
+    "--"
+    ["Copy Message to Folder..."        mh-show-copy-msg t]
+    ["Print Message"                    mh-show-print-msg t]
+    ["Write Message to File..."         mh-show-write-msg-to-file t]
+    ["Pipe Message to Command..."       mh-show-pipe-msg t]
+    ["Unpack Uuencoded Message..."      mh-show-store-msg t]
+    ["Burst Digest Message"             mh-show-burst-digest t]))
+
+;;; Folder Menu
+
+(easy-menu-define
+  mh-show-folder-menu mh-show-mode-map  "Menu for MH-E folder."
+  '("Folder"
+    ["Incorporate New Mail"             mh-show-inc-folder t]
+    ["Toggle Show/Folder"               mh-show-toggle-showing t]
+    ["Execute Delete/Refile"            mh-show-execute-commands t]
+    ["Rescan Folder"                    mh-show-rescan-folder t]
+    ["Thread Folder"                    mh-show-toggle-threads t]
+    ["Pack Folder"                      mh-show-pack-folder t]
+    ["Sort Folder"                      mh-show-sort-folder t]
+    "--"
+    ["List Folders"                     mh-show-list-folders t]
+    ["Visit a Folder..."                mh-show-visit-folder t]
+    ["View New Messages"                mh-show-index-new-messages t]
+    ["Search..."                        mh-search t]
+    "--"
+    ["Quit MH-E"                        mh-quit t]))
+
+
+
+;;; MH-Show Keys
+
+(gnus-define-keys mh-show-mode-map
+  " "    mh-show-page-msg
+  "!"    mh-show-refile-or-write-again
+  "'"    mh-show-toggle-tick
+  ","    mh-show-header-display
+  "."    mh-show-show
+  ">"    mh-show-write-message-to-file
+  "?"    mh-help
+  "E"    mh-show-extract-rejected-mail
+  "M"    mh-show-modify
+  "\177" mh-show-previous-page
+  "\C-d" mh-show-delete-msg-no-motion
+  "\t"   mh-show-next-button
+  [backtab] mh-show-prev-button
+  "\M-\t" mh-show-prev-button
+  "\ed"  mh-show-redistribute
+  "^"    mh-show-refile-msg
+  "c"    mh-show-copy-msg
+  "d"    mh-show-delete-msg
+  "e"    mh-show-edit-again
+  "f"    mh-show-forward
+  "g"    mh-show-goto-msg
+  "i"    mh-show-inc-folder
+  "k"    mh-show-delete-subject-or-thread
+  "m"    mh-show-send
+  "n"    mh-show-next-undeleted-msg
+  "\M-n" mh-show-next-unread-msg
+  "o"    mh-show-refile-msg
+  "p"    mh-show-previous-undeleted-msg
+  "\M-p" mh-show-previous-unread-msg
+  "q"    mh-show-quit
+  "r"    mh-show-reply
+  "s"    mh-show-send
+  "t"    mh-show-toggle-showing
+  "u"    mh-show-undo
+  "x"    mh-show-execute-commands
+  "v"    mh-show-index-visit-folder
+  "|"    mh-show-pipe-msg)
+
+(gnus-define-keys (mh-show-folder-map "F" mh-show-mode-map)
+  "?"    mh-prefix-help
+  "'"    mh-index-ticked-messages
+  "S"    mh-show-sort-folder
+  "c"    mh-show-catchup
+  "f"    mh-show-visit-folder
+  "k"    mh-show-kill-folder
+  "l"    mh-show-list-folders
+  "n"    mh-index-new-messages
+  "o"    mh-show-visit-folder
+  "q"    mh-show-index-sequenced-messages
+  "r"    mh-show-rescan-folder
+  "s"    mh-search
+  "t"    mh-show-toggle-threads
+  "u"    mh-show-undo-folder
+  "v"    mh-show-visit-folder)
+
+(gnus-define-keys (mh-show-sequence-map "S" mh-show-mode-map)
+  "'"    mh-show-narrow-to-tick
+  "?"    mh-prefix-help
+  "d"    mh-show-delete-msg-from-seq
+  "k"    mh-show-delete-seq
+  "l"    mh-show-list-sequences
+  "n"    mh-show-narrow-to-seq
+  "p"    mh-show-put-msg-in-seq
+  "s"    mh-show-msg-is-in-seq
+  "w"    mh-show-widen)
+
+(define-key mh-show-mode-map "I" mh-inc-spool-map)
+
+(gnus-define-keys (mh-show-junk-map "J" mh-show-mode-map)
+  "?"    mh-prefix-help
+  "b"    mh-show-junk-blacklist
+  "w"    mh-show-junk-whitelist)
+
+(gnus-define-keys (mh-show-ps-print-map "P" mh-show-mode-map)
+  "?"   mh-prefix-help
+  "C"   mh-show-ps-print-toggle-color
+  "F"   mh-show-ps-print-toggle-faces
+  "f"   mh-show-ps-print-msg-file
+  "l"   mh-show-print-msg
+  "p"   mh-show-ps-print-msg)
+
+(gnus-define-keys (mh-show-thread-map "T" mh-show-mode-map)
+  "?"    mh-prefix-help
+  "u"    mh-show-thread-ancestor
+  "p"    mh-show-thread-previous-sibling
+  "n"    mh-show-thread-next-sibling
+  "t"    mh-show-toggle-threads
+  "d"    mh-show-thread-delete
+  "o"    mh-show-thread-refile)
+
+(gnus-define-keys (mh-show-limit-map "/" mh-show-mode-map)
+  "'"    mh-show-narrow-to-tick
+  "?"    mh-prefix-help
+  "c"    mh-show-narrow-to-cc
+  "g"    mh-show-narrow-to-range
+  "m"    mh-show-narrow-to-from
+  "s"    mh-show-narrow-to-subject
+  "t"    mh-show-narrow-to-to
+  "w"    mh-show-widen)
+
+(gnus-define-keys (mh-show-extract-map "X" mh-show-mode-map)
+  "?"    mh-prefix-help
+  "s"    mh-show-store-msg
+  "u"    mh-show-store-msg)
+
+(gnus-define-keys (mh-show-digest-map "D" mh-show-mode-map)
+  "?"    mh-prefix-help
+  " "    mh-show-page-digest
+  "\177" mh-show-page-digest-backwards
+  "b"    mh-show-burst-digest)
+
+(gnus-define-keys (mh-show-mime-map "K" mh-show-mode-map)
+  "?"           mh-prefix-help
+  "a"           mh-mime-save-parts
+  "e"           mh-show-display-with-external-viewer
+  "v"           mh-show-toggle-mime-part
+  "o"           mh-show-save-mime-part
+  "i"           mh-show-inline-mime-part
+  "t"           mh-show-toggle-mime-buttons
+  "\t"          mh-show-next-button
+  [backtab]     mh-show-prev-button
+  "\M-\t"       mh-show-prev-button)
+
+
+
+;;; MH-Show Font Lock
+
+(defun mh-header-field-font-lock (field limit)
+  "Return the value of a header field FIELD to font-lock.
+Argument LIMIT limits search."
+  (if (= (point) limit)
+      nil
+    (let* ((mail-header-end (mh-mail-header-end))
+           (lesser-limit (if (< mail-header-end limit) mail-header-end limit))
+           (case-fold-search t))
+      (when (and (< (point) mail-header-end) ;Only within header
+                 (re-search-forward (format "^%s" field) lesser-limit t))
+        (let ((match-one-b (match-beginning 0))
+              (match-one-e (match-end 0)))
+          (mh-header-field-end)
+          (if (> (point) limit)         ;Don't search for end beyond limit
+              (goto-char limit))
+          (set-match-data (list match-one-b match-one-e
+                                (1+ match-one-e) (point)))
+          t)))))
+
+(defun mh-header-to-font-lock (limit)
+  "Return the value of a header field To to font-lock.
+Argument LIMIT limits search."
+  (mh-header-field-font-lock "To:" limit))
+
+(defun mh-header-cc-font-lock (limit)
+  "Return the value of a header field cc to font-lock.
+Argument LIMIT limits search."
+  (mh-header-field-font-lock "cc:" limit))
+
+(defun mh-header-subject-font-lock (limit)
+  "Return the value of a header field Subject to font-lock.
+Argument LIMIT limits search."
+  (mh-header-field-font-lock "Subject:" limit))
+
+(defun mh-letter-header-font-lock (limit)
+  "Return the entire mail header to font-lock.
+Argument LIMIT limits search."
+  (if (= (point) limit)
+      nil
+    (let* ((mail-header-end (save-match-data (mh-mail-header-end)))
+           (lesser-limit (if (< mail-header-end limit) mail-header-end limit)))
+      (when (mh-in-header-p)
+        (set-match-data (list 1 lesser-limit))
+        (goto-char lesser-limit)
+        t))))
+
+(defun mh-show-font-lock-fontify-region (beg end loudly)
+  "Limit font-lock in `mh-show-mode' to the header.
+
+Used when the option `mh-highlight-citation-style' is set to
+\"Gnus\", leaving the body to be dealt with by Gnus highlighting.
+The region between BEG and END is given over to be fontified and
+LOUDLY controls if a user sees a message about the fontification
+operation."
+  (let ((header-end (mh-mail-header-end)))
+    (cond
+     ((and (< beg header-end)(< end header-end))
+      (font-lock-default-fontify-region beg end loudly))
+     ((and (< beg header-end)(>= end header-end))
+      (font-lock-default-fontify-region beg header-end loudly))
+     (t
+      nil))))
+
+(defvar mh-show-font-lock-keywords
+  '(("^\\(From:\\|Sender:\\)\\(.*\\)"
+     (1 'default)
+     (2 'mh-show-from))
+    (mh-header-to-font-lock
+     (0 'default)
+     (1 'mh-show-to))
+    (mh-header-cc-font-lock
+     (0 'default)
+     (1 'mh-show-cc))
+    ("^\\(Reply-To:\\|Return-Path:\\)\\(.*\\)$"
+     (1 'default)
+     (2 'mh-show-from))
+    (mh-header-subject-font-lock
+     (0 'default)
+     (1 'mh-show-subject))
+    ("^\\(Apparently-To:\\|Newsgroups:\\)\\(.*\\)"
+     (1 'default)
+     (2 'mh-show-cc))
+    ("^\\(In-reply-to\\|Date\\):\\(.*\\)$"
+     (1 'default)
+     (2 'mh-show-date))
+    (mh-letter-header-font-lock
+     (0 'mh-show-header append t)))
+  "Additional expressions to highlight in MH-Show buffers.")
+
+;;;###mh-autoload
+(defun mh-show-font-lock-keywords ()
+  "Return variable `mh-show-font-lock-keywords'."
+  mh-show-font-lock-keywords)
+
+(defvar mh-show-font-lock-keywords-with-cite
+  (let* ((cite-chars "[>|}]")
+         (cite-prefix "A-Za-z")
+         (cite-suffix (concat cite-prefix "0-9_.@-`'\"")))
+    (append
+     mh-show-font-lock-keywords
+     (list
+      ;; Use MATCH-ANCHORED to effectively anchor the regexp left side.
+      `(,cite-chars
+        (,(concat "\\=[ \t]*"
+                  "\\(\\([" cite-prefix "]+[" cite-suffix "]*\\)?"
+                  "\\(" cite-chars "[ \t]*\\)\\)+"
+                  "\\(.*\\)")
+         (beginning-of-line) (end-of-line)
+         (2 font-lock-constant-face nil t)
+         (4 font-lock-comment-face nil t))))))
+  "Additional expressions to highlight in MH-Show buffers.")
+
+;;;###mh-autoload
+(defun mh-show-font-lock-keywords-with-cite ()
+  "Return variable `mh-show-font-lock-keywords-with-cite'."
+  mh-show-font-lock-keywords-with-cite)
+
+
+
+;;; MH-Show Mode
+
+;; Ensure new buffers won't get this mode if default-major-mode is nil.
+(put 'mh-show-mode 'mode-class 'special)
+
+;; Shush compiler.
+(eval-when-compile (defvar font-lock-auto-fontify))
+
+;;;###mh-autoload
+(define-derived-mode mh-show-mode text-mode "MH-Show"
+  "Major mode for showing messages in MH-E.\\<mh-show-mode-map>
+
+The hook `mh-show-mode-hook' is called upon entry to this mode.
+
+See also `mh-folder-mode'.
+
+\\{mh-show-mode-map}"
+  (set (make-local-variable 'mail-header-separator) mh-mail-header-separator)
+  (setq paragraph-start (default-value 'paragraph-start))
+  (mh-show-unquote-From)
+  (mh-show-xface)
+  (mh-show-addr)
+  (setq buffer-invisibility-spec '((vanish . t) t))
+  (set (make-local-variable 'line-move-ignore-invisible) t)
+  (make-local-variable 'font-lock-defaults)
+  ;;(set (make-local-variable 'font-lock-support-mode) nil)
+  (cond
+   ((equal mh-highlight-citation-style 'font-lock)
+    (setq font-lock-defaults '(mh-show-font-lock-keywords-with-cite t)))
+   ((equal mh-highlight-citation-style 'gnus)
+    (setq font-lock-defaults '((mh-show-font-lock-keywords)
+                               t nil nil nil
+                               (font-lock-fontify-region-function
+                                . mh-show-font-lock-fontify-region)))
+    (mh-gnus-article-highlight-citation))
+   (t
+    (setq font-lock-defaults '(mh-show-font-lock-keywords t))))
+  (if (and mh-xemacs-flag
+           font-lock-auto-fontify)
+      (turn-on-font-lock))
+  (set (make-local-variable 'tool-bar-map) mh-show-tool-bar-map)
+  (mh-funcall-if-exists mh-tool-bar-init :show)
+  (when mh-decode-mime-flag
+    (mh-make-local-hook 'kill-buffer-hook)
+    (add-hook 'kill-buffer-hook 'mh-mime-cleanup nil t))
+  (easy-menu-add mh-show-sequence-menu)
+  (easy-menu-add mh-show-message-menu)
+  (easy-menu-add mh-show-folder-menu)
+  (make-local-variable 'mh-show-folder-buffer)
+  (buffer-disable-undo)
+  (setq buffer-read-only t)
+  (use-local-map mh-show-mode-map))
+
+
+
+;;; Support Routines
+
+(defun mh-show-unquote-From ()
+  "Decode >From at beginning of lines for `mh-show-mode'."
+  (save-excursion
+    (let ((modified (buffer-modified-p))
+          (case-fold-search nil)
+          (buffer-read-only nil))
+      (goto-char (mh-mail-header-end))
+      (while (re-search-forward "^>From" nil t)
+        (replace-match "From"))
+      (set-buffer-modified-p modified))))
+
+;;;###mh-autoload
+(defun mh-show-addr ()
+  "Use `goto-address'."
+  (when mh-show-use-goto-addr-flag
+    (require 'goto-addr nil t)
+    (if (fboundp 'goto-address)
+        (goto-address))))
+
+;;;###mh-autoload
+(defun mh-gnus-article-highlight-citation ()
+  "Highlight cited text in current buffer using Gnus."
+  (interactive)
+  ;; Don't allow Gnus to create buttons while highlighting, maybe this is bad
+  ;; style?
+  (flet ((gnus-article-add-button (&rest args) nil))
+    (let* ((modified (buffer-modified-p))
+           (gnus-article-buffer (buffer-name))
+           (gnus-cite-face-list `(,@(cdr gnus-cite-face-list)
+                                    ,(car gnus-cite-face-list))))
+      (gnus-article-highlight-citation t)
+      (set-buffer-modified-p modified))))
+
+(provide 'mh-show)
+
+;; Local Variables:
+;; indent-tabs-mode: nil
+;; sentence-end-double-space: nil
+;; End:
+
+;; arch-tag: 8607a80a-9b5c-43a7-a25d-d7e4a848c25b
+;;; mh-show.el ends here
--- a/lisp/mh-e/mh-speed.el	Thu Jan 26 02:23:05 2006 +0000
+++ b/lisp/mh-e/mh-speed.el	Wed Feb 01 10:07:17 2006 +0000
@@ -1,6 +1,6 @@
-;;; mh-speed.el --- Speedbar interface for MH-E.
+;;; mh-speed.el --- MH-E speedbar support
 
-;; Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+;; Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
 
 ;; Author: Satyaki Das <satyaki@theforce.stanford.edu>
 ;; Maintainer: Bill Wohler <wohler@newt.com>
@@ -25,23 +25,21 @@
 ;; Boston, MA 02110-1301, USA.
 
 ;;; Commentary:
-;;   Future versions should only use flists.
 
-;; Speedbar support for MH-E package.
+;; Future versions should only use flists.
 
 ;;; Change Log:
 
 ;;; Code:
 
-;;(message "> mh-speed")
-(eval-when-compile (require 'mh-acros))
+(require 'mh-e)
 (mh-require-cl)
-(require 'mh-e)
+
+(require 'gnus-util)
 (require 'speedbar)
 (require 'timer)
-;;(message "< mh-speed")
 
-;; Global variables
+;; Global variables.
 (defvar mh-speed-refresh-flag nil)
 (defvar mh-speed-last-selected-folder nil)
 (defvar mh-speed-folder-map (make-hash-table :test #'equal))
@@ -50,7 +48,10 @@
 (defvar mh-speed-flists-timer nil)
 (defvar mh-speed-partial-line "")
 
-;; Add our stealth update function
+
+
+;;; Speedbar Hook
+
 (unless (member 'mh-speed-stealth-update
                 (cdr (assoc "files" speedbar-stealthy-function-list)))
   ;; Is changing constant lists in elisp safe?
@@ -59,7 +60,132 @@
   (push 'mh-speed-stealth-update
         (cdr (assoc "files" speedbar-stealthy-function-list))))
 
-;; Functions called by speedbar to initialize display...
+
+
+;;; Speedbar Menus
+
+(defvar mh-folder-speedbar-menu-items
+  '("--"
+    ["Visit Folder" mh-speed-view
+     (save-excursion
+       (set-buffer speedbar-buffer)
+       (get-text-property (line-beginning-position) 'mh-folder))]
+    ["Expand Nested Folders" mh-speed-expand-folder
+     (and (get-text-property (line-beginning-position) 'mh-children-p)
+          (not (get-text-property (line-beginning-position) 'mh-expanded)))]
+    ["Contract Nested Folders" mh-speed-contract-folder
+     (and (get-text-property (line-beginning-position) 'mh-children-p)
+          (get-text-property (line-beginning-position) 'mh-expanded))]
+    ["Refresh Speedbar" mh-speed-refresh t])
+  "Extra menu items for speedbar.")
+
+(defvar mh-show-speedbar-menu-items mh-folder-speedbar-menu-items)
+(defvar mh-letter-speedbar-menu-items mh-folder-speedbar-menu-items)
+
+
+
+;;; Speedbar Keys
+
+(defvar mh-folder-speedbar-key-map (speedbar-make-specialized-keymap)
+  "Specialized speedbar keymap for MH-E buffers.")
+
+(gnus-define-keys mh-folder-speedbar-key-map
+  "+"           mh-speed-expand-folder
+  "-"           mh-speed-contract-folder
+  "\r"          mh-speed-view
+  "r"           mh-speed-refresh)
+
+(defvar mh-show-speedbar-key-map mh-folder-speedbar-key-map)
+(defvar mh-letter-speedbar-key-map mh-folder-speedbar-key-map)
+
+
+
+;;; Speedbar Commands
+
+;; Alphabetical.
+
+(defalias 'mh-speed-contract-folder 'mh-speed-toggle)
+
+(defalias 'mh-speed-expand-folder 'mh-speed-toggle)
+
+(defun mh-speed-refresh ()
+  "Regenerates the list of folders in the speedbar.
+
+Run this command if you've added or deleted a folder, or want to
+update the unseen message count before the next automatic
+update."
+  (interactive)
+  (mh-speed-flists t)
+  (mh-speed-invalidate-map ""))
+
+(defun mh-speed-stealth-update (&optional force)
+  "Do stealth update.
+With non-nil FORCE, the update is always carried out."
+  (cond ((save-excursion (set-buffer speedbar-buffer)
+                         (get-text-property (point-min) 'mh-level))
+         ;; Execute this hook and *don't* run anything else
+         (mh-speed-update-current-folder force)
+         nil)
+        ;; Otherwise on to your regular programming
+        (t t)))
+
+(defun mh-speed-toggle (&rest args)
+  "Toggle the display of child folders in the speedbar.
+The optional ARGS from speedbar are ignored."
+  (interactive)
+  (declare (ignore args))
+  (beginning-of-line)
+  (let ((parent (get-text-property (point) 'mh-folder))
+        (kids-p (get-text-property (point) 'mh-children-p))
+        (expanded (get-text-property (point) 'mh-expanded))
+        (level (get-text-property (point) 'mh-level))
+        (point (point))
+        start-region)
+    (speedbar-with-writable
+      (cond ((not kids-p) nil)
+            (expanded
+             (forward-line)
+             (setq start-region (point))
+             (while (and (get-text-property (point) 'mh-level)
+                         (> (get-text-property (point) 'mh-level) level))
+               (let ((folder (get-text-property (point) 'mh-folder)))
+                 (when (gethash folder mh-speed-folder-map)
+                   (set-marker (gethash folder mh-speed-folder-map) nil)
+                   (remhash folder mh-speed-folder-map)))
+               (forward-line))
+             (delete-region start-region (point))
+             (forward-line -1)
+             (speedbar-change-expand-button-char ?+)
+             (add-text-properties
+              (line-beginning-position) (1+ (line-beginning-position))
+              '(mh-expanded nil)))
+            (t
+             (forward-line)
+             (mh-speed-add-buttons parent (1+ level))
+             (goto-char point)
+             (speedbar-change-expand-button-char ?-)
+             (add-text-properties
+              (line-beginning-position) (1+ (line-beginning-position))
+              `(mh-expanded t)))))))
+
+(defun mh-speed-view (&rest args)
+  "Visits the selected folder just as if you had used \\<mh-folder-mode-map>\\[mh-visit-folder].
+The optional ARGS from speedbar are ignored."
+  (interactive)
+  (declare (ignore args))
+  (let* ((folder (get-text-property (line-beginning-position) 'mh-folder))
+         (range (and (stringp folder)
+                     (mh-read-range "Scan" folder t nil nil
+                                    mh-interpret-number-as-range-flag))))
+    (when (stringp folder)
+      (speedbar-with-attached-buffer
+       (mh-visit-folder folder range)
+       (delete-other-windows)))))
+
+
+
+;;; Support Routines
+
 ;;;###mh-autoload
 (defun mh-folder-speedbar-buttons (buffer)
   "Interface function to create MH-E speedbar buffer.
@@ -86,37 +212,6 @@
 ;;;###mh-autoload
 (defalias 'mh-letter-speedbar-buttons 'mh-folder-speedbar-buttons)
 
-;; Keymaps for speedbar...
-(defvar mh-folder-speedbar-key-map (speedbar-make-specialized-keymap)
-  "Specialized speedbar keymap for MH-E buffers.")
-(gnus-define-keys mh-folder-speedbar-key-map
-  "+"           mh-speed-expand-folder
-  "-"           mh-speed-contract-folder
-  "\r"          mh-speed-view
-  "r"           mh-speed-refresh)
-
-(defvar mh-show-speedbar-key-map mh-folder-speedbar-key-map)
-(defvar mh-letter-speedbar-key-map mh-folder-speedbar-key-map)
-
-;; Menus for speedbar...
-(defvar mh-folder-speedbar-menu-items
-  '("--"
-    ["Visit Folder" mh-speed-view
-     (save-excursion
-       (set-buffer speedbar-buffer)
-       (get-text-property (line-beginning-position) 'mh-folder))]
-    ["Expand Nested Folders" mh-speed-expand-folder
-     (and (get-text-property (line-beginning-position) 'mh-children-p)
-          (not (get-text-property (line-beginning-position) 'mh-expanded)))]
-    ["Contract Nested Folders" mh-speed-contract-folder
-     (and (get-text-property (line-beginning-position) 'mh-children-p)
-          (get-text-property (line-beginning-position) 'mh-expanded))]
-    ["Refresh Speedbar" mh-speed-refresh t])
-  "Extra menu items for speedbar.")
-
-(defvar mh-show-speedbar-menu-items mh-folder-speedbar-menu-items)
-(defvar mh-letter-speedbar-menu-items mh-folder-speedbar-menu-items)
-
 (defmacro mh-speed-select-attached-frame ()
   "Compatibility macro to handle speedbar versions 0.11a and 0.14beta4."
   (cond ((fboundp 'dframe-select-attached-frame)
@@ -167,6 +262,19 @@
     (when (eq lastf speedbar-frame)
       (setq mh-speed-refresh-flag t))))
 
+(defun mh-speed-highlight (folder face)
+  "Set FOLDER to FACE."
+  (save-excursion
+    (speedbar-with-writable
+      (goto-char (gethash folder mh-speed-folder-map (point)))
+      (beginning-of-line)
+      (if (re-search-forward "([1-9][0-9]*/[0-9]+)" (line-end-position) t)
+          (setq face (mh-speed-bold-face face))
+        (setq face (mh-speed-normal-face face)))
+      (beginning-of-line)
+      (when (re-search-forward "\\[.\\] " (line-end-position) t)
+        (put-text-property (point) (line-end-position) 'face face)))))
+
 (defun mh-speed-normal-face (face)
   "Return normal face for given FACE."
   (cond ((eq face 'mh-speedbar-folder-with-unseen-messages)
@@ -183,30 +291,6 @@
          'mh-speedbar-selected-folder-with-unseen-messages)
         (t face)))
 
-(defun mh-speed-highlight (folder face)
-  "Set FOLDER to FACE."
-  (save-excursion
-    (speedbar-with-writable
-      (goto-char (gethash folder mh-speed-folder-map (point)))
-      (beginning-of-line)
-      (if (re-search-forward "([1-9][0-9]*/[0-9]+)" (line-end-position) t)
-          (setq face (mh-speed-bold-face face))
-        (setq face (mh-speed-normal-face face)))
-      (beginning-of-line)
-      (when (re-search-forward "\\[.\\] " (line-end-position) t)
-        (put-text-property (point) (line-end-position) 'face face)))))
-
-(defun mh-speed-stealth-update (&optional force)
-  "Do stealth update.
-With non-nil FORCE, the update is always carried out."
-  (cond ((save-excursion (set-buffer speedbar-buffer)
-                         (get-text-property (point-min) 'mh-level))
-         ;; Execute this hook and *don't* run anything else
-         (mh-speed-update-current-folder force)
-         nil)
-        ;; Otherwise on to your regular programming
-        (t t)))
-
 (defun mh-speed-goto-folder (folder)
   "Move point to line containing FOLDER.
 The function will expand out parent folders of FOLDER if needed."
@@ -295,64 +379,6 @@
                           mh-level ,level))))))
      folder-list)))
 
-;;;###mh-autoload
-(defun mh-speed-toggle (&rest args)
-  "Toggle the display of child folders in the speedbar.
-The optional ARGS from speedbar are ignored."
-  (interactive)
-  (declare (ignore args))
-  (beginning-of-line)
-  (let ((parent (get-text-property (point) 'mh-folder))
-        (kids-p (get-text-property (point) 'mh-children-p))
-        (expanded (get-text-property (point) 'mh-expanded))
-        (level (get-text-property (point) 'mh-level))
-        (point (point))
-        start-region)
-    (speedbar-with-writable
-      (cond ((not kids-p) nil)
-            (expanded
-             (forward-line)
-             (setq start-region (point))
-             (while (and (get-text-property (point) 'mh-level)
-                         (> (get-text-property (point) 'mh-level) level))
-               (let ((folder (get-text-property (point) 'mh-folder)))
-                 (when (gethash folder mh-speed-folder-map)
-                   (set-marker (gethash folder mh-speed-folder-map) nil)
-                   (remhash folder mh-speed-folder-map)))
-               (forward-line))
-             (delete-region start-region (point))
-             (forward-line -1)
-             (speedbar-change-expand-button-char ?+)
-             (add-text-properties
-              (line-beginning-position) (1+ (line-beginning-position))
-              '(mh-expanded nil)))
-            (t
-             (forward-line)
-             (mh-speed-add-buttons parent (1+ level))
-             (goto-char point)
-             (speedbar-change-expand-button-char ?-)
-             (add-text-properties
-              (line-beginning-position) (1+ (line-beginning-position))
-              `(mh-expanded t)))))))
-
-(defalias 'mh-speed-expand-folder 'mh-speed-toggle)
-(defalias 'mh-speed-contract-folder 'mh-speed-toggle)
-
-;;;###mh-autoload
-(defun mh-speed-view (&rest args)
-  "Visits the selected folder just as if you had used \\<mh-folder-mode-map>\\[mh-visit-folder].
-The optional ARGS from speedbar are ignored."
-  (interactive)
-  (declare (ignore args))
-  (let* ((folder (get-text-property (line-beginning-position) 'mh-folder))
-         (range (and (stringp folder)
-                     (mh-read-range "Scan" folder t nil nil
-                                    mh-interpret-number-as-range-flag))))
-    (when (stringp folder)
-      (speedbar-with-attached-buffer
-       (mh-visit-folder folder range)
-       (delete-other-windows)))))
-
 (defvar mh-speed-current-folder nil)
 (defvar mh-speed-flists-folder nil)
 
@@ -415,6 +441,7 @@
                                    'mh-speed-parse-flists-output)))))))
 
 ;; Copied from mh-make-folder-list-filter...
+;; XXX Refactor to use mh-make-folder-list-filer?
 (defun mh-speed-parse-flists-output (process output)
   "Parse the incremental results from flists.
 PROCESS is the flists process and OUTPUT is the results that must
@@ -506,17 +533,23 @@
           (setq mh-speed-last-selected-folder nil)
           (setq mh-speed-refresh-flag t)))
       (when (equal folder "")
-        (clrhash mh-sub-folders-cache)))))
-
-(defun mh-speed-refresh ()
-  "Regenerates the list of folders in the speedbar.
+        (mh-clear-sub-folders-cache)))))
 
-Run this command if you've added or deleted a folder, or want to
-update the unseen message count before the next automatic
-update."
-  (interactive)
-  (mh-speed-flists t)
-  (mh-speed-invalidate-map ""))
+;; Make it slightly more general to allow for [ ] buttons to be
+;; changed to [+].
+(defun mh-speedbar-change-expand-button-char (char)
+  "Change the expansion button character to CHAR for the current line."
+  (save-excursion
+    (beginning-of-line)
+    (if (re-search-forward "\\[.\\]" (line-end-position) t)
+        (speedbar-with-writable
+          (backward-char 2)
+          (delete-char 1)
+          (insert-char char 1 t)
+          (put-text-property (point) (1- (point)) 'invisible nil)
+          ;; make sure we fix the image on the text here.
+          (mh-funcall-if-exists
+           speedbar-insert-image-button-maybe (- (point) 2) 3)))))
 
 ;;;###mh-autoload
 (defun mh-speed-add-folder (folder)
@@ -546,22 +579,6 @@
         (mh-speed-toggle))
       (setq mh-speed-refresh-flag t))))
 
-;; Make it slightly more general to allow for [ ] buttons to be changed to
-;; [+].
-(defun mh-speedbar-change-expand-button-char (char)
-  "Change the expansion button character to CHAR for the current line."
-  (save-excursion
-    (beginning-of-line)
-    (if (re-search-forward "\\[.\\]" (line-end-position) t)
-        (speedbar-with-writable
-          (backward-char 2)
-          (delete-char 1)
-          (insert-char char 1 t)
-          (put-text-property (point) (1- (point)) 'invisible nil)
-          ;; make sure we fix the image on the text here.
-          (mh-funcall-if-exists
-           speedbar-insert-image-button-maybe (- (point) 2) 3)))))
-
 (provide 'mh-speed)
 
 ;; Local Variables:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lisp/mh-e/mh-thread.el	Wed Feb 01 10:07:17 2006 +0000
@@ -0,0 +1,884 @@
+;;; mh-thread.el --- MH-E threading support
+
+;; Copyright (C) 2002, 2003, 2004, 2006 Free Software Foundation, Inc.
+
+;; Author: Satyaki Das <satyaki@theforce.stanford.edu>
+;; Maintainer: Bill Wohler <wohler@newt.com>
+;; Keywords: mail
+;; See: mh-e.el
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
+
+;;; Commentary:
+
+;; The threading portion of this files tries to implement the
+;; algorithm described at:
+;;   http://www.jwz.org/doc/threading.html
+;; It also begins to implement the IMAP Threading extension RFC. The
+;; implementation lacks the reference and subject canonicalization of
+;; the RFC.
+
+;; In the presentation buffer, children messages are shown indented
+;; with either [ ] or < > around them. Square brackets ([ ]) denote
+;; that the algorithm can point out some headers which when taken
+;; together implies that the unindented message is an ancestor of the
+;; indented message. If no such proof exists then angles (< >) are
+;; used.
+
+;; If threading is slow on your machine, compile this file. Of all the
+;; files in MH-E, this one really benefits from compilation.
+
+;; Some issues and problems are as follows:
+
+;;  (1) Scan truncates the fields at length 512. So longer
+;;      references: headers get mutilated. The same kind of MH
+;;      format string works when composing messages. Is there a way
+;;      to avoid this? My scan command is as follows:
+;;        scan +folder -width 10000 \
+;;             -format "%(msg)\n%{message-id}\n%{references}\n%{subject}\n"
+;;      I would really appreciate it if someone would help me with this.
+
+;;  (2) Implement heuristics to recognize message identifiers in
+;;      In-Reply-To: header. Right now it just assumes that the last
+;;      text between angles (< and >) is the message identifier.
+;;      There is the chance that this will incorrectly use an email
+;;      address like a message identifier.
+
+;;  (3) Error checking of found message identifiers should be done.
+
+;;  (4) Since this breaks the assumption that message indices
+;;      increase as one goes down the buffer, the binary search
+;;      based mh-goto-msg doesn't work. I have a simpler replacement
+;;      which may be less efficient.
+
+;;  (5) Better canonicalizing for message identifier and subject
+;;      strings.
+
+;;; Change Log:
+
+;;; Code:
+
+(require 'mh-e)
+(require 'mh-scan)
+
+(mh-defstruct (mh-thread-message (:conc-name mh-message-)
+                                 (:constructor mh-thread-make-message))
+  (id nil)
+  (references ())
+  (subject "")
+  (subject-re-p nil))
+
+(mh-defstruct (mh-thread-container (:conc-name mh-container-)
+                                   (:constructor mh-thread-make-container))
+  message parent children
+  (real-child-p t))
+
+(defvar mh-thread-id-hash nil
+  "Hashtable used to canonicalize message identifiers.")
+(make-variable-buffer-local 'mh-thread-id-hash)
+
+(defvar mh-thread-subject-hash nil
+  "Hashtable used to canonicalize subject strings.")
+(make-variable-buffer-local 'mh-thread-subject-hash)
+
+(defvar mh-thread-id-table nil
+  "Thread ID table maps from message identifiers to message containers.")
+(make-variable-buffer-local 'mh-thread-id-table)
+
+(defvar mh-thread-index-id-map nil
+  "Table to look up message identifier from message index.")
+(make-variable-buffer-local 'mh-thread-index-id-map)
+
+(defvar mh-thread-id-index-map nil
+  "Table to look up message index number from message identifier.")
+(make-variable-buffer-local 'mh-thread-id-index-map)
+
+(defvar mh-thread-subject-container-hash nil
+  "Hashtable used to group messages by subject.")
+(make-variable-buffer-local 'mh-thread-subject-container-hash)
+
+(defvar mh-thread-duplicates nil
+  "Hashtable used to associate messages with the same message identifier.")
+(make-variable-buffer-local 'mh-thread-duplicates)
+
+(defvar mh-thread-history ()
+  "Variable to remember the transformations to the thread tree.
+When new messages are added, these transformations are rewound,
+then the links are added from the newly seen messages. Finally
+the transformations are redone to get the new thread tree. This
+makes incremental threading easier.")
+(make-variable-buffer-local 'mh-thread-history)
+
+(defvar mh-thread-body-width nil
+  "Width of scan substring that contains subject and body of message.")
+
+
+
+;;; MH-Folder Commands
+
+;;;###mh-autoload
+(defun mh-thread-ancestor (&optional thread-root-flag)
+  "Display ancestor of current message.
+
+If you do not care for the way a particular thread has turned,
+you can move up the chain of messages with this command. This
+command can also take a prefix argument THREAD-ROOT-FLAG to jump
+to the message that started everything."
+  (interactive "P")
+  (beginning-of-line)
+  (cond ((not (memq 'unthread mh-view-ops))
+         (error "Folder isn't threaded"))
+        ((eobp)
+         (error "No message at point")))
+  (let ((current-level (mh-thread-current-indentation-level)))
+    (cond (thread-root-flag
+           (while (mh-thread-immediate-ancestor))
+           (mh-maybe-show))
+          ((equal current-level 1)
+           (message "Message has no ancestor"))
+          (t (mh-thread-immediate-ancestor)
+             (mh-maybe-show)))))
+
+;;;###mh-autoload
+(defun mh-thread-delete ()
+  "Delete thread."
+  (interactive)
+  (cond ((not (memq 'unthread mh-view-ops))
+         (error "Folder isn't threaded"))
+        ((eobp)
+         (error "No message at point"))
+        (t (let ((region (mh-thread-find-children)))
+             (mh-iterate-on-messages-in-region () (car region) (cadr region)
+               (mh-delete-a-msg nil))
+             (mh-next-msg)))))
+
+;;;###mh-autoload
+(defun mh-thread-next-sibling (&optional previous-flag)
+  "Display next sibling.
+
+With non-nil optional argument PREVIOUS-FLAG jump to the previous
+sibling."
+  (interactive)
+  (cond ((not (memq 'unthread mh-view-ops))
+         (error "Folder isn't threaded"))
+        ((eobp)
+         (error "No message at point")))
+  (beginning-of-line)
+  (let ((point (point))
+        (done nil)
+        (my-level (mh-thread-current-indentation-level)))
+    (while (and (not done)
+                (equal (forward-line (if previous-flag -1 1)) 0)
+                (not (eobp)))
+      (let ((level (mh-thread-current-indentation-level)))
+        (cond ((equal level my-level)
+               (setq done 'success))
+              ((< level my-level)
+               (message "No %s sibling" (if previous-flag "previous" "next"))
+               (setq done 'failure)))))
+    (cond ((eq done 'success) (mh-maybe-show))
+          ((eq done 'failure) (goto-char point))
+          (t (message "No %s sibling" (if previous-flag "previous" "next"))
+             (goto-char point)))))
+
+;;;###mh-autoload
+(defun mh-thread-previous-sibling ()
+  "Display previous sibling."
+  (interactive)
+  (mh-thread-next-sibling t))
+
+;;;###mh-autoload
+(defun mh-thread-refile (folder)
+  "Refile (output) thread into FOLDER."
+  (interactive (list (intern (mh-prompt-for-refile-folder))))
+  (cond ((not (memq 'unthread mh-view-ops))
+         (error "Folder isn't threaded"))
+        ((eobp)
+         (error "No message at point"))
+        (t (let ((region (mh-thread-find-children)))
+             (mh-iterate-on-messages-in-region () (car region) (cadr region)
+               (mh-refile-a-msg nil folder))
+             (mh-next-msg)))))
+
+;;;###mh-autoload
+(defun mh-toggle-threads ()
+  "Toggle threaded view of folder."
+  (interactive)
+  (let ((msg-at-point (mh-get-msg-num nil))
+        (old-buffer-modified-flag (buffer-modified-p))
+        (buffer-read-only nil))
+    (cond ((memq 'unthread mh-view-ops)
+           (unless (mh-valid-view-change-operation-p 'unthread)
+             (error "Can't unthread folder"))
+           (let ((msg-list ()))
+             (goto-char (point-min))
+             (while (not (eobp))
+               (let ((index (mh-get-msg-num nil)))
+                 (when index
+                   (push index msg-list)))
+               (forward-line))
+             (mh-scan-folder mh-current-folder
+                             (mapcar #'(lambda (x) (format "%s" x))
+                                     (mh-coalesce-msg-list msg-list))
+                             t))
+           (when mh-index-data
+             (mh-index-insert-folder-headers)
+             (mh-notate-cur)))
+          (t (mh-thread-folder)
+             (push 'unthread mh-view-ops)))
+    (when msg-at-point (mh-goto-msg msg-at-point t t))
+    (set-buffer-modified-p old-buffer-modified-flag)
+    (mh-recenter nil)))
+
+
+
+;;; Support Routines
+
+(defun mh-thread-current-indentation-level ()
+  "Find the number of spaces by which current message is indented."
+  (save-excursion
+    (let ((address-start-offset (+ mh-cmd-note mh-scan-date-flag-width
+                                   mh-scan-date-width 1))
+          (level 0))
+      (beginning-of-line)
+      (forward-char address-start-offset)
+      (while (char-equal (char-after) ? )
+        (incf level)
+        (forward-char))
+      level)))
+
+(defun mh-thread-immediate-ancestor ()
+  "Jump to immediate ancestor in thread tree."
+  (beginning-of-line)
+  (let ((point (point))
+        (ancestor-level (- (mh-thread-current-indentation-level) 2))
+        (done nil))
+    (if (< ancestor-level 0)
+        nil
+      (while (and (not done) (equal (forward-line -1) 0))
+        (when (equal ancestor-level (mh-thread-current-indentation-level))
+          (setq done t)))
+      (unless done
+        (goto-char point))
+      done)))
+
+(defun mh-thread-find-children ()
+  "Return a region containing the current message and its children.
+The result is returned as a list of two elements. The first is
+the point at the start of the region and the second is the point
+at the end."
+  (beginning-of-line)
+  (if (eobp)
+      nil
+    (let ((address-start-offset (+ mh-cmd-note mh-scan-date-flag-width
+                                   mh-scan-date-width 1))
+          (level (mh-thread-current-indentation-level))
+          spaces begin)
+      (setq begin (point))
+      (setq spaces (format (format "%%%ss" (1+ level)) ""))
+      (forward-line)
+      (block nil
+        (while (not (eobp))
+          (forward-char address-start-offset)
+          (unless (equal (string-match spaces (buffer-substring-no-properties
+                                               (point) (line-end-position)))
+                         0)
+            (beginning-of-line)
+            (backward-char)
+            (return))
+          (forward-line)))
+      (list begin (point)))))
+
+
+
+;;; Thread Creation
+
+(defun mh-thread-folder ()
+  "Generate thread view of folder."
+  (message "Threading %s..." (buffer-name))
+  (mh-thread-initialize)
+  (goto-char (point-min))
+  (mh-remove-all-notation)
+  (let ((msg-list ()))
+    (mh-iterate-on-range msg (cons (point-min) (point-max))
+      (setf (gethash msg mh-thread-scan-line-map) (mh-thread-parse-scan-line))
+      (push msg msg-list))
+    (let* ((range (mh-coalesce-msg-list msg-list))
+           (thread-tree (mh-thread-generate (buffer-name) range)))
+      (delete-region (point-min) (point-max))
+      (mh-thread-print-scan-lines thread-tree)
+      (mh-notate-user-sequences)
+      (mh-notate-deleted-and-refiled)
+      (mh-notate-cur)
+      (message "Threading %s...done" (buffer-name)))))
+
+;;;###mh-autoload
+(defun mh-thread-inc (folder start-point)
+  "Update thread tree for FOLDER.
+All messages after START-POINT are added to the thread tree."
+  (mh-thread-rewind-pruning)
+  (mh-remove-all-notation)
+  (goto-char start-point)
+  (let ((msg-list ()))
+    (while (not (eobp))
+      (let ((index (mh-get-msg-num nil)))
+        (when (numberp index)
+          (push index msg-list)
+          (setf (gethash index mh-thread-scan-line-map)
+                (mh-thread-parse-scan-line)))
+        (forward-line)))
+    (let ((thread-tree (mh-thread-generate folder msg-list))
+          (buffer-read-only nil)
+          (old-buffer-modified-flag (buffer-modified-p)))
+      (delete-region (point-min) (point-max))
+      (mh-thread-print-scan-lines thread-tree)
+      (mh-notate-user-sequences)
+      (mh-notate-deleted-and-refiled)
+      (mh-notate-cur)
+      (set-buffer-modified-p old-buffer-modified-flag))))
+
+(defmacro mh-thread-initialize-hash (var test)
+  "Initialize the hash table in VAR.
+TEST is the test to use when creating a new hash table."
+  (unless (symbolp var) (error "Expected a symbol: %s" var))
+  `(if ,var (clrhash ,var) (setq ,var (make-hash-table :test ,test))))
+
+(defun mh-thread-initialize ()
+  "Make new hash tables, or clear them if already present."
+  (mh-thread-initialize-hash mh-thread-id-hash #'equal)
+  (mh-thread-initialize-hash mh-thread-subject-hash #'equal)
+  (mh-thread-initialize-hash mh-thread-id-table #'eq)
+  (mh-thread-initialize-hash mh-thread-id-index-map #'eq)
+  (mh-thread-initialize-hash mh-thread-index-id-map #'eql)
+  (mh-thread-initialize-hash mh-thread-scan-line-map #'eql)
+  (mh-thread-initialize-hash mh-thread-subject-container-hash #'eq)
+  (mh-thread-initialize-hash mh-thread-duplicates #'eq)
+  (setq mh-thread-history ()))
+
+(defsubst mh-thread-id-container (id)
+  "Given ID, return the corresponding container in `mh-thread-id-table'.
+If no container exists then a suitable container is created and
+the id-table is updated."
+  (when (not id)
+    (error "1"))
+  (or (gethash id mh-thread-id-table)
+      (setf (gethash id mh-thread-id-table)
+            (let ((message (mh-thread-make-message :id id)))
+              (mh-thread-make-container :message message)))))
+
+(defsubst mh-thread-remove-parent-link (child)
+  "Remove parent link of CHILD if it exists."
+  (let* ((child-container (if (mh-thread-container-p child)
+                              child (mh-thread-id-container child)))
+         (parent-container (mh-container-parent child-container)))
+    (when parent-container
+      (setf (mh-container-children parent-container)
+            (loop for elem in (mh-container-children parent-container)
+                  unless (eq child-container elem) collect elem))
+      (setf (mh-container-parent child-container) nil))))
+
+(defsubst mh-thread-add-link (parent child &optional at-end-p)
+  "Add links so that PARENT becomes a parent of CHILD.
+Doesn't make any changes if CHILD is already an ancestor of
+PARENT. If optional argument AT-END-P is non-nil, the CHILD is
+added to the end of the children list of PARENT."
+  (let ((parent-container (cond ((null parent) nil)
+                                ((mh-thread-container-p parent) parent)
+                                (t (mh-thread-id-container parent))))
+        (child-container (if (mh-thread-container-p child)
+                             child (mh-thread-id-container child))))
+    (when (and parent-container
+               (not (mh-thread-ancestor-p child-container parent-container))
+               (not (mh-thread-ancestor-p parent-container child-container)))
+      (mh-thread-remove-parent-link child-container)
+      (cond ((not at-end-p)
+             (push child-container (mh-container-children parent-container)))
+            ((null (mh-container-children parent-container))
+             (push child-container (mh-container-children parent-container)))
+            (t (let ((last-child (mh-container-children parent-container)))
+                 (while (cdr last-child)
+                   (setq last-child (cdr last-child)))
+                 (setcdr last-child (cons child-container nil)))))
+      (setf (mh-container-parent child-container) parent-container))
+    (unless parent-container
+      (mh-thread-remove-parent-link child-container))))
+
+(defun mh-thread-rewind-pruning ()
+  "Restore the thread tree to its state before pruning."
+  (while mh-thread-history
+    (let ((action (pop mh-thread-history)))
+      (cond ((eq (car action) 'DROP)
+             (mh-thread-remove-parent-link (cadr action))
+             (mh-thread-add-link (caddr action) (cadr action)))
+            ((eq (car action) 'PROMOTE)
+             (let ((node (cadr action))
+                   (parent (caddr action))
+                   (children (cdddr action)))
+               (dolist (child children)
+                 (mh-thread-remove-parent-link child)
+                 (mh-thread-add-link node child))
+               (mh-thread-add-link parent node)))
+            ((eq (car action) 'SUBJECT)
+             (let ((node (cadr action)))
+               (mh-thread-remove-parent-link node)
+               (setf (mh-container-real-child-p node) t)))))))
+
+(defun mh-thread-ancestor-p (ancestor successor)
+  "Return t if ANCESTOR is really an ancestor of SUCCESSOR and nil otherwise.
+In the limit, the function returns t if ANCESTOR and SUCCESSOR
+are the same containers."
+  (block nil
+    (while successor
+      (when (eq ancestor successor) (return t))
+      (setq successor (mh-container-parent successor)))
+    nil))
+
+;; Another and may be better approach would be to generate all the info from
+;; the scan which generates the threading info. For now this will have to do.
+;;;###mh-autoload
+(defun mh-thread-parse-scan-line (&optional string)
+  "Parse a scan line.
+If optional argument STRING is given then that is assumed to be
+the scan line. Otherwise uses the line at point as the scan line
+to parse."
+  (let* ((string (or string
+                     (buffer-substring-no-properties (line-beginning-position)
+                                                     (line-end-position))))
+         (address-start (+ mh-cmd-note mh-scan-field-from-start-offset))
+         (body-start (+ mh-cmd-note mh-scan-field-from-end-offset))
+         (first-string (substring string 0 address-start)))
+    (list first-string
+          (substring string address-start (- body-start 2))
+          (substring string body-start)
+          string)))
+
+(defsubst mh-thread-canonicalize-id (id)
+  "Produce canonical string representation for ID.
+This allows cheap string comparison with EQ."
+  (or (and (equal id "") (copy-sequence ""))
+      (gethash id mh-thread-id-hash)
+      (setf (gethash id mh-thread-id-hash) id)))
+
+(defsubst mh-thread-prune-subject (subject)
+  "Prune leading Re:'s, Fwd:'s etc. and trailing (fwd)'s from SUBJECT.
+If the result after pruning is not the empty string then it is
+canonicalized so that subjects can be tested for equality with
+eq. This is done so that all the messages without a subject are
+not put into a single thread."
+  (let ((case-fold-search t)
+        (subject-pruned-flag nil))
+    ;; Prune subject leader
+    (while (or (string-match "^[ \t]*\\(re\\|fwd?\\)\\(\\[[0-9]*\\]\\)?:[ \t]*"
+                             subject)
+               (string-match "^[ \t]*\\[[^\\]][ \t]*" subject))
+      (setq subject-pruned-flag t)
+      (setq subject (substring subject (match-end 0))))
+    ;; Prune subject trailer
+    (while (or (string-match "(fwd)$" subject)
+               (string-match "[ \t]+$" subject))
+      (setq subject-pruned-flag t)
+      (setq subject (substring subject 0 (match-beginning 0))))
+    ;; Canonicalize subject only if it is non-empty
+    (cond ((equal subject "") (values subject subject-pruned-flag))
+          (t (values
+              (or (gethash subject mh-thread-subject-hash)
+                  (setf (gethash subject mh-thread-subject-hash) subject))
+              subject-pruned-flag)))))
+
+(defsubst mh-thread-group-by-subject (roots)
+  "Group the set of message containers, ROOTS based on subject.
+Bug: Check for and make sure that something without Re: is made
+the parent in preference to something that has it."
+  (clrhash mh-thread-subject-container-hash)
+  (let ((results ()))
+    (dolist (root roots)
+      (let* ((subject (mh-thread-container-subject root))
+             (parent (gethash subject mh-thread-subject-container-hash)))
+        (cond (parent (mh-thread-remove-parent-link root)
+                      (mh-thread-add-link parent root t)
+                      (setf (mh-container-real-child-p root) nil)
+                      (push `(SUBJECT ,root) mh-thread-history))
+              (t
+               (setf (gethash subject mh-thread-subject-container-hash) root)
+               (push root results)))))
+    (nreverse results)))
+
+(defun mh-thread-container-subject (container)
+  "Return the subject of CONTAINER.
+If CONTAINER is empty return the subject info of one of its
+children."
+  (cond ((and (mh-container-message container)
+              (mh-message-id (mh-container-message container)))
+         (mh-message-subject (mh-container-message container)))
+        (t (block nil
+             (dolist (kid (mh-container-children container))
+               (when (and (mh-container-message kid)
+                          (mh-message-id (mh-container-message kid)))
+                 (let ((kid-message (mh-container-message kid)))
+                   (return (mh-message-subject kid-message)))))
+             (error "This can't happen")))))
+
+(defsubst mh-thread-update-id-index-maps (id index)
+  "Message with id, ID is the message in INDEX.
+The function also checks for duplicate messages (that is multiple
+messages with the same ID). These messages are put in the
+`mh-thread-duplicates' hash table."
+  (let ((old-index (gethash id mh-thread-id-index-map)))
+    (when old-index (push old-index (gethash id mh-thread-duplicates)))
+    (setf (gethash id mh-thread-id-index-map) index)
+    (setf (gethash index mh-thread-index-id-map) id)))
+
+(defsubst mh-thread-get-message-container (message)
+  "Return container which has MESSAGE in it.
+If there is no container present then a new container is
+allocated."
+  (let* ((id (mh-message-id message))
+         (container (gethash id mh-thread-id-table)))
+    (cond (container (setf (mh-container-message container) message)
+                     container)
+          (t (setf (gethash id mh-thread-id-table)
+                   (mh-thread-make-container :message message))))))
+
+(defsubst mh-thread-get-message (id subject-re-p subject refs)
+  "Return appropriate message.
+Otherwise update message already present to have the proper ID,
+SUBJECT-RE-P, SUBJECT and REFS fields."
+  (let* ((container (gethash id mh-thread-id-table))
+         (message (if container (mh-container-message container) nil)))
+    (cond (message
+           (setf (mh-message-subject-re-p message) subject-re-p)
+           (setf (mh-message-subject message) subject)
+           (setf (mh-message-id message) id)
+           (setf (mh-message-references message) refs)
+           message)
+          (container
+           (setf (mh-container-message container)
+                 (mh-thread-make-message :id id :references refs
+                                         :subject subject
+                                         :subject-re-p subject-re-p)))
+          (t (let ((message (mh-thread-make-message :id id :references refs
+                                                    :subject-re-p subject-re-p
+                                                    :subject subject)))
+               (prog1 message
+                 (mh-thread-get-message-container message)))))))
+
+(defvar mh-message-id-regexp "^<.*@.*>$"
+  "Regexp to recognize whether a string is a message identifier.")
+
+;;;###mh-autoload
+(defun mh-thread-generate (folder msg-list)
+  "Scan FOLDER to get info for threading.
+Only information about messages in MSG-LIST are added to the tree."
+  (with-temp-buffer
+    (mh-thread-set-tables folder)
+    (when msg-list
+      (apply
+       #'call-process (expand-file-name mh-scan-prog mh-progs) nil '(t nil) nil
+       "-width" "10000" "-format"
+       "%(msg)\n%{message-id}\n%{references}\n%{in-reply-to}\n%{subject}\n"
+       folder (mapcar #'(lambda (x) (format "%s" x)) msg-list)))
+    (goto-char (point-min))
+    (let ((roots ())
+          (case-fold-search t))
+      (block nil
+        (while (not (eobp))
+          (block process-message
+            (let* ((index-line
+                    (prog1 (buffer-substring (point) (line-end-position))
+                      (forward-line)))
+                   (index (string-to-number index-line))
+                   (id (prog1 (buffer-substring (point) (line-end-position))
+                         (forward-line)))
+                   (refs (prog1 (buffer-substring (point) (line-end-position))
+                           (forward-line)))
+                   (in-reply-to (prog1 (buffer-substring (point)
+                                                         (line-end-position))
+                                  (forward-line)))
+                   (subject (prog1
+                                (buffer-substring (point) (line-end-position))
+                              (forward-line)))
+                   (subject-re-p nil))
+              (unless (gethash index mh-thread-scan-line-map)
+                (return-from process-message))
+              (unless (integerp index) (return)) ;Error message here
+              (multiple-value-setq (subject subject-re-p)
+                (mh-thread-prune-subject subject))
+              (setq in-reply-to (mh-thread-process-in-reply-to in-reply-to))
+              (setq refs (loop for x in (append (split-string refs) in-reply-to)
+                               when (string-match mh-message-id-regexp x)
+                               collect x))
+              (setq id (mh-thread-canonicalize-id id))
+              (mh-thread-update-id-index-maps id index)
+              (setq refs (mapcar #'mh-thread-canonicalize-id refs))
+              (mh-thread-get-message id subject-re-p subject refs)
+              (do ((ancestors refs (cdr ancestors)))
+                  ((null (cdr ancestors))
+                   (when (car ancestors)
+                     (mh-thread-remove-parent-link id)
+                     (mh-thread-add-link (car ancestors) id)))
+                (mh-thread-add-link (car ancestors) (cadr ancestors)))))))
+      (maphash #'(lambda (k v)
+                   (declare (ignore k))
+                   (when (null (mh-container-parent v))
+                     (push v roots)))
+               mh-thread-id-table)
+      (setq roots (mh-thread-prune-containers roots))
+      (prog1 (setq roots (mh-thread-group-by-subject roots))
+        (let ((history mh-thread-history))
+          (set-buffer folder)
+          (setq mh-thread-history history))))))
+
+(defun mh-thread-set-tables (folder)
+  "Use the tables of FOLDER in current buffer."
+  (flet ((mh-get-table (symbol)
+                       (save-excursion
+                         (set-buffer folder)
+                         (symbol-value symbol))))
+    (setq mh-thread-id-hash (mh-get-table 'mh-thread-id-hash))
+    (setq mh-thread-subject-hash (mh-get-table 'mh-thread-subject-hash))
+    (setq mh-thread-id-table (mh-get-table 'mh-thread-id-table))
+    (setq mh-thread-id-index-map (mh-get-table 'mh-thread-id-index-map))
+    (setq mh-thread-index-id-map (mh-get-table 'mh-thread-index-id-map))
+    (setq mh-thread-scan-line-map (mh-get-table 'mh-thread-scan-line-map))
+    (setq mh-thread-subject-container-hash
+          (mh-get-table 'mh-thread-subject-container-hash))
+    (setq mh-thread-duplicates (mh-get-table 'mh-thread-duplicates))
+    (setq mh-thread-history (mh-get-table 'mh-thread-history))))
+
+(defun mh-thread-process-in-reply-to (reply-to-header)
+  "Extract message id's from REPLY-TO-HEADER.
+Ideally this should have some regexp which will try to guess if a
+string between < and > is a message id and not an email address.
+For now it will take the last string inside angles."
+  (let ((end (mh-search-from-end ?> reply-to-header)))
+    (when (numberp end)
+      (let ((begin (mh-search-from-end ?< (substring reply-to-header 0 end))))
+        (when (numberp begin)
+          (list (substring reply-to-header begin (1+ end))))))))
+
+(defun mh-thread-prune-containers (roots)
+  "Prune empty containers in the containers ROOTS."
+  (let ((dfs-ordered-nodes ())
+        (work-list roots))
+    (while work-list
+      (let ((node (pop work-list)))
+        (dolist (child (mh-container-children node))
+          (push child work-list))
+        (push node dfs-ordered-nodes)))
+    (while dfs-ordered-nodes
+      (let ((node (pop dfs-ordered-nodes)))
+        (cond ((gethash (mh-message-id (mh-container-message node))
+                        mh-thread-id-index-map)
+               ;; Keep it
+               (setf (mh-container-children node)
+                     (mh-thread-sort-containers (mh-container-children node))))
+              ((and (mh-container-children node)
+                    (or (null (cdr (mh-container-children node)))
+                        (mh-container-parent node)))
+               ;; Promote kids
+               (let ((children ()))
+                 (dolist (kid (mh-container-children node))
+                   (mh-thread-remove-parent-link kid)
+                   (mh-thread-add-link (mh-container-parent node) kid)
+                   (push kid children))
+                 (push `(PROMOTE ,node ,(mh-container-parent node) ,@children)
+                       mh-thread-history)
+                 (mh-thread-remove-parent-link node)))
+              ((mh-container-children node)
+               ;; Promote the first orphan to parent and add the other kids as
+               ;; his children
+               (setf (mh-container-children node)
+                     (mh-thread-sort-containers (mh-container-children node)))
+               (let ((new-parent (car (mh-container-children node)))
+                     (other-kids (cdr (mh-container-children node))))
+                 (mh-thread-remove-parent-link new-parent)
+                 (dolist (kid other-kids)
+                   (mh-thread-remove-parent-link kid)
+                   (setf (mh-container-real-child-p kid) nil)
+                   (mh-thread-add-link new-parent kid t))
+                 (push `(PROMOTE ,node ,(mh-container-parent node)
+                                 ,new-parent ,@other-kids)
+                       mh-thread-history)
+                 (mh-thread-remove-parent-link node)))
+              (t
+               ;; Drop it
+               (push `(DROP ,node ,(mh-container-parent node))
+                     mh-thread-history)
+               (mh-thread-remove-parent-link node)))))
+    (let ((results ()))
+      (maphash #'(lambda (k v)
+                   (declare (ignore k))
+                   (when (and (null (mh-container-parent v))
+                              (gethash (mh-message-id (mh-container-message v))
+                                       mh-thread-id-index-map))
+                     (push v results)))
+               mh-thread-id-table)
+      (mh-thread-sort-containers results))))
+
+(defun mh-thread-sort-containers (containers)
+  "Sort a list of message CONTAINERS to be in ascending order wrt index."
+  (sort containers
+        #'(lambda (x y)
+            (when (and (mh-container-message x) (mh-container-message y))
+              (let* ((id-x (mh-message-id (mh-container-message x)))
+                     (id-y (mh-message-id (mh-container-message y)))
+                     (index-x (gethash id-x mh-thread-id-index-map))
+                     (index-y (gethash id-y mh-thread-id-index-map)))
+                (and (integerp index-x) (integerp index-y)
+                     (< index-x index-y)))))))
+
+(defvar mh-thread-last-ancestor)
+
+;;;###mh-autoload
+(defun mh-thread-print-scan-lines (thread-tree)
+  "Print scan lines in THREAD-TREE in threaded mode."
+  (let ((mh-thread-body-width (- (window-width) mh-cmd-note
+                                 (1- mh-scan-field-subject-start-offset)))
+        (mh-thread-last-ancestor nil))
+    (if (null mh-index-data)
+        (mh-thread-generate-scan-lines thread-tree -2)
+      (loop for x in (mh-index-group-by-folder)
+            do (let* ((old-map mh-thread-scan-line-map)
+                      (mh-thread-scan-line-map (make-hash-table)))
+                 (setq mh-thread-last-ancestor nil)
+                 (loop for msg in (cdr x)
+                       do (let ((v (gethash msg old-map)))
+                            (when v
+                              (setf (gethash msg mh-thread-scan-line-map) v))))
+                 (when (> (hash-table-count mh-thread-scan-line-map) 0)
+                   (insert (if (bobp) "" "\n") (car x) "\n")
+                   (mh-thread-generate-scan-lines thread-tree -2))))
+      (mh-index-create-imenu-index))))
+
+(defun mh-thread-generate-scan-lines (tree level)
+  "Generate scan lines.
+TREE is the hierarchical tree of messages, SCAN-LINE-MAP maps
+message indices to the corresponding scan lines and LEVEL used to
+determine indentation of the message."
+  (cond ((null tree) nil)
+        ((mh-thread-container-p tree)
+         (let* ((message (mh-container-message tree))
+                (id (mh-message-id message))
+                (index (gethash id mh-thread-id-index-map))
+                (duplicates (gethash id mh-thread-duplicates))
+                (new-level (+ level 2))
+                (dupl-flag t)
+                (force-angle-flag nil)
+                (increment-level-flag nil))
+           (dolist (scan-line (mapcar (lambda (x)
+                                        (gethash x mh-thread-scan-line-map))
+                                      (reverse (cons index duplicates))))
+             (when scan-line
+               (when (and dupl-flag (equal level 0)
+                          (mh-thread-ancestor-p mh-thread-last-ancestor tree))
+                 (setq level (+ level 2)
+                       new-level (+ new-level 2)
+                       force-angle-flag t))
+               (when (equal level 0)
+                 (setq mh-thread-last-ancestor tree)
+                 (while (mh-container-parent mh-thread-last-ancestor)
+                   (setq mh-thread-last-ancestor
+                         (mh-container-parent mh-thread-last-ancestor))))
+               (let* ((lev (if dupl-flag level new-level))
+                      (square-flag (or (and (mh-container-real-child-p tree)
+                                            (not force-angle-flag)
+                                            dupl-flag)
+                                       (equal lev 0))))
+                 (insert (car scan-line)
+                         (format (format "%%%ss" lev) "")
+                         (if square-flag "[" "<")
+                         (cadr scan-line)
+                         (if square-flag "]" ">")
+                         (truncate-string-to-width
+                          (caddr scan-line) (- mh-thread-body-width lev))
+                         "\n"))
+               (setq increment-level-flag t)
+               (setq dupl-flag nil)))
+           (unless increment-level-flag (setq new-level level))
+           (dolist (child (mh-container-children tree))
+             (mh-thread-generate-scan-lines child new-level))))
+        (t (let ((nlevel (+ level 2)))
+             (dolist (ch tree)
+               (mh-thread-generate-scan-lines ch nlevel))))))
+
+
+
+;;; Additional Utilities
+
+;;;###mh-autoload
+(defun mh-thread-update-scan-line-map (msg notation offset)
+  "In threaded view update `mh-thread-scan-line-map'.
+MSG is the message being notated with NOTATION at OFFSET."
+  (let* ((msg (or msg (mh-get-msg-num nil)))
+         (cur-scan-line (and mh-thread-scan-line-map
+                             (gethash msg mh-thread-scan-line-map)))
+         (old-scan-lines (loop for map in mh-thread-scan-line-map-stack
+                               collect (and map (gethash msg map)))))
+    (when cur-scan-line
+      (setf (aref (car cur-scan-line) offset) notation))
+    (dolist (line old-scan-lines)
+      (when line (setf (aref (car line) offset) notation)))))
+
+;;;###mh-autoload
+(defun mh-thread-find-msg-subject (msg)
+  "Find canonicalized subject of MSG.
+This function can only be used the folder is threaded."
+  (ignore-errors
+    (mh-message-subject
+     (mh-container-message (gethash (gethash msg mh-thread-index-id-map)
+                                    mh-thread-id-table)))))
+
+;;;###mh-autoload
+(defun mh-thread-add-spaces (count)
+  "Add COUNT spaces to each scan line in `mh-thread-scan-line-map'."
+  (let ((spaces (format (format "%%%ss" count) "")))
+    (while (not (eobp))
+      (let* ((msg-num (mh-get-msg-num nil))
+             (old-line (nth 3 (gethash msg-num mh-thread-scan-line-map))))
+        (when (numberp msg-num)
+          (setf (gethash msg-num mh-thread-scan-line-map)
+                (mh-thread-parse-scan-line (format "%s%s" spaces old-line)))))
+      (forward-line 1))))
+
+;;;###mh-autoload
+(defun mh-thread-forget-message (index)
+  "Forget the message INDEX from the threading tables."
+  (let* ((id (gethash index mh-thread-index-id-map))
+         (id-index (gethash id mh-thread-id-index-map))
+         (duplicates (gethash id mh-thread-duplicates)))
+    (remhash index mh-thread-index-id-map)
+    (remhash index mh-thread-scan-line-map)
+    (cond ((and (eql index id-index) (null duplicates))
+           (remhash id mh-thread-id-index-map))
+          ((eql index id-index)
+           (setf (gethash id mh-thread-id-index-map) (car duplicates))
+           (setf (gethash (car duplicates) mh-thread-index-id-map) id)
+           (setf (gethash id mh-thread-duplicates) (cdr duplicates)))
+          (t
+           (setf (gethash id mh-thread-duplicates)
+                 (remove index duplicates))))))
+
+(provide 'mh-thread)
+
+;; Local Variables:
+;; indent-tabs-mode: nil
+;; sentence-end-double-space: nil
+;; End:
+
+;; arch-tag: b10e62f5-f028-4e04-873e-89d0e069b3d5
+;;; mh-thread.el ends here
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lisp/mh-e/mh-tool-bar.el	Wed Feb 01 10:07:17 2006 +0000
@@ -0,0 +1,420 @@
+;;; mh-tool-bar.el --- MH-E tool bar support
+
+;; Copyright (C) 2002, 2003, 2005, 2006 Free Software Foundation, Inc.
+
+;; Author: Satyaki Das <satyaki@theforce.stanford.edu>
+;; Maintainer: Bill Wohler <wohler@newt.com>
+;; Keywords: mail
+;; See: mh-e.el
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
+
+;;; Commentary:
+
+;;; Change Log:
+
+;;; Code:
+
+(require 'mh-e)
+
+;;; Tool Bar Commands
+
+(defun mh-tool-bar-search (&optional arg)
+  "Interactively call `mh-tool-bar-search-function'.
+Optional argument ARG is not used."
+  (interactive "P")
+  (call-interactively mh-tool-bar-search-function))
+
+(defun mh-tool-bar-customize ()
+  "Call `mh-customize' from the tool bar."
+  (interactive)
+  (mh-customize t))
+
+(defun mh-tool-bar-folder-help ()
+  "Visit \"(mh-e)Top\"."
+  (interactive)
+  (info "(mh-e)Top")
+  (delete-other-windows))
+
+(defun mh-tool-bar-letter-help ()
+  "Visit \"(mh-e)Editing Drafts\"."
+  (interactive)
+  (info "(mh-e)Editing Drafts")
+  (delete-other-windows))
+
+(defmacro mh-tool-bar-reply-generator (function recipient folder-buffer-flag)
+  "Generate FUNCTION that replies to RECIPIENT.
+If FOLDER-BUFFER-FLAG is nil then the function generated...
+When INCLUDE-FLAG is non-nil, include message body being replied to."
+  `(defun ,function (&optional arg)
+     ,(format "Reply to \"%s\".\nWhen ARG is non-nil include message in reply."
+              recipient)
+     (interactive "P")
+     ,(if folder-buffer-flag nil '(set-buffer mh-show-folder-buffer))
+     (mh-reply (mh-get-msg-num nil) ,recipient arg)))
+
+(mh-tool-bar-reply-generator mh-tool-bar-reply-from "from" t)
+(mh-tool-bar-reply-generator mh-show-tool-bar-reply-from "from" nil)
+(mh-tool-bar-reply-generator mh-tool-bar-reply-to "to" t)
+(mh-tool-bar-reply-generator mh-show-tool-bar-reply-to "to" nil)
+(mh-tool-bar-reply-generator mh-tool-bar-reply-all "all" t)
+(mh-tool-bar-reply-generator mh-show-tool-bar-reply-all "all" nil)
+
+
+
+;;; Tool Bar Creation
+
+(defmacro mh-tool-bar-define (defaults &rest buttons)
+  "Define a tool bar for MH-E.
+DEFAULTS is the list of buttons that are present by default. It
+is a list of lists where the sublists are of the following form:
+
+  (:KEYWORD FUNC1 FUNC2 FUNC3 ...)
+
+Here :KEYWORD is one of :folder or :letter. If it is :folder then
+the default buttons in the folder and show mode buffers are being
+specified. If it is :letter then the default buttons in the
+letter mode are listed. FUNC1, FUNC2, FUNC3, ... are the names of
+the functions that the buttons would execute.
+
+Each element of BUTTONS is a list consisting of four mandatory
+items and one optional item as follows:
+
+  (FUNCTION MODES ICON DOC &optional ENABLE-EXPR)
+
+where,
+
+  FUNCTION is the name of the function that will be executed when
+  the button is clicked.
+
+  MODES is a list of symbols. List elements must be from \"folder\",
+  \"letter\" and \"sequence\". If \"folder\" is present then the button is
+  available in the folder and show buffer. If the name of FUNCTION is
+  of the form \"mh-foo\", where foo is some arbitrary string, then we
+  check if the function `mh-show-foo' exists. If it exists then that
+  function is used in the show buffer. Otherwise the original function
+  `mh-foo' is used in the show buffer as well. Presence of \"sequence\"
+  is handled similar to the above. The only difference is that the
+  button is shown only when the folder is narrowed to a sequence. If
+  \"letter\" is present in MODES, then the button is available during
+  draft editing and runs FUNCTION when clicked.
+
+  ICON is the icon that is drawn in the button.
+
+  DOC is the documentation for the button. It is used in tool-tips and
+  in providing other help to the user. GNU Emacs uses only the first
+  line of the string. So the DOC should be formatted such that the
+  first line is useful and complete without the rest of the string.
+
+  Optional item ENABLE-EXPR is an arbitrary lisp expression. If it
+  evaluates to nil, then the button is deactivated, otherwise it is
+  active. If it isn't present then the button is always active."
+  ;; The following variable names have been carefully chosen to make code
+  ;; generation easier. Modifying the names should be done carefully.
+  (let (folder-buttons folder-docs folder-button-setter sequence-button-setter
+                       show-buttons show-button-setter show-seq-button-setter
+                       letter-buttons letter-docs letter-button-setter
+                       folder-defaults letter-defaults
+                       folder-vectors show-vectors letter-vectors)
+    (dolist (x defaults)
+      (cond ((eq (car x) :folder) (setq folder-defaults (cdr x)))
+            ((eq (car x) :letter) (setq letter-defaults (cdr x)))))
+    (dolist (button buttons)
+      (unless (and (listp button)
+                   (or (equal (length button) 4) (equal (length button) 5)))
+        (error "Incorrect MH-E tool-bar button specification: %s" button))
+      (let* ((name (nth 0 button))
+             (name-str (symbol-name name))
+             (icon (nth 2 button))
+             (xemacs-icon (mh-do-in-xemacs
+                            (cdr (assoc (intern icon) mh-xemacs-icon-map))))
+             (full-doc (nth 3 button))
+             (doc (if (string-match "\\(.*\\)\n" full-doc)
+                      (match-string 1 full-doc)
+                    full-doc))
+             (enable-expr (or (nth 4 button) t))
+             (modes (nth 1 button))
+             functions show-sym)
+        (when (memq 'letter modes) (setq functions `(:letter ,name)))
+        (when (or (memq 'folder modes) (memq 'sequence modes))
+          (setq functions
+                (append `(,(if (memq 'folder modes) :folder :sequence) ,name)
+                        functions))
+          (setq show-sym
+                (if (string-match "^mh-\\(.*\\)$" name-str)
+                    (intern (concat "mh-show-" (match-string 1 name-str)))
+                  name))
+          (setq functions
+                (append `(,(if (memq 'folder modes) :show :show-seq)
+                          ,(if (fboundp show-sym) show-sym name))
+                        functions)))
+        (do ((functions functions (cddr functions)))
+            ((null functions))
+          (let* ((type (car functions))
+                 (function (cadr functions))
+                 (type1 (substring (symbol-name type) 1))
+                 (vector-list (cond ((eq type :show) 'show-vectors)
+                                    ((eq type :show-seq) 'show-vectors)
+                                    ((eq type :letter) 'letter-vectors)
+                                    (t 'folder-vectors)))
+                 (list (cond ((eq type :letter) 'mh-tool-bar-letter-buttons)
+                             (t 'mh-tool-bar-folder-buttons)))
+                 (key (intern (concat "mh-" type1 "tool-bar-" name-str)))
+                 (setter (intern (concat type1 "-button-setter")))
+                 (mbuttons (cond ((eq type :letter) 'letter-buttons)
+                                 ((eq type :show) 'show-buttons)
+                                 ((eq type :show-seq) 'show-buttons)
+                                 (t 'folder-buttons)))
+                 (docs (cond ((eq mbuttons 'letter-buttons) 'letter-docs)
+                             ((eq mbuttons 'folder-buttons) 'folder-docs))))
+            (add-to-list vector-list `[,xemacs-icon ,function t ,full-doc])
+            (add-to-list
+             setter `(when (member ',name ,list)
+                       (mh-funcall-if-exists
+                        tool-bar-add-item ,icon ',function ',key
+                        :help ,doc :enable ',enable-expr)))
+            (add-to-list mbuttons name)
+            (if docs (add-to-list docs doc))))))
+    (setq folder-buttons (nreverse folder-buttons)
+          letter-buttons (nreverse letter-buttons)
+          show-buttons (nreverse show-buttons)
+          letter-docs (nreverse letter-docs)
+          folder-docs (nreverse folder-docs)
+          folder-vectors (nreverse folder-vectors)
+          show-vectors (nreverse show-vectors)
+          letter-vectors (nreverse letter-vectors))
+    (dolist (x folder-defaults)
+      (unless (memq x folder-buttons)
+        (error "Folder defaults contains unknown button '%s'" x)))
+    (dolist (x letter-defaults)
+      (unless (memq x letter-buttons)
+        (error "Letter defaults contains unknown button '%s'" x)))
+    `(eval-when (compile load eval)
+       (defun mh-buffer-exists-p (mode)
+         "Test whether a buffer with major mode MODE is present."
+         (loop for buf in (buffer-list)
+               when (save-excursion
+                      (set-buffer buf)
+                      (eq major-mode mode))
+               return t))
+
+       ;; GNU Emacs tool bar specific code
+       (mh-do-in-gnu-emacs
+         ;; Tool bar initialization functions
+         (defun mh-tool-bar-folder-buttons-init ()
+           (when (mh-buffer-exists-p 'mh-folder-mode)
+             (mh-image-load-path)
+             (setq mh-folder-tool-bar-map
+                   (let ((tool-bar-map (make-sparse-keymap)))
+                     ,@(nreverse folder-button-setter)
+                     tool-bar-map))
+             (setq mh-show-tool-bar-map
+                   (let ((tool-bar-map (make-sparse-keymap)))
+                     ,@(nreverse show-button-setter)
+                     tool-bar-map))
+             (setq mh-show-seq-tool-bar-map
+                   (let ((tool-bar-map (copy-keymap mh-show-tool-bar-map)))
+                     ,@(nreverse show-seq-button-setter)
+                     tool-bar-map))
+             (setq mh-folder-seq-tool-bar-map
+                   (let ((tool-bar-map (copy-keymap mh-folder-tool-bar-map)))
+                     ,@(nreverse sequence-button-setter)
+                     tool-bar-map))))
+         (defun mh-tool-bar-letter-buttons-init ()
+           (when (mh-buffer-exists-p 'mh-letter-mode)
+             (mh-image-load-path)
+             (setq mh-letter-tool-bar-map
+                   (let ((tool-bar-map (make-sparse-keymap)))
+                     ,@(nreverse letter-button-setter)
+                     tool-bar-map))))
+         ;; Custom setter functions
+         (defun mh-tool-bar-folder-buttons-set (symbol value)
+           "Construct tool bar for `mh-folder-mode' and `mh-show-mode'."
+           (set-default symbol value)
+           (mh-tool-bar-folder-buttons-init))
+         (defun mh-tool-bar-letter-buttons-set (symbol value)
+           "Construct tool bar for `mh-letter-mode'."
+           (set-default symbol value)
+           (mh-tool-bar-letter-buttons-init)))
+       ;; XEmacs specific code
+       (mh-do-in-xemacs
+         (defvar mh-tool-bar-folder-vector-map
+           ',(loop for button in folder-buttons
+                   for vector in folder-vectors
+                   collect (cons button vector)))
+         (defvar mh-tool-bar-show-vector-map
+           ',(loop for button in show-buttons
+                   for vector in show-vectors
+                   collect (cons button vector)))
+         (defvar mh-tool-bar-letter-vector-map
+           ',(loop for button in letter-buttons
+                   for vector in letter-vectors
+                   collect (cons button vector)))
+         (defvar mh-tool-bar-folder-buttons nil)
+         (defvar mh-tool-bar-show-buttons nil)
+         (defvar mh-tool-bar-letter-buttons nil)
+         ;; Custom setter functions
+         (defun mh-tool-bar-letter-buttons-set (symbol value)
+           (set-default symbol value)
+           (when mh-xemacs-has-tool-bar-flag
+             (setq mh-tool-bar-letter-buttons
+                   (loop for b in value
+                         collect (cdr (assoc b mh-tool-bar-letter-vector-map))))))
+         (defun mh-tool-bar-folder-buttons-set (symbol value)
+           (set-default symbol value)
+           (when mh-xemacs-has-tool-bar-flag
+             (setq mh-tool-bar-folder-buttons
+                   (loop for b in value
+                         collect (cdr (assoc b mh-tool-bar-folder-vector-map))))
+             (setq mh-tool-bar-show-buttons
+                   (loop for b in value
+                         collect (cdr (assoc b mh-tool-bar-show-vector-map))))))
+         (defun mh-tool-bar-init (mode)
+           "Install tool bar in MODE."
+           (let ((tool-bar (cond ((eq mode :folder) mh-tool-bar-folder-buttons)
+                                ((eq mode :letter) mh-tool-bar-letter-buttons)
+                                ((eq mode :show) mh-tool-bar-show-buttons)))
+                 (height 37)
+                 (width 40)
+                 (buffer (current-buffer)))
+             (when mh-xemacs-use-tool-bar-flag
+               (cond
+                ((eq mh-xemacs-tool-bar-position 'top)
+                 (set-specifier top-toolbar tool-bar buffer)
+                 (set-specifier top-toolbar-visible-p t)
+                 (set-specifier top-toolbar-height height))
+                ((eq mh-xemacs-tool-bar-position 'bottom)
+                 (set-specifier bottom-toolbar tool-bar buffer)
+                 (set-specifier bottom-toolbar-visible-p t)
+                 (set-specifier bottom-toolbar-height height))
+                ((eq mh-xemacs-tool-bar-position 'left)
+                 (set-specifier left-toolbar tool-bar buffer)
+                 (set-specifier left-toolbar-visible-p t)
+                 (set-specifier left-toolbar-width width))
+                ((eq mh-xemacs-tool-bar-position 'right)
+                 (set-specifier right-toolbar tool-bar buffer)
+                 (set-specifier right-toolbar-visible-p t)
+                 (set-specifier right-toolbar-width width))
+                (t (set-specifier default-toolbar tool-bar buffer)))))))
+       ;; Declare customizable tool bars
+       (custom-declare-variable
+        'mh-tool-bar-folder-buttons
+        '(list ,@(mapcar (lambda (x) `(quote ,x)) folder-defaults))
+        "List of buttons to include in MH-Folder tool bar."
+        :group 'mh-tool-bar :set 'mh-tool-bar-folder-buttons-set
+        :type '(set ,@(loop for x in folder-buttons
+                            for y in folder-docs
+                            collect `(const :tag ,y ,x))))
+       (custom-declare-variable
+        'mh-tool-bar-letter-buttons
+        '(list ,@(mapcar (lambda (x) `(quote ,x)) letter-defaults))
+        "List of buttons to include in MH-Letter tool bar."
+        :group 'mh-tool-bar :set 'mh-tool-bar-letter-buttons-set
+        :type '(set ,@(loop for x in letter-buttons
+                            for y in letter-docs
+                            collect `(const :tag ,y ,x)))))))
+
+(mh-tool-bar-define
+    ((:folder mh-inc-folder mh-mime-save-parts mh-previous-undeleted-msg
+              mh-page-msg  mh-next-undeleted-msg mh-delete-msg mh-refile-msg
+              mh-undo mh-execute-commands mh-toggle-tick mh-reply
+              mh-alias-grab-from-field mh-send mh-rescan-folder
+              mh-tool-bar-search mh-visit-folder
+              mh-tool-bar-customize mh-tool-bar-folder-help mh-widen)
+     (:letter mh-send-letter mh-compose-insertion ispell-message save-buffer
+              undo kill-region menu-bar-kill-ring-save yank mh-fully-kill-draft
+              mh-tool-bar-customize mh-tool-bar-letter-help))
+  ;; Folder/Show buffer buttons
+  (mh-inc-folder (folder) "mail"
+    "Incorporate new mail in Inbox
+This button runs `mh-inc-folder' which drags any
+new mail into your Inbox folder.")
+  (mh-mime-save-parts (folder) "attach"
+    "Save MIME parts from this message
+This button runs `mh-mime-save-parts' which saves a message's
+different parts into separate files.")
+  (mh-previous-undeleted-msg (folder) "left-arrow"
+    "Go to the previous undeleted message
+This button runs `mh-previous-undeleted-msg'")
+  (mh-page-msg (folder) "page-down"
+    "Page the current message forwards\nThis button runs `mh-page-msg'")
+  (mh-next-undeleted-msg (folder) "right-arrow"
+    "Go to the next undeleted message\nThe button runs `mh-next-undeleted-msg'")
+  (mh-delete-msg (folder) "close"
+    "Mark this message for deletion\nThis button runs `mh-delete-msg'")
+  (mh-refile-msg (folder) "mail/refile"
+    "Refile this message\nThis button runs `mh-refile-msg'")
+  (mh-undo (folder) "undo" "Undo last operation\nThis button runs `undo'"
+    (mh-outstanding-commands-p))
+  (mh-execute-commands (folder) "execute"
+    "Perform moves and deletes\nThis button runs `mh-execute-commands'"
+    (mh-outstanding-commands-p))
+  (mh-toggle-tick (folder) "highlight"
+    "Toggle tick mark\nThis button runs `mh-toggle-tick'")
+  (mh-toggle-showing (folder) "show"
+    "Toggle showing message\nThis button runs `mh-toggle-showing'")
+  (mh-tool-bar-reply-from (folder) "mail/reply-from" "Reply to \"from\"")
+  (mh-tool-bar-reply-to (folder) "mail/reply-to" "Reply to \"to\"")
+  (mh-tool-bar-reply-all (folder) "mail/reply-all" "Reply to \"all\"")
+  (mh-reply (folder) "mail/reply"
+    "Reply to this message\nThis button runs `mh-reply'")
+  (mh-alias-grab-from-field (folder) "mail/alias"
+    "Grab From alias\nThis button runs `mh-alias-grab-from-field'"
+    (and (mh-extract-from-header-value) (not (mh-alias-for-from-p))))
+  (mh-send (folder) "mail/compose"
+    "Compose new message\nThis button runs `mh-send'")
+  (mh-rescan-folder (folder) "refresh"
+    "Rescan this folder\nThis button runs `mh-rescan-folder'")
+  (mh-pack-folder (folder) "mail/repack"
+    "Repack this folder\nThis button runs `mh-pack-folder'")
+  (mh-tool-bar-search (folder) "search"
+    "Search\nThis button runs `mh-tool-bar-search-function'")
+  (mh-visit-folder (folder) "fld-open"
+    "Visit other folder\nThis button runs `mh-visit-folder'")
+  ;; Letter buffer buttons
+  (mh-send-letter (letter) "mail/send" "Send this letter")
+  (mh-compose-insertion (letter) "attach" "Insert attachment")
+  (ispell-message (letter) "spell" "Check spelling")
+  (save-buffer (letter) "save" "Save current buffer to its file"
+    (buffer-modified-p))
+  (undo (letter) "undo" "Undo last operation")
+  (kill-region (letter) "cut"
+    "Cut (kill) text in region between mark and current position")
+  (menu-bar-kill-ring-save (letter) "copy"
+    "Copy text in region between mark and current position")
+  (yank (letter) "paste" "Paste (yank) text cut or copied earlier")
+  (mh-fully-kill-draft (letter) "close" "Kill this draft")
+  ;; Common buttons
+  (mh-tool-bar-customize (folder letter) "preferences" "MH-E Preferences")
+  (mh-tool-bar-folder-help (folder) "help"
+    "Help! (general help)\nThis button runs `info'")
+  (mh-tool-bar-letter-help (letter) "help"
+    "Help! (general help)\nThis button runs `info'")
+  ;; Folder narrowed to sequence buttons
+  (mh-widen (sequence) "widen"
+    "Widen from the sequence\nThis button runs `mh-widen'"))
+
+(provide 'mh-tool-bar)
+
+;; Local Variables:
+;; indent-tabs-mode: nil
+;; sentence-end-double-space: nil
+;; End:
+
+;; arch-tag: 28c2436d-bb8d-486a-a8d7-5a4d9cae3513
+;;; mh-tool-bar.el ends here
--- a/lisp/mh-e/mh-utils.el	Thu Jan 26 02:23:05 2006 +0000
+++ b/lisp/mh-e/mh-utils.el	Wed Feb 01 10:07:17 2006 +0000
@@ -1,4 +1,4 @@
-;;; mh-utils.el --- MH-E code needed for both sending and reading
+;;; mh-utils.el --- MH-E general utilities
 
 ;; Copyright (C) 1993, 1995, 1997,
 ;;  2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
@@ -27,53 +27,18 @@
 
 ;;; Commentary:
 
-;; Internal support for MH-E package.
-
 ;;; Change Log:
 
 ;;; Code:
 
-;;(message "> mh-utils")
-(eval-and-compile
-  (defvar recursive-load-depth-limit)
-  (if (and (boundp 'recursive-load-depth-limit)
-           (integerp recursive-load-depth-limit)
-           (< recursive-load-depth-limit 50))
-      (setq recursive-load-depth-limit 50)))
-
-(eval-when-compile (require 'mh-acros))
+(require 'mh-e)
 (mh-require-cl)
 
 (require 'font-lock)
-(require 'gnus-util)
-(require 'mh-buffers)
-(require 'mh-customize)
-(require 'mh-inc)
-(require 'mouse)
-(require 'sendmail)
-;;(message "< mh-utils")
-
-;; Non-fatal dependencies
-(load "hl-line" t t)
-(load "mm-decode" t t)
-(load "mm-view" t t)
-(load "tool-bar" t t)
-(load "vcard" t t)
-
-
-
-;;; Autoloads
-
-(autoload 'gnus-article-highlight-citation "gnus-cite")
-(autoload 'message-fetch-field "message")
-(autoload 'message-tokenize-header "message")
-(unless (fboundp 'make-hash-table)
-  (autoload 'make-hash-table "cl"))
-
-
 
 ;;; CL Replacements
 
+;;;###mh-autoload
 (defun mh-search-from-end (char string)
   "Return the position of last occurrence of CHAR in STRING.
 If CHAR is not present in STRING then return nil. The function is
@@ -82,476 +47,99 @@
         when (equal (aref string index) char) return index
         finally return nil))
 
-;; Additional header fields that might someday be added:
-;; "Sender: " "Reply-to: "
-
 
 
-;;; Scan Line Formats
-
-(defvar mh-scan-msg-number-regexp "^ *\\([0-9]+\\)"
-  "This regular expression extracts the message number.
+;;; General Utilities
 
-It must match from the beginning of the line. Note that the
-message number must be placed in a parenthesized expression as in
-the default of \"^ *\\\\([0-9]+\\\\)\".")
-
-(defvar mh-scan-msg-overflow-regexp "^[?0-9][0-9]"
-  "This regular expression matches overflowed message numbers.")
+;;;###mh-autoload
+(defun mh-beginning-of-word (&optional n)
+  "Return position of the N th word backwards."
+  (unless n (setq n 1))
+  (let ((syntax-table (syntax-table)))
+    (unwind-protect
+        (save-excursion
+          (mh-mail-abbrev-make-syntax-table)
+          (set-syntax-table mail-abbrev-syntax-table)
+          (backward-word n)
+          (point))
+      (set-syntax-table syntax-table))))
 
-(defvar mh-scan-msg-format-regexp "%\\([0-9]*\\)(msg)"
-  "This regular expression finds the message number width in a scan format.
+;;;###mh-autoload
+(defun mh-colors-available-p ()
+  "Check if colors are available in the Emacs being used."
+  (or mh-xemacs-flag
+      (let ((color-cells (display-color-cells)))
+        (and (numberp color-cells) (>= color-cells 8)))))
 
-Note that the message number must be placed in a parenthesized
-expression as in the default of \"%\\\\([0-9]*\\\\)(msg)\". This
-variable is only consulted if `mh-scan-format-file' is set to
-\"Use MH-E scan Format\".")
+;;;###mh-autoload
+(defun mh-colors-in-use-p ()
+  "Check if colors are being used in the folder buffer."
+  (and mh-colors-available-flag font-lock-mode))
 
-(defvar mh-scan-msg-format-string "%d"
-  "This is a format string for width of the message number in a scan format.
+;;;###mh-autoload
+(defun mh-delete-line (lines)
+  "Delete the next LINES lines."
+  (delete-region (point) (progn (forward-line lines) (point))))
 
-Use \"0%d\" for zero-filled message numbers. This variable is only
-consulted if `mh-scan-format-file' is set to \"Use MH-E scan
-Format\".")
+(defvar mh-image-load-path-called-flag nil)
 
-(defvar mh-scan-msg-search-regexp "^[^0-9]*%d[^0-9]"
-  "This regular expression matches a particular message.
-
-It is a format string; use \"%d\" to represent the location of the
-message number within the expression as in the default of
-\"^[^0-9]*%d[^0-9]\".")
-
-(defvar mh-cmd-note 4
-  "Column for notations.
-
-This variable should be set with the function `mh-set-cmd-note'.
-This variable may be updated dynamically if
-`mh-adaptive-cmd-note-flag' is on.
+;;;###mh-autoload
+(defun mh-image-load-path ()
+  "Ensure that the MH-E images are accessible by `find-image'.
+Images for MH-E are found in ../../etc/images relative to the
+files in \"lisp/mh-e\". If `image-load-path' exists (since Emacs
+22), then the images directory is added to it if isn't already
+there. Otherwise, the images directory is added to the
+`load-path' if it isn't already there."
+  (unless mh-image-load-path-called-flag
+    (let (mh-library-name mh-image-load-path)
+      ;; First, find mh-e in the load-path.
+      (setq mh-library-name (locate-library "mh-e"))
+      (if (not mh-library-name)
+        (error "Can not find MH-E in load-path"))
+      (setq mh-image-load-path
+            (expand-file-name (concat (file-name-directory mh-library-name)
+                                      "../../etc/images")))
+      (if (not (file-exists-p mh-image-load-path))
+          (error "Can not find image directory %s" mh-image-load-path))
+      (if (boundp 'image-load-path)
+          (add-to-list 'image-load-path mh-image-load-path)
+        (add-to-list 'load-path mh-image-load-path)))
+    (setq mh-image-load-path-called-flag t)))
 
-Note that columns in Emacs start with 0.")
-(make-variable-buffer-local 'mh-cmd-note)
-
-(defvar mh-note-seq ?%
-  "Messages in a user-defined sequence are marked by this character.
+;;;###mh-autoload
+(defun mh-make-local-vars (&rest pairs)
+  "Initialize local variables according to the variable-value PAIRS."
+  (while pairs
+    (set (make-local-variable (car pairs)) (car (cdr pairs)))
+    (setq pairs (cdr (cdr pairs)))))
 
-Messages in the \"search\" sequence are marked by this character as
-well.")
-
-
+;;;###mh-autoload
+(defun mh-mapc (function list)
+  "Apply FUNCTION to each element of LIST for side effects only."
+  (while list
+    (funcall function (car list))
+    (setq list (cdr list))))
 
-(defvar mh-show-buffer-mode-line-buffer-id "    {show-%s} %d"
-  "Format string to produce `mode-line-buffer-identification' for show buffers.
-
-First argument is folder name. Second is message number.")
+;;;###mh-autoload
+(defun mh-replace-string (old new)
+  "Replace all occurrences of OLD with NEW in the current buffer.
+Ignores case when searching for OLD."
+  (goto-char (point-min))
+  (let ((case-fold-search t))
+    (while (search-forward old nil t)
+      (replace-match new t t))))
 
 
 
-(defvar mh-mail-header-separator "--------"
-  "*Line used by MH to separate headers from text in messages being composed.
-
-This variable should not be used directly in programs. Programs
-should use `mail-header-separator' instead.
-`mail-header-separator' is initialized to
-`mh-mail-header-separator' in `mh-letter-mode'; in other
-contexts, you may have to perform this initialization yourself.
-
-Do not make this a regular expression as it may be the argument
-to `insert' and it is passed through `regexp-quote' before being
-used by functions like `re-search-forward'.")
-
-(defvar mh-signature-separator-regexp "^-- $"
-  "This regular expression matches the signature separator.
-See `mh-signature-separator'.")
-
-(defvar mh-signature-separator "-- \n"
-  "Text of a signature separator.
-
-A signature separator is used to separate the body of a message
-from the signature. This can be used by user agents such as MH-E
-to render the signature differently or to suppress the inclusion
-of the signature in a reply. Use `mh-signature-separator-regexp'
-when searching for a separator.")
-
-(defun mh-signature-separator-p ()
-  "Return non-nil if buffer includes \"^-- $\"."
-  (save-excursion
-    (goto-char (point-min))
-    (re-search-forward mh-signature-separator-regexp nil t)))
-
-;; Variables for MIME display
-
-;; Structure to keep track of MIME handles on a per buffer basis.
-(mh-defstruct (mh-buffer-data (:conc-name mh-mime-)
-                              (:constructor mh-make-buffer-data))
-  (handles ())                          ; List of MIME handles
-  (handles-cache (make-hash-table))     ; Cache to avoid multiple decodes of
-                                        ; nested messages
-  (parts-count 0)                       ; The button number is generated from
-                                        ; this number
-  (part-index-hash (make-hash-table)))  ; Avoid incrementing the part number
-                                        ; for nested messages
-
-;; This has to be a macro, since we do: (setf (mh-buffer-data) ...)
-(defmacro mh-buffer-data ()
-  "Convenience macro to get the MIME data structures of the current buffer."
-  `(gethash (current-buffer) mh-globals-hash))
-
-(defvar mh-globals-hash (make-hash-table)
-  "Keeps track of MIME data on a per buffer basis.")
-
-(defvar mh-mm-inline-media-tests
-  `(("image/jpeg"
-     mm-inline-image
-     (lambda (handle)
-       (mm-valid-and-fit-image-p 'jpeg handle)))
-    ("image/png"
-     mm-inline-image
-     (lambda (handle)
-       (mm-valid-and-fit-image-p 'png handle)))
-    ("image/gif"
-     mm-inline-image
-     (lambda (handle)
-       (mm-valid-and-fit-image-p 'gif handle)))
-    ("image/tiff"
-     mm-inline-image
-     (lambda (handle)
-       (mm-valid-and-fit-image-p 'tiff handle)) )
-    ("image/xbm"
-     mm-inline-image
-     (lambda (handle)
-       (mm-valid-and-fit-image-p 'xbm handle)))
-    ("image/x-xbitmap"
-     mm-inline-image
-     (lambda (handle)
-       (mm-valid-and-fit-image-p 'xbm handle)))
-    ("image/xpm"
-     mm-inline-image
-     (lambda (handle)
-       (mm-valid-and-fit-image-p 'xpm handle)))
-    ("image/x-pixmap"
-     mm-inline-image
-     (lambda (handle)
-       (mm-valid-and-fit-image-p 'xpm handle)))
-    ("image/bmp"
-     mm-inline-image
-     (lambda (handle)
-       (mm-valid-and-fit-image-p 'bmp handle)))
-    ("image/x-portable-bitmap"
-     mm-inline-image
-     (lambda (handle)
-       (mm-valid-and-fit-image-p 'pbm handle)))
-    ("text/plain" mm-inline-text identity)
-    ("text/enriched" mm-inline-text identity)
-    ("text/richtext" mm-inline-text identity)
-    ("text/x-patch" mm-display-patch-inline
-     (lambda (handle)
-       (locate-library "diff-mode")))
-    ("application/emacs-lisp" mm-display-elisp-inline identity)
-    ("application/x-emacs-lisp" mm-display-elisp-inline identity)
-    ("text/html"
-     ,(if (fboundp 'mm-inline-text-html) 'mm-inline-text-html 'mm-inline-text)
-     (lambda (handle)
-       (or (and (boundp 'mm-inline-text-html-renderer)
-                mm-inline-text-html-renderer)
-           (and (boundp 'mm-text-html-renderer) mm-text-html-renderer))))
-    ("text/x-vcard"
-     mm-inline-text-vcard
-     (lambda (handle)
-       (or (featurep 'vcard)
-           (locate-library "vcard"))))
-    ("message/delivery-status" mm-inline-text identity)
-    ("message/rfc822" mh-mm-inline-message identity)
-    ;;("message/partial" mm-inline-partial identity)
-    ;;("message/external-body" mm-inline-external-body identity)
-    ("text/.*" mm-inline-text identity)
-    ("audio/wav" mm-inline-audio
-     (lambda (handle)
-       (and (or (featurep 'nas-sound) (featurep 'native-sound))
-            (device-sound-enabled-p))))
-    ("audio/au"
-     mm-inline-audio
-     (lambda (handle)
-       (and (or (featurep 'nas-sound) (featurep 'native-sound))
-            (device-sound-enabled-p))))
-    ("application/pgp-signature" ignore identity)
-    ("application/x-pkcs7-signature" ignore identity)
-    ("application/pkcs7-signature" ignore identity)
-    ("application/x-pkcs7-mime" ignore identity)
-    ("application/pkcs7-mime" ignore identity)
-    ("multipart/alternative" ignore identity)
-    ("multipart/mixed" ignore identity)
-    ("multipart/related" ignore identity)
-    ;; Disable audio and image
-    ("audio/.*" ignore ignore)
-    ("image/.*" ignore ignore)
-    ;; Default to displaying as text
-    (".*" mm-inline-text mm-readable-p))
-  "Alist of media types/tests saying whether types can be displayed inline.")
-
-;; Copy of `goto-address-mail-regexp'
-(defvar mh-address-mail-regexp
-  "[-a-zA-Z0-9._]+@\\([-a-zA-z0-9_]+\\.\\)+[a-zA-Z0-9]+"
-  "A regular expression probably matching an e-mail address.")
-
-;; From goto-addr.el, which we don't want to force-load on users.
-
-(defun mh-goto-address-find-address-at-point ()
-  "Find e-mail address around or before point.
-
-Then search backwards to beginning of line for the start of an
-e-mail address. If no e-mail address found, return nil."
-  (re-search-backward "[^-_A-z0-9.@]" (line-beginning-position) 'lim)
-  (if (or (looking-at mh-address-mail-regexp)	; already at start
-	  (and (re-search-forward mh-address-mail-regexp
-				  (line-end-position) 'lim)
-	       (goto-char (match-beginning 0))))
-      (match-string-no-properties 0)))
-
-(defun mh-mail-header-end ()
-  "Substitute for `mail-header-end' that doesn't widen the buffer.
-
-In MH-E we frequently need to find the end of headers in nested
-messages, where the buffer has been narrowed. This function works
-in this situation."
-  (save-excursion
-    ;; XXX: The following replaces a call to rfc822-goto-eoh. Occasionally,
-    ;; mail headers that MH-E has to read contains lines of the form:
-    ;;    From xxx@yyy Mon May 10 11:48:07 2004
-    ;; In this situation, rfc822-goto-eoh doesn't go to the end of the
-    ;; header. The replacement allows From_ lines in the mail header.
-    (goto-char (point-min))
-    (loop for p = (re-search-forward
-                   "^\\([:\n]\\|[^: \t\n]+[ \t\n]\\)" nil 'move)
-          do (cond ((null p) (return))
-                   (t (goto-char (match-beginning 0))
-                      (unless (looking-at "From ") (return))
-                      (goto-char p))))
-    (point)))
-
-(defun mh-in-header-p ()
-  "Return non-nil if the point is in the header of a draft message."
-  (< (point) (mh-mail-header-end)))
-
-(defun mh-header-field-beginning ()
-  "Move to the beginning of the current header field.
-Handles RFC 822 continuation lines."
-  (beginning-of-line)
-  (while (looking-at "^[ \t]")
-    (forward-line -1)))
-
-(defun mh-header-field-end ()
-  "Move to the end of the current header field.
-Handles RFC 822 continuation lines."
-  (forward-line 1)
-  (while (looking-at "^[ \t]")
-    (forward-line 1))
-  (backward-char 1))                    ;to end of previous line
-
-(defun mh-letter-header-font-lock (limit)
-  "Return the entire mail header to font-lock.
-Argument LIMIT limits search."
-  (if (= (point) limit)
-      nil
-    (let* ((mail-header-end (save-match-data (mh-mail-header-end)))
-           (lesser-limit (if (< mail-header-end limit) mail-header-end limit)))
-      (when (mh-in-header-p)
-        (set-match-data (list 1 lesser-limit))
-        (goto-char lesser-limit)
-        t))))
-
-(defun mh-header-field-font-lock (field limit)
-  "Return the value of a header field FIELD to font-lock.
-Argument LIMIT limits search."
-  (if (= (point) limit)
-      nil
-    (let* ((mail-header-end (mh-mail-header-end))
-           (lesser-limit (if (< mail-header-end limit) mail-header-end limit))
-           (case-fold-search t))
-      (when (and (< (point) mail-header-end) ;Only within header
-                 (re-search-forward (format "^%s" field) lesser-limit t))
-        (let ((match-one-b (match-beginning 0))
-              (match-one-e (match-end 0)))
-          (mh-header-field-end)
-          (if (> (point) limit)         ;Don't search for end beyond limit
-              (goto-char limit))
-          (set-match-data (list match-one-b match-one-e
-                                (1+ match-one-e) (point)))
-          t)))))
-
-(defun mh-header-to-font-lock (limit)
-  "Return the value of a header field To to font-lock.
-Argument LIMIT limits search."
-  (mh-header-field-font-lock "To:" limit))
-
-(defun mh-header-cc-font-lock (limit)
-  "Return the value of a header field cc to font-lock.
-Argument LIMIT limits search."
-  (mh-header-field-font-lock "cc:" limit))
-
-(defun mh-header-subject-font-lock (limit)
-  "Return the value of a header field Subject to font-lock.
-Argument LIMIT limits search."
-  (mh-header-field-font-lock "Subject:" limit))
-
-(eval-and-compile
-  ;; Otherwise byte-compilation fails on `mh-show-font-lock-keywords-with-cite'
-  (defvar mh-show-font-lock-keywords
-    '(("^\\(From:\\|Sender:\\)\\(.*\\)"
-       (1 'default)
-       (2 'mh-show-from))
-      (mh-header-to-font-lock
-       (0 'default)
-       (1 'mh-show-to))
-      (mh-header-cc-font-lock
-       (0 'default)
-       (1 'mh-show-cc))
-      ("^\\(Reply-To:\\|Return-Path:\\)\\(.*\\)$"
-       (1 'default)
-       (2 'mh-show-from))
-      (mh-header-subject-font-lock
-       (0 'default)
-       (1 'mh-show-subject))
-      ("^\\(Apparently-To:\\|Newsgroups:\\)\\(.*\\)"
-       (1 'default)
-       (2 'mh-show-cc))
-      ("^\\(In-reply-to\\|Date\\):\\(.*\\)$"
-       (1 'default)
-       (2 'mh-show-date))
-      (mh-letter-header-font-lock
-       (0 'mh-show-header append t)))
-    "Additional expressions to highlight in MH-Show buffers."))
-
-(defvar mh-show-font-lock-keywords-with-cite
-  (eval-when-compile
-    (let* ((cite-chars "[>|}]")
-           (cite-prefix "A-Za-z")
-           (cite-suffix (concat cite-prefix "0-9_.@-`'\"")))
-      (append
-       mh-show-font-lock-keywords
-       (list
-        ;; Use MATCH-ANCHORED to effectively anchor the regexp left side.
-        `(,cite-chars
-          (,(concat "\\=[ \t]*"
-                    "\\(\\([" cite-prefix "]+[" cite-suffix "]*\\)?"
-                    "\\(" cite-chars "[ \t]*\\)\\)+"
-                    "\\(.*\\)")
-           (beginning-of-line) (end-of-line)
-           (2 font-lock-constant-face nil t)
-           (4 font-lock-comment-face nil t)))))))
-  "Additional expressions to highlight in MH-Show buffers.")
-
-(defvar mh-letter-font-lock-keywords
-  `(,@mh-show-font-lock-keywords-with-cite
-    (mh-font-lock-field-data
-     (1 'mh-letter-header-field prepend t)))
-  "Additional expressions to highlight in MH-Letter buffers.")
-
-(defun mh-show-font-lock-fontify-region (beg end loudly)
-  "Limit font-lock in `mh-show-mode' to the header.
-
-Used when the option `mh-highlight-citation-style' is set to
-\"Gnus\", leaving the body to be dealt with by Gnus highlighting.
-The region between BEG and END is given over to be fontified and
-LOUDLY controls if a user sees a message about the fontification
-operation."
-  (let ((header-end (mh-mail-header-end)))
-    (cond
-     ((and (< beg header-end)(< end header-end))
-      (font-lock-default-fontify-region beg end loudly))
-     ((and (< beg header-end)(>= end header-end))
-      (font-lock-default-fontify-region beg header-end loudly))
-     (t
-      nil))))
-
-;; Shush compiler.
-(if mh-xemacs-flag
-    (eval-and-compile
-      (require 'gnus)
-      (require 'gnus-art)
-      (require 'gnus-cite)))
-
-(defun mh-gnus-article-highlight-citation ()
-  "Highlight cited text in current buffer using Gnus."
-  (interactive)
-  ;; Requiring gnus-cite should have been sufficient. However for Emacs21.1,
-  ;; recursive-load-depth-limit is only 10, so an error occurs. Also it may be
-  ;; better to have an autoload at top-level (though that won't work because
-  ;; of recursive-load-depth-limit). That gets rid of a compiler warning as
-  ;; well.
-  (unless mh-xemacs-flag
-    (require 'gnus-art)
-    (require 'gnus-cite))
-  ;; Don't allow Gnus to create buttons while highlighting, maybe this is bad
-  ;; style?
-  (flet ((gnus-article-add-button (&rest args) nil))
-    (let* ((modified (buffer-modified-p))
-           (gnus-article-buffer (buffer-name))
-           (gnus-cite-face-list `(,@(cdr gnus-cite-face-list)
-                                    ,(car gnus-cite-face-list))))
-      (gnus-article-highlight-citation t)
-      (set-buffer-modified-p modified))))
-
-
-
-;;; Internal bookkeeping variables:
-
-(defvar mh-user-path nil
-  "Cached value of the \"Path:\" MH profile component.
-User's mail folder directory.")
-
-(defvar mh-draft-folder nil
-  "Cached value of the \"Draft-Folder:\" MH profile component.
-Name of folder containing draft messages.
-Nil means do not use a draft folder.")
-
-(defvar mh-unseen-seq nil
-  "Cached value of the \"Unseen-Sequence:\" MH profile component.
-Name of the Unseen sequence.")
-
-(defvar mh-previous-seq nil
-  "Cached value of the \"Previous-Sequence:\" MH profile component.
-Name of the Previous sequence.")
-
-(defvar mh-inbox nil
-  "Cached value of the \"Inbox:\" MH profile component.
-Set to \"+inbox\" if no such component.
-Name of the Inbox folder.")
-
-(defvar mh-previous-window-config nil
-  "Window configuration before MH-E command.")
-
-(defvar mh-page-to-next-msg-flag nil
-  "Non-nil means next SPC or whatever goes to next undeleted message.")
-
-
-
-;;; Internal variables local to a folder.
-
-(defvar mh-current-folder nil
-  "Name of current folder, a string.")
-
-(defvar mh-show-buffer nil
-  "Buffer that displays message for this folder.")
-
-(defvar mh-folder-filename nil
-  "Full path of directory for this folder.")
-
-(defvar mh-msg-count nil
-  "Number of msgs in buffer.")
-
-(defvar mh-showing-mode nil
-  "If non-nil, show the message in a separate window.")
-
-(defvar mh-show-mode-map (make-sparse-keymap)
-  "Keymap used by the show buffer.")
-
-(defvar mh-show-folder-buffer nil
-  "Keeps track of folder whose message is being displayed.")
+;;; Logo Display
 
 (defvar mh-logo-cache nil)
 
+;;;###mh-autoload
 (defun mh-logo-display ()
   "Modify mode line to display MH-E logo."
+  (mh-image-load-path)
   (mh-do-in-gnu-emacs
    (add-text-properties
     0 2
@@ -569,1474 +157,223 @@
             (cons modeline-buffer-id-left-extent "XEmacs%N:"))
           (cons modeline-buffer-id-right-extent " %17b")))))
 
-(defun mh-showing-mode (&optional arg)
-  "Change whether messages should be displayed.
+
+
+;;; Read MH Profile
+
+(defvar mh-find-path-run nil
+  "Non-nil if `mh-find-path' has been run already.
+Do not access this variable; `mh-find-path' already uses it to
+avoid running more than once.")
 
-With ARG, display messages iff ARG is positive."
-  (setq mh-showing-mode
-        (if (null arg)
-            (not mh-showing-mode)
-          (> (prefix-numeric-value arg) 0))))
+;;;###mh-autoload
+(defun mh-find-path ()
+  "Set variables from user's MH profile.
+
+This function sets `mh-user-path' from your \"Path:\" MH profile
+component (but defaults to \"Mail\" if one isn't present),
+`mh-draft-folder' from \"Draft-Folder:\", `mh-unseen-seq' from
+\"Unseen-Sequence:\", `mh-previous-seq' from
+\"Previous-Sequence:\", and `mh-inbox' from \"Inbox:\" (defaults
+to \"+inbox\").
 
-(defvar mh-seq-list nil
-  "Alist of this folder's sequences.
-Elements have the form (SEQUENCE . MESSAGES).")
-
-(defvar mh-seen-list nil
-  "List of displayed messages to be removed from the \"Unseen\" sequence.")
-
-(defvar mh-showing-with-headers nil
-  "If non-nil, MH-Show buffer contains message with all header fields.
-If nil, MH-Show buffer contains message processed normally.")
+The hook `mh-find-path-hook' is run after these variables have
+been set. This hook can be used the change the value of these
+variables if you need to run with different values between MH and
+MH-E."
+  (unless mh-find-path-run
+    ;; Sanity checks.
+    (if (and (getenv "MH")
+             (not (file-readable-p (getenv "MH"))))
+        (error "MH environment variable contains unreadable file %s"
+               (getenv "MH")))
+    (if (null (mh-variants))
+        (error "Install MH and run install-mh before running MH-E"))
+    (let ((profile "~/.mh_profile"))
+      (if (not (file-readable-p profile))
+          (error "Run install-mh before running MH-E")))
+    ;; Read MH profile.
+    (setq mh-user-path (mh-profile-component "Path"))
+    (if (not mh-user-path)
+        (setq mh-user-path "Mail"))
+    (setq mh-user-path
+          (file-name-as-directory
+           (expand-file-name mh-user-path (expand-file-name "~"))))
+    (mh-set-x-image-cache-directory (expand-file-name ".mhe-x-image-cache"
+                                                      mh-user-path))
+    (setq mh-draft-folder (mh-profile-component "Draft-Folder"))
+    (if mh-draft-folder
+        (progn
+          (if (not (mh-folder-name-p mh-draft-folder))
+              (setq mh-draft-folder (format "+%s" mh-draft-folder)))
+          (if (not (file-exists-p (mh-expand-file-name mh-draft-folder)))
+              (error
+               "Draft folder \"%s\" not found; create it and try again"
+               (mh-expand-file-name mh-draft-folder)))))
+    (setq mh-inbox (mh-profile-component "Inbox"))
+    (cond ((not mh-inbox)
+           (setq mh-inbox "+inbox"))
+          ((not (mh-folder-name-p mh-inbox))
+           (setq mh-inbox (format "+%s" mh-inbox))))
+    (setq mh-unseen-seq (mh-profile-component "Unseen-Sequence"))
+    (if mh-unseen-seq
+        (setq mh-unseen-seq (intern mh-unseen-seq))
+      (setq mh-unseen-seq 'unseen))     ;old MH default?
+    (setq mh-previous-seq (mh-profile-component "Previous-Sequence"))
+    (if mh-previous-seq
+        (setq mh-previous-seq (intern mh-previous-seq)))
+    (run-hooks 'mh-find-path-hook)
+    (mh-collect-folder-names)
+    (setq mh-find-path-run t)))
 
 
 
-;;; MH-E macros
+;;; Help Functions
+
+;;;###mh-autoload
+(defun mh-ephem-message (string)
+  "Display STRING in the minibuffer momentarily."
+  (message "%s" string)
+  (sit-for 5)
+  (message ""))
+
+(defvar mh-help-default nil
+  "Mode to use if messages are not present for the current mode.")
+
+(defvar mh-help-messages nil
+  "Help messages for all modes.
+This is an alist of alists. The primary key is a symbol
+representing the mode; the value is described in `mh-set-help'.")
+
+;;;###mh-autoload
+(defun mh-set-help (messages &optional default)
+  "Set help messages.
 
-(defmacro with-mh-folder-updating (save-modification-flag &rest body)
-  "Format is (with-mh-folder-updating (SAVE-MODIFICATION-FLAG) &body BODY).
-Execute BODY, which can modify the folder buffer without having to
-worry about file locking or the read-only flag, and return its result.
-If SAVE-MODIFICATION-FLAG is non-nil, the buffer's modification flag
-is unchanged, otherwise it is cleared."
-  (setq save-modification-flag (car save-modification-flag)) ; CL style
-  `(prog1
-       (let ((mh-folder-updating-mod-flag (buffer-modified-p))
-             (buffer-read-only nil)
-             (buffer-file-name nil))    ;don't let the buffer get locked
-         (prog1
-             (progn
-               ,@body)
-           (mh-set-folder-modified-p mh-folder-updating-mod-flag)))
-     ,@(if (not save-modification-flag)
-           '((mh-set-folder-modified-p nil)))))
+The MESSAGES are assumed to be an associative array. It is used
+to show help for the most common commands in the current mode.
+The key is a prefix char. The value is one or more strings which
+are concatenated together and displayed in a help buffer if ? is
+pressed after the prefix character. The special key nil is used
+to display the non-prefixed commands.
+
+The substitutions described in `substitute-command-keys' are performed as
+well.
+
+If optional argument DEFAULT is non-nil, then these messages will
+be used if help is asked for an unknown mode."
+  (add-to-list 'mh-help-messages (cons major-mode messages))
+  (if default
+      (setq mh-help-default major-mode)))
 
-(put 'with-mh-folder-updating 'lisp-indent-hook 'defun)
-
-(defmacro mh-in-show-buffer (show-buffer &rest body)
-  "Format is (mh-in-show-buffer (SHOW-BUFFER) &body BODY).
-Display buffer SHOW-BUFFER in other window and execute BODY in it.
-Stronger than `save-excursion', weaker than `save-window-excursion'."
-  (setq show-buffer (car show-buffer))  ; CL style
-  `(let ((mh-in-show-buffer-saved-window (selected-window)))
-     (switch-to-buffer-other-window ,show-buffer)
-     (if mh-bury-show-buffer-flag (bury-buffer (current-buffer)))
-     (unwind-protect
-         (progn
-           ,@body)
-       (select-window mh-in-show-buffer-saved-window))))
-
-(put 'mh-in-show-buffer 'lisp-indent-hook 'defun)
+;;;###mh-autoload
+(defun mh-help (&optional help-messages)
+  "Display cheat sheet for the MH-E commands.
+See `mh-set-help' for setting the help messages.
+HELP-MESSAGES are used instead if given.
+This is a list of one or more strings which are concatenated together
+and displayed in a help buffer."
+  (interactive)
+  (let* ((help (or help-messages
+                  (cdr (assoc nil (assoc major-mode mh-help-messages)))))
+         (text (substitute-command-keys (mapconcat 'identity help ""))))
+    (with-electric-help
+     (function
+      (lambda ()
+        (insert text)))
+     mh-help-buffer)))
 
-(defmacro mh-do-at-event-location (event &rest body)
-  "Switch to the location of EVENT and execute BODY.
-After BODY has been executed return to original window. The
-modification flag of the buffer in the event window is
-preserved."
-  (let ((event-window (make-symbol "event-window"))
-        (event-position (make-symbol "event-position"))
-        (original-window (make-symbol "original-window"))
-        (original-position (make-symbol "original-position"))
-        (modified-flag (make-symbol "modified-flag")))
-    `(save-excursion
-       (let* ((,event-window
-               (or (mh-funcall-if-exists posn-window (event-start ,event))
-                   (mh-funcall-if-exists event-window ,event)))
-              (,event-position
-               (or (mh-funcall-if-exists posn-point (event-start ,event))
-                   (mh-funcall-if-exists event-closest-point ,event)))
-              (,original-window (selected-window))
-              (,original-position (progn
-                                   (set-buffer (window-buffer ,event-window))
-                                   (set-marker (make-marker) (point))))
-              (,modified-flag (buffer-modified-p))
-              (buffer-read-only nil))
-         (unwind-protect (progn
-                           (select-window ,event-window)
-                           (goto-char ,event-position)
-                           ,@body)
-           (set-buffer-modified-p ,modified-flag)
-           (goto-char ,original-position)
-           (set-marker ,original-position nil)
-           (select-window ,original-window))))))
+;;;###mh-autoload
+(defun mh-prefix-help ()
+  "Display cheat sheet for the commands of the current prefix in minibuffer."
+  (interactive)
+  ;; We got here because the user pressed a "?", but he pressed a prefix key
+  ;; before that. Since the the key vector starts at index 0, the index of the
+  ;; last keystroke is length-1 and thus the second to last keystroke is at
+  ;; length-2. We use that information to obtain a suitable prefix character
+  ;; from the recent keys.
+  (let* ((keys (recent-keys))
+         (prefix-char (elt keys (- (length keys) 2)))
+         (help (cdr (assoc prefix-char (assoc major-mode mh-help-messages)))))
+    (mh-help help)))
 
-(put 'mh-do-at-event-location 'lisp-indent-hook 'defun)
-
-(defmacro mh-make-seq (name msgs)
-  "Create sequence NAME with the given MSGS."
-  (list 'cons name msgs))
+
 
-(defmacro mh-seq-name (sequence)
-  "Extract sequence name from the given SEQUENCE."
-  (list 'car sequence))
-
-(defmacro mh-seq-msgs (sequence)
-  "Extract messages from the given SEQUENCE."
-  (list 'cdr sequence))
+;;; Message Number Utilities
 
-(defun mh-recenter (arg)
-  "Like recenter but with three improvements:
-
-- At the end of the buffer it tries to show fewer empty lines.
-
-- operates only if the current buffer is in the selected window.
-  (Commands like `save-some-buffers' can make this false.)
-
-- nil ARG means recenter as if prefix argument had been given."
-  (cond ((not (eq (get-buffer-window (current-buffer)) (selected-window)))
-         nil)
-        ((= (point-max) (save-excursion
-                          (forward-line (- (/ (window-height) 2) 2))
-                          (point)))
-         (let ((lines-from-end 2))
-           (save-excursion
-             (while (> (point-max) (progn (forward-line) (point)))
-               (incf lines-from-end)))
-           (recenter (- lines-from-end))))
-        ;; '(4) is the same as C-u prefix argument.
-        (t (recenter (or arg '(4))))))
+;;;###mh-autoload
+(defun mh-coalesce-msg-list (messages)
+  "Given a list of MESSAGES, return a list of message number ranges.
+This is the inverse of `mh-read-msg-list', which expands ranges.
+Message lists passed to MH programs should be processed by this
+function to avoid exceeding system command line argument limits."
+  (let ((msgs (sort (copy-sequence messages) 'mh-greaterp))
+        (range-high nil)
+        (prev -1)
+        (ranges nil))
+    (while prev
+      (if range-high
+          (if (or (not (numberp prev))
+                  (not (equal (car msgs) (1- prev))))
+              (progn                    ;non-sequential, flush old range
+                (if (eq prev range-high)
+                    (setq ranges (cons range-high ranges))
+                  (setq ranges (cons (format "%s-%s" prev range-high) ranges)))
+                (setq range-high nil))))
+      (or range-high
+          (setq range-high (car msgs))) ;start new or first range
+      (setq prev (car msgs))
+      (setq msgs (cdr msgs)))
+    ranges))
 
-(defun mh-start-of-uncleaned-message ()
-  "Position uninteresting headers off the top of the window."
-  (let ((case-fold-search t))
-    (re-search-forward
-     "^To:\\|^Cc:\\|^From:\\|^Subject:\\|^Date:" nil t)
-    (beginning-of-line)
-    (mh-recenter 0)))
+(defun mh-greaterp (msg1 msg2)
+  "Return the greater of two message indicators MSG1 and MSG2.
+Strings are \"smaller\" than numbers.
+Valid values are things like \"cur\", \"last\", 1, and 1820."
+  (if (numberp msg1)
+      (if (numberp msg2)
+          (> msg1 msg2)
+        t)
+    (if (numberp msg2)
+        nil
+      (string-lessp msg2 msg1))))
 
-(defun mh-invalidate-show-buffer ()
-  "Invalidate the show buffer so we must update it to use it."
-  (if (get-buffer mh-show-buffer)
-      (save-excursion
-        (set-buffer mh-show-buffer)
-        (mh-unvisit-file))))
+;;;###mh-autoload
+(defun mh-lessp (msg1 msg2)
+  "Return the lesser of two message indicators MSG1 and MSG2.
+Strings are \"smaller\" than numbers.
+Valid values are things like \"cur\", \"last\", 1, and 1820."
+  (not (mh-greaterp msg1 msg2)))
 
-(defun mh-unvisit-file ()
-  "Separate current buffer from the message file it was visiting."
-  (or (not (buffer-modified-p))
-      (null buffer-file-name)           ;we've been here before
-      (yes-or-no-p (format "Message %s modified; flush changes? "
-                           (file-name-nondirectory buffer-file-name)))
-      (error "Flushing changes not confirmed"))
-  (clear-visited-file-modtime)
-  (unlock-buffer)
-  (setq buffer-file-name nil))
-
+;;;###mh-autoload
 (defun mh-get-msg-num (error-if-no-message)
   "Return the message number of the displayed message.
 If the argument ERROR-IF-NO-MESSAGE is non-nil, then complain if
 the cursor is not pointing to a message."
   (save-excursion
     (beginning-of-line)
-    (cond ((looking-at mh-scan-msg-number-regexp)
+    (cond ((looking-at (mh-scan-msg-number-regexp))
            (string-to-number (buffer-substring (match-beginning 1)
                                                (match-end 1))))
           (error-if-no-message
            (error "Cursor not pointing to message"))
           (t nil))))
 
-(defun mh-folder-name-p (name)
-  "Return non-nil if NAME is the name of a folder.
-A name (a string or symbol) can be a folder name if it begins
-with \"+\"."
-  (if (symbolp name)
-      (eq (aref (symbol-name name) 0) ?+)
-    (and (> (length name) 0)
-         (eq (aref name 0) ?+))))
-
-(defun mh-expand-file-name (filename &optional default)
-  "Expand FILENAME like `expand-file-name', but also handle MH folder names.
-Any filename that starts with '+' is treated as a folder name.
-See `expand-file-name' for description of DEFAULT."
-  (if (mh-folder-name-p filename)
-      (expand-file-name (substring filename 1) mh-user-path)
-    (expand-file-name filename default)))
-
-(defun mh-msg-filename (msg &optional folder)
-  "Return the file name of MSG in FOLDER (default current folder)."
-  (expand-file-name (int-to-string msg)
-                    (if folder
-                        (mh-expand-file-name folder)
-                      mh-folder-filename)))
-
-;; Infrastructure to generate show-buffer functions from folder functions
-;; XEmacs does not have deactivate-mark? What is the equivalent of
-;; transient-mark-mode for XEmacs? Should we be restoring the mark in the
-;; folder buffer after the operation has been carried out.
-(defmacro mh-defun-show-buffer (function original-function
-                                         &optional dont-return)
-  "Define FUNCTION to run ORIGINAL-FUNCTION in folder buffer.
-If the buffer we start in is still visible and DONT-RETURN is nil
-then switch to it after that."
-  `(defun ,function ()
-     ,(format "Calls %s from the message's folder.\n%s\nSee \"%s\" for more info.\n"
-              original-function
-              (if dont-return ""
-                "When function completes, returns to the show buffer if it is
-still visible.\n")
-              original-function)
-     (interactive)
-     (when (buffer-live-p (get-buffer mh-show-folder-buffer))
-       (let ((config (current-window-configuration))
-             (folder-buffer mh-show-folder-buffer)
-             (normal-exit nil)
-             ,@(if dont-return () '((cur-buffer-name (buffer-name)))))
-         (pop-to-buffer mh-show-folder-buffer nil)
-         (unless (equal (buffer-name
-                         (window-buffer (frame-first-window (selected-frame))))
-                        folder-buffer)
-           (delete-other-windows))
-         (mh-goto-cur-msg t)
-         (mh-funcall-if-exists deactivate-mark)
-         (unwind-protect
-             (prog1 (call-interactively (function ,original-function))
-               (setq normal-exit t))
-           (mh-funcall-if-exists deactivate-mark)
-           (when (eq major-mode 'mh-folder-mode)
-             (mh-funcall-if-exists hl-line-highlight))
-           (cond ((not normal-exit)
-                  (set-window-configuration config))
-                 ,(if dont-return
-                      `(t (setq mh-previous-window-config config))
-                    `((and (get-buffer cur-buffer-name)
-                           (window-live-p (get-buffer-window
-                                           (get-buffer cur-buffer-name))))
-                      (pop-to-buffer (get-buffer cur-buffer-name) nil)))))))))
-
-;; Generate interactive functions for the show buffer from the corresponding
-;; folder functions.
-(mh-defun-show-buffer mh-show-previous-undeleted-msg
-                      mh-previous-undeleted-msg)
-(mh-defun-show-buffer mh-show-next-undeleted-msg
-                      mh-next-undeleted-msg)
-(mh-defun-show-buffer mh-show-quit mh-quit)
-(mh-defun-show-buffer mh-show-delete-msg mh-delete-msg)
-(mh-defun-show-buffer mh-show-refile-msg mh-refile-msg)
-(mh-defun-show-buffer mh-show-undo mh-undo)
-(mh-defun-show-buffer mh-show-execute-commands mh-execute-commands)
-(mh-defun-show-buffer mh-show-reply mh-reply t)
-(mh-defun-show-buffer mh-show-redistribute mh-redistribute)
-(mh-defun-show-buffer mh-show-forward mh-forward t)
-(mh-defun-show-buffer mh-show-header-display mh-header-display)
-(mh-defun-show-buffer mh-show-refile-or-write-again
-                      mh-refile-or-write-again)
-(mh-defun-show-buffer mh-show-show mh-show)
-(mh-defun-show-buffer mh-show-write-message-to-file
-                      mh-write-msg-to-file)
-(mh-defun-show-buffer mh-show-extract-rejected-mail
-                      mh-extract-rejected-mail t)
-(mh-defun-show-buffer mh-show-delete-msg-no-motion
-                      mh-delete-msg-no-motion)
-(mh-defun-show-buffer mh-show-first-msg mh-first-msg)
-(mh-defun-show-buffer mh-show-last-msg mh-last-msg)
-(mh-defun-show-buffer mh-show-copy-msg mh-copy-msg)
-(mh-defun-show-buffer mh-show-edit-again mh-edit-again t)
-(mh-defun-show-buffer mh-show-goto-msg mh-goto-msg)
-(mh-defun-show-buffer mh-show-inc-folder mh-inc-folder)
-(mh-defun-show-buffer mh-show-delete-subject-or-thread
-                      mh-delete-subject-or-thread)
-(mh-defun-show-buffer mh-show-delete-subject mh-delete-subject)
-(mh-defun-show-buffer mh-show-print-msg mh-print-msg)
-(mh-defun-show-buffer mh-show-send mh-send t)
-(mh-defun-show-buffer mh-show-toggle-showing mh-toggle-showing t)
-(mh-defun-show-buffer mh-show-pipe-msg mh-pipe-msg t)
-(mh-defun-show-buffer mh-show-sort-folder mh-sort-folder)
-(mh-defun-show-buffer mh-show-visit-folder mh-visit-folder t)
-(mh-defun-show-buffer mh-show-rescan-folder mh-rescan-folder)
-(mh-defun-show-buffer mh-show-pack-folder mh-pack-folder)
-(mh-defun-show-buffer mh-show-kill-folder mh-kill-folder t)
-(mh-defun-show-buffer mh-show-list-folders mh-list-folders t)
-(mh-defun-show-buffer mh-show-undo-folder mh-undo-folder)
-(mh-defun-show-buffer mh-show-delete-msg-from-seq
-                      mh-delete-msg-from-seq)
-(mh-defun-show-buffer mh-show-delete-seq mh-delete-seq)
-(mh-defun-show-buffer mh-show-list-sequences mh-list-sequences)
-(mh-defun-show-buffer mh-show-narrow-to-seq mh-narrow-to-seq)
-(mh-defun-show-buffer mh-show-put-msg-in-seq mh-put-msg-in-seq)
-(mh-defun-show-buffer mh-show-msg-is-in-seq mh-msg-is-in-seq)
-(mh-defun-show-buffer mh-show-widen mh-widen)
-(mh-defun-show-buffer mh-show-narrow-to-subject mh-narrow-to-subject)
-(mh-defun-show-buffer mh-show-narrow-to-from mh-narrow-to-from)
-(mh-defun-show-buffer mh-show-narrow-to-cc mh-narrow-to-cc)
-(mh-defun-show-buffer mh-show-narrow-to-range mh-narrow-to-range)
-(mh-defun-show-buffer mh-show-narrow-to-to mh-narrow-to-to)
-(mh-defun-show-buffer mh-show-store-msg mh-store-msg)
-(mh-defun-show-buffer mh-show-page-digest mh-page-digest)
-(mh-defun-show-buffer mh-show-page-digest-backwards
-                      mh-page-digest-backwards)
-(mh-defun-show-buffer mh-show-burst-digest mh-burst-digest)
-(mh-defun-show-buffer mh-show-page-msg mh-page-msg)
-(mh-defun-show-buffer mh-show-previous-page mh-previous-page)
-(mh-defun-show-buffer mh-show-modify mh-modify t)
-(mh-defun-show-buffer mh-show-next-button mh-next-button)
-(mh-defun-show-buffer mh-show-prev-button mh-prev-button)
-(mh-defun-show-buffer mh-show-toggle-mime-part mh-folder-toggle-mime-part)
-(mh-defun-show-buffer mh-show-save-mime-part mh-folder-save-mime-part)
-(mh-defun-show-buffer mh-show-inline-mime-part mh-folder-inline-mime-part)
-(mh-defun-show-buffer mh-show-toggle-threads mh-toggle-threads)
-(mh-defun-show-buffer mh-show-thread-delete mh-thread-delete)
-(mh-defun-show-buffer mh-show-thread-refile mh-thread-refile)
-(mh-defun-show-buffer mh-show-update-sequences mh-update-sequences)
-(mh-defun-show-buffer mh-show-next-unread-msg mh-next-unread-msg)
-(mh-defun-show-buffer mh-show-previous-unread-msg mh-previous-unread-msg)
-(mh-defun-show-buffer mh-show-thread-ancestor mh-thread-ancestor)
-(mh-defun-show-buffer mh-show-thread-next-sibling mh-thread-next-sibling)
-(mh-defun-show-buffer mh-show-thread-previous-sibling
-                      mh-thread-previous-sibling)
-(mh-defun-show-buffer mh-show-index-visit-folder mh-index-visit-folder t)
-(mh-defun-show-buffer mh-show-toggle-tick mh-toggle-tick)
-(mh-defun-show-buffer mh-show-narrow-to-tick mh-narrow-to-tick)
-(mh-defun-show-buffer mh-show-junk-blacklist mh-junk-blacklist)
-(mh-defun-show-buffer mh-show-junk-whitelist mh-junk-whitelist)
-(mh-defun-show-buffer mh-show-index-new-messages mh-index-new-messages)
-(mh-defun-show-buffer mh-show-index-ticked-messages mh-index-ticked-messages)
-(mh-defun-show-buffer mh-show-index-sequenced-messages
-                      mh-index-sequenced-messages)
-(mh-defun-show-buffer mh-show-catchup mh-catchup)
-(mh-defun-show-buffer mh-show-ps-print-toggle-color mh-ps-print-toggle-color)
-(mh-defun-show-buffer mh-show-ps-print-toggle-faces mh-ps-print-toggle-faces)
-(mh-defun-show-buffer mh-show-ps-print-msg-file mh-ps-print-msg-file)
-(mh-defun-show-buffer mh-show-ps-print-msg mh-ps-print-msg)
-(mh-defun-show-buffer mh-show-toggle-mime-buttons mh-toggle-mime-buttons)
-(mh-defun-show-buffer mh-show-display-with-external-viewer
-                      mh-display-with-external-viewer)
-
-
-
-;;; Build mh-show-mode keymaps
-
-(gnus-define-keys mh-show-mode-map
-  " "    mh-show-page-msg
-  "!"    mh-show-refile-or-write-again
-  "'"    mh-show-toggle-tick
-  ","    mh-show-header-display
-  "."    mh-show-show
-  ">"    mh-show-write-message-to-file
-  "?"    mh-help
-  "E"    mh-show-extract-rejected-mail
-  "M"    mh-show-modify
-  "\177" mh-show-previous-page
-  "\C-d" mh-show-delete-msg-no-motion
-  "\t"   mh-show-next-button
-  [backtab] mh-show-prev-button
-  "\M-\t" mh-show-prev-button
-  "\ed"  mh-show-redistribute
-  "^"    mh-show-refile-msg
-  "c"    mh-show-copy-msg
-  "d"    mh-show-delete-msg
-  "e"    mh-show-edit-again
-  "f"    mh-show-forward
-  "g"    mh-show-goto-msg
-  "i"    mh-show-inc-folder
-  "k"    mh-show-delete-subject-or-thread
-  "m"    mh-show-send
-  "n"    mh-show-next-undeleted-msg
-  "\M-n" mh-show-next-unread-msg
-  "o"    mh-show-refile-msg
-  "p"    mh-show-previous-undeleted-msg
-  "\M-p" mh-show-previous-unread-msg
-  "q"    mh-show-quit
-  "r"    mh-show-reply
-  "s"    mh-show-send
-  "t"    mh-show-toggle-showing
-  "u"    mh-show-undo
-  "x"    mh-show-execute-commands
-  "v"    mh-show-index-visit-folder
-  "|"    mh-show-pipe-msg)
-
-(gnus-define-keys (mh-show-folder-map "F" mh-show-mode-map)
-  "?"    mh-prefix-help
-  "'"    mh-index-ticked-messages
-  "S"    mh-show-sort-folder
-  "c"    mh-show-catchup
-  "f"    mh-show-visit-folder
-  "k"    mh-show-kill-folder
-  "l"    mh-show-list-folders
-  "n"    mh-index-new-messages
-  "o"    mh-show-visit-folder
-  "q"    mh-show-index-sequenced-messages
-  "r"    mh-show-rescan-folder
-  "s"    mh-search
-  "t"    mh-show-toggle-threads
-  "u"    mh-show-undo-folder
-  "v"    mh-show-visit-folder)
-
-(gnus-define-keys (mh-show-sequence-map "S" mh-show-mode-map)
-  "'"    mh-show-narrow-to-tick
-  "?"    mh-prefix-help
-  "d"    mh-show-delete-msg-from-seq
-  "k"    mh-show-delete-seq
-  "l"    mh-show-list-sequences
-  "n"    mh-show-narrow-to-seq
-  "p"    mh-show-put-msg-in-seq
-  "s"    mh-show-msg-is-in-seq
-  "w"    mh-show-widen)
-
-(define-key mh-show-mode-map "I" mh-inc-spool-map)
-
-(gnus-define-keys (mh-show-junk-map "J" mh-show-mode-map)
-  "?"    mh-prefix-help
-  "b"    mh-show-junk-blacklist
-  "w"    mh-show-junk-whitelist)
-
-(gnus-define-keys (mh-show-ps-print-map "P" mh-show-mode-map)
-  "?"	mh-prefix-help
-  "C"	mh-show-ps-print-toggle-color
-  "F"	mh-show-ps-print-toggle-faces
-  "f"	mh-show-ps-print-msg-file
-  "l"   mh-show-print-msg
-  "p"	mh-show-ps-print-msg)
-
-(gnus-define-keys (mh-show-thread-map "T" mh-show-mode-map)
-  "?"    mh-prefix-help
-  "u"    mh-show-thread-ancestor
-  "p"    mh-show-thread-previous-sibling
-  "n"    mh-show-thread-next-sibling
-  "t"    mh-show-toggle-threads
-  "d"    mh-show-thread-delete
-  "o"    mh-show-thread-refile)
-
-(gnus-define-keys (mh-show-limit-map "/" mh-show-mode-map)
-  "'"    mh-show-narrow-to-tick
-  "?"    mh-prefix-help
-  "c"    mh-show-narrow-to-cc
-  "g"    mh-show-narrow-to-range
-  "m"    mh-show-narrow-to-from
-  "s"    mh-show-narrow-to-subject
-  "t"    mh-show-narrow-to-to
-  "w"    mh-show-widen)
-
-(gnus-define-keys (mh-show-extract-map "X" mh-show-mode-map)
-  "?"    mh-prefix-help
-  "s"    mh-show-store-msg
-  "u"    mh-show-store-msg)
-
-;; Untested...
-(gnus-define-keys (mh-show-digest-map "D" mh-show-mode-map)
-  "?"    mh-prefix-help
-  " "    mh-show-page-digest
-  "\177" mh-show-page-digest-backwards
-  "b"    mh-show-burst-digest)
-
-(gnus-define-keys (mh-show-mime-map "K" mh-show-mode-map)
-  "?"           mh-prefix-help
-  "a"           mh-mime-save-parts
-  "e"           mh-show-display-with-external-viewer
-  "v"           mh-show-toggle-mime-part
-  "o"           mh-show-save-mime-part
-  "i"           mh-show-inline-mime-part
-  "t"           mh-show-toggle-mime-buttons
-  "\t"          mh-show-next-button
-  [backtab]     mh-show-prev-button
-  "\M-\t"       mh-show-prev-button)
-
-(easy-menu-define
-  mh-show-sequence-menu mh-show-mode-map "Menu for MH-E folder-sequence."
-  '("Sequence"
-    ["Add Message to Sequence..."       mh-show-put-msg-in-seq t]
-    ["List Sequences for Message"       mh-show-msg-is-in-seq t]
-    ["Delete Message from Sequence..."  mh-show-delete-msg-from-seq t]
-    ["List Sequences in Folder..."      mh-show-list-sequences t]
-    ["Delete Sequence..."               mh-show-delete-seq t]
-    ["Narrow to Sequence..."            mh-show-narrow-to-seq t]
-    ["Widen from Sequence"              mh-show-widen t]
-    "--"
-    ["Narrow to Subject Sequence"       mh-show-narrow-to-subject t]
-    ["Narrow to Tick Sequence"          mh-show-narrow-to-tick
-     (save-excursion
-       (set-buffer mh-show-folder-buffer)
-       (and mh-tick-seq (mh-seq-msgs (mh-find-seq mh-tick-seq))))]
-    ["Delete Rest of Same Subject"      mh-show-delete-subject t]
-    ["Toggle Tick Mark"                 mh-show-toggle-tick t]
-    "--"
-    ["Push State Out to MH"             mh-show-update-sequences t]))
-
-(easy-menu-define
-  mh-show-message-menu mh-show-mode-map "Menu for MH-E folder-message."
-  '("Message"
-    ["Show Message"                     mh-show-show t]
-    ["Show Message with Header"         mh-show-header-display t]
-    ["Next Message"                     mh-show-next-undeleted-msg t]
-    ["Previous Message"                 mh-show-previous-undeleted-msg t]
-    ["Go to First Message"              mh-show-first-msg t]
-    ["Go to Last Message"               mh-show-last-msg t]
-    ["Go to Message by Number..."       mh-show-goto-msg t]
-    ["Modify Message"                   mh-show-modify t]
-    ["Delete Message"                   mh-show-delete-msg t]
-    ["Refile Message"                   mh-show-refile-msg t]
-    ["Undo Delete/Refile"               mh-show-undo t]
-    ["Process Delete/Refile"            mh-show-execute-commands t]
-    "--"
-    ["Compose a New Message"            mh-send t]
-    ["Reply to Message..."              mh-show-reply t]
-    ["Forward Message..."               mh-show-forward t]
-    ["Redistribute Message..."          mh-show-redistribute t]
-    ["Edit Message Again"               mh-show-edit-again t]
-    ["Re-edit a Bounced Message"        mh-show-extract-rejected-mail t]
-    "--"
-    ["Copy Message to Folder..."        mh-show-copy-msg t]
-    ["Print Message"                    mh-show-print-msg t]
-    ["Write Message to File..."         mh-show-write-msg-to-file t]
-    ["Pipe Message to Command..."       mh-show-pipe-msg t]
-    ["Unpack Uuencoded Message..."      mh-show-store-msg t]
-    ["Burst Digest Message"             mh-show-burst-digest t]))
-
-(easy-menu-define
-  mh-show-folder-menu mh-show-mode-map  "Menu for MH-E folder."
-  '("Folder"
-    ["Incorporate New Mail"             mh-show-inc-folder t]
-    ["Toggle Show/Folder"               mh-show-toggle-showing t]
-    ["Execute Delete/Refile"            mh-show-execute-commands t]
-    ["Rescan Folder"                    mh-show-rescan-folder t]
-    ["Thread Folder"                    mh-show-toggle-threads t]
-    ["Pack Folder"                      mh-show-pack-folder t]
-    ["Sort Folder"                      mh-show-sort-folder t]
-    "--"
-    ["List Folders"                     mh-show-list-folders t]
-    ["Visit a Folder..."                mh-show-visit-folder t]
-    ["View New Messages"                mh-show-index-new-messages t]
-    ["Search..."                        mh-search t]
-    "--"
-    ["Quit MH-E"                        mh-quit t]))
-
-;; Ensure new buffers won't get this mode if default-major-mode is nil.
-(put 'mh-show-mode 'mode-class 'special)
-
-;; Shush compiler.
-(eval-when-compile (defvar font-lock-auto-fontify))
-
-(define-derived-mode mh-show-mode text-mode "MH-Show"
-  "Major mode for showing messages in MH-E.\\<mh-show-mode-map>
-
-The hook `mh-show-mode-hook' is called upon entry to this mode.
-
-See also `mh-folder-mode'.
-
-\\{mh-show-mode-map}"
-  (set (make-local-variable 'mail-header-separator) mh-mail-header-separator)
-  (setq paragraph-start (default-value 'paragraph-start))
-  (mh-show-unquote-From)
-  (mh-show-xface)
-  (mh-show-addr)
-  (setq buffer-invisibility-spec '((vanish . t) t))
-  (set (make-local-variable 'line-move-ignore-invisible) t)
-  (make-local-variable 'font-lock-defaults)
-  ;;(set (make-local-variable 'font-lock-support-mode) nil)
-  (cond
-   ((equal mh-highlight-citation-style 'font-lock)
-    (setq font-lock-defaults '(mh-show-font-lock-keywords-with-cite t)))
-   ((equal mh-highlight-citation-style 'gnus)
-    (setq font-lock-defaults '((mh-show-font-lock-keywords)
-                               t nil nil nil
-                               (font-lock-fontify-region-function
-                                . mh-show-font-lock-fontify-region)))
-    (mh-gnus-article-highlight-citation))
-   (t
-    (setq font-lock-defaults '(mh-show-font-lock-keywords t))))
-  (if (and mh-xemacs-flag
-           font-lock-auto-fontify)
-      (turn-on-font-lock))
-  (set (make-local-variable 'tool-bar-map) mh-show-tool-bar-map)
-  (mh-funcall-if-exists mh-tool-bar-init :show)
-  (when mh-decode-mime-flag
-    (mh-make-local-hook 'kill-buffer-hook)
-    (add-hook 'kill-buffer-hook 'mh-mime-cleanup nil t))
-  (easy-menu-add mh-show-sequence-menu)
-  (easy-menu-add mh-show-message-menu)
-  (easy-menu-add mh-show-folder-menu)
-  (make-local-variable 'mh-show-folder-buffer)
-  (buffer-disable-undo)
-  (setq buffer-read-only t)
-  (use-local-map mh-show-mode-map))
-
-(defun mh-show-addr ()
-  "Use `goto-address'."
-  (when mh-show-use-goto-addr-flag
-    (if (not (featurep 'goto-addr))
-        (load "goto-addr" t t))
-    (if (fboundp 'goto-address)
-        (goto-address))))
-
-
-
-;; X-Face and Face display
-(defvar mh-show-xface-function
-  (cond ((and mh-xemacs-flag (locate-library "x-face") (not (featurep 'xface)))
-         (load "x-face" t t)
-         #'mh-face-display-function)
-        ((>= emacs-major-version 21)
-         #'mh-face-display-function)
-        (t #'ignore))
-  "Determine at run time what function should be called to display X-Face.")
-
-(defvar mh-uncompface-executable
-  (and (fboundp 'executable-find) (executable-find "uncompface")))
-
-(defun mh-face-to-png (data)
-  "Convert base64 encoded DATA to png image."
-  (with-temp-buffer
-    (insert data)
-    (ignore-errors (base64-decode-region (point-min) (point-max)))
-    (buffer-string)))
-
-(defun mh-uncompface (data)
-  "Run DATA through `uncompface' to generate bitmap."
-  (with-temp-buffer
-    (insert data)
-    (when (and mh-uncompface-executable
-               (equal (call-process-region (point-min) (point-max)
-                                           mh-uncompface-executable t '(t nil))
-                      0))
-      (mh-icontopbm)
-      (buffer-string))))
-
-(defun mh-icontopbm ()
-  "Elisp substitute for `icontopbm'."
-  (goto-char (point-min))
-  (let ((end (point-max)))
-    (while (re-search-forward "0x\\(..\\)\\(..\\)," nil t)
-      (save-excursion
-        (goto-char (point-max))
-        (insert (string-to-number (match-string 1) 16))
-        (insert (string-to-number (match-string 2) 16))))
-    (delete-region (point-min) end)
-    (goto-char (point-min))
-    (insert "P4\n48 48\n")))
-
-(mh-do-in-xemacs (defvar default-enable-multibyte-characters))
-
-(defmacro mh-face-foreground-compat (face &optional frame inherit)
-  "Return the foreground color name of FACE, or nil if unspecified.
-See documentation for `face-foreground' for a description of the
-arguments FACE, FRAME, and INHERIT.
-
-Calls `face-foreground' correctly in older environments. Versions
-of Emacs prior to version 22 lacked an INHERIT argument which
-when t tells `face-foreground' to consider an inherited value for
-the foreground if the face does not define one itself."
-  (if (>= emacs-major-version 22)
-      `(face-foreground ,face ,frame ,inherit)
-    `(face-foreground ,face ,frame)))
-
-(defmacro mh-face-background-compat (face &optional frame inherit)
-  "Return the background color name of face, or nil if unspecified.
-See documentation for `back-foreground' for a description of the
-arguments FACE, FRAME, and INHERIT.
-
-Calls `face-background' correctly in older environments. Versions
-of Emacs prior to version 22 lacked an INHERIT argument which
-when t tells `face-background' to consider an inherited value for
-the background if the face does not define one itself."
-  (if (>= emacs-major-version 22)
-      `(face-background ,face ,frame ,inherit)
-    `(face-background ,face ,frame)))
-
-(defun mh-face-display-function ()
-  "Display a Face, X-Face, or X-Image-URL header field.
-If more than one of these are present, then the first one found
-in this order is used."
-  (save-restriction
-    (goto-char (point-min))
-    (re-search-forward "\n\n" (point-max) t)
-    (narrow-to-region (point-min) (point))
-    (let* ((case-fold-search t)
-           (default-enable-multibyte-characters nil)
-           (face (message-fetch-field "face" t))
-           (x-face (message-fetch-field "x-face" t))
-           (url (message-fetch-field "x-image-url" t))
-           raw type)
-      (cond (face (setq raw (mh-face-to-png face)
-                        type 'png))
-            (x-face (setq raw (mh-uncompface x-face)
-                          type 'pbm))
-            (url (setq type 'url))
-            (t (multiple-value-setq (type raw) (mh-picon-get-image))))
-      (when type
-        (goto-char (point-min))
-        (when (re-search-forward "^from:" (point-max) t)
-          ;; GNU Emacs
-          (mh-do-in-gnu-emacs
-            (if (eq type 'url)
-                (mh-x-image-url-display url)
-              (mh-funcall-if-exists
-               insert-image (create-image
-                             raw type t
-                             :foreground
-                             (mh-face-foreground-compat 'mh-show-xface nil t)
-                             :background
-                             (mh-face-background-compat 'mh-show-xface nil t))
-               " ")))
-          ;; XEmacs
-          (mh-do-in-xemacs
-            (cond
-             ((eq type 'url)
-              (mh-x-image-url-display url))
-             ((eq type 'png)
-              (when (featurep 'png)
-                (set-extent-begin-glyph
-                 (make-extent (point) (point))
-                 (make-glyph (vector 'png ':data (mh-face-to-png face))))))
-             ;; Try internal xface support if available...
-             ((and (eq type 'pbm) (featurep 'xface))
-              (set-glyph-face
-               (set-extent-begin-glyph
-                (make-extent (point) (point))
-                (make-glyph (vector 'xface ':data (concat "X-Face: " x-face))))
-               'mh-show-xface))
-             ;; Otherwise try external support with x-face...
-             ((and (eq type 'pbm)
-                   (fboundp 'x-face-xmas-wl-display-x-face)
-                   (fboundp 'executable-find) (executable-find "uncompface"))
-              (mh-funcall-if-exists x-face-xmas-wl-display-x-face))
-             ;; Picon display
-             ((and raw (member type '(xpm xbm gif)))
-              (when (featurep type)
-                (set-extent-begin-glyph
-                 (make-extent (point) (point))
-                 (make-glyph (vector type ':data raw))))))
-            (when raw (insert " "))))))))
-
-(defun mh-show-xface ()
-  "Display X-Face."
-  (when (and window-system mh-show-use-xface-flag
-             (or mh-decode-mime-flag mh-mhl-format-file
-                 mh-clean-message-header-flag))
-    (funcall mh-show-xface-function)))
+(add-to-list 'debug-ignored-errors "^Cursor not pointing to message$")
 
 
 
-;;; Picon display
-
-;; XXX: This should be customizable. As a side-effect of setting this
-;;   variable, arrange to reset mh-picon-existing-directory-list to 'unset.
-(defvar mh-picon-directory-list
-  '("~/.picons" "~/.picons/users" "~/.picons/usenix" "~/.picons/news"
-    "~/.picons/domains" "~/.picons/misc"
-    "/usr/share/picons/" "/usr/share/picons/users" "/usr/share/picons/usenix"
-    "/usr/share/picons/news" "/usr/share/picons/domains"
-    "/usr/share/picons/misc")
-  "List of directories where picons reside.
-The directories are searched for in the order they appear in the list.")
-
-(defvar mh-picon-existing-directory-list 'unset
-  "List of directories to search in.")
-
-(defvar mh-picon-cache (make-hash-table :test #'equal))
-
-(defvar mh-picon-image-types
-  (loop for type in '(xpm xbm gif)
-        when (or (mh-do-in-gnu-emacs
-                   (ignore-errors
-                     (mh-funcall-if-exists image-type-available-p type)))
-                 (mh-do-in-xemacs (featurep type)))
-        collect type))
-
-(defun mh-picon-set-directory-list ()
-  "Update `mh-picon-existing-directory-list' if needed."
-  (when (eq mh-picon-existing-directory-list 'unset)
-    (setq mh-picon-existing-directory-list
-          (loop for x in mh-picon-directory-list
-                when (file-directory-p x) collect x))))
-
-(defun* mh-picon-get-image ()
-  "Find the best possible match and return contents."
-  (mh-picon-set-directory-list)
-  (save-restriction
-    (let* ((from-field (ignore-errors (car (message-tokenize-header
-                                            (mh-get-header-field "from:")))))
-           (from (car (ignore-errors
-                        (mh-funcall-if-exists ietf-drums-parse-address
-                                              from-field))))
-           (host (and from
-                      (string-match "\\([^+]*\\)\\(+.*\\)?@\\(.*\\)" from)
-                      (downcase (match-string 3 from))))
-           (user (and host (downcase (match-string 1 from))))
-           (canonical-address (format "%s@%s" user host))
-           (cached-value (gethash canonical-address mh-picon-cache))
-           (host-list (and host (delete "" (split-string host "\\."))))
-           (match nil))
-      (cond (cached-value (return-from mh-picon-get-image cached-value))
-            ((not host-list) (return-from mh-picon-get-image nil)))
-      (setq match
-            (block 'loop
-              ;; u@h search
-              (loop for dir in mh-picon-existing-directory-list
-                    do (loop for type in mh-picon-image-types
-                             ;; [path]user@host
-                             for file1 = (format "%s/%s.%s"
-                                                 dir canonical-address type)
-                             when (file-exists-p file1)
-                             do (return-from 'loop file1)
-                             ;; [path]user
-                             for file2 = (format "%s/%s.%s" dir user type)
-                             when (file-exists-p file2)
-                             do (return-from 'loop file2)
-                             ;; [path]host
-                             for file3 = (format "%s/%s.%s" dir host type)
-                             when (file-exists-p file3)
-                             do (return-from 'loop file3)))
-              ;; facedb search
-              ;; Search order for user@foo.net:
-              ;;   [path]net/foo/user
-              ;;   [path]net/foo/user/face
-              ;;   [path]net/user
-              ;;   [path]net/user/face
-              ;;   [path]net/foo/unknown
-              ;;   [path]net/foo/unknown/face
-              ;;   [path]net/unknown
-              ;;   [path]net/unknown/face
-              (loop for u in (list user "unknown")
-                    do (loop for dir in mh-picon-existing-directory-list
-                             do (loop for x on host-list by #'cdr
-                                      for y = (mh-picon-generate-path x u dir)
-                                      do (loop for type in mh-picon-image-types
-                                               for z1 = (format "%s.%s" y type)
-                                               when (file-exists-p z1)
-                                               do (return-from 'loop z1)
-                                               for z2 = (format "%s/face.%s"
-                                                                y type)
-                                               when (file-exists-p z2)
-                                               do (return-from 'loop z2)))))))
-      (setf (gethash canonical-address mh-picon-cache)
-            (mh-picon-file-contents match)))))
-
-(defun mh-picon-file-contents (file)
-  "Return details about FILE.
-A list of consisting of a symbol for the type of the file and the
-file contents as a string is returned. If FILE is nil, then both
-elements of the list are nil."
-  (if (stringp file)
-      (with-temp-buffer
-        (let ((type (and (string-match ".*\\.\\(...\\)$" file)
-                         (intern (match-string 1 file)))))
-          (insert-file-contents-literally file)
-          (values type (buffer-string))))
-    (values nil nil)))
-
-(defun mh-picon-generate-path (host-list user directory)
-  "Generate the image file path.
-HOST-LIST is the parsed host address of the email address, USER
-the username and DIRECTORY is the directory relative to which the
-path is generated."
-  (loop with acc = ""
-        for elem in host-list
-        do (setq acc (format "%s/%s" elem acc))
-        finally return (format "%s/%s%s" directory acc user)))
-
-
-
-;; X-Image-URL display
-
-(defvar mh-x-image-cache-directory nil
-  "Directory where X-Image-URL images are cached.")
-(defvar mh-x-image-scaling-function
-  (cond ((executable-find "convert")
-         'mh-x-image-scale-with-convert)
-        ((and (executable-find "anytopnm") (executable-find "pnmscale")
-              (executable-find "pnmtopng"))
-         'mh-x-image-scale-with-pnm)
-        (t 'ignore))
-  "Function to use to scale image to proper size.")
-(defvar mh-wget-executable nil)
-(defvar mh-wget-choice
-  (or (and (setq mh-wget-executable (executable-find "wget")) 'wget)
-      (and (setq mh-wget-executable (executable-find "fetch")) 'fetch)
-      (and (setq mh-wget-executable (executable-find "curl")) 'curl)))
-(defvar mh-wget-option
-  (cdr (assoc mh-wget-choice '((curl . "-o") (fetch . "-o") (wget . "-O")))))
-(defvar mh-x-image-temp-file nil)
-(defvar mh-x-image-url nil)
-(defvar mh-x-image-marker nil)
-(defvar mh-x-image-url-cache-file nil)
-
-;; Functions to scale image to proper size
-(defun mh-x-image-scale-with-pnm (input output)
-  "Scale image in INPUT file and write to OUTPUT file using pnm tools."
-  (let ((res (shell-command-to-string
-              (format "anytopnm < %s | pnmscale -xysize 96 48 | pnmtopng > %s"
-                      input output))))
-    (unless (equal res "")
-      (delete-file output))))
-
-(defun mh-x-image-scale-with-convert (input output)
-  "Scale image in INPUT file and write to OUTPUT file using ImageMagick."
-  (call-process "convert" nil nil nil "-geometry" "96x48" input output))
-
-;; Copy of constant from url-util.el in Emacs 22; needed by Emacs 21.
-(if (not (boundp 'url-unreserved-chars))
-    (defconst url-unreserved-chars
-      '(
-        ?a ?b ?c ?d ?e ?f ?g ?h ?i ?j ?k ?l ?m ?n ?o ?p ?q ?r ?s ?t ?u ?v ?w ?x ?y ?z
-        ?A ?B ?C ?D ?E ?F ?G ?H ?I ?J ?K ?L ?M ?N ?O ?P ?Q ?R ?S ?T ?U ?V ?W ?X ?Y ?Z
-        ?0 ?1 ?2 ?3 ?4 ?5 ?6 ?7 ?8 ?9
-        ?- ?_ ?. ?! ?~ ?* ?' ?\( ?\))
-      "A list of characters that are _NOT_ reserved in the URL spec.
-This is taken from RFC 2396."))
-
-;; Copy of function from url-util.el in Emacs 22; needed by Emacs 21.
-(mh-defun-compat url-hexify-string (str)
-  "Escape characters in a string."
-  (mapconcat
-   (lambda (char)
-     ;; Fixme: use a char table instead.
-     (if (not (memq char url-unreserved-chars))
-	 (if (> char 255)
-	       (error "Hexifying multibyte character %s" str)
-	   (format "%%%02X" char))
-       (char-to-string char)))
-   str ""))
-
-(defun mh-x-image-url-cache-canonicalize (url)
-  "Canonicalize URL.
-Replace the ?/ character with a ?! character and append .png.
-Also replaces special characters with `url-hexify-string' since
-not all characters, such as :, are legal within Windows
-filenames. See URL `http://msdn.microsoft.com/library/default.asp?url=/library/en-us/fileio/fs/naming_a_file.asp'."
-  (format "%s/%s.png" mh-x-image-cache-directory
-          (url-hexify-string
-           (with-temp-buffer
-             (insert url)
-             (mh-replace-string "/" "!")
-             (buffer-string)))))
-
-(defun mh-x-image-set-download-state (file data)
-  "Setup a symbolic link from FILE to DATA."
-  (if data
-      (make-symbolic-link (symbol-name data) file t)
-    (delete-file file)))
-
-(defun mh-x-image-get-download-state (file)
-  "Check the state of FILE by following any symbolic links."
-  (unless (file-exists-p mh-x-image-cache-directory)
-    (call-process "mkdir" nil nil nil mh-x-image-cache-directory))
-  (cond ((file-symlink-p file)
-         (intern (file-name-nondirectory (file-chase-links file))))
-        ((not (file-exists-p file)) nil)
-        (t 'ok)))
-
-(defun mh-x-image-url-fetch-image (url cache-file marker sentinel)
-  "Fetch and display the image specified by URL.
-After the image is fetched, it is stored in CACHE-FILE. It will
-be displayed in a buffer and position specified by MARKER. The
-actual display is carried out by the SENTINEL function."
-  (if mh-wget-executable
-      (let ((buffer (get-buffer-create (generate-new-buffer-name
-                                        mh-temp-fetch-buffer)))
-            (filename (or (mh-funcall-if-exists make-temp-file "mhe-fetch")
-                          (expand-file-name (make-temp-name "~/mhe-fetch")))))
-        (save-excursion
-          (set-buffer buffer)
-          (set (make-local-variable 'mh-x-image-url-cache-file) cache-file)
-          (set (make-local-variable 'mh-x-image-marker) marker)
-          (set (make-local-variable 'mh-x-image-temp-file) filename))
-        (set-process-sentinel
-         (start-process "*mh-x-image-url-fetch*" buffer
-                        mh-wget-executable mh-wget-option filename url)
-         sentinel))
-    ;; Temporary failure
-    (mh-x-image-set-download-state cache-file 'try-again)))
-
-(defun mh-x-image-display (image marker)
-  "Display IMAGE at MARKER."
-  (save-excursion
-    (set-buffer (marker-buffer marker))
-    (let ((buffer-read-only nil)
-          (default-enable-multibyte-characters nil)
-          (buffer-modified-flag (buffer-modified-p)))
-      (unwind-protect
-          (when (and (file-readable-p image) (not (file-symlink-p image))
-                     (eq marker mh-x-image-marker))
-            (goto-char marker)
-            (mh-do-in-gnu-emacs
-              (mh-funcall-if-exists insert-image (create-image image 'png)))
-            (mh-do-in-xemacs
-              (when (featurep 'png)
-                (set-extent-begin-glyph
-                 (make-extent (point) (point))
-                 (make-glyph
-                  (vector 'png ':data (with-temp-buffer
-                                        (insert-file-contents-literally image)
-                                        (buffer-string))))))))
-        (set-buffer-modified-p buffer-modified-flag)))))
-
-(defun mh-x-image-scale-and-display (process change)
-  "When the wget PROCESS terminates scale and display image.
-The argument CHANGE is ignored."
-  (when (eq (process-status process) 'exit)
-    (let (marker temp-file cache-filename wget-buffer)
-      (save-excursion
-        (set-buffer (setq wget-buffer (process-buffer process)))
-        (setq marker mh-x-image-marker
-              cache-filename mh-x-image-url-cache-file
-              temp-file mh-x-image-temp-file))
-      (cond
-       ;; Check if we have `convert'
-       ((eq mh-x-image-scaling-function 'ignore)
-        (message "The \"convert\" program is needed to display X-Image-URL")
-        (mh-x-image-set-download-state cache-filename 'try-again))
-       ;; Scale fetched image
-       ((and (funcall mh-x-image-scaling-function temp-file cache-filename)
-             nil))
-       ;; Attempt to display image if we have it
-       ((file-exists-p cache-filename)
-        (mh-x-image-display cache-filename marker))
-       ;; We didn't find the image. Should we try to display it the next time?
-       (t (mh-x-image-set-download-state cache-filename 'try-again)))
-      (ignore-errors
-        (set-marker marker nil)
-        (delete-process process)
-        (kill-buffer wget-buffer)
-        (delete-file temp-file)))))
-
-(defun mh-x-image-url-sane-p (url)
-  "Check if URL is something sensible."
-  (let ((len (length url)))
-    (cond ((< len 5) nil)
-          ((not (equal (substring url 0 5) "http:")) nil)
-          ((> len 100) nil)
-          (t t))))
-
-(defun mh-x-image-url-display (url)
-  "Display image from location URL.
-If the URL isn't present in the cache then it is fetched with wget."
-  (let* ((cache-filename (mh-x-image-url-cache-canonicalize url))
-         (state (mh-x-image-get-download-state cache-filename))
-         (marker (set-marker (make-marker) (point))))
-    (set (make-local-variable 'mh-x-image-marker) marker)
-    (cond ((not (mh-x-image-url-sane-p url)))
-          ((eq state 'ok)
-           (mh-x-image-display cache-filename marker))
-          ((or (not mh-wget-executable)
-               (eq mh-x-image-scaling-function 'ignore)))
-          ((eq state 'never))
-          ((not mh-fetch-x-image-url)
-           (set-marker marker nil))
-          ((eq state 'try-again)
-           (mh-x-image-set-download-state cache-filename nil)
-           (mh-x-image-url-fetch-image url cache-filename marker
-                                       'mh-x-image-scale-and-display))
-          ((and (eq mh-fetch-x-image-url 'ask)
-                (not (y-or-n-p (format "Fetch %s? " url))))
-           (mh-x-image-set-download-state cache-filename 'never))
-          ((eq state nil)
-           (mh-x-image-url-fetch-image url cache-filename marker
-                                       'mh-x-image-scale-and-display)))))
-
-
-
-(defun mh-maybe-show (&optional msg)
-  "Display message at cursor, but only if in show mode.
-If optional arg MSG is non-nil, display that message instead."
-  (if mh-showing-mode (mh-show msg)))
-
-(defun mh-show (&optional message redisplay-flag)
-  "Display message\\<mh-folder-mode-map>.
-
-If the message under the cursor is already displayed, this command
-scrolls to the beginning of the message. MH-E normally hides a lot of
-the superfluous header fields that mailers add to a message, but if
-you wish to see all of them, use the command \\[mh-header-display].
-
-Two hooks can be used to control how messages are displayed. The
-first hook, `mh-show-mode-hook', is called early on in the
-process of the message display. It is usually used to perform
-some action on the message's content. The second hook,
-`mh-show-hook', is the last thing called after messages are
-displayed. It's used to affect the behavior of MH-E in general or
-when `mh-show-mode-hook' is too early.
-
-From a program, optional argument MESSAGE can be used to display an
-alternative message. The optional argument REDISPLAY-FLAG forces the
-redisplay of the message even if the show buffer was already
-displaying the correct message.
-
-See the \"mh-show\" customization group for a litany of options that
-control what displayed messages look like."
-  (interactive (list nil t))
-  (when (or redisplay-flag
-            (and mh-showing-with-headers
-                 (or mh-mhl-format-file mh-clean-message-header-flag)))
-    (mh-invalidate-show-buffer))
-  (mh-show-msg message))
-
-(defun mh-show-mouse (event)
-  "Move point to mouse EVENT and show message."
-  (interactive "e")
-  (mouse-set-point event)
-  (mh-show))
-
-(defun mh-summary-height ()
-  "Return ideal value for the variable `mh-summary-height'.
-The current frame height is taken into consideration."
-  (or (and (fboundp 'frame-height)
-           (> (frame-height) 24)
-           (min 10 (/ (frame-height) 6)))
-      4))
-
-(defun mh-show-msg (msg)
-  "Show MSG.
-
-The hook `mh-show-hook' is called after the message has been
-displayed."
-  (if (not msg)
-      (setq msg (mh-get-msg-num t)))
-  (mh-showing-mode t)
-  (setq mh-page-to-next-msg-flag nil)
-  (let ((folder mh-current-folder)
-        (folders (list mh-current-folder))
-        (clean-message-header mh-clean-message-header-flag)
-        (show-window (get-buffer-window mh-show-buffer))
-        (display-mime-buttons-flag mh-display-buttons-for-inline-parts-flag))
-    (if (not (eq (next-window (minibuffer-window)) (selected-window)))
-        (delete-other-windows))         ; force ourself to the top window
-    (mh-in-show-buffer (mh-show-buffer)
-      (setq mh-display-buttons-for-inline-parts-flag display-mime-buttons-flag)
-      (if (and show-window
-               (equal (mh-msg-filename msg folder) buffer-file-name))
-          (progn                        ;just back up to start
-            (goto-char (point-min))
-            (if (not clean-message-header)
-                (mh-start-of-uncleaned-message)))
-        (mh-display-msg msg folder)))
-    (if (not (= (1+ (window-height)) (frame-height))) ;not horizontally split
-        (shrink-window (- (window-height) (or mh-summary-height
-                                              (mh-summary-height)))))
-    (mh-recenter nil)
-    ;; The following line is a nop which forces update of the scan line so
-    ;; that font-lock will update it (if needed)...
-    (mh-notate nil nil mh-cmd-note)
-    (if (not (memq msg mh-seen-list))
-        (setq mh-seen-list (cons msg mh-seen-list)))
-    (when mh-update-sequences-after-mh-show-flag
-      (mh-update-sequences)
-      (when mh-index-data
-        (setq folders
-              (append (mh-index-delete-from-sequence mh-unseen-seq (list msg))
-                      folders)))
-      (when (mh-speed-flists-active-p)
-        (apply #'mh-speed-flists t folders)))
-    (run-hooks 'mh-show-hook)))
-
-(defun mh-modify (&optional message)
-  "Edit message.
-
-There are times when you need to edit a message. For example, you
-may need to fix a broken Content-Type header field. You can do
-this with this command. It displays the raw message in an
-editable buffer. When you are done editing, save and kill the
-buffer as you would any other.
-
-From a program, edit MESSAGE; nil means edit current message."
-  (interactive)
-  (let* ((message (or message (mh-get-msg-num t)))
-         (msg-filename (mh-msg-filename message))
-         edit-buffer)
-    (when (not (file-exists-p msg-filename))
-      (error "Message %d does not exist" message))
-
-    ;; Invalidate the show buffer if it is showing the same message that is
-    ;; to be edited.
-    (when (and (buffer-live-p (get-buffer mh-show-buffer))
-               (equal (save-excursion (set-buffer mh-show-buffer)
-                                      buffer-file-name)
-                      msg-filename))
-      (mh-invalidate-show-buffer))
-
-    ;; Edit message
-    (find-file msg-filename)
-    (setq edit-buffer (current-buffer))
-
-    ;; Set buffer properties
-    (mh-letter-mode)
-    (use-local-map text-mode-map)
-
-    ;; Just show the edit buffer...
-    (delete-other-windows)
-    (switch-to-buffer edit-buffer)))
-
-(defun mh-show-unquote-From ()
-  "Decode >From at beginning of lines for `mh-show-mode'."
-  (save-excursion
-    (let ((modified (buffer-modified-p))
-          (case-fold-search nil)
-          (buffer-read-only nil))
-      (goto-char (mh-mail-header-end))
-      (while (re-search-forward "^>From" nil t)
-        (replace-match "From"))
-      (set-buffer-modified-p modified))))
-
-(defun mh-msg-folder (folder-name)
-  "Return the name of the buffer for FOLDER-NAME."
-  folder-name)
-
-(defun mh-display-msg (msg-num folder-name)
-  "Display MSG-NUM of FOLDER-NAME.
-Sets the current buffer to the show buffer."
-  (let ((folder (mh-msg-folder folder-name)))
-    (set-buffer folder)
-    ;; When Gnus uses external displayers it has to keep handles longer. So
-    ;; we will delete these handles when mh-quit is called on the folder. It
-    ;; would be nicer if there are weak pointers in emacs lisp, then we could
-    ;; get the garbage collector to do this for us.
-    (unless (mh-buffer-data)
-      (setf (mh-buffer-data) (mh-make-buffer-data)))
-    ;; Bind variables in folder buffer in case they are local
-    (let ((formfile mh-mhl-format-file)
-          (clean-message-header mh-clean-message-header-flag)
-          (invisible-headers mh-invisible-header-fields-compiled)
-          (visible-headers nil)
-          (msg-filename (mh-msg-filename msg-num folder-name))
-          (show-buffer mh-show-buffer)
-          (mm-inline-media-tests mh-mm-inline-media-tests))
-      (if (not (file-exists-p msg-filename))
-          (error "Message %d does not exist" msg-num))
-      (if (and (> mh-show-maximum-size 0)
-               (> (elt (file-attributes msg-filename) 7)
-                  mh-show-maximum-size)
-               (not (y-or-n-p
-                     (format
-                      "Message %d (%d bytes) exceeds %d bytes. Display it? "
-                      msg-num (elt (file-attributes msg-filename) 7)
-                      mh-show-maximum-size))))
-          (error "Message %d not displayed" msg-num))
-      (set-buffer show-buffer)
-      (cond ((not (equal msg-filename buffer-file-name))
-             (mh-unvisit-file)
-             (setq buffer-read-only nil)
-             ;; Cleanup old mime handles
-             (mh-mime-cleanup)
-             (erase-buffer)
-             ;; Changing contents, so this hook needs to be reinitialized.
-             ;; pgp.el uses this.
-             (if (boundp 'write-contents-hooks) ;Emacs 19
-                 (kill-local-variable 'write-contents-hooks))
-             (if formfile
-                 (mh-exec-lib-cmd-output "mhl" "-nobell" "-noclear"
-                                         (if (stringp formfile)
-                                             (list "-form" formfile))
-                                         msg-filename)
-               (insert-file-contents-literally msg-filename))
-             ;; Use mm to display buffer
-             (when (and mh-decode-mime-flag (not formfile))
-               (mh-add-missing-mime-version-header)
-               (setf (mh-buffer-data) (mh-make-buffer-data))
-               (mh-mime-display))
-             (mh-show-mode)
-             ;; Header cleanup
-             (goto-char (point-min))
-             (cond (clean-message-header
-                    (mh-clean-msg-header (point-min)
-                                         invisible-headers
-                                         visible-headers)
-                    (goto-char (point-min)))
-                   (t
-                    (mh-start-of-uncleaned-message)))
-             (mh-decode-message-header)
-             ;; the parts of visiting we want to do (no locking)
-             (or (eq buffer-undo-list t) ;don't save undo info for prev msgs
-                 (setq buffer-undo-list nil))
-             (set-buffer-auto-saved)
-             ;; the parts of set-visited-file-name we want to do (no locking)
-             (setq buffer-file-name msg-filename)
-             (setq buffer-backed-up nil)
-             (auto-save-mode 1)
-             (set-mark nil)
-             (unwind-protect
-                 (when (and mh-decode-mime-flag (not formfile))
-                   (setq buffer-read-only nil)
-                   (mh-display-smileys)
-                   (mh-display-emphasis))
-               (setq buffer-read-only t))
-             (set-buffer-modified-p nil)
-             (setq mh-show-folder-buffer folder)
-             (setq mode-line-buffer-identification
-                   (list (format mh-show-buffer-mode-line-buffer-id
-                                 folder-name msg-num)))
-             (mh-logo-display)
-             (set-buffer folder)
-             (setq mh-showing-with-headers nil))))))
-
-(defun mh-clean-msg-header (start invisible-headers visible-headers)
-  "Flush extraneous lines in message header.
-
-Header is cleaned from START to the end of the message header.
-INVISIBLE-HEADERS contains a regular expression specifying lines
-to delete from the header. VISIBLE-HEADERS contains a regular
-expression specifying the lines to display. INVISIBLE-HEADERS is
-ignored if VISIBLE-HEADERS is non-nil."
-  ;; XXX Note that MH-E no longer supports the `mh-visible-headers'
-  ;; variable, so this function could be trimmed of this feature too."
-  (let ((case-fold-search t)
-        (buffer-read-only nil))
-    (save-restriction
-      (goto-char start)
-      (if (search-forward "\n\n" nil 'move)
-          (backward-char 1))
-      (narrow-to-region start (point))
-      (goto-char (point-min))
-      (if visible-headers
-          (while (< (point) (point-max))
-            (cond ((looking-at visible-headers)
-                   (forward-line 1)
-                   (while (looking-at "[ \t]") (forward-line 1)))
-                  (t
-                   (mh-delete-line 1)
-                   (while (looking-at "[ \t]")
-                     (mh-delete-line 1)))))
-        (while (re-search-forward invisible-headers nil t)
-          (beginning-of-line)
-          (mh-delete-line 1)
-          (while (looking-at "[ \t]")
-            (mh-delete-line 1)))))
-    (let ((mh-compose-skipped-header-fields ()))
-      (mh-letter-hide-all-skipped-fields))
-    (unlock-buffer)))
-
-(defun mh-delete-line (lines)
-  "Delete the next LINES lines."
-  (delete-region (point) (progn (forward-line lines) (point))))
-
-(defun mh-notate (msg notation offset)
-  "Mark MSG with the character NOTATION at position OFFSET.
-Null MSG means the message at cursor.
-If NOTATION is nil then no change in the buffer occurs."
-  (save-excursion
-    (if (or (null msg)
-            (mh-goto-msg msg t t))
-        (with-mh-folder-updating (t)
-          (beginning-of-line)
-          (forward-char offset)
-          (let* ((change-stack-flag
-                  (and (equal offset
-                              (+ mh-cmd-note mh-scan-field-destination-offset))
-                       (not (eq notation mh-note-seq))))
-                 (msg (and change-stack-flag (or msg (mh-get-msg-num nil))))
-                 (stack (and msg (gethash msg mh-sequence-notation-history)))
-                 (notation (or notation (char-after))))
-            (if stack
-                ;; The presence of the stack tells us that we don't need to
-                ;; notate the message, since the notation would be replaced
-                ;; by a sequence notation. So we will just put the notation
-                ;; at the bottom of the stack. If the sequence is deleted,
-                ;; the correct notation will be shown.
-                (setf (gethash msg mh-sequence-notation-history)
-                      (reverse (cons notation (cdr (reverse stack)))))
-              ;; Since we don't have any sequence notations in the way, just
-              ;; notate the scan line.
-              (delete-char 1)
-              (insert notation))
-            (when change-stack-flag
-              (mh-thread-update-scan-line-map msg notation offset)))))))
-
-(defun mh-goto-msg (number &optional no-error-if-no-message dont-show)
-  "Go to a message\\<mh-folder-mode-map>.
-
-You can enter the message NUMBER either before or after typing
-\\[mh-goto-msg]. In the latter case, Emacs prompts you.
-
-In a program, optional non-nil second argument NO-ERROR-IF-NO-MESSAGE
-means return nil instead of signaling an error if message does not
-exist\; in this case, the cursor is positioned near where the message
-would have been. Non-nil third argument DONT-SHOW means not to show
-the message."
-  (interactive "NGo to message: ")
-  (setq number (prefix-numeric-value number))
-  (let ((point (point))
-        (return-value t))
-    (goto-char (point-min))
-    (unless (re-search-forward (format mh-scan-msg-search-regexp number) nil t)
-      (goto-char point)
-      (unless no-error-if-no-message
-        (error "No message %d" number))
-      (setq return-value nil))
-    (beginning-of-line)
-    (or dont-show (not return-value) (mh-maybe-show number))
-    return-value))
-
-(defun mh-set-folder-modified-p (flag)
-  "Mark current folder as modified or unmodified according to FLAG."
-  (set-buffer-modified-p flag))
-
-(defun mh-find-seq (name)
-  "Return sequence NAME."
-  (assoc name mh-seq-list))
-
-(defun mh-seq-to-msgs (seq)
-  "Return a list of the messages in SEQ."
-  (mh-seq-msgs (mh-find-seq seq)))
-
-(defun mh-update-scan-format (fmt width)
-  "Return a scan format with the (msg) width in the FMT replaced with WIDTH.
-
-The message number width portion of the format is discovered
-using `mh-scan-msg-format-regexp'. Its replacement is controlled
-with `mh-scan-msg-format-string'."
-  (or (and
-       (string-match mh-scan-msg-format-regexp fmt)
-       (let ((begin (match-beginning 1))
-             (end (match-end 1)))
-         (concat (substring fmt 0 begin)
-                 (format mh-scan-msg-format-string width)
-                 (substring fmt end))))
-      fmt))
-
-(defun mh-msg-num-width (folder)
-  "Return the width of the largest message number in this FOLDER."
-  (or mh-progs (mh-find-path))
-  (let ((tmp-buffer (get-buffer-create mh-temp-buffer))
-        (width 0))
-    (save-excursion
-      (set-buffer tmp-buffer)
-      (erase-buffer)
-      (apply 'call-process
-             (expand-file-name mh-scan-prog mh-progs) nil '(t nil) nil
-             (list folder "last" "-format" "%(msg)"))
-      (goto-char (point-min))
-      (if (re-search-forward mh-scan-msg-number-regexp nil 0 1)
-          (setq width (length (buffer-substring
-                               (match-beginning 1) (match-end 1))))))
-    width))
-
-(defun mh-add-msgs-to-seq (msgs seq &optional internal-flag dont-annotate-flag)
-  "Add MSGS to SEQ.
-
-Remove duplicates and keep sequence sorted. If optional
-INTERNAL-FLAG is non-nil, do not mark the message in the scan
-listing or inform MH of the addition.
-
-If DONT-ANNOTATE-FLAG is non-nil then the annotations in the
-folder buffer are not updated."
-  (let ((entry (mh-find-seq seq))
-        (internal-seq-flag (mh-internal-seq seq)))
-    (if (and msgs (atom msgs)) (setq msgs (list msgs)))
-    (if (null entry)
-        (setq mh-seq-list
-              (cons (mh-make-seq seq (mh-canonicalize-sequence msgs))
-                    mh-seq-list))
-      (if msgs (setcdr entry (mh-canonicalize-sequence
-                              (append msgs (mh-seq-msgs entry))))))
-    (unless internal-flag
-      (mh-add-to-sequence seq msgs)
-      (when (not dont-annotate-flag)
-        (mh-iterate-on-range msg msgs
-          (unless (memq msg (cdr entry))
-            (mh-add-sequence-notation msg internal-seq-flag)))))))
-
-(defun mh-canonicalize-sequence (msgs)
-  "Sort MSGS in decreasing order and remove duplicates."
-  (let* ((sorted-msgs (sort (copy-sequence msgs) '>))
-         (head sorted-msgs))
-    (while (cdr head)
-      (if (= (car head) (cadr head))
-          (setcdr head (cddr head))
-        (setq head (cdr head))))
-    sorted-msgs))
+;;; Folder Cache and Access
 
 (defvar mh-sub-folders-cache (make-hash-table :test #'equal))
 (defvar mh-current-folder-name nil)
 (defvar mh-flists-partial-line "")
 (defvar mh-flists-process nil)
 
+;;;###mh-autoload
+(defun mh-clear-sub-folders-cache ()
+  "Clear `mh-sub-folders-cache'."
+  (clrhash mh-sub-folders-cache))
+
 ;; Initialize mh-sub-folders-cache...
 (defun mh-collect-folder-names ()
   "Collect folder names by running \"folders\"."
@@ -2050,17 +387,17 @@
 PROCESS is the flists process that was run to collect folder
 names and the function is called when OUTPUT is available."
   (let ((position 0)
-	(prevailing-match-data (match-data))
-	line-end folder)
+        (prevailing-match-data (match-data))
+        line-end folder)
     (unwind-protect
-	(while (setq line-end (string-match "\n" output position))
-	  (setq folder (format "+%s%s"
+        (while (setq line-end (string-match "\n" output position))
+          (setq folder (format "+%s%s"
                                mh-flists-partial-line
                                (substring output position line-end)))
-	  (setq mh-flists-partial-line "")
+          (setq mh-flists-partial-line "")
           (unless (equal (aref folder 1) ?.)
             (mh-populate-sub-folders-cache folder))
-	  (setq position (1+ line-end)))
+          (setq position (1+ line-end)))
       (set-match-data prevailing-match-data))
     (setq mh-flists-partial-line (substring output position))))
 
@@ -2148,6 +485,7 @@
        t
      nil))
 
+;;;###mh-autoload
 (defun mh-folder-list (folder)
   "Return FOLDER and its descendents.
 Returns a list of strings. For example,
@@ -2176,6 +514,7 @@
                             (mh-folder-list (concat folder (car f)))))))
     folder-list))
 
+;;;###mh-autoload
 (defun mh-sub-folders (folder &optional add-trailing-slash-flag)
   "Find the subfolders of FOLDER.
 The function avoids running folders unnecessarily by caching the
@@ -2244,6 +583,7 @@
                               results))))
     results))
 
+;;;###mh-autoload
 (defun mh-remove-from-sub-folders-cache (folder)
   "Remove FOLDER and its parent from `mh-sub-folders-cache'.
 FOLDER should be unconditionally removed from the cache. Also the
@@ -2269,12 +609,33 @@
             (setq one-ancestor-found t))))
       (remhash nil mh-sub-folders-cache))))
 
+
+
+;;; Folder Utilities
+
+;;;###mh-autoload
+(defun mh-folder-name-p (name)
+  "Return non-nil if NAME is the name of a folder.
+A name (a string or symbol) can be a folder name if it begins
+with \"+\"."
+  (if (symbolp name)
+      (eq (aref (symbol-name name) 0) ?+)
+    (and (> (length name) 0)
+         (eq (aref name 0) ?+))))
+
+;;;###mh-autoload
+(defun mh-expand-file-name (filename &optional default)
+  "Expand FILENAME like `expand-file-name', but also handle MH folder names.
+Any filename that starts with '+' is treated as a folder name.
+See `expand-file-name' for description of DEFAULT."
+  (if (mh-folder-name-p filename)
+      (expand-file-name (substring filename 1) mh-user-path)
+    (expand-file-name filename default)))
+
 (defvar mh-folder-hist nil)
 
 ;; Shush compiler.
-(eval-when-compile
-  (defvar mh-speed-folder-map)
-  (defvar mh-speed-flists-cache))
+(eval-when-compile (defvar mh-speed-flists-cache))
 
 (defvar mh-allow-root-folder-flag nil
   "Non-nil means \"+\" is an acceptable folder name.
@@ -2289,12 +650,14 @@
 
 (defvar mh-speed-flists-inhibit-flag nil)
 
+;;;###mh-autoload
 (defun mh-speed-flists-active-p ()
   "Check if speedbar is running with message counts enabled."
   (and (featurep 'mh-speed)
        (not mh-speed-flists-inhibit-flag)
        (> (hash-table-count mh-speed-flists-cache) 0)))
 
+;;;###mh-autoload
 (defun mh-folder-completion-function (name predicate flag)
   "Programmable completion for folder names.
 NAME is the partial folder name that has been input. PREDICATE if
@@ -2332,6 +695,12 @@
                    ((equal path mh-user-path) nil)
                    (t (file-exists-p path))))))))
 
+;; Shush compiler.
+(eval-when-compile
+  (mh-do-in-xemacs
+    (defvar completion-root-regexp)
+    (defvar minibuffer-completing-file-name)))
+
 (defun mh-folder-completing-read (prompt default allow-root-folder-flag)
   "Read folder name with PROMPT and default result DEFAULT.
 If ALLOW-ROOT-FOLDER-FLAG is non-nil then \"+\" is allowed to be
@@ -2345,6 +714,7 @@
                       'mh-folder-hist default))
    t))
 
+;;;###mh-autoload
 (defun mh-prompt-for-folder (prompt default can-create
                              &optional default-string allow-root-folder-flag)
   "Prompt for a folder name with PROMPT.
@@ -2408,37 +778,197 @@
 
 
 
-;;; List and string manipulation
+;;; Message Utilities
+
+;; Functions that would ordinarily be in mh-letter.el that are needed
+;; by mh-show.el are found here in order to prevent the loading of
+;; mh-letter.el until a message is actually composed.
+
+;;;###mh-autoload
+(defun mh-in-header-p ()
+  "Return non-nil if the point is in the header of a draft message."
+  (< (point) (mh-mail-header-end)))
+
+;;;###mh-autoload
+(defun mh-extract-from-header-value ()
+  "Extract From: string from header."
+  (save-excursion
+    (if (not (mh-goto-header-field "From:"))
+        nil
+      (skip-chars-forward " \t")
+      (buffer-substring-no-properties
+       (point) (progn (mh-header-field-end)(point))))))
+
+;;;###mh-autoload
+(defun mh-get-header-field (field)
+  "Find and return the body of FIELD in the mail header.
+Returns the empty string if the field is not in the header of the
+current buffer."
+  (if (mh-goto-header-field field)
+      (progn
+        (skip-chars-forward " \t")      ;strip leading white space in body
+        (let ((start (point)))
+          (mh-header-field-end)
+          (buffer-substring-no-properties start (point))))
+    ""))
 
-(defun mh-list-to-string (l)
-  "Flatten the list L and make every element of the new list into a string."
-  (nreverse (mh-list-to-string-1 l)))
+;;;###mh-autoload
+(defun mh-goto-header-field (field)
+  "Move to FIELD in the message header.
+Move to the end of the FIELD name, which should end in a colon.
+Returns t if found, nil if not."
+  (goto-char (point-min))
+  (let ((case-fold-search t)
+        (headers-end (save-excursion
+                       (mh-goto-header-end 0)
+                       (point))))
+    (re-search-forward (format "^%s" field) headers-end t)))
+
+;;;###mh-autoload
+(defun mh-goto-header-end (arg)
+  "Move the cursor ARG lines after the header."
+  (if (re-search-forward "^-*$" nil nil)
+      (forward-line arg)))
+
+;;;###mh-autoload
+(defun mh-mail-header-end ()
+  "Substitute for `mail-header-end' that doesn't widen the buffer.
+
+In MH-E we frequently need to find the end of headers in nested
+messages, where the buffer has been narrowed. This function works
+in this situation."
+  (save-excursion
+    ;; XXX: The following replaces a call to rfc822-goto-eoh. Occasionally,
+    ;; mail headers that MH-E has to read contains lines of the form:
+    ;;    From xxx@yyy Mon May 10 11:48:07 2004
+    ;; In this situation, rfc822-goto-eoh doesn't go to the end of the
+    ;; header. The replacement allows From_ lines in the mail header.
+    (goto-char (point-min))
+    (loop for p = (re-search-forward
+                   "^\\([:\n]\\|[^: \t\n]+[ \t\n]\\)" nil 'move)
+          do (cond ((null p) (return))
+                   (t (goto-char (match-beginning 0))
+                      (unless (looking-at "From ") (return))
+                      (goto-char p))))
+    (point)))
+
+;;;###mh-autoload
+(defun mh-header-field-beginning ()
+  "Move to the beginning of the current header field.
+Handles RFC 822 continuation lines."
+  (beginning-of-line)
+  (while (looking-at "^[ \t]")
+    (forward-line -1)))
+
+;;;###mh-autoload
+(defun mh-header-field-end ()
+  "Move to the end of the current header field.
+Handles RFC 822 continuation lines."
+  (forward-line 1)
+  (while (looking-at "^[ \t]")
+    (forward-line 1))
+  (backward-char 1))                    ;to end of previous line
 
-(defun mh-list-to-string-1 (l)
-  "Flatten the list L and make every element of the new list into a string."
-  (let ((new-list nil))
-    (while l
-      (cond ((null (car l)))
-            ((symbolp (car l))
-             (setq new-list (cons (symbol-name (car l)) new-list)))
-            ((numberp (car l))
-             (setq new-list (cons (int-to-string (car l)) new-list)))
-            ((equal (car l) ""))
-            ((stringp (car l)) (setq new-list (cons (car l) new-list)))
-            ((listp (car l))
-             (setq new-list (nconc (mh-list-to-string-1 (car l))
-                                   new-list)))
-            (t (error "Bad element in `mh-list-to-string': %s" (car l))))
-      (setq l (cdr l)))
-    new-list))
+;;;###mh-autoload
+(defun mh-letter-hide-all-skipped-fields ()
+  "Hide all skipped fields."
+  (save-excursion
+    (goto-char (point-min))
+    (save-restriction
+      (narrow-to-region (point) (mh-mail-header-end))
+      (while (re-search-forward mh-letter-header-field-regexp nil t)
+        (if (mh-letter-skipped-header-field-p (match-string 1))
+            (mh-letter-toggle-header-field-display -1)
+          (mh-letter-toggle-header-field-display 'long))
+        (beginning-of-line 2)))))
+
+;;;###mh-autoload
+(defun mh-letter-skipped-header-field-p (field)
+  "Check if FIELD is to be skipped."
+  (let ((field (downcase field)))
+    (loop for x in mh-compose-skipped-header-fields
+          when (equal (downcase x) field) return t
+          finally return nil)))
+
+(defvar mh-hidden-header-keymap
+  (let ((map (make-sparse-keymap)))
+    (mh-do-in-gnu-emacs
+      (define-key map [mouse-2] 'mh-letter-toggle-header-field-display-button))
+    (mh-do-in-xemacs
+      (define-key map '(button2)
+        'mh-letter-toggle-header-field-display-button))
+    map))
+
+;;;###mh-autoload
+(defun mh-letter-toggle-header-field-display (arg)
+  "Toggle display of header field at point.
 
-(defun mh-replace-string (old new)
-  "Replace all occurrences of OLD with NEW in the current buffer.
-Ignores case when searching for OLD."
-  (goto-char (point-min))
-  (let ((case-fold-search t))
-    (while (search-forward old nil t)
-      (replace-match new t t))))
+Use this command to display truncated header fields. This command
+is a toggle so entering it again will hide the field. This
+command takes a prefix argument ARG: if negative then the field
+is hidden, if positive then the field is displayed."
+  (interactive (list nil))
+  (when (and (mh-in-header-p)
+             (progn
+               (end-of-line)
+               (re-search-backward mh-letter-header-field-regexp nil t)))
+    (let ((buffer-read-only nil)
+          (modified-flag (buffer-modified-p))
+          (begin (point))
+          end)
+      (end-of-line)
+      (setq end (1- (if (re-search-forward "^[^ \t]" nil t)
+                        (match-beginning 0)
+                      (point-max))))
+      (goto-char begin)
+      ;; Make it clickable...
+      (add-text-properties begin end `(keymap ,mh-hidden-header-keymap
+                                       mouse-face highlight))
+      (unwind-protect
+          (cond ((or (and (not arg)
+                          (text-property-any begin end 'invisible 'vanish))
+                     (and (numberp arg) (>= arg 0))
+                     (and (eq arg 'long) (> (line-beginning-position 5) end)))
+                 (remove-text-properties begin end '(invisible nil))
+                 (search-forward ":" (line-end-position) t)
+                 (mh-letter-skip-leading-whitespace-in-header-field))
+                ;; XXX Redesign to make usable by user. Perhaps use a positive
+                ;; numeric prefix to make that many lines visible.
+                ((eq arg 'long)
+                 (end-of-line 4)
+                 (mh-letter-truncate-header-field end)
+                 (beginning-of-line))
+                (t (end-of-line)
+                   (mh-letter-truncate-header-field end)
+                   (beginning-of-line)))
+        (set-buffer-modified-p modified-flag)))))
+
+;;;###mh-autoload
+(defun mh-letter-skip-leading-whitespace-in-header-field ()
+  "Skip leading whitespace in a header field.
+If the header field doesn't have at least one space after the
+colon then a space character is added."
+  (let ((need-space t))
+    (while (memq (char-after) '(?\t ?\ ))
+      (forward-char)
+      (setq need-space nil))
+    (when need-space (insert " "))))
+
+(defun mh-letter-truncate-header-field (end)
+  "Replace text from current line till END with an ellipsis.
+If the current line is too long truncate a part of it as well."
+  (let ((max-len (min (window-width) 62)))
+    (when (> (+ (current-column) 4) max-len)
+      (backward-char (- (+ (current-column) 5) max-len)))
+    (when (> end (point))
+      (add-text-properties (point) end '(invisible vanish)))))
+
+;;;###mh-autoload
+(defun mh-signature-separator-p ()
+  "Return non-nil if buffer includes \"^-- $\"."
+  (save-excursion
+    (goto-char (point-min))
+    (re-search-forward mh-signature-separator-regexp nil t)))
 
 (provide 'mh-utils)
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lisp/mh-e/mh-xface.el	Wed Feb 01 10:07:17 2006 +0000
@@ -0,0 +1,479 @@
+;;; mh-xface.el --- MH-E X-Face and Face header field display
+
+;; Copyright (C) 2002, 2003, 2005, 2006 Free Software Foundation, Inc.
+
+;; Author: Bill Wohler <wohler@newt.com>
+;; Maintainer: Bill Wohler <wohler@newt.com>
+;; Keywords: mail
+;; See: mh-e.el
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
+
+;;; Commentary:
+
+;;; Change Log:
+
+;;; Code:
+
+(require 'mh-e)
+(mh-require-cl)
+
+(autoload 'message-fetch-field "message")
+
+(defvar mh-show-xface-function
+  (cond ((and mh-xemacs-flag (locate-library "x-face") (not (featurep 'xface)))
+         (load "x-face" t t)
+         #'mh-face-display-function)
+        ((>= emacs-major-version 21)
+         #'mh-face-display-function)
+        (t #'ignore))
+  "Determine at run time what function should be called to display X-Face.")
+
+(defvar mh-uncompface-executable
+  (and (fboundp 'executable-find) (executable-find "uncompface")))
+
+
+
+;;; X-Face Display
+
+;;;###mh-autoload
+(defun mh-show-xface ()
+  "Display X-Face."
+  (when (and window-system mh-show-use-xface-flag
+             (or mh-decode-mime-flag mh-mhl-format-file
+                 mh-clean-message-header-flag))
+    (funcall mh-show-xface-function)))
+
+;; Shush compiler.
+(eval-when-compile
+  (mh-do-in-xemacs (defvar default-enable-multibyte-characters)))
+
+(defun mh-face-display-function ()
+  "Display a Face, X-Face, or X-Image-URL header field.
+If more than one of these are present, then the first one found
+in this order is used."
+  (save-restriction
+    (goto-char (point-min))
+    (re-search-forward "\n\n" (point-max) t)
+    (narrow-to-region (point-min) (point))
+    (let* ((case-fold-search t)
+           (default-enable-multibyte-characters nil)
+           (face (message-fetch-field "face" t))
+           (x-face (message-fetch-field "x-face" t))
+           (url (message-fetch-field "x-image-url" t))
+           raw type)
+      (cond (face (setq raw (mh-face-to-png face)
+                        type 'png))
+            (x-face (setq raw (mh-uncompface x-face)
+                          type 'pbm))
+            (url (setq type 'url))
+            (t (multiple-value-setq (type raw) (mh-picon-get-image))))
+      (when type
+        (goto-char (point-min))
+        (when (re-search-forward "^from:" (point-max) t)
+          ;; GNU Emacs
+          (mh-do-in-gnu-emacs
+            (if (eq type 'url)
+                (mh-x-image-url-display url)
+              (mh-funcall-if-exists
+               insert-image (create-image
+                             raw type t
+                             :foreground
+                             (mh-face-foreground 'mh-show-xface nil t)
+                             :background
+                             (mh-face-background 'mh-show-xface nil t))
+               " ")))
+          ;; XEmacs
+          (mh-do-in-xemacs
+            (cond
+             ((eq type 'url)
+              (mh-x-image-url-display url))
+             ((eq type 'png)
+              (when (featurep 'png)
+                (set-extent-begin-glyph
+                 (make-extent (point) (point))
+                 (make-glyph (vector 'png ':data (mh-face-to-png face))))))
+             ;; Try internal xface support if available...
+             ((and (eq type 'pbm) (featurep 'xface))
+              (set-glyph-face
+               (set-extent-begin-glyph
+                (make-extent (point) (point))
+                (make-glyph (vector 'xface ':data (concat "X-Face: " x-face))))
+               'mh-show-xface))
+             ;; Otherwise try external support with x-face...
+             ((and (eq type 'pbm)
+                   (fboundp 'x-face-xmas-wl-display-x-face)
+                   (fboundp 'executable-find) (executable-find "uncompface"))
+              (mh-funcall-if-exists x-face-xmas-wl-display-x-face))
+             ;; Picon display
+             ((and raw (member type '(xpm xbm gif)))
+              (when (featurep type)
+                (set-extent-begin-glyph
+                 (make-extent (point) (point))
+                 (make-glyph (vector type ':data raw))))))
+            (when raw (insert " "))))))))
+
+(defun mh-face-to-png (data)
+  "Convert base64 encoded DATA to png image."
+  (with-temp-buffer
+    (insert data)
+    (ignore-errors (base64-decode-region (point-min) (point-max)))
+    (buffer-string)))
+
+(defun mh-uncompface (data)
+  "Run DATA through `uncompface' to generate bitmap."
+  (with-temp-buffer
+    (insert data)
+    (when (and mh-uncompface-executable
+               (equal (call-process-region (point-min) (point-max)
+                                           mh-uncompface-executable t '(t nil))
+                      0))
+      (mh-icontopbm)
+      (buffer-string))))
+
+(defun mh-icontopbm ()
+  "Elisp substitute for `icontopbm'."
+  (goto-char (point-min))
+  (let ((end (point-max)))
+    (while (re-search-forward "0x\\(..\\)\\(..\\)," nil t)
+      (save-excursion
+        (goto-char (point-max))
+        (insert (string-to-number (match-string 1) 16))
+        (insert (string-to-number (match-string 2) 16))))
+    (delete-region (point-min) end)
+    (goto-char (point-min))
+    (insert "P4\n48 48\n")))
+
+
+
+;;; Picon Display
+
+;; XXX: This should be customizable. As a side-effect of setting this
+;;   variable, arrange to reset mh-picon-existing-directory-list to 'unset.
+(defvar mh-picon-directory-list
+  '("~/.picons" "~/.picons/users" "~/.picons/usenix" "~/.picons/news"
+    "~/.picons/domains" "~/.picons/misc"
+    "/usr/share/picons/" "/usr/share/picons/users" "/usr/share/picons/usenix"
+    "/usr/share/picons/news" "/usr/share/picons/domains"
+    "/usr/share/picons/misc")
+  "List of directories where picons reside.
+The directories are searched for in the order they appear in the list.")
+
+(defvar mh-picon-existing-directory-list 'unset
+  "List of directories to search in.")
+
+(defvar mh-picon-cache (make-hash-table :test #'equal))
+
+(defvar mh-picon-image-types
+  (loop for type in '(xpm xbm gif)
+        when (or (mh-do-in-gnu-emacs
+                   (ignore-errors
+                     (mh-funcall-if-exists image-type-available-p type)))
+                 (mh-do-in-xemacs (featurep type)))
+        collect type))
+
+(autoload 'message-tokenize-header "sendmail")
+
+(defun* mh-picon-get-image ()
+  "Find the best possible match and return contents."
+  (mh-picon-set-directory-list)
+  (save-restriction
+    (let* ((from-field (ignore-errors (car (message-tokenize-header
+                                            (mh-get-header-field "from:")))))
+           (from (car (ignore-errors
+                        (mh-funcall-if-exists ietf-drums-parse-address
+                                              from-field))))
+           (host (and from
+                      (string-match "\\([^+]*\\)\\(+.*\\)?@\\(.*\\)" from)
+                      (downcase (match-string 3 from))))
+           (user (and host (downcase (match-string 1 from))))
+           (canonical-address (format "%s@%s" user host))
+           (cached-value (gethash canonical-address mh-picon-cache))
+           (host-list (and host (delete "" (split-string host "\\."))))
+           (match nil))
+      (cond (cached-value (return-from mh-picon-get-image cached-value))
+            ((not host-list) (return-from mh-picon-get-image nil)))
+      (setq match
+            (block 'loop
+              ;; u@h search
+              (loop for dir in mh-picon-existing-directory-list
+                    do (loop for type in mh-picon-image-types
+                             ;; [path]user@host
+                             for file1 = (format "%s/%s.%s"
+                                                 dir canonical-address type)
+                             when (file-exists-p file1)
+                             do (return-from 'loop file1)
+                             ;; [path]user
+                             for file2 = (format "%s/%s.%s" dir user type)
+                             when (file-exists-p file2)
+                             do (return-from 'loop file2)
+                             ;; [path]host
+                             for file3 = (format "%s/%s.%s" dir host type)
+                             when (file-exists-p file3)
+                             do (return-from 'loop file3)))
+              ;; facedb search
+              ;; Search order for user@foo.net:
+              ;;   [path]net/foo/user
+              ;;   [path]net/foo/user/face
+              ;;   [path]net/user
+              ;;   [path]net/user/face
+              ;;   [path]net/foo/unknown
+              ;;   [path]net/foo/unknown/face
+              ;;   [path]net/unknown
+              ;;   [path]net/unknown/face
+              (loop for u in (list user "unknown")
+                    do (loop for dir in mh-picon-existing-directory-list
+                             do (loop for x on host-list by #'cdr
+                                      for y = (mh-picon-generate-path x u dir)
+                                      do (loop for type in mh-picon-image-types
+                                               for z1 = (format "%s.%s" y type)
+                                               when (file-exists-p z1)
+                                               do (return-from 'loop z1)
+                                               for z2 = (format "%s/face.%s"
+                                                                y type)
+                                               when (file-exists-p z2)
+                                               do (return-from 'loop z2)))))))
+      (setf (gethash canonical-address mh-picon-cache)
+            (mh-picon-file-contents match)))))
+
+(defun mh-picon-set-directory-list ()
+  "Update `mh-picon-existing-directory-list' if needed."
+  (when (eq mh-picon-existing-directory-list 'unset)
+    (setq mh-picon-existing-directory-list
+          (loop for x in mh-picon-directory-list
+                when (file-directory-p x) collect x))))
+
+(defun mh-picon-generate-path (host-list user directory)
+  "Generate the image file path.
+HOST-LIST is the parsed host address of the email address, USER
+the username and DIRECTORY is the directory relative to which the
+path is generated."
+  (loop with acc = ""
+        for elem in host-list
+        do (setq acc (format "%s/%s" elem acc))
+        finally return (format "%s/%s%s" directory acc user)))
+
+(defun mh-picon-file-contents (file)
+  "Return details about FILE.
+A list of consisting of a symbol for the type of the file and the
+file contents as a string is returned. If FILE is nil, then both
+elements of the list are nil."
+  (if (stringp file)
+      (with-temp-buffer
+        (let ((type (and (string-match ".*\\.\\(...\\)$" file)
+                         (intern (match-string 1 file)))))
+          (insert-file-contents-literally file)
+          (values type (buffer-string))))
+    (values nil nil)))
+
+
+
+;;; X-Image-URL Display
+
+(defvar mh-x-image-scaling-function
+  (cond ((executable-find "convert")
+         'mh-x-image-scale-with-convert)
+        ((and (executable-find "anytopnm") (executable-find "pnmscale")
+              (executable-find "pnmtopng"))
+         'mh-x-image-scale-with-pnm)
+        (t 'ignore))
+  "Function to use to scale image to proper size.")
+
+(defun mh-x-image-scale-with-pnm (input output)
+  "Scale image in INPUT file and write to OUTPUT file using pnm tools."
+  (let ((res (shell-command-to-string
+              (format "anytopnm < %s | pnmscale -xysize 96 48 | pnmtopng > %s"
+                      input output))))
+    (unless (equal res "")
+      (delete-file output))))
+
+(defun mh-x-image-scale-with-convert (input output)
+  "Scale image in INPUT file and write to OUTPUT file using ImageMagick."
+  (call-process "convert" nil nil nil "-geometry" "96x48" input output))
+
+(defvar mh-wget-executable nil)
+(defvar mh-wget-choice
+  (or (and (setq mh-wget-executable (executable-find "wget")) 'wget)
+      (and (setq mh-wget-executable (executable-find "fetch")) 'fetch)
+      (and (setq mh-wget-executable (executable-find "curl")) 'curl)))
+(defvar mh-wget-option
+  (cdr (assoc mh-wget-choice '((curl . "-o") (fetch . "-o") (wget . "-O")))))
+(defvar mh-x-image-temp-file nil)
+(defvar mh-x-image-url nil)
+(defvar mh-x-image-marker nil)
+(defvar mh-x-image-url-cache-file nil)
+
+(defun mh-x-image-url-display (url)
+  "Display image from location URL.
+If the URL isn't present in the cache then it is fetched with wget."
+  (let* ((cache-filename (mh-x-image-url-cache-canonicalize url))
+         (state (mh-x-image-get-download-state cache-filename))
+         (marker (set-marker (make-marker) (point))))
+    (set (make-local-variable 'mh-x-image-marker) marker)
+    (cond ((not (mh-x-image-url-sane-p url)))
+          ((eq state 'ok)
+           (mh-x-image-display cache-filename marker))
+          ((or (not mh-wget-executable)
+               (eq mh-x-image-scaling-function 'ignore)))
+          ((eq state 'never))
+          ((not mh-fetch-x-image-url)
+           (set-marker marker nil))
+          ((eq state 'try-again)
+           (mh-x-image-set-download-state cache-filename nil)
+           (mh-x-image-url-fetch-image url cache-filename marker
+                                       'mh-x-image-scale-and-display))
+          ((and (eq mh-fetch-x-image-url 'ask)
+                (not (y-or-n-p (format "Fetch %s? " url))))
+           (mh-x-image-set-download-state cache-filename 'never))
+          ((eq state nil)
+           (mh-x-image-url-fetch-image url cache-filename marker
+                                       'mh-x-image-scale-and-display)))))
+
+(defvar mh-x-image-cache-directory nil
+  "Directory where X-Image-URL images are cached.")
+
+;;;###mh-autoload
+(defun mh-set-x-image-cache-directory (directory)
+  "Set the DIRECTORY where X-Image-URL images are cached.
+This is only done if `mh-x-image-cache-directory' is nil."
+  ;; XXX This is the code that used to be in find-user-path. Is there
+  ;; a good reason why the variable is set conditionally? Do we expect
+  ;; the user to have set this variable directly?
+  (unless mh-x-image-cache-directory
+    (setq mh-x-image-cache-directory directory)))
+
+(defun mh-x-image-url-cache-canonicalize (url)
+  "Canonicalize URL.
+Replace the ?/ character with a ?! character and append .png.
+Also replaces special characters with `mh-url-hexify-string'
+since not all characters, such as :, are legal within Windows
+filenames. See URL
+`http://msdn.microsoft.com/library/default.asp?url=/library/en-us/fileio/fs/naming_a_file.asp'."
+  (format "%s/%s.png" mh-x-image-cache-directory
+          (mh-url-hexify-string
+           (with-temp-buffer
+             (insert url)
+             (mh-replace-string "/" "!")
+             (buffer-string)))))
+
+(defun mh-x-image-get-download-state (file)
+  "Check the state of FILE by following any symbolic links."
+  (unless (file-exists-p mh-x-image-cache-directory)
+    (call-process "mkdir" nil nil nil mh-x-image-cache-directory))
+  (cond ((file-symlink-p file)
+         (intern (file-name-nondirectory (file-chase-links file))))
+        ((not (file-exists-p file)) nil)
+        (t 'ok)))
+
+(defun mh-x-image-set-download-state (file data)
+  "Setup a symbolic link from FILE to DATA."
+  (if data
+      (make-symbolic-link (symbol-name data) file t)
+    (delete-file file)))
+
+(defun mh-x-image-url-sane-p (url)
+  "Check if URL is something sensible."
+  (let ((len (length url)))
+    (cond ((< len 5) nil)
+          ((not (equal (substring url 0 5) "http:")) nil)
+          ((> len 100) nil)
+          (t t))))
+
+(defun mh-x-image-display (image marker)
+  "Display IMAGE at MARKER."
+  (save-excursion
+    (set-buffer (marker-buffer marker))
+    (let ((buffer-read-only nil)
+          (default-enable-multibyte-characters nil)
+          (buffer-modified-flag (buffer-modified-p)))
+      (unwind-protect
+          (when (and (file-readable-p image) (not (file-symlink-p image))
+                     (eq marker mh-x-image-marker))
+            (goto-char marker)
+            (mh-do-in-gnu-emacs
+              (mh-funcall-if-exists insert-image (create-image image 'png)))
+            (mh-do-in-xemacs
+              (when (featurep 'png)
+                (set-extent-begin-glyph
+                 (make-extent (point) (point))
+                 (make-glyph
+                  (vector 'png ':data (with-temp-buffer
+                                        (insert-file-contents-literally image)
+                                        (buffer-string))))))))
+        (set-buffer-modified-p buffer-modified-flag)))))
+
+(defun mh-x-image-url-fetch-image (url cache-file marker sentinel)
+  "Fetch and display the image specified by URL.
+After the image is fetched, it is stored in CACHE-FILE. It will
+be displayed in a buffer and position specified by MARKER. The
+actual display is carried out by the SENTINEL function."
+  (if mh-wget-executable
+      (let ((buffer (get-buffer-create (generate-new-buffer-name
+                                        mh-temp-fetch-buffer)))
+            (filename (or (mh-funcall-if-exists make-temp-file "mhe-fetch")
+                          (expand-file-name (make-temp-name "~/mhe-fetch")))))
+        (save-excursion
+          (set-buffer buffer)
+          (set (make-local-variable 'mh-x-image-url-cache-file) cache-file)
+          (set (make-local-variable 'mh-x-image-marker) marker)
+          (set (make-local-variable 'mh-x-image-temp-file) filename))
+        (set-process-sentinel
+         (start-process "*mh-x-image-url-fetch*" buffer
+                        mh-wget-executable mh-wget-option filename url)
+         sentinel))
+    ;; Temporary failure
+    (mh-x-image-set-download-state cache-file 'try-again)))
+
+(defun mh-x-image-scale-and-display (process change)
+  "When the wget PROCESS terminates scale and display image.
+The argument CHANGE is ignored."
+  (when (eq (process-status process) 'exit)
+    (let (marker temp-file cache-filename wget-buffer)
+      (save-excursion
+        (set-buffer (setq wget-buffer (process-buffer process)))
+        (setq marker mh-x-image-marker
+              cache-filename mh-x-image-url-cache-file
+              temp-file mh-x-image-temp-file))
+      (cond
+       ;; Check if we have `convert'
+       ((eq mh-x-image-scaling-function 'ignore)
+        (message "The \"convert\" program is needed to display X-Image-URL")
+        (mh-x-image-set-download-state cache-filename 'try-again))
+       ;; Scale fetched image
+       ((and (funcall mh-x-image-scaling-function temp-file cache-filename)
+             nil))
+       ;; Attempt to display image if we have it
+       ((file-exists-p cache-filename)
+        (mh-x-image-display cache-filename marker))
+       ;; We didn't find the image. Should we try to display it the next time?
+       (t (mh-x-image-set-download-state cache-filename 'try-again)))
+      (ignore-errors
+        (set-marker marker nil)
+        (delete-process process)
+        (kill-buffer wget-buffer)
+        (delete-file temp-file)))))
+
+(provide 'mh-xface)
+
+;; Local Variables:
+;; indent-tabs-mode: nil
+;; sentence-end-double-space: nil
+;; End:
+
+;; arch-tag: a79dd33f-d0e5-4b19-a53a-be690f90229a
+;;; mh-xface.el ends here
--- a/lisp/net/tramp-vc.el	Thu Jan 26 02:23:05 2006 +0000
+++ b/lisp/net/tramp-vc.el	Wed Feb 01 10:07:17 2006 +0000
@@ -436,26 +436,30 @@
 	      (t	   (error "tramp-handle-vc-user-login-name cannot cope!")))))))
 
 
-(defadvice vc-user-login-name
-  (around tramp-vc-user-login-name activate)
-  "Support for files on remote machines accessed by TRAMP."
-  ;; We rely on the fact that `file' is bound when this is called.
-  ;; This appears to be the case everywhere in vc.el and vc-hooks.el
-  ;; as of Emacs 20.5.
-  ;;
-  ;; CCC TODO there should be a real solution!  Talk to Andre Spiegel
-  ;; about this.
-  (let ((file (when (boundp 'file)
-                (symbol-value 'file))))    ;pacify byte-compiler
-    (or (and (stringp file)
-             (tramp-tramp-file-p file)	; tramp file
-             (setq ad-return-value
-		   (save-match-data
-		     (tramp-handle-vc-user-login-name uid)))) ; get the owner name
-        ad-do-it)))                     ; else call the original
+;; The following defadvice is no longer necessary after changes in VC
+;; on 2006-01-25, Andre.
 
-(add-hook 'tramp-unload-hook
-	  '(lambda () (ad-unadvise 'vc-user-login-name)))
+(unless (fboundp 'process-file)
+  (defadvice vc-user-login-name
+    (around tramp-vc-user-login-name activate)
+    "Support for files on remote machines accessed by TRAMP."
+    ;; We rely on the fact that `file' is bound when this is called.
+    ;; This appears to be the case everywhere in vc.el and vc-hooks.el
+    ;; as of Emacs 20.5.
+    ;;
+    ;; With Emacs 22, the definition of `vc-user-login-name' has been
+    ;; changed.  It doesn't need to be adviced any longer.
+    (let ((file (when (boundp 'file)
+		  (symbol-value 'file))))    ;pacify byte-compiler
+      (or (and (stringp file)
+	       (tramp-tramp-file-p file)	; tramp file
+	       (setq ad-return-value
+		     (save-match-data
+		       (tramp-handle-vc-user-login-name uid)))) ; get the owner name
+	  ad-do-it)))                     ; else call the original
+
+  (add-hook 'tramp-unload-hook
+	    '(lambda () (ad-unadvise 'vc-user-login-name))))
 
 
 ;; Determine the name of the user owning a file.
--- a/lisp/replace.el	Thu Jan 26 02:23:05 2006 +0000
+++ b/lisp/replace.el	Wed Feb 01 10:07:17 2006 +0000
@@ -973,7 +973,8 @@
 (defun multi-occur (bufs regexp &optional nlines)
   "Show all lines in buffers BUFS containing a match for REGEXP.
 This function acts on multiple buffers; otherwise, it is exactly like
-`occur'."
+`occur'.  When you invoke this command interactively, you must specify
+the buffer names that you want, one by one."
   (interactive
    (cons
     (let* ((bufs (list (read-buffer "First buffer to search: "
@@ -993,15 +994,19 @@
     (occur-read-primary-args)))
   (occur-1 regexp nlines bufs))
 
-(defun multi-occur-by-filename-regexp (bufregexp regexp &optional nlines)
-  "Show all lines matching REGEXP in buffers named by BUFREGEXP.
+(defun multi-occur-in-matching-buffers (bufregexp regexp &optional allbufs)
+  "Show all lines matching REGEXP in buffers specified by BUFREGEXP.
+Normally BUFREGEXP matches against each buffer's visited file name,
+but if you specify a prefix argument, it matches against the buffer name.
 See also `multi-occur'."
   (interactive
    (cons
     (let* ((default (car regexp-history))
 	   (input
 	    (read-from-minibuffer
-	     "List lines in buffers whose filename matches regexp: "
+	     (if allbufs
+		 "List lines in buffers whose names match regexp: "
+	       "List lines in buffers whose filenames match regexp: ")
 	     nil
 	     nil
 	     nil
@@ -1014,9 +1019,12 @@
     (occur-1 regexp nlines
 	     (delq nil
 		   (mapcar (lambda (buf)
-			     (when (and (buffer-file-name buf)
-					(string-match bufregexp
-						      (buffer-file-name buf)))
+			     (when (if allbufs
+				       (string-match bufregexp
+						     (buffer-name buf))
+				     (and (buffer-file-name buf)
+					  (string-match bufregexp
+							(buffer-file-name buf))))
 			       buf))
 			   (buffer-list))))))
 
--- a/lisp/simple.el	Thu Jan 26 02:23:05 2006 +0000
+++ b/lisp/simple.el	Wed Feb 01 10:07:17 2006 +0000
@@ -3733,19 +3733,22 @@
 To ignore intangibility, bind `inhibit-point-motion-hooks' to t."
   (interactive "p")
   (or arg (setq arg 1))
-  (if (/= arg 1)
-      (line-move (1- arg) t))
   
-  ;; Move to beginning-of-line, ignoring fields and invisibles.
-  (skip-chars-backward "^\n")
-  (while (and (not (bobp)) (line-move-invisible-p (1- (point))))
-    (goto-char (previous-char-property-change (1- (point))))
-    (skip-chars-backward "^\n"))
-
   (let ((orig (point)))
-    (vertical-motion 0)
-    (if (/= orig (point))
-	(goto-char (constrain-to-field (point) orig (/= arg 1) t nil)))))
+
+    ;; Move by lines, if ARG is not 1 (the default).
+    (if (/= arg 1)
+	(line-move (1- arg) t))
+
+    ;; Move to beginning-of-line, ignoring fields and invisibles.
+    (skip-chars-backward "^\n")
+    (while (and (not (bobp)) (line-move-invisible-p (1- (point))))
+      (goto-char (previous-char-property-change (1- (point))))
+      (skip-chars-backward "^\n"))
+
+    ;; Take care of fields.
+    (goto-char (constrain-to-field (point) orig
+				   (/= arg 1) t nil))))
 
 
 ;;; Many people have said they rarely use this feature, and often type
@@ -5286,11 +5289,8 @@
     buffer))
 
 
-(defun clone-indirect-buffer-other-window (buffer &optional norecord)
-  "Create an indirect buffer that is a twin copy of BUFFER.
-Select the new buffer in another window.
-Optional second arg NORECORD non-nil means do not put this buffer at
-the front of the list of recently selected ones."
+(defun clone-indirect-buffer-other-window (newname display-flag &optional norecord)
+  "Like `clone-indirect-buffer' but display in another window."
   (interactive
    (progn
      (if (get major-mode 'no-clone-indirect)
@@ -5299,8 +5299,7 @@
 	       (read-buffer "Name of indirect buffer: " (current-buffer)))
 	   t)))
   (let ((pop-up-windows t))
-    (set-buffer buffer)
-    (clone-indirect-buffer nil t norecord)))
+    (clone-indirect-buffer newname display-flag norecord)))
 
 
 ;;; Handling of Backspace and Delete keys.
--- a/lisp/subr.el	Thu Jan 26 02:23:05 2006 +0000
+++ b/lisp/subr.el	Wed Feb 01 10:07:17 2006 +0000
@@ -1831,6 +1831,12 @@
 This variable is meaningful on MS-DOG and Windows NT.
 On those systems, it is automatically local in every buffer.
 On other systems, this variable is normally always nil.")
+
+;; The `assert' macro from the cl package signals
+;; `cl-assertion-failed' at runtime so always define it.
+(put 'cl-assertion-failed 'error-conditions '(error))
+(put 'cl-assertion-failed 'error-message "Assertion failed")
+
 
 ;;;; Misc. useful functions.
 
@@ -2274,7 +2280,9 @@
 arguments.  FUN must return the completion table that will be stored in VAR.
 If completion is requested in the minibuffer, FUN will be called in the buffer
 from which the minibuffer was entered.  The return value of
-`lazy-completion-table' must be used to initialize the value of VAR."
+`lazy-completion-table' must be used to initialize the value of VAR.
+
+You should give VAR a non-nil `risky-local-variable' property."
   (declare (debug (symbol lambda-expr)))
   (let ((str (make-symbol "string")))
     `(dynamic-completion-table
--- a/lisp/textmodes/flyspell.el	Thu Jan 26 02:23:05 2006 +0000
+++ b/lisp/textmodes/flyspell.el	Wed Feb 01 10:07:17 2006 +0000
@@ -427,7 +427,7 @@
 (defface flyspell-incorrect
   '((((class color)) (:foreground "OrangeRed" :bold t :underline t))
     (t (:bold t)))
-  "Face used for marking a misspelled word in Flyspell."
+  "Face used to display a misspelled word in Flyspell."
   :group 'flyspell)
 ;; backward-compatibility alias
 (put 'flyspell-incorrect-face 'face-alias 'flyspell-incorrect)
@@ -435,7 +435,7 @@
 (defface flyspell-duplicate
   '((((class color)) (:foreground "Gold3" :bold t :underline t))
     (t (:bold t)))
-  "Face used for marking a misspelled word that appears twice in the buffer.
+  "Face used to display subsequent occurrences of a misspelled word.
 See also `flyspell-duplicate-distance'."
   :group 'flyspell)
 ;; backward-compatibility alias
--- a/lisp/textmodes/ispell.el	Thu Jan 26 02:23:05 2006 +0000
+++ b/lisp/textmodes/ispell.el	Wed Feb 01 10:07:17 2006 +0000
@@ -913,7 +913,9 @@
     (ispell-aspell-add-aliases)
     ;; Add a default entry
     (let* ((english-dict (assoc "en" ispell-dictionary-alist))
-	   (default-dict (cons nil (cdr english-dict))))
+	   (default-dict
+	     (cons nil (or (cdr english-dict)
+			   (cdr (car ispell-dictionary-alist-1))))))
       (push default-dict ispell-dictionary-alist))
     (setq ispell-have-aspell-dictionaries t)))
 
--- a/lisp/textmodes/org.el	Thu Jan 26 02:23:05 2006 +0000
+++ b/lisp/textmodes/org.el	Wed Feb 01 10:07:17 2006 +0000
@@ -130,7 +130,7 @@
   "Are we using the new outline mode?")
 
 (defgroup org nil
-  "Outline-based notes management and organizer "
+  "Outline-based notes management and organizer."
   :tag "Org"
   :group 'outlines
   :group 'hypermedia
@@ -307,7 +307,7 @@
   :type 'string)
 
 (defcustom org-closed-string "CLOSED:"
-  "String ued as the prefix for timestamps logging closing a TODO entry."
+  "String used as the prefix for timestamps logging closing a TODO entry."
   :group 'org-keywords
   :type 'string)
 
@@ -324,13 +324,13 @@
 Quoting applies only to the text in the entry following the headline, and does
 not extend beyond the next headline, even if that is lower level.
 An entry can be toggled between QUOTE and normal with
-\\[org-toggle-fixed-width-section]"
+\\[org-toggle-fixed-width-section]."
   :group 'org-keywords
   :type 'string)
 
 (defcustom org-after-todo-state-change-hook nil
   "Hook which is run after the state of a TODO item was changed.
-The new state (a string with a todo keyword, or nil) is available in the
+The new state (a string with a TODO keyword, or nil) is available in the
 Lisp variable `state'."
   :group 'org-keywords
   :type 'hook)
@@ -526,8 +526,8 @@
 (defcustom org-calendar-to-agenda-key [?c]
   "The key to be installed in `calendar-mode-map' for switching to the agenda.
 The command `org-calendar-goto-agenda' will be bound to this key.  The
-default is the character `c' because then`c' can be used to switch back and
-force between agenda and calendar."
+default is the character `c' because then `c' can be used to switch back and
+forth between agenda and calendar."
   :group 'org-agenda
   :type 'sexp)
 
@@ -535,7 +535,7 @@
   "Sorting structure for the agenda items of a single day.
 This is a list of symbols which will be used in sequence to determine
 if an entry should be listed before another entry.  The following
-symbols are recognized.
+symbols are recognized:
 
 time-up         Put entries with time-of-day indications first, early first
 time-down       Put entries with time-of-day indications first, late first
@@ -630,9 +630,9 @@
 (defcustom org-agenda-use-time-grid t
   "Non-nil means, show a time grid in the agenda schedule.
 A time grid is a set of lines for specific times (like every two hours between
-8:00 and 20:00.  The items scheduled for a day at specific times are
+8:00 and 20:00).  The items scheduled for a day at specific times are
 sorted in between these lines.
-For deails about when the grid will be shown, and what it will look like, see
+For details about when the grid will be shown, and what it will look like, see
 the variable `org-agenda-time-grid'."
   :group 'org-agenda
   :type 'boolean)
@@ -760,7 +760,7 @@
 When doing an `org-occur' it is useful to show the headline which
 follows the match, even if they do not match the regexp.  This makes it
 easier to edit directly inside the sparse tree.  However, if you use
-org-occur mainly as an overview, the following headlines are
+`org-occur' mainly as an overview, the following headlines are
 unnecessary clutter."
   :group 'org-structure
   :type 'boolean)
@@ -775,7 +775,7 @@
 (defcustom org-level-color-stars-only nil
   "Non-nil means fontify only the stars in each headline.
 When nil, the entire headline is fontified.
-After changin this, requires restart of Emacs to become effective."
+Changing it requires a restart of Emacs to become effective."
   :group 'org-structure
   :type 'boolean)
 
@@ -871,7 +871,7 @@
 
 (defcustom org-tags-column 48
   "The column to which tags should be indented in a headline.
-If this number is positive, it specified the column.  If it is negative,
+If this number is positive, it specifies the column.  If it is negative,
 it means that the tags should be flushright to that column.  For example,
 -79 works well for a normal 80 character screen."
   :group 'org-tags
@@ -887,7 +887,7 @@
 
 (defcustom org-use-tag-inheritance t
   "Non-nil means, tags in levels apply also for sublevels.
-When nil, only the tags directly give in a specific line apply there.
+When nil, only the tags directly given in a specific line apply there.
 If you turn off this option, you very likely want to turn on the
 companion option `org-tags-match-list-sublevels'."
   :group 'org-tags
@@ -948,7 +948,7 @@
 When nil, it becomes possible to put several links into a line.
 Note that in tables, a link never extends accross fields, so in a table
 it is always possible to put several links into a line.
-Changing this varable requires a re-launch of Emacs of become effective."
+Changing this variable requires a restart of Emacs to become effective."
   :group 'org-link
   :type 'boolean)
 
@@ -1014,7 +1014,7 @@
 		 (const find-file-other-frame)))))
 
 (defcustom org-usenet-links-prefer-google nil
-  "Non-nil means, `org-store-link' will create web links to google groups.
+  "Non-nil means, `org-store-link' will create web links to Google groups.
 When nil, Gnus will be used for such links.
 Using a prefix arg to the command \\[org-store-link] (`org-store-link')
 negates this setting for the duration of the command."
@@ -1035,7 +1035,7 @@
 
 (defconst org-file-apps-defaults-gnu
   '((t . mailcap))
-  "Default file applications on a UNIX/LINUX system.
+  "Default file applications on a UNIX or GNU/Linux system.
 See `org-file-apps'.")
 
 (defconst org-file-apps-defaults-macosx
@@ -1131,7 +1131,7 @@
 When nil, such lines will be treated like ordinary lines.
 
 When equal to the symbol `optimized', the table editor will be optimized to
-do the following
+do the following:
 - Use automatic overwrite mode in front of whitespace in table fields.
   This make the structure of the table stay in tact as long as the edited
   field does not exceed the column width.
@@ -1271,7 +1271,7 @@
     calc-display-working-message t
     )
   "List with Calc mode settings for use in calc-eval for table formulas.
-The list must contain alternating symbols (calc modes variables and values.
+The list must contain alternating symbols (Calc modes variables and values).
 Don't remove any of the default settings, just change the values.  Org-mode
 relies on the variables to be present in the list."
   :group 'org-table-calculation
@@ -1320,7 +1320,7 @@
   :type 'boolean)
 
 (defcustom org-table-allow-automatic-line-recalculation t
-  "Non-nil means, lines makred with |#| or |*| will be recomputed automatically.
+  "Non-nil means, lines marked with |#| or |*| will be recomputed automatically.
 Automatically means, when TAB or RET or C-c C-c are pressed in the line."
   :group 'org-table-calculation
   :type 'boolean)
@@ -1357,7 +1357,7 @@
   :group 'org-export
   :type 'string)
 
-(defcustom org-export-html-style 
+(defcustom org-export-html-style
 "<style type=\"text/css\">
   html {
 	font-family: Times, serif;
@@ -1381,13 +1381,13 @@
   "The default style specification for exported HTML files.
 Since there are different ways of setting style information, this variable
 needs to contain the full HTML structure to provide a style, including the
-surrounding HTML tags.  The style specifications should include definiitons
+surrounding HTML tags.  The style specifications should include definitions
 for new classes todo, done, title, and deadline.  For example, legal values
-would be.
+would be:
 
    <style type=\"text/css\">
-       p {font-weight: normal; color: gray; }
-       h1 {color: black; }
+       p { font-weight: normal; color: gray; }
+       h1 { color: black; }
       .title { text-align: center; }
       .todo, .deadline { color: red; }
       .done { color: green; }
@@ -1483,7 +1483,7 @@
 (defcustom org-export-with-fixed-width t
   "Non-nil means, lines starting with \":\" will be in fixed width font.
 This can be used to have pre-formatted text, fragments of code etc.  For
-example
+example:
   : ;; Some Lisp examples
   : (while (defc cnt)
   :   (ding))
@@ -1553,7 +1553,7 @@
 needed.  For example, the following things will be parsed as single
 sub- or superscripts.
 
- 10^24   or   10^tau     several digits will be considered 1 item
+ 10^24   or   10^tau     several digits will be considered 1 item.
  10^-12  or   10^-tau    a leading sign with digits or a word
  x^2-y^3                 will be read as x^2 - y^3, because items are
 			 terminated by almost any nonword/nondigit char.
@@ -1695,7 +1695,7 @@
     (((class color) (background light)) (:foreground "RosyBrown"))
     (((class color) (background dark)) (:foreground "LightSalmon"))
     (t (:italic t)))
-  "Face used for level 8 headlines."
+  "Face used for special keywords."
   :group 'org-faces)
 
 (defface org-warning ;; font-lock-warning-face
@@ -1757,7 +1757,7 @@
     (((class color) (background light)) (:foreground "Firebrick"))
     (((class color) (background dark)) (:foreground "chocolate1"))
     (t (:bold t :italic t)))
-  "Face for items scheduled previously, and not yet done."
+  "Face for formulas."
   :group 'org-faces)
 
 (defface org-link
@@ -1789,7 +1789,7 @@
     (((class color) (background light)) (:foreground "DarkGoldenrod"))
     (((class color) (background dark)) (:foreground "LightGoldenrod"))
     (t (:bold t :italic t)))
-  "Face used for level 2 headlines."
+  "Face used for time grids."
   :group 'org-faces)
 
 (defvar org-level-faces
@@ -1926,7 +1926,8 @@
   (defvar org-selected-point)
   (defvar calendar-mode-map)
   (defvar remember-save-after-remembering)
-  (defvar remember-data-file))
+  (defvar remember-data-file)
+  (defvar last-arg))
 
 
 ;;; Define the mode
@@ -1941,7 +1942,7 @@
 ;; We use a before-change function to check if a table might need
 ;; an update.
 (defvar org-table-may-need-update t
-  "Indicates of a table might need an update.
+  "Indicates that a table might need an update.
 This variable is set by `org-before-change-function'. `org-table-align'
 sets it back to nil.")
 (defvar org-mode-hook nil)
@@ -1952,7 +1953,7 @@
 ;;;###autoload
 (define-derived-mode org-mode outline-mode "Org"
   "Outline-based notes management and organizer, alias
-\"Carstens outline-mode for keeping track of everything.\"
+\"Carsten's outline-mode for keeping track of everything.\"
 
 Org-mode develops organizational tasks around a NOTES file which
 contains information about projects as plain text.  Org-mode is
@@ -2216,9 +2217,9 @@
 - When point is at the beginning of a headline, rotate the subtree started
   by this line through 3 different states (local cycling)
   1. FOLDED:   Only the main headline is shown.
-  2. CHILDREN: The main headline and the direct children are shown.  From
-	       this state, you can move to one of the children and
-	       zoom in further.
+  2. CHILDREN: The main headline and the direct children are shown.
+               From this state, you can move to one of the children
+               and zoom in further.
   3. SUBTREE:  Show the entire subtree, including body text.
 
 - When there is a numeric prefix, go up to a heading with level ARG, do
@@ -2475,14 +2476,14 @@
 
 ;;  FIXME:  It may not be a good idea to temper with the prefix argument...
 (defun org-goto-ret (&optional arg)
-  "Finish org-goto by going to the new location."
+  "Finish `org-goto' by going to the new location."
   (interactive "P")
   (setq org-selected-point (point)
 	current-prefix-arg arg)
   (throw 'exit nil))
 
 (defun org-goto-left ()
-  "Finish org-goto by going to the new location."
+  "Finish `org-goto' by going to the new location."
   (interactive)
   (if (org-on-heading-p)
       (progn
@@ -2493,7 +2494,7 @@
     (error "Not on a heading")))
 
 (defun org-goto-right ()
-  "Finish org-goto by going to the new location."
+  "Finish `org-goto' by going to the new location."
   (interactive)
   (if (org-on-heading-p)
       (progn
@@ -2505,7 +2506,7 @@
     (error "Not on a heading")))
 
 (defun org-goto-quit ()
-  "Finish org-goto without cursor motion."
+  "Finish `org-goto' without cursor motion."
   (interactive)
   (setq org-selected-point nil)
   (throw 'exit nil))
@@ -2516,8 +2517,7 @@
   "To temporarily disable the active region.")
 
 (defun org-insert-heading (&optional force-heading)
-  "Insert a new heading or item with same depth at point.
-If ARG is non-nil"
+  "Insert a new heading or item with same depth at point."
   (interactive "P")
   (when (or force-heading (not (org-insert-item)))
     (let* ((head (save-excursion
@@ -2877,7 +2877,7 @@
   (let ((llt org-plain-list-ordered-item-terminator))
     (save-excursion
       (goto-char (point-at-bol))
-      (looking-at 
+      (looking-at
        (cond
 	((eq llt t)  "\\([ \t]*\\([-+]\\|\\([0-9]+[.)]\\)\\)\\|[ \t]+\\*\\)\\( \\|$\\)")
 	((= llt ?.)  "\\([ \t]*\\([-+]\\|\\([0-9]+\\.\\)\\)\\|[ \t]+\\*\\)\\( \\|$\\)")
@@ -2885,7 +2885,7 @@
 	(t (error "Invalid value of `org-plain-list-ordered-item-terminator'")))))))
 
 (defun org-get-indentation ()
-  "Get the indentation of the current line, ionterpreting tabs."
+  "Get the indentation of the current line, interpreting tabs."
   (save-excursion
     (beginning-of-line 1)
     (skip-chars-forward " \t")
@@ -2895,7 +2895,7 @@
   "Go to the beginning of the current hand-formatted item.
 If the cursor is not in an item, throw an error."
   (let ((pos (point))
-	(limit (save-excursion (org-back-to-heading) 
+	(limit (save-excursion (org-back-to-heading)
 			       (beginning-of-line 2) (point)))
 	ind ind1)
     (if (org-at-item-p)
@@ -2917,7 +2917,7 @@
 	(error "Not in an item")))))
 
 (defun org-end-of-item ()
-  "Go to the beginning of the current hand-formatted item.
+  "Go to the end of the current hand-formatted item.
 If the cursor is not in an item, throw an error."
   (let ((pos (point))
 	(limit (save-excursion (outline-next-heading) (point)))
@@ -2937,10 +2937,10 @@
 	(beginning-of-line 1)
       (goto-char pos)
       (error "Not in an item"))))
-      
+
 (defun org-move-item-down (arg)
   "Move the plain list item at point down, i.e. swap with following item.
-Subitems (items with larger indentation are considered part of the item,
+Subitems (items with larger indentation) are considered part of the item,
 so this really moves item trees."
   (interactive "p")
   (let (beg end ind ind1 (pos (point)) txt)
@@ -2962,10 +2962,10 @@
 	  (org-maybe-renumber-ordered-list))
       (goto-char pos)
       (error "Cannot move this item further down"))))
-    
+
 (defun org-move-item-up (arg)
   "Move the plain list item at point up, i.e. swap with previous item.
-Subitems (items with larger indentation are considered part of the item,
+Subitems (items with larger indentation) are considered part of the item,
 so this really moves item trees."
   (interactive "p")
   (let (beg end ind ind1 (pos (point)) txt)
@@ -2998,7 +2998,7 @@
 	  (org-maybe-renumber-ordered-list))
       (goto-char pos)
       (error "Cannot move this item further up"))))
-    
+
 (defun org-maybe-renumber-ordered-list ()
   "Renumber the ordered list at point if setup allows it.
 This tests the user option `org-auto-renumber-ordered-lists' before
@@ -3021,7 +3021,7 @@
 
 (defun org-renumber-ordered-list (arg)
   "Renumber an ordered plain list.
-Cursor neext to be in the first line of an item, the line that starts
+Cursor next to be in the first line of an item, the line that starts
 with something like \"1.\" or \"2)\"."
   (interactive "p")
   (unless (and (org-at-item-p)
@@ -3309,13 +3309,13 @@
      *** TODO Write paper
      *** DONE Call mom
 
-The different keywords are specified in the variable `org-todo-keywords'.  By
-default the available states are \"TODO\" and \"DONE\".
+The different keywords are specified in the variable `org-todo-keywords'.
+By default the available states are \"TODO\" and \"DONE\".
 So for this example: when the item starts with TODO, it is changed to DONE.
 When it starts with DONE, the DONE is removed.  And when neither TODO nor
 DONE are present, add TODO at the beginning of the heading.
 
-With prefix arg, use completion to determined the new state.  With numeric
+With prefix arg, use completion to determine the new state.  With numeric
 prefix arg, switch to that state."
   (interactive "P")
   (save-excursion
@@ -3381,7 +3381,7 @@
 
 (defun org-log-done (&optional undone)
   "Add a time stamp logging that a TODO entry has been closed.
-When UNDONE is non-nil, remove such a time stamg again."
+When UNDONE is non-nil, remove such a time stamp again."
   (interactive)
   (let (beg end col)
     (save-excursion
@@ -3394,7 +3394,7 @@
       (setq end (point))
       (goto-char beg)
       (when (re-search-forward (concat
-				"[\r\n]\\([ \t]*" 
+				"[\r\n]\\([ \t]*"
 				(regexp-quote org-closed-string)
 				" *\\[.*?\\][^\n\r]*[\n\r]?\\)") end t)
 	(delete-region (match-beginning 1) (match-end 1)))
@@ -3405,12 +3405,12 @@
 	(when (not (member (char-before) '(?\r ?\n)))
 	  (insert "\n"))
 	(indent-to col)
-	(insert org-closed-string " " 
-		(format-time-string 
+	(insert org-closed-string " "
+		(format-time-string
 		 (concat "[" (substring (cdr org-time-stamp-formats) 1 -1) "]")
 		 (current-time))
 		"\n")))))
-			    
+
 (defun org-show-todo-tree (arg)
   "Make a compact tree which shows all headlines marked with TODO.
 The tree will show the lines where the regexp matches, and all higher
@@ -3460,7 +3460,7 @@
 The tree will show the lines where the regexp matches, and all higher
 headlines above the match.  It will also show the heading after the match,
 to make sure editing the matching entry is easy.
-if CALLBACK is non-nil, it is a function which is called to confirm
+If CALLBACK is non-nil, it is a function which is called to confirm
 that the match should indeed be shown."
   (interactive "sRegexp: ")
   (org-remove-occur-highlights nil nil t)
@@ -3506,7 +3506,7 @@
   (if org-xemacs-p (make-extent beg end buffer) (make-overlay beg end buffer)))
 (defun org-delete-overlay (ovl)
   (if org-xemacs-p (delete-extent ovl) (delete-overlay ovl)))
-(defun org-detatch-overlay (ovl) 
+(defun org-detatch-overlay (ovl)
   (if org-xemacs-p (detach-extent ovl) (delete-overlay ovl)))
 (defun org-move-overlay (ovl beg end &optional buffer)
   (if org-xemacs-p
@@ -3527,14 +3527,14 @@
 (defun org-remove-occur-highlights (&optional beg end noremove)
   "Remove the occur highlights from the buffer.
 BEG and END are ignored.  If NOREMOVE is nil, remove this function
-from the before-change-functions in the current buffer."
+from the `before-change-functions' in the current buffer."
   (interactive)
   (mapc 'org-delete-overlay org-occur-highlights)
   (setq org-occur-highlights nil)
   (unless noremove
     (remove-hook 'before-change-functions
 		 'org-remove-occur-highlights 'local)))
-  
+
 ;;; Priorities
 
 (defvar org-priority-regexp ".*?\\(\\[#\\([A-Z]\\)\\] ?\\)"
@@ -3673,7 +3673,7 @@
   "Read a date and make things smooth for the user.
 The prompt will suggest to enter an ISO date, but you can also enter anything
 which will at least partially be understood by `parse-time-string'.
-Unrecognized parts of the date will default to the current day, month ,year,
+Unrecognized parts of the date will default to the current day, month, year,
 hour and minute.  For example,
   3-2-5         --> 2003-02-05
   feb 15        --> currentyear-02-15
@@ -3688,9 +3688,9 @@
 
 While prompting, a calendar is popped up - you can also select the
 date with the mouse (button 1).  The calendar shows a period of three
-month.  To scroll it to other months, use the keys `>' and `<'.
+months.  To scroll it to other months, use the keys `>' and `<'.
 If you don't like the calendar, turn it off with
-       \(setq org-popup-calendar-for-date-prompt nil).
+       \(setq org-popup-calendar-for-date-prompt nil)
 
 With optional argument TO-TIME, the date will immediately be converted
 to an internal time.
@@ -4080,7 +4080,7 @@
 (defun org-goto-calendar (&optional arg)
   "Go to the Emacs calendar at the current date.
 If there is a time stamp in the current line, go to that date.
-A prefix ARG can be used force the current date."
+A prefix ARG can be used to force the current date."
   (interactive "P")
   (let ((tsr org-ts-regexp) diff
 	(calendar-move-hook nil)
@@ -4288,10 +4288,10 @@
 a     Call `org-agenda' to display the agenda for the current day or week.
 t     Call `org-todo-list' to display the global todo list.
 T     Call `org-todo-list' to display the global todo list, select only
-      entries with a specific TODO keyword (the user get a prompt).
+      entries with a specific TODO keyword (the user gets a prompt).
 m     Call `org-tags-view' to display headlines with tags matching
       a condition  (the user is prompted for the condition).
-M     like `m', but select only TODO entries, no ordinary headlines.
+M     Like `m', but select only TODO entries, no ordinary headlines.
 
 More commands can be added by configuring the variable
 `org-agenda-custom-commands'.  In particular, specific tags and TODO keyword
@@ -4315,7 +4315,7 @@
 --------------------------------
 a   Agenda for current week or day
 t   List of all TODO entries             T   Entries with special TODO kwd
-m   Match a TAGS query                   M   Like m, but only TODO entries.
+m   Match a TAGS query                   M   Like m, but only TODO entries
 C   Configure your own agenda commands")
 	(while (setq entry (pop custom))
 	  (setq key (car entry) type (nth 1 entry) string (nth 2 entry))
@@ -4611,10 +4611,10 @@
 	(catch 'nextfile
 	  (org-check-agenda-file file)
 	  (if org-agenda-show-log
-	      (setq rtn (org-agenda-get-day-entries 
+	      (setq rtn (org-agenda-get-day-entries
 			 file date
 			 :deadline :scheduled :timestamp :closed))
-	    (setq rtn (org-agenda-get-day-entries 
+	    (setq rtn (org-agenda-get-day-entries
 		       file date
 		       :deadline :scheduled :timestamp)))
 	  (setq rtnall (append rtnall rtn))))
@@ -4813,7 +4813,7 @@
   (message "Switched to week view"))
 
 (defun org-agenda-day-view ()
-  "Switch to weekly view for agenda."
+  "Switch to daily view for agenda."
   (interactive)
   (org-agenda-check-type t 'agenda)
   (setq org-agenda-ndays 1)
@@ -4837,7 +4837,7 @@
   (goto-char (match-beginning 0)))
 
 (defun org-agenda-previous-date-line (&optional arg)
-  "Jump to the next line indicating a date in agenda buffer."
+  "Jump to the previous line indicating a date in agenda buffer."
   (interactive "p")
   (org-agenda-check-type t 'agenda 'timeline)
   (beginning-of-line 1)
@@ -4867,7 +4867,7 @@
 	   (if org-agenda-follow-mode "on" "off")))
 
 (defun org-agenda-log-mode ()
-  "Toggle follow mode in an agenda buffer."
+  "Toggle log mode in an agenda buffer."
   (interactive)
   (org-agenda-check-type t 'agenda 'timeline)
   (setq org-agenda-show-log (not org-agenda-show-log))
@@ -4877,7 +4877,7 @@
 	   (if org-agenda-show-log "on" "off")))
 
 (defun org-agenda-toggle-diary ()
-  "Toggle follow mode in an agenda buffer."
+  "Toggle diary inclusion in an agenda buffer."
   (interactive)
   (org-agenda-check-type t 'agenda)
   (setq org-agenda-include-diary (not org-agenda-include-diary))
@@ -4887,7 +4887,7 @@
 	   (if org-agenda-include-diary "on" "off")))
 
 (defun org-agenda-toggle-time-grid ()
-  "Toggle follow mode in an agenda buffer."
+  "Toggle time grid in an agenda buffer."
   (interactive)
   (org-agenda-check-type t 'agenda)
   (setq org-agenda-use-time-grid (not org-agenda-use-time-grid))
@@ -4959,10 +4959,10 @@
 	     entries)))))
 
 (defun org-agenda-cleanup-fancy-diary ()
-  "Remove unwanted stuff in buffer created by fancy-diary-display.
+  "Remove unwanted stuff in buffer created by `fancy-diary-display'.
 This gets rid of the date, the underline under the date, and
 the dummy entry installed by `org-mode' to ensure non-empty diary for each
-date.  Itt also removes lines that contain only whitespace."
+date.  It also removes lines that contain only whitespace."
   (goto-char (point-min))
   (if (looking-at ".*?:[ \t]*")
       (progn
@@ -5035,8 +5035,8 @@
       (find-file (car org-agenda-files)))))
 
 (defun org-agenda-file-to-end (&optional file)
-  "Move/add the current file to the end of the agenda fiole list.
-I the file is not present in the list, it is appended ot the list.  If it is
+  "Move/add the current file to the end of the agenda file list.
+If the file is not present in the list, it is appended to the list.  If it is
 present, it is moved there."
   (interactive)
   (org-agenda-file-to-front 'to-end file))
@@ -5315,7 +5315,7 @@
 		      'help-echo
 		      (format "mouse-2 or RET jump to org file %s"
 			      (abbreviate-file-name (buffer-file-name)))))
-	 (regexp (concat "[\n\r]\\*+ *\\(" 
+	 (regexp (concat "[\n\r]\\*+ *\\("
 			 (if org-select-this-todo-keyword
 			     (concat "\\<\\(" org-select-this-todo-keyword
 				     "\\)\\>")
@@ -5347,7 +5347,7 @@
     (nreverse ee)))
 
 (defconst org-agenda-no-heading-message
-  "No heading for this item in buffer or region")
+  "No heading for this item in buffer or region.")
 
 (defun org-agenda-get-timestamps ()
   "Return the date stamp information for agenda display."
@@ -5428,7 +5428,7 @@
     (nreverse ee)))
 
 (defun org-agenda-get-closed ()
-  "Return the loggedd TODO entries for agenda display."
+  "Return the logged TODO entries for agenda display."
   (let* ((props (list 'mouse-face 'highlight
 		      'keymap org-agenda-keymap
 		      'help-echo
@@ -5579,7 +5579,7 @@
 		  (if (string-match org-looking-at-done-regexp head)
 		      (setq txt nil)
 		    (setq txt (org-format-agenda-item
-			       (format "Sched.%2dx: " (- 1 diff)) head 
+			       (format "Sched.%2dx: " (- 1 diff)) head
 			       category tags))))
 	      (setq txt org-agenda-no-heading-message))
 	    (when txt
@@ -5680,14 +5680,14 @@
   "Format TXT to be inserted into the agenda buffer.
 In particular, it adds the prefix and corresponding text properties.  EXTRA
 must be a string and replaces the `%s' specifier in the prefix format.
-CATEGORY (string, symbol or nil) may be used to overule the default
-category taken from local variable or file name. It will replace the `%c'
+CATEGORY (string, symbol or nil) may be used to overrule the default
+category taken from local variable or file name.  It will replace the `%c'
 specifier in the format.  DOTIME, when non-nil, indicates that a
 time-of-day should be extracted from TXT for sorting of this entry, and for
 the `%t' specifier in the format.  When DOTIME is a string, this string is
 searched for a time before TXT is.  NOPREFIX is a flag and indicates that
 only the correctly processes TXT should be returned - this is used by
-`org-agenda-change-all-lines'. TAG can be the tag of the headline."
+`org-agenda-change-all-lines'.  TAG can be the tag of the headline."
   (save-match-data
     ;; Diary entries sometimes have extra whitespace at the beginning
     (if (string-match "^ +" txt) (setq txt (replace-match "" nil nil txt)))
@@ -5841,7 +5841,7 @@
   (mapconcat 'identity (sort list 'org-entries-lessp) "\n"))
 
 (defsubst org-cmp-priority (a b)
-  "Compare the priorities of string a and b."
+  "Compare the priorities of string A and B."
   (let ((pa (or (get-text-property 1 'priority a) 0))
 	(pb (or (get-text-property 1 'priority b) 0)))
     (cond ((> pa pb) +1)
@@ -5849,7 +5849,7 @@
 	  (t nil))))
 
 (defsubst org-cmp-category (a b)
-  "Compare the string values of categories of strings a and b."
+  "Compare the string values of categories of strings A and B."
   (let ((ca (or (get-text-property 1 'category a) ""))
 	(cb (or (get-text-property 1 'category b) "")))
     (cond ((string-lessp ca cb) -1)
@@ -5857,7 +5857,7 @@
 	  (t nil))))
 
 (defsubst org-cmp-time (a b)
-  "Compare the time-of-day values of strings a and b."
+  "Compare the time-of-day values of strings A and B."
   (let* ((def (if org-sort-agenda-notime-is-late 2401 -1))
 	 (ta (or (get-text-property 1 'time-of-day a) def))
 	 (tb (or (get-text-property 1 'time-of-day b) def)))
@@ -6001,7 +6001,7 @@
     (move-to-column col)))
 
 (defun org-agenda-change-all-lines (newhead hdmarker &optional fixface)
-  "Change all lines in the agenda buffer which match hdmarker.
+  "Change all lines in the agenda buffer which match HDMARKER.
 The new content of the line will be NEWHEAD (as modified by
 `org-format-agenda-item').  HDMARKER is checked with
 `equal' against all `org-hd-marker' text properties in the file.
@@ -6153,7 +6153,7 @@
 
 (defun org-agenda-diary-entry ()
   "Make a diary entry, like the `i' command from the calendar.
-All the standard commands work: block, weekly etc"
+All the standard commands work: block, weekly etc."
   (interactive)
   (org-agenda-check-type t 'agenda 'timeline)
   (require 'diary-lib)
@@ -6292,8 +6292,8 @@
   "Scan headline tags with inheritance and produce output ACTION.
 ACTION can be `sparse-tree' or `agenda'.  MATCHER is a Lisp form to be
 evaluated, testing if a given set of tags qualifies a headline for
-inclusion.  When TODO-ONLY is non-nil, only lines with a TDOD keyword
-d are included in the output."
+inclusion.  When TODO-ONLY is non-nil, only lines with a TODO keyword
+are included in the output."
   (let* ((re (concat "[\n\r]" outline-regexp " *\\(\\<\\("
 		     (mapconcat 'regexp-quote
 				(nreverse (cdr (reverse org-todo-keywords)))
@@ -6329,7 +6329,7 @@
 	;; add the nex tags
 	(when tags
 	  (setq tags (mapcar 'downcase (org-split-string tags ":"))
-		tags-alist 
+		tags-alist
 		(cons (cons level tags) tags-alist)))
 	;; compile tags for current headline
 	(setq tags-list
@@ -6342,7 +6342,7 @@
 	  (if (eq action 'sparse-tree)
 	      (progn
 		(org-show-hierarchy-above))
-	    (setq txt (org-format-agenda-item 
+	    (setq txt (org-format-agenda-item
 		       ""
 		       (concat
 			(if org-tags-match-list-sublevels
@@ -6352,7 +6352,7 @@
             (goto-char lspos)
 	    (setq marker (org-agenda-new-marker))
 	    (add-text-properties
-	     0 (length txt) 
+	     0 (length txt)
 	     (append (list 'org-marker marker 'org-hd-marker marker
 			   'category category)
 		     props)
@@ -6403,7 +6403,7 @@
 
 ;;;###autoload
 (defun org-tags-view (&optional todo-only match keep-modes)
-  "Show all headlines for all `org-agenda-files' matching a TAGS criterions.
+  "Show all headlines for all `org-agenda-files' matching a TAGS criterion.
 The prefix arg TODO-ONLY limits the search to TODO entries."
   (interactive "P")
   (org-agenda-maybe-reset-markers 'force)
@@ -6427,7 +6427,7 @@
     (org-agenda-mode) (setq buffer-read-only nil)
     (set (make-local-variable 'org-agenda-type) 'tags)
     (set (make-local-variable 'org-agenda-redo-command)
-	 (list 'org-tags-view (list 'quote todo-only) 
+	 (list 'org-tags-view (list 'quote todo-only)
 	       (list 'if 'current-prefix-arg nil match) t))
     (setq files (org-agenda-files)
 	  rtnall nil)
@@ -6525,12 +6525,12 @@
     (if (string-match "^\\(.*[-+:&|]\\)\\([^-+:&|]*\\)$" string)
         (setq s1 (match-string 1 string)
               s2 (match-string 2 string))
-      (setq s1 "" s2 string)) 
+      (setq s1 "" s2 string))
     (cond
      ((eq flag nil)
       ;; try completion
       (setq rtn (try-completion s2 ctable))
-      (if (stringp rtn) 
+      (if (stringp rtn)
 	  (concat s1 s2 (substring rtn (length s2))
 		  (if (and org-add-colon-after-tag-completion
 			   (assoc rtn ctable))
@@ -6620,7 +6620,7 @@
 		(setq path (concat "*" path))))
 	  (throw 'match t))
 	(save-excursion
-	  (when (re-search-forward 
+	  (when (re-search-forward
 		 org-link-regexp
 		 (save-excursion
 		   (condition-case nil
@@ -6634,9 +6634,9 @@
       ;; Remove any trailing spaces in path
       (if (string-match " +\\'" path)
 	  (setq path (replace-match "" t t path)))
-      
+
       (cond
-       
+
        ((string= type "tags")
 	(org-tags-view in-emacs path))
        ((string= type "camel")
@@ -6645,7 +6645,7 @@
 	 (cond ((equal in-emacs '(4)) 'occur)
 	       ((equal in-emacs '(16)) 'org-occur)
 	       (t nil))))
-       
+
        ((string= type "file")
 	(if (string-match "::?\\([0-9]+\\)\\'" path) ;; second : optional
 	    (setq line (string-to-number (match-string 1 path))
@@ -6654,13 +6654,13 @@
 	      (setq search (match-string 1 path)
 		    path (substring path 0 (match-beginning 0)))))
 	(org-open-file path in-emacs line search))
-       
+
        ((string= type "news")
 	(org-follow-gnus-link path))
-       
+
        ((string= type "bbdb")
 	(org-follow-bbdb-link path))
-       
+
        ((string= type "gnus")
 	(let (group article)
 	  (if (not (string-match "\\`\\([^#]+\\)\\(#\\(.*\\)\\)?" path))
@@ -6668,7 +6668,7 @@
 	  (setq group (match-string 1 path)
 		article (match-string 3 path))
 	  (org-follow-gnus-link group article)))
-       
+
        ((string= type "vm")
 	(let (folder article)
 	  (if (not (string-match "\\`\\([^#]+\\)\\(#\\(.*\\)\\)?" path))
@@ -6677,7 +6677,7 @@
 		article (match-string 3 path))
 	  ;; in-emacs is the prefix arg, will be interpreted as read-only
 	  (org-follow-vm-link folder article in-emacs)))
-       
+
        ((string= type "wl")
 	(let (folder article)
 	  (if (not (string-match "\\`\\([^#]+\\)\\(#\\(.*\\)\\)?" path))
@@ -6685,7 +6685,7 @@
 	  (setq folder (match-string 1 path)
 		article (match-string 3 path))
 	  (org-follow-wl-link folder article)))
-       
+
        ((string= type "rmail")
 	(let (folder article)
 	  (if (not (string-match "\\`\\([^#]+\\)\\(#\\(.*\\)\\)?" path))
@@ -6693,7 +6693,7 @@
 	  (setq folder (match-string 1 path)
 		article (match-string 3 path))
 	  (org-follow-rmail-link folder article)))
-       
+
        ((string= type "shell")
 	(let ((cmd path))
 	  (while (string-match "@{" cmd)
@@ -6704,7 +6704,7 @@
 		  (yes-or-no-p (format "Execute \"%s\" in the shell? " cmd)))
 	      (shell-command cmd)
 	    (error "Abort"))))
-       
+
        (t
 	(browse-url-at-point))))))
 
@@ -6713,7 +6713,7 @@
 When S is a CamelCaseWord, search for a target, or for a sentence containing
 the words.  If S is surrounded by forward slashes, it is interpreted as a
 regular expression.  In org-mode files, this will create an `org-occur'
-sparse tree.  In ordinary files, `occur' will be used to list matched.
+sparse tree.  In ordinary files, `occur' will be used to list matches.
 If the current buffer is in `dired-mode', grep will be used to search
 in all files."
   (let ((case-fold-search t)
@@ -6735,7 +6735,7 @@
 	       (setq pre "^\\*+[ \t]*\\(\\sw+\\)?[ \t]*"
 		     post "[ \t]*$"
 		     s (substring s 1)))
-	   (remove-text-properties 
+	   (remove-text-properties
 	    0 (length s)
 	    '(face nil mouse-face nil keymap nil fontified nil) s)
 	   ;; Make a series of regular expressions to find a match
@@ -6792,7 +6792,7 @@
       (select-window cwin))))
 
 (defun org-camel-to-words (s)
-  "Split \"CamelCaseWords\" to (\"Camel \" \"Case\" \"Words\")."
+  "Split \"CamelCaseWords\" to (\"Camel\" \"Case\" \"Words\")."
   (let ((case-fold-search nil)
 	words)
     (while (string-match "[a-z][A-Z]" s)
@@ -6907,10 +6907,10 @@
 With optional argument IN-EMACS, Emacs will visit the file.
 Optional LINE specifies a line to go to, optional SEARCH a string to
 search for.  If LINE or SEARCH is given, the file will always be
-openen in emacs.
+opened in Emacs.
 If the file does not exist, an error is thrown."
   (setq in-emacs (or in-emacs line search))
-  (let* ((file (if (equal path "") 
+  (let* ((file (if (equal path "")
 		   (buffer-file-name)
 		 (convert-standard-filename (org-expand-file-name path))))
 	 (dfile (downcase file))
@@ -7102,7 +7102,7 @@
 			(org-make-org-heading-camel
 			 (cond
 			  ((org-on-heading-p) nil)
-			  ((org-region-active-p) 
+			  ((org-region-active-p)
 			   (buffer-substring (region-beginning) (region-end)))
 			  (t (buffer-substring (point-at-bol) (point-at-eol))))
 			 )))))
@@ -7115,9 +7115,9 @@
       ;; Add a context string
       (when (org-xor org-context-in-file-links arg)
 	(setq cpltxt
-	      (concat cpltxt "::" 
+	      (concat cpltxt "::"
 		      (org-make-org-heading-camel
-		       (if (org-region-active-p) 
+		       (if (org-region-active-p)
 			   (buffer-substring (region-beginning) (region-end))
 			 (buffer-substring (point-at-bol) (point-at-eol)))))))
       (setq link (org-make-link cpltxt)))
@@ -7295,7 +7295,7 @@
 Then the command offers the headings tree of the selected file in order to
 file the text at a specific location.
 You can either immediately press RET to get the note appended to the
-file.  Or you can use vertical cursor motion and visibility cycling (TAB) to
+file, or you can use vertical cursor motion and visibility cycling (TAB) to
 find a better place.  Then press RET or <left> or <right> in insert the note.
 
 Key      Cursor position   Note gets inserted
@@ -7497,7 +7497,7 @@
 The region goes from BEG0 to END0, but these borders will be moved
 slightly, to make sure a beginning of line in the first line is included.
 When NSPACE is non-nil, it indicates the minimum number of spaces that
-separate columns (default: just one space)"
+separate columns (default: just one space)."
   (let* ((beg (min beg0 end0))
 	 (end (max beg0 end0))
 	 (tabsep t)
@@ -8130,11 +8130,11 @@
     (org-table-modify-formulas 'swap col (if left (1- col) (1+ col)))))
 
 (defun org-table-move-row-down ()
-  "move table row down."
+  "Move table row down."
   (interactive)
   (org-table-move-row nil))
 (defun org-table-move-row-up ()
-  "move table row up."
+  "Move table row up."
   (interactive)
   (org-table-move-row 'up))
 
@@ -8287,7 +8287,7 @@
 (defun org-table-copy-region (beg end &optional cut)
   "Copy rectangular region in table to clipboard.
 A special clipboard is used which can only be accessed
-with `org-table-paste-rectangle'"
+with `org-table-paste-rectangle'."
   (interactive "rP")
   (let* (l01 c01 l02 c02 l1 c1 l2 c2 ic1 ic2
 	 region cols
@@ -8402,7 +8402,7 @@
 the text in the column is wrapped to minimum width for the given number of
 lines.  Generally, this makes the table more compact.  A prefix ARG may be
 used to change the number of desired lines.  For example, `C-2 \\[org-table-wrap]'
-formats the selected text to two lines.  If the region was longer than 2
+formats the selected text to two lines.  If the region was longer than two
 lines, the remaining lines remain empty.  A negative prefix argument reduces
 the current number of lines by that amount.  The wrapped text is pasted back
 into the table.  If you formatted it to more lines than it was before, fields
@@ -8549,7 +8549,7 @@
   "Toggle the visibility of table vertical lines.
 The effect is immediate and on all tables in the file.
 With prefix ARG, make lines invisible when ARG is positive, make lines
-visible when ARG is not positive"
+visible when ARG is not positive."
   (interactive "P")
   (let ((action (cond
 		 ((and arg (> (prefix-numeric-value arg) 0)) 'on)
@@ -8663,7 +8663,7 @@
      (t n))))
 
 (defun org-table-get-vertical-vector (desc &optional tbeg col)
-  "Get a calc vector from a column, accorting to desctiptor DESC.
+  "Get a calc vector from a column, accorting to descriptor DESC.
 Optional arguments TBEG and COL can give the beginning of the table and
 the current column, to avoid unnecessary parsing."
   (save-excursion
@@ -8807,7 +8807,7 @@
 (defun org-table-modify-formulas (action &rest columns)
   "Modify the formulas stored below the current table.
 ACTION can be `remove', `insert', `swap'.  For `swap', two column numbers are
-expected, for the other action only a single column number is needed."
+expected, for the other actions only a single column number is needed."
   (let ((list (org-table-get-stored-formulas))
 	(nmax (length (org-split-string
 		       (buffer-substring (point-at-bol) (point-at-eol))
@@ -8857,7 +8857,7 @@
       (setcdr elt s))))
 
 (defun org-table-get-specials ()
-  "Get the column nmaes and local parameters for this table."
+  "Get the column names and local parameters for this table."
   (save-excursion
     (let ((beg (org-table-begin)) (end (org-table-end))
 	  names name fields fields1 field cnt c v line col)
@@ -8920,7 +8920,7 @@
 	    (org-table-eval-formula (if named '(4) nil) eq))))))
 
 (defvar org-recalc-commands nil
-  "List of commands triggering the reccalculation of a line.
+  "List of commands triggering the recalculation of a line.
 Will be filled automatically during use.")
 
 (defvar org-recalc-marks
@@ -8935,10 +8935,10 @@
 (defun org-table-rotate-recalc-marks (&optional newchar)
   "Rotate the recalculation mark in the first column.
 If in any row, the first field is not consistent with a mark,
-insert a new column for the makers.
+insert a new column for the markers.
 When there is an active region, change all the lines in the region,
 after prompting for the marking character.
-After each change, a message will be displayed indication the meaning
+After each change, a message will be displayed indicating the meaning
 of the new mark."
   (interactive)
   (unless (org-at-table-p) (error "Not at a table"))
@@ -9025,12 +9025,12 @@
 					 suppress-store)
   "Replace the table field value at the cursor by the result of a calculation.
 
-This function makes use of Dave Gillespie's calc package, in my view the
-most exciting program ever written for GNU Emacs.  So you need to have calc
+This function makes use of Dave Gillespie's Calc package, in my view the
+most exciting program ever written for GNU Emacs.  So you need to have Calc
 installed in order to use this function.
 
 In a table, this command replaces the value in the current field with the
-result of a formula.  It also installes the formula as the \"current\" column
+result of a formula.  It also installs the formula as the \"current\" column
 formula, by storing it in a special line below the table.  When called
 with a `C-u' prefix, the current field must ba a named field, and the
 formula is installed as valid in only this specific field.
@@ -9041,15 +9041,15 @@
 These stored formulas are adapted correctly when moving, inserting, or
 deleting columns with the corresponding commands.
 
-The formula can be any algebraic expression understood by the calc package.
+The formula can be any algebraic expression understood by the Calc package.
 For details, see the Org-mode manual.
 
 This function can also be called from Lisp programs and offers
-additional Arguments: EQUATION can be the formula to apply.  If this
+additional arguments: EQUATION can be the formula to apply.  If this
 argument is given, the user will not be prompted.  SUPPRESS-ALIGN is
 used to speed-up recursive calls by by-passing unnecessary aligns.
 SUPPRESS-CONST suppresses the interpretation of constants in the
-formula, assuming that this has been done already outside the fuction.
+formula, assuming that this has been done already outside the function.
 SUPPRESS-STORE means the formula should not be stored, either because
 it is already stored, or because it is a modified equation that should
 not overwrite the stored one."
@@ -9490,8 +9490,8 @@
 
 (defun orgtbl-make-binding (fun n &rest keys)
   "Create a function for binding in the table minor mode.
-FUN is the command to call inside a table. N is used to create a unique
-command name. KEYS are keys that should be checked in for a command
+FUN is the command to call inside a table.  N is used to create a unique
+command name.  KEYS are keys that should be checked in for a command
 to execute outside of tables."
   (eval
    (list 'defun
@@ -10660,7 +10660,7 @@
 		    start-is-num (match-beginning 4)
 		    starter (if (match-beginning 2) (match-string 2 line))
 		    line (substring line (match-beginning 5)))
-	      (unless (string-match "[^ \t]" line) 
+	      (unless (string-match "[^ \t]" line)
 		;; empty line.  Pretend indentation is large.
 		(setq ind (1+ (or (car local-list-indent) 1))))
 	      (while (and in-local-list
@@ -11966,7 +11966,7 @@
 	      (delete arg buffer-invisibility-spec)))))
 
 (defun org-in-invisibility-spec-p (arg)
-  "Is ARG a member of `buffer-invisibility-spec'?."
+  "Is ARG a member of `buffer-invisibility-spec'?"
   (if (consp buffer-invisibility-spec)
       (member arg buffer-invisibility-spec)
     nil))
@@ -12195,4 +12195,4 @@
 ;; arch-tag: e77da1a7-acc7-4336-b19e-efa25af3f9fd
 ;;; org.el ends here
 
-      
+
--- a/lisp/thumbs.el	Thu Jan 26 02:23:05 2006 +0000
+++ b/lisp/thumbs.el	Wed Feb 01 10:07:17 2006 +0000
@@ -174,6 +174,8 @@
 
 (defvar thumbs-marked-list nil
   "List of marked files.")
+(make-variable-buffer-local 'thumbs-marked-list)
+(put 'thumbs-marked-list 'permanent-local t)
 
 (defalias 'thumbs-gensym
     (if (fboundp 'gensym)
@@ -334,9 +336,9 @@
 	((string-match ".*\\.tiff?\\'" img) 'tiff)))
 
 (defun thumbs-file-size (img)
-  (let ((i (image-size (find-image `((:type ,(thumbs-image-type img) :file ,img))) t)))
-    (concat (number-to-string (round (car i)))
-	    "x"
+  (let ((i (image-size
+	    (find-image `((:type ,(thumbs-image-type img) :file ,img))) t)))
+    (concat (number-to-string (round (car i))) "x"
 	    (number-to-string (round (cdr i))))))
 
 ;;;###autoload
@@ -366,7 +368,8 @@
    (thumbs-make-thumb img) 'jpeg thumbs-relief marked)
   (add-text-properties (1- (point)) (point)
 		     `(thumb-image-file ,img
-		       help-echo ,(file-name-nondirectory img))))
+		       help-echo ,(file-name-nondirectory img)
+		       rear-nonsticky help-echo)))
 
 (defun thumbs-do-thumbs-insertion (list)
   "Insert all thumbnails into thumbs buffer."
@@ -380,7 +383,7 @@
       (when (= 0 (mod (setq i (1+ i)) thumbs-per-line))
 	(newline)))
     (unless (bobp) (newline))
-    (if diff (message "Type + to display more images."))))
+    (if (> diff 0) (message "Type + to display more images."))))
 
 (defun thumbs-show-thumbs-list (list &optional dir same-window)
   (unless (and (display-images-p)
@@ -488,7 +491,7 @@
       (let (list)
 	(goto-char (point-min))
 	(while (not (eobp))
-	  (unless (= 0 (mod (point) (1+ thumbs-per-line)))
+	  (unless (eolp)
 	    (if (thumbs-current-image)
 		(push (cons (point-marker)
 			    (thumbs-current-image))
@@ -623,8 +626,7 @@
     (push elt thumbs-marked-list)
     (let ((inhibit-read-only t))
       (delete-char 1)
-      (save-excursion
-	(thumbs-insert-thumb elt t))))
+      (thumbs-insert-thumb elt t)))
   (when (eolp) (forward-char)))
 
 (defun thumbs-unmark ()
@@ -636,11 +638,9 @@
     (setq thumbs-marked-list (delete elt thumbs-marked-list))
     (let ((inhibit-read-only t))
       (delete-char 1)
-      (save-excursion
-	(thumbs-insert-thumb elt nil))))
+      (thumbs-insert-thumb elt nil)))
   (when (eolp) (forward-char)))
 
-
 ;; cleaning of old temp files
 (mapc 'delete-file
       (directory-files (thumbs-temp-dir) t thumbs-temp-prefix))
@@ -777,8 +777,7 @@
 (define-derived-mode thumbs-mode
   fundamental-mode "thumbs"
   "Preview images in a thumbnails buffer"
-  (setq buffer-read-only t)
-  (set (make-local-variable 'thumbs-marked-list) nil))
+  (setq buffer-read-only t))
 
 (defvar thumbs-view-image-mode-map
   (let ((map (make-sparse-keymap)))
--- a/lisp/tumme.el	Thu Jan 26 02:23:05 2006 +0000
+++ b/lisp/tumme.el	Wed Feb 01 10:07:17 2006 +0000
@@ -3,7 +3,7 @@
 ;; Copyright (C) 2005 Free Software Foundation, Inc.
 ;;
 ;; Version: 0.4.10
-;; Keywords: images, thumbnails, dired
+;; Keywords: multimedia
 ;; Author: Mathias Dahl <mathias.rem0veth1s.dahl@gmail.com>
 
 ;; This file is part of GNU Emacs.
@@ -969,6 +969,7 @@
           (tumme-display-image-mode)))
     buf))
 
+;;;###autoload
 (defun tumme-dired (dir &optional arg)
   "Open directory DIR and create a default window configuration.
 
@@ -1643,6 +1644,7 @@
   (tumme-define-display-image-mode-keymap)
   (message "tumme-display-image-mode enabled"))
 
+;;;###autoload
 (defun tumme-setup-dired-keybindings ()
   "Setup easy-to-use keybindings for the commands to be used in dired mode.
 Note that n, p and <down> and <up> will be hijacked and bound to
@@ -2601,7 +2603,7 @@
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
 
-(setq tumme-dir-max-size 12300000)
+(defvar tumme-dir-max-size 12300000)
 
 (defun tumme-test ()
   "Clean `tumme-dir' from old thumbnail files.
--- a/lisp/vc-hooks.el	Thu Jan 26 02:23:05 2006 +0000
+++ b/lisp/vc-hooks.el	Wed Feb 01 10:07:17 2006 +0000
@@ -410,14 +410,22 @@
           (vc-file-setprop file 'vc-checkout-model
                            (vc-call checkout-model file)))))
 
-(defun vc-user-login-name (&optional uid)
-  "Return the name under which the user is logged in, as a string.
-\(With optional argument UID, return the name of that user.)
-This function does the same as function `user-login-name', but unlike
-that, it never returns nil.  If a UID cannot be resolved, that
-UID is returned as a string."
-  (or (user-login-name uid)
-      (number-to-string (or uid (user-uid)))))
+(defun vc-user-login-name (file)
+  "Return the name under which the user accesses the given FILE."
+  (or (and (eq (string-match tramp-file-name-regexp file) 0)
+           ;; tramp case: execute "whoami" via tramp
+           (let ((default-directory (file-name-directory file)))
+             (with-temp-buffer
+               (if (not (zerop (process-file "whoami" nil t)))
+                   ;; fall through if "whoami" didn't work
+                   nil
+                 ;; remove trailing newline
+                 (delete-region (1- (point-max)) (point-max))
+                 (buffer-string)))))
+      ;; normal case
+      (user-login-name)
+      ;; if user-login-name is nil, return the UID as a string
+      (number-to-string (user-uid))))
 
 (defun vc-state (file)
   "Return the version control state of FILE.
--- a/lisp/vc-rcs.el	Thu Jan 26 02:23:05 2006 +0000
+++ b/lisp/vc-rcs.el	Wed Feb 01 10:07:17 2006 +0000
@@ -818,7 +818,7 @@
             'needs-patch))
 	 ;; locked by the calling user
 	 ((and (stringp locking-user)
-	       (string= locking-user (vc-user-login-name)))
+	       (string= locking-user (vc-user-login-name file)))
 	  (if (or (eq (vc-checkout-model file) 'locking)
 		  workfile-is-latest
 		  (vc-rcs-latest-on-branch-p file workfile-version))
@@ -907,7 +907,8 @@
 	  (vc-file-setprop file 'vc-state
 			   (cond
 			    ((eq locking-user 'none) 'up-to-date)
-			    ((string= locking-user (vc-user-login-name)) 'edited)
+			    ((string= locking-user (vc-user-login-name file)) 
+                             'edited)
 			    (t locking-user)))
 	  ;; If the file has headers, we don't want to query the
 	  ;; master file, because that would eliminate all the
--- a/lisp/vc-sccs.el	Thu Jan 26 02:23:05 2006 +0000
+++ b/lisp/vc-sccs.el	Wed Feb 01 10:07:17 2006 +0000
@@ -108,7 +108,7 @@
               (if (vc-workfile-unchanged-p file)
                   'up-to-date
                 'unlocked-changes)
-            (if (string= locking-user (vc-user-login-name))
+            (if (string= locking-user (vc-user-login-name file))
                 'edited
               locking-user)))
       'up-to-date)))
--- a/lisp/vc.el	Thu Jan 26 02:23:05 2006 +0000
+++ b/lisp/vc.el	Wed Feb 01 10:07:17 2006 +0000
@@ -2119,7 +2119,7 @@
   (let ((state (vc-state file)))
     (cond
      ((stringp state) (concat "(" state ")"))
-     ((eq state 'edited) (concat "(" (vc-user-login-name) ")"))
+     ((eq state 'edited) (concat "(" (vc-user-login-name file) ")"))
      ((eq state 'needs-merge) "(merge)")
      ((eq state 'needs-patch) "(patch)")
      ((eq state 'unlocked-changes) "(stale)"))))
@@ -2852,6 +2852,8 @@
 		   (expand-file-name "vc"
 				     (or small-temporary-file-directory
 					 temporary-file-directory))))
+        (login-name (or user-login-name
+                        (format "uid%d" (number-to-string (user-uid)))))
 	(full-name (or add-log-full-name
 		       (user-full-name)
 		       (user-login-name)
@@ -2874,7 +2876,7 @@
                                                       exec-directory)
                                     nil (list t tempfile) nil
                                     "-c" changelog
-                                    "-u" (concat (vc-user-login-name)
+                                    "-u" (concat login-name
                                                  "\t" full-name
                                                  "\t" mailing-address)
                                     (mapcar
--- a/lisp/wid-edit.el	Thu Jan 26 02:23:05 2006 +0000
+++ b/lisp/wid-edit.el	Wed Feb 01 10:07:17 2006 +0000
@@ -850,11 +850,14 @@
 ;;; Keymap and Commands.
 
 ;;;###autoload
+(defalias 'advertised-widget-backward 'widget-backward)
+
+;;;###autoload
 (defvar widget-keymap
   (let ((map (make-sparse-keymap)))
     (define-key map "\t" 'widget-forward)
     (define-key map "\e\t" 'widget-backward)
-    (define-key map [(shift tab)] 'widget-backward)
+    (define-key map [(shift tab)] 'advertised-widget-backward)
     (define-key map [backtab] 'widget-backward)
     (define-key map [down-mouse-2] 'widget-button-click)
     (define-key map "\C-m" 'widget-button-press)
--- a/lisp/window.el	Thu Jan 26 02:23:05 2006 +0000
+++ b/lisp/window.el	Wed Feb 01 10:07:17 2006 +0000
@@ -297,24 +297,24 @@
 
 ;;; Window or object edges
 
-(defun bw-l(obj)
+(defun bw-l (obj)
   "Left edge of OBJ."
   (if (windowp obj) (nth 0 (window-edges obj)) (cdr (assq 'l obj))))
-(defun bw-t(obj)
+(defun bw-t (obj)
   "Top edge of OBJ."
   (if (windowp obj) (nth 1 (window-edges obj)) (cdr (assq 't obj))))
-(defun bw-r(obj)
+(defun bw-r (obj)
   "Right edge of OBJ."
   (if (windowp obj) (nth 2 (window-edges obj)) (cdr (assq 'r obj))))
-(defun bw-b(obj)
+(defun bw-b (obj)
   "Bottom edge of OBJ."
   (if (windowp obj) (nth 3 (window-edges obj)) (cdr (assq 'b obj))))
 
 ;;; Split directions
 
-(defun bw-dir(obj)
+(defun bw-dir (obj)
   "Return window split tree direction if OBJ.
-If OBJ is a window return 'both. If it is a window split tree
+If OBJ is a window return 'both.  If it is a window split tree
 then return its direction."
   (if (symbolp obj)
       obj
@@ -325,10 +325,10 @@
           (error "Can't find dir in %s" obj))
         dir))))
 
-(defun bw-eqdir(obj1 obj2)
+(defun bw-eqdir (obj1 obj2)
   "Return t if window split tree directions are equal.
 OBJ1 and OBJ2 should be either windows or window split trees in
-our format. The directions returned by `bw-dir' are compared and
+our format.  The directions returned by `bw-dir' are compared and
 t is returned if they are `eq' or one of them is 'both."
   (let ((dir1 (bw-dir obj1))
         (dir2 (bw-dir obj2)))
@@ -338,7 +338,7 @@
 
 ;;; Building split tree
 
-(defun bw-refresh-edges(obj)
+(defun bw-refresh-edges (obj)
   "Refresh the edge information of OBJ and return OBJ."
   (unless (windowp obj)
     (let ((childs (cdr (assq 'childs obj)))
@@ -364,12 +364,12 @@
 
 ;;; Balance windows
 
-(defun balance-windows(&optional window-or-frame)
+(defun balance-windows (&optional window-or-frame)
   "Make windows the same heights or widths in window split subtrees.
 
 When called non-interactively WINDOW-OR-FRAME may be either a
-window or a frame. It then balances the windows on the implied
-frame. If the parameter is a window only the corresponding window
+window or a frame.  It then balances the windows on the implied
+frame.  If the parameter is a window only the corresponding window
 subtree is balanced."
   (interactive)
   (let (
@@ -383,7 +383,7 @@
     (when wt
       (while (not (member last-sizes tried-sizes))
         (when last-sizes (setq tried-sizes (cons last-sizes tried-sizes)))
-        (setq last-sizes (mapcar (lambda(w)
+        (setq last-sizes (mapcar (lambda (w)
                                    (window-edges w))
                                  windows))
         (when (eq 'hor (bw-dir wt))
@@ -392,7 +392,7 @@
           (setq h (- (bw-b wt) (bw-t wt))))
         (bw-balance-sub wt w h)))))
 
-(defun bw-adjust-window(window delta horizontal)
+(defun bw-adjust-window (window delta horizontal)
   "Wrapper around `adjust-window-trailing-edge' with error checking.
 Arguments WINDOW, DELTA and HORIZONTAL are passed on to that function."
   (condition-case err
@@ -401,7 +401,7 @@
      ;;(message "adjust: %s" (error-message-string err))
      )))
 
-(defun bw-balance-sub(wt w h)
+(defun bw-balance-sub (wt w h)
   (setq wt (bw-refresh-edges wt))
   (unless w (setq w (- (bw-r wt) (bw-l wt))))
   (unless h (setq h (- (bw-b wt) (bw-t wt))))
@@ -434,7 +434,7 @@
 
 This option applies only to `split-window-vertically' and
 functions that call it.  `split-window' always keeps the original
-point in both children,"
+point in both children."
   :type 'boolean
   :group 'windows)
 
--- a/lispref/ChangeLog	Thu Jan 26 02:23:05 2006 +0000
+++ b/lispref/ChangeLog	Wed Feb 01 10:07:17 2006 +0000
@@ -1,3 +1,18 @@
+2006-01-29  Chong Yidong  <cyd@stupidchicken.com>
+
+	* display.texi (Other Display Specs, Image Descriptors): Image
+	description is a list, not a cons cell.
+
+2006-01-28  Luc Teirlinck  <teirllm@auburn.edu>
+
+	* lists.texi (Cons Cells): Minor correction (the cdr of a dotted
+	list is not necessarily a list).
+
+2006-01-27  Eli Zaretskii  <eliz@gnu.org>
+
+	* frames.texi (Layout Parameters): border-width and
+	internal-border-width belong to the frame, not the window.
+
 2006-01-19  Richard M. Stallman  <rms@gnu.org>
 
 	* nonascii.texi (Translation of Characters): Search cmds use
--- a/lispref/display.texi	Thu Jan 26 02:23:05 2006 +0000
+++ b/lispref/display.texi	Wed Feb 01 10:07:17 2006 +0000
@@ -3280,7 +3280,7 @@
 Recursive display specifications are not supported---@var{string}'s
 @code{display} properties, if any, are not used.
 
-@item (image . @var{image-props})
+@item (image @var{image-props})
 This kind of display specification is an image descriptor (@pxref{Images}).
 When used as a display specification, it means to display the image
 instead of the text that has the display specification.
@@ -3508,7 +3508,7 @@
 @cindex image descriptor
 
   An image description is a list of the form @code{(image
-. @var{props})}, where @var{props} is a property list containing
+@var{props})}, where @var{props} is a property list containing
 alternating keyword symbols (symbols whose names start with a colon) and
 their values.  You can use any Lisp object as a property, but the only
 properties that have any special meaning are certain symbols, all of
--- a/lispref/frames.texi	Thu Jan 26 02:23:05 2006 +0000
+++ b/lispref/frames.texi	Wed Feb 01 10:07:17 2006 +0000
@@ -466,10 +466,10 @@
 
 @table @code
 @item border-width
-The width in pixels of the window border.
+The width in pixels of the frame's border.
 
 @item internal-border-width
-The distance in pixels between text and border.
+The distance in pixels between text and the frame's border.
 
 @item vertical-scroll-bars
 Whether the frame has scroll bars for vertical scrolling, and which side
--- a/lispref/lists.texi	Thu Jan 26 02:23:05 2006 +0000
+++ b/lispref/lists.texi	Wed Feb 01 10:07:17 2006 +0000
@@ -82,7 +82,7 @@
 @dfn{list structure} has come to mean any structure made out of cons
 cells.
 
-  The @sc{cdr} of any nonempty list @var{l} is a list containing all the
+  The @sc{cdr} of any nonempty true list @var{l} is a list containing all the
 elements of @var{l} except the first.
 
   @xref{Cons Cell Type}, for the read and print syntax of cons cells and
--- a/man/ChangeLog	Thu Jan 26 02:23:05 2006 +0000
+++ b/man/ChangeLog	Wed Feb 01 10:07:17 2006 +0000
@@ -1,3 +1,136 @@
+2006-01-31  Romain Francoise  <romain@orebokech.com>
+
+	* message.texi (Message Headers): Explain what
+	`message-alternative-emails' does in more detail.
+	Update copyright year.
+
+2006-01-31  Richard M. Stallman  <rms@gnu.org>
+
+	* display.texi (Scrolling, Horizontal Scrolling, Follow Mode):
+	Nodes moved to top.
+
+	* display.texi: Minor clarifications.
+	(Display): Rearrange menu.
+	(Standard Faces): Mention query-replace face.
+	(Faces): Simplify.
+	(Font Lock): Simplify face customization info.
+	(Highlight Changes): Node merged into Highlight Interactively.
+	(Highlight Interactively): Much rewriting and cleanup.
+	(Optional Mode Line): Narrowed line number not good for goto-line.
+	Simplify face customization advice.
+	(Text Display): Mention use of escape-glyph face.
+	Move ctl-arrow and tab-width here.
+	(Display Custom): Move no-redraw-on-reenter to end of node.
+
+	* search.texi: Minor clarifications.
+	(Isearch Scroll): Simplify.
+	(Other Repeating Search): Document multi-occur-in-matching-buffers.
+
+	* regs.texi (Registers): Mention bookmarks here.
+
+	* mark.texi: Minor clarifications.
+	(Selective Undo): Node deleted.
+
+	* m-x.texi: Minor clarifications
+
+	* killing.texi: Minor clarifications.
+	Refer to "graphical" terminals, rather than window systems.
+
+	* help.texi: Clarifications.
+	(Help): Don't describe C-h F and C-h K here.
+	(Key Help): Describe C-h K here.
+	(Name Help): Mention Emacs Lisp Intro.
+	Describe C-h F here.
+	(Misc Help): Mention C-h F and C-h K only briefly.
+
+	* fixit.texi (Undo): New node, mostly copied from basic.texi.
+	Selective undo text merged in.
+	(Spelling): Mention Aspell along with Ispell.
+
+	* emacs.texi (Top): Update subnode menus.
+
+	* basic.texi (Basic Undo): Renamed from Undo.  Most of text
+	moved to new Undo node.
+
+2006-01-30  Juanma Barranquero  <lekktu@gmail.com>
+
+	* makefile.w32-in (clean): Add newsticker, sieve, pgg, erc and
+	rcirc.
+
+2006-01-29  Chong Yidong  <cyd@stupidchicken.com>
+
+	* basic.texi (Continuation Lines, Inserting Text): Mention
+	longlines mode.
+
+2006-01-29  Richard M. Stallman  <rms@gnu.org>
+
+	* screen.texi: Minor cleaups.
+	(Screen): Clean up the intro paragraphs.
+	(Mode Line): Lots of rewriting.  Handle frame-name better.
+	eol-mnemonic-... vars moved out.
+
+	* emacs.texi (Top): Change menu item for MS-DOS node.
+	Update subnode menu.
+
+	* msdog.texi (MS-DOS): Rewrite intro to explain how this
+	chapter relates to Windows.  Title changed.
+
+	* mini.texi: Minor cleanups.
+
+	* mark.texi (Selective Undo): New node, text moved from basic.texi.
+	(Mark): Put it in the menu.
+
+	* entering.texi: Minor cleanups.
+
+	* emacs.texi (Top): Add xref to Mac chapter; explain Windows better.
+	(Intro): Refer to "graphical" terminals, rather than X.
+
+	* display.texi (Display Custom): Add xref to Variables.
+	(Optional Mode Line): eol-mnemonic-... vars moved here.
+
+	* commands.texi: Minor cleanups.  Refer to "graphical" terminals,
+	rather than X.
+
+	* cc-mode.texi (Indentation Commands): Inserts newline, not "linefeed".
+
+	* basic.texi: Minor cleanups.
+	(Undo): selective-undo moved.
+
+2006-01-29  Michael Olson  <mwolson@gnu.org>
+
+	* makefile.w32-in ($(infodir)/erc, erc.dvi): New targets.
+
+	* Makefile.in (INFO_TARGETS, DVI_TARGETS): Add ERC.
+
+	* faq.texi (New in Emacs 22): Mention ERC.
+
+2006-01-28  Luc Teirlinck  <teirllm@auburn.edu>
+
+	* rcirc.texi: Capitalize dir entry for consistency with the entry
+	in info/dir and other entries in the Emacs category.
+	Fix typos.  Delete trailing whitespace.
+
+2006-01-28  Bj,Av(Brn Lindstr,Av(Bm  <bkhl@elektrubadur.se>
+
+	* rcirc.texi: Some @cindex changes, some changes from @kbd to
+	@key.
+
+2006-01-27  Eli Zaretskii  <eliz@gnu.org>
+
+	* makefile.w32-in ($(infodir)/rcirc, rcirc.dvi): New targets.
+	(INFO_TARGETS, DVI_TARGETS): Add rcirc.
+
+	* Makefile.in (../info/rcirc, rcirc.dvi): New targets.
+	(INFO_TARGETS, DVI_TARGETS): Add rcirc.
+
+2006-01-27  Alex Schroeder  <alex@gnu.org>
+
+	* rcirc.texi: New file.
+
+2006-01-25  Luc Teirlinck  <teirllm@auburn.edu>
+
+	* anti.texi (Antinews): Various corrections and additions.
+
 2006-01-23  Juri Linkov  <juri@jurta.org>
 
 	* custom.texi (Easy Customization, Customization Groups)
@@ -23,9 +156,9 @@
 
 	* ses.texi (Formulas, Printer functions): Use @key for TAB.
 
-	* kmacro.texi (Keyboard Macro Step-Edit): : Use @key for TAB.
-
-	* ebrowse.texi (Switching to Tree, Symbol Completion): : Use @key
+	* kmacro.texi (Keyboard Macro Step-Edit): Use @key for TAB.
+
+	* ebrowse.texi (Switching to Tree, Symbol Completion): Use @key
 	for TAB.
 
 	* cc-mode.texi (Indentation Calculation): Use @key for TAB.
@@ -68,7 +201,7 @@
 
 2006-01-13  Carsten Dominik  <dominik@science.uva.nl>
 
-	* org.texi: (Agenda commands): Document tags command.
+	* org.texi (Agenda commands): Document tags command.
 
 2006-01-11  Luc Teirlinck  <teirllm@auburn.edu>
 
@@ -539,7 +672,7 @@
 
 2005-11-01  Katsumi Yamaoka  <yamaoka@jpl.org>
 
-	* gnus.texi (Group Parameters): Mention new varable
+	* gnus.texi (Group Parameters): Mention new variable
 	gnus-parameters-case-fold-search.
 	(Home Score File): Addition.
 
--- a/man/Makefile.in	Thu Jan 26 02:23:05 2006 +0000
+++ b/man/Makefile.in	Wed Feb 01 10:07:17 2006 +0000
@@ -42,7 +42,7 @@
 		../info/idlwave ../info/eudc ../info/ebrowse ../info/pcl-cvs \
 		../info/woman ../info/eshell ../info/org ../info/url \
 		../info/speedbar ../info/tramp ../info/ses ../info/smtpmail \
-		../info/flymake ../info/newsticker
+		../info/flymake ../info/newsticker ../info/rcirc ../info/erc
 DVI_TARGETS = 	emacs.dvi calc.dvi cc-mode.dvi cl.dvi dired-x.dvi \
 		 ediff.dvi forms.dvi gnus.dvi message.dvi emacs-mime.dvi \
                  gnus.dvi message.dvi sieve.dvi pgg.dvi mh-e.dvi \
@@ -50,7 +50,7 @@
 		 ada-mode.dvi autotype.dvi idlwave.dvi eudc.dvi ebrowse.dvi \
 		 pcl-cvs.dvi woman.dvi eshell.dvi org.dvi url.dvi \
 		 speedbar.dvi tramp.dvi ses.dvi smtpmail.dvi flymake.dvi \
-                 newsticker.dvi emacs-xtra.dvi
+                 newsticker.dvi emacs-xtra.dvi rcirc.dvi erc.dvi
 INFOSOURCES = info.texi
 
 # The following rule does not work with all versions of `make'.
@@ -327,6 +327,16 @@
 newsticker.dvi: newsticker.texi
 	$(ENVADD) $(TEXI2DVI) ${srcdir}/newsticker.texi
 
+../info/rcirc: rcirc.texi
+	cd $(srcdir); $(MAKEINFO) rcirc.texi
+rcirc.dvi: rcirc.texi
+	$(ENVADD) $(TEXI2DVI) ${srcdir}/rcirc.texi
+
+../info/erc: erc.texi
+	cd $(srcdir); $(MAKEINFO) erc.texi
+erc.dvi: erc.texi
+	$(ENVADD) $(TEXI2DVI) ${srcdir}/erc.texi
+
 mostlyclean:
 	rm -f *.log *.cp *.fn *.ky *.pg *.vr core *.tp *.core gnustmp.*
 
--- a/man/anti.texi	Thu Jan 26 02:23:05 2006 +0000
+++ b/man/anti.texi	Wed Feb 01 10:07:17 2006 +0000
@@ -34,9 +34,9 @@
 onto an Emacs window, nothing will happen.
 
 @item
-On an xterm, Emacs provides a more convincing simulation of a text
-terminal by not responding to mouse-clicks on the mode-line,
-header-line, or display margin.
+On an xterm, even if you enable Xterm Mouse mode, Emacs provides a
+more convincing simulation of a text terminal by not responding to
+mouse clicks on the mode line, header line, or display margin.
 
 @item
 For simplicity, windows always have fringes.  We wouldn't want to
@@ -88,8 +88,8 @@
 the @code{setenv} command does not expand @samp{$} at all.
 
 @item
-Emacs will not query you if a command accumulates too much undo
-information.  If Emacs runs out of memory as a result, it will handle
+If a single command accumulates too much undo information, Emacs never
+discards it.  If Emacs runs out of memory as a result, it will handle
 this by crashing.
 
 @item
@@ -131,9 +131,7 @@
 equivalent to typing them once.  @kbd{M-h} ignores numeric arguments.
 
 @item
-If you want to repeat a jump to a previous mark, you should supply the
-prefix argument explicitly.  So, instead of typing @kbd{C-u C-SPC
-C-SPC C-SPC}, type @kbd{C-u C-SPC C-u C-SPC C-u C-SPC}.
+The user option @code{set-mark-command-repeat-pop} has been removed.
 
 @item
 @kbd{C-@key{SPC} C-@key{SPC}} has no special meaning--it just sets the
@@ -261,7 +259,8 @@
 The Kmacro package has been replaced with a simple and elegant
 keyboard macro system.  Use @kbd{C-x (} to start a new keyboard macro,
 @kbd{C-x )} to end the macro, and @kbd{C-x e} to execute the last
-macro.
+macro.  Use @kbd{M-x name-last-kbd-macro} to name the most recently
+defined macro.
 
 @item
 The Calc, CUA, GDB-UI, Ibuffer, Ido, Password, Printing, Reveal,
--- a/man/basic.texi	Thu Jan 26 02:23:05 2006 +0000
+++ b/man/basic.texi	Wed Feb 01 10:07:17 2006 +0000
@@ -21,7 +21,7 @@
 * Moving Point::        How to move the cursor to the place where you want to
 			  change something.
 * Erasing::	        Deleting and killing text.
-* Undo::	        Undoing recent changes in the text.
+* Basic Undo::	        Undoing recent changes in the text.
 * Files: Basic Files.   Visiting, creating, and saving files.
 * Help: Basic Help.     Asking what a character does.
 * Blank Lines::	        Commands to make or delete blank lines.
@@ -80,7 +80,8 @@
 
   Emacs can split lines automatically when they become too long, if you
 turn on a special minor mode called @dfn{Auto Fill} mode.
-@xref{Filling}, for how to use Auto Fill mode.
+@xref{Filling}, for how to use Auto Fill mode and other modes for
+@dfn{filling} text.
 
   If you prefer to have text characters replace (overwrite) existing
 text rather than shove it to the right, you can enable Overwrite mode,
@@ -154,9 +155,9 @@
 clicking the left mouse button where you want to move to.
 
   There are also control and meta characters for cursor motion.  Some
-are equivalent to the arrow keys (these date back to the days before
-terminals had arrow keys, and are usable on terminals which don't have
-them).  Others do more sophisticated things.
+are equivalent to the arrow keys (it is faster to use these control
+keys than move your hand over to the arrow keys).  Others do more
+sophisticated things.
 
 @kindex C-a
 @kindex C-e
@@ -282,8 +283,8 @@
 @item @key{DELETE}
 @itemx @key{BACKSPACE}
 One of these keys, whichever is the large key above the @key{RET} or
-@key{ENTER} key, deletes the character before point, like @key{DEL}.
-If that is @key{BACKSPACE}, and your keyboard also has @key{DELETE},
+@key{ENTER} key, deletes the character before point---it is @key{DEL}.
+If @key{BACKSPACE} is @key{DEL}, and your keyboard also has @key{DELETE},
 then @key{DELETE} deletes forwards, like @kbd{C-d}.
 @item C-k
 Kill to the end of the line (@code{kill-line}).
@@ -311,141 +312,56 @@
 
   @xref{Killing}, for more flexible ways of killing text.
 
-@node Undo
+@node Basic Undo
 @section Undoing Changes
-@cindex undo
-@cindex changes, undoing
 
-  You can undo all the recent changes in the buffer text, up to a
-certain point.  Each buffer records changes individually, and the undo
-command always applies to the current buffer.  Usually each editing
-command makes a separate entry in the undo records, but some commands
-such as @code{query-replace} make many entries, and very simple commands
-such as self-inserting characters are often grouped to make undoing less
-tedious.
+  Emacs records a list of changes made in the buffer text, so you can
+you can undo all the recent changes, as far as the records go.
+Usually each editing command makes a separate entry in the undo
+records, but sometimes an entry covers just part of a command, and
+very simple commands may be grouped.
 
 @table @kbd
 @item C-x u
-Undo one batch of changes---usually, one command worth (@code{undo}).
+Undo one entry of the undo records---usually, one command worth
+(@code{undo}).
 @item C-_
 @itemx C-/
 The same.
-@item C-u C-x u
-Undo one batch of changes in the region.
 @end table
 
-@kindex C-x u
-@kindex C-_
-@kindex C-/
-@findex undo
   The command @kbd{C-x u} (or @kbd{C-_} or @kbd{C-/}) is how you undo.
 The first time you give this command, it undoes the last change.
 Point moves back to where it was before the command that made the
 change.
 
-  Consecutive repetitions of @kbd{C-_} or @kbd{C-x u} undo earlier and
-earlier changes, back to the limit of the undo information available.
-If all recorded changes have already been undone, the undo command
-displays an error message and does nothing.
-
-@findex undo-only
-  Any command other than an undo command breaks the sequence of undo
-commands.  Starting from that moment, the previous undo commands become
-ordinary changes that you can undo.  Thus, to redo changes you have
-undone, type @kbd{C-f} or any other command that will harmlessly break
-the sequence of undoing, then type more undo commands.  On the other
-hand, if you want to ignore previous undo commands, use @kbd{M-x
-undo-only}.  This is like @code{undo}, but will not redo changes
-you have just undone.
-
-@cindex selective undo
-@kindex C-u C-x u
-  Ordinary undo applies to all changes made in the current buffer.  You
-can also perform @dfn{selective undo}, limited to the current region
-(@pxref{Mark}).
-To do this, specify the region you want, then run the @code{undo}
-command with a prefix argument (the value does not matter): @kbd{C-u C-x
-u} or @kbd{C-u C-_}.  This undoes the most recent change in the region.
-To undo further changes in the same region, repeat the @code{undo}
-command (no prefix argument is needed).  In Transient Mark mode
-(@pxref{Transient Mark}), any use of @code{undo} when there is an
-active region performs selective undo; you do not need a prefix
-argument.
-
-  If you notice that a buffer has been modified accidentally, the
-easiest way to recover is to type @kbd{C-_} repeatedly until the stars
-disappear from the front of the mode line.  At this time, all the
-modifications you made have been canceled.  Whenever an undo command
-makes the stars disappear from the mode line, it means that the buffer
-contents are the same as they were when the file was last read in or
-saved.
-
-  If you do not remember whether you changed the buffer deliberately,
-type @kbd{C-_} once.  When you see the last change you made undone, you
-will see whether it was an intentional change.  If it was an accident,
-leave it undone.  If it was deliberate, redo the change as described
-above.
+  Consecutive repetitions of @kbd{C-x u} (or its aliases) undo earlier
+and earlier changes, back to the limit of the undo information
+available.  If all recorded changes have already been undone, the undo
+command displays an error message and does nothing.
 
-  Not all buffers record undo information.  Buffers whose names start with
-spaces don't; these buffers are used internally by Emacs and its extensions
-to hold text that users don't normally look at or edit.
-
-  You cannot undo mere cursor motion; only changes in the buffer
-contents save undo information.  However, some cursor motion commands
-set the mark, so if you use these commands from time to time, you can
-move back to the neighborhoods you have moved through by popping the
-mark ring (@pxref{Mark Ring}).
-
-@vindex undo-limit
-@vindex undo-strong-limit
-@vindex undo-outer-limit
-@cindex undo limit
-  When the undo information for a buffer becomes too large, Emacs
-discards the oldest undo information from time to time (during garbage
-collection).  You can specify how much undo information to keep by
-setting three variables: @code{undo-limit}, @code{undo-strong-limit},
-and @code{undo-outer-limit}.  Their values are expressed in units of
-bytes of space.
-
-  The variable @code{undo-limit} sets a soft limit: Emacs keeps undo
-data for enough commands to reach this size, and perhaps exceed it,
-but does not keep data for any earlier commands beyond that.  Its
-default value is 20000.  The variable @code{undo-strong-limit} sets a
-stricter limit: a previous command (not the most recent one) which
-pushes the size past this amount is itself forgotten.  The default
-value of @code{undo-strong-limit} is 30000.
-
-  Regardless of the values of those variables, the most recent change
-is never discarded unless it gets bigger than @code{undo-outer-limit}
-(normally 3,000,000).  At that point, Emacs discards the undo data and
-warns you about it.  This is the only situation in which you cannot
-undo the last command.  If this happens, you can increase the value of
-@code{undo-outer-limit} to make it even less likely to happen in the
-future.  But if you didn't expect the command to create such large
-undo data, then it is probably a bug and you should report it.
-@xref{Bugs,, Reporting Bugs}.
-
-  The reason the @code{undo} command has three key bindings, @kbd{C-x
-u}, @kbd{C-_} and @kbd{C-/}, is that it is worthy of a
-single-character key, but @kbd{C-x u} is more straightforward for
-beginners to type.
+  The undo command applies only to changes in the buffer; you can't
+use it to undo mere cursor motion.  However, some cursor motion
+commands set the mark, so if you use these commands from time to time,
+you can move back to the neighborhoods you have moved through by
+popping the mark ring (@pxref{Mark Ring}).
 
 @node Basic Files
 @section Files
 
   The commands described above are sufficient for creating and altering
 text in an Emacs buffer; the more advanced Emacs commands just make
-things easier.  But to keep any text permanently you must put it in a
+things easier.  However, to keep any text permanently you must put it in a
 @dfn{file}.  Files are named units of text which are stored by the
 operating system for you to retrieve later by name.  To look at or use
 the contents of a file in any way, including editing the file with
 Emacs, you must specify the file name.
 
-  Consider a file named @file{/usr/rms/foo.c}.  In Emacs, to begin editing
-this file, type
+  Consider a file named @file{test.emacs}.  (We can assume it is in
+your home directory.)  In Emacs, to begin editing this file, type
 
 @example
-C-x C-f /usr/rms/foo.c @key{RET}
+C-x C-f test.emacs @key{RET}
 @end example
 
 @noindent
@@ -459,8 +375,8 @@
 the buffer for you to edit.  If you alter the text, you can @dfn{save}
 the new text in the file by typing @kbd{C-x C-s} (@code{save-buffer}).
 This makes the changes permanent by copying the altered buffer contents
-back into the file @file{/usr/rms/foo.c}.  Until you save, the changes
-exist only inside Emacs, and the file @file{foo.c} is unaltered.
+back into the file @file{test.emacs}.  Until you save, the changes
+exist only inside Emacs, and the file @file{test.emacs} is unaltered.
 
   To create a file, just visit the file with @kbd{C-x C-f} as if it
 already existed.  This creates an empty buffer in which you can insert
@@ -549,17 +465,20 @@
 characters in the ``empty'' columns, just before the @samp{\}
 character that indicates continuation.
 
-  Sometimes it is nice to have Emacs insert newlines automatically when
-a line gets too long.  Continuation on the screen does not do that.  Use
-Auto Fill mode (@pxref{Filling}) if that's what you want.
+  Continued lines can be rather difficult to read, since each line is
+typically broken in the middle of a word.  You can have Emacs insert a
+newline automatically when a line gets too long, by using Auto Fill
+mode.  Another approach, intermediate between continued lines and Auto
+Fill mode, is Long Lines mode, which ensures that wrapping only occurs
+in the spaces between words.  @xref{Filling}.
 
 @cindex truncation
 @cindex line truncation, and fringes
-  As an alternative to continuation, Emacs can display long lines by
-@dfn{truncation}.  This means that all the characters that do not fit
-in the width of the screen or window do not appear at all.  @samp{$}
-in the last column or a small straight arrow in the fringe to the
-right of the window indicates a truncated line.
+  Emacs can also display long lines by @dfn{truncation}.  This means
+that all the characters that do not fit in the width of the screen or
+window do not appear at all.  @samp{$} in the last column or a small
+straight arrow in the fringe to the right of the window indicates a
+truncated line.
 
   @xref{Display Custom}, for more information about line truncation,
 and other variables that affect how text is displayed.
@@ -777,15 +696,14 @@
 negative argument, type a minus sign after @kbd{C-u}.  Just a minus sign
 without digits normally means @minus{}1.
 
-  @kbd{C-u} followed by a character which is neither a digit nor a minus
-sign has the special meaning of ``multiply by four.''  It multiplies the
-argument for the next command by four.  @kbd{C-u} twice multiplies it by
-sixteen.  Thus, @kbd{C-u C-u C-f} moves forward sixteen characters.  This
-is a good way to move forward ``fast,'' since it moves about 1/5 of a line
-in the usual size screen.  Other useful combinations are @kbd{C-u C-n},
-@kbd{C-u C-u C-n} (move down a good fraction of a screen), @kbd{C-u C-u
-C-o} (make ``a lot'' of blank lines), and @kbd{C-u C-k} (kill four
-lines).@refill
+  @kbd{C-u} without digits or minus sign has the special meaning of
+``four times'': it multiplies the argument for the next command by
+four.  @kbd{C-u C-u} multiplies it by sixteen.  Thus, @kbd{C-u C-u
+C-f} moves forward sixteen characters.  This is a good way to move
+forward ``fast,'' since it moves about 1/5 of a line in the usual size
+screen.  Other useful combinations are @kbd{C-u C-n}, @kbd{C-u C-u
+C-n} (move down a good fraction of a screen), @kbd{C-u C-u C-o} (make
+``a lot'' of blank lines), and @kbd{C-u C-k} (kill four lines).@refill
 
   Some commands care only about whether there is an argument, and not about
 its value.  For example, the command @kbd{M-q} (@code{fill-paragraph}) with
--- a/man/cc-mode.texi	Thu Jan 26 02:23:05 2006 +0000
+++ b/man/cc-mode.texi	Wed Feb 01 10:07:17 2006 +0000
@@ -750,7 +750,7 @@
 @item @kbd{C-j} (@code{newline-and-indent})
 @kindex C-j
 @findex newline-and-indent
-Inserts a linefeed and indents the new blank line, ready to start
+Inserts a newline and indents the new blank line, ready to start
 typing.  This is a standard (X)Emacs command.
 
 @item @kbd{C-M-q} (@code{c-indent-exp})
--- a/man/commands.texi	Thu Jan 26 02:23:05 2006 +0000
+++ b/man/commands.texi	Wed Feb 01 10:07:17 2006 +0000
@@ -39,8 +39,7 @@
 have special keys you can type them with: for example, @key{RET},
 @key{TAB}, @key{DEL} and @key{ESC}.  The space character is usually
 referred to below as @key{SPC}, even though strictly speaking it is a
-graphic character whose graphic happens to be blank.  Some keyboards
-have a key labeled ``linefeed'' which is an alias for @kbd{C-j}.
+graphic character whose graphic happens to be blank.
 
   Emacs extends the @acronym{ASCII} character set with thousands more printing
 characters (@pxref{International}), additional control characters, and a
@@ -54,31 +53,28 @@
 
   But the Emacs character set has room for control variants of all
 printing characters, and for distinguishing between @kbd{C-a} and
-@kbd{C-A}.  The X Window System makes it possible to enter all these
-characters.  For example, @kbd{C--} (that's Control-Minus) and @kbd{C-5}
-are meaningful Emacs commands under X.
+@kbd{C-A}.  Graphical terminals make it possible to enter all these
+characters.  For example, @kbd{C--} (that's Control-Minus) and
+@kbd{C-5} are meaningful Emacs commands on a graphical terminal.
 
   Another Emacs character-set extension is additional modifier bits.
 Only one modifier bit is commonly used; it is called Meta.  Every
 character has a Meta variant; examples include @kbd{Meta-a} (normally
-written @kbd{M-a}, for short), @kbd{M-A} (not the same character as
-@kbd{M-a}, but those two characters normally have the same meaning in
-Emacs), @kbd{M-@key{RET}}, and @kbd{M-C-a}.  For reasons of tradition,
-we usually write @kbd{C-M-a} rather than @kbd{M-C-a}; logically
-speaking, the order in which the modifier keys @key{CTRL} and @key{META}
-are mentioned does not matter.
+written @kbd{M-a}, for short), @kbd{M-A} (different from @kbd{M-a},
+but they are normally equivalent in Emacs), @kbd{M-@key{RET}}, and
+@kbd{M-C-a}.  That last means @kbd{a} with both the @key{CTRL} and
+@key{META} modifiers.  We usually write it as @kbd{C-M-a} rather than
+@kbd{M-C-a}, for reasons of tradition.
 
 @cindex Meta
 @cindex M-
 @cindex @key{ESC} replacing @key{META} key
   Some terminals have a @key{META} key, and allow you to type Meta
-characters by holding this key down.  Thus, @kbd{Meta-a} is typed by
-holding down @key{META} and pressing @kbd{a}.  The @key{META} key
-works much like the @key{SHIFT} key.  Such a key is not always labeled
-@key{META}, however, as this function is often a special option for a
-key with some other primary purpose.  Sometimes it is labeled
-@key{ALT} or @key{EDIT}; on a Sun keyboard, it may have a diamond on
-it.
+characters by holding this key down.  Thus, you can type @kbd{Meta-a}
+by holding down @key{META} and pressing @kbd{a}.  The @key{META} key
+works much like the @key{SHIFT} key.  In fact, this key is more often
+labeled @key{ALT} or @key{EDIT}, instead of @key{META}; on a Sun
+keyboard, it may have a diamond on it.
 
   If there is no @key{META} key, you can still type Meta characters
 using two-character sequences starting with @key{ESC}.  Thus, you can
@@ -90,16 +86,16 @@
 @key{ESC} is allowed on terminals with @key{META} keys, too, in case
 you have formed a habit of using it.
 
-  The X Window System provides several other modifier keys that can be
-applied to any input character.  These are called @key{SUPER},
-@key{HYPER} and @key{ALT}.  We write @samp{s-}, @samp{H-} and @samp{A-}
-to say that a character uses these modifiers.  Thus, @kbd{s-H-C-x} is
-short for @kbd{Super-Hyper-Control-x}.  Not all X terminals actually
+  Emacs defines several other modifier keys that can be applied to any
+input character.  These are called @key{SUPER}, @key{HYPER} and
+@key{ALT}.  We write @samp{s-}, @samp{H-} and @samp{A-} to say that a
+character uses these modifiers.  Thus, @kbd{s-H-C-x} is short for
+@kbd{Super-Hyper-Control-x}.  Not all graphical terminals actually
 provide keys for these modifier flags---in fact, many terminals have a
 key labeled @key{ALT} which is really a @key{META} key.  The standard
 key bindings of Emacs do not include any characters with these
-modifiers.  But you can assign them meanings of your own by customizing
-Emacs.
+modifiers.  But you can assign them meanings of your own by
+customizing Emacs.
 
   If your keyboard lacks one of these modifier keys, you can enter it
 using @kbd{C-x @@}: @kbd{C-x @@ h} adds the ``hyper'' flag to the next
@@ -109,18 +105,18 @@
 two modifiers by using @kbd{C-x @@} twice for the same character,
 because the first one goes to work on the @kbd{C-x}.)
 
-  Keyboard input includes keyboard keys that are not characters at all:
-for example function keys and arrow keys.  Mouse buttons are also
-outside the gamut of characters.  You can modify these events with the
-modifier keys @key{CTRL}, @key{META}, @key{SUPER}, @key{HYPER} and
-@key{ALT}, just like keyboard characters.
+  Keyboard input includes keyboard keys that are not characters at
+all: for example function keys and arrow keys.  Mouse buttons are also
+outside the gamut of characters.  However, you can modify these events
+with the modifier keys @key{CTRL}, @key{META}, @key{SUPER},
+@key{HYPER} and @key{ALT}, just as you can modify keyboard characters.
 
 @cindex input event
   Input characters and non-character inputs are collectively called
 @dfn{input events}.  @xref{Input Events,,, elisp, The Emacs Lisp
-Reference Manual}, for more information.  If you are not doing Lisp
-programming, but simply want to redefine the meaning of some characters
-or non-character events, see @ref{Customization}.
+Reference Manual}, for the full Lisp-level details.  If you are not
+doing Lisp programming, but simply want to redefine the meaning of
+some characters or non-character events, see @ref{Customization}.
 
   @acronym{ASCII} terminals cannot really send anything to the computer except
 @acronym{ASCII} characters.  These terminals use a sequence of characters to
@@ -170,12 +166,12 @@
 
   All told, the prefix keys in Emacs are @kbd{C-c}, @kbd{C-h},
 @kbd{C-x}, @kbd{C-x @key{RET}}, @kbd{C-x @@}, @kbd{C-x a}, @kbd{C-x
-n}, @w{@kbd{C-x r}}, @kbd{C-x v}, @kbd{C-x 4}, @kbd{C-x 5}, @kbd{C-x 6},
-@key{ESC}, @kbd{M-o} and @kbd{M-g}.  (@key{F1} and @key{F2} are aliases for
-@kbd{C-h} and @kbd{C-x 6}.)  But this list is not cast in concrete; it
-is just a matter of Emacs's standard key bindings.  If you customize
-Emacs, you can make new prefix keys, or eliminate these.  @xref{Key
-Bindings}.
+n}, @w{@kbd{C-x r}}, @kbd{C-x v}, @kbd{C-x 4}, @kbd{C-x 5}, @kbd{C-x
+6}, @key{ESC}, @kbd{M-g}, and @kbd{M-o}.  (@key{F1} and @key{F2} are
+aliases for @kbd{C-h} and @kbd{C-x 6}.)  But this list is not cast in
+concrete; it is just a matter of Emacs's standard key bindings.  If
+you customize Emacs, you can make new prefix keys, or eliminate some
+of the standard ones.  @xref{Key Bindings}.
 
   If you do make or eliminate prefix keys, that changes the set of
 possible key sequences.  For example, if you redefine @kbd{C-f} as a
@@ -184,12 +180,11 @@
 definition of @kbd{C-x 4}, then @kbd{C-x 4 f} (or @kbd{C-x 4
 @var{anything}}) is no longer a key.
 
-  Typing the help character (@kbd{C-h} or @key{F1}) after a prefix
-key displays a list of the commands starting with that prefix.
-There are a few prefix keys for which @kbd{C-h} does not
-work---for historical reasons, they have other meanings for @kbd{C-h}
-which are not easy to change.  But @key{F1} should work for all prefix
-keys.
+  Typing the help character (@kbd{C-h} or @key{F1}) after a prefix key
+displays a list of the commands starting with that prefix.  There are
+a few prefix keys for which @kbd{C-h} does not work---for historical
+reasons, they define other meanings for @kbd{C-h} which are painful to
+change.  But @key{F1} should work for all prefix keys.
 
 @node Commands, Text Characters, Keys, Top
 @section Keys and Commands
--- a/man/display.texi	Thu Jan 26 02:23:05 2006 +0000
+++ b/man/display.texi	Wed Feb 01 10:07:17 2006 +0000
@@ -11,16 +11,15 @@
 display it.
 
 @menu
+* Scrolling::	           Moving text up and down in a window.
+* Horizontal Scrolling::   Moving text left and right in a window.
+* Follow Mode::            Follow mode lets two windows scroll as one.
 * Faces::	           How to change the display style using faces.
 * Standard Faces::         Emacs' predefined faces.
 * Font Lock::              Minor mode for syntactic highlighting using faces.
 * Highlight Interactively:: Tell Emacs what text to highlight.
-* Highlight Changes::      Using colors to show where you changed the buffer.
-* Scrolling::	           Moving text up and down in a window.
-* Horizontal Scrolling::   Moving text left and right in a window.
 * Fringes::                Enabling or disabling window fringes.
 * Useless Whitespace::     Showing possibly-spurious trailing whitespace.
-* Follow Mode::            Follow mode lets two windows scroll as one.
 * Selective Display::      Hiding lines with lots of indentation.
 * Optional Mode Line::     Optional mode line display features.
 * Text Display::           How text characters are normally displayed.
@@ -28,458 +27,6 @@
 * Display Custom::         Information on variables for customizing display.
 @end menu
 
-@node Faces
-@section Using Multiple Typefaces
-@cindex faces
-
-  You can specify various styles for displaying text using
-@dfn{faces}.  Each face can specify various @dfn{face attributes},
-such as the font family, the height, weight and slant of the
-characters, the foreground and background color, and underlining or
-overlining.  A face does not have to specify all of these attributes;
-often it inherits most of them from another face.
-
-  On a window system, all the Emacs face attributes are meaningful.
-On a character terminal, only some of them work.  Some character
-terminals support inverse video, bold, and underline attributes; some
-support colors.  Character terminals generally do not support changing
-the height and width or the font family.
-
-  The easiest way to use faces is to turn on Font Lock mode.
-@xref{Font Lock}, for more information about Font Lock mode and
-syntactic highlighting.  You can print out the buffer with the
-highlighting that appears on your screen using the command
-@code{ps-print-buffer-with-faces}.  @xref{PostScript}.
-
-  Features which rely on text in multiple faces (such as Font Lock mode)
-will also work on non-windowed terminals that can display more than one
-face, whether by colors or underlining and emboldening.  This includes
-the console on GNU/Linux, an @code{xterm} which supports colors, the
-MS-DOS display (@pxref{MS-DOS}), and the MS-Windows version invoked with
-the @option{-nw} option.  Emacs determines automatically whether the
-terminal has this capability.
-
-  You control the appearance of a part of the text in the buffer by
-specifying the face or faces to use for it.  The style of display used
-for any given character is determined by combining the attributes of
-all the applicable faces specified for that character.  Any attribute
-that isn't specified by these faces is taken from the @code{default} face,
-whose attributes reflect the default settings of the frame itself.
-
-  Enriched mode, the mode for editing formatted text, includes several
-commands and menus for specifying faces for text in the buffer.
-@xref{Format Faces}, for how to specify the font for text in the
-buffer.  @xref{Format Colors}, for how to specify the foreground and
-background color.
-
-@cindex face colors, setting
-@findex set-face-foreground
-@findex set-face-background
-  To alter the appearance of a face, use the customization buffer.
-@xref{Face Customization}.  You can also use X resources to specify
-attributes of particular faces (@pxref{Resources}).  Alternatively,
-you can change the foreground and background colors of a specific face
-with @kbd{M-x set-face-foreground} and @kbd{M-x set-face-background}.
-These commands prompt in the minibuffer for a face name and a color
-name, with completion, and then set that face to use the specified
-color.  Changing the colors of the @code{default} face also changes
-the foreground and background colors on all frames, both existing and
-those to be created in the future.  (You can also set foreground and
-background colors for the current frame only; see @ref{Frame
-Parameters}.)
-
-  Emacs can correctly display variable-width fonts, but Emacs commands
-that calculate width and indentation do not know how to calculate
-variable widths.  This can sometimes lead to incorrect results when
-you use variable-width fonts.  In particular, indentation commands can
-give inconsistent results, so we recommend you avoid variable-width
-fonts for editing program source code.  Filling will sometimes make
-lines too long or too short.  We plan to address these issues in
-future Emacs versions.
-
-@node Standard Faces
-@section Standard Faces
-
-@findex list-faces-display
-  To see what faces are currently defined, and what they look like,
-type @kbd{M-x list-faces-display}.  It's possible for a given face to
-look different in different frames; this command shows the appearance
-in the frame in which you type it.
-
-Here are the standard faces for specifying text appearance.  You can
-use them on specific text, when you want the effects they produce.
-
-@table @code
-@item default
-This face is used for ordinary text that doesn't specify any other face.
-@item bold
-This face uses a bold variant of the default font, if it has one.
-It's up to you to choose a default font that has a bold variant,
-if you want to use one.
-@item italic
-This face uses an italic variant of the default font, if it has one.
-@item bold-italic
-This face uses a bold italic variant of the default font, if it has one.
-@item underline
-This face underlines text.
-@item fixed-pitch
-This face forces use of a particular fixed-width font.
-@item variable-pitch
-This face forces use of a particular variable-width font.  It's
-reasonable to customize this to use a different variable-width font,
-if you like, but you should not make it a fixed-width font.
-@item shadow
-This face is used for making the text less noticeable than the surrounding
-ordinary text.  Usually this can be achieved by using shades of gray in
-contrast with either black or white default foreground color.
-@end table
-
-  Here's an incomplete list of faces used to highlight parts of the
-text temporarily for specific purposes.  (Many other modes define
-their own faces for this purpose.)
-
-@table @code
-@item highlight
-This face is used for highlighting portions of text, in various modes.
-For example, mouse-sensitive text is highlighted using this face.
-@item isearch
-This face is used for highlighting Isearch matches.
-@item lazy-highlight
-This face is used for lazy highlighting of Isearch and Query Replace
-matches other than the current one.
-@item region
-This face is used for displaying a selected region (when Transient Mark
-mode is enabled---see below).
-@item secondary-selection
-This face is used for displaying a secondary X selection (@pxref{Secondary
-Selection}).
-@item trailing-whitespace
-The face for highlighting excess spaces and tabs at the end of a line
-when @code{show-trailing-whitespace} is non-@code{nil}; see
-@ref{Useless Whitespace}.
-@item nobreak-space
-The face for displaying the character ``nobreak space''.
-@item escape-glyph
-The face for highlighting the @samp{\} or @samp{^} that indicates
-a control character.  It's also used when @samp{\} indicates a
-nobreak space or nobreak (soft) hyphen.
-@end table
-
-@cindex @code{region} face
-  When Transient Mark mode is enabled, the text of the region is
-highlighted when the mark is active.  This uses the face named
-@code{region}; you can control the style of highlighting by changing the
-style of this face (@pxref{Face Customization}).  @xref{Transient Mark},
-for more information about Transient Mark mode and activation and
-deactivation of the mark.
-
-  These faces control the appearance of parts of the Emacs frame.
-They exist as faces to provide a consistent way to customize the
-appearance of these parts of the frame.
-
-@table @code
-@item mode-line
-@itemx modeline
-This face is used for the mode line of the currently selected window,
-and for menu bars when toolkit menus are not used.  By default, it's
-drawn with shadows for a ``raised'' effect on window systems, and
-drawn as the inverse of the default face on non-windowed terminals.
-@code{modeline} is an alias for the @code{mode-line} face, for
-compatibility with old Emacs versions.
-@item mode-line-inactive
-Like @code{mode-line}, but used for mode lines of the windows other
-than the selected one (if @code{mode-line-in-non-selected-windows} is
-non-@code{nil}).  This face inherits from @code{mode-line}, so changes
-in that face affect mode lines in all windows.
-@item mode-line-highlight
-Like @code{highlight}, but used for portions of text on mode lines.
-@item mode-line-buffer-id
-This face is used for buffer identification parts in the mode line.
-@item header-line
-Similar to @code{mode-line} for a window's header line.  Most modes
-don't use the header line, but some special modes, such the Info mode, do.
-@item vertical-border
-This face is used for the vertical divider between windows.
-By default this face inherits from the @code{mode-line-inactive} face
-on character terminals.  On window systems the foreground color of
-this face is used for the vertical line between windows without
-scrollbars.
-@item minibuffer-prompt
-@cindex @code{minibuffer-prompt} face
-@vindex minibuffer-prompt-properties
-This face is used for the prompt strings displayed in the minibuffer.
-By default, Emacs automatically adds this face to the value of
-@code{minibuffer-prompt-properties}, which is a list of text
-properties used to display the prompt text.
-@item fringe
-@cindex @code{fringe} face
-The face for the fringes to the left and right of windows on graphic
-displays.  (The fringes are the narrow portions of the Emacs frame
-between the text area and the window's right and left borders.)
-@xref{Fringes}.
-@item scroll-bar
-This face determines the visual appearance of the scroll bar.
-@xref{Scroll Bars}.
-@item border
-This face determines the color of the frame border.
-@item cursor
-This face determines the color of the cursor.
-@item mouse
-This face determines the color of the mouse pointer.
-@item tool-bar
-This is the basic tool-bar face.  No text appears in the tool bar, but the
-colors of this face affect the appearance of tool bar icons.  @xref{Tool Bars}.
-@item tooltip
-This face is used for tooltips.  @xref{Tooltips}.
-@item menu
-@cindex menu bar appearance
-@cindex @code{menu} face, no effect if customized
-@cindex customization of @code{menu} face
-This face determines the colors and font of Emacs's menus.  @xref{Menu
-Bars}.  Setting the font of LessTif/Motif menus is currently not
-supported; attempts to set the font are ignored in this case.
-Likewise, attempts to customize this face in Emacs built with GTK and
-in the MS-Windows port are ignored by the respective GUI toolkits;
-you need to use system-wide styles and options to change the
-appearance of the menus.
-@end table
-
-@node Font Lock
-@section Font Lock mode
-@cindex Font Lock mode
-@cindex mode, Font Lock
-@cindex syntax highlighting and coloring
-
-  Font Lock mode is a minor mode, always local to a particular buffer,
-which highlights (or ``fontifies'') the buffer contents according to
-the syntax of the text you are editing.  It can recognize comments and
-strings in most languages; in several languages, it can also recognize
-and properly highlight various other important constructs---for
-example, names of functions being defined or reserved keywords.
-Some special modes, such as Occur mode and Info mode, have completely
-specialized ways of assigning fonts for Font Lock mode.
-
-@findex font-lock-mode
-  Font Lock mode is turned on by default in all modes which support it.
-You can toggle font-lock for each buffer with the command @kbd{M-x
-font-lock-mode}.  Using a positive argument unconditionally turns Font
-Lock mode on, and a negative or zero argument turns it off.
-
-@findex global-font-lock-mode
-@vindex global-font-lock-mode
-  If you do not wish Font Lock mode to be turned on by default,
-customize the variable @code{global-font-lock-mode} using the Customize
-interface (@pxref{Easy Customization}), or use the function
-@code{global-font-lock-mode} in your @file{.emacs} file, like this:
-
-@example
-(global-font-lock-mode 0)
-@end example
-
-@findex turn-on-font-lock
-  If you have disabled Global Font Lock mode, you can still enable font
-lock for specific major modes by adding the function
-@code{turn-on-font-lock} to the mode hooks (@pxref{Hooks}).  For
-example, to enable Font Lock mode for editing C files, you can do this:
-
-@example
-(add-hook 'c-mode-hook 'turn-on-font-lock)
-@end example
-
-  Font Lock mode uses several specifically named faces to do its job,
-including @code{font-lock-string-face}, @code{font-lock-comment-face},
-and others.  The easiest way to find them all is to use
-@kbd{M-x customize-group @key{RET} font-lock-faces @key{RET}}.
-
-  To change the colors or the fonts used by Font Lock mode to fontify
-different parts of text, just change these faces.  There are
-two ways to do it:
-
-@itemize @bullet
-@item
-Invoke @kbd{M-x set-face-foreground} or @kbd{M-x set-face-background}
-to change the colors of a particular face used by Font Lock.
-@xref{Faces}.  The command @kbd{M-x list-faces-display} displays all
-the faces currently known to Emacs, including those used by Font Lock.
-
-@item
-Customize the faces interactively with @kbd{M-x customize-face}, as
-described in @ref{Face Customization}.
-@end itemize
-
-@vindex font-lock-maximum-decoration
-  The variable @code{font-lock-maximum-decoration} specifies the
-preferred level of fontification, for modes that provide multiple
-levels.  Level 1 is the least amount of fontification; some modes
-support levels as high as 3.  The normal default is ``as high as
-possible.''  You can specify an integer, which applies to all modes, or
-you can specify different numbers for particular major modes; for
-example, to use level 1 for C/C++ modes, and the default level
-otherwise, use this:
-
-@example
-(setq font-lock-maximum-decoration
-      '((c-mode . 1) (c++-mode . 1)))
-@end example
-
-@vindex font-lock-maximum-size
-  Fontification can be too slow for large buffers, so you can suppress
-it.  The variable @code{font-lock-maximum-size} specifies a buffer size,
-beyond which buffer fontification is suppressed.
-
-@c @w is used below to prevent a bad page-break.
-@vindex font-lock-beginning-of-syntax-function
-@cindex incorrect fontification
-@cindex parenthesis in column zero and fontification
-@cindex brace in column zero and fontification
-  Comment and string fontification (or ``syntactic'' fontification)
-relies on analysis of the syntactic structure of the buffer text.  For
-the sake of speed, some modes, including C mode and Lisp mode,
-rely on a special convention: an open-parenthesis or open-brace in the
-leftmost column always defines the @w{beginning} of a defun, and is
-thus always outside any string or comment.  (@xref{Left Margin
-Paren}.)  If you don't follow this convention, Font Lock mode can
-misfontify the text that follows an open-parenthesis or open-brace in
-the leftmost column that is inside a string or comment.
-
-@cindex slow display during scrolling
-  The variable @code{font-lock-beginning-of-syntax-function} (always
-buffer-local) specifies how Font Lock mode can find a position
-guaranteed to be outside any comment or string.  In modes which use the
-leftmost column parenthesis convention, the default value of the variable
-is @code{beginning-of-defun}---that tells Font Lock mode to use the
-convention.  If you set this variable to @code{nil}, Font Lock no longer
-relies on the convention.  This avoids incorrect results, but the price
-is that, in some cases, fontification for a changed text must rescan
-buffer text from the beginning of the buffer.  This can considerably
-slow down redisplay while scrolling, particularly if you are close to
-the end of a large buffer.
-
-@findex font-lock-add-keywords
-  Font Lock highlighting patterns already exist for many modes, but you
-may want to fontify additional patterns.  You can use the function
-@code{font-lock-add-keywords}, to add your own highlighting patterns for
-a particular mode.  For example, to highlight @samp{FIXME:} words in C
-comments, use this:
-
-@example
-(font-lock-add-keywords
- 'c-mode
- '(("\\<\\(FIXME\\):" 1 font-lock-warning-face t)))
-@end example
-
-@findex font-lock-remove-keywords
-  To remove keywords from the font-lock highlighting patterns, use the
-function @code{font-lock-remove-keywords}.  @xref{Search-based
-Fontification,,, elisp, The Emacs Lisp Reference Manual}, for
-documentation of the format of this list.
-
-@cindex just-in-time (JIT) font-lock
-@cindex background syntax highlighting
-  Fontifying large buffers can take a long time.  To avoid large
-delays when a file is visited, Emacs fontifies only the visible
-portion of a buffer.  As you scroll through the buffer, each portion
-that becomes visible is fontified as soon as it is displayed.  The
-parts of the buffer that are not displayed are fontified
-``stealthily,'' in the background, i.e.@: when Emacs is idle.  You can
-control this background fontification, also called @dfn{Just-In-Time}
-(or @dfn{JIT}) Lock, by customizing variables in the customization
-group @samp{jit-lock}.  @xref{Specific Customization}.
-
-@node Highlight Interactively
-@section Interactive Highlighting by Matching
-@cindex highlighting by matching
-@cindex interactive highlighting
-
-  It is sometimes useful to temporarily highlight text that
-matches a certain regular expression.  For example, you might wish to
-see all the references to a certain variable in a program source file,
-highlight certain parts in a voluminous output of some program, or
-make certain names stand out in an article.
-
-@findex hi-lock-mode
-  Use the @kbd{M-x hi-lock-mode} command to turn on a minor mode that
-allows you to interactively add and remove regular expressions
-specifying text to be highlighted.  Hi Lock mode works like Font Lock
-mode (@pxref{Font Lock}), except that it lets you easily add and
-remove regular expressions while you are editing a buffer.  To enable
-Hi Lock mode for all buffers use @kbd{M-x global-hi-lock-mode} or
-place @code{(global-hi-lock-mode 1)} in your @file{.emacs} file.
-
-You control Hi Lock mode with these commands:
-
-@table @kbd
-@item C-x w h @var{regexp} @key{RET} @var{face} @key{RET}
-@kindex C-x w h
-@findex highlight-regexp
-Highlight text that matches @var{regexp} using face @var{face}
-(@code{highlight-regexp}).  By using this command more than once, you
-can highlight various parts of the text in different ways.  The
-highlighting will remain as long as the buffer is loaded.  For
-example, to highlight all occurrences of the word ``whim'' using the
-default face (a yellow background) @kbd{C-x w h whim @key{RET}
-@key{RET}}.  Any face can be used for highlighting, Hi Lock provides
-several of its own and these are pre-loaded into a history list.  While
-being prompted for a face use @kbd{M-p} and @kbd{M-n} to cycle through
-them.
-
-@item C-x w r @var{regexp} @key{RET}
-@kindex C-x w r
-@findex unhighlight-regexp
-Unhighlight @var{regexp} (@code{unhighlight-regexp}).
-When activated from the menu select the expression to unhighlight from
-a list.  When activated from the keyboard the most recently added
-expression will be shown.  Use @kbd{M-p} to show the next older
-expression and @kbd{M-n} to select the next newer expression.  When
-the expression to unhighlight appears press @kbd{@key{RET}} to unhighlight
-it.  The expression can also be typed and completion is available.
-
-@item C-x w l @var{regexp} @key{RET} @var{face} @key{RET}
-@kindex C-x w l
-@findex highlight-lines-matching-regexp
-@cindex lines, highlighting
-@cindex highlighting lines of text
-Highlight entire lines containing a match for @var{regexp}, using face
-@var{face} (@code{highlight-lines-matching-regexp}).
-
-@item C-x w b
-@kindex C-x w b
-@findex hi-lock-write-interactive-patterns
-Insert all the current highlighting regexp/face pairs into the buffer
-at point, with comment delimiters to prevent them from changing your
-program.  This key binding runs the
-@code{hi-lock-write-interactive-patterns} command.
-
-These patterns will be read the next time you visit the file while
-Hi Lock mode is enabled, or whenever you use the @kbd{M-x
-hi-lock-find-patterns} command.
-
-@item C-x w i
-@kindex C-x w i
-@findex hi-lock-find-patterns
-@vindex hi-lock-exclude-modes
-Re-read regexp/face pairs in the current buffer
-(@code{hi-lock-write-interactive-patterns}).  Users familiar with Font
-Lock keywords might interactively enter patterns
-(@code{highlight-regexp}), write them into the file
-(@code{hi-lock-write-interactive-patterns}), edit them, perhaps
-including different faces for different parenthesized parts of the
-match, and finally use this command
-(@code{hi-lock-write-interactive-patterns}) to have Hi Lock highlight
-them.
-
-This command does nothing if the major mode is a member of the list
-@code{hi-lock-exclude-modes}.
-@end table
-
-@node Highlight Changes
-@section Highlight Changes Mode
-
-@findex highlight-changes-mode
-  Use @kbd{M-x highlight-changes-mode} to enable a minor mode
-that uses faces (colors, typically) to indicate which parts of
-the buffer were changed most recently.
-
 @node Scrolling
 @section Scrolling
 
@@ -489,12 +36,13 @@
 
 @cindex scrolling
   @dfn{Scrolling} means moving text up or down in the window so that
-different parts of the text are visible.  Scrolling forward means that text
-moves up, and new text appears at the bottom.  Scrolling backward moves
-text down and new text appears at the top.
+different parts of the text are visible.  Scrolling ``forward'' or
+``up'' means that text moves up, and new text appears at the bottom.
+Scrolling ``backward'' or ``down'' moves text down, and new text
+appears at the top.
 
-  Scrolling happens automatically if you move point past the bottom or top
-of the window.  You can also explicitly request scrolling with the commands
+  Scrolling happens automatically if you move point past the bottom or
+top of the window.  You can also scroll explicitly with the commands
 in this section.
 
 @table @kbd
@@ -696,6 +244,467 @@
   To disable automatic horizontal scrolling, set the variable
 @code{auto-hscroll-mode} to @code{nil}.
 
+@node Follow Mode
+@section Follow Mode
+@cindex Follow mode
+@cindex mode, Follow
+@findex follow-mode
+@cindex windows, synchronizing
+@cindex synchronizing windows
+
+  @dfn{Follow mode} is a minor mode that makes two windows, both
+showing the same buffer, scroll as a single tall ``virtual window.''
+To use Follow mode, go to a frame with just one window, split it into
+two side-by-side windows using @kbd{C-x 3}, and then type @kbd{M-x
+follow-mode}.  From then on, you can edit the buffer in either of the
+two windows, or scroll either one; the other window follows it.
+
+  In Follow mode, if you move point outside the portion visible in one
+window and into the portion visible in the other window, that selects
+the other window---again, treating the two as if they were parts of
+one large window.
+
+  To turn off Follow mode, type @kbd{M-x follow-mode} a second time.
+
+@node Faces
+@section Using Multiple Typefaces
+@cindex faces
+
+  You can specify various styles for displaying text using
+@dfn{faces}.  Each face can specify various @dfn{face attributes},
+such as the font family, the height, weight and slant of the
+characters, the foreground and background color, and underlining or
+overlining.  A face does not have to specify all of these attributes;
+often it inherits most of them from another face.
+
+  On graphical display, all the Emacs face attributes are meaningful.
+On a text-only terminal, only some of them work.  Some text-only
+terminals support inverse video, bold, and underline attributes; some
+support colors.  Text-only terminals generally do not support changing
+the height and width or the font family.
+
+  Emacs uses faces automatically for highlighting, through the work of
+Font Lock mode.  @xref{Font Lock}, for more information about Font
+Lock mode and syntactic highlighting.  You can print out the buffer
+with the highlighting that appears on your screen using the command
+@code{ps-print-buffer-with-faces}.  @xref{PostScript}.
+
+  You control the appearance of a part of the text in the buffer by
+specifying the face or faces to use for it.  The style of display used
+for any given character is determined by combining the attributes of
+all the applicable faces specified for that character.  Any attribute
+that isn't specified by these faces is taken from the @code{default} face,
+whose attributes reflect the default settings of the frame itself.
+
+  Enriched mode, the mode for editing formatted text, includes several
+commands and menus for specifying faces for text in the buffer.
+@xref{Format Faces}, for how to specify the font for text in the
+buffer.  @xref{Format Colors}, for how to specify the foreground and
+background color.
+
+@cindex face colors, setting
+@findex set-face-foreground
+@findex set-face-background
+  To alter the appearance of a face, use the customization buffer.
+@xref{Face Customization}.  You can also use X resources to specify
+attributes of particular faces (@pxref{Resources}).  Alternatively,
+you can change the foreground and background colors of a specific face
+with @kbd{M-x set-face-foreground} and @kbd{M-x set-face-background}.
+These commands prompt in the minibuffer for a face name and a color
+name, with completion, and then set that face to use the specified
+color.  Changing the colors of the @code{default} face also changes
+the foreground and background colors on all frames, both existing and
+those to be created in the future.  (You can also set foreground and
+background colors for the current frame only; see @ref{Frame
+Parameters}.)
+
+  Emacs can correctly display variable-width fonts, but Emacs commands
+that calculate width and indentation do not know how to calculate
+variable widths.  This can sometimes lead to incorrect results when
+you use variable-width fonts.  In particular, indentation commands can
+give inconsistent results, so we recommend you avoid variable-width
+fonts for editing program source code.  Filling will sometimes make
+lines too long or too short.  We plan to address these issues in
+future Emacs versions.
+
+@node Standard Faces
+@section Standard Faces
+
+@findex list-faces-display
+  To see what faces are currently defined, and what they look like,
+type @kbd{M-x list-faces-display}.  It's possible for a given face to
+look different in different frames; this command shows the appearance
+in the frame in which you type it.
+
+  Here are the standard faces for specifying text appearance.  You can
+apply them to specific text when you want the effects they produce.
+
+@table @code
+@item default
+This face is used for ordinary text that doesn't specify any face.
+@item bold
+This face uses a bold variant of the default font, if it has one.
+It's up to you to choose a default font that has a bold variant,
+if you want to use one.
+@item italic
+This face uses an italic variant of the default font, if it has one.
+@item bold-italic
+This face uses a bold italic variant of the default font, if it has one.
+@item underline
+This face underlines text.
+@item fixed-pitch
+This face forces use of a particular fixed-width font.
+@item variable-pitch
+This face forces use of a particular variable-width font.  It's
+reasonable to customize this face to use a different variable-width font,
+if you like, but you should not make it a fixed-width font.
+@item shadow
+This face is used for making the text less noticeable than the surrounding
+ordinary text.  Usually this can be achieved by using shades of gray in
+contrast with either black or white default foreground color.
+@end table
+
+  Here's an incomplete list of faces used to highlight parts of the
+text temporarily for specific purposes.  (Many other modes define
+their own faces for this purpose.)
+
+@table @code
+@item highlight
+This face is used for highlighting portions of text, in various modes.
+For example, mouse-sensitive text is highlighted using this face.
+@item isearch
+This face is used for highlighting the current Isearch match.
+@item query-replace
+This face is used for highlighting the current Query Replace match.
+@item lazy-highlight
+This face is used for lazy highlighting of Isearch and Query Replace
+matches other than the current one.
+@item region
+This face is used for displaying a selected region (when Transient Mark
+mode is enabled---see below).
+@item secondary-selection
+This face is used for displaying a secondary X selection (@pxref{Secondary
+Selection}).
+@item trailing-whitespace
+The face for highlighting excess spaces and tabs at the end of a line
+when @code{show-trailing-whitespace} is non-@code{nil}; see
+@ref{Useless Whitespace}.
+@item nobreak-space
+The face for displaying the character ``nobreak space''.
+@item escape-glyph
+The face for highlighting the @samp{\} or @samp{^} that indicates
+a control character.  It's also used when @samp{\} indicates a
+nobreak space or nobreak (soft) hyphen.
+@end table
+
+@cindex @code{region} face
+  When Transient Mark mode is enabled, the text of the region is
+highlighted when the mark is active.  This uses the face named
+@code{region}; you can control the style of highlighting by changing the
+style of this face (@pxref{Face Customization}).  @xref{Transient Mark},
+for more information about Transient Mark mode and activation and
+deactivation of the mark.
+
+  These faces control the appearance of parts of the Emacs frame.
+They exist as faces to provide a consistent way to customize the
+appearance of these parts of the frame.
+
+@table @code
+@item mode-line
+@itemx modeline
+This face is used for the mode line of the currently selected window,
+and for menu bars when toolkit menus are not used.  By default, it's
+drawn with shadows for a ``raised'' effect on graphical displays, and
+drawn as the inverse of the default face on non-windowed terminals.
+@code{modeline} is an alias for the @code{mode-line} face, for
+compatibility with old Emacs versions.
+@item mode-line-inactive
+Like @code{mode-line}, but used for mode lines of the windows other
+than the selected one (if @code{mode-line-in-non-selected-windows} is
+non-@code{nil}).  This face inherits from @code{mode-line}, so changes
+in that face affect mode lines in all windows.
+@item mode-line-highlight
+Like @code{highlight}, but used for portions of text on mode lines.
+@item mode-line-buffer-id
+This face is used for buffer identification parts in the mode line.
+@item header-line
+Similar to @code{mode-line} for a window's header line, which appears
+at the top of a window just as the mode line appears at the bottom.
+Most windows do not have a header line---only some special modes, such
+Info mode, create one.
+@item vertical-border
+This face is used for the vertical divider between windows.
+By default this face inherits from the @code{mode-line-inactive} face
+on character terminals.  On graphical displays the foreground color of
+this face is used for the vertical line between windows without
+scrollbars.
+@item minibuffer-prompt
+@cindex @code{minibuffer-prompt} face
+@vindex minibuffer-prompt-properties
+This face is used for the prompt strings displayed in the minibuffer.
+By default, Emacs automatically adds this face to the value of
+@code{minibuffer-prompt-properties}, which is a list of text
+properties used to display the prompt text.
+@item fringe
+@cindex @code{fringe} face
+The face for the fringes to the left and right of windows on graphic
+displays.  (The fringes are the narrow portions of the Emacs frame
+between the text area and the window's right and left borders.)
+@xref{Fringes}.
+@item scroll-bar
+This face determines the visual appearance of the scroll bar.
+@xref{Scroll Bars}.
+@item border
+This face determines the color of the frame border.
+@item cursor
+This face determines the color of the cursor.
+@item mouse
+This face determines the color of the mouse pointer.
+@item tool-bar
+This face determines the color of tool bar icons.  @xref{Tool Bars}.
+@item tooltip
+This face is used for tooltips.  @xref{Tooltips}.
+@item menu
+@cindex menu bar appearance
+@cindex @code{menu} face, no effect if customized
+@cindex customization of @code{menu} face
+This face determines the colors and font of Emacs's menus.  @xref{Menu
+Bars}.  Setting the font of LessTif/Motif menus is currently not
+supported; attempts to set the font are ignored in this case.
+Likewise, attempts to customize this face in Emacs built with GTK and
+in the MS-Windows port are ignored by the respective GUI toolkits;
+you need to use system-wide styles and options to change the
+appearance of the menus.
+@end table
+
+@node Font Lock
+@section Font Lock mode
+@cindex Font Lock mode
+@cindex mode, Font Lock
+@cindex syntax highlighting and coloring
+
+  Font Lock mode is a minor mode, always local to a particular buffer,
+which highlights (or ``fontifies'') the buffer contents according to
+the syntax of the text you are editing.  It can recognize comments and
+strings in most languages; in several languages, it can also recognize
+and properly highlight various other important constructs---for
+example, names of functions being defined or reserved keywords.
+Some special modes, such as Occur mode and Info mode, have completely
+specialized ways of assigning fonts for Font Lock mode.
+
+@findex font-lock-mode
+  Font Lock mode is turned on by default in all modes which support it.
+You can toggle font-lock for each buffer with the command @kbd{M-x
+font-lock-mode}.  Using a positive argument unconditionally turns Font
+Lock mode on, and a negative or zero argument turns it off.
+
+@findex global-font-lock-mode
+@vindex global-font-lock-mode
+  If you do not wish Font Lock mode to be turned on by default,
+customize the variable @code{global-font-lock-mode} using the Customize
+interface (@pxref{Easy Customization}), or use the function
+@code{global-font-lock-mode} in your @file{.emacs} file, like this:
+
+@example
+(global-font-lock-mode 0)
+@end example
+
+@findex turn-on-font-lock
+  If you have disabled Global Font Lock mode, you can still enable Font
+Lock for specific major modes by adding the function
+@code{turn-on-font-lock} to the mode hooks (@pxref{Hooks}).  For
+example, to enable Font Lock mode for editing C files, you can do this:
+
+@example
+(add-hook 'c-mode-hook 'turn-on-font-lock)
+@end example
+
+  Font Lock mode uses several specifically named faces to do its job,
+including @code{font-lock-string-face}, @code{font-lock-comment-face},
+and others.  The easiest way to find them all is to use @kbd{M-x
+customize-group @key{RET} font-lock-faces @key{RET}}.  You can then
+use that customization buffer to customize the appearance of these
+faces.  @xref{Face Customization}.
+
+  You can also customize these faces using @kbd{M-x
+set-face-foreground} or @kbd{M-x set-face-background}.  @xref{Faces}.
+
+@vindex font-lock-maximum-decoration
+  The variable @code{font-lock-maximum-decoration} specifies the
+preferred level of fontification, for modes that provide multiple
+levels.  Level 1 is the least amount of fontification; some modes
+support levels as high as 3.  The normal default is ``as high as
+possible.''  You can specify an integer, which applies to all modes, or
+you can specify different numbers for particular major modes; for
+example, to use level 1 for C/C++ modes, and the default level
+otherwise, use this:
+
+@example
+(setq font-lock-maximum-decoration
+      '((c-mode . 1) (c++-mode . 1)))
+@end example
+
+@vindex font-lock-maximum-size
+  Fontification can be too slow for large buffers, so you can suppress
+it for buffers above a certain size.  The variable
+@code{font-lock-maximum-size} specifies a buffer size, beyond which
+buffer fontification is suppressed.
+
+@c @w is used below to prevent a bad page-break.
+@vindex font-lock-beginning-of-syntax-function
+@cindex incorrect fontification
+@cindex parenthesis in column zero and fontification
+@cindex brace in column zero and fontification
+  Comment and string fontification (or ``syntactic'' fontification)
+relies on analysis of the syntactic structure of the buffer text.  For
+the sake of speed, some modes, including C mode and Lisp mode,
+rely on a special convention: an open-parenthesis or open-brace in the
+leftmost column always defines the @w{beginning} of a defun, and is
+thus always outside any string or comment.  (@xref{Left Margin
+Paren}.)  If you don't follow this convention, Font Lock mode can
+misfontify the text that follows an open-parenthesis or open-brace in
+the leftmost column that is inside a string or comment.
+
+@cindex slow display during scrolling
+  The variable @code{font-lock-beginning-of-syntax-function} (always
+buffer-local) specifies how Font Lock mode can find a position
+guaranteed to be outside any comment or string.  In modes which use the
+leftmost column parenthesis convention, the default value of the variable
+is @code{beginning-of-defun}---that tells Font Lock mode to use the
+convention.  If you set this variable to @code{nil}, Font Lock no longer
+relies on the convention.  This avoids incorrect results, but the price
+is that, in some cases, fontification for a changed text must rescan
+buffer text from the beginning of the buffer.  This can considerably
+slow down redisplay while scrolling, particularly if you are close to
+the end of a large buffer.
+
+@findex font-lock-add-keywords
+  Font Lock highlighting patterns already exist for many modes, but you
+may want to fontify additional patterns.  You can use the function
+@code{font-lock-add-keywords}, to add your own highlighting patterns for
+a particular mode.  For example, to highlight @samp{FIXME:} words in C
+comments, use this:
+
+@example
+(font-lock-add-keywords
+ 'c-mode
+ '(("\\<\\(FIXME\\):" 1 font-lock-warning-face t)))
+@end example
+
+@findex font-lock-remove-keywords
+  To remove keywords from the font-lock highlighting patterns, use the
+function @code{font-lock-remove-keywords}.  @xref{Search-based
+Fontification,,, elisp, The Emacs Lisp Reference Manual}, for
+documentation of the format of this list.
+
+@cindex just-in-time (JIT) font-lock
+@cindex background syntax highlighting
+  Fontifying large buffers can take a long time.  To avoid large
+delays when a file is visited, Emacs fontifies only the visible
+portion of a buffer.  As you scroll through the buffer, each portion
+that becomes visible is fontified as soon as it is displayed.  The
+parts of the buffer that are not displayed are fontified
+``stealthily,'' in the background, i.e.@: when Emacs is idle.  You can
+control this background fontification, also called @dfn{Just-In-Time}
+(or @dfn{JIT}) Lock, by customizing variables in the customization
+group @samp{jit-lock}.  @xref{Specific Customization}.
+
+@node Highlight Interactively
+@section Interactive Highlighting
+@cindex highlighting by matching
+@cindex interactive highlighting
+@cindex Highlight Changes mode
+
+@findex highlight-changes-mode
+  Use @kbd{M-x highlight-changes-mode} to enable (or disable)
+Highlight Changes mode, a minor mode that uses faces (colors,
+typically) to indicate which parts of the buffer were changed most
+recently.
+
+@cindex Hi Lock mode
+@findex hi-lock-mode
+  Hi Lock mode is another minor mode, which highlights text that
+matches your specified regular expressions.  For example, you might
+wish to see all the references to a certain variable in a program
+source file, highlight certain parts in a voluminous output of some
+program, or make certain names stand out in an article.  Use the
+@kbd{M-x hi-lock-mode} command to enable (or disable) Hi Lock mode.
+To enable Hi Lock mode for all buffers, use @kbd{M-x
+global-hi-lock-mode} or place @code{(global-hi-lock-mode 1)} in your
+@file{.emacs} file.
+
+  Hi Lock mode works like Font Lock mode (@pxref{Font Lock}), except
+that you specify explicitly the regular expressions to highlight.  You
+control them with these commands:
+
+@table @kbd
+@item C-x w h @var{regexp} @key{RET} @var{face} @key{RET}
+@kindex C-x w h
+@findex highlight-regexp
+Highlight text that matches @var{regexp} using face @var{face}
+(@code{highlight-regexp}).  The highlighting will remain as long as
+the buffer is loaded.  For example, to highlight all occurrences of
+the word ``whim'' using the default face (a yellow background)
+@kbd{C-x w h whim @key{RET} @key{RET}}.  Any face can be used for
+highlighting, Hi Lock provides several of its own and these are
+pre-loaded into a history list.  While being prompted for a face use
+@kbd{M-p} and @kbd{M-n} to cycle through them.
+
+You can use this command multiple times, specifying various regular
+expressions to highlight in different ways.
+
+@item C-x w r @var{regexp} @key{RET}
+@kindex C-x w r
+@findex unhighlight-regexp
+Unhighlight @var{regexp} (@code{unhighlight-regexp}).
+
+If you invoke this from the menu, you select the expression to
+unhighlight from a list.  If you invoke this from the keyboard, you
+use the minibuffer.  It will show the most recently added regular
+expression; use @kbd{M-p} to show the next older expression and
+@kbd{M-n} to select the next newer expression.  (You can also type the
+expression by hand, with completion.)  When the expression you want to
+unhighlight appears in the minibuffer, press @kbd{@key{RET}} to exit
+the minibuffer and unhighlight it.
+
+@item C-x w l @var{regexp} @key{RET} @var{face} @key{RET}
+@kindex C-x w l
+@findex highlight-lines-matching-regexp
+@cindex lines, highlighting
+@cindex highlighting lines of text
+Highlight entire lines containing a match for @var{regexp}, using face
+@var{face} (@code{highlight-lines-matching-regexp}).
+
+@item C-x w b
+@kindex C-x w b
+@findex hi-lock-write-interactive-patterns
+Insert all the current highlighting regexp/face pairs into the buffer
+at point, with comment delimiters to prevent them from changing your
+program.  (This key binding runs the
+@code{hi-lock-write-interactive-patterns} command.)
+
+These patterns will be read the next time you visit the file while
+Hi Lock mode is enabled, or whenever you use the @kbd{M-x
+hi-lock-find-patterns} command.
+
+@item C-x w i
+@kindex C-x w i
+@findex hi-lock-find-patterns
+@vindex hi-lock-exclude-modes
+Re-read regexp/face pairs in the current buffer
+(@code{hi-lock-write-interactive-patterns}).  Users familiar with Font
+Lock keywords might interactively enter patterns
+(@code{highlight-regexp}), write them into the file
+(@code{hi-lock-write-interactive-patterns}), edit them, perhaps
+including different faces for different parenthesized parts of the
+match, and finally use this command
+(@code{hi-lock-write-interactive-patterns}) to have Hi Lock highlight
+them.
+
+This command does nothing if the major mode is a member of the list
+@code{hi-lock-exclude-modes}.
+@end table
+
 @node Fringes
 @section Window Fringes
 @cindex fringes
@@ -733,7 +742,9 @@
   It is easy to leave unnecessary spaces at the end of a line, or
 empty lines at the end of a file, without realizing it.  In most
 cases, this @dfn{trailing whitespace} has no effect, but there are
-special circumstances where it matters.
+special circumstances where it matters.  It can also be a nuisance
+that the line has ``changed,'' when the change is just spaces added or
+removed at the end.
 
   You can make trailing whitespace at the end of a line visible on the
 screen by setting the buffer-local variable
@@ -768,29 +779,7 @@
 value of this variable is controlled by the variable
 @code{default-indicate-empty-lines}; by setting that variable, you
 can enable or disable this feature for all new buffers.  (This feature
-currently doesn't work on character terminals.)
-
-@node Follow Mode
-@section Follow Mode
-@cindex Follow mode
-@cindex mode, Follow
-@findex follow-mode
-@cindex windows, synchronizing
-@cindex synchronizing windows
-
-  @dfn{Follow mode} is a minor mode that makes two windows, both
-showing the same buffer, scroll as a single tall ``virtual window.''
-To use Follow mode, go to a frame with just one window, split it into
-two side-by-side windows using @kbd{C-x 3}, and then type @kbd{M-x
-follow-mode}.  From then on, you can edit the buffer in either of the
-two windows, or scroll either one; the other window follows it.
-
-  In Follow mode, if you move point outside the portion visible in one
-window and into the portion visible in the other window, that selects
-the other window---again, treating the two as if they were parts of
-one large window.
-
-  To turn off Follow mode, type @kbd{M-x follow-mode} a second time.
+currently doesn't work on text-only terminals.)
 
 @node Selective Display
 @section Selective Display
@@ -868,6 +857,9 @@
 @cindex narrowing, and line number display
   If you have narrowed the buffer (@pxref{Narrowing}), the displayed
 line number is relative to the accessible portion of the buffer.
+Thus, it isn't suitable as an argument to @code{goto-line}.  (Use
+@code{what-line} command to see the line number relative to the whole
+file.)
 
 @vindex line-number-display-limit
   If the buffer is very large (larger than the value of
@@ -933,19 +925,7 @@
 3D-style highlighting, like that of a button when it is not being
 pressed.  If you don't like this effect, you can disable the 3D
 highlighting of the mode line, by customizing the attributes of the
-@code{mode-line} face in your @file{.emacs} init file, like this:
-
-@example
-(set-face-attribute 'mode-line nil :box nil)
-@end example
-
-@noindent
-Alternatively, you can turn off the box attribute in your
-@file{.Xdefaults} file:
-
-@example
-Emacs.mode-line.AttributeBox: off
-@end example
+@code{mode-line} face.  @xref{Face Customization}.
 
 @cindex non-selected windows, mode line appearance
   By default, the mode line of nonselected windows is displayed in a
@@ -961,6 +941,15 @@
 @code{mode-line-in-non-selected-windows} to @code{nil}; then all mode
 lines are displayed in the @code{mode-line} face.
 
+@vindex eol-mnemonic-unix
+@vindex eol-mnemonic-dos
+@vindex eol-mnemonic-mac
+@vindex eol-mnemonic-undecided
+  You can customize the mode line display for each of the end-of-line
+formats by setting each of the variables @code{eol-mnemonic-unix},
+@code{eol-mnemonic-dos}, @code{eol-mnemonic-mac}, and
+@code{eol-mnemonic-undecided} to the strings you prefer.
+
 @node Text Display
 @section How Text Is Displayed
 @cindex characters (in text)
@@ -976,17 +965,27 @@
 
   Other @acronym{ASCII} control characters are normally displayed as a caret
 (@samp{^}) followed by the non-control version of the character; thus,
-control-A is displayed as @samp{^A}.
+control-A is displayed as @samp{^A}.  The caret appears in face
+@code{escape-glyph}.
+
+  Non-@acronym{ASCII} characters 0200 through 0237 (octal) are
+displayed with octal escape sequences; thus, character code 0230
+(octal) is displayed as @samp{\230}.  The backslash appears in face
+@code{escape-glyph}.
 
-  Non-@acronym{ASCII} characters 0200 through 0237 (octal) are displayed with
-octal escape sequences; thus, character code 0230 (octal) is displayed
-as @samp{\230}.  The display of character codes 0240 through 0377
-(octal) may be either as escape sequences or as graphics.  They do not
-normally occur in multibyte buffers, but if they do, they are displayed
-as Latin-1 graphics.  In unibyte mode, if you enable European display
-they are displayed using their graphics (assuming your terminal supports
-them), otherwise as escape sequences.  @xref{Single-Byte Character
-Support}.
+@vindex ctl-arrow
+  If the variable @code{ctl-arrow} is @code{nil}, control characters in
+the buffer are displayed with octal escape sequences, except for newline
+and tab.  Altering the value of @code{ctl-arrow} makes it local to the
+current buffer; until that time, the default value is in effect.  The
+default is initially @code{t}.
+
+  The display of character codes 0240 through 0377 (octal) may be
+either as escape sequences or as graphics.  They do not normally occur
+in multibyte buffers, but if they do, they are displayed as Latin-1
+graphics.  In unibyte mode, if you enable European display they are
+displayed using their graphics (assuming your terminal supports them),
+otherwise as escape sequences.  @xref{Single-Byte Character Support}.
 
 @vindex nobreak-char-display
 @cindex no-break space, display
@@ -1001,6 +1000,23 @@
 @code{nil}.  If you set the variable to any other value, that means to
 prefix these characters with an escape character.
 
+@vindex tab-width
+@vindex default-tab-width
+  Normally, a tab character in the buffer is displayed as whitespace which
+extends to the next display tab stop position, and display tab stops come
+at intervals equal to eight spaces.  The number of spaces per tab is
+controlled by the variable @code{tab-width}, which is made local by
+changing it.  Note that how the tab character
+in the buffer is displayed has nothing to do with the definition of
+@key{TAB} as a command.  The variable @code{tab-width} must have an
+integer value between 1 and 1000, inclusive.  The variable
+@code{default-tab-width} controls the default value of this variable
+for buffers where you have not set it locally.
+
+  You can customize the way any particular character code is displayed
+by means of a display table.  @xref{Display Tables,, Display Tables,
+elisp, The Emacs Lisp Reference Manual}.
+
 @node Cursor Display
 @section Displaying the Cursor
 
@@ -1043,16 +1059,19 @@
 @findex hl-line-mode
 @findex global-hl-line-mode
 @cindex highlight current line
-  If you find it hard to see the cursor, you might like HL Line mode,
-a minor mode that highlights the line containing point.  Use @kbd{M-x
+  To make the cursor even more visible, you can use HL Line mode, a
+minor mode that highlights the line containing point.  Use @kbd{M-x
 hl-line-mode} to enable or disable it in the current buffer.  @kbd{M-x
 global-hl-line-mode} enables or disables the same mode globally.
 
 @node Display Custom
 @section Customization of Display
 
-  This section contains information for customization only.  Beginning
-users should skip it.
+  This section describes variables (@pxref{Variables}) that you can
+change to customize how Emacs displays.  Beginning users can skip
+it.
+@c the reason for that pxref is because an xref early in the
+@c ``echo area'' section leads here.
 
 @vindex inverse-video
   If the variable @code{inverse-video} is non-@code{nil}, Emacs attempts
@@ -1064,51 +1083,18 @@
 sound.  This variable has no effect if your terminal does not have a way
 to make the screen blink.
 
-@vindex no-redraw-on-reenter
-  On a text terminal, when you reenter Emacs after suspending, Emacs
-normally clears the screen and redraws the entire display.  On some
-terminals with more than one page of memory, it is possible to arrange
-the termcap entry so that the @samp{ti} and @samp{te} strings (output
-to the terminal when Emacs is entered and exited, respectively) switch
-between pages of memory so as to use one page for Emacs and another
-page for other output.  Then you might want to set the variable
-@code{no-redraw-on-reenter} non-@code{nil}; this tells Emacs to
-assume, when resumed, that the screen page it is using still contains
-what Emacs last wrote there.
-
 @vindex echo-keystrokes
   The variable @code{echo-keystrokes} controls the echoing of multi-character
 keys; its value is the number of seconds of pause required to cause echoing
-to start, or zero meaning don't echo at all.  @xref{Echo Area}.
-
-@vindex ctl-arrow
-  If the variable @code{ctl-arrow} is @code{nil}, all control characters in
-the buffer are displayed with octal escape sequences, except for newline
-and tab.  Altering the value of @code{ctl-arrow} makes it local to the
-current buffer; until that time, the default value is in effect.  The
-default is initially @code{t}.  @xref{Display Tables,, Display Tables,
-elisp, The Emacs Lisp Reference Manual}.
-
-@vindex tab-width
-@vindex default-tab-width
-  Normally, a tab character in the buffer is displayed as whitespace which
-extends to the next display tab stop position, and display tab stops come
-at intervals equal to eight spaces.  The number of spaces per tab is
-controlled by the variable @code{tab-width}, which is made local by
-changing it, just like @code{ctl-arrow}.  Note that how the tab character
-in the buffer is displayed has nothing to do with the definition of
-@key{TAB} as a command.  The variable @code{tab-width} must have an
-integer value between 1 and 1000, inclusive.  The variable
-@code{default-tab-width} controls the default value of this variable
-for buffers where you have not set it locally.
+to start, or zero, meaning don't echo at all.  @xref{Echo Area}.
 
 @cindex truncation
 @cindex line truncation, and fringes
   As an alternative to continuation, Emacs can display long lines by
 @dfn{truncation}.  This means that all the characters that do not fit
 in the width of the screen or window do not appear at all.  On
-graphical terminals, a small straight arrow in the fringe indicates
-truncation at either end of the line.  On text terminals, @samp{$}
+graphical displays, a small straight arrow in the fringe indicates
+truncation at either end of the line.  On text-only terminals, @samp{$}
 appears in the first column when there is text truncated to the left,
 and in the last column when there is text truncated to the right.
 
@@ -1134,27 +1120,22 @@
 
 @vindex overflow-newline-into-fringe
   If the variable @code{overflow-newline-into-fringe} is
-non-@code{nil} on a window system, it specifies that lines which are
-exactly as wide as the window (not counting the final newline
-character) shall not be broken into two lines on the display (with
-just the newline on the second line).  Instead, the newline
-overflows into the right fringe, and the cursor will be displayed in
-the fringe when positioned on that newline.
+non-@code{nil} on a graphical display, then Emacs does not continue or
+truncate a line which is exactly as wide as the window.  Instead, the
+newline overflows into the right fringe, and the cursor appears in the
+fringe when positioned on that newline.
 
 @vindex indicate-buffer-boundaries
-  On a window system, Emacs may indicate the buffer boundaries in the
-fringes.  The buffer boundaries, i.e. first and last line in the
-buffer, can be marked with angle bitmaps in the left or right fringe.
-This can be combined with up and down arrow bitmaps shown at the top
-and bottom of the left or right fringe if the window can be scrolled
-in either direction.
+  On a graphical display, Emacs can indicate the buffer boundaries in
+the fringes.  It inddicates the first line and the last line with
+angle images in the fringes.  This can be combined with up and down
+arrow images which say whether it is possible to scroll the window up
+and down.
 
   The buffer-local variable @code{indicate-buffer-boundaries} controls
 how the buffer boundaries and window scrolling is indicated in the
-fringes.
-
-  If the value is @code{left} or @code{right}, both angle and arrow
-bitmaps are displayed in the left or right fringe, respectively.
+fringes.  If the value is @code{left} or @code{right}, both angle and
+arrow bitmaps are displayed in the left or right fringe, respectively.
 
   If value is an alist, each element @code{(@var{indicator} .
 @var{position})} specifies the position of one of the indicators.
@@ -1176,25 +1157,21 @@
 that do not override it.
 
 @vindex baud-rate
-  The variable @anchor{baud-rate}@code{baud-rate} holds the output speed of the
-terminal, as far as Emacs knows.  Setting this variable does not
-change the speed of actual data transmission, but the value is used
-for calculations.  On terminals, it affects padding, and decisions
-about whether to scroll part of the screen or redraw it instead.
-It also affects the behavior of incremental search.
+  The variable @anchor{baud-rate}@code{baud-rate} holds the output
+speed of the terminal, as far as Emacs knows.  Setting this variable
+does not change the speed of actual data transmission, but the value
+is used for calculations.  On text-only terminals, it affects padding,
+and decisions about whether to scroll part of the screen or redraw it
+instead.  It also affects the behavior of incremental search.
 
-  On window-systems, @code{baud-rate} is only used to determine how
-frequently to look for pending input during display updating.  A
+  On graphical displays, @code{baud-rate} is only used to determine
+how frequently to look for pending input during display updating.  A
 higher value of @code{baud-rate} means that check for pending input
 will be done less frequently.
 
-  You can customize the way any particular character code is displayed
-by means of a display table.  @xref{Display Tables,, Display Tables,
-elisp, The Emacs Lisp Reference Manual}.
-
 @cindex hourglass pointer display
 @vindex hourglass-delay
-  On a window system, Emacs can optionally display the mouse pointer
+  On graphical display, Emacs can optionally display the mouse pointer
 in a special shape to say that Emacs is busy.  To turn this feature on
 or off, customize the group @code{cursor}.  You can also control the
 amount of time Emacs must remain busy before the busy indicator is
@@ -1206,6 +1183,18 @@
 @code{tty-suppress-bold-inverse-default-colors} with a non-@code{nil}
 argument to suppress the effect of bold-face in this case.
 
+@vindex no-redraw-on-reenter
+  On a text-only terminal, when you reenter Emacs after suspending, Emacs
+normally clears the screen and redraws the entire display.  On some
+terminals with more than one page of memory, it is possible to arrange
+the termcap entry so that the @samp{ti} and @samp{te} strings (output
+to the terminal when Emacs is entered and exited, respectively) switch
+between pages of memory so as to use one page for Emacs and another
+page for other output.  Then you might want to set the variable
+@code{no-redraw-on-reenter} non-@code{nil}; this tells Emacs to
+assume, when resumed, that the screen page it is using still contains
+what Emacs last wrote there.
+
 @ignore
    arch-tag: 2219f910-2ff0-4521-b059-1bd231a536c4
 @end ignore
--- a/man/emacs.texi	Thu Jan 26 02:23:05 2006 +0000
+++ b/man/emacs.texi	Wed Feb 01 10:07:17 2006 +0000
@@ -123,7 +123,7 @@
 * Glossary::	        The glossary.
 * Antinews::	        Information about Emacs version 21.
 * Mac OS::              Using Emacs in the Mac.
-* MS-DOS::              Using Emacs on MS-DOS (otherwise known as "MS-DOG").
+* MS-DOS::              Using Emacs on MS-DOS and Microsoft Windows.
 * Manifesto::	        What's GNU?  Gnu's Not Unix!
 * Acknowledgments::     Major contributors to GNU Emacs.
 
@@ -235,7 +235,7 @@
 * Moving Point::        How to move the cursor to the place where you want to
 			  change something.
 * Erasing::	        Deleting and killing text.
-* Undo::	        Undoing recent changes in the text.
+* Basic Undo::	        Undoing recent changes in the text.
 * Basic Files::         Visiting, creating, and saving files.
 * Basic Help::          Asking what a character does.
 * Blank Lines::	        Commands to make or delete blank lines.
@@ -306,16 +306,15 @@
 
 Controlling the Display
 
+* Scrolling::	           Moving text up and down in a window.
+* Horizontal Scrolling::   Moving text left and right in a window.
+* Follow Mode::            Follow mode lets two windows scroll as one.
 * Faces::	           How to change the display style using faces.
 * Standard Faces::         Emacs' predefined faces.
 * Font Lock::              Minor mode for syntactic highlighting using faces.
 * Highlight Interactively:: Tell Emacs what text to highlight.
-* Highlight Changes::      Using colors to show where you changed the buffer.
-* Scrolling::	           Moving text up and down in a window.
-* Horizontal Scrolling::   Moving text left and right in a window.
 * Fringes::                Enabling or disabling window fringes.
 * Useless Whitespace::     Showing possibly-spurious trailing whitespace.
-* Follow Mode::            Follow mode lets two windows scroll as one.
 * Selective Display::      Hiding lines with lots of indentation.
 * Optional Mode Line::     Optional mode line display features.
 * Text Display::           How text characters are normally displayed.
@@ -342,6 +341,7 @@
 
 Commands for Fixing Typos
 
+* Undo::                Full details of Emacs undo commands.
 * Kill Errors::         Commands to kill a batch of recently entered text.
 * Transpose::	        Exchanging two characters, words, lines, lists...
 * Fixing Case::         Correcting case of last word entered.
@@ -907,7 +907,7 @@
 
   This manual documents the use and simple customization of the Emacs
 editor.  The reader is not expected to be a programmer; simple
-customizations do not require programming skill.  But the user who is not
+customizations do not require programming skill.  The user who is not
 interested in customizing can ignore the scattered customization hints.
 
   This is primarily a reference manual, but can also be used as a
@@ -959,12 +959,14 @@
 Publications Department, Laboratory for Computer Science, 545 Tech Square,
 Cambridge, MA 02139, USA@.  The price today is $3.
 
-This edition of the manual is intended for use with GNU Emacs installed
-on GNU and Unix systems.  GNU Emacs can also be used on VMS, MS-DOS
-(also called MS-DOG), Windows NT, and Windows 95 systems.  Those systems use
-different file name syntax; in addition, VMS and MS-DOS do not support
-all GNU Emacs features.  We don't try to describe VMS usage in this
-manual.  @xref{MS-DOS}, for information about using Emacs on MS-DOS.
+This edition of the manual is intended for use with GNU Emacs
+installed on GNU and Unix systems.  GNU Emacs can also be used on VMS,
+MS-DOS (also called MS-DOG), Microsoft Windows, and Macintosh systems.
+Those systems use different file name syntax; in addition, VMS and
+MS-DOS do not support all GNU Emacs features.  @xref{MS-DOS}, for
+information about using Emacs on MS-DOS and Windows.  @xref{Mac OS},
+for information about using Emacs on Macintosh.  We don't try to
+describe VMS usage in this manual.
 @end iftex
 
 @node Distrib, Intro, Top, Top
@@ -1146,11 +1148,11 @@
 Emacs Lisp Intro, Preface, eintr, An Introduction to Programming in
 Emacs Lisp}, if you want to learn Emacs Lisp programming.
 
-   When run under the X Window System, Emacs provides its own menus and
-convenient bindings to mouse buttons.  But Emacs can provide many of the
-benefits of a window system on a text-only terminal.  For instance, you
-can look at or edit several files at once, move text between files, and
-edit files while running shell commands.
+   When running on a graphics terminal, Emacs provides its own menus
+and convenient handling of mouse buttons.  But Emacs provides many of
+the benefits of a window system even on a text-only terminal.  For
+instance, you can look at or edit several files at once, move text
+between files, and edit files while running shell commands.
 
 @include screen.texi
 @include commands.texi
--- a/man/entering.texi	Thu Jan 26 02:23:05 2006 +0000
+++ b/man/entering.texi	Wed Feb 01 10:07:17 2006 +0000
@@ -7,12 +7,12 @@
 @cindex entering Emacs
 @cindex starting Emacs
 
-  The usual way to invoke Emacs is with the shell command @command{emacs}.
-Emacs clears the screen and then displays an initial help message and
-copyright notice.  Some operating systems discard all type-ahead when
-Emacs starts up; they give Emacs no way to prevent this.  Therefore, it
-is advisable to wait until Emacs clears the screen before typing your
-first editing command.
+  The usual way to invoke Emacs is with the shell command
+@command{emacs}.  Emacs clears the screen and then displays an initial
+help message and copyright notice.  Some operating systems discard all
+type-ahead when Emacs starts up; they give Emacs no way to prevent
+this.  If you ever use those systems, learn the habit of waiting for
+Emacs to clear the screen before typing your first editing command.
 
   If you run Emacs from a shell window under the X Window System, run it
 in the background with @command{emacs&}.  This way, Emacs does not tie up
@@ -22,11 +22,12 @@
 
 @vindex initial-major-mode
   When Emacs starts up, it creates a buffer named @samp{*scratch*}.
-That's the buffer you start out in.  The @samp{*scratch*} buffer uses Lisp
-Interaction mode; you can use it to type Lisp expressions and evaluate
-them, or you can ignore that capability and simply doodle.  (You can
-specify a different major mode for this buffer by setting the variable
-@code{initial-major-mode} in your init file.  @xref{Init File}.)
+That's the buffer you start out in.  The @samp{*scratch*} buffer uses
+Lisp Interaction mode; you can use it to type Lisp expressions and
+evaluate them, or you can ignore that capability and just write notes
+in it.  (You can specify a different major mode for this buffer by
+setting the variable @code{initial-major-mode} in your init file.
+@xref{Init File}.)
 
   It is possible to specify files to be visited, Lisp files to be
 loaded, and functions to be called, by giving Emacs arguments in the
@@ -45,7 +46,7 @@
 ability to visit more than one file in a single editing session, and
 it would lose the other accumulated context, such as the kill ring,
 registers, undo history, and mark ring, that are useful for operating
-on multiple files.
+on multiple files or even one.
 
   The recommended way to use GNU Emacs is to start it only once, just
 after you log in, and do all your editing in the same Emacs session.
@@ -84,7 +85,8 @@
 
   @dfn{Iconifying} means replacing the Emacs frame with a small box
 somewhere on the screen.  This is the usual way to exit Emacs when you're
-using a graphics terminal.
+using a graphics terminal---if you bother to ``exit'' at all.  (Just switching
+to another application is usually sufficient.)
 
   @dfn{Killing} Emacs means destroying the Emacs job.  You can run Emacs
 again later, but you will get a fresh Emacs; there is no way to resume
@@ -101,14 +103,14 @@
 @kindex C-z
 @findex suspend-emacs
   To suspend or iconify Emacs, type @kbd{C-z} (@code{suspend-emacs}).
-On text terminals, this suspends Emacs.  On graphics terminals,
+On text terminals, this suspends Emacs.  On graphical displays,
 it iconifies the Emacs frame.
 
   Suspending Emacs takes you back to the shell from which you invoked
 Emacs.  You can resume Emacs with the shell command @command{%emacs}
 in most common shells.  On systems that don't support suspending
 programs, @kbd{C-z} starts an inferior shell that communicates
-directly with the terminal.  Emacs waits until you exit the subshell.
+directly with the terminal, and Emacs waits until you exit the subshell.
 (The way to do that is probably with @kbd{C-d} or @command{exit}, but
 it depends on which shell you use.)  The only way on these systems to
 get back to the shell from which Emacs was run (to log out, for
@@ -122,7 +124,7 @@
 failing to support job control properly, but that is a matter of
 taste.)
 
-  On graphics terminals, @kbd{C-z} has a different meaning: it runs
+  On graphical displays, @kbd{C-z} has a different meaning: it runs
 the command @code{iconify-or-deiconify-frame}, which temporarily
 iconifies (or ``minimizes'') the selected Emacs frame
 (@pxref{Frames}).  Then you can use the window manager to get back to
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/man/erc.texi	Wed Feb 01 10:07:17 2006 +0000
@@ -0,0 +1,624 @@
+\input texinfo
+@c %**start of header
+@setfilename ../info/erc
+@settitle ERC Manual
+@c %**end of header
+
+@dircategory Emacs
+@direntry
+* ERC: (erc).  Powerful, modular, and extensible IRC client for Emacs.
+@end direntry
+
+@syncodeindex fn cp
+
+@copying
+This manual is for ERC version 5.1.
+
+Copyright @copyright{} 2005, 2006 Free Software Foundation, Inc.
+
+@quotation
+Permission is granted to copy, distribute and/or modify this document
+under the terms of the GNU Free Documentation License, Version 1.2 or
+any later version published by the Free Software Foundation; with no
+Invariant Sections, Front-Cover texts, or Back-Cover Texts.
+@end quotation
+@end copying
+
+@titlepage
+@title ERC manual
+@subtitle a full-featured IRC client
+@subtitle for GNU Emacs and XEmacs
+
+@c The following two commands
+@c start the copyright page.
+@page
+@vskip 0pt plus 1filll
+@insertcopying
+@end titlepage
+
+@c So the toc is printed at the start
+@contents
+
+@ifnottex
+@node Top, Introduction, (dir), (dir)
+@comment  node-name,  next,  previous,  up
+@top ERC
+
+@insertcopying
+@end ifnottex
+
+@menu
+* Introduction::                What is ERC?
+* Obtaining ERC::               How to get ERC releases and development
+                                  versions.
+* Installation::                Compiling and installing ERC.
+* Getting Started::             Quick Start guide to using ERC.
+* Keystroke Summary::           Keystrokes used in ERC buffers.
+* Modules::                     Available modules for ERC.
+* Advanced Usage::              Cool ways of using ERC.
+* Getting Help and Reporting Bugs::  
+* History::                     The history of ERC.
+* Concept Index::               Search for terms.
+
+@detailmenu
+ --- The Detailed Node Listing ---
+
+Obtaining ERC
+
+* Releases::                    Released versions of ERC.
+* Development::                 Latest unreleased development changes.
+
+@end detailmenu
+@end menu
+
+@node Introduction, Obtaining ERC, Top, Top
+@comment  node-name,  next,  previous,  up
+@chapter Introduction
+
+ERC is a powerful, modular, and extensible IRC client for Emacs.
+
+It comes with the following capabilities enabled by default.
+
+@itemize @bullet
+@item Flood control
+@item Timestamps
+@item Join channels automatically
+@item Buttonize URLs, nicknames, and other text
+@item Wrap long lines
+@item Highlight or remove IRC control characters
+@item Highlight pals, fools, and other keywords
+@item Detect netsplits
+@item Complete nicknames and commands in a programmable fashion
+@item Make displayed lines read-only
+@item Input history
+@item Track channel activity in the mode-line
+
+@end itemize
+
+@node Obtaining ERC, Installation, Introduction, Top
+@comment  node-name,  next,  previous,  up
+@chapter Obtaining ERC
+
+@menu
+* Releases::                    Released versions of ERC.
+* Development::                 Latest unreleased development changes.
+@end menu
+
+These sections may be skipped if you are using the version of ERC that
+comes with Emacs.
+
+@node Releases, Development, Obtaining ERC, Obtaining ERC
+@comment  node-name,  next,  previous,  up
+@section Releases
+
+Choose to install a release if you want to minimize risk.
+
+Errors are corrected in development first.  User-visible changes will be
+announced on the @email{erc-help@@lists.sourceforge.net} mailing list.
+@pxref{Getting Help and Reporting Bugs}.
+
+@cindex releases, Debian package
+@cindex Debian package for ERC
+Debian users can get ERC via apt-get.  The @file{erc} package is
+available in the official Debian repository.
+
+@cindex releases, from source
+Alternatively, you can download the latest release from
+@uref{http://sourceforge.net/project/showfiles.php?group_id=30118}.
+
+@node Development,  , Releases, Obtaining ERC
+@comment  node-name,  next,  previous,  up
+@section Development
+@cindex development
+
+Choose the development version if you want to live on the bleeding edge
+of ERC development or try out new features before release.
+
+@subsection Using CVS
+@cindex CVS, using
+
+ERC is primarily developed using a CVS repository on sourceforge.net.
+To check out a copy of the latest changes, do the following.
+
+@example
+cvs -d:pserver:anonymous@@cvs.sourceforge.net:/cvsroot/erc login
+cvs -z3 -d:pserver:anonymous@@cvs.sourceforge.net:/cvsroot/erc co -P erc
+@end example
+
+@cindex CVS snapshot
+Alternatively, the latest CVS snapshot may be downloaded in the
+following forms.
+
+@itemize @bullet
+@item http://mwolson.org/static/dist/erc-latest.tar.gz
+@item http://mwolson.org/static/dist/erc-latest.zip
+@end itemize
+
+@subsection Using the GNU Arch Revision Control System
+@cindex arch revision control system, using
+The Arch revision control system allows you to retrieve previous
+versions and select specific features and bug fixes.
+
+Michael Olson maintains an official Arch branch for ERC which stays
+current with the CVS repository for ERC.  If you would like to
+contribute to ERC development, and would prefer to use a modern Revision
+Control System, feel free to make your own branch.
+
+If you are new to Arch, you might find this tutorial helpful:
+@uref{http://www.mwolson.org/projects/ArchTutorial.html}.
+
+Downloading ERC with Arch and staying up-to-date involves the following
+steps.
+
+@enumerate
+@item Install arch
+
+@itemize @bullet
+@item Debian: @kbd{apt-get install tla}.
+@item Other distributions: see @uref{ftp://ftp.gnu.org/gnu/gnu-arch/}.
+@end itemize
+
+@item Register the archive.
+@example
+tla register-archive -f http://www.mwolson.org/archives/2006
+@end example
+
+@item Download the ERC source code.
+@example
+# Download ERC into the @file{erc} directory.
+tla get mwolson@@gnu.org--2006/erc--cvs--0 erc
+@end example
+
+@item List upstream changes that are missing from your local copy.
+Do this whenever you want to see whether new changes have been committed
+to ERC.
+
+@example
+# Change to the source directory you are interested in.
+cd erc/
+
+# Display the summary of changes
+tla missing --summary
+@end example
+
+@cindex updating ERC with Arch
+@item Update to the latest version by replaying missing changes.
+@example
+cd erc
+tla replay
+@end example
+
+@end enumerate
+
+There are other ways to interact with the ERC archive.
+
+@itemize
+@item Browse arch repository: @uref{http://www.mwolson.org/archives/}
+@item Latest development snapshot: @uref{http://www.mwolson.org/static/dist/erc-latest.tar.gz}
+@end itemize
+
+The latest development snapshot will be kept up-to-date since it is
+updated at the same time as the Arch repository.
+
+
+@node Installation, Getting Started, Obtaining ERC, Top
+@comment  node-name,  next,  previous,  up
+@chapter Installation
+
+ERC may be compiled and installed on your machine.
+
+This section may be skipped if you are using the version of ERC that
+comes with Emacs.
+
+@subsubheading Compilation
+
+This is an optional step, since Emacs Lisp source code does not
+necessarily have to be byte-compiled.  It will yield a speed increase,
+though.
+
+A working copy of Emacs or XEmacs is needed in order to compile ERC.  By
+default, the program that is installed with the name @command{emacs}
+will be used.
+
+If you want to use the @command{xemacs} binary to perform the
+compilation, you would need to edit @file{Makefile} in the top-level
+directory as follows.  You can put either a full path to an Emacs or
+XEmacs binary or just the command name, as long as it is in the
+@env{PATH}.
+
+@example
+EMACS    = xemacs
+SITEFLAG = -no-site-file
+@end example
+
+Running @code{make} should compile the ERC source files in the
+@file{lisp} directory.
+
+@subsubheading Installation
+
+ERC may be installed into your file hierarchy by doing the following.
+
+Edit the @file{Makefile} file so that @env{ELISPDIR} points to where you
+want the source and compiled ERC files to be installed and
+@env{INFODIR} indicates where to put the ERC manual.  Of course, you
+will want to edit @env{EMACS} and @env{SITEFLAG} as shown in the
+Compilation section if you are using XEmacs.
+
+If you are installing ERC on a Debian system, you might want to change
+the value of @env{INSTALLINFO} as specified in @file{Makefile}.
+
+Run @code{make} as a normal user.
+
+Run @code{make install} as the root user if you have chosen installation
+locations that require this.
+
+
+@node Getting Started, Keystroke Summary, Installation, Top
+@comment  node-name,  next,  previous,  up
+@chapter Getting Started
+@cindex settings
+
+@c PRE5_2: Mention .ercrc.el
+
+To use ERC, add the directory containing its files to your
+@code{load-path} variable, in your @file{.emacs} file.  Then, load ERC
+itself along with any extra modules you desire.  An example follows.
+
+@lisp
+(require 'erc)
+
+(require 'erc-spelling)
+@end lisp
+
+Once this is loaded, the command @kbd{M-x erc-select} will start ERC and
+prompt for the server to connect to.
+
+@c PRE5_2: Sample session, including:
+@c - connect to Freenode
+@c - /join #emacs
+@c - see messages flying past, point out topic lines, messages, channel
+@c   members
+@c - identifying your nick with NickServ (most IRC servers have this)
+@c - talking to the channel
+@c - open a /query buffer to talk to someone (must identify first in
+@c   FreeNode)
+
+
+@node Keystroke Summary, Modules, Getting Started, Top
+@comment  node-name,  next,  previous,  up
+@chapter Keys Used in ERC
+@cindex keystrokes
+
+This is a summary of keystrokes available in every ERC buffer.
+
+@table @kbd
+
+@item C-a or <home> (`erc-bol')
+Go to beginning of line or end of prompt.
+
+@item RET (`erc-send-current-line')
+Send the current line
+
+@item TAB (`erc-complete-word')
+If at prompt, complete the current word.
+Otherwise, move to the next link or button.
+
+@item M-TAB (`ispell-complete-word')
+Complete the given word, using ispell.
+
+@item C-c C-a (`erc-bol')
+Go to beginning of line or end of prompt.
+
+@item C-c C-b (`erc-iswitchb')
+Use `iswitchb-read-buffer' to prompt for a ERC buffer to switch to.
+
+@item C-c C-c (`erc-toggle-interpret-controls')
+Toggle interpretation of control sequences in messages.
+
+@item C-c C-d (`erc-input-action')
+Interactively input a user action and send it to IRC.
+
+@item C-c C-e (`erc-toggle-ctcp-autoresponse')
+Toggle automatic CTCP replies (like VERSION and PING).
+
+@item C-c C-f (`erc-toggle-flood-control')
+Toggle use of flood control on sent messages.
+
+@item C-c TAB (`erc-invite-only-mode')
+Turn on the invite only mode (+i) for the current channel.
+
+@item C-c C-j (`erc-join-channel')
+Join channel.  If point is at the beginning of a channel name, use that
+as default.
+
+@item C-c C-k (`erc-go-to-log-matches-buffer')
+Interactively open an erc-log-matches buffer
+
+@item C-c C-l (`erc-save-buffer-in-logs')
+Append buffer contents to the log file, if logging is enabled.
+
+@item C-c C-n (`erc-channel-names')
+Run "/names #channel" in the current channel.
+
+@item C-c C-o (`erc-get-channel-mode-from-keypress')
+Read a key sequence and call the corresponding channel mode function.
+After doing C-c C-o type in a channel mode letter.
+
+C-g means quit.
+RET let's you type more than one mode at a time.
+If "l" is pressed, `erc-set-channel-limit' gets called.
+If "k" is pressed, `erc-set-channel-key' gets called.
+Anything else will be sent to `erc-toggle-channel-mode'.
+
+@item C-c C-p (`erc-part-from-channel')
+Part from the current channel and prompt for a reason.
+
+@item C-c C-q (`erc-quit-server')
+Disconnect from current server after prompting for reason.
+
+@item C-c C-r (`erc-remove-text-properties-region')
+Clears the region (start,end) in object from all colors, etc.
+
+@item C-c C-t (`erc-set-topic')
+Prompt for a topic for the current channel.
+
+@item C-c C-u (`erc-kill-input')
+Kill current input line using `erc-bol' followed by `kill-line'.
+
+@end table
+
+
+@node Modules, Advanced Usage, Keystroke Summary, Top
+@comment  node-name,  next,  previous,  up
+@chapter Modules
+@cindex modules
+
+One way to add functionality to ERC is to customize which of its many
+modules are loaded.
+
+There is a spiffy customize interface, which may be reached by typing
+@kbd{M-x customize-option erc-modules RET}.  Alternatively, set
+@code{erc-modules} manually and then call @code{erc-update-modules}.
+
+The following is a list of available modules.
+
+@table @code
+
+@cindex modules, autoaway
+@item autoaway
+Set away status automatically.
+
+@cindex modules, autojoin
+@item autojoin
+Join channels automatically
+
+@cindex modules, bbdb
+@item bbdb
+Integrate with the Big Brother Database
+
+@cindex modules, button
+@item button
+Buttonize URLs, nicknames, and other text
+
+@cindex modules, fill
+@item fill
+Wrap long lines
+
+@cindex modules, irccontrols
+@item irccontrols
+Highlight or remove IRC control characters
+
+@cindex modules, log
+@item log
+Save buffers in logs
+
+@cindex modules, match
+@item match
+Highlight pals, fools, and other keywords
+
+@cindex modules, netsplit
+@item netsplit
+Detect netsplits
+
+@cindex modules, noncommands
+@item noncommands
+Don't display non-IRC commands after evaluation
+
+@cindex modules, notify
+@item notify
+Notify when the online status of certain users changes
+
+@cindex modules, pcomplete
+@item pcomplete
+Complete nicknames and commands (programmable)
+
+@cindex modules, readonly
+@item readonly
+Make displayed lines read-only
+
+@cindex modules, replace
+@item replace
+Replace text in messages
+
+@cindex modules, ring
+@item ring
+Enable an input history
+
+@cindex modules, scrolltobottom
+@item scrolltobottom
+Scroll to the bottom of the buffer
+
+@cindex modules, services
+@item services
+Identify to Nickserv (IRC Services) automatically
+
+@cindex modules, smiley
+@item smiley
+Convert smileys to pretty icons
+
+@cindex modules, sound
+@item sound
+Play sounds when you receive CTCP SOUND requests
+
+@cindex modules, spell
+@item spell
+Check spelling
+
+@cindex modules, stamp
+@item stamp
+Add timestamps to messages
+
+@cindex modules, track
+@item track
+Track channel activity in the mode-line
+
+@cindex modules, truncate
+@item truncate
+Truncate buffers to a certain size
+
+@cindex modules, unmorse
+@item unmorse
+Translate morse code in messages
+
+@end table
+
+@c PRE5_2: Document every option of every module in its own subnode
+
+
+@node Advanced Usage, Getting Help and Reporting Bugs, Modules, Top
+@comment  node-name,  next,  previous,  up
+@chapter Advanced Usage
+@cindex advanced topics
+
+Write me.
+
+@c PRE5_2: (Node) Document every ERC option
+
+@c PRE5_2: (Node) Tips and tricks
+
+@c PRE5_2: (Node) Sample configs
+
+
+@node Getting Help and Reporting Bugs, History, Advanced Usage, Top
+@comment  node-name,  next,  previous,  up
+@chapter Getting Help and Reporting Bugs
+@cindex help, getting
+@cindex bugs, reporting
+
+After you have read this guide, if you still have questions about ERC,
+or if you have bugs to report, there are several places you can go.
+
+@itemize @bullet
+
+@item
+@uref{http://www.emacswiki.org/cgi-bin/wiki/EmacsIRCClient} is the
+emacswiki.org page for ERC.  Anyone may add tips, hints, or bug
+descriptions to it.
+
+@item
+You can join the mailing list at @email{erc-help@@lists.sourceforge.net}
+using the subscription form at
+@uref{http://lists.sourceforge.net/lists/listinfo/erc-help}.
+
+This mailing list is also available via Gmane
+(@url{http://gmane.org/}). The group is called
+@samp{gmane.emacs.erc.general}.  This provides additional methods for
+accessing the mailing list, adding content to it, and searching it.
+
+@item
+You can visit the IRC Freenode channel @samp{#emacs}. Many of the
+contributors are frequently around and willing to answer your
+questions.
+
+@end itemize
+
+
+@node History, Concept Index, Getting Help and Reporting Bugs, Top
+@comment  node-name,  next,  previous,  up
+@chapter History
+@cindex history, of ERC
+
+ERC was originally written by Alexander L. Belikoff
+@email{abel@@bfr.co.il} and Sergey Berezin
+@email{sergey.berezin@@cs.cmu.edu}.  They stopped development around
+december 1999. Their last released version was ERC 2.0.
+
+P.S.: If one of the original developers of ERC reads this, we'd like to
+receive additional information for this file and hear comments in
+general.
+
+@itemize
+@item 2001
+
+In June 2001, Mario Lang @email{mlang@@delysid.org} and Alex Schroeder
+@email{alex@@gnu.org} took over development and created a ERC Project at
+sourceforge.net.
+
+In reaction to a mail about the new erc development, Sergey Berezin
+said, "First of all, I'm glad that my version of ERC is being used out
+there. The thing is, I do not have free time and enough incentive
+anymore to work on ERC, so I would be happy if you guys take over the
+project entirely."
+
+So we happily hacked away on ERC, and soon after (september 2001)
+released the next "stable" version, 2.1.
+
+Most of the development of the new ERC happend on #emacs on
+irc.openprojects.net. Over time, many people contributed code, ideas,
+bugfixes. And not to forget alot of alpha/beta/gamma testing.
+
+See the @file{CREDITS} file for a list of contributors.
+
+@item 2003
+
+ERC 3.0 is released.
+
+@item 2004
+
+ERC 4.0 is released.
+
+@item 2005
+
+ERC 5.0 is released.  Michael Olson @email{mwolson@@gnu.org} becomes
+the release manager and eventually the maintainer.
+
+After some discussion between him and the Emacs developers, it is
+decided to include ERC in Emacs.
+
+@item 2006
+
+ERC 5.1 is released.
+
+@end itemize
+
+@node Concept Index,  , History, Top
+@comment  node-name,  next,  previous,  up
+@unnumbered Index
+
+@printindex cp
+
+@bye
+
+@ignore
+   arch-tag: cf9cfaff-fc12-4297-ad15-ec2493002b1e
+@end ignore
--- a/man/faq.texi	Thu Jan 26 02:23:05 2006 +0000
+++ b/man/faq.texi	Wed Feb 01 10:07:17 2006 +0000
@@ -1146,7 +1146,7 @@
 
 @cindex New modes
 Many new modes and packages have been included in Emacs, such as Leim,
-Calc, Tramp and URL, as well as IDO, CUA, rcirc, conf-mode,
+Calc, Tramp and URL, as well as IDO, CUA, rcirc, ERC, conf-mode,
 python-mode, table, tumme, SES, ruler, Flymake, Org, etc.
 
 @cindex Documentation
--- a/man/fixit.texi	Thu Jan 26 02:23:05 2006 +0000
+++ b/man/fixit.texi	Wed Feb 01 10:07:17 2006 +0000
@@ -20,12 +20,126 @@
 available.  @xref{Undo}, for more information.
 
 @menu
+* Undo::        The Undo commands.
 * Kill Errors:: Commands to kill a batch of recently entered text.
 * Transpose::   Exchanging two characters, words, lines, lists...
 * Fixing Case:: Correcting case of last word entered.
 * Spelling::    Apply spelling checker to a word, or a whole file.
 @end menu
 
+@node Undo
+@section Undo
+@cindex undo
+@cindex changes, undoing
+
+  The @dfn{undo} commands undo recent changes in the buffer's text.
+Each buffer records changes individually, and the undo command always
+applies to the current buffer.  You can undo all the changes in a
+buffer for as far as back these records go.  Usually each editing
+command makes a separate entry in the undo records, but some commands
+such as @code{query-replace} divide their changes into multiple
+entries for flexibility in undoing.  Meanwhile, self-inserting
+characters are usually grouped to make undoing less tedious.
+
+@table @kbd
+@item C-x u
+@itemx C-_
+@itemx C-/
+Undo one entry in the current buffer's undo records (@code{undo}).
+@end table
+
+@kindex C-x u
+@kindex C-_
+@kindex C-/
+@findex undo
+  To begin to undo, type the command @kbd{C-x u} (or its aliases,
+@kbd{C-_} or @kbd{C-/}).  This undoes the most recent change in the
+buffer, and moves point back to where it was before that change.
+
+  Consecutive repetitions of @kbd{C-x u} (or its aliases) undo earlier
+and earlier changes in the current buffer, back to the limit of the
+current buffer's undo records.  If all the recorded changes have
+already been undone, the undo command just signals an error.
+
+  If you notice that a buffer has been modified accidentally, the
+easiest way to recover is to type @kbd{C-_} repeatedly until the stars
+disappear from the front of the mode line.  At this time, all the
+modifications you made have been canceled.  Whenever an undo command
+makes the stars disappear from the mode line, it means that the buffer
+contents are the same as they were when the file was last read in or
+saved.
+
+  If you do not remember whether you changed the buffer deliberately,
+type @kbd{C-_} once.  When you see the last change you made undone, you
+will see whether it was an intentional change.  If it was an accident,
+leave it undone.  If it was deliberate, redo the change as described
+below.
+
+@findex undo-only
+  Any command other than an undo command breaks the sequence of undo
+commands.  Starting from that moment, the previous undo commands
+become ordinary changes that you can undo.  Thus, to redo changes you
+have undone, type @kbd{C-f} or any other command that will harmlessly
+break the sequence of undoing, then type undo commands again.  On the
+other hand, if you want to resume undoing, without redoing previous
+undo commands, use @kbd{M-x undo-only}.  This is like @code{undo}, but
+will not redo changes you have just undone.
+
+@cindex selective undo
+@kindex C-u C-x u
+  Ordinary undo applies to all changes made in the current buffer.  You
+can also perform @dfn{selective undo}, limited to the region.
+
+  To do this, specify the region you want, then run the @code{undo}
+command with a prefix argument (the value does not matter): @kbd{C-u
+C-x u} or @kbd{C-u C-_}.  This undoes the most recent change in the
+region.  To undo further changes in the same region, repeat the
+@code{undo} command (no prefix argument is needed).  In Transient Mark
+mode (@pxref{Transient Mark}), any use of @code{undo} when there is an
+active region performs selective undo; you do not need a prefix
+argument.
+
+  Some specialized buffers do not make undo records.  Buffers
+whose names start with spaces never do; these buffers are used
+internally by Emacs and its extensions to hold text that users don't
+normally look at or edit.
+
+@vindex undo-limit
+@vindex undo-strong-limit
+@vindex undo-outer-limit
+@cindex undo limit
+  When the undo records for a buffer becomes too large, Emacs
+discards the oldest undo records from time to time (during garbage
+collection).  You can specify how much undo records to keep by
+setting three variables: @code{undo-limit}, @code{undo-strong-limit},
+and @code{undo-outer-limit}.  Their values are expressed in units of
+bytes of space.
+
+  The variable @code{undo-limit} sets a soft limit: Emacs keeps undo
+data for enough commands to reach this size, and perhaps exceed it,
+but does not keep data for any earlier commands beyond that.  Its
+default value is 20000.  The variable @code{undo-strong-limit} sets a
+stricter limit: a previous command (not the most recent one) which
+pushes the size past this amount is itself forgotten.  The default
+value of @code{undo-strong-limit} is 30000.
+
+  Regardless of the values of those variables, the most recent change
+is never discarded unless it gets bigger than @code{undo-outer-limit}
+(normally 3,000,000).  At that point, Emacs discards the undo data and
+warns you about it.  This is the only situation in which you cannot
+undo the last command.  If this happens, you can increase the value of
+@code{undo-outer-limit} to make it even less likely to happen in the
+future.  But if you didn't expect the command to create such large
+undo data, then it is probably a bug and you should report it.
+@xref{Bugs,, Reporting Bugs}.
+
+  The reason the @code{undo} command has three key bindings, @kbd{C-x
+u}, @kbd{C-_} and @kbd{C-/}, is that it is worthy of a
+single-character key, but @kbd{C-x u} is more straightforward for
+beginners to remember and type.  Meanwhile, @kbd{C--} on a text-only
+terminal is really @kbd{C-_}, which makes it a natural and easily
+typed binding for undoing.
+
 @node Kill Errors
 @section Killing Your Mistakes
 
@@ -41,7 +155,7 @@
   The @key{DEL} character (@code{delete-backward-char}) is the most
 important correction command.  It deletes the character before point.
 When @key{DEL} follows a self-inserting character command, you can think
-of it as canceling that command.  However, avoid the mistake of thinking
+of it as canceling that command.  However, avoid the confusion of thinking
 of @key{DEL} as a general way to cancel a command!
 
   When your mistake is longer than a couple of characters, it might be
@@ -152,9 +266,9 @@
 
   This section describes the commands to check the spelling of a single
 word or of a portion of a buffer.  These commands work with the spelling
-checker program Ispell, which is not part of Emacs.
+checker programs Aspell and Ispell, which are not part of Emacs.
 @ifinfo
-@xref{Top, Ispell, Overview ispell, ispell, The Ispell Manual}.
+@xref{Top, Aspell,, aspell, The Aspell Manual}.
 @end ifinfo
 
 @table @kbd
@@ -178,9 +292,9 @@
 Check and correct spelling of each word in a draft mail message,
 excluding cited material.
 @item M-x ispell-change-dictionary @key{RET} @var{dict} @key{RET}
-Restart the Ispell process, using @var{dict} as the dictionary.
+Restart the Aspell or Ispell process, using @var{dict} as the dictionary.
 @item M-x ispell-kill-ispell
-Kill the Ispell subprocess.
+Kill the Aspell or Ispell subprocess.
 @end table
 
 @cindex Flyspell mode
@@ -261,7 +375,7 @@
 editing session and for this buffer.
 
 @item i
-Insert this word in your private dictionary file so that Ispell will
+Insert this word in your private dictionary file so that Aspell or Ispell will
 consider it correct from now on, even in future sessions.
 
 @item u
@@ -328,26 +442,27 @@
 
 @cindex @code{ispell} program
 @findex ispell-kill-ispell
-  Once started, the Ispell subprocess continues to run (waiting for
-something to do), so that subsequent spell checking commands complete
-more quickly.  If you want to get rid of the Ispell process, use
-@kbd{M-x ispell-kill-ispell}.  This is not usually necessary, since the
-process uses no time except when you do spelling correction.
+  Once started, the Aspell or Ispell subprocess continues to run
+(waiting for something to do), so that subsequent spell checking
+commands complete more quickly.  If you want to get rid of the
+process, use @kbd{M-x ispell-kill-ispell}.  This is not usually
+necessary, since the process uses no time except when you do spelling
+correction.
 
 @vindex ispell-dictionary
-  Ispell uses two dictionaries together for spell checking: the
+  Ispell and Aspell use two dictionaries together for spell checking: the
 standard dictionary and your private dictionary.  The variable
 @code{ispell-dictionary} specifies the file name to use for the
 standard dictionary; a value of @code{nil} selects the default
 dictionary.  The command @kbd{M-x ispell-change-dictionary} sets this
-variable and then restarts the Ispell subprocess, so that it will use
+variable and then restarts the subprocess, so that it will use
 a different standard dictionary.
 
 @vindex ispell-complete-word-dict
-  Ispell uses a separate dictionary for word completion.  The variable
-@code{ispell-complete-word-dict} specifies the file name of this
-dictionary.  The completion dictionary must be different because it
-cannot use root and affix information.  For some languages
+  Aspell and Ispell use a separate dictionary for word completion.
+The variable @code{ispell-complete-word-dict} specifies the file name
+of this dictionary.  The completion dictionary must be different
+because it cannot use root and affix information.  For some languages
 there is a spell checking dictionary but no word completion
 dictionary.
 
--- a/man/help.texi	Thu Jan 26 02:23:05 2006 +0000
+++ b/man/help.texi	Wed Feb 01 10:07:17 2006 +0000
@@ -12,17 +12,19 @@
 @kindex F1
 
   Emacs provides extensive help features accessible through a single
-character, @kbd{C-h}.  @kbd{C-h} is a prefix key that is used for
-commands that display documentation.  The characters that you can type after
-@kbd{C-h} are called @dfn{help options}.  One help option is @kbd{C-h};
-that is how you ask for help about using @kbd{C-h}.  To cancel, type
-@kbd{C-g}.  The function key @key{F1} is equivalent to @kbd{C-h}.
+character, @kbd{C-h} (or @key{F1}).  @kbd{C-h} is a prefix key that is
+used for commands that display documentation.  The characters that you
+can type after @kbd{C-h} are called @dfn{help options}.  One help
+option is @kbd{C-h}; that is how you ask for help about using
+@kbd{C-h}.  To cancel, type @kbd{C-g}.  The function key @key{F1} is
+equivalent to @kbd{C-h}.
 
 @kindex C-h C-h
 @findex help-for-help
   @kbd{C-h C-h} (@code{help-for-help}) displays a list of the possible
-help options, each with a brief description.  Before you type a help
-option, you can use @key{SPC} or @key{DEL} to scroll through the list.
+help options, each with a brief description.  You can look at the
+list, using @key{SPC} and @key{DEL} to scroll through it, then type
+the help option you want.  To cancel, type @kbd{C-g}.
 
   @kbd{C-h} or @key{F1} means ``help'' in various other contexts as
 well.  After a prefix key, it displays a list of the alternatives that
@@ -70,13 +72,6 @@
 pertinent to the feature you need.  @xref{Library Keywords}.
 @end table
 
-  To find the documentation of a key sequence or a menu item, type
-@kbd{C-h K} and then type that key sequence or select the menu
-item.  This looks up the description of the command invoked by the key
-or the menu in the appropriate manual (not necessarily the Emacs
-manual).  Likewise, use @kbd{C-h F} for reading documentation of a
-command.
-
 @menu
 * Help Summary::	Brief list of all Help commands.
 * Key Help::		Asking what a key does in Emacs.
@@ -100,7 +95,8 @@
 
   Here is a summary of the Emacs interactive help commands.
 @xref{Help Files}, for other help commands that just display a
-pre-written file of information.
+pre-written file of information.  The character that follows
+@kbd{C-h} is a ``help option.''
 
 @table @kbd
 @item C-h a @var{topics} @key{RET}
@@ -180,7 +176,7 @@
 
 @kindex C-h c
 @findex describe-key-briefly
-  The most basic @kbd{C-h} options are @kbd{C-h c}
+  The most basic @kbd{C-h} commands are @kbd{C-h c}
 (@code{describe-key-briefly}) and @w{@kbd{C-h k}} (@code{describe-key}).
 @kbd{C-h c @var{key}} displays in the echo area the name of the command
 that @var{key} is bound to.  For example, @kbd{C-h c C-f} displays
@@ -194,8 +190,19 @@
 displays the documentation string of the command as well as its name.
 This is too big for the echo area, so a window is used for the display.
 
-  @kbd{C-h c} and @kbd{C-h k} work for any sort of key sequences,
-including function keys and mouse events.
+@kindex C-h K
+@findex Info-goto-emacs-key-command-node
+  To find the documentation of a key sequence, type @kbd{C-h K} and
+then enter that key sequence.  This looks up the description of the
+command invoked by the key in whichever manual describes it (this need
+not be the Emacs manual).  @kbd{C-h K} runs the command
+@code{Info-goto-emacs-key-command-node}.
+
+  @kbd{C-h c}, @kbd{C-h k} and @kbd{C-h K} work for any sort of key
+sequences, including function keys, menus, and mouse events.  For
+instance, you can type @kbd{C-h k} and then select a menu item from
+the menu bar, to show the documentation string of the command that
+menu item runs.
 
 @kindex C-h w
 @findex where-is
@@ -256,9 +263,18 @@
 hyperlinks to the definition, if you have the source files installed.
 (@xref{Hyperlinking}.)  If you know Lisp (or C), this provides the
 ultimate documentation.  If you don't know Lisp, you should learn it.
-If you are just @emph{using} Emacs, treating Emacs as an object
-(file), then you don't really love it.  For true intimacy with your
-editor, you need to read the source code.
+(The Introduction to Emacs Lisp Programming, available from the FSF
+through fsf.org, is a good way to get started.)  Emacs won't be happy
+if it feels you are just @emph{using} Emacs, treating it as an object
+program.  If you really love Emacs, show that you care by reading the
+source code.
+
+@kindex C-h F
+@findex Info-goto-emacs-command-node
+  To find a specific function's documentation in a manual, use
+@kbd{C-h F} (@code{Info-goto-emacs-command-node}).  This knows
+about various manuals, not just the Emacs manual, and finds the
+right one.
 
 @node Apropos
 @section Apropos
@@ -432,8 +448,8 @@
 the support for a specific language environment.  @xref{Language
 Environments}.  This tells you which languages this language
 environment is useful for, and lists the character sets, coding
-systems, and input methods that go with it.  It also shows some sample
-text to illustrate scripts.
+systems, and input methods that it operates on.  It also shows some
+sample text to illustrate scripts.
 
   The command @kbd{C-h h} (@code{view-hello-file}) displays the file
 @file{etc/HELLO}, which shows how to say ``hello'' in many languages.
@@ -456,9 +472,7 @@
 @item @key{SPC}
 Scroll forward.
 @item @key{DEL}
-@itemx @key{BS}
-Scroll backward.  On some keyboards, this key is known as @key{BS} or
-@key{backspace}.
+Scroll backward.
 @item @key{RET}
 Follow a cross reference at point.
 @item @key{TAB}
@@ -521,24 +535,9 @@
 need to get to the documentation quickly, and you know the exact name
 of the file.
 
-@kindex C-h F
-@kindex C-h K
-@findex Info-goto-emacs-key-command-node
-@findex Info-goto-emacs-command-node
-  There are two special help commands for accessing Emacs
-documentation through Info.  @kbd{C-h F @var{function} @key{RET}}
-enters Info and goes straight to the documentation of the Emacs
-function @var{function}.  @kbd{C-h K @var{key}} enters Info and goes
-straight to the documentation of the key @var{key}.  These two keys
-run the commands @code{Info-goto-emacs-command-node} and
-@code{Info-goto-emacs-key-command-node}.  You can use @kbd{C-h K} to
-find the documentation of a menu item: just select that menu item when
-@kbd{C-h K} prompts for a key.
-
-  @kbd{C-h F} and @kbd{C-h K} know about commands and keys described
-in manuals other than the Emacs manual.  Thus, they make it easier to
-find the documentation of commands and keys when you are not sure
-which manual describes them, like when using some specialized mode.
+  The help commands @kbd{C-h F @var{function} @key{RET}} and @kbd{C-h
+K @var{key}}, described above, enter Info and go straight to the
+documentation of @var{function} or @var{key}.
 
 @kindex C-h S
 @findex info-lookup-symbol
--- a/man/killing.texi	Thu Jan 26 02:23:05 2006 +0000
+++ b/man/killing.texi	Wed Feb 01 10:07:17 2006 +0000
@@ -84,8 +84,7 @@
 binds it to @code{delete-char} as well.
 @item @key{DEL}
 @itemx @key{BS}
-Delete previous character (@code{delete-backward-char}).  Some keyboards
-refer to this key as a ``backspace key'' and label it with a left arrow.
+Delete previous character (@code{delete-backward-char}).
 @item M-\
 Delete spaces and tabs around point (@code{delete-horizontal-space}).
 @item M-@key{SPC}
@@ -112,11 +111,12 @@
 @kindex BACKSPACE
 @kindex BS
 @kindex DELETE
-  Every keyboard has a large key, labeled @key{DEL}, @key{BACKSPACE},
-@key{BS} or @key{DELETE}, which is a short distance above the
+  Every keyboard has a large key which is a short distance above the
 @key{RET} or @key{ENTER} key and is normally used for erasing what you
-have typed.  Regardless of the actual name on the key, in Emacs it is
-equivalent to @key{DEL}---or it should be.
+have typed.  It may be labeled @key{DEL}, @key{BACKSPACE}, @key{BS},
+@key{DELETE}, or even with a left arrow.  Regardless of the label on
+the key, in Emacs it called @key{DEL}, and it should delete one
+character backwards.
 
   Many keyboards (including standard PC keyboards) have a
 @key{BACKSPACE} key a short ways above @key{RET} or @key{ENTER}, and a
@@ -251,22 +251,23 @@
 @kbd{M-k} (@pxref{Sentences}).@refill
 
 @node Graphical Kill
-@subsection Killing on Graphical Terminals
+@subsection Killing on Graphical Displays
 
-  On multi-window terminals, the most recent kill done in Emacs is
-also the primary selection, if it is more recent than any selection
-you made in another program.  This means that the paste commands of
-other applications with separate windows copy the text that you killed
-in Emacs.  In addition, Emacs yank commands treat other applications'
-selections as part of the kill ring, so you can yank them into Emacs.
+  On graphical displays with window systems, the most recent kill done
+in Emacs is also the primary selection, if it is more recent than any
+selection you made in another program.  This means that the paste
+commands of other window-based applications copy the text that you
+killed in Emacs.  In addition, Emacs yank commands treat other
+applications' selections as part of the kill ring, so you can yank
+them into Emacs.
 
 @cindex Delete Selection mode
 @cindex mode, Delete Selection
 @findex delete-selection-mode
   Many window systems follow the convention that insertion while text
 is selected deletes the selected text.  You can make Emacs behave this
-way by enabling Delete Selection mode, with @kbd{M-x
-delete-selection-mode}, or using Custom.  Another effect of this mode
+way by enabling Delete Selection mode---with @kbd{M-x
+delete-selection-mode} or using Custom.  Another effect of this mode
 is that @key{DEL}, @kbd{C-d} and some other keys, when a selection
 exists, will kill the whole selection.  It also enables Transient Mark
 mode (@pxref{Transient Mark}).
@@ -297,10 +298,10 @@
 Append next kill to last batch of killed text (@code{append-next-kill}).
 @end table
 
-  On window systems, if there is a current selection in some other
-application, and you selected it more recently than you killed any
-text in Emacs, @kbd{C-y} copies the selection instead of text
-killed within Emacs.
+  On graphical displays with window systems, if there is a current
+selection in some other application, and you selected it more recently
+than you killed any text in Emacs, @kbd{C-y} copies the selection
+instead of text killed within Emacs.
 
 @menu
 * Kill Ring::		Where killed text is stored.  Basic yanking.
@@ -601,7 +602,8 @@
 rectangle is not stored in the kill ring, but in a special place that
 can only record the most recent rectangle killed.  This is because yanking
 a rectangle is so different from yanking linear text that different yank
-commands have to be used and yank-popping is hard to make sense of.
+commands have to be used.  It is hard to define yank-popping for rectangles,
+so we do not try.
 
 @kindex C-x r y
 @findex yank-rectangle
@@ -665,7 +667,7 @@
 paste (yank), and @kbd{C-z} undo.  Standard Emacs commands like
 @kbd{C-x C-c} still work, because @kbd{C-x} and @kbd{C-c} only take
 effect when the mark is active (and the region is highlighted).
-However, if you don't want these bindings at all, set
+However, if you don't want to override these bindings Emacs at all, set
 @code{cua-enable-cua-keys} to @code{nil}.
 
   In CUA mode, using @kbd{Shift} together with the movement keys
@@ -674,10 +676,10 @@
 replaces the active region as in Delete-Selection mode
 (@pxref{Graphical Kill}).
 
-  To run a command like @kbd{C-x C-f} while the mark is active, use
-one of the following methods: either hold @kbd{Shift} together with
-the prefix key, e.g. @kbd{S-C-x C-f}, or quickly type the prefix key
-twice, e.g. @kbd{C-x C-x C-f}.
+  To enter an Emacs command like @kbd{C-x C-f} while the mark is
+active, use one of the following methods: either hold @kbd{Shift}
+together with the prefix key, e.g. @kbd{S-C-x C-f}, or quickly type
+the prefix key twice, e.g. @kbd{C-x C-x C-f}.
 
 @cindex rectangle highlighting
   CUA mode provides enhanced rectangle support with visible
--- a/man/m-x.texi	Thu Jan 26 02:23:05 2006 +0000
+++ b/man/m-x.texi	Wed Feb 01 10:07:17 2006 +0000
@@ -8,10 +8,10 @@
   Every Emacs command has a name that you can use to run it.  Commands
 that are used often, or that must be quick to type, are also bound to
 keys---short sequences of characters---for convenient use.  You can
-run them by name if you don't remember the keys.  Other Emacs commands
-that do not need to be quick are not bound to keys; the only way to
-run them is by name.  @xref{Key Bindings}, for the description of
-how to bind commands to keys.
+run them by typing the keys, or run them by name if you don't remember
+the keys.  Other Emacs commands that do not need to be quick are not
+bound to keys; the only way to run them is by name.  @xref{Key
+Bindings}, for the description of how to bind commands to keys.
 
   By convention, a command name consists of one or more words,
 separated by hyphens; for example, @code{auto-fill-mode} or
@@ -47,9 +47,9 @@
 the key @kbd{C-f}.  You can run any Emacs command by name using
 @kbd{M-x}, whether or not any keys are bound to it.
 
-  If you type @kbd{C-g} while the command name is being read, you
-cancel the @kbd{M-x} command and get out of the minibuffer, ending up
-at command level.
+  If you type @kbd{C-g} while the command name is being read, that
+cancels the @kbd{M-x} command and exits the minibuffer, so you end up
+back at command level.
 
   To pass a numeric argument to the command you are invoking with
 @kbd{M-x}, specify the numeric argument before the @kbd{M-x}.  @kbd{M-x}
@@ -58,10 +58,11 @@
 
 @vindex suggest-key-bindings
   If the command you type has a key binding of its own, Emacs mentions
-this in the echo area.  For example, if you type @kbd{M-x
-forward-word}, the message says that you can run the same command more
-easily by typing @kbd{M-f}.  You can turn off these messages by
-setting @code{suggest-key-bindings} to @code{nil}.
+this in the echo area after running the command.  For example, if you
+type @kbd{M-x forward-word}, the message says that you can run the
+same command more easily by typing @kbd{M-f}.  You can turn off these
+messages by setting the variable @code{suggest-key-bindings} to
+@code{nil}.
 
   Normally, when describing in this manual a command that is run by
 name, we omit the @key{RET} that is needed to terminate the name.  Thus
--- a/man/makefile.w32-in	Thu Jan 26 02:23:05 2006 +0000
+++ b/man/makefile.w32-in	Wed Feb 01 10:07:17 2006 +0000
@@ -42,7 +42,7 @@
 		$(infodir)/woman $(infodir)/eshell $(infodir)/org \
 		$(infodir)/url $(infodir)/speedbar $(infodir)/tramp \
 		$(infodir)/ses $(infodir)/smtpmail $(infodir)/flymake \
-		$(infodir)/newsticker
+		$(infodir)/newsticker $(infodir)/rcirc $(infodir)/erc
 DVI_TARGETS = 	emacs.dvi calc.dvi cc-mode.dvi cl.dvi dired-x.dvi \
 		 ediff.dvi forms.dvi gnus.dvi message.dvi emacs-mime.dvi \
                  gnus.dvi message.dvi sieve.dvi pgg.dvi mh-e.dvi \
@@ -50,7 +50,7 @@
 		 ada-mode.dvi autotype.dvi idlwave.dvi eudc.dvi ebrowse.dvi \
 		 pcl-cvs.dvi woman.dvi eshell.dvi org.dvi url.dvi \
 		 speedbar.dvi tramp.dvi ses.dvi smtpmail.dvi flymake.dvi \
-                 newsticker.dvi emacs-xtra.dvi
+                 newsticker.dvi emacs-xtra.dvi rcirc.dvi erc.dvi
 INFOSOURCES = info.texi
 
 # The following rule does not work with all versions of `make'.
@@ -331,6 +331,16 @@
 newsticker.dvi: newsticker.texi
 	$(ENVADD) $(TEXI2DVI) $(srcdir)/newsticker.texi
 
+$(infodir)/rcirc: rcirc.texi
+	$(MAKEINFO) rcirc.texi
+rcirc.dvi: rcirc.texi
+	$(ENVADD) $(TEXI2DVI) $(srcdir)/rcirc.texi
+
+$(infodir)/erc: erc.texi
+	$(MAKEINFO) erc.texi
+erc.dvi: erc.texi
+	$(ENVADD) $(TEXI2DVI) $(srcdir)/erc.texi
+
 mostlyclean:
 	- $(DEL) *.log *.cp *.fn *.ky *.pg *.vr core *.tp *.core gnustmp.*
 
@@ -351,7 +361,9 @@
 		 $(infodir)/speedbar* $(infodir)/tramp* \
 		 $(infodir)/ses* $(infodir)/smtpmail* \
 		 $(infodir)/url* $(infodir)/org* \
-		 $(infodir)/flymake*
+		 $(infodir)/flymake* $(infodir)/newsticker* \
+		 $(infodir)/sieve* $(infodir)/pgg* \
+		 $(infodir)/erc* $(infodir)/rcirc*
 
 distclean: clean
 
--- a/man/mark.texi	Thu Jan 26 02:23:05 2006 +0000
+++ b/man/mark.texi	Wed Feb 01 10:07:17 2006 +0000
@@ -87,9 +87,11 @@
 mouse button, and sets the mark at the other end of that range.  Or you
 can click mouse button three, which sets the mark at point (like
 @kbd{C-@key{SPC}}) and then moves point where you clicked (like
-@kbd{Mouse-1}).  Both of these methods copy the region into the kill
+@kbd{Mouse-1}).
+
+  Using the mouse to mark a region copies the region into the kill
 ring in addition to setting the mark; that gives behavior consistent
-with other window-driven applications, but if you don't want to modify
+with other window-driven applications.  If you don't want to modify
 the kill ring, you must use keyboard commands to set the mark.
 @xref{Mouse Commands}.
 
@@ -297,6 +299,8 @@
 Print hardcopy with @kbd{M-x print-region} (@pxref{Printing}).
 @item
 Evaluate it as Lisp code with @kbd{M-x eval-region} (@pxref{Lisp Eval}).
+@item
+Undo changes within it using @kbd{C-u C-x u} (@pxref{Undo}).
 @end itemize
 
   Most commands that operate on the text in the region have the word
@@ -347,12 +351,12 @@
 marks @var{n} paragraphs, running back form the one surrounding point.
 In that last case, point moves forward to the end of that paragraph,
 and the mark goes at the start of the region.  Repeating the @kbd{M-h}
-command extends the region, just as with @kbd{M-@@} and @kbd{C-M-@@}.
+command extends the region to subsequent paragraphs.
 
   @kbd{C-M-h} (@code{mark-defun}) similarly puts point before, and the
 mark after, the current (or following) major top-level definition, or
-defun (@pxref{Moving by Defuns}).  Repeating @kbd{C-M-h} also extends
-the region.
+defun (@pxref{Moving by Defuns}).  Repeating @kbd{C-M-h} extends
+the region to subsequent defuns.
 
   @kbd{C-x C-p} (@code{mark-page}) puts point before the current page,
 and mark at the end (@pxref{Pages}).  The mark goes after the
--- a/man/message.texi	Thu Jan 26 02:23:05 2006 +0000
+++ b/man/message.texi	Wed Feb 01 10:07:17 2006 +0000
@@ -9,7 +9,7 @@
 This file documents Message, the Emacs message composition mode.
 
 Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
-   2005 Free Software Foundation, Inc.
+   2005, 2006 Free Software Foundation, Inc.
 
 @quotation
 Permission is granted to copy, distribute and/or modify this document
@@ -1386,8 +1386,23 @@
 
 @item message-alternative-emails
 @vindex message-alternative-emails
-A regexp to match the alternative email addresses.  The first matched
-address (not primary one) is used in the @code{From} field.
+Regexp matching alternative email addresses.  The first address in the
+To, Cc or From headers of the original article matching this variable is
+used as the From field of outgoing messages, replacing the default From
+value.
+
+For example, if you have two secondary email addresses john@@home.net
+and john.doe@@work.com and want to use them in the From field when
+composing a reply to a message addressed to one of them, you could set
+this variable like this:
+
+@lisp
+(setq message-alternative-emails
+      (regexp-opt '("john@@home.net" "john.doe@@work.com")))
+@end lisp
+
+This variable has precedence over posting styles and anything that runs
+off @code{message-setup-hook}.
 
 @item message-allow-no-recipients
 @vindex message-allow-no-recipients
--- a/man/mini.texi	Thu Jan 26 02:23:05 2006 +0000
+++ b/man/mini.texi	Wed Feb 01 10:07:17 2006 +0000
@@ -114,10 +114,10 @@
 the terminal allows it; to disable this, turn off
 @code{file-name-shadow-mode} minor mode.
 
-  If you set @code{insert-default-directory} to @code{nil}, the default
-directory is not inserted in the minibuffer.  This way, the minibuffer
-starts out empty.  But the name you type, if relative, is still
-interpreted with respect to the same default directory.
+  If you set @code{insert-default-directory} to @code{nil}, the
+default directory is never inserted in the minibuffer---so the
+minibuffer starts out empty.  But the name you type, if relative, is
+still interpreted with respect to the same default directory.
 
 @node Minibuffer Edit
 @section Editing in the Minibuffer
@@ -128,17 +128,17 @@
 
   Since @key{RET} in the minibuffer is defined to exit the minibuffer,
 you can't use it to insert a newline in the minibuffer.  To do that,
-type @kbd{C-o} or @kbd{C-q C-j}.  (On text terminals, newline is
-really the @acronym{ASCII} character control-J.)
+type @kbd{C-o} or @kbd{C-q C-j}.  (The newline character is really the
+@acronym{ASCII} character control-J.)
 
-  The minibuffer has its own window which always has space on the screen
-but acts as if it were not there when the minibuffer is not in use.  When
-the minibuffer is in use, its window is just like the others; you can
-switch to another window with @kbd{C-x o}, edit text in other windows and
-perhaps even visit more files, before returning to the minibuffer to submit
-the argument.  You can kill text in another window, return to the
-minibuffer window, and then yank the text to use it in the argument.
-@xref{Windows}.
+  The minibuffer has its own window, which normally has space on the
+Emacs frame at all times, but it only acts like an Emacs window when
+the minibuffer is really in use.  At those times, its window is much
+like any other Emacs window; you can switch from the minibuffer window
+to another window with @kbd{C-x o}, and edit text in other windows,
+before returning to the minibuffer to submit the argument.  You can
+kill text in another window, return to the minibuffer window, and then
+yank the text to use it in the argument.  @xref{Windows}.
 
 @cindex height of minibuffer
 @cindex size of minibuffer
@@ -389,11 +389,11 @@
 
   If an element of the list in @code{completion-ignored-extensions} ends
 in a slash @file{/}, it indicates a subdirectory that should be ignored
-when completing file names.  (Elements of
+when completing file names.  Elements of
 @code{completion-ignored-extensions} which do not end in a slash are
 never considered when a completion candidate is a directory; thus,
 completion returns directories whose names end in @file{.elc} even
-though there's an element @code{".elc"} in the list.)
+though there's an element @code{".elc"} in the list.
 
 @vindex completion-auto-help
   Normally, a completion command that cannot determine even one
@@ -486,12 +486,9 @@
 ``moved'' to, but your new argument does go at the end of the history
 list in its own right.
 
-  For many minibuffer arguments there is a ``default'' value.  In some
-cases, the minibuffer history commands know the default value.  Then you
-can insert the default value into the minibuffer as text by using
-@kbd{M-n} to move ``into the future'' in the history.  Eventually we
-hope to make this feature available whenever the minibuffer has a
-default value.
+  For many minibuffer arguments there is a ``default'' value.  Then
+you can insert the default value into the minibuffer as text by using
+@kbd{M-n} to move ``into the future'' in the history.
 
 @findex previous-matching-history-element
 @findex next-matching-history-element
--- a/man/msdog.texi	Thu Jan 26 02:23:05 2006 +0000
+++ b/man/msdog.texi	Wed Feb 01 10:07:17 2006 +0000
@@ -3,25 +3,28 @@
 @c   2002, 2003, 2004, 2005 Free Software Foundation, Inc.
 @c See file emacs.texi for copying conditions.
 @node MS-DOS, Manifesto, Mac OS, Top
-@appendix Emacs and MS-DOS
+@appendix Emacs and Microsoft Systems
 @cindex MS-DOG
+@cindex Microsoft Windows
 @cindex MS-DOS peculiarities
 
-  This section briefly describes the peculiarities of using Emacs under
-the MS-DOS ``operating system'' (also known as ``MS-DOG'').  If you
-build Emacs for MS-DOS, the binary will also run on Windows 3.X, Windows
-NT, Windows 9X/ME, Windows 2000, or OS/2 as a DOS application; the
-information in this chapter applies for all of those systems, if you use
-an Emacs that was built for MS-DOS.
+  This section briefly describes the peculiarities of using Emacs on
+the MS-DOS ``operating system'' (also known as ``MS-DOG'') and on
+Microsoft Windows.
+
+  If you build Emacs for MS-DOS, the binary will also run on Windows
+3.X, Windows NT, Windows 9X/ME, Windows 2000, or OS/2 as a DOS
+application; all the of this chapter applies for all of those systems,
+if you use an Emacs that was built for MS-DOS.
 
-  Note that it is possible to build Emacs specifically for Windows NT/2K
-or Windows 9X/ME.  If you do that, most of this chapter does not apply;
-instead, you get behavior much closer to what is documented in the rest
-of the manual, including support for long file names, multiple frames,
-scroll bars, mouse menus, and subprocesses.  However, the section on
-text files and binary files does still apply.  There are also two
-sections at the end of this chapter which apply specifically for the
-Windows version.
+  However, if you want to use Emacs on Windows, you would normally
+build Emacs specifically for Windows.  If you do that, most of this
+chapter does not apply; instead, you get behavior much closer to what
+is documented in the rest of the manual, including support for long
+file names, multiple frames, scroll bars, mouse menus, and
+subprocesses.  However, the section on text files and binary files
+does still apply.  There are also two sections at the end of this
+chapter which apply specifically for the Windows version.
 
 @menu
 * Keyboard: MS-DOS Keyboard.   Keyboard conventions on MS-DOS.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/man/rcirc.texi	Wed Feb 01 10:07:17 2006 +0000
@@ -0,0 +1,666 @@
+\input texinfo
+@c %**start of header
+@setfilename ../info/rcirc
+@settitle rcirc Manual
+@c %**end of header
+
+@copying
+Copyright (C) 2006 Free Software Foundation, Inc.
+
+@quotation
+Permission is granted to copy, distribute and/or modify this document
+under the terms of the GNU Free Documentation License, Version 1.2 or
+any later version published by the Free Software Foundation; with no
+Invariant Sections, with the Front-Cover texts being ``A GNU Manual'',
+and with the Back-Cover Texts as in (a) below.  A copy of the license is
+included in the section entitled ``GNU Free Documentation License'' in
+the Emacs manual.
+
+(a) The FSF's Back-Cover Text is: ``You have freedom to copy and modify
+this GNU Manual, like GNU software.  Copies published by the Free
+Software Foundation raise funds for GNU development.''
+
+This document is part of a collection distributed under the GNU Free
+Documentation License.  If you want to distribute this document
+separately from the collection, you can do so by adding a copy of the
+license to the document, as described in section 6 of the license.
+@end quotation
+@end copying
+
+@dircategory Emacs
+@direntry
+* Rcirc: (rcirc).       Internet Relay Chat (IRC) client.
+@end direntry
+
+@titlepage
+@title rcirc Manual
+@page
+@vskip 0pt plus 1filll
+@insertcopying
+@end titlepage
+
+@ifnottex
+@node Top, Basics, (dir), (dir)
+@top rcirc Manual
+@end ifnottex
+
+@code{rcirc} is an Emacs IRC client.
+
+IRC (Internet Relay Chat) is a multi-user chat protocol.  Users
+communicate with each other in real-time.  Communication occurs both in
+topic channels which are collections of many users, or privately, with
+just one other user.
+
+@menu
+* Basics::
+* Reference::
+* Hacking and Tweaking::
+* Key Index::
+* Variable Index::
+* Index::
+
+@detailmenu
+ --- The Detailed Node Listing ---
+
+Basics
+
+* Internet Relay Chat::
+* Getting started with rcirc::
+
+Reference
+
+* rcirc commands::
+* Useful IRC commands::
+* Configuration::
+
+Hacking and Tweaking
+
+* Skipping /away messages using handlers::
+* Using fly spell mode::
+* Scrolling conservatively::
+* Changing the time stamp format::
+* Defining a new command::
+* Reconnecting after you have lost the connection::
+
+@end detailmenu
+@end menu
+
+@node Basics, Reference, Top, Top
+@chapter Basics
+
+This chapter contains a brief introduction to IRC (Internet Relay Chat),
+and a quick tutorial on @code{rcirc}.
+
+@menu
+* Internet Relay Chat::
+* Getting started with rcirc::
+@end menu
+
+@node Internet Relay Chat, Getting started with rcirc, Basics, Basics
+@section Internet Relay Chat
+@cindex internet relay chat
+@cindex irc
+
+@cindex channel
+@dfn{Internet Relay Chat} (IRC) is a form of instant communication over the
+Internet.  It is mainly designed for group (many-to-many) communication
+in discussion forums called channels, but also allows one-to-one
+communication.
+
+@cindex instant messaging, comparison
+@cindex server
+@cindex network
+Contrary to most Instant Messenger (IM) systems, users usually don't
+connect to a central server.  Instead, users connect to a random server
+in a network, and the servers share information between them.
+
+Here's a typical example:
+
+@cindex redirection to random servers
+When you connect to the Freenode network
+(@indicateurl{http://freenode.net/}), you point your IRC client at the
+server @code{irc.freenode.net}.  That server will redirect your client
+to a random server on the network, such as @code{zelazny.freenode.net}.
+
+@cindex channel name
+@cindex # starts a channel name
+Once you're connected, you can send messages to all other users
+connected to the same network, and you can join all channels on the same
+network.  You might join the @code{#emacs} and the @code{#rcirc}
+channels, for example.  (Typically, channel names begin with a hash
+character.)
+
+Once you have joined a channel, anything you type will be broadcast to
+all the other users on the same channel.
+
+@cindex addressing other people
+@cindex other people, addressing them
+@cindex talk to other people
+If you want to address someone specifically, for example as an answer
+to a question, it is custom to prefix the message with the nick
+followed by a colon, like this:
+
+@example
+deego: fsbot rules!
+@end example
+
+@cindex nick completion
+@cindex completion of nicks
+@kindex TAB
+Since this is so common, you can use @key{TAB} to do nick completion.
+
+@node Getting started with rcirc, , Internet Relay Chat, Basics
+@section Getting started with rcirc
+@cindex getting started
+@cindex connecting to a server
+
+@cindex irc command
+Use the command @kbd{M-x irc} to connect to a server.  You will be asked
+for four things:
+
+@table @asis
+@cindex server, connecting
+@cindex Freenode network
+@item IRC server
+What server do you want to connect to? All the servers in a particular
+network are equivalent.  Some networks use a round-robin system where a
+single server redirects new connections to a random server in the
+network.  @code{irc.freenode.net} is such a server for the Freenode
+network.  Freenode provides the network ``for the Free and Open Source
+Software communities, for not-for-profit organisations and for related
+communities and organizations.''
+
+@cindex port, connecting
+@cindex 6667, default IRC port
+@item IRC port
+All network connections require a port.  Just as web servers and clients
+use port 80 per default, IRC uses port 6667 per default.  You rarely
+have to use a different port.
+
+@cindex nick, connecting
+@cindex changing nick
+@cindex name changes
+@item IRC nick
+@vindex user-login-name
+Every users needs a handle on-line.  You will automatically be assigned
+a slightly different nick if your chosen nick is already in use.  If
+your @code{user-login-name} is @code{"alex"}, and this nick is already
+in use, you might for example get assigned the nick @code{alex`}.
+
+@cindex channels, connecting
+@cindex initial channels
+@cindex startup channels
+@item Channels
+A space separated list of channels you want to join when connecting.
+You don't need to join any channels, if you just want to have one-to-one
+conversations with friends on the same network.  If you're new to the
+Freenode network, join @code{#emacs}, the about all things Emacs.
+@end table
+
+@cindex server buffer
+When you have answered these questions, @code{rcirc} will create a server
+buffer, which will be named something like @code{*irc.freenode.net*},
+and a channel buffer for each of the channels you wanted to join.
+
+@kindex RET
+@cindex talking
+@cindex communicating
+To talk in a channel, just type in what you want to say in a channel
+buffer, and press @key{RET}.
+
+@kindex C-c C-c
+@cindex multiline messages
+@cindex messages, multiple lines
+@cindex pasting multiple lines
+@cindex edit message before sending
+If you want to paste multiple lines, such as source code, you can use
+@kbd{C-c C-c} to edit your message in a separate buffer.  Use @kbd{C-c
+C-c} to finish editing.  You still need to press @key{RET} to send it,
+though.  Generally, IRC users don't like people pasting more than around
+four lines of code, so use with care.
+
+@kindex C-c C-SPC
+@cindex switching channels
+@cindex tracking activity
+@cindex active channel
+@cindex abbreviated channel names
+@cindex modeline tracks activity
+You will note that when other people say things in buffers that are
+currently buried (no window is showing them), the mode line will show
+you the abbreviated channel or nick name.  Use @kbd{C-c C-@key{SPC}} to switch
+to these buffers.
+
+@node Reference, Hacking and Tweaking, Basics, Top
+@chapter Reference
+@cindex reference
+
+This is the reference section of the manual.  It is not complete.  For
+complete listings of @code{rcirc} features, use Emacs built-in
+documentation.
+
+@menu
+* rcirc commands::
+* Useful IRC commands::
+* Configuration::
+@end menu
+
+@node rcirc commands, Useful IRC commands, Reference, Reference
+@section rcirc commands
+@cindex rcirc commands
+@cindex commands
+
+@kindex C-h m
+This is a list of commands that you may use in @code{rcirc}.  It is not
+complete.  For a complete listing, press @kbd{C-h m} in an @code{rcirc}
+buffer.
+
+In addition to using regular Emacs key bindings, you can call them by
+typing them into an @code{rcirc} buffer.
+
+@cindex call commands
+@cindex typing commands
+@cindex commands
+For instance, instead of using the command @kbd{C-c C-j} to join a new
+channel, you may type this in an @code{rcirc} buffer, and press @key{RET}:
+
+@example
+/join #emacs
+@end example
+
+@cindex / starts a command
+@cindex messages starting with a slash disappear
+@cindex disappearing messages if starting with a slash
+@cindex slash hides message
+This is why you cannot start a message with a slash.  You will have to
+precede the command with a space, or rewrite your message in order to
+send it to a channel.
+
+@cindex multiple words as parameters
+@cindex string delimiters
+@cindex quotes
+@cindex double-quotes
+Many commands take parameters.  IRC commands usually ignore string
+delimiters.  Neither quote nor double-quote have special meanings in
+IRC.
+
+@example
+/nick "alex schroeder"
+@end example
+
+This will try to change your nick to @code{"alex}.  Usually this will
+fail because the double quote character is not a legal character for
+nicks.
+
+@cindex case insensitive commands
+These commands are case insensitive.
+
+@cindex new command
+@cindex unknown command
+@cindex command unknown
+If a command isn't known by @code{rcirc}, it will simply be sent along to the
+server.  There is a list of some useful commands like that in the next
+section.
+
+@table @kbd
+@item C-c C-j
+@kindex C-c C-j
+@cindex /join
+@cindex join channels
+@cindex other channels
+@cindex rooms, joining
+@cindex discussion, joining
+This joins a channel such as @code{#rcirc} or @code{#emacs}.  On most
+networks, anybody can create new channels.  If you want to talk with
+some friends, for example, all you have to do is agree on a valid
+channel name and join that channel.  (Also @code{/join #emacs}.)
+
+@item C-c C-p
+@kindex C-c C-p
+@cindex /part
+@cindex part a channel
+@cindex leave a channel
+@cindex disconnect from a channel
+@cindex stop talking on a channel
+@cindex kill channel buffer
+This leaves the current channel.  You can optionally provide a reason
+for parting.  When you kill a channel buffer, you automatically part the
+corresponding channel.  (Also @code{/part you are too weird!}.)
+
+@item C-c C-r
+@kindex C-c C-r
+@cindex /nick
+@cindex change name
+@cindex nick changing
+@cindex rename yourself
+@cindex other name
+This changes your nick to some other name.  Your nick must be unique
+across the network.  Most networks don't allow too many nick changes in
+quick succession, and have restrictions on the valid characters in nick
+names.  (Also @code{/nick alex-test})
+
+@item C-c C-w
+@kindex C-c C-w
+@cindex /whois
+@cindex who are these people
+@cindex identifying people
+@cindex channels other people are on
+@cindex what channels people are on
+Gives you some basic information about a nick.  This often includes what
+other channels people are on.  (Also @code{/whois fsbot}.)
+
+@item C-c C-q
+@kindex C-c C-q
+@cindex /query
+@cindex starting a private conversation
+@cindex one-to-one conversation
+@cindex talk privately
+@cindex private conversation
+@cindex contact one person only
+@cindex query a person
+Starts a one-to-one conversation with another person on the same
+network.  A new buffer will be created for this conversation.  It works
+like a channel with only two members.  (Also @code{/query fsbot}.)
+
+@item C-c @key{RET}
+@kindex C-c RET
+@cindex /msg
+@cindex single message
+@cindex message sending
+This sends a single message to a nick.  Like with @kbd{C-c C-q}, a new
+buffer is created, where the response from the other party will show
+up.  (Also @code{/msg nickserv identify secret}.)
+
+@item C-c C-x
+@kindex C-c C-x
+@cindex /quit
+@cindex quit
+@cindex disconnect
+@cindex kill connection
+@cindex connection end
+@cindex part all channels
+@cindex end connection
+@cindex server buffer killing
+@cindex reason for quitting
+This disconnects from the server and parts all channels.  You can
+optionally provide a reason for quitting.  When you kill the server
+buffer, you automatically quit the server and part all channels.  (Also
+@code{/quit ZZZzzz...}.)
+@end table
+
+Some commands may not have a key binding, but only be available as typed
+commands, such as:
+
+@table @code
+@item /ignore
+@cindex /ignore
+@cindex ignoring other people
+@cindex trolls, ignoring
+@cindex hide some posts
+@cindex idiots online
+This command toggles the ignore status of a nick, if you provide one.
+If you don't provide a nick, the command lists all the nicks you are
+ignoring.  All messages by ignored nicks are---you guessed it---ignored.
+Since only ``operators'' can kick people from channels, the
+ignore command is often the only way to deal with some of the more
+obnoxious fellows online.  Example: @code{/ignore xah}.
+@end table
+
+@node Useful IRC commands, Configuration, rcirc commands, Reference
+@section Useful IRC commands
+@cindex irc commands
+@cindex commands
+
+As mentioned, if a command isn't known by @code{rcirc}, it will simply be sent
+along to the server.  Some such commands are available on nearly all IRC
+servers, such as:
+
+@table @code
+@item /away
+@cindex /away
+@cindex away status
+@cindex pause status
+@cindex unavailable status
+@cindex set away status
+This sets your status as ``being away'' if you provide a reason, or sets
+your status as ``being back'' if you do not.  People can use the
+@kbd{C-c C-w} command to check your status.  Example: @code{/away food}.
+@end table
+
+@cindex irc resources
+@cindex help about irc
+Typical IRC servers implement many more commands.  You can read more
+about the fantastic world of IRC online at
+@indicateurl{http://www.irchelp.org/}, the Internet Relay Chat (IRC)
+help archive.
+
+@node Configuration, , Useful IRC commands, Reference
+@section Configuration
+@cindex configuring rcirc
+
+These are some variables you can change to configure @code{rcirc} to your
+liking.
+
+@table @code
+@item rcirc-server
+@vindex rcirc-server
+the default server to connect to.
+
+@item rcirc-port
+@vindex rcirc-port
+the default port to connect to.
+
+@item rcirc-nick
+@vindex rcirc-nick
+the default nick to use.
+@end table
+
+@example
+(setq rcirc-server "irc.mozilla.org"
+      rcirc-port 6666
+      rcirc-nick "alx")
+@end example
+
+@vindex rcirc-user-full-name
+@cindex full name
+@cindex real name
+@cindex surname
+@code{rcirc-user-full-name} is used to set your ``real name'' on IRC.
+It defaults to @code{user-full-name}.  If you want to hide your full
+name, you might want to set it to some pseudonym.
+
+@example
+(setq rcirc-user-full-name "Curious Minds Want To Know")
+@end example
+
+@vindex rcirc-startup-channels-alist
+@cindex channels, configuration
+@cindex initial channels, configuration
+@cindex startup channels, configuration
+@code{rcirc-startup-channels-alist} is the alist of channels to join
+when connecting to a particular network.  An alist is a list of lists.
+Each sublist starts with a regular expression that is compared to the
+server address you're connecting to.  The remaining sublist items are
+the channels to join.
+
+@example
+(setq rcirc-startup-channels-alist
+      '(("\\.freenode\\.net$" "#emacs" "#rcirc" "#wiki")))
+@end example
+
+Note the subtle problem, here --- IRC clients connect to servers, and
+there is no way of knowing which servers belong to a particular network.
+In the example above we're exploiting a naming convention used by within
+the Freenode network --- all servers within the network have a host in
+the @code{freenode.net} domain.
+
+@node Hacking and Tweaking, Key Index, Reference, Top
+@chapter Hacking and Tweaking
+@cindex hacking and tweaking
+
+Here are some examples of stuff you can do to configure @code{rcirc}.
+
+@menu
+* Skipping /away messages using handlers::
+* Using fly spell mode::
+* Scrolling conservatively::
+* Changing the time stamp format::
+* Defining a new command::
+* Reconnecting after you have lost the connection::
+@end menu
+
+@node Skipping /away messages using handlers, Using fly spell mode, Hacking and Tweaking, Hacking and Tweaking
+@section Skipping @code{/away} messages using handlers
+@cindex /away messages
+
+@cindex handlers
+@cindex status codes
+The IRC protocol specifies how certain events are signaled from server
+to client.  These events have numbers and are dealt with using so-called
+handlers.  You can override existing handlers by exploiting the naming
+convention adopted for @code{rcirc}.
+
+Here's how to stop @code{rcirc} from printing @code{/away} messages.
+Since @code{rcirc} doesn't define a 301 handler, you don't need to
+require @code{rcirc} before defining the handler:
+
+@example
+(defun rcirc-handler-301 (process cmd sender args)
+  "/away message handler.")
+@end example
+
+@node Using fly spell mode, Scrolling conservatively, Skipping /away messages using handlers, Hacking and Tweaking
+@section Using fly spell mode
+@cindex fly spell
+@cindex spelling
+@cindex spell-checking as you type
+@cindex automatic spelling
+@vindex rcirc-mode-hook
+
+The following code activates Fly Spell Mode
+for @code{rcirc} buffers:
+
+@example
+(add-hook 'rcirc-mode-hook (lambda ()
+                             (flyspell-mode 1)))
+@end example
+
+@xref{Spelling, , Flyspell mode, emacs, The GNU Emacs Manual},
+for details.
+
+@node Scrolling conservatively, Changing the time stamp format, Using fly spell mode, Hacking and Tweaking
+@section Scrolling conservatively
+@cindex input line
+@cindex scrolling
+@vindex scroll-conservatively
+@vindex rcirc-mode-hook
+
+IRC buffers are constantly growing.  If you want to see as much as
+possible at all times, you would want the prompt at the bottom of the
+window when possible.  The following snippet uses a local value for
+@code{scroll-conservatively} to achieve this:
+
+@example
+(add-hook 'rcirc-mode-hook
+          (lambda ()
+            (set (make-local-variable 'scroll-conservatively)
+                 8192)))
+@end example
+
+@xref{Scrolling, , Scrolling conservatively, emacs, The GNU Emacs
+Manual}, for details.
+
+@node Changing the time stamp format, Defining a new command, Scrolling conservatively, Hacking and Tweaking
+@section Changing the time stamp format
+@cindex time stamp
+@cindex date time
+@cindex format time stamp
+@vindex rcirc-time-format
+
+@code{rcirc-time-format} is the format used for the time stamp.  Here's
+how to include the date in the time stamp:
+
+@example
+(setq rcirc-time-format "%Y-%m-%d %H:%M ")
+@end example
+
+@node Defining a new command, Reconnecting after you have lost the connection, Changing the time stamp format, Hacking and Tweaking
+@section Defining a new command
+@cindex defining commands
+@cindex commands, defining
+@cindex new commands, defining
+
+Here's a simple new command, @code{/sv}.  With it, you can boast about
+your IRC client.  It shows how you can use @code{defun-rcirc-command} to
+define new commands.
+
+We're waiting for the definition of this command until @code{rcirc} is loaded
+because @code{defun-rcirc-command} is not yet available, and without
+@code{rcirc} loaded, the command wouldn't do us much good anyway.
+
+@smallexample
+(eval-after-load 'rcirc
+  '(defun-rcirc-command sv (arg)
+     "Boast about rcirc."
+     (interactive "i")
+     (rcirc-send-message process target
+                         (concat "I use " rcirc-id-string))))
+@end smallexample
+
+@node Reconnecting after you have lost the connection, , Defining a new command, Hacking and Tweaking
+@section Reconnecting after you have lost the connection
+@cindex reconnecting
+@cindex disconnecting servers, reconnecting
+
+If you're chatting from a laptop, then you might be familiar with this
+problem: When your laptop falls asleep and wakes up later, your IRC
+client doesn't realise that it has been disconnected.  It takes several
+minutes until the client decides that the connection has in fact been
+lost.  The simple solution is to use @kbd{M-x rcirc}.  The problem is
+that this opens an @emph{additional} connection, so you'll have two
+copies of every channel buffer --- one dead and one live.
+
+The real answer, therefore, is a @code{/reconnect} command:
+
+@smallexample
+(eval-after-load 'rcirc
+  '(defun-rcirc-command reconnect (arg)
+     "Reconnect the server process."
+     (interactive "i")
+     (unless process
+       (error "There's no process for this target"))
+     (let* ((server (car (process-contact process)))
+            (port (process-contact process :service))
+            (nick (with-rcirc-process-buffer process rcirc-nick))
+            channels query-buffers)
+       (dolist (buf (buffer-list))
+         (with-current-buffer buf
+           (when (eq process rcirc-process)
+             (if (rcirc-channel-p rcirc-target)
+                 (setq channels (cons rcirc-target channels))
+               (setq query-buffers (cons buf query-buffers))))))
+       (delete-process process)
+       (let ((new-process (rcirc-connect server port nick
+                                         rcirc-user-name user-full-name
+                                         channels)))
+         (dolist (buf query-buffers)
+           (with-current-buffer buf
+             (setq rcirc-process new-process)))))))
+@end smallexample
+
+@node Key Index, Variable Index, Hacking and Tweaking, Top
+@unnumbered Key Index
+@printindex ky
+
+@node Variable Index, Index, Key Index, Top
+@unnumbered Variable Index
+@printindex vr
+
+@node Index, , Variable Index, Top
+@unnumbered Index
+@printindex cp
+
+@bye
+
+@ignore
+   arch-tag: 2589e562-3843-4ffc-8c2f-477cbad57c01
+@end ignore
--- a/man/regs.texi	Thu Jan 26 02:23:05 2006 +0000
+++ b/man/regs.texi	Wed Feb 01 10:07:17 2006 +0000
@@ -25,6 +25,11 @@
 Display a description of what register @var{r} contains.
 @end table
 
+  @dfn{Bookmarks} record files and positions in them, so you can
+return to those positions when you look at the file again.
+Bookmarks are similar enough in spirit to registers that they
+seem to belong in this chapter.
+
 @menu
 * Position: RegPos.           Saving positions in registers.
 * Text: RegText.              Saving text in registers.
--- a/man/screen.texi	Thu Jan 26 02:23:05 2006 +0000
+++ b/man/screen.texi	Wed Feb 01 10:07:17 2006 +0000
@@ -6,42 +6,45 @@
 @chapter The Organization of the Screen
 @cindex screen
 @cindex parts of the screen
-@c
 
-  On a text-only terminal, the Emacs display occupies the whole screen.
-On the X Window System, Emacs creates its own X windows to use.  We use
-the term @dfn{frame} to mean an entire text-only screen or an entire X
-window used by Emacs.  Emacs uses both kinds of frames in the same way
-to display your editing.  Emacs normally starts out with just one frame,
-but you can create additional frames if you wish.  @xref{Frames}.
+  On a text-only terminal, the Emacs display occupies the whole
+screen.  On a graphical display, such as on GNU/Linux using the X
+Window System, Emacs creates its own windows to use.  We use the term
+@dfn{frame} to mean the entire text-only screen or an entire
+system-level window used by Emacs.  Emacs uses both kinds of frames,
+in the same way, to display your editing.  Emacs normally starts out
+with just one frame, but you can create additional frames if you wish.
+@xref{Frames}.
 
-  When you start Emacs, the entire frame except for the top and bottom
-is devoted to the text you are editing.  This area is called the
-@dfn{window}.  At the top there is normally a @dfn{menu bar} where you
-can access a series of menus; then there may be a @dfn{tool bar}, a
-row of icons that perform editing commands if you click on them.
-Below this, the window begins.  The last line is a special @dfn{echo
-area} or @dfn{minibuffer window}, where prompts appear and where you
-enter information when Emacs asks for it.  See below for more
-information about these special lines.
+  When you start Emacs, the main central area of the frame, all except
+for the top and bottom and sides, displays the text you are editing.
+This area is called @dfn{the window}.  At the top there is normally a
+@dfn{menu bar} where you can access a series of menus; then there may
+be a @dfn{tool bar}, a row of icons that perform editing commands if
+you click on them.  Below this, the window begins, often with a
+@dfn{scroll bar} on one side.  Below the window comes the last line of
+the frame, a special @dfn{echo area} or @dfn{minibuffer window}, where
+prompts appear and where you enter information when Emacs asks for it.
+See following sections for more information about these special lines.
 
-  You can subdivide the large text window horizontally or vertically
-into multiple text windows, each of which can be used for a different
-file (@pxref{Windows}).  In this manual, the word ``window'' always
-refers to the subdivisions of a frame within Emacs.
+  You can subdivide the window horizontally or vertically to make
+multiple text windows, each of which can independently display some
+file or text (@pxref{Windows}).  In this manual, the word ``window''
+refers to the initial large window if not subdivided, or any one of
+the multiple windows you have subdivided it into.
 
   At any time, one window is the @dfn{selected window}.  On graphical
 terminals, the selected window normally shows a more prominent cursor
-(solid and blinking) while other windows show a weaker cursor (such as
-a hollow box).  On text terminals, which have just one cursor, that cursor
-appears in the selected window.
+(usually solid and blinking) while other windows show a weaker cursor
+(such as a hollow box).  On text terminals, which have just one
+cursor, that cursor always appears in the selected window.
 
   Most Emacs commands implicitly apply to the text in the selected
 window (though mouse commands generally operate on whatever window you
-click them in, whether selected or not).  The other windows display
-text for reference only, unless/until you select them.  If you use
-multiple frames under the X Window System, then giving the input focus
-to a particular frame selects a window in that frame.
+click them in, whether selected or not).  The text in other windows is
+mostly visible for reference, unless/until you select them.  If you
+use multiple frames on a graphical display, then giving the input
+focus to a particular frame selects a window in that frame.
 
   Each window's last line is a @dfn{mode line}, which describes what
 is going on in that window.  It appears in different color and/or a
@@ -67,9 +70,9 @@
 editing commands will take effect.  This location is called @dfn{point}.
 Many Emacs commands move point through the text, so that you can edit at
 different places in it.  You can also place point by clicking mouse
-button 1.
+button 1 (normally the left button).
 
-  While the cursor appears to point @emph{at} a character, you should
+  While the cursor appears to be @emph{on} a character, you should
 think of point as @emph{between} two characters; it points @emph{before}
 the character that appears under the cursor.  For example, if your text
 looks like @samp{frob} with the cursor over the @samp{b}, then point is
@@ -112,7 +115,6 @@
 @node Echo Area
 @section The Echo Area
 @cindex echo area
-@c
 
   The line at the bottom of the frame (below the mode line) is the
 @dfn{echo area}.  It is used to display small amounts of text for
@@ -133,10 +135,10 @@
 (@pxref{Display Custom}).
 
 @cindex error message in the echo area
-  If a command cannot be executed, it may display an @dfn{error message}
-in the echo area.  Error messages are accompanied by beeping or by
-flashing the screen.  The error also discards any input you have typed
-ahead.
+  If a command cannot do its job, it may display an @dfn{error
+message} in the echo area.  Error messages are accompanied by beeping
+or by flashing the screen.  The error also discards any input you have
+typed ahead.
 
   Some commands display informative messages in the echo area.  These
 messages look much like error messages, but they are not announced
@@ -149,7 +151,8 @@
 character position of point in the text and its current column in the
 window.  Commands that take a long time often display messages ending
 in @samp{...} while they are working, and add @samp{done} at the end
-when they are finished.
+when they are finished.  They may also indicate progress with
+percentages.
 
 @cindex @samp{*Messages*} buffer
 @cindex saved echo area messages
@@ -182,19 +185,19 @@
 @c
 
   Each text window's last line is a @dfn{mode line}, which describes
-what is going on in that window.  When there is only one text window,
-the mode line appears right above the echo area; it is the
-next-to-last line in the frame.  The mode line starts and ends with
-dashes.  On a text-mode display, the mode line is in inverse video if
-the terminal supports that; on a graphics display, the mode line has a
-3D box appearance to help it stand out.  The mode line of the
-selected window has a slightly different appearance than those of
-other windows; see @ref{Optional Mode Line}, for more about this.
+what is going on in that window.  The mode line starts and ends with
+dashes.  When there is only one text window, the mode line appears
+right above the echo area; it is the next-to-last line in the frame.
+On a text-mode display, the mode line is in inverse video if the
+terminal supports that; on a graphics display, the mode line has a 3D
+box appearance to help it stand out.  The mode line of the selected
+window has a slightly different appearance than those of other
+windows; see @ref{Optional Mode Line}, for more about this.
 
   Normally, the mode line looks like this:
 
 @example
--@var{cs}:@var{ch}  @var{buf}      @var{pos} @var{line}   (@var{major} @var{minor})------
+-@var{cs}:@var{ch}-@var{fr}  @var{buf}      @var{pos} @var{line}   (@var{major} @var{minor})------
 @end example
 
 @noindent
@@ -208,13 +211,16 @@
 not been edited.  For a read-only buffer, it is @samp{%*} if the buffer
 is modified, and @samp{%%} otherwise.
 
+  @var{fr} appears only on text-only terminals, to show the selected
+frame name.  @xref{Frames}.  The initial frame's name is @samp{F1}.
+
   @var{buf} is the name of the window's @dfn{buffer}.  In most cases
 this is the same as the name of a file you are editing.  @xref{Buffers}.
 
   The buffer displayed in the selected window (the window that the
-cursor is in) is also Emacs's current buffer, the one that editing
-takes place in.  When we speak of what some command does to ``the
-buffer,'' we are talking about the current buffer.
+cursor is in) is the @dfn{current buffer}--the one that editing takes
+place in.  When we speak of what some command does to ``the buffer,''
+we mean it does those things to the current buffer.
 
   @var{pos} tells you whether there is additional text above the top of
 the window, or below the bottom.  If your buffer is small and it is all
@@ -243,13 +249,13 @@
 the total number of messages.  Compilation buffers and Shell buffers
 display the status of the subprocess.
 
-  @var{minor} is a list of some of the @dfn{minor modes} that are turned
-on at the moment in the window's chosen buffer.  For example,
+  @var{minor} is a list of some of the @dfn{minor modes} that are
+turned on at the moment in the window's chosen buffer.  For example,
 @samp{Fill} means that Auto Fill mode is on.  @samp{Abbrev} means that
 Word Abbrev mode is on.  @samp{Ovwrt} means that Overwrite mode is on.
-@xref{Minor Modes}, for more information.  @samp{Narrow} means that the
-buffer being displayed has editing restricted to only a portion of its
-text.  This is not really a minor mode, but is like one.
+@xref{Minor Modes}, for more information.  @samp{Narrow} means that
+the buffer being displayed has editing restricted to only a portion of
+its text.  (This is not really a minor mode, but is like one.)
 @xref{Narrowing}.  @samp{Def} means that a keyboard macro is being
 defined.  @xref{Keyboard Macros}.
 
@@ -261,26 +267,22 @@
 brackets appear in every window's mode line or not in any of them.
 @xref{Recursive Edit}.@refill
 
-  Non-windowing terminals can only show a single Emacs frame at a time
-(@pxref{Frames}).  On such terminals, the mode line displays the name of
-the selected frame, after @var{ch}.  The initial frame's name is
-@samp{F1}.
-
   @var{cs} states the coding system used for the file you are editing.
 A dash indicates the default state of affairs: no code conversion,
 except for end-of-line translation if the file contents call for that.
 @samp{=} means no conversion whatsoever.  Nontrivial code conversions
 are represented by various letters---for example, @samp{1} refers to ISO
-Latin-1.  @xref{Coding Systems}, for more information.  If you are using
-an input method, a string of the form @samp{@var{i}>} is added to the
-beginning of @var{cs}; @var{i} identifies the input method.  (Some input
-methods show @samp{+} or @samp{@@} instead of @samp{>}.)  @xref{Input
-Methods}.
+Latin-1.  @xref{Coding Systems}, for more information.
 
-  When you are using a character-only terminal (not a window system),
-@var{cs} uses three characters to describe, respectively, the coding
-system for keyboard input, the coding system for terminal output, and
-the coding system used for the file you are editing.
+  On a text-only terminal, @var{cs} includes two additional characters
+which describe the coding system for keyboard input and the coding
+system for terminal output.  They come right before the coding system
+used for the file you are editing.
+
+  If you are using an input method, a string of the form
+@samp{@var{i}>} is added to the beginning of @var{cs}; @var{i}
+identifies the input method.  (Some input methods show @samp{+} or
+@samp{@@} instead of @samp{>}.)  @xref{Input Methods}.
 
   When multibyte characters are not enabled, @var{cs} does not appear at
 all.  @xref{Enabling Multibyte}.
@@ -298,22 +300,12 @@
 @samp{(Unix)} instead of the colon even for files that use newline to
 separate lines.
 
-@vindex eol-mnemonic-unix
-@vindex eol-mnemonic-dos
-@vindex eol-mnemonic-mac
-@vindex eol-mnemonic-undecided
-  You can customize the mode line display for each of the end-of-line
-formats by setting each of the variables @code{eol-mnemonic-unix},
-@code{eol-mnemonic-dos}, @code{eol-mnemonic-mac}, and
-@code{eol-mnemonic-undecided} to any string you find appropriate.
-@xref{Variables}, for an explanation of how to set variables.
-
   @xref{Optional Mode Line}, for features that add other handy
 information to the mode line, such as the size of the buffer, the
-current column number of point, the current time, and whether new mail
-for you has arrived.
+current column number of point, and whether new mail for you has
+arrived.
 
-The mode line is mouse-sensitive; when you move the mouse across
+  The mode line is mouse-sensitive; when you move the mouse across
 various parts of it, Emacs displays help text to say what a click in
 that place will do.  @xref{Mode Line Mouse}.
 
@@ -328,11 +320,11 @@
 @kindex M-`
 @kindex F10
 @findex tmm-menubar
-  When you are using a window system, you can use the mouse to choose a
-command from the menu bar.  An arrow pointing right, after the menu
-item, indicates that the item leads to a subsidiary menu; @samp{...} at
-the end means that the command will read arguments (further input from you)
-before it actually does anything.
+  On a graphical terminal, you can use the mouse to choose a command
+from the menu bar.  An arrow pointing right, after the menu item,
+indicates that the item leads to a subsidiary menu; @samp{...} at the
+end means that the command will read arguments (further input from
+you) before it actually does anything.
 
   To view the full command name and documentation for a menu item, type
 @kbd{C-h k}, and then select the menu bar with the mouse in the usual
--- a/man/search.texi	Thu Jan 26 02:23:05 2006 +0000
+++ b/man/search.texi	Wed Feb 01 10:07:17 2006 +0000
@@ -41,7 +41,6 @@
 want, you can stop.  Depending on what you plan to do next, you may or
 may not need to terminate the search explicitly with @key{RET}.
 
-@c WideCommands
 @table @kbd
 @item C-s
 Incremental search forward (@code{isearch-forward}).
@@ -73,9 +72,9 @@
 characters.  If you type @kbd{C-s} and then @kbd{F}, that puts the
 cursor after the first @samp{F} (the first following the starting point, since
 this is a forward search).  Then if you type an @kbd{O}, you will see
-the cursor move just after the first @samp{FO} (the @samp{F} in that
+the cursor move to just after the first @samp{FO} (the @samp{F} in that
 @samp{FO} may or may not be the first @samp{F}).  After another
-@kbd{O}, the cursor moves after the first @samp{FOO} after the place
+@kbd{O}, the cursor moves to just after the first @samp{FOO} after the place
 where you started the search.  At each step, the buffer text that
 matches the search string is highlighted, if the terminal can do that;
 the current search string is always displayed in the echo area.
@@ -135,19 +134,20 @@
 search ring, type @kbd{M-e}.  Type @kbd{C-s} or @kbd{C-r}
 to terminate editing the string and search for it.
 
-  You can change to searching backwards with @kbd{C-r}.  If a search fails
-because the place you started was too late in the file, you should do this.
-Repeated @kbd{C-r} keeps looking for more occurrences backwards.  A
-@kbd{C-s} starts going forwards again.  @kbd{C-r} in a search can be canceled
+  You can change to searching backwards with @kbd{C-r}.  For instance,
+if you are searching forward but you realize you were looking for
+something above the starting point, you can do this.  Repeated
+@kbd{C-r} keeps looking for more occurrences backwards.  A @kbd{C-s}
+starts going forwards again.  @kbd{C-r} in a search can be canceled
 with @key{DEL}.
 
 @kindex C-r
 @findex isearch-backward
   If you know initially that you want to search backwards, you can use
-@kbd{C-r} instead of @kbd{C-s} to start the search, because @kbd{C-r} as
-a key runs a command (@code{isearch-backward}) to search backward.  A
-backward search finds matches that are entirely before the starting
-point, just as a forward search finds matches that begin after it.
+@kbd{C-r} instead of @kbd{C-s} to start the search, because @kbd{C-r}
+as a key runs a command (@code{isearch-backward}) to search backward.
+A backward search finds matches that end before the starting point,
+just as a forward search finds matches that begin after it.
 
 @node Error in Isearch
 @subsection Errors in Incremental Search
@@ -281,50 +281,46 @@
 @cindex faces for highlighting search matches
   You can control how this highlighting looks by customizing the faces
 @code{isearch} (used for the current match) and @code{lazy-highlight}
-(for all the other matches).  The latter is also used for other matches
-inside @code{query-replace}.
+(for all the other matches).
 
 @node Isearch Scroll
 @subsection Scrolling During Incremental Search
 
-  Vertical scrolling during incremental search can be enabled by
-setting the customizable variable @code{isearch-allow-scroll} to a
-non-@code{nil} value.
-
-  You can then use the vertical scroll-bar or certain keyboard
+  You can enable the use of vertical scrolling during incremental
+search (without exiting the search) by setting the customizable
+variable @code{isearch-allow-scroll} to a non-@code{nil} value.  This
+applies to using the vertical scroll-bar and to certain keyboard
 commands such as @kbd{@key{PRIOR}} (@code{scroll-down}),
-@kbd{@key{NEXT}} (@code{scroll-up}) and @kbd{C-l} (@code{recenter})
-within the search, thus letting you see more of the text near the
-current match.  You must run these commands via their key sequences to
-stay in the search---typing M-x @var{command-name} will always
-terminate a search.
+@kbd{@key{NEXT}} (@code{scroll-up}) and @kbd{C-l} (@code{recenter}).
+You must run these commands via their key sequences to stay in the
+search---typing @kbd{M-x} will terminate the search.  You can give
+prefix arguments to these commands in the usual way.
+
+  This feature won't let you scroll the current match out of visibility,
+however.
 
-  You can give prefix arguments to these commands in the usual way.
-The current match cannot be scrolled out of the window---this is
-intentional.
-
-  Several other commands, such as @kbd{C-x 2}
+  The feature also affects some other commands, such as @kbd{C-x 2}
 (@code{split-window-vertically}) and @kbd{C-x ^}
-(@code{enlarge-window}) which don't scroll the window, are
-nevertheless made available under this rubric, since they are likewise
-handy during a search.
+(@code{enlarge-window}) which don't exactly scroll but do affect where
+the text appears on the screen.  In general, it applies to any command
+whose name has a non-@code{nil} @code{isearch-scroll} property.  So you
+can control which commands are affected by changing these properties.
 
-  You can make other commands usable within an incremental search by
-giving the command a non-@code{nil} @code{isearch-scroll} property.
-For example, to make @kbd{C-h l} usable within an incremental search
+  For example, to make @kbd{C-h l} usable within an incremental search
 in all future Emacs sessions, use @kbd{C-h c} to find what command it
-runs.  (You type @kbd{C-h c C-h l}; it says @code{view-lossage}.)  Then
-you can put the following line in your @file{.emacs} file (@pxref{Init File}):
+runs.  (You type @kbd{C-h c C-h l}; it says @code{view-lossage}.)
+Then you can put the following line in your @file{.emacs} file
+(@pxref{Init File}):
 
 @example
 (put 'view-lossage 'isearch-scroll t)
 @end example
 
 @noindent
-This works for commands that don't permanently change point, the
-buffer contents, the match data, the current buffer, or the selected
-window and frame.  The command must not delete the current window and
-must not itself attempt an incremental search.
+This feature can be applied to any command that doesn't permanently
+change point, the buffer contents, the match data, the current buffer,
+or the selected window and frame.  The command must not itself attempt
+an incremental search.
 
 @node Slow Isearch
 @subsection Slow Terminal Incremental Search
@@ -387,7 +383,7 @@
 commands @code{search-forward} and @code{search-backward}.  These
 commands may be bound to keys in the usual manner.  The feature that you
 can get to them via the incremental search commands exists for
-historical reasons, and to avoid the need to find key sequences
+historical reasons, and to avoid the need to find separate key sequences
 for them.
 
 @node Word Search
@@ -427,7 +423,7 @@
 @code{word-search-forward} and @code{word-search-backward}.  These
 commands may be bound to keys in the usual manner.  They are available
 via the incremental search commands both for historical reasons and
-to avoid the need to find suitable key sequences for them.
+to avoid the need to find separate key sequences for them.
 
 @node Regexp Search
 @section Regular Expression Search
@@ -468,10 +464,10 @@
   If you type @key{SPC} in incremental regexp search, it matches any
 sequence of whitespace characters, including newlines.  If you want to
 match just a space, type @kbd{C-q @key{SPC}}.  You can control what a
-bare spece matches by setting the variable
+bare space matches by setting the variable
 @code{search-whitespace-regexp} to the desired regexp.
 
-  Note that adding characters to the regexp in an incremental regexp
+  In some cases, adding characters to the regexp in an incremental regexp
 search can make the cursor move back and start again.  For example, if
 you have searched for @samp{foo} and you add @samp{\|bar}, the cursor
 backs up in case the first @samp{bar} precedes the first @samp{foo}.
@@ -932,7 +928,7 @@
   The replace commands normally operate on the text from point to the
 end of the buffer; however, in Transient Mark mode (@pxref{Transient
 Mark}), when the mark is active, they operate on the region.  The
-replace commands all replace one string (or regexp) with one
+basic replace commands replace one string (or regexp) with one
 replacement string.  It is possible to perform several replacements in
 parallel using the command @code{expand-region-abbrevs}
 (@pxref{Expanding Abbrevs}).
@@ -1246,7 +1242,7 @@
 @findex list-matching-lines
 @findex occur
 @findex multi-occur
-@findex multi-occur-by-filename-regexp
+@findex multi-occur-in-matching-buffers
 @findex how-many
 @findex delete-non-matching-lines
 @findex delete-matching-lines
@@ -1273,19 +1269,21 @@
 @kbd{o} and @kbd{C-o} display the match in another window; @kbd{C-o}
 does not select it.
 
-Occur mode supports the @code{next-error} functionality described in
-@ref{Compilation Mode}.
+After using @kbd{M-x occur}, you can use @code{next-error} to visit
+the occurrences found, one by one.  @ref{Compilation Mode}.
 
 @item M-x list-matching-lines
 Synonym for @kbd{M-x occur}.
 
 @item M-x multi-occur @key{RET} @var{buffers} @key{RET} @var{regexp} @key{RET}
 This function is just like @code{occur}, except it is able to search
-through multiple buffers.
+through multiple buffers.  It asks you to specify the buffer names one by one.
 
-@item M-x multi-occur-by-filename-regexp @key{RET} @var{bufregexp} @key{RET} @var{regexp} @key{RET}
+@item M-x multi-occur-in-matching-buffers @key{RET} @var{bufregexp} @key{RET} @var{regexp} @key{RET}
 This function is similar to @code{multi-occur}, except the buffers to
-search are specified by a regexp on their filename.
+search are specified by a regular expression that matches visited
+filenames.  With a prefix argument, it uses the regular expression to match
+buffer names instead.
 
 @item M-x how-many @key{RET} @var{regexp} @key{RET}
 Print the number of matches for @var{regexp} that exist in the buffer
--- a/src/ChangeLog	Thu Jan 26 02:23:05 2006 +0000
+++ b/src/ChangeLog	Wed Feb 01 10:07:17 2006 +0000
@@ -1,3 +1,60 @@
+2006-01-31  Jan Dj,Ad(Brv  <jan.h.d@swipnet.se>
+
+	* gtkutil.c (update_frame_tool_bar): Use new tool bar functions
+	(gtk_toolbar_insert) so we can have tool bars of different sizes.
+
+2006-01-30  Luc Teirlinck  <teirllm@auburn.edu>
+
+	* data.c (Flistp): Doc fix.
+
+2006-01-30  Juanma Barranquero  <lekktu@gmail.com>
+
+	* window.c (Fother_window, Fwindow_vscroll, Fset_window_vscroll):
+	Fix typos in docstrings.
+
+2006-01-28  Luc Teirlinck  <teirllm@auburn.edu>
+
+	* data.c (Fcar, Fcdr): Add links to Elisp manual to the docstrings.
+
+2006-01-27  Chong Yidong  <cyd@stupidchicken.com>
+
+	* alloc.c (make_interval, allocate_string)
+	(allocate_string_data, make_float, Fcons, allocate_vectorlike)
+	(Fmake_symbol, allocate_misc): Use BLOCK_INPUT when accessing
+	global variables.
+
+2006-01-27  Eli Zaretskii  <eliz@gnu.org>
+
+	* dired.c (DIRENTRY_NONEMPTY) [__CYGWIN__]: Don't use d_ino; use
+	the MSDOS definition.
+
+2006-01-26  Richard M. Stallman  <rms@gnu.org>
+
+	* alloc.c (check_pure_size): Make overflow message an "error message".
+
+	* keymap.c (Fmap_keymap): Doc fix.
+
+	* xfns.c (Fx_create_frame): Put all specified parms into f->param_alist
+	unless they were cleared out.
+
+	* frame.c (x_get_arg): "Clear out" the parm in ALIST if found there.
+
+2006-01-26  L$,1 q(Brentey K,Aa(Broly  <lorentey@elte.hu>
+
+	* editfns.c (Fconstrain_to_field): Fix behaviour on field boundaries.
+	(find_field): Set before_field to after_field when pos is at BEGV.
+	(Fline_beginning_position, Fline_end_position): Clarify
+	confusing doc string.
+
+	* cmds.c (Fbeginning_of_line, Fend_of_line): Clarify confusing doc
+	string.
+
+2006-01-26  Kenichi Handa  <handa@m17n.org>
+
+	* callproc.c (Fcall_process): GCPRO error_file.  Encode infile,
+	current_dir, and error_file.  On reporting an error, decode them
+	back.
+
 2006-01-24  Stefan Monnier  <monnier@iro.umontreal.ca>
 
 	* regex.c (IMMEDIATE_QUIT_CHECK): Use it with SYNC_INPUT as well.
--- a/src/alloc.c	Thu Jan 26 02:23:05 2006 +0000
+++ b/src/alloc.c	Wed Feb 01 10:07:17 2006 +0000
@@ -1422,7 +1422,11 @@
 {
   INTERVAL val;
 
-  eassert (!handling_signal);
+  /* eassert (!handling_signal); */
+
+#ifndef SYNC_INPUT
+  BLOCK_INPUT;
+#endif
 
   if (interval_free_list)
     {
@@ -1445,6 +1449,11 @@
 	}
       val = &interval_block->intervals[interval_block_index++];
     }
+
+#ifndef SYNC_INPUT
+  UNBLOCK_INPUT;
+#endif
+
   consing_since_gc += sizeof (struct interval);
   intervals_consed++;
   RESET_INTERVAL (val);
@@ -1842,7 +1851,11 @@
 {
   struct Lisp_String *s;
 
-  eassert (!handling_signal);
+  /* eassert (!handling_signal); */
+
+#ifndef SYNC_INPUT
+  BLOCK_INPUT;
+#endif
 
   /* If the free-list is empty, allocate a new string_block, and
      add all the Lisp_Strings in it to the free-list.  */
@@ -1873,6 +1886,10 @@
   s = string_free_list;
   string_free_list = NEXT_FREE_LISP_STRING (s);
 
+#ifndef SYNC_INPUT
+  UNBLOCK_INPUT;
+#endif
+
   /* Probably not strictly necessary, but play it safe.  */
   bzero (s, sizeof *s);
 
@@ -1920,6 +1937,12 @@
   /* Determine the number of bytes needed to store NBYTES bytes
      of string data.  */
   needed = SDATA_SIZE (nbytes);
+  old_data = s->data ? SDATA_OF_STRING (s) : NULL;
+  old_nbytes = GC_STRING_BYTES (s);
+
+#ifndef SYNC_INPUT
+  BLOCK_INPUT;
+#endif
 
   if (nbytes > LARGE_STRING_BYTES)
     {
@@ -1974,12 +1997,13 @@
   else
     b = current_sblock;
 
-  old_data = s->data ? SDATA_OF_STRING (s) : NULL;
-  old_nbytes = GC_STRING_BYTES (s);
-
   data = b->next_free;
   b->next_free = (struct sdata *) ((char *) data + needed + GC_STRING_EXTRA);
 
+#ifndef SYNC_INPUT
+  UNBLOCK_INPUT;
+#endif
+
   data->string = s;
   s->data = SDATA_DATA (data);
 #ifdef GC_CHECK_STRING_BYTES
@@ -2560,7 +2584,11 @@
 {
   register Lisp_Object val;
 
-  eassert (!handling_signal);
+  /* eassert (!handling_signal); */
+
+#ifndef SYNC_INPUT
+  BLOCK_INPUT;
+#endif
 
   if (float_free_list)
     {
@@ -2587,6 +2615,10 @@
       float_block_index++;
     }
 
+#ifndef SYNC_INPUT
+  UNBLOCK_INPUT;
+#endif
+
   XFLOAT_DATA (val) = float_value;
   eassert (!FLOAT_MARKED_P (XFLOAT (val)));
   consing_since_gc += sizeof (struct Lisp_Float);
@@ -2681,7 +2713,11 @@
 {
   register Lisp_Object val;
 
-  eassert (!handling_signal);
+  /* eassert (!handling_signal); */
+
+#ifndef SYNC_INPUT
+  BLOCK_INPUT;
+#endif
 
   if (cons_free_list)
     {
@@ -2707,6 +2743,10 @@
       cons_block_index++;
     }
 
+#ifndef SYNC_INPUT
+  UNBLOCK_INPUT;
+#endif
+
   XSETCAR (val, car);
   XSETCDR (val, cdr);
   eassert (!CONS_MARKED_P (XCONS (val)));
@@ -2880,8 +2920,17 @@
   consing_since_gc += nbytes;
   vector_cells_consed += len;
 
+#ifndef SYNC_INPUT
+  BLOCK_INPUT;
+#endif
+
   p->next = all_vectors;
   all_vectors = p;
+
+#ifndef SYNC_INPUT
+  UNBLOCK_INPUT;
+#endif
+
   ++n_vectors;
   return p;
 }
@@ -3119,6 +3168,10 @@
 
   eassert (!handling_signal);
 
+#ifndef SYNC_INPUT
+  BLOCK_INPUT;
+#endif
+
   if (symbol_free_list)
     {
       XSETSYMBOL (val, symbol_free_list);
@@ -3140,6 +3193,10 @@
       symbol_block_index++;
     }
 
+#ifndef SYNC_INPUT
+  UNBLOCK_INPUT;
+#endif
+
   p = XSYMBOL (val);
   p->xname = name;
   p->plist = Qnil;
@@ -3199,7 +3256,11 @@
 {
   Lisp_Object val;
 
-  eassert (!handling_signal);
+  /* eassert (!handling_signal); */
+
+#ifndef SYNC_INPUT
+  BLOCK_INPUT;
+#endif
 
   if (marker_free_list)
     {
@@ -3223,6 +3284,10 @@
       marker_block_index++;
     }
 
+#ifndef SYNC_INPUT
+  UNBLOCK_INPUT;
+#endif
+
   --total_free_markers;
   consing_since_gc += sizeof (union Lisp_Misc);
   misc_objects_consed++;
@@ -4616,7 +4681,7 @@
 check_pure_size ()
 {
   if (pure_bytes_used_before_overflow)
-    message ("Pure Lisp storage overflow (approx. %d bytes needed)",
+    message ("emacs:0:Pure Lisp storage overflow (approx. %d bytes needed)",
 	     (int) (pure_bytes_used + pure_bytes_used_before_overflow));
 }
 
--- a/src/callproc.c	Thu Jan 26 02:23:05 2006 +0000
+++ b/src/callproc.c	Wed Feb 01 10:07:17 2006 +0000
@@ -355,11 +355,11 @@
      protected by the caller, so all we really have to worry about is
      buffer.  */
   {
-    struct gcpro gcpro1, gcpro2, gcpro3;
+    struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
 
     current_dir = current_buffer->directory;
 
-    GCPRO3 (infile, buffer, current_dir);
+    GCPRO4 (infile, buffer, current_dir, error_file);
 
     current_dir
       = expand_and_dir_to_file (Funhandled_file_name_directory (current_dir),
@@ -368,6 +368,12 @@
       report_file_error ("Setting current directory",
 			 Fcons (current_buffer->directory, Qnil));
 
+    if (STRING_MULTIBYTE (infile))
+      infile = ENCODE_FILE (infile);
+    if (STRING_MULTIBYTE (current_dir))
+      current_dir = ENCODE_FILE (current_dir);
+    if (STRINGP (error_file) && STRING_MULTIBYTE (error_file))
+      error_file = ENCODE_FILE (error_file);
     UNGCPRO;
   }
 
@@ -376,6 +382,7 @@
   filefd = emacs_open (SDATA (infile), O_RDONLY, 0);
   if (filefd < 0)
     {
+      infile = DECODE_FILE (infile);
       report_file_error ("Opening process input file", Fcons (infile, Qnil));
     }
   /* Search for program; barf if not found.  */
@@ -529,14 +536,13 @@
 #ifdef MSDOS
 	unlink (tempfile);
 #endif
-	report_file_error ("Cannot redirect stderr",
-			   Fcons ((NILP (error_file)
-				   ? build_string (NULL_DEVICE) : error_file),
-				  Qnil));
+	if (NILP (error_file))
+	  error_file = build_string (NULL_DEVICE);
+	else if (STRINGP (error_file))
+	  error_file = DECODE_FILE (error_file);
+	report_file_error ("Cannot redirect stderr", Fcons (error_file, Qnil));
       }
 
-    current_dir = ENCODE_FILE (current_dir);
-
 #ifdef MAC_OS8
     {
       /* Call run_mac_command in sysdep.c here directly instead of doing
--- a/src/cmds.c	Thu Jan 26 02:23:05 2006 +0000
+++ b/src/cmds.c	Wed Feb 01 10:07:17 2006 +0000
@@ -157,13 +157,13 @@
 With argument N not nil or 1, move forward N - 1 lines first.
 If point reaches the beginning or end of buffer, it stops there.
 
-This command does not move point across a field boundary unless doing so
-would move beyond there to a different line; If N is nil or 1, and point
-starts at a field boundary, point does not move.  To ignore field
-boundaries, either bind `inhibit-field-text-motion' to t, or use the
-`forward-line' function instead.  For instance, `(forward-line 0)' does
-the same thing as `(beginning-of-line)', except that it ignores field
-boundaries.  */)
+This function constrains point to the current field unless this moves
+point to a different line than the original, unconstrained result.  If
+N is nil or 1, and a front-sticky field starts at point, the point
+does not move.  To ignore field boundaries bind
+`inhibit-field-text-motion' to t, or use the `forward-line' function
+instead.  For instance, `(forward-line 0)' does the same thing as
+`(beginning-of-line)', except that it ignores field boundaries.  */)
      (n)
      Lisp_Object n;
 {
@@ -183,10 +183,11 @@
 If point reaches the beginning or end of buffer, it stops there.
 To ignore intangibility, bind `inhibit-point-motion-hooks' to t.
 
-This command does not move point across a field boundary unless doing so
-would move beyond there to a different line; if N is nil or 1, and
-point starts at a field boundary, point does not move.  To ignore field
-boundaries bind `inhibit-field-text-motion' to t.  */)
+This function constrains point to the current field unless this moves
+point to a different line than the original, unconstrained result.  If
+N is nil or 1, and a rear-sticky field ends at point, the point does
+not move.  To ignore field boundaries bind `inhibit-field-text-motion'
+to t.  */)
      (n)
      Lisp_Object n;
 {
--- a/src/data.c	Thu Jan 26 02:23:05 2006 +0000
+++ b/src/data.c	Wed Feb 01 10:07:17 2006 +0000
@@ -274,7 +274,8 @@
 }
 
 DEFUN ("listp", Flistp, Slistp, 1, 1, 0,
-       doc: /* Return t if OBJECT is a list.  This includes nil.  */)
+       doc: /* Return t if OBJECT is a list, that is, a cons cell or nil.
+Otherwise, return nil.  */)
      (object)
      Lisp_Object object;
 {
@@ -521,7 +522,10 @@
 
 DEFUN ("car", Fcar, Scar, 1, 1, 0,
        doc: /* Return the car of LIST.  If arg is nil, return nil.
-Error if arg is not nil and not a cons cell.  See also `car-safe'.  */)
+Error if arg is not nil and not a cons cell.  See also `car-safe'.
+
+See Info node `(elisp)Cons Cells' for a discussion of related basic
+Lisp concepts such as car, cdr, cons cell and list.  */)
      (list)
      register Lisp_Object list;
 {
@@ -549,7 +553,10 @@
 
 DEFUN ("cdr", Fcdr, Scdr, 1, 1, 0,
        doc: /* Return the cdr of LIST.  If arg is nil, return nil.
-Error if arg is not nil and not a cons cell.  See also `cdr-safe'.  */)
+Error if arg is not nil and not a cons cell.  See also `cdr-safe'.
+
+See Info node `(elisp)Cons Cells' for a discussion of related basic
+Lisp concepts such as cdr, car, cons cell and list.  */)
      (list)
      register Lisp_Object list;
 {
--- a/src/dired.c	Thu Jan 26 02:23:05 2006 +0000
+++ b/src/dired.c	Wed Feb 01 10:07:17 2006 +0000
@@ -85,7 +85,8 @@
 #endif /* not MSDOS */
 #endif /* not SYSV_SYSTEM_DIR */
 
-#ifdef MSDOS
+/* Some versions of Cygwin don't have d_ino in `struct dirent'.  */
+#if defined(MSDOS) || defined(__CYGWIN__)
 #define DIRENTRY_NONEMPTY(p) ((p)->d_name[0] != 0)
 #else
 #define DIRENTRY_NONEMPTY(p) ((p)->d_ino)
--- a/src/editfns.c	Thu Jan 26 02:23:05 2006 +0000
+++ b/src/editfns.c	Wed Feb 01 10:07:17 2006 +0000
@@ -524,7 +524,9 @@
     = (XFASTINT (pos) > BEGV
        ? get_char_property_and_overlay (make_number (XINT (pos) - 1),
 					Qfield, Qnil, NULL)
-       : Qnil);
+       /* Using nil here would be a more obvious choice, but it would
+          fail when the buffer starts with a non-sticky field.  */
+       : after_field);
 
   /* See if we need to handle the case where MERGE_AT_BOUNDARY is nil
      and POS is at beginning of a field, which can also be interpreted
@@ -715,7 +717,8 @@
 {
   /* If non-zero, then the original point, before re-positioning.  */
   int orig_point = 0;
-
+  int fwd, prev_old, prev_new;
+  
   if (NILP (new_pos))
     /* Use the current point, and afterwards, set it.  */
     {
@@ -723,23 +726,40 @@
       XSETFASTINT (new_pos, PT);
     }
 
+  CHECK_NUMBER_COERCE_MARKER (new_pos);
+  CHECK_NUMBER_COERCE_MARKER (old_pos);
+
+  fwd = (XFASTINT (new_pos) > XFASTINT (old_pos));
+
+  prev_old = make_number (XFASTINT (old_pos) - 1);
+  prev_new = make_number (XFASTINT (new_pos) - 1);
+  
   if (NILP (Vinhibit_field_text_motion)
       && !EQ (new_pos, old_pos)
-      && (!NILP (Fget_char_property (new_pos, Qfield, Qnil))
-	  || !NILP (Fget_char_property (old_pos, Qfield, Qnil)))
+      && (!NILP (Fget_text_property (new_pos, Qfield, Qnil))
+          || !NILP (Fget_text_property (old_pos, Qfield, Qnil))
+          /* To recognize field boundaries, we must also look at the
+             previous positions; we could use `get_pos_property'
+             instead, but in itself that would fail inside non-sticky
+             fields (like comint prompts).  */
+          || (XFASTINT (new_pos) > BEGV
+              && !NILP (Fget_text_property (prev_new, Qfield, Qnil)))
+          || (XFASTINT (old_pos) > BEGV
+              && !NILP (Fget_text_property (prev_old, Qfield, Qnil))))
       && (NILP (inhibit_capture_property)
-	  || NILP (Fget_char_property(old_pos, inhibit_capture_property, Qnil))))
-    /* NEW_POS is not within the same field as OLD_POS; try to
-       move NEW_POS so that it is.  */
+          /* Field boundaries are again a problem; but now we must
+             decide the case exactly, so we need to call
+             `get_pos_property' as well.  */
+          || (NILP (get_pos_property (old_pos, inhibit_capture_property, Qnil))
+              && (XFASTINT (old_pos) <= BEGV
+                  || NILP (Fget_text_property (old_pos, inhibit_capture_property, Qnil))
+                  || NILP (Fget_text_property (prev_old, inhibit_capture_property, Qnil))))))
+    /* It is possible that NEW_POS is not within the same field as
+       OLD_POS; try to move NEW_POS so that it is.  */
     {
-      int fwd, shortage;
+      int shortage;
       Lisp_Object field_bound;
 
-      CHECK_NUMBER_COERCE_MARKER (new_pos);
-      CHECK_NUMBER_COERCE_MARKER (old_pos);
-
-      fwd = (XFASTINT (new_pos) > XFASTINT (old_pos));
-
       if (fwd)
 	field_bound = Ffield_end (old_pos, escape_from_edge, new_pos);
       else
@@ -780,9 +800,10 @@
 With argument N not nil or 1, move forward N - 1 lines first.
 If scan reaches end of buffer, return that position.
 
-The scan does not cross a field boundary unless doing so would move
-beyond there to a different line; if N is nil or 1, and scan starts at a
-field boundary, the scan stops as soon as it starts.  To ignore field
+This function constrains the returned position to the current field
+unless that would be on a different line than the original,
+unconstrained result.  If N is nil or 1, and a front-sticky field
+starts at point, the scan stops as soon as it starts.  To ignore field
 boundaries bind `inhibit-field-text-motion' to t.
 
 This function does not move point.  */)
@@ -814,9 +835,10 @@
 With argument N not nil or 1, move forward N - 1 lines first.
 If scan reaches end of buffer, return that position.
 
-The scan does not cross a field boundary unless doing so would move
-beyond there to a different line; if N is nil or 1, and scan starts at a
-field boundary, the scan stops as soon as it starts.  To ignore field
+This function constrains the returned position to the current field
+unless that would be on a different line than the original,
+unconstrained result.  If N is nil or 1, and a rear-sticky field ends
+at point, the scan stops as soon as it starts.  To ignore field
 boundaries bind `inhibit-field-text-motion' to t.
 
 This function does not move point.  */)
--- a/src/frame.c	Thu Jan 26 02:23:05 2006 +0000
+++ b/src/frame.c	Wed Feb 01 10:07:17 2006 +0000
@@ -3519,8 +3519,21 @@
   register Lisp_Object tem;
 
   tem = Fassq (param, alist);
-  if (EQ (tem, Qnil))
+
+  if (!NILP (tem))
+    {
+      /* If we find this parm in ALIST, clear it out
+	 so that it won't be "left over" at the end.  */
+#ifdef HAVE_X_WINDOWS /* macfns.c and w32fns.c have not yet
+			 been changed to cope with this.  */
+      XSETCAR (tem, Qnil);
+#endif
+    }
+  else
     tem = Fassq (param, Vdefault_frame_alist);
+
+  /* If it wasn't specified in ALIST or the Lisp-level defaults,
+     look in the X resources.  */
   if (EQ (tem, Qnil))
     {
       if (attribute)
--- a/src/gtkutil.c	Thu Jan 26 02:23:05 2006 +0000
+++ b/src/gtkutil.c	Wed Feb 01 10:07:17 2006 +0000
@@ -3359,9 +3359,7 @@
   Lisp_Object help, frame;
 
   if (! GTK_IS_BUTTON (w))
-    {
-      return FALSE;
-    }
+    return FALSE;
 
   if (! f || ! f->n_tool_bar_items || NILP (f->tool_bar_items))
     return FALSE;
@@ -3596,54 +3594,56 @@
       if (! wicon)
         {
           GtkWidget *w = xg_get_image_for_pixmap (f, img, x->widget, NULL);
+          GtkToolItem *ti = gtk_tool_button_new (w, "");
 
           gtk_misc_set_padding (GTK_MISC (w), hmargin, vmargin);
 
+          gtk_toolbar_insert (GTK_TOOLBAR (x->toolbar_widget),
+                              ti,
+                              i);
           /* The EMACS_INT cast avoids a warning. */
-          gtk_toolbar_append_item (GTK_TOOLBAR (x->toolbar_widget),
-                                   0, 0, 0,
-                                   w,
-                                   GTK_SIGNAL_FUNC (xg_tool_bar_callback),
-                                   (gpointer) (EMACS_INT) i);
+          g_signal_connect (GTK_WIDGET (ti), "clicked",
+                            GTK_SIGNAL_FUNC (xg_tool_bar_callback),
+                            (gpointer) (EMACS_INT) i);
+
+          gtk_widget_show (GTK_WIDGET (ti));
+          gtk_widget_show (GTK_WIDGET (w));
 
           /* Save the image so we can see if an update is needed when
              this function is called again.  */
           g_object_set_data (G_OBJECT (w), XG_TOOL_BAR_IMAGE_DATA,
                              (gpointer)img->pixmap);
 
+          g_object_set_data (G_OBJECT (ti), XG_FRAME_DATA, (gpointer)f);
+
           /* Catch expose events to overcome an annoying redraw bug, see
              comment for xg_tool_bar_item_expose_callback.  */
-          g_signal_connect (G_OBJECT (w),
+          g_signal_connect (G_OBJECT (ti),
                             "expose-event",
                             G_CALLBACK (xg_tool_bar_item_expose_callback),
                             0);
 
-          /* We must set sensitive on the button that is the parent
-             of the GtkImage parent.  Go upwards until we find the button.  */
+          gtk_widget_set_sensitive (GTK_WIDGET (ti), enabled_p);
+          gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (ti), FALSE);
+          
           while (! GTK_IS_BUTTON (w))
             w = gtk_widget_get_parent (w);
 
-          if (w)
-            {
-              /* Save the frame in the button so the xg_tool_bar_callback
-                 can get at it.  */
-              g_object_set_data (G_OBJECT (w), XG_FRAME_DATA, (gpointer)f);
-              gtk_widget_set_sensitive (w, enabled_p);
-
-              /* Use enter/leave notify to show help.  We use the events
-                 rather than the GtkButton specific signals "enter" and
-                 "leave", so we can have only one callback.  The event
-                 will tell us what kind of event it is.  */
-              /* The EMACS_INT cast avoids a warning. */
-              g_signal_connect (G_OBJECT (w),
-                                "enter-notify-event",
-                                G_CALLBACK (xg_tool_bar_help_callback),
-                                (gpointer) (EMACS_INT) i);
-              g_signal_connect (G_OBJECT (w),
-                                "leave-notify-event",
-                                G_CALLBACK (xg_tool_bar_help_callback),
-                                (gpointer) (EMACS_INT) i);
-            }
+          g_object_set_data (G_OBJECT (w), XG_FRAME_DATA, (gpointer)f);
+
+          /* Use enter/leave notify to show help.  We use the events
+             rather than the GtkButton specific signals "enter" and
+             "leave", so we can have only one callback.  The event
+             will tell us what kind of event it is.  */
+          /* The EMACS_INT cast avoids a warning. */
+          g_signal_connect (G_OBJECT (w),
+                            "enter-notify-event",
+                            G_CALLBACK (xg_tool_bar_help_callback),
+                            (gpointer) (EMACS_INT) i);
+          g_signal_connect (G_OBJECT (w),
+                            "leave-notify-event",
+                            G_CALLBACK (xg_tool_bar_help_callback),
+                            (gpointer) (EMACS_INT) i);
         }
       else
         {
--- a/src/keymap.c	Thu Jan 26 02:23:05 2006 +0000
+++ b/src/keymap.c	Wed Feb 01 10:07:17 2006 +0000
@@ -718,7 +718,7 @@
 }
 
 DEFUN ("map-keymap", Fmap_keymap, Smap_keymap, 2, 3, 0,
-       doc: /* Call FUNCTION once for each binding in KEYMAP.
+       doc: /* Call FUNCTION once for each event binding in KEYMAP.
 FUNCTION is called with two arguments: the event that is bound, and
 the definition it is bound to.
 
--- a/src/window.c	Thu Jan 26 02:23:05 2006 +0000
+++ b/src/window.c	Wed Feb 01 10:07:17 2006 +0000
@@ -1829,7 +1829,7 @@
 All windows on current frame are arranged in a cyclic order.
 This command selects the window ARG steps away in that order.
 A negative ARG moves in the opposite order.  The optional second
-argument ALL_FRAMES has the same meaning as in `next-window', which see.  */)
+argument ALL-FRAMES has the same meaning as in `next-window', which see.  */)
      (arg, all_frames)
      Lisp_Object arg, all_frames;
 {
@@ -6660,7 +6660,7 @@
        doc: /* Return the amount by which WINDOW is scrolled vertically.
 Use the selected window if WINDOW is nil or omitted.
 Normally, value is a multiple of the canonical character height of WINDOW;
-optional second arg PIXELS_P means value is measured in pixels.  */)
+optional second arg PIXELS-P means value is measured in pixels.  */)
   (window, pixels_p)
      Lisp_Object window, pixels_p;
 {
@@ -6690,7 +6690,7 @@
        doc: /* Set amount by which WINDOW should be scrolled vertically to VSCROLL.
 WINDOW nil means use the selected window.  Normally, VSCROLL is a
 non-negative multiple of the canonical character height of WINDOW;
-optional third arg PIXELS_P non-nil means that VSCROLL is in pixels.
+optional third arg PIXELS-P non-nil means that VSCROLL is in pixels.
 If PIXELS-P is nil, VSCROLL may have to be rounded so that it
 corresponds to an integral number of pixels.  The return value is the
 result of this rounding.
--- a/src/xfns.c	Thu Jan 26 02:23:05 2006 +0000
+++ b/src/xfns.c	Wed Feb 01 10:07:17 2006 +0000
@@ -2988,6 +2988,8 @@
 
   check_x ();
 
+  parms = Fcopy_alist (parms);
+
   /* Use this general default value to start with
      until we know if this frame has a specified name.  */
   Vx_resource_name = Vinvocation_name;
@@ -3368,6 +3370,12 @@
           || !FRAME_LIVE_P (XFRAME (kb->Vdefault_minibuffer_frame))))
     kb->Vdefault_minibuffer_frame = frame;
 
+  /* All remaining specified parameters, which have not been "used"
+     by x_get_arg and friends, now go in the misc. alist of the frame.  */
+  for (tem = parms; !NILP (tem); tem = XCDR (tem))
+    if (CONSP (XCAR (tem)) && !NILP (XCAR (XCAR (tem))))
+      f->param_alist = Fcons (XCAR (tem), f->param_alist);
+
   UNGCPRO;
 
   /* Make sure windows on this frame appear in calls to next-window