(current-fill-column): If fill-column is nil, return nil.
[bpt/emacs.git] / lisp / gnus.el
index e06288d..f9e1f73 100644 (file)
@@ -1,8 +1,7 @@
-;;; GNUS: an NNTP-based News Reader for GNU Emacs
-;; Copyright (C) 1987, 1988, 1989, 1990, 1993 Free Software Foundation, Inc.
+;;; gnus.el --- NNTP-based News Reader for GNU Emacs
+;; Copyright (C) 1987,88,89,90,93,94,95 Free Software Foundation, Inc.
 
 ;; Author: Masanobu UMEDA <umerin@mse.kyutech.ac.jp>
-;; Version: $Header: /home/fsf/rms/e19/lisp/RCS/gnus.el,v 1.29 1993/11/16 10:47:27 rms Exp rms $
 ;; Keywords: news
 
 ;; This file is part of GNU Emacs.
@@ -52,8 +51,7 @@
 ;;     (setq gnus-nntp-service 119)
 ;;
 ;;     Or, if you'd like to use a local news spool directly in stead
-;;     of NNTP, install nnspool.el and set the variable to nil as
-;;     follows:
+;;     of NNTP, set the variable to nil as follows:
 ;;
 ;;     (setq gnus-nntp-service nil)
 ;;
 
 ;;; Code:
 
