Revision: emacs@sv.gnu.org/emacs--devo--0--patch-22
authorMiles Bader <miles@gnu.org>
Sun, 29 Jan 2006 13:08:58 +0000 (13:08 +0000)
committerMiles Bader <miles@gnu.org>
Sun, 29 Jan 2006 13:08:58 +0000 (13:08 +0000)
Creator:  Michael Olson <mwolson@gnu.org>

Install ERC.

53 files changed:
ChangeLog
Makefile.in
etc/ChangeLog
etc/ERC-NEWS [new file with mode: 0644]
etc/NEWS
info/dir
lisp/erc/ChangeLog [new file with mode: 0644]
lisp/erc/ChangeLog.2001 [new file with mode: 0644]
lisp/erc/ChangeLog.2002 [new file with mode: 0644]
lisp/erc/ChangeLog.2003 [new file with mode: 0644]
lisp/erc/ChangeLog.2004 [new file with mode: 0644]
lisp/erc/ChangeLog.2005 [new file with mode: 0644]
lisp/erc/erc-autoaway.el [new file with mode: 0644]
lisp/erc/erc-autojoin.el [new file with mode: 0644]
lisp/erc/erc-backend.el [new file with mode: 0644]
lisp/erc/erc-button.el [new file with mode: 0644]
lisp/erc/erc-compat.el [new file with mode: 0644]
lisp/erc/erc-complete.el [new file with mode: 0644]
lisp/erc/erc-dcc.el [new file with mode: 0644]
lisp/erc/erc-ezbounce.el [new file with mode: 0644]
lisp/erc/erc-fill.el [new file with mode: 0644]
lisp/erc/erc-goodies.el [new file with mode: 0644]
lisp/erc/erc-ibuffer.el [new file with mode: 0644]
lisp/erc/erc-identd.el [new file with mode: 0644]
lisp/erc/erc-imenu.el [new file with mode: 0644]
lisp/erc/erc-lang.el [new file with mode: 0644]
lisp/erc/erc-list.el [new file with mode: 0644]
lisp/erc/erc-log.el [new file with mode: 0644]
lisp/erc/erc-match.el [new file with mode: 0644]
lisp/erc/erc-menu.el [new file with mode: 0644]
lisp/erc/erc-nets.el [new file with mode: 0644]
lisp/erc/erc-netsplit.el [new file with mode: 0644]
lisp/erc/erc-nicklist.el [new file with mode: 0644]
lisp/erc/erc-nickserv.el [new file with mode: 0644]
lisp/erc/erc-notify.el [new file with mode: 0644]
lisp/erc/erc-page.el [new file with mode: 0644]
lisp/erc/erc-pcomplete.el [new file with mode: 0644]
lisp/erc/erc-replace.el [new file with mode: 0644]
lisp/erc/erc-ring.el [new file with mode: 0644]
lisp/erc/erc-sound.el [new file with mode: 0644]
lisp/erc/erc-speedbar.el [new file with mode: 0644]
lisp/erc/erc-spelling.el [new file with mode: 0644]
lisp/erc/erc-stamp.el [new file with mode: 0644]
lisp/erc/erc-track.el [new file with mode: 0644]
lisp/erc/erc-truncate.el [new file with mode: 0644]
lisp/erc/erc-viper.el [new file with mode: 0644]
lisp/erc/erc-xdcc.el [new file with mode: 0644]
lisp/erc/erc.el [new file with mode: 0644]
man/ChangeLog
man/Makefile.in
man/erc.texi [new file with mode: 0644]
man/faq.texi
man/makefile.w32-in

index 267a762..37e9613 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+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.
index 26b2e29..8468d13 100644 (file)
@@ -497,7 +497,7 @@ install-arch-indep: mkdir info
              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* rcirc*; 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 @@ install-arch-indep: mkdir info
        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 rcirc; 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 @@ uninstall:
        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* rcirc*)
+       (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))
 
index e3ee6b3..7d97586 100644 (file)
@@ -1,3 +1,7 @@
+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.
diff --git a/etc/ERC-NEWS b/etc/ERC-NEWS
new file mode 100644 (file)
index 0000000..fea5497
--- /dev/null
@@ -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
index 4e5e0be..983dd52 100644 (file)
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -1504,6 +1504,17 @@ colors as on X.
 \f
 * 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
index 10309c8..035ed6e 100644 (file)
--- a/info/dir
+++ b/info/dir
@@ -41,6 +41,8 @@ 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.
 
diff --git a/lisp/erc/ChangeLog b/lisp/erc/ChangeLog
new file mode 100644 (file)
index 0000000..b50ac5a
--- /dev/null
@@ -0,0 +1,327 @@
+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 '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.
+
+    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.
+
+;; arch-tag: 865a75f6-2bcb-46df-bf0c-b514dadf688a
diff --git a/lisp/erc/ChangeLog.2001 b/lisp/erc/ChangeLog.2001
new file mode 100644 (file)
index 0000000..52a209b
--- /dev/null
@@ -0,0 +1,1042 @@
+2001-12-18  Mario Lang  <mlang@delysid.org>
+
+       * erc.el: * Added missing 747 numreply (banned)
+
+2001-12-15  Gergely Nagy  <algernon@debian.org>
+
+       * debian/scripts/install, debian/rules:
+       updated to 2.1.cvs.20011215-1
+
+       * debian/changelog: Debian version 2.1.cvs.20011215-1
+
+2001-12-11  Andreas Fuchs  <asf@void.at>
+
+       * erc.el:
+       * applied a nicer version of mhp's patch to remove the last prompt from
+         saved logs
+
+       * erc-replace.el: * Initial checkin
+
+2001-12-11  Mario Lang  <mlang@delysid.org>
+
+       * erc.el:
+       * 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: * 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: added defcustom erc-nick-uniquifier ^ (i prefer _)
+
+2001-12-07  Gergely Nagy  <algernon@debian.org>
+
+       * debian/changelog: changelog for version 2.1.cvs.20011208-1
+
+2001-12-07  Tijs van Bakel  <smoke@wanadoo.nl>
+
+       * erc.el:
+       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: * Fixed silly bug in erc-server-TOPIC (thanks mhp)
+
+       * erc-speak.el:
+       * Fix non-greedy matching bug. That one somehow swallowed text
+
+       * erc.el:
+       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:
+       * 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: * 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: changelog for 2.1.cvs.20011206-1 added
+
+2001-12-06  Andreas Fuchs  <asf@void.at>
+
+       * erc.el:
+       * Don't discard away status when identifying to NickServ
+       * Modify `erc-already-logged-in': check for port, too.
+
+       * erc-fill.el:
+       * 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:
+       * (erc-process-input): Make ' /command' work for quoting /commands
+
+       * erc-speak.el: see changelog
+
+       * erc-fill.el: see erc.el changelog
+
+       * erc.el:
+       * 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:
+       * (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: fix order of attack
+
+       * erc.el: * macroexpanded define-minor-mode for XEmacs
+
+       * erc.el: First try to make channel tracking mouse sensitive
+
+       * erc.el: * 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: * (erc-iswitchb): Rewrite, docfix.
+       Make it use erc-modified-channels as default if available.
+
+       * erc-menu.el:
+       * Fixage related to erc-track-modified-channels-minor-mode rewrite
+
+       * erc.el:
+       * erc-track-modified-channels-minor-mode: Use buffer objects instead of erc-default-target return value for internal state keeping.
+
+       * erc.el: * 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: final version
+
+2001-11-29  Mario Lang  <mlang@delysid.org>
+
+       * erc.el:
+       * (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:
+       * (erc-prepare-mode-line-format): Added sanity checks to prevent it from having problems with server buffers where the connection failed
+
+       * erc-bbdb.el:
+       * (erc-bbdb-JOIN): regexp-quote the fingerhost before searching, some people have really strange characters as their user names
+
+       * erc.el: Remove a stupid debug like (message ...) call
+
+2001-11-28  Gergely Nagy  <algernon@debian.org>
+
+       * debian/changelog: draft of 2.1.cvs.20011128-1
+
+       * debian/rules: simplify for the all-in-one erc package
+
+       * debian/control: integrated erc-speak back into erc
+
+       * debian/maint/conffiles, debian/maint/conffiles.in, debian/maint/postinst, 
+         debian/maint/postinst.in, debian/maint/prerm, debian/maint/prerm.in, 
+         debian/scripts/install, debian/scripts/install.in, debian/scripts/remove, 
+         debian/scripts/remove.in, debian/scripts/startup.erc-speak:
+       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: * (erc-mode): Shouldn't be interactive.
+       * (erc-info-mode): Ditto.
+
+       * erc.el: * (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: *** empty log message ***
+
+       * erc-speedbar.el: * (erc-speedbar-expand-user): New function.
+       Used when more information than just the nick name is available about a dude.
+
+       * erc.el: * Fixed stupid edit,checkin,save cycle error :)
+
+       * erc.el:
+       * (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: *** empty log message ***
+
+2001-11-26  Mario Lang  <mlang@delysid.org>
+
+       * erc-speedbar.el: * 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:
+       * Added erc-speedbar-goto-buffer and therefore enable switching to the buffers from speedbar
+
+       * erc-speedbar.el:
+       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(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:
+       * 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:
+       * new function erc-BBDB-NICK to handle nickname anotation on a nick-change event of a known record
+
+       * erc.el: * 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: * Fixed stupid typo
+
+2001-11-22  Mario Lang  <mlang@delysid.org>
+
+       * erc.el: * 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: *** empty log message ***
+
+       * erc-fill.el: Initial version.
+
+       * erc-complete.el:
+       Applied antifuchs patch to make completion work with (string= erc-prompt "")
+
+       * erc-complete.el:
+       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:
+       * Changed usage of 'finger-host to bbdb-finger-host-field
+
+       * erc-bbdb.el:
+       * 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: * Added JOIN support
+
+2001-11-19  Mario Lang  <mlang@delysid.org>
+
+       * erc.el:
+       Initial message catalog code. converted erc-action-format usage to use it
+
+       * erc.el: * erc-play-sound: Added XEmacs related check
+
+       * erc-bbdb.el: * Initial version, many thanks to Andreas Fuchs
+
+       * erc.el: * Fixed silly problem with whois/was handling
+
+       * erc.el: * 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:
+       fixed xemacs compatibility prob with delete, thanks Adam
+
+2001-11-18  Mario Lang  <mlang@delysid.org>
+
+       * erc.el: numreplies 301 & 461
+
+2001-11-13  Tijs van Bakel  <smoke@wanadoo.nl>
+
+       * erc.el:
+       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: * 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: * some more numreply handlers
+       * cleanup in erc-process-away-p
+       * new function erc-display-error-notice
+
+       * erc.el: * numreply 501 and 221
+
+       * erc.el:
+       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:
+       fixed serious bug which cause privmsgs vanishing when erc-auto-query was set to nil
+
+       * erc.el: cleaned up erc-process-filter
+
+       * erc.el: * 401 and 320 numreplies implemented
+
+       * erc.el: * Removed old/now obsolete code
+
+       * erc.el: * Fixed bug in erc-server-MODE
+
+2001-11-12  Mario Lang  <mlang@delysid.org>
+
+       * erc.el: fixed it
+
+       * erc.el:
+       *** 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: *** empty log message ***
+
+2001-11-12  Tijs van Bakel  <smoke@wanadoo.nl>
+
+       * erc.el:
+       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: erc-server-353
+
+2001-11-12  Tijs van Bakel  <smoke@wanadoo.nl>
+
+       * erc.el: 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: * erc-buffer-filter: do it differently
+
+       * erc.el: ugly but working fix for mhp's query problem
+
+       * erc.el: * erc-server-PRIVMSG-or-NOTICE
+         Now, all the server word replies are finished. Going to numreplies now
+
+       * erc.el:
+       * 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: * erc-server-KICK and erc-server-TOPIC. new functions
+       * erc-server-305-or-306 and erc-server-311-or-314
+
+       * erc.el:
+       * 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: * erc-server-JOIN
+
+       * erc.el: * Ported erc-server-INVITE code
+
+       * erc.el: * erc-server-ERROR and erc-server-MODE
+
+2001-11-11  Mario Lang  <mlang@delysid.org>
+
+       * erc.el: * zen
+
+       * erc.el: * New variable erc-connect-function.
+
+       * erc.el:
+       * New function erc-channel-p and use it where appropriate
+
+       * erc.el: * Removed the variable erc-buffer-list completely now
+       * Moved erc-dbuf around a bit
+
+       * erc.el: * Fix silly change in quit/rename msg handling
+
+       * erc.el: thanks mhp, fixed
+
+       * erc.el: * 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: * Added variable listing when /set is used without args
+
+2001-11-10  Mario Lang  <mlang@delysid.org>
+
+       * erc.el:
+       * Comment/structure cleanup, removal of unnecessary code
+
+       * erc.el: only some code beautification
+
+       * erc-imenu.el:
+       remove add-hook call, thats done in erc.el now for autoloadability
+
+       * erc.el: * Make erc-imenu autoloadable
+
+       * erc.el:
+       * The long promised erc-mode-line-format handling rewrite
+          Poke at it, try it, play with it, report bugs
+
+       * erc.el:
+       some regex-quote fixes, new function erc-cmd-set, and minor things
+
+2001-11-08  Mario Lang  <mlang@delysid.org>
+
+       * erc.el:
+       * added second timestamp-format (erc-away-timestamp-format) for marking msgs when being away
+
+       * erc-complete.el: fixed silly deffun
+
+       * erc.el: * Rewrote erc-load-irc-script (simplified)
+       * Removed depricated code
+
+       * erc-speak.el: * reflect changes in erc.el
+
+       * erc.el:
+       * 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: _ Initial checkin
+
+       * erc.el: * 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: * Patch from Fabien Penso
+         Make completion case insensitive. try it! its cool
+
+       * erc.el: * 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: * Initial checkin
+
+       * erc.el: * The great reduction patch :-)
+         moved relevant function from erc.el to new file erc-menu.el and erc-imenu.el
+
+       * erc-imenu.el: nitial version
+
+       * erc-menu.el: * Initial version
+
+       * erc.el: * wording change suggested by Benjamin Drieu
+
+2001-11-07  Tijs van Bakel  <smoke@wanadoo.nl>
+
+       * erc.el: Added Emacs version to /SV
+
+2001-11-07  Mario Lang  <mlang@delysid.org>
+
+       * erc.el: * Hookification patch, read the diff
+
+       * erc.el: too tired for a changelog :)
+
+2001-11-06  Mario Lang  <mlang@delysid.org>
+
+       * erc.el:
+       * make erc-cmd-op and erc-cmd-deop take multiple nicknames as argument
+
+2001-11-06  Gergely Nagy  <algernon@debian.org>
+
+       * debian/changelog: sync
+
+       * debian/rules: fixed a typo: PKGDIR, not PKIDR
+
+2001-11-06  Mario Lang  <mlang@delysid.org>
+
+       * erc.el:
+       * 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: 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: stupid delYsid, forgot require 'format-spec. good nite
+
+       * erc.el:
+       * new variable erc-action-format. Some erc-notice-prefix fixes again
+
+       * erc.el: * erc-minibuffer-privmsg defaults to t
+
+       * erc.el:
+       * Small fix in relation to the transition to erc-make-notice
+
+2001-11-05  Tijs van Bakel  <smoke@wanadoo.nl>
+
+       * erc.el:
+       Renamed erc-message-notices to erc-minibuffer-notice, and renamed erc-prevent-minibuffer-privmsg to erc-minibuffer-privmsg, inverting its functionality
+
+       * erc.el: 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:
+       * New function erc-nickserv-identify-autodetect for erc-insert-hook. Added by default currently.
+
+       * erc.el:
+       * 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: updated to reflect changes
+
+       * debian/scripts/install.in:
+       moved #PKGFLAG# before -f batch-byte-compile
+
+2001-10-29  Mario Lang  <mlang@delysid.org>
+
+       * erc.el:
+       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: sigh. -2
+
+2001-10-25  Gergely Nagy  <algernon@debian.org>
+
+       * debian/changelog: updated to reflect changes
+
+       * debian/rules: handle conffiles.in too
+
+       * debian/maint/conffiles.in: new file
+
+       * debian/maint/conffiles: superceded by conffiles.in
+
+       * debian/scripts/startup: superceded by startup.erc
+
+2001-10-25  Mario Lang  <mlang@delysid.org>
+
+       * debian/scripts/startup.erc-speak: * Initial version
+
+       * debian/scripts/startup.erc: * Added and fixes minimal typo
+
+2001-10-25  Gergely Nagy  <algernon@debian.org>
+
+       * debian/changelog: updated to reflect changes
+
+       * debian/rules:
+       modified to be able to build the erc-speak package too
+
+       * debian/control: added the new erc-speak package
+
+       * debian/README.erc-speak, debian/maint/postinst.in, debian/maint/prerm.in, 
+         debian/scripts/install.in, debian/scripts/remove.in:
+       new file
+
+       * debian/maint/postinst, debian/maint/prerm, debian/scripts/install, 
+         debian/scripts/remove:
+       removed, superceded by it's .in counterpart
+
+2001-10-25  Mario Lang  <mlang@delysid.org>
+
+       * erc.el: * 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: * Patch by smoke: fix erc-cmd-* commands and add aliases
+
+2001-10-23  Mario Lang  <mlang@delysid.org>
+
+       * erc-speak.el:
+       * 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:
+       * Made the completion postfix customizable through erc-nick-completion-postfix
+
+       * erc-speak.el, erc.el:
+       * Added erc-prevent-minibuffer-privmsg
+
+       * erc-speak.el:
+       * 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:
+       * Removed now really obsolete code. Package size reduced by 50%
+
+       * erc-speak.el:
+       * 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: *** empty log message ***
+
+       * erc-speak.el: * Major simplification. depends on my 2001-10-21 changes to erc.el.
+       * Things removed, read diff
+
+2001-10-21  Gergely Nagy  <algernon@debian.org>
+
+       * debian/changelog: oops, silly typo
+
+       * debian/changelog, debian/control, debian/copyright, 
+         debian/maint/conffiles, debian/maint/postinst, debian/maint/prerm, 
+         debian/rules, debian/scripts/install, debian/scripts/remove, 
+         debian/scripts/startup:
+       initial check-in
+
+2001-10-21  Mario Lang  <mlang@delysid.org>
+
+       * erc.el:
+       * 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:
+       * Made erc-smiley a new option, currently set to t to showoff this feature. :)
+
+2001-10-20  Mario Lang  <mlang@delysid.org>
+
+       * erc.el: * Add missing erc-mode-hook variable
+       * Add smiley-support (preliminary test)
+
+2001-10-20  Alex Schroeder  <alex@gnu.org>
+
+       * erc.el:
+       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: 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: * irc vs ircd default port fixed
+
+       * erc.el: * Added topic-change to imenu
+
+       * erc.el: * More imenu spiffyness
+
+       * erc.el: * Added imenu support
+
+       * erc.el:
+       * Fix to /topic to show topic instead of setting it to null :)
+
+2001-10-05  Mario Lang  <mlang@delysid.org>
+
+       * erc.el: * First version of erc-rename-buffer
+
+       * erc.el: * more header-line tricks.
+
+       * erc.el:
+       * Small fix to do erc-update-mode-line-buffer in erc-update-channel-topic
+
+       * erc.el: * Added erc-header-line-format
+
+2001-10-04  Mario Lang  <mlang@delysid.org>
+
+       * erc.el: * mini-fix, add msgp to auto-query code
+
+       * erc.el: * 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:
+       * 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: * Added erc-kill-input and keybinding C-c C-u for it
+
+2001-10-01  Mario Lang  <mlang@delysid.org>
+
+       * erc.el: * Another fix to nick-completion
+       * Additional checks in erc-track-modified-channels
+
+2001-09-26  Mario Lang  <mlang@delysid.org>
+
+       * erc.el: * 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: Fixed silly quoting-escape error
+
+2001-09-23  Mario Lang  <mlang@delysid.org>
+
+       * erc.el: * Added auto-op support (unfinished)
+       * Added erc-latest-version.
+       * Added erc-ediff-latest-version.
+
+2001-09-21  Mario Lang  <mlang@delysid.org>
+
+       * erc.el:
+       * Minor menu additions (invite only mode is now a checkbox)
+
+2001-09-20  Mario Lang  <mlang@delysid.org>
+
+       * erc.el:
+       * 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: * Fixes XEmacs easymenu usage (2nd time).
+
+2001-09-19  Mario Lang  <mlang@delysid.org>
+
+       * erc.el:
+       * (erc-complete-nick): Add ": " only if one completes directly after the erc-prompt, otherwise, add just one space
+
+       * erc.el:
+       * 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: Updated erc-version-string
+
+       * erc.el: Version number change and last read-through...
+
+2001-09-04  Mario Lang  <mlang@delysid.org>
+
+       * erc.el: Added some asterisks
+
+2001-08-24  Mario Lang  <mlang@delysid.org>
+
+       * erc.el:
+       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:
+       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:
+       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:
+       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: Tweaked erc-join-channel and erc-part-from-channel
+
+2001-07-27  Mario Lang  <mlang@delysid.org>
+
+       * erc.el: some more defcustom stuff
+
+       * erc.el: Patch from Henrik Enberg <henrik@enberg.org>:
+          Adds variables erc-frame-alist and erc-frame-dedicated-p.
+
+       * erc.el: fixed erc-part-from-channel
+
+       * erc.el:
+       fixed match-string problem and added interactive topic setting function.
+
+       * erc.el: fixed silly string-match bug
+
+       * erc.el:
+       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(erc-display-line-buffer): Simplified filling.
+       (erc-fill-region): New function.
+
+2001-07-27  Mario Lang  <mlang@delysid.org>
+
+       * erc.el: Added redundancy check in output
+
+2001-07-26  Alex Schroeder  <alex@gnu.org>
+
+       * erc.el(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:
+       fixed one occurence of a setq with only one argument (XEmacs didnt like that)
+
+       * erc.el:
+       Added erc-next-line-add-newlines customisation possibility.
+
+       * erc.el:
+       added erc-fill-prefix for defining your own way of filling and fixed filling somehow
+
+       * erc.el:
+       fixed small incompatibility in erc-parse-line-from-server at (and (= n 353) regexp
+
+2001-07-25  Mario Lang  <mlang@delysid.org>
+
+       * erc.el:
+       Added erc-filling and filling code to erc-display-line-buffer.
+
+2001-07-08  Alex Schroeder  <alex@gnu.org>
+
+       * erc.el(try-complete-erc-nick): Make the ": " part of the
+       expansion
+
+       * erc.el: require ring
+
+2001-07-08  Mario Lang  <mlang@delysid.org>
+
+       * erc.el: *** empty log message ***
+
+2001-07-07  Mario Lang  <mlang@delysid.org>
+
+       * erc.el: typo
+
+       * erc.el: ommit
+       :wq
+
+2001-07-06  Alex Schroeder  <alex@gnu.org>
+
+       * erc.el(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(erc-highlight-strings): Removed debug message.
+
+       * erc.el(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: Resolved...
+
+2001-07-03  Alex Schroeder  <alex@gnu.org>
+
+       * erc.el(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: Removed more empty lines.
+
+       * erc.el(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: Ugly hack, but looks nicer when giving commands
+
+       * erc-speak.el: ugly hack, but looks nicer now
+
+2001-07-03  Alex Schroeder  <alex@gnu.org>
+
+       * erc.el(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:
+       Insert (erc-current-nick) instead of (erc-display-prompt). good night :)
+
+       * erc.el:
+       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: 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: hmm, defcustom for erc-user-full-name
+
+       * erc-speak.el, erc.el: *** empty log message ***
+
+2001-06-27  Mario Lang  <mlang@delysid.org>
+
+       * erc.el: typo
+
+       * erc.el: Some more defcustom
+
+       * erc-speak.el: nothing, really
+
+2001-06-26  Mario Lang  <mlang@delysid.org>
+
+       * erc.el: Some defcustom stuff. Still no defgroup though :)
+
+       * erc.el:
+       Initial change to erc.el (2.0). Mainly list of ideas and features
+       and syntax-table entries.
+
+       * erc-speak.el, erc.el: Initial Import
+
+       * erc-speak.el, erc.el: 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.
+
+;; arch-tag: 306c4b58-f9ae-4f3d-9fd9-db2d743f05a6
diff --git a/lisp/erc/ChangeLog.2002 b/lisp/erc/ChangeLog.2002
new file mode 100644 (file)
index 0000000..0851f3b
--- /dev/null
@@ -0,0 +1,2601 @@
+2002-12-31  Francis Litterio  <franl@users.sourceforge.net>
+
+       * erc.el(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(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(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(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(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:
+       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:
+       * (erc-track-get-active-buffer): remove superflous (+ arg 0)
+
+2002-12-29  Alex Schroeder  <alex@gnu.org>
+
+       * erc-autoaway.el(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:
+       added (provide 'erc-auto), which is required for (require 'erc-auto) :)
+
+       * erc.el(erc-display-prompt):
+       Set the face property of the prompt to
+       everything but the last character.
+
+       * erc.el(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(erc-bol):
+       Fixed bug when there is only a prompt, and no property
+       change.
+
+       * erc.el(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:
+       make ChangeLog .PHONY, thus forcing it always to be rebuilt.
+
+2002-12-28  Jorgen Schaefer  <forcer@users.sourceforge.net>
+
+       * erc.el(erc-log-irc-protocol):
+       Removed check wether get-buffer-create
+           returned nil. "The value is never nil", says the docstring.
+
+       * erc.el: 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:
+       Added "-f" to "rm" command in rule for target "realclean".
+
+       * erc.el:
+       New function: erc-log-irc-protocol.  Consolidates nearly duplicate code
+       from functions erc-send-command and erc-process-filter into one function.
+
+       * erc.el(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(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(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:
+       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(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: fixed resolve's email add
+
+       * AUTHORS: added damien
+
+       * erc.el(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:
+       erc-encoding-default: check for (coding-system-p) for older emacs versions
+
+       * erc.el(erc-connect): missing ()s added. "don't commit at 2am"
+
+       * erc.el(erc-connect):
+       check if (set-process-coding-system) is available before use
+
+2002-12-27  Alex Schroeder  <alex@gnu.org>
+
+       * AUTHORS: added franl
+
+2002-12-26  Alex Schroeder  <alex@gnu.org>
+
+       * erc-pcomplete.el(pcomplete-parse-erc-arguments):
+       Reworked, and fixed a bug that had
+       caused completions to corrupt preceding text under some circumstances.
+
+       * erc.el(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:
+       Removed fix for bug 658552 recently checked-in, because it doesn't work.
+
+       * erc.el(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:
+       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(erc-cmd-SMV): Bug, now call erc-version-modules.
+
+       * erc-pcomplete.el(erc-pcomplete-version): New.
+
+2002-12-26  Francis Litterio  <franl@users.sourceforge.net>
+
+       * erc-pcomplete.el:
+       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(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(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(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(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(erc-server-ERROR):
+       Show the error reason, not only the originating host.
+
+       * erc.el(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:
+       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: Doc
+
+       * erc-track.el(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: Fix (erc-version) string
+
+2002-12-23  Francis Litterio  <franl@users.sourceforge.net>
+
+       * erc.el:
+       Removed unnecessary assignment to free-variable "p" in erc-downcase.
+
+       * erc.el:
+       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:
+       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:
+       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:
+       AWAY notice duplication prevention. erc-prevent-duplicates now set to ("301") by default, and timeout to 60
+
+       * erc.el: erc-prevent-duplicates: New variable, see docstring
+
+2002-12-20  Jorgen Schaefer  <forcer@users.sourceforge.net>
+
+       * erc-track.el:
+       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(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: erc-track-count patch by az
+
+2002-12-14  Damien Elmes  <erc@repose.cx>
+
+       * erc.el:
+       last-peers: initialise to a cons. thanks to Francis Litterio
+           <franl@world.std.com> for the patch
+
+       * erc.el:
+       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(erc-unique-channel-names): Fix another #hurd
+       vs. #hurd-bunny bug.
+
+       * erc-match.el(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:
+       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:
+       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(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: save logfile when killing buffer
+
+2002-12-09  Alex Schroeder  <alex@gnu.org>
+
+       * erc-track.el(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(erc-insert-timestamp-right): Do not assume
+       erc-fill-column is available.
+
+2002-12-09  Jorgen Schaefer  <forcer@users.sourceforge.net>
+
+       * erc.el:
+       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: erc-noncommands-list: added erc-cmd-SM and erc-cmd-SMV
+
+2002-12-08  Alex Schroeder  <alex@gnu.org>
+
+       * erc.el(erc-cmd-SM): New.
+       (erc-cmd-SMV): New.
+
+       * erc.el(erc-modes): New.
+
+2002-12-08  Jorgen Schaefer  <forcer@users.sourceforge.net>
+
+       * erc-compat.el:
+       field-end: use (not (fboundp 'field-end)) instead of (featurep 'xemacs)
+
+2002-12-08  Alex Schroeder  <alex@gnu.org>
+
+       * erc.el(erc-version-modules): New.
+
+2002-12-08  Mario Lang  <mlang@delysid.org>
+
+       * debian/changelog, debian/control, debian/scripts/startup.erc:
+       debian release 3.0.cvs.20021208
+
+2002-12-08  Jorgen Schaefer  <forcer@users.sourceforge.net>
+
+       * erc.el(erc-split-command): Do the right thing with CTCPs.
+
+2002-12-08  Mario Lang  <mlang@delysid.org>
+
+       * erc-stamp.el: Be a bit more functional
+
+2002-12-08  Jorgen Schaefer  <forcer@users.sourceforge.net>
+
+       * erc-compat.el:
+       XEmacs doesn't seem to have field-end, so we provide our own version here.
+
+2002-12-08  Mario Lang  <mlang@delysid.org>
+
+       * Makefile: Small fixes to debrelease target
+
+2002-12-08  Jorgen Schaefer  <forcer@users.sourceforge.net>
+
+       * erc.el:
+       make-obsolete-variable: xemacs doesn't have the WHEN parameter, remove it.
+
+2002-12-07  Jorgen Schaefer  <forcer@users.sourceforge.net>
+
+       * erc-imenu.el(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:
+       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:
+       erc-uncontrol-input-line: The comment said "Consider it deprecated",
+       so I removed it now.
+       erc-prompt-interactive-input: Marked obsolete as of previous change.
+
+       * erc.el:
+       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(erc-insert-timestamp-right): New algorithm.
+
+2002-12-07  Jorgen Schaefer  <forcer@users.sourceforge.net>
+
+       * erc.el:
+       last-peers, erc-message: Explained what last-peers is used for.
+
+2002-12-07  Alex Schroeder  <alex@gnu.org>
+
+       * erc-page.el(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: provide feature at the end
+
+2002-12-06  Brian P Templeton  <bpt@tunes.org>
+
+       * erc-nickserv.el:
+       Added austnet in erc-nickserv.el (thanks to Damien Elmes
+       <resolve@repose.cx>)
+
+2002-12-05  Mario Lang  <mlang@delysid.org>
+
+       * erc-complete.el: Add autoload cookie
+
+       * erc-speak.el: Small fix to make proper voice-changes
+
+2002-12-05  Alex Schroeder  <alex@gnu.org>
+
+       * erc-lang.el: New
+
+2002-12-03  Jorgen Schaefer  <forcer@users.sourceforge.net>
+
+       * erc.el:
+       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:
+       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: 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: Add missing requires
+
+2002-11-29  Jorgen Schaefer  <forcer@users.sourceforge.net>
+
+       * erc.el(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(erc-encode-coding-string): Add second argument
+               coding-system, and for non-mule xemacsen, use a new defun instead
+               of identity.
+
+       * erc.el:  (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(erc-button): New group, changed all custom groups
+       from erc to erc-button, but left all erc-faces as-is.
+
+       * erc-track.el(erc-track): New group, changed all custom groups
+       from erc to erc-track.
+
+2002-11-26  Mario Lang  <mlang@delysid.org>
+
+       * erc-macs.el:
+       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:
+       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: nick-stk: replaced by the local variable current-nick.
+
+2002-11-25  Alex Schroeder  <alex@gnu.org>
+
+       * erc.el(erc-send-command): Use erc-encode-string-for-target.
+       (erc-encode-string-for-target): New.
+
+       * erc-compat.el(erc-encode-coding-string): Add second argument
+       coding-system, and for non-mule xemacsen, use a new defun instead
+       of identity.
+
+       * erc-nickserv.el(erc-nickserv-version): New.
+
+2002-11-25  Jorgen Schaefer  <forcer@users.sourceforge.net>
+
+       * Makefile:
+       UNCOMPILED: erc-chess.el depends on chess-network.el, which might not
+       be installed. Don't compile it.
+
+       * erc.el:
+       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: erc-track-faces-priority-list: Extended list
+
+       * erc.el:
+       channel-members: Updated docstring: We have a VOICE predicate, too.
+
+       * erc-track.el(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:
+       support for BrasNET. Thanks to rw on IRC for the settings.
+
+2002-11-23  Alex Schroeder  <alex@gnu.org>
+
+       * erc.el: (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: Switched tests to iso-8859-1 instead of latin-1.
+
+       * erc-compat.el(erc-compat-version): New.
+
+2002-11-22  Alex Schroeder  <alex@gnu.org>
+
+       * erc.el(smiley): Smileys are a very small module, now.
+
+2002-11-22  Jorgen Schaefer  <forcer@users.sourceforge.net>
+
+       * erc.el:
+       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:
+       erc-minibuffer-privmsg: Removed setting this variable to nil, since it
+           was removed from erc.el.
+
+       * erc.el(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: 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:
+       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(erc-track-shorten-function): Allow nil.
+
+2002-11-21  Alex Schroeder  <alex@gnu.org>
+
+       * erc-track.el(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:
+       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: * (require pcomplete): Only when compiling.
+
+2002-11-19  Jorgen Schaefer  <forcer@users.sourceforge.net>
+
+       * erc-track.el:
+       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(erc-stamp): Require it.
+
+       * erc-match.el(away): devar for the compiler.
+
+       * erc-stamp.el(stamp): Moved.
+
+       * erc.el(erc-version-string): New version.
+
+       * erc-autoaway.el(erc-autoaway-idletimer): Moved to the front of
+       the file.
+
+       * erc-auto.in: (generated-autoload-file, command-line-args-left):
+       Added defvar without value to silence byte compiler.
+
+       * Makefile(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(erc-match): Require it.
+       (hippie-exp): Require it.
+
+       * erc-ezbounce.el(erc): Require it.
+
+       * erc-imenu.el(imenu): Require it.
+
+       * erc-nickserv.el(erc-networks): Moved up.
+
+       * erc-notify.el(pcomplete): Require it.
+
+       * erc-replace.el(erc): Require it.
+
+       * erc-sound.el(sound): Typo -- define-key in erc-mode-map.
+
+       * erc-speedbar.el(dframe): Require it.
+       (speedbar): Require it.
+
+       * erc-track.el(erc-default-recipients): devar for the compiler.
+
+       * README: New file.
+
+2002-11-18  Mario Lang  <mlang@delysid.org>
+
+       * AUTHORS: File needed for mkChangeLog
+
+       * mkChangeLog: Original code by mhp
+
+2002-11-18  Alex Schroeder  <alex@gnu.org>
+
+       * erc-button.el(erc-button-list): Renamed to erc-list and moved
+       to erc.el.
+
+       * erc.el(erc-list): New.
+
+       * erc-track.el(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: 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:
+       erc-unique-substrings: define this before using it in assert
+
+       * erc.el:
+       with-erc-channel-buffer: Define *before* using this macro. This
+       hopefully fixes a bug noted on IRC.
+
+       * erc-notify.el:
+       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: Typo.
+
+       * erc-speedbar.el: Whitespace only.
+
+       * erc.el(define-erc-module): Avoid defining an alias if name and
+       alias are the same.
+
+       * erc-ibuffer.el: URL
+
+       * erc-imenu.el(erc-imenu-version): New constant.
+
+       * erc-ibuffer.el(erc-ibuffer-version): New constant.
+
+       * erc-ibuffer.el: File header, comments.
+
+       * erc-fill.el(erc-fill-version): New constant.
+
+       * erc-ezbounce.el(erc-ezb-version): New constant.
+
+       * erc-complete.el(erc-complete-version): New constant.
+
+       * erc-chess.el(erc-chess-version): New constant.
+
+       * erc-chess.el: Whitespace only.
+
+       * erc-bbdb.el(erc-bbdb-version): Typo.
+
+       * erc-bbdb.el(erc-bbdb-version): New constant.
+       Lots of whitespace changes.  Changes to the header.
+
+       * erc-track.el(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(match): Rewrote a as module.
+
+2002-11-17  Alex Schroeder  <alex@gnu.org>
+
+       * erc-netsplit.el(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(erc-track-switch-buffer):
+       define-erc-module defines erc-track-mode,
+       not erc-track-modified-channels-mode.
+
+       * erc.el:
+       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:
+       erc-page.el: New file. CTCP PAGE support for ERC, extracted from erc.el.
+
+       * erc-sound.el:
+       defin-erc-module: Typo. Autoload should do erc-sound-mode and "erc-sound".
+
+       * erc-sound.el:
+       erc-sound.el: New file. Contains all the CTCP SOUND stuff from erc.el.
+
+       * erc.el(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(erc-button-version): New constant.
+
+       * erc-button.el(button): rewrote as a module.
+
+2002-11-17  Jorgen Schaefer  <forcer@users.sourceforge.net>
+
+       * erc.el: 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:
+       Practically total rewrite.  All smiley stuff deleted.
+
+       * erc-track.el(track): typo.
+
+       * erc.el(define-erc-module): Doc change.
+
+2002-11-17  Jorgen Schaefer  <forcer@users.sourceforge.net>
+
+       * erc-autoaway.el: Changed to use define-erc-module.
+
+       * erc.el(define-erc-module):
+       Make the enable/disable functions interactive.
+
+       * erc.el(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(stamp): Doc change.
+
+       * erc-stamp.el(erc-stamp-version): New constant.
+       (stamp): downcase alias name of the mode.
+
+       * erc.el(define-erc-module): Added defalias option, renamed
+       parameters again.
+
+       * erc-track.el: 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: * Spelling fix
+
+       * erc-fill.el: * Fix autoload definition for erc-fill-mode
+
+       * debian/control, debian/maint/postinst, debian/maint/prerm:
+       * Remove /usr/doc -> /usr/share/doc link handling
+
+       * debian/changelog: * Sync with reality
+
+       * debian/scripts/startup.erc:
+       * Add /usr/share/emacs/site-lisp/erc/ to load-path
+       * (load "erc-auto")
+
+       * debian/README.Debian:
+       * Info about the changes since last release updated
+
+       * erc-pcomplete.el: * Fix emacs/xemacs compatibility
+
+       * debian/scripts/install: * Dont compile erc-compat, fix ELCDIR
+
+       * debian/control: * Change maintainer field
+
+       * erc.el:
+       * (defin-erc-module): Renamed argument mode-name to mname because silly byte-compiler thought we were talking about `mode-name'.
+
+       * Makefile: * Added debrelease target
+
+       * erc-bbdb.el, erc-pcomplete.el, erc-stamp.el, erc.el:
+       * (define-erc-module): Added mode-name argument.
+       * Converted erc-bbdb, erc-pcomplete and erc-stamp to new macro.
+       * autoload fixes
+
+       * erc-bbdb.el:
+       * Create a global-minor-mode (i.e., make it a proper erc-module)
+
+       * erc.el: * (define-erc-modle): New defmacro
+
+2002-11-16  Jorgen Schaefer  <forcer@users.sourceforge.net>
+
+       * erc-autoaway.el(erc-autoaway-idle-seconds):
+       t in docstrings should be non-nil
+
+2002-11-16  Alex Schroeder  <alex@gnu.org>
+
+       * erc-autoaway.el, erc-button.el, erc-fill.el, erc-match.el, 
+         erc-menu.el, erc-ring.el, erc-track.el:
+       Cleanup of file headers: copyright years, GPL mumbo-jumbo, commentaries.
+
+       * erc-stamp.el(erc-insert-away-timestamp-function):
+       New custom type.
+       (erc-insert-timestamp-function): New custom type.
+
+       * erc-fill.el(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(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:
+       - 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: erc-mode-map: Removed the C-c C-g binding for erc-grab
+
+       * erc.el:
+       (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(erc-decode-coding-string): typo
+
+2002-11-14  Jorgen Schaefer  <forcer@users.sourceforge.net>
+
+       * erc.el(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:
+       Set back on all servers, not just the current one, since we're set
+       away on all servers as well.
+
+       * HISTORY: Fixed typo (ngu.org => gnu.org)
+
+       * erc-autoaway.el, erc-fill.el, erc.el: 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:
+       TODO: moved it to http://www.emacswiki.org/cgi-bin/wiki.pl?ErcTODO
+
+       * erc.el(with-erc-channel-buffer): Rudimentary doc string.
+
+2002-11-09  Alex Schroeder  <alex@gnu.org>
+
+       * erc-button.el(erc-nick-popup-alist): Made a defcustom.
+
+       * erc-button.el(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(erc-button-entry): Use erc-button-syntax-table.
+
+       * erc.el, erc-stamp.el: Doc changes.
+
+       * erc-match.el(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(erc-button-syntax-table): New variable.
+       (erc-button-add-buttons): Use it.
+
+2002-11-06  Mario Lang  <mlang@delysid.org>
+
+       * erc.el:
+       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(erc-connect): set-process-coding-system to raw-text.
+
+2002-11-01  Brian P Templeton  <bpt@tunes.org>
+
+       * erc-pcomplete.el, erc-stamp.el, erc-track.el:
+       Fixed more autoloads
+
+       * erc-compat.el: Added autoload for erc-define-minor-mode
+
+2002-11-01  Mario Lang  <mlang@delysid.org>
+
+       * erc.el: * (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(erc-compat): Require.
+       (erc-completion-mode): Use erc-define-minor-mode.
+
+       * erc-track.el(erc-compat): Require.
+       (erc-track-modified-channels-mode): Use erc-define-minor-mode.
+
+       * erc-stamp.el(erc-compat): Require.
+       (erc-timestamp-mode): Use erc-define-minor-mode.
+
+       * erc-compat.el: 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(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(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, erc.el:
+       Added LASTLOG command and action for nick-button
+
+2002-10-22  Sandra Jean Chua  <sacha@free.net.ph>
+
+       * erc-pcomplete.el:
+       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:
+       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: update from sachac
+
+2002-10-13  Alex Schroeder  <alex@gnu.org>
+
+       * erc.el(erc-emacs-time-to-erc-time): Catch when tm is nil.
+
+2002-10-11  Andreas Fuchs  <asf@void.at>
+
+       * erc.el:
+       * 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: Fixed erc-networks for the opn->freenode change
+
+2002-10-08  Mario Lang  <mlang@delysid.org>
+
+       * erc-pcomplete.el:
+       Make erc-completion-mode work interactively with already joined channel buffers
+
+       * erc-chess.el: Add autoload cookies
+
+       * erc-notify.el: Add pcomplete support
+
+       * erc.el:
+       Remove autoload statments, remove autoload cookie from erc-mode and erc-info-mode
+
+       * erc-fill.el, erc-match.el: add/remove autoload cookies
+
+2002-10-06  Alex Schroeder  <alex@gnu.org>
+
+       * erc-pcomplete.el(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: Doc changes.
+
+       * erc-stamp.el(erc-stamp-enable): Renamed erc-stamp-initialize.
+       (erc-stamp-disable): Renamed erc-stamp-destroy.
+       (erc-timestamp-mode): Use new names.
+
+       * erc.el: 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:
+       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(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:
+       Added customizable `erc-process-coding-system' variable.
+
+2002-09-22  Brian P Templeton  <bpt@tunes.org>
+
+       * erc-fill.el:
+       `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:
+       patch from Peter Solodov <peter@alcor.concordia.ca>  (note, its slightly broken still
+
+2002-09-05  Mario Lang  <mlang@delysid.org>
+
+       * erc-pcomplete.el: Added LEAVE as alias for PART
+
+2002-09-04  Mario Lang  <mlang@delysid.org>
+
+       * erc-pcomplete.el:
+       By sachac (good work!) keep up doing such things
+
+2002-08-31  Mario Lang  <mlang@delysid.org>
+
+       * erc.el:
+       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:
+       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: Try to reactivate isearch in xemacs
+
+       * erc-stamp.el:
+       fixes issues related to comparative emacsology and a silly bug
+
+2002-08-27  Mario Lang  <mlang@delysid.org>
+
+       * erc.el:
+       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:
+       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:
+       erc-nick-popup-alist: New variable to make erc-nick-popup configurable
+
+2002-08-16  Alex Schroeder  <alex@gnu.org>
+
+       * erc-button.el(erc-recompute-nick-regexp): Fixed regexp.
+
+       * erc-button.el(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(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:
+       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, debian/scripts/install:
+       * Added info to README.Debian
+       * Finished debian/scripts/install
+
+2002-08-13  Mario Lang  <mlang@delysid.org>
+
+       * debian/scripts/install: First attempt to fix it
+
+       * debian/README.Debian, debian/changelog, debian/scripts/install:
+       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: Added C-c C-SPC in addition to C-c C-@
+
+       * erc-notify.el: Little docstring change
+
+2002-08-09  Mario Lang  <mlang@delysid.org>
+
+       * erc-stamp.el:
+       Change one use of set-text-properties to add-text-properties (tnx Lathi)
+
+2002-08-02  Mario Lang  <mlang@delysid.org>
+
+       * erc-stamp.el: added erc-timestamp-only-if-changed-flag
+
+2002-07-22  Mario Lang  <mlang@delysid.org>
+
+       * erc.el:
+       Removed timestamp related code and moved into erc-stampe.l
+
+       * erc-stamp.el:
+       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:
+       * 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:
+       * 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: New snapshot deb
+
+       * debian/scripts/install: Rewrote in make.
+       Does not byte-compile erc-speak.el at all, and excludes erc-track.el too, if
+       ran for xemacs.
+
+       * debian/control: Added dependency on make
+
+       * debian/copyright: Updated copyright info
+
+       * debian/rules: Use $(wildcard *.el) instead of a hardcoded list
+
+2002-07-03  Diane Murray  <disumu@x3y2z1.net>
+
+       * erc.el:
+       erc-iswitchb now works correctly if erc-modified-channels-alist is non-nil
+
+2002-07-01  Diane Murray  <disumu@x3y2z1.net>
+
+       * erc-menu.el:
+       * 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:
+       * 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:
+       * 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: Use pp-to-string in /set (without args)
+
+       * erc-netsplit.el:
+       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: added "Customize ERC"
+
+2002-06-25  Mario Lang  <mlang@delysid.org>
+
+       * erc.el: 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:
+       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:
+       Fixed bug where buffer-names suddenly had text-properties.
+
+2002-06-19  Diane Murray  <disumu@x3y2z1.net>
+
+       * Makefile: changed erc-auto.el to $(SPECIAL) in make fullclean
+
+       * Makefile: remove erc-auto.el on make fullclean
+
+2002-06-18  Diane Murray  <disumu@x3y2z1.net>
+
+       * erc-match.el: fixed spelling error
+
+       * erc-track.el, erc-match.el: * 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: * 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:
+       * 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(erc-nickserv-alist): Fixed typo.
+
+2002-06-15  Alex Schroeder  <alex@gnu.org>
+
+       * erc-nickserv.el(erc-networks): Added doc string.
+       (erc-nickserv-alist): Added doc string.
+
+2002-06-14  Diane Murray  <disumu@x3y2z1.net>
+
+       * erc-ring.el:
+       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: Added iip support.
+       Added :type for erc-nickserv-passwords custom.
+       Fixed hook usage.
+
+2002-06-07  Diane Murray  <disumu@x3y2z1.net>
+
+       * erc-nickserv.el: * 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: Fix for kill-buffer hook stuff
+
+2002-06-06  Mario Lang  <mlang@delysid.org>
+
+       * erc.el: Added /squery command
+
+2002-06-06  Diane Murray  <disumu@x3y2z1.net>
+
+       * erc-menu.el: * 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:
+       * 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, erc-match.el:
+       * 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, erc.el: * 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:
+       * 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:
+       * 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:
+       * 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:
+       * 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:
+       Removed multiple calls of `erc-prompt' in `erc-display-prompt'
+
+2002-05-29  Mario Lang  <mlang@delysid.org>
+
+       * erc.el:
+       First step timestampkiller cleanup. I'm tired, do the rest tomorrow.
+
+       * erc.el:
+       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:
+       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, erc.el:
+       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: added myself, vain as it sounds ;)
+
+2002-05-25  Mario Lang  <mlang@delysid.org>
+
+       * erc.el: * 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: Mostly docstring fixes/additions
+
+       * erc-netsplit.el: Doc fixes, and a new netjoin-done message.
+
+       * erc-fill.el: Doc fixes, erc-fill custom group, autoloads.
+
+       * erc-netsplit.el: Fix to erc-netsplit-timer.
+
+       * erc-netsplit.el: Fixed a silly typo
+
+       * erc-maint.el: is this really necessary?
+
+       * erc.el: 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: Doh, I should really test this before checkin :)
+
+       * Makefile: Silly cut&paste bug fixed
+
+       * erc-list.el: Added autoload cookie
+
+       * erc-match.el: Added missing require erc.
+
+       * erc-notify.el: Autoload cookies and a -initialize function.
+
+       * erc-chess.el: Added autoload cookies
+
+       * Makefile: Finally, we have a Makefile.
+       Primarily used for autoload definition generation right now.
+
+       * erc-auto.in: First version.
+
+       * erc-track.el: Added autoload cookie
+
+       * erc-netsplit.el:
+       New module, used to autodetect and hide netsplits.
+       (Untested, no netsplit happened yet :) )
+
+       * erc-nets.el: Added some old code I once worked on.
+       Added autoload cookie
+
+2002-05-24  Diane Murray  <disumu@x3y2z1.net>
+
+       * erc-fill.el:
+       removed reference in documentation to old variable, changed it to the new one
+
+       * erc.el:
+       * 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: fixed bug where prompt was missing after reconnect
+
+2002-05-21  Diane Murray  <disumu@x3y2z1.net>
+
+       * erc.el:
+       in erc-nickserv-identify: if network is unknown, just use "Nickserv"
+
+       * erc.el: * 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: forgot documentaion for erc-nickserv-alist
+
+       * erc.el: 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:
+       * 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: 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: whitespace fix
+
+2002-05-15  Diane Murray  <disumu@x3y2z1.net>
+
+       * erc.el:
+       * 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:
+       - 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:
+       * 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, erc.el:
+       * 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: 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(erc-send-pre-hook): Doc change.
+
+       * CREDITS: Alexander L. Belikoff is confirmed original author.
+
+2002-05-10  Mario Lang  <mlang@delysid.org>
+
+       * erc.el:
+       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: *** empty log message ***
+
+2002-05-06  Mario Lang  <mlang@delysid.org>
+
+       * erc.el:
+       New var: erc-echo-notices-in-minibuffer-flag. defaults to t.
+
+2002-05-04  John Wiegley  <johnw@gnu.org>
+
+       * TODO: *** empty log message ***
+
+2002-05-03  Alex Schroeder  <alex@gnu.org>
+
+       * erc.el: Copyright notice, version string updates.
+
+2002-05-02  Alex Schroeder  <alex@gnu.org>
+
+       * erc.el: Comment: dme is David Edmondson
+
+2002-05-01  Alex Schroeder  <alex@gnu.org>
+
+       * erc.el(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: Version 2.92
+
+       * erc.el(erc-send-modify-hook): Default value is nil.
+
+2002-04-27  John Wiegley  <johnw@gnu.org>
+
+       * erc.el:
+       Don't redisplay the prompt if the ERC buffer is no longer alive.
+
+2002-04-26  John Wiegley  <johnw@gnu.org>
+
+       * erc.el:
+       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: fixed up erc-nick-regexp
+
+2002-04-22  Brian P Templeton  <bpt@tunes.org>
+
+       * erc.el:
+       `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:
+       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: Fix for xemacs elt behaviour
+
+2002-04-17  John Wiegley  <johnw@gnu.org>
+
+       * erc-chess.el:
+       Added a missing arg in a call to erc-chess-handler.
+
+2002-04-15  John Wiegley  <johnw@gnu.org>
+
+       * erc-chess.el: *** empty log message ***
+
+2002-04-14  John Wiegley  <johnw@gnu.org>
+
+       * erc-chess.el: *** empty log message ***
+
+2002-04-12  John Wiegley  <johnw@gnu.org>
+
+       * erc-chess.el: *** empty log message ***
+
+       * erc-chess.el: bug fixes
+
+       * erc-chess.el: *** empty log message ***
+
+2002-04-12  Mario Lang  <mlang@delysid.org>
+
+       * erc-chess.el: change order.
+
+       * erc-chess.el: more fixing.
+
+       Now, the 'match question works. It sends an accept back.
+       But display popup doesnt work..
+
+       * erc-chess.el: fixup (still far from working)
+
+2002-04-11  Mario Lang  <mlang@delysid.org>
+
+       * erc.el:
+       * Added :options entry for erc-mode-hook (erc-add-scroll-to-bottom)
+
+2002-04-11  John Wiegley  <johnw@gnu.org>
+
+       * erc.el: remove trailing \n from any sent text
+
+       * servers.pl, erc-bbdb.el, erc-button.el, erc-chess.el, 
+         erc-complete.el, erc-fill.el, erc-ibuffer.el, erc-list.el, 
+         erc-match.el, erc-menu.el, erc-nets.el, erc-replace.el, 
+         erc-speak.el, erc-speedbar.el, erc-track.el, erc.el:
+       clean whitespace
+
+       * erc.el: Replaced erc-scroll-to-bottom.
+
+2002-04-11  Mario Lang  <mlang@delysid.org>
+
+       * erc-track.el:
+       try to fix behaviour when used with different frames.
+
+2002-04-09  Mario Lang  <mlang@delysid.org>
+
+       * erc-chess.el:
+       fixup release, far from ready for real usage, but it appears to work.
+
+       * erc.el:
+       speed improvments based on elp-instrument-package RET erc- RET results
+
+       * erc-chess.el: 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: New hackery latenightwise
+
+       * erc.el: upupadowndowncase
+
+2002-04-04  Gergely Nagy  <algernon@debian.org>
+
+       * debian/changelog: Updated for the new snapshot
+
+       * debian/rules: Install README.Debian into the package
+
+       * debian/README.Debian: Initial check-in
+
+2002-04-04  Mario Lang  <mlang@delysid.org>
+
+       * erc.el:
+       Fixed that /me in query buffers ended up in server buffer
+
+       * erc.el: * Implemented joining +k channels
+
+2002-03-14  Mario Lang  <mlang@delysid.org>
+
+       * erc.el: 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:
+       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: *** empty log message ***
+
+2002-03-09  Mario Lang  <mlang@delysid.org>
+
+       * erc-complete.el:
+       New variable: erc-nick-completion-ignore-case. Defaults to t.
+
+       * erc-track.el:
+       * 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, debian/rules: update to new snapshot
+
+2002-03-06  Mario Lang  <mlang@delysid.org>
+
+       * erc.el:
+       Fixed nasty bug which prevented channel limit from correctly display/handling
+
+       * erc-track.el: 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:
+       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: added iirc to the abbreviation expansion list.
+
+       * erc-track.el:
+       Added customization variable: erc-track-use-faces. defaults to t.
+
+       * erc-track.el: *** empty log message ***
+
+       * erc-track.el:
+       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: * added docfixes (thanks ore)
+
+       * erc-track.el: Fixed channel-name reduction.
+       thanks again alex.
+       Renamed the vars to erc-track-opt-start and erc-track-opt-cutoff.
+
+       * erc.el: fixed another silly error
+
+       * erc-track.el: 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 2002-07-15T00:01:34Z!raeburn@raeburn.org: silly typo corrected
+
+       * erc.el:       * erc.el: * 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:
+       CTCP handling rewritten. Seems to work. please test and report probs.
+
+2002-02-24  Mario Lang  <mlang@delysid.org>
+
+       * erc.el:
+       Fixed emacs20 backward compatibility (new defun/alias: erc-propertize)
+
+2002-02-22  Mario Lang  <mlang@delysid.org>
+
+       * erc-button.el: *** empty log message ***
+
+2002-02-21  Mario Lang  <mlang@delysid.org>
+
+       * erc-button.el, erc.el:
+       minor fixup related to read-only prompts and command renaming.
+
+2002-02-21  Andreas Fuchs  <asf@void.at>
+
+       * erc.el: * 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:
+       fixed erc-replace-command to behave right when text is read-only.
+       Also, use erc-insert-marker and (point-max) now.
+
+       * erc.el: * 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: added comment to docstring
+
+       * erc-speak.el: minor updates, use erc-nick-regexp now
+
+       * erc.el:
+       ensure that erc-timer-hook is called inside the server-buffer.
+
+2002-02-19  Andreas Fuchs  <asf@void.at>
+
+       * erc-match.el:
+       * Probably fixed the "number-char-or-marker-p: nil" bug.
+
+2002-02-19  Mario Lang  <mlang@delysid.org>
+
+       * erc-notify.el: Initial release.
+
+       * erc.el: added #303 handling
+       moved timer and added an arg (erc-current-time)
+
+       * erc-list.el, erc.el:
+       slightly changed the erc-once-with-server-event macro
+
+       * erc-button.el: erc-button-alist: doc fix and custom type fix
+
+2002-02-18  Mario Lang  <mlang@delysid.org>
+
+       * erc-list.el, erc.el: new macro: erc-once-with-server-event
+       erc-list.el: use it
+
+       * erc-match.el:
+       Minor fix related to hook call method change (-until-seccess now)
+
+       * erc.el: fixed ctcp behaviour abit (with auto-query on)
+
+       * erc-list.el: ChanList mode.
+       Load it, and type M-x erc-chanlist RET
+       Demonstrates how the new hook system can be nicely used.
+
+       * erc.el:
+       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: fix regexp to not buttonize ~user@host hostnames
+
+2002-02-17  Mario Lang  <mlang@delysid.org>
+
+       * erc-complete.el, erc.el: 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:
+       * Fix unfunctional code in `erc-get-parsed-vector-type'.
+
+       * erc-bbdb.el, erc-button.el, erc-match.el, erc.el:
+       * 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: Added item
+
+2002-02-17  Brian P Templeton  <bpt@tunes.org>
+
+       * CREDITS, erc.el: Added invisible timestamp support.
+
+2002-02-16  Gergely Nagy  <algernon@debian.org>
+
+       * debian/changelog, debian/rules, debian/scripts/install:
+       updated to new snapshot
+
+2002-02-16  Mario Lang  <mlang@delysid.org>
+
+       * erc.el:
+       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: TODO list created.
+       Add comments and expand it.
+
+       * erc.el:
+       Fixed bug in query buffer handling (only happend in mixed-case situations)
+
+       * erc.el: shapr checkdoc patch #1
+       massive docfixes! yay, keep going!
+
+2002-02-15  Mario Lang  <mlang@delysid.org>
+
+       * erc.el: various other fixes
+       make s301 a catalog entry
+
+2002-02-15  Andreas Fuchs  <asf@void.at>
+
+       * erc.el: * 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, erc.el:
+       * 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:
+       first step, new function: erc-display-message
+
+       * erc.el: added numreply 379 and 405.
+
+       * erc.el: stupid typo fixed
+
+       * erc.el:
+       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:
+       * 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(erc-format-privmessage):
+       fix it, so timestamp-coloring works again (patch from antifuchs)
+
+2002-02-14  Mario Lang  <mlang@delysid.org>
+
+       * erc.el: 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, erc-ibuffer.el: minor fixes
+
+       * erc.el: 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, erc.el:
+       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:
+       Database of irc networks. Use erc-server-select to interactively select one.
+
+       * erc.el: * 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: Split code from erc.el
+
+2002-02-01  Mario Lang  <mlang@delysid.org>
+
+       * erc-ibuffer.el:
+       * erc-target now uses erc-port-to-string
+
+       * servers.pl:
+       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:
+       * 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:
+       * erc-already-logged-in-p: compare ports is more robust now.
+
+       * erc-button.el: * Add buttonization to erc-send-modify-hook, too
+
+2002-01-31  Mario Lang  <mlang@delysid.org>
+
+       * erc.el:
+       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, erc.el: minor fixes
+
+       * erc.el:
+       * (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:
+       Minor docstring fixes (using M-x checkdoc-current-buffer)
+         If you find time, and you are native english speaker, do that too!!
+
+       * erc.el: fixed macro-invokation
+
+2002-01-31  Andreas Fuchs  <asf@void.at>
+
+       * erc.el: * 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:
+       * Fix last multiline bug in erc-send-distinguish-noncommands.
+
+2002-01-31  Mario Lang  <mlang@delysid.org>
+
+       * erc-ibuffer.el, erc.el: minor fixes
+
+2002-01-30  Mario Lang  <mlang@delysid.org>
+
+       * erc-ibuffer.el, erc-menu.el, erc-speak.el, erc.el:
+       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:
+       * 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, erc.el:
+       * 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, erc-button.el, erc-speak.el, erc.el:
+       hook handling rewrite phase 1.
+
+2002-01-30  Andreas Fuchs  <asf@void.at>
+
+       * erc.el: * 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, HISTORY:
+       Initial checkin.
+
+2002-01-29  Andreas Fuchs  <asf@void.at>
+
+       * erc.el: * 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, erc.el:
+       Rewrote channel tracking using window-configuration-change-hook instead of defadvices.
+
+2002-01-28  Andreas Fuchs  <asf@void.at>
+
+       * erc-fill.el, erc.el:
+       * 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:
+       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:
+       Highlight tracking finished. All necessary info should now be in erc-modified-channels.
+
+       * erc.el, erc-ibuffer.el, erc-speedbar.el:
+       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: Added erc-members column
+
+       * erc-ibuffer.el: *** empty log message ***
+
+2002-01-28  Andreas Fuchs  <asf@void.at>
+
+       * erc-bbdb.el:
+       * 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: *** empty log message ***
+
+2002-01-27  Mario Lang  <mlang@delysid.org>
+
+       * erc-ibuffer.el: Fixup, it sort of works now. Try it
+
+       * erc-ibuffer.el: Initial version
+
+2002-01-26  Mario Lang  <mlang@delysid.org>
+
+       * erc.el: *** empty log message ***
+
+2002-01-25  Andreas Fuchs  <asf@void.at>
+
+       * erc-bbdb.el: * 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: *** empty log message ***
+
+2002-01-25  Andreas Fuchs  <asf@void.at>
+
+       * erc-bbdb.el: * 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:
+       * Fix the erc-button-alist regexp for EmacsWiki stuff. delYsid's version
+         is better (-:
+
+       * erc-button.el: * 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:
+       erc-bbdb-NICK: Added regexp-quote around fingerhost search.
+
+2002-01-10  Andreas Fuchs  <asf@void.at>
+
+       * erc.el:
+       * 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: * fix stupid documentation errors.
+
+2002-01-07  Mario Lang  <mlang@delysid.org>
+
+       * erc.el:
+       * (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:
+       * Added require for erc-button. This is devel. so I need testers :)
+
+       * erc-button.el: * Added proper file headers (GPL).
+
+2002-01-04  Mario Lang  <mlang@delysid.org>
+
+       * erc-button.el: * erc-button-alist: Added entry for finger
+
+       * erc-button.el: * Removed bogus usage of :button-keymap.
+       P
+          Does anyone know what this was supposed to do anyway?
+
+       * erc-button.el: * 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
+
+    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.
+
+;; arch-tag: a6779d5e-99fa-442b-98cf-90e73eb2c272
diff --git a/lisp/erc/ChangeLog.2003 b/lisp/erc/ChangeLog.2003
new file mode 100644 (file)
index 0000000..d67393c
--- /dev/null
@@ -0,0 +1,2145 @@
+2003-12-30  Francis Litterio  <franl@users.sourceforge.net>
+
+       * erc.el(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(erc-query-buffer-p): Added this function.
+
+2003-12-28  Jorgen Schaefer  <forcer@users.sourceforge.net>
+
+       * erc.el(erc-cmd-SV): Use erc-emacs-build-time.
+
+       * erc-compat.el: erc-emacs-build-time: New variable.
+
+       * erc.el(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(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(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(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(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: Fixed another typo.
+
+       * erc-list.el: Fixed a typo.
+
+       * erc-list.el:
+       Added text to the top of the channel list buffer describing the keybinding for
+       function erc-chanlist-join-channel.
+
+       * erc-list.el: Minor appearance changes.  No functional change.
+
+       * erc-list.el:
+       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:
+       Removed a bunch of unused code.  No semantic change.
+
+       * erc-list.el: Added lots of functionality.
+
+2003-12-15  Mario Lang  <mlang@delysid.org>
+
+       * erc-track.el, erc.el:
+       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(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(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(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(erc-define-minor-mode):
+       Deal with :global and :group keywords.
+
+       * erc-nickserv.el(erc-current-network):
+       Make server regex more permissive.
+
+       * erc.el(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: 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: Code provided by johnw, thanks!
+
+2003-11-09  Lawrence Mitchell  <wence@gmx.li>
+
+       * erc.el(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: Add more info to /sv
+
+2003-11-06  Francis Litterio  <franl@users.sourceforge.net>
+
+       * erc.el: Added optional argument BUFFER to erc-server-buffer-p.
+
+2003-11-04  Mario Lang  <mlang@delysid.org>
+
+       * AUTHORS: Add sachac
+
+2003-11-02  Lawrence Mitchell  <wence@gmx.li>
+
+       * erc.el(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(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: Added a (provide 'erc-sound) line.
+
+       * erc.el(erc-cmd-NAMES): send to TGT, not CHANNEL.
+
+2003-10-29  Sandra Jean Chua  <sacha@free.net.ph>
+
+       * erc-pcomplete.el, erc.el, CREDITS:
+       Merged Jeremy Maitin-Shepard's patch for time-sensitive nick completion.
+
+2003-10-27  Mario Lang  <mlang@delysid.org>
+
+       * Makefile, debian/changelog:
+       New Debian package 4.0.cvs.20031027
+
+2003-10-25  Mario Lang  <mlang@delysid.org>
+
+       * erc.el: Fix typo tuncate->rruncate
+
+2003-10-24  Mario Lang  <mlang@delysid.org>
+
+       * erc-dcc.el: 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(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(erc-log-file-coding-system): New variable.
+       (erc-save-buffer-in-logs): Use it.
+
+2003-10-17  Mario Lang  <mlang@delysid.org>
+
+       * erc.el(erc-interpret-mirc-color): New boolean defcustom
+
+       * erc.el: Do not use -nowait on darwin (thanks johnw)
+
+2003-10-15  Lawrence Mitchell  <wence@gmx.li>
+
+       * erc.el(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(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(erc-hide-list): Add a nice defcustom type
+
+2003-10-08  Mario Lang  <mlang@delysid.org>
+
+       * Makefile, debian/changelog, debian/control:
+       Debian snapshot 20031008
+
+       * erc-speedbar.el:
+       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(erc-match-syntax-table): New variable.
+       (erc-match-current-nick-p): Use it.
+
+       * erc.el(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(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(erc-keywords): Removed. Wasn't used by anything.
+
+2003-09-25  Lawrence Mitchell  <wence@gmx.li>
+
+       * erc.el: 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(erc-parse-line-from-server):
+       Ignore empty lines as required by RFC.
+
+2003-09-17  Mario Lang  <mlang@delysid.org>
+
+       * erc.el: Add lag time calculation
+
+2003-09-13  Mario Lang  <mlang@delysid.org>
+
+       * Makefile, debian/README.Debian, debian/changelog:
+       New debian release
+
+       * erc-notify.el:
+       Call erc-notify-install-message-catalogs on load, not on module init
+
+       * erc.el(erc-update-modules):
+       Use `load' instead of `require'.  XEmacs appears
+       to have the NOERROR arg only sometimes... Strange
+
+       * erc.el: No fboundp if we have a defvar
+
+       * erc.el: Properly defvar erc-ping-handler
+
+2003-09-11  Damien Elmes  <erc@repose.cx>
+
+       * erc.el(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(erc-cmd-NICK):
+       Warn about exceeded NICKLEN if we know it.
+
+       * erc.el: Make erc-server-PONG obey erc-verbose-server-ping.
+       Cancel old `erc-ping-handler' timer when restablishing connection in the same
+       buffer.
+
+       * debian/changelog, Makefile: New debian snapshot
+
+       * erc-dcc.el, erc-xdcc.el:
+       Use new function erc-dcc-file-to-name to convert spaces to underscores
+
+       * erc-xdcc.el: Add autoload for erc-xdcc-add-file
+
+2003-09-08  Mario Lang  <mlang@delysid.org>
+
+       * erc-dcc.el: indent fixes and copyright update
+
+       * erc.el:
+       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(erc-default-coding-system):
+       Test for undecided and utf-8
+       before setting.
+
+2003-09-01  Mario Lang  <mlang@delysid.org>
+
+       * erc.el(erc-modules): Add some more symbols to the set
+
+       * erc.el(erc-modules):  * erc.el(erc-modules): Add :greedy t to the set in 
+
+       * erc-dcc.el:
+       More autoloads which make dcc autoload upon ctcp dcc query received.
+
+       * erc-dcc.el(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: Update copyright
+
+       * erc-autojoin.el(erc-autojoin-add):
+       Only add the channel if it is not already there.
+
+       * erc-notify.el:
+       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(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:
+       * 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:
+       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: Fix typo in varname which led to a compiler warning
+
+       * AUTHORS: Added lawrence
+
+2003-08-27  Mario Lang  <mlang@delysid.org>
+
+       * erc-dcc.el:
+       Set process and file-coding system to 'binary (for Windows)
+
+       * erc-stamp.el: Rename custom group erc-timestamp to erc-stamp.
+
+2003-08-07  Lawrence Mitchell  <wence@gmx.li>
+
+       * erc-fill.el(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(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 the immediate previous version by wencem.
+
+2003-08-04  Lawrence Mitchell  <wence@gmx.li>
+
+       * erc.el(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: 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(erc-display-line-1):
+       Fixed bad indentation on one line.  No semantic change.
+
+2003-07-29  Lawrence Mitchell  <wence@gmx.li>
+
+       * erc-match.el:
+       Quote open paren in docstring of erc-text-matched-hook
+
+       * erc.el: Anchor match only at beginning in erc-ignored-user-p.
+
+       * erc-button.el: 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(erc-network-name):
+       Improved docstring.  Removed an unnecessary call to erc-server-buffer.
+
+2003-07-28  Mario Lang  <mlang@delysid.org>
+
+       * erc.el: 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, erc-nickserv.el, erc.el:
+       Changed all references to Openprojects into references to Freenode.
+
+2003-07-25  Francis Litterio  <franl@users.sourceforge.net>
+
+       * erc.el:
+       Now variable erc-debug-irc-protocol is defvar'ed instead of defcustom'ed.
+       Made the docstring clearer too.
+
+       * erc.el: Fixed a wrong-type-argument error from window-live-p.
+
+2003-07-15  Damien Elmes  <erc@repose.cx>
+
+       * erc-log.el(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(erc-dcc-open-network-stream):
+       -nowait still crashes emacs cvs - disable for now
+
+2003-07-02  Francis Litterio  <franl@users.sourceforge.net>
+
+       * erc.el(erc): Minor docstring modification.
+
+2003-07-01  Damien Elmes  <erc@repose.cx>
+
+       * erc-match.el(erc-match-current-nick-p):
+       match only on word boundaries
+
+       * erc-log.el(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(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(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(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:
+       Added some text to the docstring for variable erc-debug-irc-protocol.
+
+2003-06-23  Francis Litterio  <franl@users.sourceforge.net>
+
+       * erc-dcc.el(erc-dcc-auto-mask-p):
+       Fixed a docstring typo that caused a load-time error.
+
+       * erc-dcc.el(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(erc-notify-timer and erc-notify-QUIT):
+       Added network name to notify_off message.
+
+       * erc.el(erc-network-name):
+       Now returns the name of the IRC server if the network name
+           cannot be determined.
+
+       * erc-notify.el(erc-notify-JOIN and erc-notify-NICK):
+       Added argument ?m to call to erc-display-message.
+
+       * erc-dcc.el(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(erc-notify-timer):
+       Now we include the network name in the notify_on message.
+
+       * erc.el:
+       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(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(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(erc-display-prompt):
+       Fixed incorrect indentation.  No semantic change.
+
+       * erc.el(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(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:
+       * added quickstart information to the comments up the top
+
+2003-06-16  Mario Lang  <mlang@delysid.org>
+
+       * erc.el:
+       Default to open-network-stream on MS Windows. (thanks lawrence)
+
+2003-06-11  Damien Elmes  <erc@repose.cx>
+
+       * erc.el(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:
+       Re-add the last few changes which weren't merged for some reason.
+
+       * erc.el(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:
+       Added comment to explain (eval-after-load "erc" '(erc-update-modules)).
+
+2003-06-01  Mario Lang  <mlang@delysid.org>
+
+       * erc-pcomplete.el: Add completion for /unignore
+
+2003-05-31  Alex Schroeder  <alex@gnu.org>
+
+       * erc-compat.el(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:
+       Add handlers for 313 and 330 (by arne@rfc2549.org, thanks)
+
+2003-05-30  Damien Elmes  <erc@repose.cx>
+
+       * erc.el:
+       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(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(erc-decode-coding-string):
+       Now requires coding-system as an argument.
+
+2003-05-15  Mario Lang  <mlang@delysid.org>
+
+       * erc.el:
+       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:
+       * erc-truncate-buffer-to-size: use fboundp. Scheme takes its toll...
+
+2003-05-01  Jorgen Schaefer  <forcer@users.sourceforge.net>
+
+       * erc-truncate.el: 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, erc-truncate.el, erc.el: 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(erc):
+       Check wether erc-save-buffer-in-logs is bound, too
+
+       * erc.el(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:
+       * while we're at it, remove the (declare (ignore ignore)) statements.
+
+       * erc-log.el:
+       * add autoload statement for erc-log-mode/etc. Sorry for the delay.
+
+       * erc-log.el, erc.el: * 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:       * erc.el: erc-modules: added 
+
+2003-04-27  Alex Schroeder  <alex@gnu.org>
+
+       * Makefile(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:
+       erc-button-keymap: set the parent keymap to erc-mode-map
+
+2003-04-20  Damien Elmes  <erc@repose.cx>
+
+       * erc.el:
+       erc-official-location: shouldn't the official location be the base URL of erc?
+
+       * erc.el:
+       erc-modules: updated the docstring to make the semantics clearer
+
+2003-04-19  Mario Lang  <mlang@delysid.org>
+
+       * erc.el:
+       Fix problem where % in NOTICE produced errors (from mmc)
+
+2003-04-18  Damien Elmes  <erc@repose.cx>
+
+       * erc.el(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, erc.el:
+       (erc-update-modules: added a condition in for erc-nickserv -> erc-services
+
+       * erc-pcomplete.el:
+       - 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:
+       - 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, Makefile:
+       Updated Makefile and documentation to reflect the new release
+
+       * erc.el:
+       - 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:
+       fixed about 20 instances of (message (format ...)) which will break if the
+       format returns a string with %s in it
+
+       * erc.el: erc-error-face: make it red, not pink
+
+       * erc-pcomplete.el:
+       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(define-erc-module): no need for delete, use delq
+
+       * erc-members.el(erc-nick-channels):
+       (erc-person-channels) takes one arg
+       (erc-format-user): again, they all take an arg
+
+       * erc.el:
+       - 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(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:
+       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(erc):
+       but when inserting the contents of a previous logfile, use the logfile
+           name, not ""!
+
+       * erc.el(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(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(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:
+       Fix erc-prompt and erc-user-mode custom :type (Closes: #185794)
+
+2003-03-20  Damien Elmes  <erc@repose.cx>
+
+       * erc.el:
+       erc-server-hook-list: correct documentation of ordering of (proc parsed)
+
+2003-03-16  Alex Schroeder  <alex@gnu.org>
+
+       * erc-track.el(erc-modified-channels-string):
+       Make it a risky-local-variable.
+
+2003-03-16  Jorgen Schaefer  <forcer@users.sourceforge.net>
+
+       * erc-track.el(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(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(erc-find-parsed-property):
+       simplified a little, so it shouldn't return nil anymore
+
+       * erc.el: erc-send-post-hook: document narrowing which occurs
+
+2003-03-14  Alex Schroeder  <alex@gnu.org>
+
+       * erc-track.el(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:
+       Fix erc-set-topic to accept a channel name as first word
+
+2003-03-11  Jorgen Schaefer  <forcer@users.sourceforge.net>
+
+       * erc-dcc.el:
+       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(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:
+       (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: banlist*: patch from mrbump to avoid using cl packages
+
+2003-03-04  Francis Litterio  <franl@users.sourceforge.net>
+
+       * erc.el:
+       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(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(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(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(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(erc-cmd-SERVER):
+       remove erroneous references to line, use server instead
+
+2003-02-23  Francis Litterio  <franl@users.sourceforge.net>
+
+       * erc.el(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(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(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:
+       * s/choose/choice/ in customize options, as kensanata requested.
+
+2003-02-15  Francis Litterio  <franl@users.sourceforge.net>
+
+       * erc.el(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(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:
+       * 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(erc-login): register that we're connected
+
+2003-02-10  Mario Lang  <mlang@delysid.org>
+
+       * erc-members.el: * Provide erc-members
+       * Fix excessive )
+       * Comment out broken self-tests
+
+2003-02-07  Damien Elmes  <erc@repose.cx>
+
+       * erc.el(erc-connect):
+       notify the user we're trying to connect when using asych
+           connections
+
+       * erc.el(erc-connect): support an asyncronous connection
+       (erc-process-sentinel): ditto
+
+       * erc-track.el:
+       * advise switch-to-buffer in the case of xemacs, since it doesn't have
+         window-configuration-change-hook
+
+       * erc.el(erc-send-current-line):
+       if not connected, refuse to send either a message or
+           a command
+
+       * erc.el: (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(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(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(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(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(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(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(erc-cmd-NOTICE): fix from mrbump
+
+2003-01-31  Francis Litterio  <franl@users.sourceforge.net>
+
+       * erc.el(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(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:
+       (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(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(services): Defined a module
+
+2003-01-25  Jorgen Schaefer  <forcer@users.sourceforge.net>
+
+       * erc.el(erc-process-ctcp-query):
+       Display recipient of CTCP query if it's not
+       our current nick.
+
+       * erc.el(erc-cmd-WHOIS):
+       Accept an optional second argument SERVER.
+
+2003-01-25  Alex Schroeder  <alex@gnu.org>
+
+       * erc-stamp.el(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(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:
+       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(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(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(erc-cmd-BANLIST):
+       in the absence of a fill-column, use the screen width
+
+2003-01-22  Damien Elmes  <erc@repose.cx>
+
+       * erc.el:
+       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:
+       * 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:
+       Put "how to use" documentation in the comments up the top
+
+2003-01-21  Alex Schroeder  <alex@gnu.org>
+
+       * erc-autojoin.el(erc-autojoin-version): New.
+
+       * erc-autojoin.el(erc-autojoin-add): Added body.
+       (erc-autojoin-remove): Added body.
+       (erc-autojoin): Provide it.
+
+2003-01-21  Damien Elmes  <erc@repose.cx>
+
+       * erc.el: erc-cmd-*: removed a bunch of references to force
+
+2003-01-21  Alex Schroeder  <alex@gnu.org>
+
+       * erc-autojoin.el(erc-autojoin-channels-alist): More doc.
+
+2003-01-20  Alex Schroeder  <alex@gnu.org>
+
+       * erc-autojoin.el:
+       new, based on resolve's mail, and the stuff on the wiki
+
+       * erc-members.el: new
+
+2003-01-19  Mario Lang  <mlang@delysid.org>
+
+       * debian/README.Debian, debian/changelog, debian/scripts/install, 
+         debian/scripts/startup.erc, Makefile:
+       Prepare for 20030119 debian package
+
+       * erc-dcc.el: <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:
+       * (erc-log-irc-protocol): Use erc-propertize, not propertize
+
+2003-01-19  Alex Schroeder  <alex@gnu.org>
+
+       * erc-button.el(erc-button-add-buttons): Added regexp-quote for
+       the list case, too.
+
+2003-01-19  Damien Elmes  <erc@repose.cx>
+
+       * erc-dcc.el(erc-dcc-member): fix for case where a prop is nil
+
+       * erc-dcc.el(erc-dcc-member):
+       fix for xemacs's version of plist-member
+
+2003-01-19  Mario Lang  <mlang@delysid.org>
+
+       * erc-notify.el: Delete empty strings from the ison-list
+
+       * erc-track.el:
+       * (erc-track-switch-buffer): Call erc-modified-channels-update here.
+
+       * erc-track.el: * toplevel: require 'erc-match
+
+       * erc-track.el: * (erc-track-mode): Make autoload interactive
+
+       * erc-button.el: * (button): Make the autoload interactive
+
+       * erc.el:
+       * (erc-mode): Comment out the case-table stuff, breaks xemacs
+       * (erc-downcase): Revert.
+
+       * erc-dcc.el:
+       * (erc-dcc-handle-ctcp-send): Use erc-decimal-to-ip on the ip we get...
+
+       * erc-speak.el:
+       Eliminate reference to erc-nick-regexp, which no longer exists
+
+2003-01-19  Alex Schroeder  <alex@gnu.org>
+
+       * erc-stamp.el(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(erc-downcase): Use the old behavior in non-CVS Emacs.
+
+       * erc.el(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(erc-cmd-QUIT): make reason optional.
+
+       * erc.el(erc-cmd-GQUIT): Fixed typo.
+
+2003-01-17  Mario Lang  <mlang@delysid.org>
+
+       * erc.el:
+       * (erc-current-logfile): call expand-file-name, so that downcase doesn't mess up ~
+
+       * erc.el: * (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: * (erc-button-add-buttons): regex-quote the nick
+
+2003-01-17  Alex Schroeder  <alex@gnu.org>
+
+       * erc-button.el(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: 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(erc-autoaway-set-back):
+       Don't pass a force argument to erc-cmd-GAWAY.
+
+       * erc.el(erc-cmd-AWAY): Removed usage of the force variable.
+
+2003-01-17  Alex Schroeder  <alex@gnu.org>
+
+       * erc-button.el(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(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(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:
+       fix erc-remove-channel-member again to not error out on nil as first arg...
+
+       * erc.el: * (erc-occur): New function
+
+2003-01-17  Damien Elmes  <erc@repose.cx>
+
+       * erc.el: erc-banlist-*: return nil so further hooks are called
+
+       * erc.el(erc-server-368):
+       supress "end of ban list" messages - use /listbans now
+
+       * erc.el(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(erc-cmd-JOIN): fixed (again)
+
+       * erc.el: * fixed call to erc-cmd-NICK when connecting
+       * support for listing bans and mass unbanning, again thanks to MrBump
+
+       * erc.el(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:
+       * (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: moved misplaced paren
+
+2003-01-16  Damien Elmes  <erc@repose.cx>
+
+       * erc.el(erc-cmd-UNIGNORE):
+       reference argument directly - no string matching
+
+       * erc.el(erc-extract-command-from-line):
+       hmm, thinko in the canonicalisation. should
+           be fixed
+
+2003-01-16  Francis Litterio  <franl@users.sourceforge.net>
+
+       * erc.el(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: * (erc-dcc-do-SEND-command): Fix it
+
+       * erc-ezbounce.el, erc-lang.el: Arglist changes...
+
+       * erc.el: Various docstring fixes and additions.
+
+       * erc-notify.el:
+       * (erc-cmd-NOTIFY): Change the function arglist to (&rest args)
+
+       * erc-netsplit.el: * (erc-cmd-WHOLEFT): Has no args...
+
+2003-01-16  Damien Elmes  <erc@repose.cx>
+
+       * erc-fill.el:
+       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:
+       * (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:
+       * (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:
+       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: * bad-syntax now reports like incorrect-args
+       * bunch of extra cmds fixed, nick, sv etc.
+
+       * erc.el(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:
+       * 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(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(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: * (erc-cmd-IGNORE): fixed
+
+       * erc.el: * (erc-cmd-NAMES): fixed
+
+       * erc.el:
+       * (erc-cmd-CLEARTOPIC): Simplify, fix doc, make interactive
+
+2003-01-15  Damien Elmes  <erc@repose.cx>
+
+       * erc.el(erc-cmd-JOIN):
+       correct invite behavior, and document it.
+
+2003-01-15  Mario Lang  <mlang@delysid.org>
+
+       * erc.el: * (erc-cmd-PART): Put 'do-not-parse-args t
+
+2003-01-15  Damien Elmes  <erc@repose.cx>
+
+       * erc.el(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:
+       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:
+       * (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: * (erc-cmd-OP): LINE is PEOPLE now, and already parsed.
+
+       * erc-notify.el:
+       * (erc-cmd-NOTIFY): Arg LINE is now ARGS, and already parsed.
+
+2003-01-15  Jorgen Schaefer  <forcer@users.sourceforge.net>
+
+       * erc-stamp.el(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: 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:nick:      * erc-dcc.el: * 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(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:
+       * (erc-cmd-AMSG): Remove useless call to erc-display-message.
+
+       * erc-dcc.el:
+       * 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: * (erc-cmd-AMSG). New command.
+
+       * erc-xdcc.el: * (erc-xdcc): delete empty strings from ARGS
+
+       * erc-dcc.el: * 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:
+       * (erc-insert-timestamp-right): Subtract (length string) from
+       POS in any case, otherwise, linewrap occurs.
+
+       * erc-dcc.el:
+       * 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:
+       * 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: * 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(erc-server-JOIN):
+       Oops, send MODE command only when *we* joined a channel.
+
+       * erc.el:
+       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:
+       (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: * 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: * (pcomplete-erc-mode/DCC): Fixes
+
+       * erc-xdcc.el: Initial version.
+
+       * erc-pcomplete.el:
+       * (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: Fix to pcomplete/erc-mode/DCC
+
+       * erc-dcc.el: * (pcomplete/erc-mode/DCC): New function
+
+       * erc-dcc.el: *** empty log message ***
+
+       * erc-dcc.el: Move code around, just basic changes
+
+2003-01-11  Jorgen Schaefer  <forcer@users.sourceforge.net>
+
+       * erc-stamp.el(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:
+       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:   * erc-dcc.el: * (erc-dcc-do-LIST-command): Fix 
+
+       * erc-dcc.el:
+       * 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:
+       * (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: *** empty log message ***
+
+       * erc-dcc.el: Moved some functions around.
+       Doc string fixes.
+       "/dcc send nick filename" works now
+
+2003-01-11  Alex Schroeder  <alex@gnu.org>
+
+       * erc.el(erc-send-command): Fixed flood protect message.
+
+       * erc-button.el(erc-button-syntax-table): Make `-' a legal nick
+       constituent.
+
+2003-01-10  Mario Lang  <mlang@delysid.org>
+
+       * erc-dcc.el: Some more steps toward dcc send.
+
+2003-01-10  Francis Litterio  <franl@users.sourceforge.net>
+
+       * erc-notify.el(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(erc-ison-p):
+       Fixed so it calls erc-member-ignore-case instead of member.
+
+       * erc.el(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:
+       (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: erc-complete-functions: New variable.
+       erc-mode-map: Bind \t to 'erc-complete-word
+       erc-complete-word: New function.
+
+       * erc-pcomplete.el(erc-pcomplete-mode):
+       Use new erc-complete-functions
+       (erc-pcomplete): Check that we're in the input line, else return nil.
+
+       * erc-button.el(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: cleanup
+
+       * erc-dcc.el:
+       * (erc-dcc-chat-request): No longer use erc-send-ctcp-message.
+
+       * erc-dcc.el:
+       * (erc-dcc-no-such-nick): Also call delete-process if we have a peer already
+
+       * erc-dcc.el:
+       * (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: Moved code around a bit, and doc fixes
+
+       * erc-dcc.el: *** empty log message ***
+
+       * erc-dcc.el: Rename erc-dcc-plist to erc-dcc-list
+
+2003-01-09  Damien Elmes  <erc@repose.cx>
+
+       * erc-dcc.el(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:
+       (erc), (erc-setup-buffer): factor out window generation code so DCC can use
+           it too
+
+       * erc-dcc.el:
+       (erc-dcc-do-CLOSE-command), (erc-dcc-do-LIST-command): work with erc-dcc-plist
+
+       * erc-dcc.el:
+       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(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(erc-add-to-input-ring): s/nullp/null/
+
+2003-01-09  Damien Elmes  <erc@repose.cx>
+
+       * erc-ring.el(erc-add-to-input-ring):
+       set up the ring if it's not already setup
+
+       * erc-dcc.el(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: (temporarily) fix erc-process setting...
+
+       * erc-dcc.el: * (erc-dcc-chat-send-line): Removed
+
+       * erc.el:
+       Check if target is stringp (we can now also have 'dcc as value...)
+
+       * erc-dcc.el(erc-dcc-chat-send-input-line):
+       New function, used for
+       erc-send-input-line-function.
+       Use erc-send-current-line now.
+
+       * erc-dcc.el: evt to elt...
+
+       * erc-dcc.el: Remove () from a var (how silly!)
+
+       * erc-dcc.el: * (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(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(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:
+       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:
+       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:
+       * erc-send-input-line-function: New variable, used for dispatch...
+
+2003-01-08  Damien Elmes  <erc@repose.cx>
+
+       * erc-dcc.el(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(erc-all-buffer-names):
+       Check for erc-dcc-chat-mode too
+
+2003-01-08  Francis Litterio  <franl@users.sourceforge.net>
+
+       * erc-ring.el, erc.el(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(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:
+       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: reindent some code, and add TODO to comments
+
+       * erc-dcc.el: *** empty log message ***
+
+       * erc-dcc.el: Make dcc-chat-ended a notice
+       Remove now bogus comment
+
+2003-01-08  Damien Elmes  <erc@repose.cx>
+
+       * erc-dcc.el(erc-pack-int): from erc-packed-int
+       (erc-unpack-int): new
+
+       * erc-dcc.el(erc-unpack-str): added
+
+2003-01-08  Mario Lang  <mlang@delysid.org>
+
+       * erc.el(erc-server-482):
+       New handler, handles KICK reply if you're not channel-op
+
+       * erc-dcc.el: Document SEND in erc-dcc-alist.
+       Move sproc, parent-proc and file into erc-dcc-alist
+
+       * erc-dcc.el: stubs
+
+       * erc-dcc.el(erc-dcc-get-host):
+       Change :iface to :local since Kim committed it now to CVS emacs
+
+       * erc-dcc.el(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(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(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:
+       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(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(erc-cmd-DCC):
+       Change (cond ... (t nil)) to (when ...)
+
+       * erc-dcc.el: Use erc-current-nick-p
+
+2003-01-07  Jorgen Schaefer  <forcer@users.sourceforge.net>
+
+       * erc.el:
+       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(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(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:
+       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: Add autoload cookie
+
+       * erc-notify.el:
+       Now also pass SERVER argument to signon/off hooks, and provide a erc-notify-signon/off function for echo-area printing
+
+       * erc-notify.el(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(erc-ctcp-query-VERSION):
+       v%s -> %s, so we are no longer vVersion...
+
+2003-01-06  Mario Lang  <mlang@delysid.org>
+
+       * erc.el: Small change to erc-ison-p, and fixme tag
+
+2003-01-06  Francis Litterio  <franl@users.sourceforge.net>
+
+       * erc.el(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:
+       Some stub functions, some code, nothing really works yet
+
+       * erc.el(erc-ison-p): New function
+
+       * erc-dcc.el: Some functions which will be needed for dcc send
+
+       * erc-dcc.el(erc-ip-address-to-decimal):
+       New function, thanks lawrence
+
+       * erc-dcc.el: Again, simplify code, fix stuff, DCC CHAT works now
+
+       * erc-dcc.el: Many fixes, chat nearly works now
+
+       * erc-netsplit.el: Also detect fast netsplit/joins
+
+       * erc-dcc.el: some more fixes
+
+       * erc-dcc.el: Fixup stage 1, now dcc get works
+
+       * erc-dcc.el: make /dcc LIST work
+
+       * erc-dcc.el:
+       Initial checkin, dont use it!  its really far from complete.  Hackers: help!
+
+       * erc-notify.el:
+       New function erc-notify-NICK, and added signon/off hooks which were missing
+
+2003-01-05  Jorgen Schaefer  <forcer@users.sourceforge.net>
+
+       * erc.el(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(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:
+       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(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.
+
+    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.
+
+;; arch-tag: 808865e1-3cce-4c5b-9997-95a8b7a9d384
diff --git a/lisp/erc/ChangeLog.2004 b/lisp/erc/ChangeLog.2004
new file mode 100644 (file)
index 0000000..2a5ce9e
--- /dev/null
@@ -0,0 +1,2074 @@
+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. Brian Palmer's change of 2004-12-12 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
+       `èrc-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 `èrc-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 my changes from 2004-01-11.
+
+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.
+
+    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.
+
+;; arch-tag: cc606d2d-635b-4b36-829b-a50e3c51e2d1
diff --git a/lisp/erc/ChangeLog.2005 b/lisp/erc/ChangeLog.2005
new file mode 100644 (file)
index 0000000..2895306
--- /dev/null
@@ -0,0 +1,1222 @@
+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): Fix broken undo.
+
+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).
+
+    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.
+
+;; arch-tag: 70f1733a-3e2f-43c2-91c3-d9ace93f82ba
diff --git a/lisp/erc/erc-autoaway.el b/lisp/erc/erc-autoaway.el
new file mode 100644 (file)
index 0000000..41c16b8
--- /dev/null
@@ -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
diff --git a/lisp/erc/erc-autojoin.el b/lisp/erc/erc-autojoin.el
new file mode 100644 (file)
index 0000000..38a149d
--- /dev/null
@@ -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
diff --git a/lisp/erc/erc-backend.el b/lisp/erc/erc-backend.el
new file mode 100644 (file)
index 0000000..a99af9d
--- /dev/null
@@ -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
diff --git a/lisp/erc/erc-button.el b/lisp/erc/erc-button.el
new file mode 100644 (file)
index 0000000..6c6998a
--- /dev/null
@@ -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.
+
+\f
+;;; 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
diff --git a/lisp/erc/erc-compat.el b/lisp/erc/erc-compat.el
new file mode 100644 (file)
index 0000000..2a06fa9
--- /dev/null
@@ -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
diff --git a/lisp/erc/erc-complete.el b/lisp/erc/erc-complete.el
new file mode 100644 (file)
index 0000000..3b124f5
--- /dev/null
@@ -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
diff --git a/lisp/erc/erc-dcc.el b/lisp/erc/erc-dcc.el
new file mode 100644 (file)
index 0000000..d5789a5
--- /dev/null
@@ -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
diff --git a/lisp/erc/erc-ezbounce.el b/lisp/erc/erc-ezbounce.el
new file mode 100644 (file)
index 0000000..59e80b6
--- /dev/null
@@ -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
diff --git a/lisp/erc/erc-fill.el b/lisp/erc/erc-fill.el
new file mode 100644 (file)
index 0000000..f945d83
--- /dev/null
@@ -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
diff --git a/lisp/erc/erc-goodies.el b/lisp/erc/erc-goodies.el
new file mode 100644 (file)
index 0000000..dbbdaac
--- /dev/null
@@ -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
diff --git a/lisp/erc/erc-ibuffer.el b/lisp/erc/erc-ibuffer.el
new file mode 100644 (file)
index 0000000..63ec7bc
--- /dev/null
@@ -0,0 +1,184 @@
+;;; 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 '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)
+
+(ibuffer-define-limiter erc-server
+  (:documentation
+   "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)))))
+
+(ibuffer-define-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))
+         " "))
+    " "))
+
+(ibuffer-define-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))
+    ""))
+
+(ibuffer-define-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)))
+
+(ibuffer-define-column erc-topic (:name "Topic")
+  (if (and (eq major-mode 'erc-mode)
+          erc-channel-topic)
+      (erc-controls-interpret erc-channel-topic)
+    ""))
+
+(ibuffer-define-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))
+    ""))
+
+(ibuffer-define-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"
+    " "))
+
+(ibuffer-define-column
+ erc-op (:name "O")
+  (if (and (eq major-mode 'erc-mode)
+          (erc-channel-user-op-p (erc-current-nick)))
+      "@"
+    " "))
+
+(ibuffer-define-column erc-voice (:name "V")
+  (if (and (eq major-mode 'erc-mode)
+          (erc-channel-user-voice-p (erc-current-nick)))
+      "+"
+    " "))
+
+(ibuffer-define-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
+      "")))
+
+(ibuffer-define-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
diff --git a/lisp/erc/erc-identd.el b/lisp/erc/erc-identd.el
new file mode 100644 (file)
index 0000000..5cb179c
--- /dev/null
@@ -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
diff --git a/lisp/erc/erc-imenu.el b/lisp/erc/erc-imenu.el
new file mode 100644 (file)
index 0000000..c64c9c0
--- /dev/null
@@ -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
diff --git a/lisp/erc/erc-lang.el b/lisp/erc/erc-lang.el
new file mode 100644 (file)
index 0000000..20c89a8
--- /dev/null
@@ -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
diff --git a/lisp/erc/erc-list.el b/lisp/erc/erc-list.el
new file mode 100644 (file)
index 0000000..785e4d1
--- /dev/null
@@ -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
diff --git a/lisp/erc/erc-log.el b/lisp/erc/erc-log.el
new file mode 100644 (file)
index 0000000..d4e6e5a
--- /dev/null
@@ -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
diff --git a/lisp/erc/erc-match.el b/lisp/erc/erc-match.el
new file mode 100644 (file)
index 0000000..a5e3bf8
--- /dev/null
@@ -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
diff --git a/lisp/erc/erc-menu.el b/lisp/erc/erc-menu.el
new file mode 100644 (file)
index 0000000..8e1f81a
--- /dev/null
@@ -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
diff --git a/lisp/erc/erc-nets.el b/lisp/erc/erc-nets.el
new file mode 100644 (file)
index 0000000..716a429
--- /dev/null
@@ -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
diff --git a/lisp/erc/erc-netsplit.el b/lisp/erc/erc-netsplit.el
new file mode 100644 (file)
index 0000000..70ec2f2
--- /dev/null
@@ -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
diff --git a/lisp/erc/erc-nicklist.el b/lisp/erc/erc-nicklist.el
new file mode 100644 (file)
index 0000000..5599565
--- /dev/null
@@ -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
diff --git a/lisp/erc/erc-nickserv.el b/lisp/erc/erc-nickserv.el
new file mode 100644 (file)
index 0000000..be5541d
--- /dev/null
@@ -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-\ 2IDENTIFY\ 2\\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-\1fpassword"
+     "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"
+     "\ 2/NickServ\\s-IDENTIFY\\s-\1fsenha\1f\ 2"
+     "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"
+      "\ 2/ns\\s-IDENTIFY\\s-password\ 2"
+      "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
diff --git a/lisp/erc/erc-notify.el b/lisp/erc/erc-notify.el
new file mode 100644 (file)
index 0000000..9fc7f57
--- /dev/null
@@ -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
diff --git a/lisp/erc/erc-page.el b/lisp/erc/erc-page.el
new file mode 100644 (file)
index 0000000..d8e6770
--- /dev/null
@@ -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
diff --git a/lisp/erc/erc-pcomplete.el b/lisp/erc/erc-pcomplete.el
new file mode 100644 (file)
index 0000000..1107043
--- /dev/null
@@ -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
diff --git a/lisp/erc/erc-replace.el b/lisp/erc/erc-replace.el
new file mode 100644 (file)
index 0000000..07e8cd1
--- /dev/null
@@ -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
diff --git a/lisp/erc/erc-ring.el b/lisp/erc/erc-ring.el
new file mode 100644 (file)
index 0000000..cabb8e2
--- /dev/null
@@ -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
diff --git a/lisp/erc/erc-sound.el b/lisp/erc/erc-sound.el
new file mode 100644 (file)
index 0000000..c5b0f81
--- /dev/null
@@ -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
diff --git a/lisp/erc/erc-speedbar.el b/lisp/erc/erc-speedbar.el
new file mode 100644 (file)
index 0000000..e6ca538
--- /dev/null
@@ -0,0 +1,369 @@
+;;; 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))
+
+;;; 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)
+    (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)))
+         (select-frame speedbar-attached-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
diff --git a/lisp/erc/erc-spelling.el b/lisp/erc/erc-spelling.el
new file mode 100644 (file)
index 0000000..dd9aad6
--- /dev/null
@@ -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
diff --git a/lisp/erc/erc-stamp.el b/lisp/erc/erc-stamp.el
new file mode 100644 (file)
index 0000000..767839e
--- /dev/null
@@ -0,0 +1,335 @@
+;;; 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)))
+
+(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 the current version of Emacs doesn't support this, use
+\(- POS FALLBACK) to determine how many spaces to insert."
+  (if (or (featurep 'xemacs)
+         (< emacs-major-version 22)
+         (not (eq window-system 'x)))
+      (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
diff --git a/lisp/erc/erc-track.el b/lisp/erc/erc-track.el
new file mode 100644 (file)
index 0000000..6d760d7
--- /dev/null
@@ -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
diff --git a/lisp/erc/erc-truncate.el b/lisp/erc/erc-truncate.el
new file mode 100644 (file)
index 0000000..49cd20d
--- /dev/null
@@ -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
diff --git a/lisp/erc/erc-viper.el b/lisp/erc/erc-viper.el
new file mode 100644 (file)
index 0000000..0d6ff04
--- /dev/null
@@ -0,0 +1,74 @@
+;;; erc-viper.el --- Viper compatibility hacks for ERC
+
+;; Copyright (C) 2005 Free Software Foundation, Inc.
+
+;; Author: Edward O'Connor <ted@oconnor.cx>
+;; Keywords: emulation
+
+;; 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:
+
+;; Viper is a VI emulation mode for Emacs. ERC and Viper don't quite get
+;; along by default; the code in this file fixes that. A simple
+;;   (require 'erc-viper)
+;; in your ~/.ercrc.el should be all it takes for you to use ERC and
+;; Viper together happily.
+
+;;; Code:
+
+(require 'viper)
+
+;; We need this for `erc-mode-hook' and `erc-buffer-list'. Perhaps it
+;; would be better to use an `eval-after-load', so that there could be
+;; some autodetection / loading of this file from within erc.el?
+(require 'erc)
+
+;; Fix RET in ERC buffers, by telling Viper to pass RET through to the
+;; normal keymap.
+
+(add-to-list 'viper-major-mode-modifier-list
+             '(erc-mode insert-state viper-comint-mode-modifier-map))
+(add-to-list 'viper-major-mode-modifier-list
+             '(erc-mode vi-state viper-comint-mode-modifier-map))
+
+(viper-apply-major-mode-modifiers)
+
+;; Ensure that ERC buffers come up in insert state.
+(add-to-list 'viper-insert-state-mode-list 'erc-mode)
+
+;; Fix various local variables in Viper.
+(add-hook 'erc-mode-hook 'viper-comint-mode-hook)
+
+;; Fix ERC buffers that already exist (buffers in which `erc-mode-hook'
+;; has already been run).
+(mapc (lambda (buf)
+        (with-current-buffer buf
+          (viper-comint-mode-hook)
+          ;; If there *is* a final newline in this buffer, delete it, as
+          ;; it interferes with ERC /-commands.
+          (let ((last (1- (point-max))))
+            (when (eq (char-after last) ?\n)
+              (goto-char last)
+              (delete-char 1)))))
+      (erc-buffer-list))
+
+(provide 'erc-viper)
+
+;; arch-tag: 659fa645-e9ad-428c-ad53-8304d9f900f6
+;;; erc-viper.el ends here
diff --git a/lisp/erc/erc-xdcc.el b/lisp/erc/erc-xdcc.el
new file mode 100644 (file)
index 0000000..7c8ee6f
--- /dev/null
@@ -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
diff --git a/lisp/erc/erc.el b/lisp/erc/erc.el
new file mode 100644 (file)
index 0000000..9ff3ff5
--- /dev/null
@@ -0,0 +1,6144 @@
+;; 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 'ssl)
+    (let ((proc (open-ssl-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.
+      (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
index 810fe60..209493e 100644 (file)
@@ -1,3 +1,11 @@
+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
index bf1553a..78e282b 100644 (file)
@@ -42,7 +42,7 @@ INFO_TARGETS = ../info/emacs ../info/emacs-xtra ../info/ccmode ../info/cl \
                ../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/rcirc
+               ../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 @@ DVI_TARGETS =         emacs.dvi calc.dvi cc-mode.dvi cl.dvi dired-x.dvi \
                 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 rcirc.dvi
+                 newsticker.dvi emacs-xtra.dvi rcirc.dvi erc.dvi
 INFOSOURCES = info.texi
 
 # The following rule does not work with all versions of `make'.
@@ -332,6 +332,11 @@ newsticker.dvi: newsticker.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.*
 
diff --git a/man/erc.texi b/man/erc.texi
new file mode 100644 (file)
index 0000000..d4053e5
--- /dev/null
@@ -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
index b34a4d4..95b79a8 100644 (file)
@@ -1146,7 +1146,7 @@ operation on X.  Mouse wheel support is now enabled by default.
 
 @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
index ba5435c..a6d77de 100644 (file)
@@ -42,7 +42,7 @@ INFO_TARGETS = $(infodir)/emacs $(infodir)/emacs-xtra $(infodir)/ccmode \
                $(infodir)/woman $(infodir)/eshell $(infodir)/org \
                $(infodir)/url $(infodir)/speedbar $(infodir)/tramp \
                $(infodir)/ses $(infodir)/smtpmail $(infodir)/flymake \
-               $(infodir)/newsticker $(infodir)/rcirc
+               $(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 @@ DVI_TARGETS =         emacs.dvi calc.dvi cc-mode.dvi cl.dvi dired-x.dvi \
                 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 rcirc.dvi
+                 newsticker.dvi emacs-xtra.dvi rcirc.dvi erc.dvi
 INFOSOURCES = info.texi
 
 # The following rule does not work with all versions of `make'.
@@ -336,6 +336,11 @@ $(infodir)/rcirc: 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.*