-(provide 'gnus)
 (require 'nntp)
 (require 'mail-utils)
+(require 'timezone)
 
 (defvar gnus-default-nntp-server nil
   "*Specify default NNTP server.
-This variable should be defined in paths.el.")
+This variable should be defined in `site-init.el'.")
 
 (defvar gnus-nntp-server (or (getenv "NNTPSERVER") gnus-default-nntp-server)
   "*The name of the host running NNTP server.
-If it is a string such as `:DIRECTORY', the user's private DIRECTORY
-is used as a news spool.
-Initialized from the NNTPSERVER environment variable.")
+If it is a string starting with a colon, as in as `:DIRECTORY', then the
+directory ~/DIRECTORY is used as the news spool.
+This variable is initialized from the NNTPSERVER environment variable
+or from `gnus-default-nntp-server'.")
 
 (defvar gnus-nntp-service "nntp"
   "*NNTP service name (\"nntp\" or 119).
@@ -125,7 +124,7 @@ read in all newsgroups.")
 
 (defvar gnus-use-followup-to t
   "*Specifies what to do with Followup-To: field.
-If nil, ignore followup-to: field.  If t, use its value except for
+If nil, ignore `Followup-to:' field.  If t, use its value except for
 `poster'.  Otherwise, if not nil nor t, always use its value.")
 
 (defvar gnus-large-newsgroup 50
@@ -140,23 +139,27 @@ Initialized from the AUTHORCOPY environment variable.
 Articles are saved using a function specified by the the variable
 `gnus-author-copy-saver' (`rmail-output' is default) if a file name is
 given.  Instead, if the first character of the name is `|', the
-contents of the article is piped out to the named program. It is
+contents of the article is piped out to the named program.  It is
 possible to save an article in an MH folder as follows:
 
-(setq gnus-author-copy \"|/usr/local/lib/mh/rcvstore +Article\")")
+\(setq gnus-author-copy \"|/usr/local/lib/mh/rcvstore +Article\")")
 
 (defvar gnus-author-copy-saver (function rmail-output)
   "*A function called with a file name to save an author copy to.
-The default function is `rmail-output' which saves in Unix mailbox format.")
+The default function is `rmail-output' which saves in  inbox format.")
 
 (defvar gnus-use-long-file-name
   (not (memq system-type '(usg-unix-v xenix)))
   "*Non-nil means that a newsgroup name is used as a default file name
-to save articles to. If it's nil, the directory form of a newsgroup is
+to save articles to.  If it's nil, the directory form of a newsgroup is
 used instead.")
 
 (defvar gnus-article-save-directory (getenv "SAVEDIR")
-  "*A directory name to save articles to (default to ~/News).
+  "*A directory name to save articles to (default is `~/News').
+Initialized from the SAVEDIR environment variable.")
+
+(defvar gnus-kill-files-directory (getenv "SAVEDIR")
+  "*A directory name to save kill files to (default to ~/News).
 Initialized from the SAVEDIR environment variable.")
 
 (defvar gnus-default-article-saver (function gnus-summary-save-in-rmail)
@@ -205,7 +208,7 @@ or your confirmations may be required.")
 
 (defvar gnus-user-login-name nil
   "*The login name of the user.
-Got from the USER and LOGNAME environment variable if undefined.")
+Got from the function `user-login-name' if undefined.")
 
 (defvar gnus-user-full-name nil
   "*The full name of the user.
@@ -243,15 +246,17 @@ thus making them effectively invisible.")
 
 (defvar gnus-ignored-headers
   "^Path:\\|^Posting-Version:\\|^Article-I.D.:\\|^Expires:\\|^Date-Received:\\|^References:\\|^Control:\\|^Xref:\\|^Lines:\\|^Posted:\\|^Relay-Version:\\|^Message-ID:\\|^Nf-ID:\\|^Nf-From:\\|^Approved:\\|^Sender:"
-  "*All random fields within the header of a message.")
+  "*Header fields not worth displaying.
+Ordinarily GNUS excludes these when displaying an article.
+If you want to see them, ask to see the message with \"the full header\"
+\(also known as \"the original header\").")
 
 (defvar gnus-required-headers
   '(From Date Newsgroups Subject Message-ID Path Organization Distribution)
   "*All required fields for articles you post.
 RFC977 and RFC1036 require From, Date, Newsgroups, Subject, Message-ID
 and Path fields.  Organization, Distribution and Lines are optional.
-If you want GNUS not to insert some field, remove it from the
-variable.")
+If you want GNUS not to insert some field, remove it from this list.")
 
 (defvar gnus-show-all-headers nil
   "*Show all headers of an article if non-nil.")
@@ -261,7 +266,7 @@ variable.")
 
 (defvar gnus-optional-headers (function gnus-optional-lines-and-from)
   "*A function generating a optional string displayed in GNUS Summary
-mode buffer.  The function is called with an article HEADER. The
+mode buffer.  The function is called with an article HEADER.  The
 result must be a string excluding `[' and `]'.")
 
 (defvar gnus-auto-extend-newsgroup t
@@ -372,7 +377,7 @@ order.  The function `gnus-subscribe-interactively' asks for your decision.")
 
 (defvar gnus-startup-hook nil
   "*A hook called at start up time.
-This hook is called after GNUS is connected to the NNTP server. So, it
+This hook is called after GNUS is connected to the NNTP server.  So, it
 is possible to change the behavior of GNUS according to the selected
 NNTP server.")
 
@@ -393,8 +398,7 @@ If you want to run a special decoding program like nkf, use this hook.")
 If you want to sort Summary buffer by date and then by subject, you
 can use the following hook:
 
-\(setq gnus-select-group-hook
-      (list
+\(add-hook 'gnus-select-group-hook
        (function
        (lambda ()
          ;; First of all, sort by date.
@@ -412,14 +416,13 @@ can use the following hook:
              (if case-fold-search
                  (downcase (gnus-simplify-subject (gnus-header-subject a) t))
                (gnus-simplify-subject (gnus-header-subject a) t)))))
-         ))))
+         )))
 
 If you'd like to simplify subjects like the
 `gnus-summary-next-same-subject' command does, you can use the
 following hook:
 
-\(setq gnus-select-group-hook
-      (list
+\(add-hook 'gnus-select-group-hook
        (function
        (lambda ()
          (mapcar (function
@@ -428,13 +431,12 @@ following hook:
                      header
                      (gnus-simplify-subject
                       (gnus-header-subject header) 're-only))))
-                 gnus-newsgroup-headers)))))
+                 gnus-newsgroup-headers))))
 
-In some newsgroups author name is meaningless. It is possible to
+In some newsgroups author name is meaningless.  It is possible to
 prevent listing author names in GNUS Summary buffer as follows:
 
-\(setq gnus-select-group-hook
-      (list
+\(add-hook 'gnus-select-group-hook
        (function
        (lambda ()
          (cond ((string-equal \"comp.sources.unix\" gnus-newsgroup-name)
@@ -442,7 +444,7 @@ prevent listing author names in GNUS Summary buffer as follows:
                       (function gnus-optional-lines)))
                (t
                 (setq gnus-optional-headers
-                      (function gnus-optional-lines-and-from))))))))")
+                      (function gnus-optional-lines-and-from)))))))")
 
 (defvar gnus-select-article-hook
   '(gnus-summary-show-thread)
@@ -450,21 +452,20 @@ prevent listing author names in GNUS Summary buffer as follows:
 The default hook shows conversation thread subtrees of the selected
 article automatically using `gnus-summary-show-thread'.
 
-If you'd like to run RMAIL on a digest article automagically, you can
+If you'd like to run Rmail on a digest article automagically, you can
 use the following hook:
 
-\(setq gnus-select-article-hook
-      (list
+\(add-hook 'gnus-select-article-hook
        (function
        (lambda ()
-         (gnus-summary-show-thread)
          (cond ((string-equal \"comp.sys.sun\" gnus-newsgroup-name)
                 (gnus-summary-rmail-digest))
                ((and (string-equal \"comp.text\" gnus-newsgroup-name)
                      (string-match \"^TeXhax Digest\"
                                    (gnus-header-subject gnus-current-headers)))
                 (gnus-summary-rmail-digest)
-                ))))))")
+                ))))
+       t)")
 
 (defvar gnus-select-digest-hook
   (list
@@ -479,15 +480,14 @@ use the following hook:
 This hook can be used to modify incomplete digest articles as follows
 \(this is the default):
 
-\(setq gnus-select-digest-hook
-      (list
+\(add-hook 'gnus-select-digest-hook
        (function
        (lambda ()
          ;; Reply-To: is required by `undigestify-rmail-message'.
          (or (mail-position-on-field \"Reply-to\" t)
              (progn
                (mail-position-on-field \"Reply-to\")
-               (insert (gnus-fetch-field \"From\"))))))))")
+               (insert (gnus-fetch-field \"From\")))))))")
 
 (defvar gnus-rmail-digest-hook nil
   "*A hook called when reading digest messages using Rmail.
@@ -499,7 +499,7 @@ This hook is intended to apply a KILL file to the selected newsgroup.
 The function `gnus-apply-kill-file' is called by default.
 
 Since a general KILL file is too heavy to use only for a few
-newsgroups, I recommend you to use a lighter hook function. For
+newsgroups, I recommend you to use a lighter hook function.  For
 example, if you'd like to apply a KILL file to articles which contains
 a string `rmgroup' in subject in newsgroup `control', you can use the
 following hook:
@@ -545,7 +545,7 @@ to a file).")
 (defvar gnus-exit-group-hook nil
   "*A hook called when exiting (not quitting) Summary mode.
 If your machine is so slow that exiting from Summary mode takes very
-long time, set the variable `gnus-use-cross-reference' to nil. This
+long time, set the variable `gnus-use-cross-reference' to nil.  This
 inhibits marking articles as read using cross-reference information.")
 
 (defvar gnus-suspend-gnus-hook nil
@@ -559,7 +559,7 @@ inhibits marking articles as read using cross-reference information.")
 This hook is called before saving the `.newsrc' file.")
 
 \f
-;; Site dependent variables. You have to define these variables in
+;; Site dependent variables.  You have to define these variables in
 ;;  site-init.el, default.el or your .emacs.
 
 (defvar gnus-local-timezone nil
@@ -589,11 +589,30 @@ file is available, its content is also used.")
 
 (defvar gnus-use-generic-from nil
   "*If nil, prepend local host name to the defined domain in the From:
-field; if stringp, use this; if non-nil, strip of the local host name.")
+field; if a string, use this; if non-nil, strip off the local host name.")
 
 (defvar gnus-use-generic-path nil
   "*If nil, use the NNTP server name in the Path: field; if stringp,
 use this; if non-nil, use no host name (user name only)")
+
+(defvar gnus-newsgroups-regex "^\\([^ \t\n]+\\)[ \t]+\\(.*\\)$"
+  "Regex to retrieve the group name and the group description from
+the output of the newsgroups listing.
+
+If you have ^M at the end of lines try \"^\\([^ \t\n]+\\)[ \t]+\\([^\r]+\\)[\r]*$\"")
+
+(defvar gnus-newsgroups-display t
+  "*display the newsgroup description in *Newsgroup* buffer if not nil")
+
+(defvar gnus-newsgroups-alist nil
+  "alist (groupname . description)")
+
+(defvar gnus-newsgroups-hashtb nil
+  "hashtable of gnus-newsgroups-alist")
+
+(defvar gnus-newsgroups-showall nil
+  "non nil if we display all the groups")
+
 \f
 ;; Internal variables.
 
@@ -681,7 +700,7 @@ It is a list of `(original overload &optional file)'.")
 (defvar gnus-distribution-list nil)
 
 (defvar gnus-newsrc-options nil
-  "Options line in the .newsrc file.")
+  "Options line in the `.newsrc' file.")
 
 (defvar gnus-newsrc-options-n-yes nil
   "Regexp representing subscribed newsgroups.")
@@ -691,24 +710,24 @@ It is a list of `(original overload &optional file)'.")
 
 (defvar gnus-newsrc-assoc nil
   "Assoc list of read articles.
-gnus-newsrc-hashtb should be kept so that both hold the same information.")
+`gnus-newsrc-hashtb' should be kept so that both hold the same information.")
 
 (defvar gnus-newsrc-hashtb nil
-  "Hashtable of gnus-newsrc-assoc.")
+  "Hashtable of `gnus-newsrc-assoc'.")
 
 (defvar gnus-killed-assoc nil
-  "Assoc list of newsgroups removed from gnus-newsrc-assoc.
-gnus-killed-hashtb should be kept so that both hold the same information.")
+  "Assoc list of newsgroups removed from `gnus-newsrc-assoc'.
+`gnus-killed-hashtb' should be kept so that both hold the same information.")
 
 (defvar gnus-killed-hashtb nil
-  "Hashtable of gnus-killed-assoc.")
+  "Hashtable of `gnus-killed-assoc'.")
 
 (defvar gnus-marked-assoc nil
   "Assoc list of articles marked as unread.
-gnus-marked-hashtb should be kept so that both hold the same information.")
+`gnus-marked-hashtb' should be kept so that both hold the same information.")
 
 (defvar gnus-marked-hashtb nil
-  "Hashtable of gnus-marked-assoc.")
+  "Hashtable of `gnus-marked-assoc'.")
 
 (defvar gnus-unread-hashtb nil
   "Hashtable of unread articles.")
@@ -749,9 +768,8 @@ gnus-marked-hashtb should be kept so that both hold the same information.")
 
 (defvar gnus-newsgroup-headers nil
   "List of article headers in the current newsgroup.
-If the variable is modified (added or deleted), the function
-gnus-clear-hashtables-for-newsgroup-headers must be called to clear
-the hash tables.")
+If you modify the variable, you must call the function
+`gnus-clear-hashtables-for-newsgroup-headers' to clear the hash tables.")
 (defvar gnus-newsgroup-headers-hashtb-by-id nil)
 (defvar gnus-newsgroup-headers-hashtb-by-number nil)
 
@@ -770,8 +788,8 @@ the hash tables.")
 (defvar gnus-article-mode-map nil)
 (defvar gnus-kill-file-mode-map nil)
 
-(defvar rmail-last-file (expand-file-name "~/XMBOX"))
-(defvar rmail-last-rmail-file (expand-file-name "~/XNEWS"))
+(defvar rmail-default-file (expand-file-name "~/XMBOX"))
+(defvar rmail-default-rmail-file (expand-file-name "~/XNEWS"))
 
 ;; Define GNUS Subsystems.
 (autoload 'gnus-group-post-news "gnuspost"
@@ -808,10 +826,7 @@ the hash tables.")
          "Rewrite Date field in GMT to local in current buffer.")
 
 (autoload 'metamail-buffer "metamail"
-         "Process current buffer through 'metamail'." t)
-
-(autoload 'timezone-make-sortable-date "timezone")
-(autoload 'timezone-parse-date "timezone")
+         "Process current buffer through `metamail'." t)
 
 (autoload 'rmail-output "rmailout"
          "Append this message to Unix mail file named FILE-NAME." t)
@@ -823,6 +838,8 @@ the hash tables.")
 (put 'gnus-summary-mode 'mode-class 'special)
 (put 'gnus-article-mode 'mode-class 'special)
 
+(autoload 'gnus-uu-ctl-map "gnus-uu" nil nil 'keymap)
+(autoload 'gnus-uu-mark-article "gnus-uu" nil t)
 \f
 ;;(put 'gnus-eval-in-buffer-window 'lisp-indent-hook 1)
 
@@ -847,13 +864,13 @@ Optional argument HASHSIZE specifies the table size."
   (` (symbol-value (intern-soft (, string) (, hashtable)))))
 
 (defmacro gnus-sethash (string value hashtable)
-  "Set hash value. Arguments are STRING, VALUE, and HASHTABLE."
+  "Set hash value.  Arguments are STRING, VALUE, and HASHTABLE."
   ;; We cannot use define-abbrev since it only accepts string as value.
   (` (set (intern (, string) (, hashtable)) (, value))))
 
-;; Note: Macros defined here are also defined in nntp.el. I don't like
+;; Note: Macros defined here are also defined in nntp.el.  I don't like
 ;; to put them here, but many users got troubled with the old
-;; definitions in nntp.elc. These codes are NNTP 3.10 version.
+;; definitions in nntp.elc.  These codes are NNTP 3.10 version.
 
 (defmacro nntp-header-number (header)
   "Return article number in HEADER."
@@ -938,6 +955,8 @@ Optional argument HASHSIZE specifies the table size."
   (define-key gnus-group-mode-map "P" 'gnus-group-prev-group)
   (define-key gnus-group-mode-map "\C-n" 'gnus-group-next-group)
   (define-key gnus-group-mode-map "\C-p" 'gnus-group-prev-group)
+  (define-key gnus-group-mode-map [down] 'gnus-group-next-group)
+  (define-key gnus-group-mode-map [up] 'gnus-group-prev-group)
   (define-key gnus-group-mode-map "\r" 'next-line)
   ;;(define-key gnus-group-mode-map "/" 'isearch-forward)
   (define-key gnus-group-mode-map "<" 'beginning-of-buffer)
@@ -967,7 +986,60 @@ Optional argument HASHSIZE specifies the table size."
   (define-key gnus-group-mode-map "q" 'gnus-group-exit)
   (define-key gnus-group-mode-map "Q" 'gnus-group-quit)
   (define-key gnus-group-mode-map "?" 'gnus-group-describe-briefly)
-  (define-key gnus-group-mode-map "\C-c\C-i" 'gnus-info-find-node))
+  (define-key gnus-group-mode-map "\C-c\C-i" 'gnus-info-find-node)
+  (define-key gnus-group-mode-map   [mouse-2] 'gnus-mouse-pick-group)
+  (define-key gnus-group-mode-map "t" 'gnus-newsgroups-display-toggle)
+
+  ;; Make a menu bar item.
+  (define-key gnus-group-mode-map [menu-bar GNUS]
+       (cons "GNUS" (make-sparse-keymap "GNUS")))
+
+  (define-key gnus-group-mode-map [menu-bar GNUS force-update]
+       '("Force Update" . gnus-group-force-update))
+  (define-key gnus-group-mode-map [menu-bar GNUS quit]
+       '("Quit" . gnus-group-quit))
+  (define-key gnus-group-mode-map [menu-bar GNUS exit]
+       '("Exit" . gnus-group-exit))
+  (define-key gnus-group-mode-map [menu-bar GNUS restart]
+       '("Restart" . gnus-group-restart))
+  (define-key gnus-group-mode-map [menu-bar GNUS suspend]
+       '("Suspend" . gnus-group-suspend))
+  (define-key gnus-group-mode-map [menu-bar GNUS get-new-news]
+       '("Get New News" . gnus-group-get-new-news))
+
+  ;; Make a menu bar item.
+  (define-key gnus-group-mode-map [menu-bar groups]
+       (cons "Groups" (make-sparse-keymap "Groups")))
+
+  (define-key gnus-group-mode-map [menu-bar groups catchup]
+       '("Catchup" . gnus-group-catchup))
+  (define-key gnus-group-mode-map [menu-bar groups edit-global-kill]
+       '("Edit Kill File" . gnus-group-edit-global-kill))
+
+  (define-key gnus-group-mode-map [menu-bar groups separator-2]
+       '("--"))
+
+  (define-key gnus-group-mode-map [menu-bar groups yank-group]
+       '("Yank Group" . gnus-group-yank-group))
+  (define-key gnus-group-mode-map [menu-bar groups kill-group]
+       '("Kill Group" . gnus-group-kill-group))
+
+  (define-key gnus-group-mode-map [menu-bar groups separator-1]
+       '("--"))
+
+  (define-key gnus-group-mode-map [menu-bar groups newsgroups-update-description]
+        '("Update descriptions" . gnus-newsgroups-update-description))
+  (define-key gnus-group-mode-map [menu-bar groups newsgroups-display-toggle]
+        '("Toggle descriptions" . gnus-newsgroups-display-toggle))
+  (define-key gnus-group-mode-map [menu-bar groups jump-to-group]
+       '("Jump to Group..." . gnus-group-jump-to-group))
+  (define-key gnus-group-mode-map [menu-bar groups list-all-groups]
+       '("List All Groups" . gnus-group-list-all-groups))
+  (define-key gnus-group-mode-map [menu-bar groups list-groups]
+       '("List Groups" . gnus-group-list-groups))
+  (define-key gnus-group-mode-map [menu-bar groups unsub-current-group]
+       '("Unsubscribe Group" . gnus-group-unsubscribe-current-group))
+  )
 
 (defun gnus-group-mode ()
   "Major mode for reading network news.
@@ -1009,17 +1081,18 @@ V       Show the version number of this GNUS.
 ?      Describe Group Mode commands briefly.
 C-h m  Describe Group Mode.
 C-c C-i        Read Info about Group Mode.
+t       Toggle displaying newsgroup descriptions.
 
   The name of the host running NNTP server is asked for if no default
-host is specified. It is also possible to choose another NNTP server
+host is specified.  It is also possible to choose another NNTP server
 even when the default server is defined by giving a prefix argument to
 the command `\\[gnus]'.
 
-  If an NNTP server is preceded by a colon such as `:Mail', the user's
-private directory `~/Mail' is used as a news spool. This makes it
+  If the NNTP server name starts with a colon, as in `:Mail', the user's
+own directory `~/Mail' is used as a news spool.  This makes it
 possible to read mail stored in MH folders or articles saved by GNUS.
 File names of mail or articles must consist of only numeric
-characters. Otherwise, they are ignored.
+characters.  Otherwise, they are ignored.
 
   If there is a file named `~/.newsrc-SERVER', it is used as the
 startup file instead of standard one when talking to SERVER.  It is
@@ -1027,7 +1100,7 @@ possible to talk to many hosts by using different startup files for
 each.
 
   Option `-n' of the options line in the startup file is recognized
-properly the same as the Bnews system. For example, if the options
+properly the same as the Bnews system.  For example, if the options
 line is `options -n !talk talk.rumors', newsgroups under the `talk'
 hierarchy except for `talk.rumors' are ignored while checking new
 newsgroups.
@@ -1046,7 +1119,7 @@ nntp.el, nnspool.el, and mhspoo.el, respectively.
 
 User customizable variables:
  gnus-nntp-server
-    Specifies the name of the host running the NNTP server. If its
+    Specifies the name of the host running the NNTP server.  If its
     value is a string such as `:DIRECTORY', the user's private
     DIRECTORY is used as a news spool.  The variable is initialized
     from the NNTPSERVER environment variable.
@@ -1127,12 +1200,12 @@ User customizable variables:
 Various hooks for customization:
  gnus-group-mode-hook
     Entry to this mode calls the value with no arguments, if that
-    value is non-nil. This hook is called before GNUS is connected to
-    the NNTP server. So, you can change or define the NNTP server in
+    value is non-nil.  This hook is called before GNUS is connected to
+    the NNTP server.  So, you can change or define the NNTP server in
     this hook.
 
  gnus-startup-hook
-    Called with no arguments after the NNTP server is selected. It is
+    Called with no arguments after the NNTP server is selected.  It is
     possible to change the behavior of GNUS or initialize the
     variables according to the selected NNTP server.
 
@@ -1180,8 +1253,14 @@ Various hooks for customization:
   (use-local-map gnus-group-mode-map)
   (buffer-flush-undo (current-buffer))
   (setq buffer-read-only t)            ;Disable modification
+  (setq truncate-lines t)              ;In case descriptions are too long.
   (run-hooks 'gnus-group-mode-hook))
 
+(defun gnus-mouse-pick-group (e)
+  (interactive "e")
+  (mouse-set-point e)
+  (gnus-group-read-group nil))
+
 ;;;###autoload
 (defun gnus (&optional confirm)
   "Read network news.
@@ -1218,7 +1297,7 @@ If optional argument CONFIRM is non-nil, ask NNTP server."
 
 
 If you have any trouble with this software, please let me
-know. I will fix your problems in the next release.
+know.  I will fix your problems in the next release.
 
 Comments, suggestions, and bug fixes are welcome.
 
@@ -1235,6 +1314,7 @@ umerin@mse.kyutech.ac.jp" gnus-version))
   "List newsgroups in the Newsgroup buffer.
 If argument SHOW-ALL is non-nil, unsubscribed groups are also listed."
   (interactive "P")
+  (setq gnus-newsgroups-showall show-all)
   (let ((case-fold-search nil)
        (last-group                     ;Current newsgroup.
         (gnus-group-group-name))
@@ -1272,21 +1352,27 @@ If optional argument ALL is non-nil, unsubscribed groups are also listed."
        (newsrc gnus-newsrc-assoc)
        (group-info nil)
        (group-name nil)
+       (group-description nil)
        (unread-count 0)
+       (nb-tab 0)
        ;; This specifies the format of Group buffer.
-       (cntl "%s%s%5d: %s\n"))
+       (cntl "%s%s%5d: %s"))
     (erase-buffer)
     ;; List newsgroups.
     (while newsrc
       (setq group-info (car newsrc))
       (setq group-name (car group-info))
+      (if gnus-newsgroups-display
+         (progn (setq group-description (gnus-gethash group-name gnus-newsgroups-hashtb))
+                (setq nb-tab (/ (- 38 (length group-name)) tab-width))))
       (setq unread-count (nth 1 (gnus-gethash group-name gnus-unread-hashtb)))
       (if (or all
              (and (nth 1 group-info)   ;Subscribed.
                   (> unread-count 0))) ;There are unread articles.
          ;; Yes, I can use gnus-group-prepare-line, but this is faster.
          (insert
-          (format cntl
+          (format (concat cntl (make-string (if (> nb-tab 0) nb-tab 1) ?\t)
+                          "%s\n")
                   ;; Subscribed or not.
                   (if (nth 1 group-info) " " "U")
                   ;; Has new news?
@@ -1300,7 +1386,10 @@ If optional argument ALL is non-nil, unsubscribed groups are also listed."
                   ;; Number of unread articles.
                   unread-count
                   ;; Newsgroup name.
-                  group-name))
+                  group-name
+                  ;; Newsgroup description
+                  (if group-description (cdr group-description) "")
+                  ))
        )
       (setq newsrc (cdr newsrc))
       )
@@ -1311,8 +1400,10 @@ If optional argument ALL is non-nil, unsubscribed groups are also listed."
 
 (defun gnus-group-prepare-line (info)
   "Return a string for the Newsgroup buffer from INFO.
-INFO is an element of gnus-newsrc-assoc or gnus-killed-assoc."
+INFO is an element of `gnus-newsrc-assoc' or `gnus-killed-assoc'."
   (let* ((group-name (car info))
+        (group-description nil)
+        (nb-tab 0)
         (unread-count
          (or (nth 1 (gnus-gethash group-name gnus-unread-hashtb))
              ;; Not in hash table, so compute it now.
@@ -1321,8 +1412,13 @@ INFO is an element of gnus-newsrc-assoc or gnus-killed-assoc."
                (nth 2 (gnus-gethash group-name gnus-active-hashtb))
                (nthcdr 2 info)))))
         ;; This specifies the format of Group buffer.
-        (cntl "%s%s%5d: %s\n"))
-    (format cntl
+        (cntl "%s%s%5d: %s"))
+    (if gnus-newsgroups-display
+       (progn
+         (setq group-description (gnus-gethash group-name gnus-newsgroups-hashtb))
+         (setq nb-tab (/ (- 38 (length group-name)) tab-width))))
+    (format (concat cntl (make-string (if (> nb-tab 0) nb-tab 1) ?\t)
+                   "%s\n")
            ;; Subscribed or not.
            (if (nth 1 info) " " "U")
            ;; Has new news?
@@ -1337,6 +1433,8 @@ INFO is an element of gnus-newsrc-assoc or gnus-killed-assoc."
            unread-count
            ;; Newsgroup name.
            group-name
+           ;; Newsgroup description
+           (if group-description (cdr group-description) "")
            )))
 
 (defun gnus-group-update-group (group &optional visible-only)
@@ -1364,7 +1462,7 @@ If optional argument VISIBLE-ONLY is non-nil, non displayed group is ignored."
                ((progn
                   (goto-char (point-max))
                   (re-search-backward regexp nil t))))
-         ;; GROUP is listed in current buffer. So, delete old line.
+         ;; GROUP is listed in current buffer.  So, delete old line.
          (progn
            (setq visible t)
            (beginning-of-line)
@@ -1384,9 +1482,10 @@ If optional argument VISIBLE-ONLY is non-nil, non displayed group is ignored."
   "Get newsgroup name around point."
   (save-excursion
     (beginning-of-line)
-    (if (looking-at "^.+:[ \t]+\\([^ \t\n]+\\)\\([ \t].*\\|$\\)")
-       (buffer-substring (match-beginning 1) (match-end 1))
-      )))
+    (if (looking-at "^..[0-9 \t]+:[ \t]+\\([^ \t\n]+\\)\\([ \t].*\\|$\\)")
+        (let ((group-name (buffer-substring (match-beginning 1) (match-end 1))))
+          (set-text-properties 0 (length group-name) nil group-name)
+          group-name))))
 
 (defun gnus-group-make-regexp (newsgroup)
   "Return regexp that matches for a line of NEWSGROUP."
@@ -1463,7 +1562,7 @@ If argument ALL is non-nil, already read articles become readable."
     ))
 
 (defun gnus-group-next-group (n)
-  "Go to next N'th newsgroup."
+  "Go to Nth following newsgroup."
   (interactive "p")
   (while (and (> n 1)
              (gnus-group-search-forward nil t))
@@ -1472,7 +1571,7 @@ If argument ALL is non-nil, already read articles become readable."
       (message "No more newsgroups")))
 
 (defun gnus-group-next-unread-group (n)
-  "Go to next N'th unread newsgroup."
+  "Go to Nth following unread newsgroup."
   (interactive "p")
   (while (and (> n 1)
              (gnus-group-search-forward nil nil))
@@ -1481,7 +1580,7 @@ If argument ALL is non-nil, already read articles become readable."
       (message "No more unread newsgroups")))
 
 (defun gnus-group-prev-group (n)
-  "Go to previous N'th newsgroup."
+  "Go to Nth previous newsgroup."
   (interactive "p")
   (while (and (> n 1)
              (gnus-group-search-forward t t))
@@ -1490,7 +1589,7 @@ If argument ALL is non-nil, already read articles become readable."
       (message "No more newsgroups")))
 
 (defun gnus-group-prev-unread-group (n)
-  "Go to previous N'th unread newsgroup."
+  "Go to Nth previous unread newsgroup."
   (interactive "p")
   (while (and (> n 1)
              (gnus-group-search-forward t nil))              
@@ -1529,12 +1628,16 @@ Cross references (Xref: field) of articles are ignored."
 (defun gnus-group-unsubscribe-current-group ()
   "Toggle subscribe from/to unsubscribe current group."
   (interactive)
-  (gnus-group-unsubscribe-group (gnus-group-group-name))
-  (gnus-group-next-group 1))
+  (let ((group (gnus-group-group-name)))
+    (if group
+        (progn
+          (gnus-group-unsubscribe-group group)
+          (gnus-group-next-group 1))
+      (message "No Newsgroup found to \(un\)subscribe"))))
 
 (defun gnus-group-unsubscribe-group (group)
   "Toggle subscribe from/to unsubscribe GROUP.
-New newsgroup is added to .newsrc automatically."
+\(If GROUP is new, it is added to `.newsrc' automatically.)"
   (interactive
    (list (completing-read "Newsgroup: "
                          gnus-active-hashtb nil 'require-match)))
@@ -1561,10 +1664,12 @@ New newsgroup is added to .newsrc automatically."
 (defun gnus-group-list-all-groups ()
   "List all of newsgroups in the Newsgroup buffer."
   (interactive)
-  (gnus-group-list-groups t))
+  (message "Listing all groups...")
+  (gnus-group-list-groups t)
+  (message "Listing all groups...done"))
 
 (defun gnus-group-get-new-news ()
-  "Get newly arrived articles. In fact, read the active file again."
+  "Get newly arrived articles.  In fact, read the active file again."
   (interactive)
   (gnus-setup-news)
   (gnus-group-list-groups gnus-have-all-newsgroups))
@@ -1616,29 +1721,31 @@ Type \\[widen] to remove restriction."
     "Editing a local KILL file (Type \\[gnus-kill-file-exit] to exit)")))
 
 (defun gnus-group-force-update ()
-  "Update .newsrc file."
+  "Update `.newsrc' file."
   (interactive)
   (gnus-save-newsrc-file))
 
 (defun gnus-group-suspend ()
   "Suspend the current GNUS session.
 In fact, cleanup buffers except for Group Mode buffer.
-The hook gnus-suspend-gnus-hook is called before actually suspending."
+The hook `gnus-suspend-gnus-hook' is called before actually suspending."
   (interactive)
   (run-hooks 'gnus-suspend-gnus-hook)
   ;; Kill GNUS buffers except for Group Mode buffer.
-  (let ((buffers gnus-buffer-list))
+  (let ((buffers gnus-buffer-list)
+       (group-buf (get-buffer gnus-group-buffer)))
     (while buffers
       (and (not (eq (car buffers) gnus-group-buffer))
           (get-buffer (car buffers))
           (kill-buffer (car buffers)))
       (setq buffers (cdr buffers))
-      ))
-  (bury-buffer))
+      )
+    (bury-buffer group-buf)
+    (delete-windows-on group-buf t)))
 
 (defun gnus-group-exit ()
-  "Quit reading news after updating .newsrc.
-The hook gnus-exit-gnus-hook is called before actually quitting."
+  "Quit reading news after updating `.newsrc'.
+The hook `gnus-exit-gnus-hook' is called before actually quitting."
   (interactive)
   (if (or noninteractive               ;For gnus-batch-kill
          (zerop (buffer-size))         ;No news is good news.
@@ -1654,8 +1761,8 @@ The hook gnus-exit-gnus-hook is called before actually quitting."
     ))
 
 (defun gnus-group-quit ()
-  "Quit reading news without updating .newsrc.
-The hook gnus-exit-gnus-hook is called before actually quitting."
+  "Quit reading news without updating `.newsrc'.
+The hook `gnus-exit-gnus-hook' is called before actually quitting."
   (interactive)
   (if (or noninteractive               ;For gnus-batch-kill
          (zerop (buffer-size))
@@ -1692,6 +1799,8 @@ The hook gnus-exit-gnus-hook is called before actually quitting."
     nil
   (setq gnus-summary-mode-map (make-keymap))
   (suppress-keymap gnus-summary-mode-map)
+  (define-key gnus-summary-mode-map "\C-c\C-v" 'gnus-uu-ctl-map)
+  (define-key gnus-summary-mode-map "#" 'gnus-uu-mark-article)
   (define-key gnus-summary-mode-map " " 'gnus-summary-next-page)
   (define-key gnus-summary-mode-map "\177" 'gnus-summary-prev-page)
   (define-key gnus-summary-mode-map "\r" 'gnus-summary-scroll-up)
@@ -1707,6 +1816,8 @@ The hook gnus-exit-gnus-hook is called before actually quitting."
   (define-key gnus-summary-mode-map "\C-c\C-p" 'gnus-summary-prev-digest)
   (define-key gnus-summary-mode-map "\C-n" 'gnus-summary-next-subject)
   (define-key gnus-summary-mode-map "\C-p" 'gnus-summary-prev-subject)
+  (define-key gnus-summary-mode-map [down] 'gnus-summary-next-subject)
+  (define-key gnus-summary-mode-map [up] 'gnus-summary-prev-subject)
   (define-key gnus-summary-mode-map "\en" 'gnus-summary-next-unread-subject)
   (define-key gnus-summary-mode-map "\ep" 'gnus-summary-prev-unread-subject)
   ;;(define-key gnus-summary-mode-map "\C-cn" 'gnus-summary-next-group)
@@ -1784,7 +1895,128 @@ The hook gnus-exit-gnus-hook is called before actually quitting."
   (define-key gnus-summary-mode-map "q" 'gnus-summary-exit)
   (define-key gnus-summary-mode-map "Q" 'gnus-summary-quit)
   (define-key gnus-summary-mode-map "?" 'gnus-summary-describe-briefly)
-  (define-key gnus-summary-mode-map "\C-c\C-i" 'gnus-info-find-node))
+  (define-key gnus-summary-mode-map "\C-c\C-i" 'gnus-info-find-node)
+  (define-key gnus-summary-mode-map [mouse-2] 'gnus-mouse-pick-article)
+
+  (define-key gnus-summary-mode-map [menu-bar misc]
+       (cons "Misc" (make-sparse-keymap "misc")))
+
+  (define-key gnus-summary-mode-map [menu-bar misc caesar-message]
+       '("Caesar Message" . gnus-summary-caesar-message))
+  (define-key gnus-summary-mode-map [menu-bar misc cancel-article]
+       '("Cancel Article" . gnus-summary-cancel-article))
+  (define-key gnus-summary-mode-map [menu-bar misc edit-local-kill]
+       '("Edit Kill File" . gnus-summary-edit-local-kill))
+
+  (define-key gnus-summary-mode-map [menu-bar misc mark-as-unread]
+       '("Mark as Unread" . gnus-summary-mark-as-unread-forward))
+  (define-key gnus-summary-mode-map [menu-bar misc mark-as-read]
+       '("Mark as Read" . gnus-summary-mark-as-read))
+
+  (define-key gnus-summary-mode-map [menu-bar misc quit]
+       '("Quit Group" . gnus-summary-quit))
+  (define-key gnus-summary-mode-map [menu-bar misc exit]
+       '("Exit Group" . gnus-summary-exit))
+
+  (define-key gnus-summary-mode-map [menu-bar sort]
+       (cons "Sort" (make-sparse-keymap "sort")))
+
+  (define-key gnus-summary-mode-map [menu-bar sort sort-by-author]
+       '("Sort by Author" . gnus-summary-sort-by-author))
+  (define-key gnus-summary-mode-map [menu-bar sort sort-by-date]
+       '("Sort by Date" . gnus-summary-sort-by-date))
+  (define-key gnus-summary-mode-map [menu-bar sort sort-by-number]
+       '("Sort by Number" . gnus-summary-sort-by-number))
+  (define-key gnus-summary-mode-map [menu-bar sort sort-by-subject]
+       '("Sort by Subject" . gnus-summary-sort-by-subject))
+
+  (define-key gnus-summary-mode-map [menu-bar show/hide]
+       (cons "Show/Hide" (make-sparse-keymap "show/hide")))
+
+  (define-key gnus-summary-mode-map [menu-bar show/hide hide-all-threads]
+       '("Hide All Threads" . gnus-summary-hide-all-threads))
+  (define-key gnus-summary-mode-map [menu-bar show/hide hide-thread]
+       '("Hide Thread" . gnus-summary-hide-thread))
+  (define-key gnus-summary-mode-map [menu-bar show/hide show-all-threads]
+       '("Show All Threads" . gnus-summary-show-all-threads))
+  (define-key gnus-summary-mode-map [menu-bar show/hide show-all-headers]
+       '("Show All Headers" . gnus-summary-show-all-headers))
+  (define-key gnus-summary-mode-map [menu-bar show/hide show-thread]
+       '("Show Thread" . gnus-summary-show-thread))
+  (define-key gnus-summary-mode-map [menu-bar show/hide show-article]
+       '("Show Article" . gnus-summary-show-article))
+  (define-key gnus-summary-mode-map [menu-bar show/hide toggle-truncation]
+       '("Toggle Truncation" . gnus-summary-toggle-truncation))
+  (define-key gnus-summary-mode-map [menu-bar show/hide toggle-mime]
+       '("Toggle Mime" . gnus-summary-toggle-mime))
+  (define-key gnus-summary-mode-map [menu-bar show/hide toggle-header]
+       '("Toggle Header" . gnus-summary-toggle-header))
+
+  (define-key gnus-summary-mode-map [menu-bar action]
+       (cons "Action" (make-sparse-keymap "action")))
+
+  (define-key gnus-summary-mode-map [menu-bar action kill-same-subject]
+       '("Kill Same Subject" . gnus-summary-kill-same-subject))
+  (define-key gnus-summary-mode-map [menu-bar action kill-thread]
+       '("Kill Thread" . gnus-summary-kill-thread))
+  (define-key gnus-summary-mode-map [menu-bar action delete-marked-with]
+       '("Delete Marked With" . gnus-summary-delete-marked-with))
+  (define-key gnus-summary-mode-map [menu-bar action delete-marked-as-read]
+       '("Delete Marked As Read" . gnus-summary-delete-marked-as-read))
+  (define-key gnus-summary-mode-map [menu-bar action catchup-and-exit]
+       '("Catchup And Exit" . gnus-summary-catchup-and-exit))
+  (define-key gnus-summary-mode-map [menu-bar action catchup-to-here]
+       '("Catchup to Here" . gnus-summary-catchup-to-here))
+
+  (define-key gnus-summary-mode-map [menu-bar action ignore]
+    '("---"))
+
+  (define-key gnus-summary-mode-map [menu-bar action save-in-file]
+       '("Save in File" . gnus-summary-save-in-file))
+  (define-key gnus-summary-mode-map [menu-bar action save-article]
+       '("Save Article" . gnus-summary-save-article))
+
+  (define-key gnus-summary-mode-map [menu-bar action lambda]
+    '("---"))
+
+  (define-key gnus-summary-mode-map [menu-bar action forward]
+       '("Forward" . gnus-summary-mail-forward))
+  (define-key gnus-summary-mode-map [menu-bar action followup-with-original]
+       '("Followup with Original" . gnus-summary-followup-with-original))
+  (define-key gnus-summary-mode-map [menu-bar action followup]
+       '("Followup" . gnus-summary-followup))
+  (define-key gnus-summary-mode-map [menu-bar action reply-with-original]
+       '("Reply with Original" . gnus-summary-reply-with-original))
+  (define-key gnus-summary-mode-map [menu-bar action reply]
+       '("Reply" . gnus-summary-reply))
+  (define-key gnus-summary-mode-map [menu-bar action post]
+       '("Post News" . gnus-summary-post-news))
+
+  (define-key gnus-summary-mode-map [menu-bar move]
+       (cons "Move" (make-sparse-keymap "move")))
+
+  (define-key gnus-summary-mode-map [menu-bar move isearch-article]
+       '("Search in Article" . gnus-summary-isearch-article))
+  (define-key gnus-summary-mode-map [menu-bar move search-through-articles]
+       '("Search through Articles" . gnus-summary-search-article-forward))
+  (define-key gnus-summary-mode-map [menu-bar move down-thread]
+       '("Down Thread" . gnus-summary-down-thread))
+  (define-key gnus-summary-mode-map [menu-bar move prev-same-subject]
+       '("Prev Same Subject" . gnus-summary-prev-same-subject))
+  (define-key gnus-summary-mode-map [menu-bar move prev-group]
+       '("Prev Group" . gnus-summary-prev-group))
+  (define-key gnus-summary-mode-map [menu-bar move next-unread-same-subject]
+       '("Next Unread Same Subject" . gnus-summary-next-unread-same-subject))
+  (define-key gnus-summary-mode-map [menu-bar move next-unread-article]
+       '("Next Unread Article" . gnus-summary-next-unread-article))
+  (define-key gnus-summary-mode-map [menu-bar move next-thread]
+       '("Next Thread" . gnus-summary-next-thread))
+  (define-key gnus-summary-mode-map [menu-bar move next-group]
+       '("Next Group" . gnus-summary-next-group))
+  (define-key gnus-summary-mode-map [menu-bar move first-unread-article]
+       '("First Unread Article" . gnus-summary-first-unread-article))
+  )
+\f
 
 (defun gnus-summary-mode ()
   "Major mode for reading articles in this newsgroup.
@@ -1870,7 +2102,7 @@ C-c C-s C-a       Sort subjects by article author.
 C-c C-s C-s    Sort subjects alphabetically.
 C-c C-s C-d    Sort subjects by date.
 =      Expand Summary window to show headers full window.
-C-x C-s        Reselect the current newsgroup. Prefix argument means to select all.
+C-x C-s        Reselect the current newsgroup.  Prefix argument means to select all.
 w      Stop page breaking by linefeed.
 C-c C-r        Caesar rotates letters by 13/47 places.
 g      Force to show the current article.
@@ -1898,21 +2130,21 @@ C-c C-i Read Info about Summary mode.
 
 User customizable variables:
  gnus-large-newsgroup
-    The number of articles which indicates a large newsgroup. If the
+    The number of articles which indicates a large newsgroup.  If the
     number of articles in a newsgroup is greater than the value, the
-    number of articles to be selected is asked for. If the given value
-    N is positive, the last N articles is selected. If N is negative,
-    the first N articles are selected. An empty string means to select
+    number of articles to be selected is asked for.  If the given value
+    N is positive, the last N articles is selected.  If N is negative,
+    the first N articles are selected.  An empty string means to select
     all articles.
 
  gnus-use-long-file-name
     Non-nil means that a newsgroup name is used as a default file name
-    to save articles to. If it's nil, the directory form of a
+    to save articles to.  If it's nil, the directory form of a
     newsgroup is used instead.
 
  gnus-default-article-saver
     Specifies your favorite article saver which is interactively
-    funcallable. Following functions are available:
+    funcallable.  Following functions are available:
 
        gnus-summary-save-in-rmail (in Rmail format)
        gnus-summary-save-in-mail (in Unix mail format)
@@ -1926,15 +2158,20 @@ User customizable variables:
     Specifies a function generating a file name to save articles in
     specified format.  The function is called with NEWSGROUP, HEADERS,
     and optional LAST-FILE.  Access macros to the headers are defined
-    as nntp-header-FIELD, and functions are defined as
-    gnus-header-FIELD.
+    as `nntp-header-FIELD', and functions are defined as
+    `gnus-header-FIELD'.
 
  gnus-article-save-directory
     Specifies a directory name to save articles to using the commands
-    gnus-summary-save-in-rmail, gnus-summary-save-in-mail and
-    gnus-summary-save-in-file. The variable is initialized from the
+    `gnus-summary-save-in-rmail', `gnus-summary-save-in-mail' and
+    `gnus-summary-save-in-file'.  The variable is initialized from the
     SAVEDIR environment variable.
 
+ gnus-kill-files-directory
+    Specifies a directory name to save KILL files to using the commands
+    `gnus-edit-global-kill', and `gnus-edit-local-kill'.  The variable is
+    initialized from the SAVEDIR environment variable.
+
  gnus-show-all-headers
     Non-nil means that all headers of an article are shown.
 
@@ -1965,7 +2202,7 @@ User customizable variables:
 
  gnus-optional-headers
     Specifies a function which generates an optional string displayed
-    in the Summary buffer. The function is called with an article
+    in the Summary buffer.  The function is called with an article
     HEADERS.  The result must be a string excluding `[' and `]'.  The
     default function returns a string like NNN:AUTHOR, where NNN is
     the number of lines in an article and AUTHOR is the name of the
@@ -1977,16 +2214,16 @@ User customizable variables:
 
  gnus-auto-select-first
     Non-nil means the first unread article is selected automagically
-    when a newsgroup is selected normally (by gnus-group-read-group).
+    when a newsgroup is selected normally (by `gnus-group-read-group').
     If you'd like to prevent automatic selection of the first unread
     article in some newsgroups, set the variable to nil in
-    gnus-select-group-hook or gnus-apply-kill-hook.
+    `gnus-select-group-hook' or `gnus-apply-kill-hook'.
 
  gnus-auto-select-next
     Non-nil means the next newsgroup is selected automagically at the
-    end of the newsgroup. If the value is t and the next newsgroup is
+    end of the newsgroup.  If the value is t and the next newsgroup is
     empty (no unread articles), GNUS will exit Summary mode and go
-    back to Group mode. If the value is neither nil nor t, GNUS won't
+    back to Group mode.  If the value is neither nil nor t, GNUS won't
     exit Summary mode but select the following unread newsgroup.
     Especially, if the value is the symbol `quietly', the next unread
     newsgroup will be selected without any confirmations.
@@ -2008,9 +2245,6 @@ User customizable variables:
     Specifies a regexp describing line-beginnings that separate pages
     of news article.
 
- [gnus-more-message is obsolete.  overlay-arrow-string interfares
-    with other subsystems, such as dbx mode.]
-
  gnus-digest-show-summary
     Non-nil means that a summary of digest messages is shown when
     reading a digest article using `gnus-summary-rmail-digest'
@@ -2022,17 +2256,17 @@ User customizable variables:
  gnus-mail-reply-method
  gnus-mail-other-window-method
     Specifies a function to begin composing mail message using
-    commands gnus-summary-reply and gnus-summary-mail-other-window.
-    Functions gnus-mail-reply-using-mail and gnus-mail-reply-using-mhe
-    are available for the value of gnus-mail-reply-method.  And
-    functions gnus-mail-other-window-using-mail and
-    gnus-mail-other-window-using-mhe are available for the value of
-    gnus-mail-other-window-method.
+    commands `gnus-summary-reply' and `gnus-summary-mail-other-window'.
+    Functions `gnus-mail-reply-using-mail' and `gnus-mail-reply-using-mhe'
+    are available for the value of `gnus-mail-reply-method'.  And
+    functions `gnus-mail-other-window-using-mail' and
+    `gnus-mail-other-window-using-mhe' are available for the value of
+    `gnus-mail-other-window-method'.
 
  gnus-mail-send-method
     Specifies a function to mail a message too which is being posted
     as an article.  The message must have To: or Cc: field.  The value
-    of the variable send-mail-function is the default function which
+    of the variable `send-mail-function' is the default function, which
     uses sendmail mail program.
 
 Various hooks for customization:
@@ -2042,47 +2276,47 @@ Various hooks for customization:
 
  gnus-select-group-hook
     Called with no arguments when newsgroup is selected, if that value
-    is non-nil. It is possible to sort subjects in this hook. See the
+    is non-nil.  It is possible to sort subjects in this hook.  See the
     documentation of this variable for more information.
 
  gnus-summary-prepare-hook
     Called with no arguments after a summary list is created in the
-    Summary buffer, if that value is non-nil. If you'd like to modify
+    Summary buffer, if that value is non-nil.  If you'd like to modify
     the buffer, you can use this hook.
 
  gnus-select-article-hook
     Called with no arguments when an article is selected, if that
-    value is non-nil. See the documentation of this variable for more
+    value is non-nil.  See the documentation of this variable for more
     information.
 
  gnus-select-digest-hook
     Called with no arguments when reading digest messages using Rmail,
-    if that value is non-nil. This hook can be used to modify an
-    article so that Rmail can work with it. See the documentation of
+    if that value is non-nil.  This hook can be used to modify an
+    article so that Rmail can work with it.  See the documentation of
     the variable for more information.
 
  gnus-rmail-digest-hook
     Called with no arguments when reading digest messages using Rmail,
-    if that value is non-nil. This hook is intended to customize Rmail
+    if that value is non-nil.  This hook is intended to customize Rmail
     mode.
 
  gnus-apply-kill-hook
     Called with no arguments when a newsgroup is selected and the
-    Summary buffer is prepared. This hook is intended to apply a KILL
-    file to the selected newsgroup. The format of KILL file is
-    completely different from that of version 3.8. You have to rewrite
-    them in the new format. See the documentation of Kill file mode
+    Summary buffer is prepared.  This hook is intended to apply a KILL
+    file to the selected newsgroup.  The format of KILL file is
+    completely different from that of version 3.8.  You have to rewrite
+    them in the new format.  See the documentation of Kill file mode
     for more information.
 
  gnus-mark-article-hook
     Called with no arguments when an article is selected at the first
-    time. The hook is intended to mark an article as read (or unread)
+    time.  The hook is intended to mark an article as read (or unread)
     automatically when it is selected.  See the documentation of the
     variable for more information.
 
  gnus-exit-group-hook
     Called with no arguments when exiting the current newsgroup, if
-    that value is non-nil. If your machine is so slow that exiting
+    that value is non-nil.  If your machine is so slow that exiting
     from Summary mode takes very long time, inhibit marking articles
     as read using cross-references by setting the variable
     gnus-use-cross-reference to nil in this hook."
@@ -2114,6 +2348,11 @@ Various hooks for customization:
   ;;(setq case-fold-search t)
   (run-hooks 'gnus-summary-mode-hook))
 
+(defun gnus-mouse-pick-article (e)
+  (interactive "e")
+  (mouse-set-point e)
+  (gnus-summary-next-page nil))
+
 (defun gnus-summary-setup-buffer ()
   "Initialize Summary buffer."
   (if (get-buffer gnus-summary-buffer)
@@ -2295,7 +2534,7 @@ Optional PARENT-SUBJECT specifies the subject of the parent."
 
 (defun gnus-summary-set-mode-line ()
   "Set Summary mode line string.
-If you don't like it, define your own gnus-summary-set-mode-line."
+If you don't like it, define your own `gnus-summary-set-mode-line'."
   (let ((unmarked
         (- (length gnus-newsgroup-unreads)
            (length (gnus-intersection
@@ -2348,7 +2587,7 @@ the same subject will be searched for."
        (regexp 
         (format "^%s[ \t]+\\([0-9]+\\):.\\[[^]\r\n]*\\][ \t]+%s"
                 ;;(if unread " " ".")
-                (cond ((eq unread t) " ") (unread "[ ---]") (t "."))
+                (cond ((eq unread t) " ") (unread "[]") (t "."))
                 (if subject
                     (concat "\\([Rr][Ee]:[ \t]+\\)*"
                             (regexp-quote (gnus-simplify-subject subject))
@@ -2385,7 +2624,8 @@ the same subject will be searched for."
   (gnus-summary-search-subject t unread subject))
 
 (defun gnus-summary-article-number ()
-  "Article number around point. If nothing, return current number."
+  "Return the Article number around point.
+If none, return current article number."
   (save-excursion
     (beginning-of-line)
     (if (looking-at ".[ \t]+\\([0-9]+\\):")
@@ -2479,8 +2719,8 @@ If prefix argument NO-ARTICLE is non-nil, no article is selected initially."
              (get-buffer gnus-summary-buffer))
          (eq gnus-auto-select-next t)
          ;; Expected newsgroup has nothing to read since the articles
-         ;; are marked as read by cross-referencing. So, try next
-         ;; newsgroup. (Make sure we are in Group mode buffer now.)
+         ;; are marked as read by cross-referencing.  So, try next
+         ;; newsgroup.  (Make sure we are in Group mode buffer now.)
          (and (eq (current-buffer)
                   (get-buffer gnus-group-buffer))
               (gnus-group-group-name)
@@ -2512,8 +2752,8 @@ If prefix argument NO-ARTICLE is non-nil, no article is selected initially."
              (get-buffer gnus-summary-buffer))
          (eq gnus-auto-select-next t)
          ;; Expected newsgroup has nothing to read since the articles
-         ;; are marked as read by cross-referencing. So, try next
-         ;; newsgroup. (Make sure we are in Group mode buffer now.)
+         ;; are marked as read by cross-referencing.  So, try next
+         ;; newsgroup.  (Make sure we are in Group mode buffer now.)
          (and (eq (current-buffer)
                   (get-buffer gnus-group-buffer))
               (gnus-summary-search-group t)
@@ -2525,7 +2765,7 @@ If prefix argument NO-ARTICLE is non-nil, no article is selected initially."
 ;; Walking around summary lines.
 
 (defun gnus-summary-next-subject (n &optional unread)
-  "Go to next N'th summary line.
+  "Go to Nth following summary line.
 If optional argument UNREAD is non-nil, only unread article is selected."
   (interactive "p")
   (while (and (> n 1)
@@ -2540,12 +2780,12 @@ If optional argument UNREAD is non-nil, only unread article is selected."
        ))
 
 (defun gnus-summary-next-unread-subject (n)
-  "Go to next N'th unread summary line."
+  "Go to Nth following unread summary line."
   (interactive "p")
   (gnus-summary-next-subject n t))
 
 (defun gnus-summary-prev-subject (n &optional unread)
-  "Go to previous N'th summary line.
+  "Go to Nth previous summary line.
 If optional argument UNREAD is non-nil, only unread article is selected."
   (interactive "p")
   (while (and (> n 1)
@@ -2560,7 +2800,7 @@ If optional argument UNREAD is non-nil, only unread article is selected."
        ))
 
 (defun gnus-summary-prev-unread-subject (n)
-  "Go to previous N'th unread summary line."
+  "Go to Nth previous unread summary line."
   (interactive "p")
   (gnus-summary-prev-subject n t))
 
@@ -2682,7 +2922,7 @@ If argument UNREAD is non-nil, only unread article is selected."
           (gnus-summary-goto-article gnus-newsgroup-end))
          (t
           ;; Select next newsgroup automatically if requested.
-          (let ((cmd (string-to-char (this-command-keys)))
+          (let ((cmd (aref (this-command-keys) 0))
                 (group (gnus-summary-search-group))
                 (auto-select
                  (and gnus-auto-select-next
@@ -2700,20 +2940,22 @@ If argument UNREAD is non-nil, only unread article is selected."
                       ;; Ignore characters typed ahead.
                       (not (input-pending-p))
                       )))
+            ;; Keep just the event type of CMD.
+            (if (listp cmd)
+                (setq cmd (car cmd)))
             (message "No more%s articles%s"
                      (if unread " unread" "")
                      (if (and auto-select
                               (not (eq gnus-auto-select-next 'quietly)))
                          (if group
                              (format " (Type %s for %s [%d])"
-                                     (key-description (char-to-string cmd))
+                                     (single-key-description cmd)
                                      group
                                      (nth 1 (gnus-gethash group
                                                           gnus-unread-hashtb)))
                            (format " (Type %s to exit %s)"
-                                   (key-description (char-to-string cmd))
-                                   gnus-newsgroup-name
-                                   ))
+                                   (single-key-description cmd)
+                                   gnus-newsgroup-name))
                        ""))
             ;; Select next unread newsgroup automagically.
             (cond ((and auto-select
@@ -2722,10 +2964,14 @@ If argument UNREAD is non-nil, only unread article is selected."
                    (gnus-summary-next-group nil))
                   (auto-select
                    ;; Confirm auto selection.
-                   (let ((char (read-char)))
-                     (if (= char cmd)
+                   (let* ((event (read-event))
+                          (type
+                           (if (listp event)
+                               (car event)
+                             event)))
+                     (if (and (eq event type) (eq event cmd))
                          (gnus-summary-next-group nil)
-                       (setq unread-command-char char))))
+                       (setq unread-command-events (list event)))))
                   )
             ))
          )))
@@ -2773,7 +3019,7 @@ If argument UNREAD is non-nil, only unread article is selected."
          )))
 
 (defun gnus-summary-prev-unread-article ()
-  "Select unred article before current one."
+  "Select unread article before current one."
   (interactive)
   (gnus-summary-prev-article t (and gnus-auto-select-same
                                    (gnus-summary-subject-string))))
@@ -2851,7 +3097,7 @@ Argument LINES specifies lines to be scrolled up (or down if negative)."
   "Refer parent article of current article.
 If a prefix argument CHILD is non-nil, go back to the child article
 using internally maintained articles history.
-NOTE: This command may not work with nnspool.el."
+NOTE: This command may not work with `nnspool.el'."
   (interactive "P")
   (gnus-summary-select-article t t)    ;Request all headers.
   (let ((referenced-id nil))           ;Message-id of parent or child article.
@@ -2879,7 +3125,7 @@ NOTE: This command may not work with nnspool.el."
   "Refer article specified by MESSAGE-ID.
 If the MESSAGE-ID is nil or an empty string, Message-ID is poped from
 internally maintained articles history.
-NOTE: This command may not work with nnspool.el nor mhspool.el."
+NOTE: This command may not work with `nnspool.el' nor `mhspool.el'."
   (interactive "sMessage-ID: ")
   ;; Make sure that this command depends on the fact that article
   ;; related information is not updated when an article is retrieved
@@ -2914,24 +3160,23 @@ NOTE: This command may not work with nnspool.el nor mhspool.el."
     (error "No such references"))
   )
 
-(defun gnus-summary-next-digest (nth)
-  "Move to head of NTH next digested message."
+(defun gnus-summary-next-digest (n)
+  "Move to head of Nth next digested message."
   (interactive "p")
   (gnus-summary-select-article)
   (gnus-eval-in-buffer-window gnus-article-buffer
-    (gnus-article-next-digest (or nth 1))
+    (gnus-article-next-digest (or n 1))
     ))
 
-(defun gnus-summary-prev-digest (nth)
-  "Move to head of NTH previous digested message."
+(defun gnus-summary-prev-digest (n)
+  "Move to head of Nth previous digested message."
   (interactive "p")
   (gnus-summary-select-article)
   (gnus-eval-in-buffer-window gnus-article-buffer
-    (gnus-article-prev-digest (or nth 1))
-    ))
+    (gnus-article-prev-digest (or n 1))))
 
 (defun gnus-summary-first-unread-article ()
-  "Select first unread article. Return non-nil if successfully selected."
+  "Select first unread article.  Return non-nil if successfully selected."
   (interactive)
   (let ((begin (point)))
     (goto-char (point-min))
@@ -2954,7 +3199,8 @@ NOTE: This command may not work with nnspool.el nor mhspool.el."
 
 (defun gnus-summary-search-article-forward (regexp)
   "Search for an article containing REGEXP forward.
-gnus-select-article-hook is not called during the search."
+`gnus-select-article-hook' is not called for articles examined
+by searching search."
   (interactive
    (list (read-string
          (concat "Search forward (regexp): "
@@ -2973,7 +3219,8 @@ gnus-select-article-hook is not called during the search."
 
 (defun gnus-summary-search-article-backward (regexp)
   "Search for an article containing REGEXP backward.
-gnus-select-article-hook is not called during the search."
+`gnus-select-article-hook' is not called for articles examined
+by searching search."
   (interactive
    (list (read-string
          (concat "Search backward (regexp): "
@@ -2993,7 +3240,8 @@ gnus-select-article-hook is not called during the search."
 (defun gnus-summary-search-article (regexp &optional backward)
   "Search for an article containing REGEXP.
 Optional argument BACKWARD means do search for backward.
-gnus-select-article-hook is not called during the search."
+`gnus-select-article-hook' is not called for articles examined
+by searching search."
   (let ((gnus-select-article-hook nil) ;Disable hook.
        (gnus-mark-article-hook nil)    ;Inhibit marking as read.
        (re-search
@@ -3058,10 +3306,10 @@ If optional (prefix) argument BACKWARD is non-nil, do backward instead."
                    (` (lambda ()
                         (call-interactively '(, (key-binding command)))))
                    backward)
-      (message "Executing %s... done" (key-description command)))))
+      (message "Executing %s...done" (key-description command)))))
 
 (defun gnus-summary-beginning-of-article ()
-  "Go to beginning of article body"
+  "Go to beginning of article body."
   (interactive)
   (gnus-summary-select-article)
   (gnus-eval-in-buffer-window gnus-article-buffer
@@ -3072,7 +3320,7 @@ If optional (prefix) argument BACKWARD is non-nil, do backward instead."
     ))
 
 (defun gnus-summary-end-of-article ()
-  "Go to end of article body"
+  "Go to end of article body."
   (interactive)
   (gnus-summary-select-article)
   (gnus-eval-in-buffer-window gnus-article-buffer
@@ -3083,8 +3331,8 @@ If optional (prefix) argument BACKWARD is non-nil, do backward instead."
     ))
 
 (defun gnus-summary-goto-article (article &optional all-headers)
-  "Read ARTICLE if exists.
-Optional argument ALL-HEADERS means all headers are shown."
+  "Read article number ARTICLE if it exists.
+Optional argument ALL-HEADERS means show the full header."
   (interactive
    (list
     (string-to-int
@@ -3140,7 +3388,7 @@ With arg, turn MIME processing on iff arg is positive."
   (gnus-summary-select-article (not gnus-have-all-headers) t))
 
 (defun gnus-summary-stop-page-breaking ()
-  "Stop page breaking by linefeed temporary (Widen article buffer)."
+  "Stop page breaking by linefeed temporary (widen article buffer)."
   (interactive)
   (gnus-summary-select-article)
   (gnus-eval-in-buffer-window gnus-article-buffer
@@ -3157,7 +3405,7 @@ If argument UNMARK is negative, mark articles as unread instead."
   (let ((count
         (gnus-summary-mark-same-subject
          (gnus-summary-subject-string) unmark)))
-    ;; Select next unread article. If auto-select-same mode, should
+    ;; Select next unread article.  If auto-select-same mode, should
     ;; select the first unread article.
     (gnus-summary-next-article t (and gnus-auto-select-same
                                      (gnus-summary-subject-string)))
@@ -3253,7 +3501,7 @@ Optional 2nd argument CLEAR-MARK remove any kinds of mark."
 
 (defun gnus-summary-mark-as-read-forward (count)
   "Mark current article as read, and then go forward.
-Argument COUNT specifies number of articles marked as read"
+Argument COUNT specifies number of articles marked as read."
   (interactive "p")
   (while (> count 0)
     (gnus-summary-mark-as-read)
@@ -3262,7 +3510,7 @@ Argument COUNT specifies number of articles marked as read"
 
 (defun gnus-summary-mark-as-read-backward (count)
   "Mark current article as read, and then go backward.
-Argument COUNT specifies number of articles marked as read"
+Argument COUNT specifies number of articles marked as read."
   (interactive "p")
   (while (> count 0)
     (gnus-summary-mark-as-read)
@@ -3293,7 +3541,7 @@ Any kind of string (length 1) except for a space and `-' is ok."
 
 (defun gnus-summary-clear-mark-forward (count)
   "Remove current article's mark, and go forward.
-Argument COUNT specifies number of articles unmarked"
+Argument COUNT specifies number of articles unmarked."
   (interactive "p")
   (while (> count 0)
     (gnus-summary-mark-as-unread nil t)
@@ -3302,7 +3550,7 @@ Argument COUNT specifies number of articles unmarked"
 
 (defun gnus-summary-clear-mark-backward (count)
   "Remove current article's mark, and go backward.
-Argument COUNT specifies number of articles unmarked"
+Argument COUNT specifies number of articles unmarked."
   (interactive "p")
   (while (> count 0)
     (gnus-summary-mark-as-unread nil t)
@@ -3310,13 +3558,13 @@ Argument COUNT specifies number of articles unmarked"
     (setq count (1- count))))
 
 (defun gnus-summary-delete-marked-as-read ()
-  "Delete lines which is marked as read."
+  "Delete summary lines for articles that are marked as read."
   (interactive)
   (if gnus-newsgroup-unreads
       (let ((buffer-read-only nil))
        (save-excursion
          (goto-char (point-min))
-         (delete-non-matching-lines "^[ ---]"))
+         (delete-non-matching-lines "^[]"))
        ;; Adjust point.
        (if (eobp)
            (gnus-summary-prev-subject 1)
@@ -3588,7 +3836,7 @@ Argument REVERSE means reverse order."
    ))
 
 (defun gnus-summary-sort-by-subject (reverse)
-  "Sort Summary buffer by subject alphabetically. `Re:'s are ignored.
+  "Sort Summary buffer by subject alphabetically.  `Re:'s are ignored.
 If case-fold-search is non-nil, case of letters is ignored.
 Argument REVERSE means reverse order."
   (interactive "P")
@@ -3668,11 +3916,11 @@ Caesar rotates Japanese letters by 47 places in any case."
 
 (defun gnus-summary-rmail-digest ()
   "Run RMAIL on current digest article.
-gnus-select-digest-hook will be called with no arguments, if that
-value is non-nil. It is possible to modify the article so that Rmail
+`gnus-select-digest-hook' will be called with no arguments, if that
+value is non-nil.  It is possible to modify the article so that Rmail
 can work with it.
-gnus-rmail-digest-hook will be called with no arguments, if that value
-is non-nil. The hook is intended to customize Rmail mode."
+`gnus-rmail-digest-hook' will be called with no arguments, if that value
+is non-nil.  The hook is intended to customize Rmail mode."
   (interactive)
   (gnus-summary-select-article)
   (require 'rmail)
@@ -3710,13 +3958,13 @@ is non-nil. The hook is intended to customize Rmail mode."
                         (message "(No changes need to be saved)")
                         'no-need-to-write-this-buffer))))
          ;; Default file name saving digest messages.
-         (setq rmail-last-rmail-file
+         (setq rmail-default-rmail-file
                (funcall gnus-rmail-save-name
                         gnus-newsgroup-name
                         gnus-current-headers
                         gnus-newsgroup-last-rmail
                         ))
-         (setq rmail-last-file
+         (setq rmail-default-file
                (funcall gnus-mail-save-name
                         gnus-newsgroup-name
                         gnus-current-headers
@@ -3927,6 +4175,7 @@ Optional argument FOLDER specifies folder name."
 If prefix argument ALL is non-nil, all articles are marked as read."
   (interactive "P")
   (if (or quietly
+         (not gnus-interactive-catchup) ;Without confirmation?
          (y-or-n-p
           (if all
               "Do you really want to mark everything as read? "
@@ -3943,6 +4192,16 @@ If prefix argument ALL is non-nil, all articles are marked as read."
          ))
     ))
 
+(defun gnus-summary-catchup-to-here ()
+  "Mark all articles before the current one in this newsgroup as read."
+  (interactive)
+  (beginning-of-line)
+  (let ((current (gnus-summary-article-number)))
+       (beginning-of-buffer)
+       (while (not (= (gnus-summary-article-number) current))
+         (gnus-summary-mark-as-read)
+         (gnus-summary-next-subject 1))))
+
 (defun gnus-summary-catchup-all (&optional quietly)
   "Mark all articles in this newsgroup as read."
   (interactive)
@@ -3953,6 +4212,7 @@ If prefix argument ALL is non-nil, all articles are marked as read."
 If prefix argument ALL is non-nil, all articles are marked as read."
   (interactive "P")
   (if (or quietly
+         (not gnus-interactive-catchup) ;Without confirmation?
          (y-or-n-p
           (if all
               "Do you really want to mark everything as read? "
@@ -3997,7 +4257,7 @@ If prefix argument ALL is non-nil, all articles are marked as read."
 
 (defun gnus-summary-exit (&optional temporary)
   "Exit reading current newsgroup, and then return to group selection mode.
-gnus-exit-group-hook is called with no arguments if that value is non-nil."
+`gnus-exit-group-hook' is called with no arguments if that value is non-nil."
   (interactive)
   (let ((updated nil)
        (gnus-newsgroup-headers gnus-newsgroup-headers)
@@ -4141,7 +4401,8 @@ Various hooks for customization:
 (defun gnus-article-prepare (article &optional all-headers)
   "Prepare ARTICLE in Article mode buffer.
 ARTICLE can be either a article number or Message-ID.
-If optional argument ALL-HEADERS is non-nil, all headers are inserted."
+If optional argument ALL-HEADERS is non-nil,
+include the article's whole original header."
   ;; Make sure a connection to NNTP server is alive.
   (if (not (gnus-server-opened))
       (progn
@@ -4259,7 +4520,7 @@ If optional argument ALL-HEADERS is non-nil, all headers are inserted."
 
 (defun gnus-article-set-mode-line ()
   "Set Article mode line string.
-If you don't like it, define your own gnus-article-set-mode-line."
+If you don't like it, define your own `gnus-article-set-mode-line'."
   (let ((maxlen 15)                    ;Maximum subject length
        (subject
         (if gnus-current-headers
@@ -4297,7 +4558,7 @@ If you don't like it, define your own gnus-article-set-mode-line."
 
 (defun gnus-article-next-page (lines)
   "Show next page of current article.
-If end of article, return non-nil. Otherwise return nil.
+If end of article, return non-nil.  Otherwise return nil.
 Argument LINES specifies lines to be scrolled up."
   (interactive "P")
   (move-to-window-line -1)
@@ -4368,18 +4629,18 @@ Set mark at end of digested message."
     (message "End of message")
     ))
 
-(defun gnus-article-prev-digest (nth)
-  "Move to head of NTH previous digested message."
+(defun gnus-article-prev-digest (n)
+  "Move to head of Nth previous digested message."
   ;; Stop page breaking in digest mode.
   (widen)
   (beginning-of-line)
-  ;; Skip NTH - 1 digest.
+  ;; Skip N - 1 digest.
   ;; Suggested by Khalid Sattar <admin@cs.exeter.ac.uk>.
   ;; Digest separator is customizable.
   ;; Suggested by Skip Montanaro <montanaro@sprite.crd.ge.com>.
-  (while (and (> nth 1)
+  (while (and (> n 1)
              (re-search-backward gnus-digest-separator nil 'move))
-    (setq nth (1- nth)))
+    (setq n (1- n)))
   (if (re-search-backward gnus-digest-separator nil t)
       (let ((begin (point)))
        ;; Search for end of this message.
@@ -4464,27 +4725,27 @@ In addition to Emacs-Lisp Mode, the following commands are available:
 \\[gnus-kill-file-exit]        Save file and exit editing KILL file.
 \\[gnus-info-find-node]        Read Info about KILL file.
 
-  A KILL file contains lisp expressions to be applied to a selected
-newsgroup. The purpose is to mark articles as read on the basis of
-some set of regexps. A global KILL file is applied to every newsgroup,
-and a local KILL file is applied to a specified newsgroup. Since a
+  A KILL file contains Lisp expressions to be applied to a selected
+newsgroup.  The purpose is to mark articles as read on the basis of
+some set of regexps.  A global KILL file is applied to every newsgroup,
+and a local KILL file is applied to a specified newsgroup.  Since a
 global KILL file is applied to every newsgroup, for better performance
 use a local one.
 
-  A KILL file can contain any kind of Emacs lisp expressions expected
-to be evaluated in the Summary buffer. Writing lisp programs for this
+  A KILL file can contain any kind of Emacs Lisp expressions expected
+to be evaluated in the Summary buffer.  Writing Lisp programs for this
 purpose is not so easy because the internal working of GNUS must be
-well-known. For this reason, GNUS provides a general function which
+well-known.  For this reason, GNUS provides a general function which
 does this easily for non-Lisp programmers.
 
   The `gnus-kill' function executes commands available in Summary Mode
-by their key sequences. `gnus-kill' should be called with FIELD,
-REGEXP and optional COMMAND and ALL. FIELD is a string representing
-the header field or an empty string. If FIELD is an empty string, the
-entire article body is searched for. REGEXP is a string which is
-compared with FIELD value. COMMAND is a string representing a valid
-key sequence in Summary Mode or Lisp expression. COMMAND is default to
-'(gnus-summary-mark-as-read nil \"X\"). Make sure that COMMAND is
+by their key sequences.  `gnus-kill' should be called with FIELD,
+REGEXP and optional COMMAND and ALL.  FIELD is a string representing
+the header field or an empty string.  If FIELD is an empty string, the
+entire article body is searched for.  REGEXP is a string which is
+compared with FIELD value.  COMMAND is a string representing a valid
+key sequence in Summary mode or Lisp expression.  COMMAND defaults to
+\(gnus-summary-mark-as-read nil \"X\").  Make sure that COMMAND is
 executed in the Summary buffer.  If the second optional argument ALL
 is non-nil, the COMMAND is applied to articles which are already
 marked as read or unread.  Articles which are marked are skipped over
@@ -4500,8 +4761,8 @@ the following expression:
 
        (gnus-kill \"Subject\" \"AI\" \"d\")
 
-In this example it is assumed that the command
-`gnus-summary-mark-as-read-forward' is assigned to `d' in Summary Mode.
+\(Here we assume the command `gnus-summary-mark-as-read-forward' is
+assigned to `d' in Summary Mode.)
 
   It is possible to delete unnecessary headers which are marked with
 `X' in a KILL file as follows:
@@ -4514,8 +4775,8 @@ with `D' are deleted in a KILL file, it is impossible to read articles
 which are marked as read in the previous GNUS sessions.  Marks other
 than `D' should be used for articles which should really be deleted.
 
-Entry to this mode calls emacs-lisp-mode-hook and
-gnus-kill-file-mode-hook with no arguments, if that value is non-nil."
+Entry to this mode calls `emacs-lisp-mode-hook' and
+`gnus-kill-file-mode-hook' with no arguments, if that value is non-nil."
   (interactive)
   (kill-all-local-variables)
   (use-local-map gnus-kill-file-mode-map)
@@ -4780,17 +5041,17 @@ If NEWSGROUP is nil, return the global KILL file instead."
             (string-equal newsgroup ""))
         ;; The global KILL file is placed at top of the directory.
         (expand-file-name gnus-kill-file-name
-                          (or gnus-article-save-directory "~/News")))
+                          (or gnus-kill-files-directory "~/News")))
        (gnus-use-long-file-name
         ;; Append ".KILL" to capitalized newsgroup name.
         (expand-file-name (concat (gnus-capitalize-newsgroup newsgroup)
                                   "." gnus-kill-file-name)
-                          (or gnus-article-save-directory "~/News")))
+                          (or gnus-kill-files-directory "~/News")))
        (t
         ;; Place "KILL" under the hierarchical directory.
         (expand-file-name (concat (gnus-newsgroup-directory-form newsgroup)
                                   "/" gnus-kill-file-name)
-                          (or gnus-article-save-directory "~/News")))
+                          (or gnus-kill-files-directory "~/News")))
        ))
 
 (defun gnus-newsgroup-kill-file (newsgroup)
@@ -4800,16 +5061,16 @@ If NEWSGROUP is nil, return the global KILL file instead."
             (string-equal newsgroup ""))
         ;; The global KILL file is placed at top of the directory.
         (expand-file-name gnus-kill-file-name
-                          (or gnus-article-save-directory "~/News")))
+                          (or gnus-kill-files-directory "~/News")))
        (gnus-use-long-file-name
         ;; Append ".KILL" to newsgroup name.
         (expand-file-name (concat newsgroup "." gnus-kill-file-name)
-                          (or gnus-article-save-directory "~/News")))
+                          (or gnus-kill-files-directory "~/News")))
        (t
         ;; Place "KILL" under the hierarchical directory.
         (expand-file-name (concat (gnus-newsgroup-directory-form newsgroup)
                                   "/" gnus-kill-file-name)
-                          (or gnus-article-save-directory "~/News")))
+                          (or gnus-kill-files-directory "~/News")))
        ))
 
 ;; For subscribing new newsgroup
@@ -4908,11 +5169,12 @@ If optional argument NEXT is non-nil, it is inserted before NEXT."
        ))
 
 (defun gnus-capitalize-newsgroup (newsgroup)
-  "Capitalize NEWSGROUP name with treating '.' and '-' as part of words."
+  "Capitalize NEWSGROUP name with treating `.' and `-' as part of words."
   ;; Suggested by "Jonathan I. Kamens" <jik@pit-manager.MIT.EDU>.
-  (let ((current-syntax-table (copy-syntax-table (syntax-table))))
+  (let ((current-syntax-table (syntax-table)))
     (unwind-protect
        (progn
+         (set-syntax-table (copy-syntax-table current-syntax-table))
          (modify-syntax-entry ?- "w")
          (modify-syntax-entry ?. "w")
          (capitalize newsgroup))
@@ -4993,7 +5255,7 @@ Optional argument REVERSE means reverse order."
 
 (defun gnus-string-lessp (a b)
   "Return T if first arg string is less than second in lexicographic order.
-If case-fold-search is non-nil, case of letters is ignored."
+If `case-fold-search' is non-nil, case of letters is ignored."
   (if case-fold-search
       (string-lessp (downcase a) (downcase b))
     (string-lessp a b)))
@@ -5004,16 +5266,15 @@ If case-fold-search is non-nil, case of letters is ignored."
                (gnus-sortable-date date2)))
 
 (defun gnus-sortable-date (date)
-  "Make sortable string by string-lessp from DATE.
+  "Convert DATE into a string that can be sorted with `string-lessp'.
 Timezone package is used."
-  (let* ((date   (timezone-parse-date date)) ;[Y M D T]
-        (year   (string-to-int (aref date 0)))
-        (month  (string-to-int (aref date 1)))
-        (day    (string-to-int (aref date 2)))
-        (time   (aref date 3)))        ;HH:MM:SS
-    ;; Timezone package is used.  But, we don't have to care about
-    ;; the timezone since article's timezones are always GMT.
-    (timezone-make-sortable-date year month day time)
+  (let* ((date   (timezone-fix-time date nil nil)) ;[Y M D H M S]
+        (year   (aref date 0))
+        (month  (aref date 1))
+        (day    (aref date 2)))
+    (timezone-make-sortable-date year month day 
+                                (timezone-make-time-string
+                                 (aref date 3) (aref date 4) (aref date 5)))
     ))
 
 ;;(defun gnus-sortable-date (date)
@@ -5056,7 +5317,7 @@ Timezone package is used."
                        (progn (search-forward "\n\n" nil 'move) (point)))
       (mail-fetch-field field))))
 
-(fset 'gnus-expunge 'gnus-summary-delete-marked-with)
+(defalias 'gnus-expunge 'gnus-summary-delete-marked-with)
 
 (defun gnus-kill (field regexp &optional command all)
   "If FIELD of an article matches REGEXP, execute COMMAND.
@@ -5064,12 +5325,12 @@ Optional 1st argument COMMAND is default to
        (gnus-summary-mark-as-read nil \"X\").
 If optional 2nd argument ALL is non-nil, articles marked are also applied to.
 If FIELD is an empty string (or nil), entire article body is searched for.
-COMMAND must be a lisp expression or a string representing a key sequence."
+COMMAND must be a Lisp expression or a string representing a key sequence."
   ;; We don't want to change current point nor window configuration.
   (save-excursion
     (save-window-excursion
       ;; Selected window must be Summary buffer to execute keyboard
-      ;; macros correctly. See command_loop_1.
+      ;; macros correctly.  See command_loop_1.
       (switch-to-buffer gnus-summary-buffer 'norecord)
       (goto-char (point-min))          ;From the beginning.
       (if (null command)
@@ -5081,8 +5342,8 @@ COMMAND must be a lisp expression or a string representing a key sequence."
   "If FIELD of article header matches REGEXP, execute lisp FORM (or a string).
 If FIELD is an empty string (or nil), entire article body is searched for.
 If optional 1st argument BACKWARD is non-nil, do backward instead.
-If optional 2nd argument IGNORE-MARKED is non-nil, articles which are
-marked as read or unread are ignored."
+If optional 2nd argument IGNORE-MARKED is non-nil, ignore articles
+marked as read or unread."
   (let ((function nil)
        (header nil)
        (article nil))
@@ -5191,7 +5452,7 @@ ROT47 will be performed for Japanese text in any case."
                          (if (<= v t1) (if (< v t2) v (+ v 47))
                            (if (<= v t3) (- v 47) v))))
                  (setq i (1+ i))))
-             (message "Building caesar-translate-table... done")))
+             (message "Building caesar-translate-table...done")))
        (let ((from (region-beginning))
              (to (region-end))
              (i 0) str len)
@@ -5249,7 +5510,7 @@ ROT47 will be performed for Japanese text in any case."
   (require 'rmail)
   ;; Most of these codes are borrowed from rmailout.el.
   (setq file-name (expand-file-name file-name))
-  (setq rmail-last-rmail-file file-name)
+  (setq rmail-default-rmail-file file-name)
   (let ((artbuf (current-buffer))
        (tmpbuf (get-buffer-create " *GNUS-output*")))
     (save-excursion
@@ -5354,7 +5615,7 @@ ROT47 will be performed for Japanese text in any case."
   "Open network stream to remote NNTP server.
 If optional argument CONFIRM is non-nil, ask you host that NNTP server
 is running even if it is defined.
-Run gnus-open-server-hook just before opening news server."
+Run `gnus-open-server-hook' just before opening news server."
   (if (gnus-server-opened)
       ;; Stream is already opened.
       nil
@@ -5400,12 +5661,12 @@ Run gnus-open-server-hook just before opening news server."
          ((gnus-open-server gnus-nntp-server gnus-nntp-service)
           (message ""))
          (t
-          (error
+          (error "%s"
            (gnus-nntp-message
             (format "Cannot open NNTP server on %s" gnus-nntp-server)))))
     ))
 
-;; Dummy functions used only once. Should return nil.
+;; Dummy functions used only once.  Should return nil.
 (defun gnus-server-opened () nil)
 (defun gnus-close-server () nil)
 
@@ -5421,7 +5682,7 @@ If no message is available and optional MESSAGE is given, return it."
 (defun gnus-define-access-method (method &optional access-methods)
   "Define access functions for the access METHOD.
 Methods definition is taken from optional argument ACCESS-METHODS or
-the variable gnus-access-methods."
+the variable `gnus-access-methods'."
   (let ((bindings
         (cdr (assoc method (or access-methods gnus-access-methods)))))
     (if (null bindings)
@@ -5542,8 +5803,8 @@ are selected."
 
 (defun gnus-get-header-by-number (number)
   "Return a header specified by a NUMBER.
-If the variable gnus-newsgroup-headers is updated, the hashed table
-gnus-newsgroup-headers-hashtb-by-number must be set to nil to indicate
+If you update the variable `gnus-newsgroup-headers', you must set the
+hash table `gnus-newsgroup-headers-hashtb-by-number' to nil to indicate
 rehash is necessary."
   (or gnus-newsgroup-headers-hashtb-by-number
       (gnus-make-headers-hashtable-by-number))
@@ -5552,8 +5813,8 @@ rehash is necessary."
 
 (defun gnus-get-header-by-id (id)
   "Return a header specified by an ID.
-If the variable gnus-newsgroup-headers is updated, the hashed table
-gnus-newsgroup-headers-hashtb-by-id must be set to nil to indicate
+If you update the variable `gnus-newsgroup-headers', you must set the
+hash table `gnus-newsgroup-headers-hashtb-by-id' to nil to indicate
 rehash is necessary."
   (or gnus-newsgroup-headers-hashtb-by-id
       (gnus-make-headers-hashtable-by-id))
@@ -5561,7 +5822,7 @@ rehash is necessary."
        (gnus-gethash id gnus-newsgroup-headers-hashtb-by-id)))
 
 (defun gnus-make-headers-hashtable-by-number ()
-  "Make hashtable for the variable gnus-newsgroup-headers by number."
+  "Make hashtable for the variable `gnus-newsgroup-headers' by number."
   (let ((header nil)
        (headers gnus-newsgroup-headers))
     (setq gnus-newsgroup-headers-hashtb-by-number
@@ -5574,7 +5835,7 @@ rehash is necessary."
       )))
 
 (defun gnus-make-headers-hashtable-by-id ()
-  "Make hashtable for the variable gnus-newsgroup-headers by id."
+  "Make hashtable for the variable `gnus-newsgroup-headers' by id."
   (let ((header nil)
        (headers gnus-newsgroup-headers))
     (setq gnus-newsgroup-headers-hashtb-by-id
@@ -5587,7 +5848,7 @@ rehash is necessary."
       )))
 
 (defun gnus-clear-hashtables-for-newsgroup-headers ()
-  "Clear hash tables created for the variable gnus-newsgroup-headers."
+  "Clear hash tables created for the variable `gnus-newsgroup-headers'."
   (setq gnus-newsgroup-headers-hashtb-by-id nil)
   (setq gnus-newsgroup-headers-hashtb-by-number nil))
 
@@ -5698,7 +5959,7 @@ that it was marked as read once."
   "Configure GNUS windows according to the next ACTION.
 The ACTION is either a symbol, such as `summary', or a
 configuration list such as `(1 1 2)'.  If ACTION is not a list,
-configuration list is got from the variable gnus-window-configuration."
+configuration list is got from the variable `gnus-window-configuration'."
   (let* ((windows
          (if (listp action)
              action (car (cdr (assq action gnus-window-configuration)))))
@@ -5709,7 +5970,9 @@ configuration list is got from the variable gnus-window-configuration."
         (height nil)
         (grpheight 0)
         (subheight 0)
-        (artheight 0))
+        (artheight 0)
+        ;; Make split-window-vertically leave focus in upper window.
+        (split-window-keep-point t))
     (if (or (null windows)             ;No configuration is specified.
            (and (eq (null grpwin)
                     (zerop (nth 0 windows)))
@@ -5729,7 +5992,7 @@ configuration list is got from the variable gnus-window-configuration."
             (setq height (+ (if grpwin (window-height grpwin) 0)
                             (if subwin (window-height subwin) 0)
                             (if artwin (window-height artwin) 0)))))
-      ;; The Newsgroup buffer exits always. So, use it to extend the
+      ;; The Newsgroup buffer exits always.  So, use it to extend the
       ;; Group window so as to get enough window space.
       (switch-to-buffer gnus-group-buffer 'norecord)
       (and (get-buffer gnus-summary-buffer)
@@ -5826,7 +6089,7 @@ configuration list is got from the variable gnus-window-configuration."
 
 (defun gnus-overload-functions (&optional overloads)
   "Overload functions specified by optional argument OVERLOADS.
-If nothing is specified, use the variable gnus-overload-functions."
+If nothing is specified, use the variable `gnus-overload-functions'."
   (let ((defs nil)
        (overloads (or overloads gnus-overload-functions)))
     (while overloads
@@ -6042,6 +6305,15 @@ If optional argument RAWFILE is non-nil, force to read raw startup file."
          ))
     (gnus-expire-marked-articles)
     (gnus-get-unread-articles)
+    
+    ;; newsgroups description
+    (if gnus-newsgroups-display
+       (if (not gnus-newsgroups-alist)
+           ;; Get newsgroups file only once.
+           (gnus-newsgroups-retrieve-description)))
+       
+    (setq gnus-newsgroups-hashtb (gnus-make-hashtable-from-alist gnus-newsgroups-alist))
+    
     ;; Check new newsgroups and subscribe them.
     (if init
        (let ((new-newsgroups (gnus-find-new-newsgroups)))
@@ -6061,7 +6333,7 @@ If optional argument RAWFILE is non-nil, force to read raw startup file."
 
 (defun gnus-find-new-newsgroups ()
   "Looking for new newsgroups and return names.
-`-n' option of options line in .newsrc file is recognized."
+`-n' option of options line in `.newsrc' file is recognized."
   (let ((group nil)
        (new-newsgroups nil))
     (mapatoms
@@ -6085,7 +6357,7 @@ If optional argument RAWFILE is non-nil, force to read raw startup file."
     ))
 
 (defun gnus-kill-newsgroup (group)
-  "Kill GROUP from gnus-newsrc-assoc, .newsrc and gnus-unread-hashtb."
+  "Kill GROUP from `gnus-newsrc-assoc', `.newsrc' and `gnus-unread-hashtb'."
   (let ((info (gnus-gethash group gnus-newsrc-hashtb)))
     (if (null info)
        nil
@@ -6155,8 +6427,8 @@ If optional argument NEXT is nil, appended to the last."
     ))
 
 (defun gnus-check-killed-newsgroups ()
-  "Check consistency between gnus-newsrc-assoc and gnus-killed-assoc.
-gnus-killed-hashtb is also updated."
+  "Update `gnus-killed-assoc' based on `gnus-newsrc-assoc'.
+Update `gnus-killed-hashtb' also."
   (let ((group nil)
        (new-killed nil)
        (old-killed gnus-killed-assoc))
@@ -6232,7 +6504,7 @@ If optional argument CONFIRM is non-nil, confirm deletion of newsgroups."
     (setq gnus-marked-assoc new-marked)
     (setq gnus-marked-hashtb
          (gnus-make-hashtable-from-alist gnus-marked-assoc))
-    (message "Checking bogus newsgroups... done")
+    (message "Checking bogus newsgroups...done")
     ))
 
 (defun gnus-get-unread-articles ()
@@ -6267,7 +6539,7 @@ If optional argument CONFIRM is non-nil, confirm deletion of newsgroups."
        )
       (setq read (cdr read))
       )
-    (message "Checking new news... done")
+    (message "Checking new news...done")
     ))
 
 (defun gnus-expire-marked-articles ()
@@ -6436,12 +6708,12 @@ Arguments are GROUP, HEADERS, UNREADS, and optional SUBSCRIBED-ONLY."
       (save-excursion
        (set-buffer nntp-server-buffer)
        (gnus-active-to-gnus-format)
-       (message "Reading active file... done"))
+       (message "Reading active file...done"))
     (error "Cannot read active file from NNTP server.")))
 
 (defun gnus-active-to-gnus-format ()
   "Convert active file format to internal format.
-Lines matching gnus-ignored-newsgroups are ignored."
+Lines matching `gnus-ignored-newsgroups' are ignored."
   ;; Delete unnecessary lines.
   (goto-char (point-min))
   ;;(delete-matching-lines "^to\\..*$")
@@ -6516,7 +6788,7 @@ If optional argument RAWFILE is non-nil, the raw startup file is read."
             (message "Reading %s..." newsrc-file)
             (gnus-newsrc-to-gnus-format)
             (gnus-check-killed-newsgroups)
-            (message "Reading %s... Done" newsrc-file)))
+            (message "Reading %s...done" newsrc-file)))
       )))
 
 (defun gnus-make-newsrc-file (file)
@@ -6528,7 +6800,7 @@ If optional argument RAWFILE is non-nil, the raw startup file is read."
     ))
 
 (defun gnus-newsrc-to-gnus-format ()
-  "Parse current buffer as .newsrc file."
+  "Parse current buffer as `.newsrc' file."
   (let ((newsgroup nil)
        (subscribe nil)
        (ranges nil)
@@ -6570,18 +6842,17 @@ If optional argument RAWFILE is non-nil, the raw startup file is read."
     ;; Before supporting continuation lines, " newsgroup ! 1-5" was
     ;; okay, but now it is invalid.  It should be "newsgroup! 1-5".
     (goto-char (point-min))
-    ;; Due to overflows in regex.c, change the following regexp:
+    ;; We used this regexp, but it caused overflows.
     ;; "^\\([^:! \t\n]+\\)\\([:!]\\)[ \t]*\\(.*\\)$"
     ;; Suggested by composer@bucsf.bu.edu (Jeff Kellem)
     ;; but no longer viable because of extensive backtracking in Emacs 19:
     ;; "^\\([^:! \t\n]+\\)\\([:!]\\)[ \t]*\\(\\(...\\)*.*\\)$"
     ;; but, the following causes trouble on some case:
     ;; "^\\([^:! \t\n]+\\)\\([:!]\\)[ \t]*\\(\\|[^ \t\n].*\\)$"
-    (while (re-search-forward
-           (if (= gnus-emacs-version 18)
-               "^\\([^:! \t\n]+\\)\\([:!]\\)[ \t]*\\(\\(...\\)*.*\\)$"
-             "^\\([^:! \t\n]+\\)\\([:!]\\)[ \t]*\\(.*\\)$")
-           nil t)
+    ;; So now we don't try to match the tail of the line at all.
+    ;; It's just as easy to extract it later.
+    (while (re-search-forward "^\\([^:! \t\n]+\\)\\([:!]\\)"
+                             nil t)
       (setq newsgroup (buffer-substring (match-beginning 1) (match-end 1)))
       ;; Check duplications of newsgroups.
       ;; Note: Checking the duplications takes very long time.
@@ -6590,7 +6861,9 @@ If optional argument RAWFILE is non-nil, the raw startup file is read."
        (setq subscribe
              (string-equal
               ":" (buffer-substring (match-beginning 2) (match-end 2))))
-       (setq ranges (buffer-substring (match-beginning 3) (match-end 3)))
+       (skip-chars-forward " \t")
+       (setq ranges (buffer-substring (point) (save-excursion
+                                                (end-of-line) (point))))
        (setq read-list nil)
        (while (string-match "^[, \t]*\\([0-9-]+\\)" ranges)
          (setq subrange (substring ranges (match-beginning 1) (match-end 1)))
@@ -6632,7 +6905,7 @@ If optional argument RAWFILE is non-nil, the raw startup file is read."
     ;; Parse each newsgroup description such as "comp.all".  Commas
     ;; and white spaces can be a newsgroup separator.
     (while
-       (string-match "^[ \t\n,]*\\(!?\\)\\([^--- \t\n,][^ \t\n,]*\\)" options)
+       (string-match "^[ \t\n,]*\\(!?\\)\\([^- \t\n,][^ \t\n,]*\\)" options)
       (setq yes-or-no
            (substring options (match-beginning 1) (match-end 1)))
       (setq newsgroup
@@ -6680,7 +6953,7 @@ If optional argument RAWFILE is non-nil, the raw startup file is read."
     ))
 
 (defun gnus-save-newsrc-file ()
-  "Save to .newsrc FILE."
+  "Save current status in the `.newsrc' file."
   ;; Note: We cannot save .newsrc file if all newsgroups are removed
   ;; from the variable gnus-newsrc-assoc.
   (and (or gnus-newsrc-assoc gnus-killed-assoc)
@@ -6709,12 +6982,12 @@ If optional argument RAWFILE is non-nil, the raw startup file is read."
                 (require-final-newline t)) ;Don't ask even if requested.
             (write-file (concat gnus-current-startup-file ".el")))
           (kill-buffer (current-buffer))
-          (message "Saving %s... Done" gnus-current-startup-file)
+          (message "Saving %s...done" gnus-current-startup-file)
           ))
     ))
 
 (defun gnus-update-newsrc-buffer (group &optional delete next)
-  "Incrementally update .newsrc buffer about GROUP.
+  "Incrementally update `.newsrc' buffer about GROUP.
 If optional 1st argument DELETE is non-nil, delete the group.
 If optional 2nd argument NEXT is non-nil, inserted before it."
   (save-excursion
@@ -6770,7 +7043,7 @@ If optional 2nd argument NEXT is non-nil, inserted before it."
       )))
 
 (defun gnus-gnus-to-quick-newsrc-format ()
-  "Insert GNUS variables such as gnus-newsrc-assoc in lisp format."
+  "Insert GNUS variables such as `gnus-newsrc-assoc' in Lisp format."
   (insert ";; GNUS internal format of .newsrc.\n")
   (insert ";; Touch .newsrc instead if you think to remove this file.\n")
   (let ((variable nil)
@@ -6855,7 +7128,7 @@ If optional 2nd argument NEXT is non-nil, inserted before it."
   (let ((count 0))
     (while range
       (if (/= (cdr (car range)) 0)
-         ;; If end1 is 0, it must be skipped. Usually no articles in
+         ;; If end1 is 0, it must be skipped.  Usually no articles in
          ;;  this group.
          (setq count (+ count 1 (- (cdr (car range)) (car (car range))))))
       (setq range (cdr range))
@@ -6903,7 +7176,7 @@ Range of OBJ is expressed as `((beg1 . end1) (beg2 . end2) ...)."
       (save-excursion
        (set-buffer nntp-server-buffer)
        (gnus-distributions-to-gnus-format)
-       (message "Reading distributions file... done"))
+       (message "Reading distributions file...done"))
     ;; It's not a fatal error.
     ;;(error "Cannot read distributions file from NNTP server.")
     )
@@ -6930,26 +7203,39 @@ Range of OBJ is expressed as `((beg1 . end1) (beg2 . end2) ...)."
                gnus-distribution-list)))
   (setq gnus-distribution-list
        (nreverse gnus-distribution-list)))
+\f
+(defun gnus-newsgroups-retrieve-description ()
+  "Retrieve newsgroups description and build gnus-newsgroups-alist"
+  (message "Reading newsgroups file...")
+  (if (gnus-request-list-newsgroups)
+      (save-excursion
+       (setq gnus-newsgroups-alist nil)
+       (set-buffer nntp-server-buffer)
+       (goto-char (point-min))
+       (while (re-search-forward gnus-newsgroups-regex nil t)
+         (setq gnus-newsgroups-alist
+               (cons (cons (buffer-substring (match-beginning 1) (match-end 1))
+                           (buffer-substring (match-beginning 2) (match-end 2)))
+                     gnus-newsgroups-alist)))
+       (message "Reading newsgroups file...done"))
+    (message "Cannot read newsgroups file")))
+
+(defun gnus-newsgroups-update-description ()
+  "Update the newsgroups description"
+  (interactive)
+  (gnus-newsgroups-retrieve-description)
+  (setq gnus-newsgroups-hashtb (gnus-make-hashtable-from-alist gnus-newsgroups-alist)))
 
-;; Some older version of GNU Emacs does not support function
-;; `file-newer-than-file-p'.
-
-(or (fboundp 'file-newer-than-file-p)
-    (defun file-newer-than-file-p (file1 file2)
-      "Return t if file FILE1 is newer than file FILE2.
-If FILE1 does not exist, the answer is nil;
-otherwise, if FILE2 does not exist, the answer is t."
-      (let ((mod1 (nth 5 (file-attributes file1)))
-           (mod2 (nth 5 (file-attributes file2))))
-       (cond ((not (file-exists-p file1)) nil)
-             ((not (file-exists-p file2)) t)
-             ((and mod2 mod1)
-              (or (< (car mod2) (car mod1))
-                  (and (= (car mod2) (car mod1))
-                       (<= (nth 1 mod2) (nth 1 mod1)))))
-             ))))
-
+(defun gnus-newsgroups-display-toggle ()
+  "Toggle displaying newsgroup descriptions in *Newsgroup* buffer."
+  (interactive)
+  (setq gnus-newsgroups-display (not gnus-newsgroups-display))
+  (if gnus-newsgroups-showall
+        (gnus-group-list-groups t)
+    (gnus-group-list-groups nil)))
 \f
+(provide 'gnus)
+
 ;;Local variables:
 ;;eval: (put 'gnus-eval-in-buffer-window 'lisp-indent-hook 1)
 ;;end: