Import Oort Gnus v0.16.
[elisp/gnus.git-] / lisp / gnus-sum.el
index 9ccfe4f..596da96 100644 (file)
@@ -1,5 +1,5 @@
 ;;; gnus-sum.el --- summary mode commands for Gnus
-;; Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002
+;; Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
 ;;        Free Software Foundation, Inc.
 
 ;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
@@ -46,9 +46,9 @@
 (autoload 'gnus-article-outlook-deuglify-article "deuglify"
   "Deuglify broken Outlook (Express) articles and redisplay."
   t)
-(autoload 'gnus-outlook-unwrap-lines "deuglify" nil t)
-(autoload 'gnus-outlook-repair-attribution "deuglify" nil t)
-(autoload 'gnus-outlook-rearrange-citation "deuglify" nil t)
+(autoload 'gnus-article-outlook-unwrap-lines "deuglify" nil t)
+(autoload 'gnus-article-outlook-repair-attribution "deuglify" nil t)
+(autoload 'gnus-article-outlook-rearrange-citation "deuglify" nil t)
 
 (defcustom gnus-kill-summary-on-exit t
   "*If non-nil, kill the summary buffer when you exit from it.
@@ -321,13 +321,13 @@ place point on some subject line."
 (defcustom gnus-auto-select-next t
   "*If non-nil, offer to go to the next group from the end of the previous.
 If the value is t and the next newsgroup is empty, Gnus will exit
-summary mode and go back to group mode.         If the value is neither nil
-nor t, Gnus will select the following unread newsgroup.         In
+summary mode and go back to group mode.  If the value is neither nil
+nor t, Gnus will select the following unread newsgroup.  In
 particular, if the value is the symbol `quietly', the next unread
 newsgroup will be selected without any confirmation, and if it is
 `almost-quietly', the next group will be selected without any
 confirmation if you are located on the last article in the group.
-Finally, if this variable is `slightly-quietly', the `Z n' command
+Finally, if this variable is `slightly-quietly', the `\\<gnus-summary-mode-map>\\[gnus-summary-catchup-and-goto-next-group]' command
 will go to the next group without confirmation."
   :group 'gnus-summary-maneuvering
   :type '(choice (const :tag "off" nil)
@@ -343,6 +343,23 @@ the first unread article."
   :group 'gnus-summary-maneuvering
   :type 'boolean)
 
+(defcustom gnus-auto-goto-ignores 'unfetched
+  "*Says how to handle unfetched articles when maneuvering.
+
+This variable can either be the symbols `nil' (maneuver to any
+article), `undownloaded' (maneuvering while unplugged ignores articles
+that have not been fetched), `always-undownloaded' (maneuvering always
+ignores articles that have not been fetched), `unfetched' (maneuvering
+ignores articles whose headers have not been fetched).
+
+NOTE: The list of unfetched articles will always be nil when plugged
+and, when unplugged, a subset of the undownloaded article list."
+  :group 'gnus-summary-maneuvering
+  :type '(choice (const :tag "None" nil)
+                 (const :tag "Undownloaded when unplugged" undownloaded)
+                 (const :tag "Undownloaded" always-undownloaded)
+                 (const :tag "Unfetched" unfetched)))
+
 (defcustom gnus-summary-check-current nil
   "*If non-nil, consider the current article when moving.
 The \"unread\" movement commands will stay on the same line if the
@@ -360,6 +377,9 @@ and non-`vertical', do both horizontal and vertical recentering."
                 (integer :tag "height")
                 (sexp :menu-tag "both" t)))
 
+(defvar gnus-auto-center-group t
+  "*If non-nil, always center the group buffer.")
+
 (defcustom gnus-show-all-headers nil
   "*If non-nil, don't hide any headers."
   :group 'gnus-article-hiding
@@ -429,7 +449,7 @@ this variable specifies group names."
   :group 'gnus-summary-marks
   :type 'character)
 
-(defcustom gnus-spam-mark ?H
+(defcustom gnus-spam-mark ?$
   "*Mark used for spam articles."
   :group 'gnus-summary-marks
   :type 'character)
@@ -847,6 +867,21 @@ automatically when it is selected."
   :group 'gnus-summary
   :type 'hook)
 
+(defcustom gnus-summary-article-move-hook nil
+  "*A hook called after an article is moved, copied, respooled, or crossposted."
+  :group 'gnus-summary
+  :type 'hook)
+
+(defcustom gnus-summary-article-delete-hook nil
+  "*A hook called after an article is deleted."
+  :group 'gnus-summary
+  :type 'hook)
+
+(defcustom gnus-summary-article-expire-hook nil
+  "*A hook called after an article is expired."
+  :group 'gnus-summary
+  :type 'hook)
+
 (defcustom gnus-summary-display-arrow
   (and (fboundp 'display-graphic-p)
        (display-graphic-p))
@@ -922,7 +957,10 @@ mark:         The articles mark."
 (defcustom gnus-alter-header-function nil
   "Function called to allow alteration of article header structures.
 The function is called with one parameter, the article header vector,
-which it may alter in any way.")
+which it may alter in any way."
+  :type '(choice (const :tag "None" nil)
+                function)
+  :group 'gnus-summary)
 
 (defvar gnus-decode-encoded-word-function 'mail-decode-encoded-word-string
   "Variable that says which function should be used to decode a string with encoded words.")
@@ -1013,9 +1051,10 @@ For example: ((1 . cn-gb-2312) (2 . big5))."
                 integer))
 
 (defcustom gnus-summary-save-parts-default-mime "image/.*"
-  "*A regexp to match MIME parts when saving multiple parts of a message
-with gnus-summary-save-parts (X m). This regexp will be used by default
-when prompting the user for which type of files to save."
+  "*A regexp to match MIME parts when saving multiple parts of a
+message with `gnus-summary-save-parts' (\\<gnus-summary-mode-map>\\[gnus-summary-save-parts]).
+This regexp will be used by default when prompting the user for which
+type of files to save."
   :group 'gnus-summary
   :type 'regexp)
 
@@ -1231,8 +1270,14 @@ the type of the variable (string, integer, character, etc).")
 (defvar gnus-newsgroup-downloadable nil
   "Sorted list of articles in the current newsgroup that can be processed.")
 
+(defvar gnus-newsgroup-unfetched nil
+  "Sorted list of articles in the current newsgroup whose headers have
+not been fetched into the agent.
+
+This list will always be a subset of gnus-newsgroup-undownloaded.")
+
 (defvar gnus-newsgroup-undownloaded nil
-  "List of articles in the current newsgroup that haven't been downloaded..")
+  "List of articles in the current newsgroup that haven't been downloaded.")
 
 (defvar gnus-newsgroup-unsendable nil
   "List of articles in the current newsgroup that won't be sent.")
@@ -1294,6 +1339,7 @@ the type of the variable (string, integer, character, etc).")
     gnus-newsgroup-expirable
     gnus-newsgroup-processable gnus-newsgroup-killed
     gnus-newsgroup-downloadable gnus-newsgroup-undownloaded
+    gnus-newsgroup-unfetched
     gnus-newsgroup-unsendable gnus-newsgroup-unseen
     gnus-newsgroup-seen gnus-newsgroup-articles
     gnus-newsgroup-bookmarks gnus-newsgroup-dormant
@@ -1385,26 +1431,24 @@ For example:
 
 (defun gnus-simplify-whitespace (str)
   "Remove excessive whitespace from STR."
-  (let ((mystr str))
-    ;; Multiple spaces.
-    (while (string-match "[ \t][ \t]+" mystr)
-      (setq mystr (concat (substring mystr 0 (match-beginning 0))
-                         " "
-                         (substring mystr (match-end 0)))))
-    ;; Leading spaces.
-    (when (string-match "^[ \t]+" mystr)
-      (setq mystr (substring mystr (match-end 0))))
-    ;; Trailing spaces.
-    (when (string-match "[ \t]+$" mystr)
-      (setq mystr (substring mystr 0 (match-beginning 0))))
-    mystr))
+  ;; Multiple spaces.
+  (while (string-match "[ \t][ \t]+" str)
+    (setq str (concat (substring str 0 (match-beginning 0))
+                       " "
+                       (substring str (match-end 0)))))
+  ;; Leading spaces.
+  (when (string-match "^[ \t]+" str)
+    (setq str (substring str (match-end 0))))
+  ;; Trailing spaces.
+  (when (string-match "[ \t]+$" str)
+    (setq str (substring str 0 (match-beginning 0))))
+  str)
 
 (defun gnus-simplify-all-whitespace (str)
   "Remove all whitespace from STR."
-  (let ((mystr str))
-    (while (string-match "[ \t\n]+" mystr)
-      (setq mystr (replace-match "" nil nil mystr)))
-    mystr))
+  (while (string-match "[ \t\n]+" str)
+    (setq str (replace-match "" nil nil str)))
+  str)
 
 (defsubst gnus-simplify-subject-re (subject)
   "Remove \"Re:\" from subject lines."
@@ -1482,7 +1526,7 @@ See `gnus-simplify-buffer-fuzzy' for details."
       (buffer-string))))
 
 (defsubst gnus-simplify-subject-fully (subject)
-  "Simplify a subject string according to gnus-summary-gather-subject-limit."
+  "Simplify a subject string according to `gnus-summary-gather-subject-limit'."
   (cond
    (gnus-simplify-subject-functions
     (gnus-map-function gnus-simplify-subject-functions subject))
@@ -1498,7 +1542,7 @@ See `gnus-simplify-buffer-fuzzy' for details."
 
 (defsubst gnus-subject-equal (s1 s2 &optional simple-first)
   "Check whether two subjects are equal.
-If optional argument simple-first is t, first argument is already
+If optional argument SIMPLE-FIRST is t, first argument is already
 simplified."
   (cond
    ((null simple-first)
@@ -1523,444 +1567,441 @@ increase the score of each group you read."
 
 (defvar gnus-article-commands-menu)
 
-(when t
-  ;; Non-orthogonal keys
-
-  (gnus-define-keys gnus-summary-mode-map
-    " " gnus-summary-next-page
-    "\177" gnus-summary-prev-page
-    [delete] gnus-summary-prev-page
-    [backspace] gnus-summary-prev-page
-    "\r" gnus-summary-scroll-up
-    "\M-\r" gnus-summary-scroll-down
-    "n" gnus-summary-next-unread-article
-    "p" gnus-summary-prev-unread-article
-    "N" gnus-summary-next-article
-    "P" gnus-summary-prev-article
-    "\M-\C-n" gnus-summary-next-same-subject
-    "\M-\C-p" gnus-summary-prev-same-subject
-    "\M-n" gnus-summary-next-unread-subject
-    "\M-p" gnus-summary-prev-unread-subject
-    "." gnus-summary-first-unread-article
-    "," gnus-summary-best-unread-article
-    "\M-s" gnus-summary-search-article-forward
-    "\M-r" gnus-summary-search-article-backward
-    "<" gnus-summary-beginning-of-article
-    ">" gnus-summary-end-of-article
-    "j" gnus-summary-goto-article
-    "^" gnus-summary-refer-parent-article
-    "\M-^" gnus-summary-refer-article
-    "u" gnus-summary-tick-article-forward
-    "!" gnus-summary-tick-article-forward
-    "U" gnus-summary-tick-article-backward
-    "d" gnus-summary-mark-as-read-forward
-    "D" gnus-summary-mark-as-read-backward
-    "E" gnus-summary-mark-as-expirable
-    "\M-u" gnus-summary-clear-mark-forward
-    "\M-U" gnus-summary-clear-mark-backward
-    "k" gnus-summary-kill-same-subject-and-select
-    "\C-k" gnus-summary-kill-same-subject
-    "\M-\C-k" gnus-summary-kill-thread
-    "\M-\C-l" gnus-summary-lower-thread
-    "e" gnus-summary-edit-article
-    "#" gnus-summary-mark-as-processable
-    "\M-#" gnus-summary-unmark-as-processable
-    "\M-\C-t" gnus-summary-toggle-threads
-    "\M-\C-s" gnus-summary-show-thread
-    "\M-\C-h" gnus-summary-hide-thread
-    "\M-\C-f" gnus-summary-next-thread
-    "\M-\C-b" gnus-summary-prev-thread
-    [(meta down)] gnus-summary-next-thread
-    [(meta up)] gnus-summary-prev-thread
-    "\M-\C-u" gnus-summary-up-thread
-    "\M-\C-d" gnus-summary-down-thread
-    "&" gnus-summary-execute-command
-    "c" gnus-summary-catchup-and-exit
-    "\C-w" gnus-summary-mark-region-as-read
-    "\C-t" gnus-summary-toggle-truncation
-    "?" gnus-summary-mark-as-dormant
-    "\C-c\M-\C-s" gnus-summary-limit-include-expunged
-    "\C-c\C-s\C-n" gnus-summary-sort-by-number
-    "\C-c\C-s\C-l" gnus-summary-sort-by-lines
-    "\C-c\C-s\C-c" gnus-summary-sort-by-chars
-    "\C-c\C-s\C-a" gnus-summary-sort-by-author
-    "\C-c\C-s\C-s" gnus-summary-sort-by-subject
-    "\C-c\C-s\C-d" gnus-summary-sort-by-date
-    "\C-c\C-s\C-i" gnus-summary-sort-by-score
-    "\C-c\C-s\C-o" gnus-summary-sort-by-original
-    "\C-c\C-s\C-r" gnus-summary-sort-by-random
-    "=" gnus-summary-expand-window
-    "\C-x\C-s" gnus-summary-reselect-current-group
-    "\M-g" gnus-summary-rescan-group
-    "w" gnus-summary-stop-page-breaking
-    "\C-c\C-r" gnus-summary-caesar-message
-    "f" gnus-summary-followup
-    "F" gnus-summary-followup-with-original
-    "C" gnus-summary-cancel-article
-    "r" gnus-summary-reply
-    "R" gnus-summary-reply-with-original
-    "\C-c\C-f" gnus-summary-mail-forward
-    "o" gnus-summary-save-article
-    "\C-o" gnus-summary-save-article-mail
-    "|" gnus-summary-pipe-output
-    "\M-k" gnus-summary-edit-local-kill
-    "\M-K" gnus-summary-edit-global-kill
-    ;; "V" gnus-version
-    "\C-c\C-d" gnus-summary-describe-group
-    "q" gnus-summary-exit
-    "Q" gnus-summary-exit-no-update
-    "\C-c\C-i" gnus-info-find-node
-    gnus-mouse-2 gnus-mouse-pick-article
-    "m" gnus-summary-mail-other-window
-    "a" gnus-summary-post-news
-    "i" gnus-summary-news-other-window
-    "x" gnus-summary-limit-to-unread
-    "s" gnus-summary-isearch-article
-    "t" gnus-summary-toggle-header
-    "g" gnus-summary-show-article
-    "l" gnus-summary-goto-last-article
-    "\C-c\C-v\C-v" gnus-uu-decode-uu-view
-    "\C-d" gnus-summary-enter-digest-group
-    "\M-\C-d" gnus-summary-read-document
-    "\M-\C-e" gnus-summary-edit-parameters
-    "\M-\C-a" gnus-summary-customize-parameters
-    "\C-c\C-b" gnus-bug
-    "*" gnus-cache-enter-article
-    "\M-*" gnus-cache-remove-article
-    "\M-&" gnus-summary-universal-argument
-    "\C-l" gnus-recenter
-    "I" gnus-summary-increase-score
-    "L" gnus-summary-lower-score
-    "\M-i" gnus-symbolic-argument
-    "h" gnus-summary-select-article-buffer
-
-    "b" gnus-article-view-part
-    "\M-t" gnus-summary-toggle-display-buttonized
-
-    "V" gnus-summary-score-map
-    "X" gnus-uu-extract-map
-    "S" gnus-summary-send-map)
-
-  ;; Sort of orthogonal keymap
-  (gnus-define-keys (gnus-summary-mark-map "M" gnus-summary-mode-map)
-    "t" gnus-summary-tick-article-forward
-    "!" gnus-summary-tick-article-forward
-    "d" gnus-summary-mark-as-read-forward
-    "r" gnus-summary-mark-as-read-forward
-    "c" gnus-summary-clear-mark-forward
-    " " gnus-summary-clear-mark-forward
-    "e" gnus-summary-mark-as-expirable
-    "x" gnus-summary-mark-as-expirable
-    "?" gnus-summary-mark-as-dormant
-    "b" gnus-summary-set-bookmark
-    "B" gnus-summary-remove-bookmark
-    "#" gnus-summary-mark-as-processable
-    "\M-#" gnus-summary-unmark-as-processable
-    "S" gnus-summary-limit-include-expunged
-    "C" gnus-summary-catchup
-    "H" gnus-summary-catchup-to-here
-    "h" gnus-summary-catchup-from-here
-    "\C-c" gnus-summary-catchup-all
-    "k" gnus-summary-kill-same-subject-and-select
-    "K" gnus-summary-kill-same-subject
-    "P" gnus-uu-mark-map)
-
-  (gnus-define-keys (gnus-summary-mscore-map "V" gnus-summary-mark-map)
-    "c" gnus-summary-clear-above
-    "u" gnus-summary-tick-above
-    "m" gnus-summary-mark-above
-    "k" gnus-summary-kill-below)
-
-  (gnus-define-keys (gnus-summary-limit-map "/" gnus-summary-mode-map)
-    "/" gnus-summary-limit-to-subject
-    "n" gnus-summary-limit-to-articles
-    "w" gnus-summary-pop-limit
-    "s" gnus-summary-limit-to-subject
-    "a" gnus-summary-limit-to-author
-    "u" gnus-summary-limit-to-unread
-    "m" gnus-summary-limit-to-marks
-    "M" gnus-summary-limit-exclude-marks
-    "v" gnus-summary-limit-to-score
-    "*" gnus-summary-limit-include-cached
-    "D" gnus-summary-limit-include-dormant
-    "T" gnus-summary-limit-include-thread
-    "d" gnus-summary-limit-exclude-dormant
-    "t" gnus-summary-limit-to-age
-    "." gnus-summary-limit-to-unseen
-    "x" gnus-summary-limit-to-extra
-    "p" gnus-summary-limit-to-display-predicate
-    "E" gnus-summary-limit-include-expunged
-    "c" gnus-summary-limit-exclude-childless-dormant
-    "C" gnus-summary-limit-mark-excluded-as-read
-    "o" gnus-summary-insert-old-articles
-    "N" gnus-summary-insert-new-articles)
-
-  (gnus-define-keys (gnus-summary-goto-map "G" gnus-summary-mode-map)
-    "n" gnus-summary-next-unread-article
-    "p" gnus-summary-prev-unread-article
-    "N" gnus-summary-next-article
-    "P" gnus-summary-prev-article
-    "\C-n" gnus-summary-next-same-subject
-    "\C-p" gnus-summary-prev-same-subject
-    "\M-n" gnus-summary-next-unread-subject
-    "\M-p" gnus-summary-prev-unread-subject
-    "f" gnus-summary-first-unread-article
-    "b" gnus-summary-best-unread-article
-    "j" gnus-summary-goto-article
-    "g" gnus-summary-goto-subject
-    "l" gnus-summary-goto-last-article
-    "o" gnus-summary-pop-article)
-
-  (gnus-define-keys (gnus-summary-thread-map "T" gnus-summary-mode-map)
-    "k" gnus-summary-kill-thread
-    "l" gnus-summary-lower-thread
-    "i" gnus-summary-raise-thread
-    "T" gnus-summary-toggle-threads
-    "t" gnus-summary-rethread-current
-    "^" gnus-summary-reparent-thread
-    "s" gnus-summary-show-thread
-    "S" gnus-summary-show-all-threads
-    "h" gnus-summary-hide-thread
-    "H" gnus-summary-hide-all-threads
-    "n" gnus-summary-next-thread
-    "p" gnus-summary-prev-thread
-    "u" gnus-summary-up-thread
-    "o" gnus-summary-top-thread
-    "d" gnus-summary-down-thread
-    "#" gnus-uu-mark-thread
-    "\M-#" gnus-uu-unmark-thread)
-
-  (gnus-define-keys (gnus-summary-buffer-map "Y" gnus-summary-mode-map)
-    "g" gnus-summary-prepare
-    "c" gnus-summary-insert-cached-articles
-    "d" gnus-summary-insert-dormant-articles)
-
-  (gnus-define-keys (gnus-summary-exit-map "Z" gnus-summary-mode-map)
-    "c" gnus-summary-catchup-and-exit
-    "C" gnus-summary-catchup-all-and-exit
-    "E" gnus-summary-exit-no-update
-    "Q" gnus-summary-exit
-    "Z" gnus-summary-exit
-    "n" gnus-summary-catchup-and-goto-next-group
-    "R" gnus-summary-reselect-current-group
-    "G" gnus-summary-rescan-group
-    "N" gnus-summary-next-group
-    "s" gnus-summary-save-newsrc
-    "P" gnus-summary-prev-group)
-
-  (gnus-define-keys (gnus-summary-article-map "A" gnus-summary-mode-map)
-    " " gnus-summary-next-page
-    "n" gnus-summary-next-page
-    "\177" gnus-summary-prev-page
-    [delete] gnus-summary-prev-page
-    "p" gnus-summary-prev-page
-    "\r" gnus-summary-scroll-up
-    "\M-\r" gnus-summary-scroll-down
-    "<" gnus-summary-beginning-of-article
-    ">" gnus-summary-end-of-article
-    "b" gnus-summary-beginning-of-article
-    "e" gnus-summary-end-of-article
-    "^" gnus-summary-refer-parent-article
-    "r" gnus-summary-refer-parent-article
-    "D" gnus-summary-enter-digest-group
-    "R" gnus-summary-refer-references
-    "T" gnus-summary-refer-thread
-    "g" gnus-summary-show-article
-    "s" gnus-summary-isearch-article
-    "P" gnus-summary-print-article
-    "M" gnus-mailing-list-insinuate
-    "t" gnus-article-babel)
-
-  (gnus-define-keys (gnus-summary-wash-map "W" gnus-summary-mode-map)
-    "b" gnus-article-add-buttons
-    "B" gnus-article-add-buttons-to-head
-    "o" gnus-article-treat-overstrike
-    "e" gnus-article-emphasize
-    "w" gnus-article-fill-cited-article
-    "Q" gnus-article-fill-long-lines
-    "C" gnus-article-capitalize-sentences
-    "c" gnus-article-remove-cr
-    "q" gnus-article-de-quoted-unreadable
-    "6" gnus-article-de-base64-unreadable
-    "Z" gnus-article-decode-HZ
-    "h" gnus-article-wash-html
-    "u" gnus-article-unsplit-urls
-    "s" gnus-summary-force-verify-and-decrypt
-    "f" gnus-article-display-x-face
-    "l" gnus-summary-stop-page-breaking
-    "r" gnus-summary-caesar-message
-    "m" gnus-summary-morse-message
-    "t" gnus-summary-toggle-header
-    "g" gnus-treat-smiley
-    "v" gnus-summary-verbose-headers
-    "a" gnus-article-strip-headers-in-body ;; mnemonic: wash archive
-    "p" gnus-article-verify-x-pgp-sig
-    "d" gnus-article-treat-dumbquotes
-    "k" gnus-article-outlook-deuglify-article) ;; mnemonic: outloo*k*
-
-  (gnus-define-keys (gnus-summary-wash-deuglify-map "Y" gnus-summary-wash-map)
-    ;; mnemonic: deuglif*Y*
-    "u" gnus-outlook-unwrap-lines
-    "a" gnus-outlook-repair-attribution
-    "c" gnus-outlook-rearrange-citation
-    "f" gnus-article-outlook-deuglify-article) ;; mnemonic: full deuglify
-
-  (gnus-define-keys (gnus-summary-wash-hide-map "W" gnus-summary-wash-map)
-    "a" gnus-article-hide
-    "h" gnus-article-hide-headers
-    "b" gnus-article-hide-boring-headers
-    "s" gnus-article-hide-signature
-    "c" gnus-article-hide-citation
-    "C" gnus-article-hide-citation-in-followups
-    "l" gnus-article-hide-list-identifiers
-    "p" gnus-article-hide-pgp
-    "B" gnus-article-strip-banner
-    "P" gnus-article-hide-pem
-    "\C-c" gnus-article-hide-citation-maybe)
-
-  (gnus-define-keys (gnus-summary-wash-highlight-map "H" gnus-summary-wash-map)
-    "a" gnus-article-highlight
-    "h" gnus-article-highlight-headers
-    "c" gnus-article-highlight-citation
-    "s" gnus-article-highlight-signature)
-
-  (gnus-define-keys (gnus-summary-wash-header-map "G" gnus-summary-wash-map)
-    "f" gnus-article-treat-fold-headers
-    "u" gnus-article-treat-unfold-headers
-    "n" gnus-article-treat-fold-newsgroups)
-
-  (gnus-define-keys (gnus-summary-wash-display-map "D" gnus-summary-wash-map)
-    "x" gnus-article-display-x-face
-    "d" gnus-article-display-face
-    "s" gnus-treat-smiley
-    "D" gnus-article-remove-images
-    "f" gnus-treat-from-picon
-    "m" gnus-treat-mail-picon
-    "n" gnus-treat-newsgroups-picon)
-
-  (gnus-define-keys (gnus-summary-wash-mime-map "M" gnus-summary-wash-map)
-    "w" gnus-article-decode-mime-words
-    "c" gnus-article-decode-charset
-    "v" gnus-mime-view-all-parts
-    "b" gnus-article-view-part)
-
-  (gnus-define-keys (gnus-summary-wash-time-map "T" gnus-summary-wash-map)
-    "z" gnus-article-date-ut
-    "u" gnus-article-date-ut
-    "l" gnus-article-date-local
-    "p" gnus-article-date-english
-    "e" gnus-article-date-lapsed
-    "o" gnus-article-date-original
-    "i" gnus-article-date-iso8601
-    "s" gnus-article-date-user)
-
-  (gnus-define-keys (gnus-summary-wash-empty-map "E" gnus-summary-wash-map)
-    "t" gnus-article-remove-trailing-blank-lines
-    "l" gnus-article-strip-leading-blank-lines
-    "m" gnus-article-strip-multiple-blank-lines
-    "a" gnus-article-strip-blank-lines
-    "A" gnus-article-strip-all-blank-lines
-    "s" gnus-article-strip-leading-space
-    "e" gnus-article-strip-trailing-space
-    "w" gnus-article-remove-leading-whitespace)
-
-  (gnus-define-keys (gnus-summary-help-map "H" gnus-summary-mode-map)
-    "v" gnus-version
-    "f" gnus-summary-fetch-faq
-    "d" gnus-summary-describe-group
-    "h" gnus-summary-describe-briefly
-    "i" gnus-info-find-node
-    "c" gnus-group-fetch-charter
-    "C" gnus-group-fetch-control)
-
-  (gnus-define-keys (gnus-summary-backend-map "B" gnus-summary-mode-map)
-    "e" gnus-summary-expire-articles
-    "\M-\C-e" gnus-summary-expire-articles-now
-    "\177" gnus-summary-delete-article
-    [delete] gnus-summary-delete-article
-    [backspace] gnus-summary-delete-article
-    "m" gnus-summary-move-article
-    "r" gnus-summary-respool-article
-    "w" gnus-summary-edit-article
-    "c" gnus-summary-copy-article
-    "B" gnus-summary-crosspost-article
-    "q" gnus-summary-respool-query
-    "t" gnus-summary-respool-trace
-    "i" gnus-summary-import-article
-    "I" gnus-summary-create-article
-    "p" gnus-summary-article-posted-p)
-
-  (gnus-define-keys (gnus-summary-save-map "O" gnus-summary-mode-map)
-    "o" gnus-summary-save-article
-    "m" gnus-summary-save-article-mail
-    "F" gnus-summary-write-article-file
-    "r" gnus-summary-save-article-rmail
-    "f" gnus-summary-save-article-file
-    "b" gnus-summary-save-article-body-file
-    "h" gnus-summary-save-article-folder
-    "v" gnus-summary-save-article-vm
-    "p" gnus-summary-pipe-output
-    "P" gnus-summary-muttprint
-    "s" gnus-soup-add-article)
-
-  (gnus-define-keys (gnus-summary-mime-map "K" gnus-summary-mode-map)
-    "b" gnus-summary-display-buttonized
-    "m" gnus-summary-repair-multipart
-    "v" gnus-article-view-part
-    "o" gnus-article-save-part
-    "c" gnus-article-copy-part
-    "C" gnus-article-view-part-as-charset
-    "e" gnus-article-view-part-externally
-    "E" gnus-article-encrypt-body
-    "i" gnus-article-inline-part
-    "|" gnus-article-pipe-part)
-
-  (gnus-define-keys (gnus-uu-mark-map "P" gnus-summary-mark-map)
-    "p" gnus-summary-mark-as-processable
-    "u" gnus-summary-unmark-as-processable
-    "U" gnus-summary-unmark-all-processable
-    "v" gnus-uu-mark-over
-    "s" gnus-uu-mark-series
-    "r" gnus-uu-mark-region
-    "g" gnus-uu-unmark-region
-    "R" gnus-uu-mark-by-regexp
-    "G" gnus-uu-unmark-by-regexp
-    "t" gnus-uu-mark-thread
-    "T" gnus-uu-unmark-thread
-    "a" gnus-uu-mark-all
-    "b" gnus-uu-mark-buffer
-    "S" gnus-uu-mark-sparse
-    "k" gnus-summary-kill-process-mark
-    "y" gnus-summary-yank-process-mark
-    "w" gnus-summary-save-process-mark
-    "i" gnus-uu-invert-processable)
-
-  (gnus-define-keys (gnus-uu-extract-map "X" gnus-summary-mode-map)
-    ;;"x" gnus-uu-extract-any
-    "m" gnus-summary-save-parts
-    "u" gnus-uu-decode-uu
-    "U" gnus-uu-decode-uu-and-save
-    "s" gnus-uu-decode-unshar
-    "S" gnus-uu-decode-unshar-and-save
-    "o" gnus-uu-decode-save
-    "O" gnus-uu-decode-save
-    "b" gnus-uu-decode-binhex
-    "B" gnus-uu-decode-binhex
-    "p" gnus-uu-decode-postscript
-    "P" gnus-uu-decode-postscript-and-save)
-
-  (gnus-define-keys
-      (gnus-uu-extract-view-map "v" gnus-uu-extract-map)
-    "u" gnus-uu-decode-uu-view
-    "U" gnus-uu-decode-uu-and-save-view
-    "s" gnus-uu-decode-unshar-view
-    "S" gnus-uu-decode-unshar-and-save-view
-    "o" gnus-uu-decode-save-view
-    "O" gnus-uu-decode-save-view
-    "b" gnus-uu-decode-binhex-view
-    "B" gnus-uu-decode-binhex-view
-    "p" gnus-uu-decode-postscript-view
-    "P" gnus-uu-decode-postscript-and-save-view))
+;; Non-orthogonal keys
+
+(gnus-define-keys gnus-summary-mode-map
+  " " gnus-summary-next-page
+  "\177" gnus-summary-prev-page
+  [delete] gnus-summary-prev-page
+  [backspace] gnus-summary-prev-page
+  "\r" gnus-summary-scroll-up
+  "\M-\r" gnus-summary-scroll-down
+  "n" gnus-summary-next-unread-article
+  "p" gnus-summary-prev-unread-article
+  "N" gnus-summary-next-article
+  "P" gnus-summary-prev-article
+  "\M-\C-n" gnus-summary-next-same-subject
+  "\M-\C-p" gnus-summary-prev-same-subject
+  "\M-n" gnus-summary-next-unread-subject
+  "\M-p" gnus-summary-prev-unread-subject
+  "." gnus-summary-first-unread-article
+  "," gnus-summary-best-unread-article
+  "\M-s" gnus-summary-search-article-forward
+  "\M-r" gnus-summary-search-article-backward
+  "<" gnus-summary-beginning-of-article
+  ">" gnus-summary-end-of-article
+  "j" gnus-summary-goto-article
+  "^" gnus-summary-refer-parent-article
+  "\M-^" gnus-summary-refer-article
+  "u" gnus-summary-tick-article-forward
+  "!" gnus-summary-tick-article-forward
+  "U" gnus-summary-tick-article-backward
+  "d" gnus-summary-mark-as-read-forward
+  "D" gnus-summary-mark-as-read-backward
+  "E" gnus-summary-mark-as-expirable
+  "\M-u" gnus-summary-clear-mark-forward
+  "\M-U" gnus-summary-clear-mark-backward
+  "k" gnus-summary-kill-same-subject-and-select
+  "\C-k" gnus-summary-kill-same-subject
+  "\M-\C-k" gnus-summary-kill-thread
+  "\M-\C-l" gnus-summary-lower-thread
+  "e" gnus-summary-edit-article
+  "#" gnus-summary-mark-as-processable
+  "\M-#" gnus-summary-unmark-as-processable
+  "\M-\C-t" gnus-summary-toggle-threads
+  "\M-\C-s" gnus-summary-show-thread
+  "\M-\C-h" gnus-summary-hide-thread
+  "\M-\C-f" gnus-summary-next-thread
+  "\M-\C-b" gnus-summary-prev-thread
+  [(meta down)] gnus-summary-next-thread
+  [(meta up)] gnus-summary-prev-thread
+  "\M-\C-u" gnus-summary-up-thread
+  "\M-\C-d" gnus-summary-down-thread
+  "&" gnus-summary-execute-command
+  "c" gnus-summary-catchup-and-exit
+  "\C-w" gnus-summary-mark-region-as-read
+  "\C-t" gnus-summary-toggle-truncation
+  "?" gnus-summary-mark-as-dormant
+  "\C-c\M-\C-s" gnus-summary-limit-include-expunged
+  "\C-c\C-s\C-n" gnus-summary-sort-by-number
+  "\C-c\C-s\C-l" gnus-summary-sort-by-lines
+  "\C-c\C-s\C-c" gnus-summary-sort-by-chars
+  "\C-c\C-s\C-a" gnus-summary-sort-by-author
+  "\C-c\C-s\C-s" gnus-summary-sort-by-subject
+  "\C-c\C-s\C-d" gnus-summary-sort-by-date
+  "\C-c\C-s\C-i" gnus-summary-sort-by-score
+  "\C-c\C-s\C-o" gnus-summary-sort-by-original
+  "\C-c\C-s\C-r" gnus-summary-sort-by-random
+  "=" gnus-summary-expand-window
+  "\C-x\C-s" gnus-summary-reselect-current-group
+  "\M-g" gnus-summary-rescan-group
+  "w" gnus-summary-stop-page-breaking
+  "\C-c\C-r" gnus-summary-caesar-message
+  "f" gnus-summary-followup
+  "F" gnus-summary-followup-with-original
+  "C" gnus-summary-cancel-article
+  "r" gnus-summary-reply
+  "R" gnus-summary-reply-with-original
+  "\C-c\C-f" gnus-summary-mail-forward
+  "o" gnus-summary-save-article
+  "\C-o" gnus-summary-save-article-mail
+  "|" gnus-summary-pipe-output
+  "\M-k" gnus-summary-edit-local-kill
+  "\M-K" gnus-summary-edit-global-kill
+  ;; "V" gnus-version
+  "\C-c\C-d" gnus-summary-describe-group
+  "q" gnus-summary-exit
+  "Q" gnus-summary-exit-no-update
+  "\C-c\C-i" gnus-info-find-node
+  gnus-mouse-2 gnus-mouse-pick-article
+  "m" gnus-summary-mail-other-window
+  "a" gnus-summary-post-news
+  "i" gnus-summary-news-other-window
+  "x" gnus-summary-limit-to-unread
+  "s" gnus-summary-isearch-article
+  "t" gnus-summary-toggle-header
+  "g" gnus-summary-show-article
+  "l" gnus-summary-goto-last-article
+  "\C-c\C-v\C-v" gnus-uu-decode-uu-view
+  "\C-d" gnus-summary-enter-digest-group
+  "\M-\C-d" gnus-summary-read-document
+  "\M-\C-e" gnus-summary-edit-parameters
+  "\M-\C-a" gnus-summary-customize-parameters
+  "\C-c\C-b" gnus-bug
+  "*" gnus-cache-enter-article
+  "\M-*" gnus-cache-remove-article
+  "\M-&" gnus-summary-universal-argument
+  "\C-l" gnus-recenter
+  "I" gnus-summary-increase-score
+  "L" gnus-summary-lower-score
+  "\M-i" gnus-symbolic-argument
+  "h" gnus-summary-select-article-buffer
+
+  "b" gnus-article-view-part
+  "\M-t" gnus-summary-toggle-display-buttonized
+
+  "V" gnus-summary-score-map
+  "X" gnus-uu-extract-map
+  "S" gnus-summary-send-map)
+
+;; Sort of orthogonal keymap
+(gnus-define-keys (gnus-summary-mark-map "M" gnus-summary-mode-map)
+  "t" gnus-summary-tick-article-forward
+  "!" gnus-summary-tick-article-forward
+  "d" gnus-summary-mark-as-read-forward
+  "r" gnus-summary-mark-as-read-forward
+  "c" gnus-summary-clear-mark-forward
+  " " gnus-summary-clear-mark-forward
+  "e" gnus-summary-mark-as-expirable
+  "x" gnus-summary-mark-as-expirable
+  "?" gnus-summary-mark-as-dormant
+  "b" gnus-summary-set-bookmark
+  "B" gnus-summary-remove-bookmark
+  "#" gnus-summary-mark-as-processable
+  "\M-#" gnus-summary-unmark-as-processable
+  "S" gnus-summary-limit-include-expunged
+  "C" gnus-summary-catchup
+  "H" gnus-summary-catchup-to-here
+  "h" gnus-summary-catchup-from-here
+  "\C-c" gnus-summary-catchup-all
+  "k" gnus-summary-kill-same-subject-and-select
+  "K" gnus-summary-kill-same-subject
+  "P" gnus-uu-mark-map)
+
+(gnus-define-keys (gnus-summary-mscore-map "V" gnus-summary-mark-map)
+  "c" gnus-summary-clear-above
+  "u" gnus-summary-tick-above
+  "m" gnus-summary-mark-above
+  "k" gnus-summary-kill-below)
+
+(gnus-define-keys (gnus-summary-limit-map "/" gnus-summary-mode-map)
+  "/" gnus-summary-limit-to-subject
+  "n" gnus-summary-limit-to-articles
+  "w" gnus-summary-pop-limit
+  "s" gnus-summary-limit-to-subject
+  "a" gnus-summary-limit-to-author
+  "u" gnus-summary-limit-to-unread
+  "m" gnus-summary-limit-to-marks
+  "M" gnus-summary-limit-exclude-marks
+  "v" gnus-summary-limit-to-score
+  "*" gnus-summary-limit-include-cached
+  "D" gnus-summary-limit-include-dormant
+  "T" gnus-summary-limit-include-thread
+  "d" gnus-summary-limit-exclude-dormant
+  "t" gnus-summary-limit-to-age
+  "." gnus-summary-limit-to-unseen
+  "x" gnus-summary-limit-to-extra
+  "p" gnus-summary-limit-to-display-predicate
+  "E" gnus-summary-limit-include-expunged
+  "c" gnus-summary-limit-exclude-childless-dormant
+  "C" gnus-summary-limit-mark-excluded-as-read
+  "o" gnus-summary-insert-old-articles
+  "N" gnus-summary-insert-new-articles)
+
+(gnus-define-keys (gnus-summary-goto-map "G" gnus-summary-mode-map)
+  "n" gnus-summary-next-unread-article
+  "p" gnus-summary-prev-unread-article
+  "N" gnus-summary-next-article
+  "P" gnus-summary-prev-article
+  "\C-n" gnus-summary-next-same-subject
+  "\C-p" gnus-summary-prev-same-subject
+  "\M-n" gnus-summary-next-unread-subject
+  "\M-p" gnus-summary-prev-unread-subject
+  "f" gnus-summary-first-unread-article
+  "b" gnus-summary-best-unread-article
+  "j" gnus-summary-goto-article
+  "g" gnus-summary-goto-subject
+  "l" gnus-summary-goto-last-article
+  "o" gnus-summary-pop-article)
+
+(gnus-define-keys (gnus-summary-thread-map "T" gnus-summary-mode-map)
+  "k" gnus-summary-kill-thread
+  "l" gnus-summary-lower-thread
+  "i" gnus-summary-raise-thread
+  "T" gnus-summary-toggle-threads
+  "t" gnus-summary-rethread-current
+  "^" gnus-summary-reparent-thread
+  "s" gnus-summary-show-thread
+  "S" gnus-summary-show-all-threads
+  "h" gnus-summary-hide-thread
+  "H" gnus-summary-hide-all-threads
+  "n" gnus-summary-next-thread
+  "p" gnus-summary-prev-thread
+  "u" gnus-summary-up-thread
+  "o" gnus-summary-top-thread
+  "d" gnus-summary-down-thread
+  "#" gnus-uu-mark-thread
+  "\M-#" gnus-uu-unmark-thread)
+
+(gnus-define-keys (gnus-summary-buffer-map "Y" gnus-summary-mode-map)
+  "g" gnus-summary-prepare
+  "c" gnus-summary-insert-cached-articles
+  "d" gnus-summary-insert-dormant-articles)
+
+(gnus-define-keys (gnus-summary-exit-map "Z" gnus-summary-mode-map)
+  "c" gnus-summary-catchup-and-exit
+  "C" gnus-summary-catchup-all-and-exit
+  "E" gnus-summary-exit-no-update
+  "Q" gnus-summary-exit
+  "Z" gnus-summary-exit
+  "n" gnus-summary-catchup-and-goto-next-group
+  "R" gnus-summary-reselect-current-group
+  "G" gnus-summary-rescan-group
+  "N" gnus-summary-next-group
+  "s" gnus-summary-save-newsrc
+  "P" gnus-summary-prev-group)
+
+(gnus-define-keys (gnus-summary-article-map "A" gnus-summary-mode-map)
+  " " gnus-summary-next-page
+  "n" gnus-summary-next-page
+  "\177" gnus-summary-prev-page
+  [delete] gnus-summary-prev-page
+  "p" gnus-summary-prev-page
+  "\r" gnus-summary-scroll-up
+  "\M-\r" gnus-summary-scroll-down
+  "<" gnus-summary-beginning-of-article
+  ">" gnus-summary-end-of-article
+  "b" gnus-summary-beginning-of-article
+  "e" gnus-summary-end-of-article
+  "^" gnus-summary-refer-parent-article
+  "r" gnus-summary-refer-parent-article
+  "D" gnus-summary-enter-digest-group
+  "R" gnus-summary-refer-references
+  "T" gnus-summary-refer-thread
+  "g" gnus-summary-show-article
+  "s" gnus-summary-isearch-article
+  "P" gnus-summary-print-article
+  "M" gnus-mailing-list-insinuate
+  "t" gnus-article-babel)
+
+(gnus-define-keys (gnus-summary-wash-map "W" gnus-summary-mode-map)
+  "b" gnus-article-add-buttons
+  "B" gnus-article-add-buttons-to-head
+  "o" gnus-article-treat-overstrike
+  "e" gnus-article-emphasize
+  "w" gnus-article-fill-cited-article
+  "Q" gnus-article-fill-long-lines
+  "C" gnus-article-capitalize-sentences
+  "c" gnus-article-remove-cr
+  "q" gnus-article-de-quoted-unreadable
+  "6" gnus-article-de-base64-unreadable
+  "Z" gnus-article-decode-HZ
+  "h" gnus-article-wash-html
+  "u" gnus-article-unsplit-urls
+  "s" gnus-summary-force-verify-and-decrypt
+  "f" gnus-article-display-x-face
+  "l" gnus-summary-stop-page-breaking
+  "r" gnus-summary-caesar-message
+  "m" gnus-summary-morse-message
+  "t" gnus-summary-toggle-header
+  "g" gnus-treat-smiley
+  "v" gnus-summary-verbose-headers
+  "a" gnus-article-strip-headers-in-body ;; mnemonic: wash archive
+  "p" gnus-article-verify-x-pgp-sig
+  "d" gnus-article-treat-dumbquotes)
+
+(gnus-define-keys (gnus-summary-wash-deuglify-map "Y" gnus-summary-wash-map)
+  ;; mnemonic: deuglif*Y*
+  "u" gnus-article-outlook-unwrap-lines
+  "a" gnus-article-outlook-repair-attribution
+  "c" gnus-article-outlook-rearrange-citation
+  "f" gnus-article-outlook-deuglify-article) ;; mnemonic: full deuglify
+
+(gnus-define-keys (gnus-summary-wash-hide-map "W" gnus-summary-wash-map)
+  "a" gnus-article-hide
+  "h" gnus-article-hide-headers
+  "b" gnus-article-hide-boring-headers
+  "s" gnus-article-hide-signature
+  "c" gnus-article-hide-citation
+  "C" gnus-article-hide-citation-in-followups
+  "l" gnus-article-hide-list-identifiers
+  "B" gnus-article-strip-banner
+  "P" gnus-article-hide-pem
+  "\C-c" gnus-article-hide-citation-maybe)
+
+(gnus-define-keys (gnus-summary-wash-highlight-map "H" gnus-summary-wash-map)
+  "a" gnus-article-highlight
+  "h" gnus-article-highlight-headers
+  "c" gnus-article-highlight-citation
+  "s" gnus-article-highlight-signature)
+
+(gnus-define-keys (gnus-summary-wash-header-map "G" gnus-summary-wash-map)
+  "f" gnus-article-treat-fold-headers
+  "u" gnus-article-treat-unfold-headers
+  "n" gnus-article-treat-fold-newsgroups)
+
+(gnus-define-keys (gnus-summary-wash-display-map "D" gnus-summary-wash-map)
+  "x" gnus-article-display-x-face
+  "d" gnus-article-display-face
+  "s" gnus-treat-smiley
+  "D" gnus-article-remove-images
+  "f" gnus-treat-from-picon
+  "m" gnus-treat-mail-picon
+  "n" gnus-treat-newsgroups-picon)
+
+(gnus-define-keys (gnus-summary-wash-mime-map "M" gnus-summary-wash-map)
+  "w" gnus-article-decode-mime-words
+  "c" gnus-article-decode-charset
+  "v" gnus-mime-view-all-parts
+  "b" gnus-article-view-part)
+
+(gnus-define-keys (gnus-summary-wash-time-map "T" gnus-summary-wash-map)
+  "z" gnus-article-date-ut
+  "u" gnus-article-date-ut
+  "l" gnus-article-date-local
+  "p" gnus-article-date-english
+  "e" gnus-article-date-lapsed
+  "o" gnus-article-date-original
+  "i" gnus-article-date-iso8601
+  "s" gnus-article-date-user)
+
+(gnus-define-keys (gnus-summary-wash-empty-map "E" gnus-summary-wash-map)
+  "t" gnus-article-remove-trailing-blank-lines
+  "l" gnus-article-strip-leading-blank-lines
+  "m" gnus-article-strip-multiple-blank-lines
+  "a" gnus-article-strip-blank-lines
+  "A" gnus-article-strip-all-blank-lines
+  "s" gnus-article-strip-leading-space
+  "e" gnus-article-strip-trailing-space
+  "w" gnus-article-remove-leading-whitespace)
+
+(gnus-define-keys (gnus-summary-help-map "H" gnus-summary-mode-map)
+  "v" gnus-version
+  "f" gnus-summary-fetch-faq
+  "d" gnus-summary-describe-group
+  "h" gnus-summary-describe-briefly
+  "i" gnus-info-find-node
+  "c" gnus-group-fetch-charter
+  "C" gnus-group-fetch-control)
+
+(gnus-define-keys (gnus-summary-backend-map "B" gnus-summary-mode-map)
+  "e" gnus-summary-expire-articles
+  "\M-\C-e" gnus-summary-expire-articles-now
+  "\177" gnus-summary-delete-article
+  [delete] gnus-summary-delete-article
+  [backspace] gnus-summary-delete-article
+  "m" gnus-summary-move-article
+  "r" gnus-summary-respool-article
+  "w" gnus-summary-edit-article
+  "c" gnus-summary-copy-article
+  "B" gnus-summary-crosspost-article
+  "q" gnus-summary-respool-query
+  "t" gnus-summary-respool-trace
+  "i" gnus-summary-import-article
+  "I" gnus-summary-create-article
+  "p" gnus-summary-article-posted-p)
+
+(gnus-define-keys (gnus-summary-save-map "O" gnus-summary-mode-map)
+  "o" gnus-summary-save-article
+  "m" gnus-summary-save-article-mail
+  "F" gnus-summary-write-article-file
+  "r" gnus-summary-save-article-rmail
+  "f" gnus-summary-save-article-file
+  "b" gnus-summary-save-article-body-file
+  "h" gnus-summary-save-article-folder
+  "v" gnus-summary-save-article-vm
+  "p" gnus-summary-pipe-output
+  "P" gnus-summary-muttprint
+  "s" gnus-soup-add-article)
+
+(gnus-define-keys (gnus-summary-mime-map "K" gnus-summary-mode-map)
+  "b" gnus-summary-display-buttonized
+  "m" gnus-summary-repair-multipart
+  "v" gnus-article-view-part
+  "o" gnus-article-save-part
+  "c" gnus-article-copy-part
+  "C" gnus-article-view-part-as-charset
+  "e" gnus-article-view-part-externally
+  "E" gnus-article-encrypt-body
+  "i" gnus-article-inline-part
+  "|" gnus-article-pipe-part)
+
+(gnus-define-keys (gnus-uu-mark-map "P" gnus-summary-mark-map)
+  "p" gnus-summary-mark-as-processable
+  "u" gnus-summary-unmark-as-processable
+  "U" gnus-summary-unmark-all-processable
+  "v" gnus-uu-mark-over
+  "s" gnus-uu-mark-series
+  "r" gnus-uu-mark-region
+  "g" gnus-uu-unmark-region
+  "R" gnus-uu-mark-by-regexp
+  "G" gnus-uu-unmark-by-regexp
+  "t" gnus-uu-mark-thread
+  "T" gnus-uu-unmark-thread
+  "a" gnus-uu-mark-all
+  "b" gnus-uu-mark-buffer
+  "S" gnus-uu-mark-sparse
+  "k" gnus-summary-kill-process-mark
+  "y" gnus-summary-yank-process-mark
+  "w" gnus-summary-save-process-mark
+  "i" gnus-uu-invert-processable)
+
+(gnus-define-keys (gnus-uu-extract-map "X" gnus-summary-mode-map)
+  ;;"x" gnus-uu-extract-any
+  "m" gnus-summary-save-parts
+  "u" gnus-uu-decode-uu
+  "U" gnus-uu-decode-uu-and-save
+  "s" gnus-uu-decode-unshar
+  "S" gnus-uu-decode-unshar-and-save
+  "o" gnus-uu-decode-save
+  "O" gnus-uu-decode-save
+  "b" gnus-uu-decode-binhex
+  "B" gnus-uu-decode-binhex
+  "p" gnus-uu-decode-postscript
+  "P" gnus-uu-decode-postscript-and-save)
+
+(gnus-define-keys
+    (gnus-uu-extract-view-map "v" gnus-uu-extract-map)
+  "u" gnus-uu-decode-uu-view
+  "U" gnus-uu-decode-uu-and-save-view
+  "s" gnus-uu-decode-unshar-view
+  "S" gnus-uu-decode-unshar-and-save-view
+  "o" gnus-uu-decode-save-view
+  "O" gnus-uu-decode-save-view
+  "b" gnus-uu-decode-binhex-view
+  "B" gnus-uu-decode-binhex-view
+  "p" gnus-uu-decode-postscript-view
+  "P" gnus-uu-decode-postscript-and-save-view)
 
 (defvar gnus-article-post-menu nil)
 
@@ -2030,7 +2071,6 @@ increase the score of each group you read."
              ["Signature" gnus-article-hide-signature t]
              ["Citation" gnus-article-hide-citation t]
              ["List identifiers" gnus-article-hide-list-identifiers t]
-             ["PGP" gnus-article-hide-pgp t]
              ["Banner" gnus-article-strip-banner t]
              ["Boring headers" gnus-article-hide-boring-headers t])
             ("Highlight"
@@ -2047,7 +2087,18 @@ increase the score of each group you read."
              ["View all" gnus-mime-view-all-parts t]
              ["Verify and Decrypt" gnus-summary-force-verify-and-decrypt t]
              ["Encrypt body" gnus-article-encrypt-body t]
-             ["Extract all parts" gnus-summary-save-parts t])
+             ["Extract all parts" gnus-summary-save-parts t]
+             ("Multipart"
+              ["Repair multipart" gnus-summary-repair-multipart t]
+              ["Add buttons" gnus-summary-display-buttonized t]
+              ["Pipe part" gnus-article-pipe-part t]
+              ["Inline part" gnus-article-inline-part t]
+              ["Encrypt body" gnus-article-encrypt-body t]
+              ["View part externally" gnus-article-view-part-externally t]
+              ["View part with charset" gnus-article-view-part-as-charset t]
+              ["Copy part" gnus-article-copy-part t]
+              ["Save part" gnus-article-save-part t]
+              ["View part" gnus-article-view-part t]))
             ("Date"
              ["Local" gnus-article-date-local t]
              ["ISO8601" gnus-article-date-iso8601 t]
@@ -2119,9 +2170,9 @@ gnus-summary-show-article-from-menu-as-charset-%s" cs))))
              ["Verify X-PGP-Sig" gnus-article-verify-x-pgp-sig t]
              ["HZ" gnus-article-decode-HZ t]
              ("(Outlook) Deuglify"
-              ["Unwrap lines" gnus-outlook-unwrap-lines t]
-              ["Repair attribution" gnus-outlook-repair-attribution t]
-              ["Rearrange citation" gnus-outlook-rearrange-citation t]
+              ["Unwrap lines" gnus-article-outlook-unwrap-lines t]
+              ["Repair attribution" gnus-article-outlook-repair-attribution t]
+              ["Rearrange citation" gnus-article-outlook-rearrange-citation t]
               ["Full (Outlook) deuglify"
                gnus-article-outlook-deuglify-article t])
              )
@@ -2293,7 +2344,8 @@ gnus-summary-show-article-from-menu-as-charset-%s" cs))))
         ["Catchup all" gnus-summary-catchup-all t]
         ["Catchup to here" gnus-summary-catchup-to-here t]
         ["Catchup from here" gnus-summary-catchup-from-here t]
-        ["Catchup region" gnus-summary-mark-region-as-read t]
+        ["Catchup region" gnus-summary-mark-region-as-read 
+         (gnus-mark-active-p)]
         ["Mark excluded" gnus-summary-limit-mark-excluded-as-read t])
        ("Mark Various"
         ["Tick" gnus-summary-tick-article-forward t]
@@ -2327,8 +2379,8 @@ gnus-summary-show-article-from-menu-as-charset-%s" cs))))
         ["Remove all marks" gnus-summary-unmark-all-processable t]
         ["Mark above" gnus-uu-mark-over t]
         ["Mark series" gnus-uu-mark-series t]
-        ["Mark region" gnus-uu-mark-region t]
-        ["Unmark region" gnus-uu-unmark-region t]
+        ["Mark region" gnus-uu-mark-region (gnus-mark-active-p)]
+        ["Unmark region" gnus-uu-unmark-region (gnus-mark-active-p)]
         ["Mark by regexp..." gnus-uu-mark-by-regexp t]
         ["Unmark by regexp..." gnus-uu-unmark-by-regexp t]
         ["Mark all" gnus-uu-mark-all t]
@@ -2340,7 +2392,8 @@ gnus-summary-show-article-from-menu-as-charset-%s" cs))))
          ["Kill" gnus-summary-kill-process-mark t]
          ["Yank" gnus-summary-yank-process-mark
           gnus-newsgroup-process-stack]
-         ["Save" gnus-summary-save-process-mark t]))
+         ["Save" gnus-summary-save-process-mark t]
+         ["Run command on marked..." gnus-summary-universal-argument t]))
        ("Scroll article"
         ["Page forward" gnus-summary-next-page
          ,@(if (featurep 'xemacs) '(t)
@@ -2395,7 +2448,7 @@ gnus-summary-show-article-from-menu-as-charset-%s" cs))))
        ["See old articles" gnus-summary-insert-old-articles t]
        ["See new articles" gnus-summary-insert-new-articles t]
        ["Filter articles..." gnus-summary-execute-command t]
-       ["Run command on subjects..." gnus-summary-universal-argument t]
+       ["Run command on articles..." gnus-summary-universal-argument t]
        ["Search articles forward..." gnus-summary-search-article-forward t]
        ["Search articles backward..." gnus-summary-search-article-backward t]
        ["Toggle line truncation" gnus-summary-toggle-truncation t]
@@ -3003,10 +3056,6 @@ display only a single character."
                                               (point)
                                               (current-buffer))))))
 
-(defun gnus-summary-buffer-name (group)
-  "Return the summary buffer name of GROUP."
-  (concat "*Summary " (gnus-group-decoded-name group) "*"))
-
 (defun gnus-summary-setup-buffer (group)
   "Initialize summary buffer."
   (let ((buffer (gnus-summary-buffer-name group))
@@ -3245,11 +3294,11 @@ buffer that was in action when the last article was fetched."
       (setq gnus-tmp-lines -1))
     (if (= gnus-tmp-lines -1)
        (setq gnus-tmp-lines "?")
-      (setq gnus-tmp-lines (number-to-string gnus-tmp-lines)))
-    (gnus-put-text-property
+      (setq gnus-tmp-lines (number-to-string gnus-tmp-lines))) 
+      (gnus-put-text-property
      (point)
      (progn (eval gnus-summary-line-format-spec) (point))
-     'gnus-number gnus-tmp-number)
+       'gnus-number gnus-tmp-number)
     (when (gnus-visual-p 'summary-highlight 'highlight)
       (forward-line -1)
       (gnus-run-hooks 'gnus-summary-update-hook)
@@ -3515,7 +3564,8 @@ If NO-DISPLAY, don't generate a summary buffer."
          (gnus-summary-position-point)
          (gnus-configure-windows 'summary 'force)
          (gnus-set-mode-line 'summary))
-       (when (get-buffer-window gnus-group-buffer t)
+       (when (and gnus-auto-center-group
+                  (get-buffer-window gnus-group-buffer t))
          ;; Gotta use windows, because recenter does weird stuff if
          ;; the current buffer ain't the displayed window.
          (let ((owin (selected-window)))
@@ -4023,40 +4073,41 @@ the id of the parent article (if any)."
     (gnus-summary-goto-subject article)
     (let* ((datal (gnus-data-find-list article))
           (data (car datal))
-          (length (when (cdr datal)
-                    (- (gnus-data-pos data)
-                       (gnus-data-pos (cadr datal)))))
           (buffer-read-only nil)
           (level (gnus-summary-thread-level)))
       (gnus-delete-line)
-      (gnus-summary-insert-line
-       header level nil 
-       (memq article gnus-newsgroup-undownloaded)
-       (gnus-article-mark article)
-       (memq article gnus-newsgroup-replied)
-       (memq article gnus-newsgroup-expirable)
-       ;; Only insert the Subject string when it's different
-       ;; from the previous Subject string.
-       (if (and
-           gnus-show-threads
-           (gnus-subject-equal
-            (condition-case ()
-                (mail-header-subject
-                 (gnus-data-header
-                  (cadr
-                   (gnus-data-find-list
-                    article
-                    (gnus-data-list t)))))
-              ;; Error on the side of excessive subjects.
-              (error ""))
-            (mail-header-subject header)))
-          ""
-        (mail-header-subject header))
-       nil (cdr (assq article gnus-newsgroup-scored))
-       (memq article gnus-newsgroup-processable))
-      (when length
-       (gnus-data-update-list
-        (cdr datal) (- length (- (gnus-data-pos data) (point))))))))
+      (let ((inserted (- (point)
+                         (progn
+                           (gnus-summary-insert-line
+                            header level nil 
+                            (memq article gnus-newsgroup-undownloaded)
+                            (gnus-article-mark article)
+                            (memq article gnus-newsgroup-replied)
+                            (memq article gnus-newsgroup-expirable)
+                            ;; Only insert the Subject string when it's different
+                            ;; from the previous Subject string.
+                            (if (and
+                                 gnus-show-threads
+                                 (gnus-subject-equal
+                                  (condition-case ()
+                                      (mail-header-subject
+                                       (gnus-data-header
+                                        (cadr
+                                         (gnus-data-find-list
+                                          article
+                                          (gnus-data-list t)))))
+                                    ;; Error on the side of excessive subjects.
+                                    (error ""))
+                                  (mail-header-subject header)))
+                                ""
+                              (mail-header-subject header))
+                            nil (cdr (assq article gnus-newsgroup-scored))
+                            (memq article gnus-newsgroup-processable))
+                           (point)))))
+        (when (cdr datal)
+          (gnus-data-update-list
+           (cdr datal) 
+           (- (gnus-data-pos data) (gnus-data-pos (cadr datal)) inserted)))))))
 
 (defun gnus-summary-update-article (article &optional iheader)
   "Update ARTICLE in the summary buffer."
@@ -4540,7 +4591,8 @@ or a straight list of headers."
        gnus-tmp-number gnus-tmp-opening-bracket gnus-tmp-closing-bracket
        tree-stack)
 
-    (setq gnus-tmp-prev-subject nil)
+    (setq gnus-tmp-prev-subject nil
+          gnus-tmp-thread-tree-header-string "")
 
     (if (vectorp (car threads))
        ;; If this is a straight (sic) list of headers, then a
@@ -4782,10 +4834,10 @@ or a straight list of headers."
            (if (= gnus-tmp-lines -1)
                (setq gnus-tmp-lines "?")
              (setq gnus-tmp-lines (number-to-string gnus-tmp-lines)))
-           (gnus-put-text-property
+              (gnus-put-text-property
             (point)
             (progn (eval gnus-summary-line-format-spec) (point))
-            'gnus-number number)
+               'gnus-number number)
            (when gnus-visual-p
              (forward-line -1)
              (gnus-run-hooks 'gnus-summary-update-hook)
@@ -4921,13 +4973,13 @@ If SELECT-ARTICLES, only select those articles from GROUP."
        (gnus-activate-group group)     ; Or we can activate it...
        (progn                          ; Or we bug out.
          (when (equal major-mode 'gnus-summary-mode)
-           (kill-buffer (current-buffer)))
+           (gnus-kill-buffer (current-buffer)))
          (error "Couldn't activate group %s: %s"
                 group (gnus-status-message group))))
 
     (unless (gnus-request-group group t)
       (when (equal major-mode 'gnus-summary-mode)
-       (kill-buffer (current-buffer)))
+       (gnus-kill-buffer (current-buffer)))
       (error "Couldn't request group %s: %s"
             group (gnus-status-message group)))
 
@@ -5212,10 +5264,10 @@ If SELECT-ARTICLES, only select those articles from GROUP."
       (setq gnus-newsgroup-unselected
            (gnus-sorted-difference gnus-newsgroup-unreads articles))
       (when gnus-alter-articles-to-read-function
-       (setq gnus-newsgroup-unreads
+       (setq articles
              (sort
               (funcall gnus-alter-articles-to-read-function
-                       gnus-newsgroup-name gnus-newsgroup-unreads)
+                       gnus-newsgroup-name articles)
               '<)))
       articles)))
 
@@ -5830,8 +5882,7 @@ This is meant to be called in `gnus-article-internal-prepare-hook'."
                           (looking-at "Xref:"))
                      (search-forward "\nXref:" nil t))
              (goto-char (1+ (match-end 0)))
-             (setq xref (buffer-substring (point)
-                                          (progn (end-of-line) (point))))
+             (setq xref (buffer-substring (point) (gnus-point-at-eol)))
              (mail-header-set-xref headers xref)))))))
 
 (defun gnus-summary-insert-subject (id &optional old-header use-old-header)
@@ -5993,52 +6044,68 @@ If EXCLUDE-GROUP, do not go to this group."
     (save-excursion
       (gnus-group-best-unread-group exclude-group))))
 
-(defun gnus-summary-find-next (&optional unread article backward undownloaded)
-  (if backward (gnus-summary-find-prev)
+(defun gnus-summary-find-next (&optional unread article backward)
+  (if backward (gnus-summary-find-prev unread article)
     (let* ((dummy (gnus-summary-article-intangible-p))
           (article (or article (gnus-summary-article-number)))
-          (arts (gnus-data-find-list article))
+          (data (gnus-data-find-list article))
           result)
       (when (and (not dummy)
                 (or (not gnus-summary-check-current)
                     (not unread)
-                    (not (gnus-data-unread-p (car arts)))))
-       (setq arts (cdr arts)))
+                    (not (gnus-data-unread-p (car data)))))
+       (setq data (cdr data)))
       (when (setq result
                  (if unread
                      (progn
-                       (while arts
-                         (when (or (and undownloaded
-                                        (memq (car arts) gnus-newsgroup-undownloaded))
-                                   (gnus-data-unread-p (car arts)))
-                           (setq result (car arts)
-                                 arts nil))
-                         (setq arts (cdr arts)))
+                       (while data
+                          (unless (memq (gnus-data-number (car data)) 
+                                        (cond ((eq gnus-auto-goto-ignores 'always-undownloaded)
+                                               gnus-newsgroup-undownloaded)
+                                              (gnus-plugged
+                                               nil)
+                                              ((eq gnus-auto-goto-ignores 'unfetched)
+                                               gnus-newsgroup-unfetched)
+                                              ((eq gnus-auto-goto-ignores 'undownloaded)
+                                               gnus-newsgroup-undownloaded)))
+                            (when (gnus-data-unread-p (car data))
+                              (setq result (car data)
+                                    data nil)))
+                         (setq data (cdr data)))
                        result)
-                   (car arts)))
+                   (car data)))
        (goto-char (gnus-data-pos result))
        (gnus-data-number result)))))
 
 (defun gnus-summary-find-prev (&optional unread article)
   (let* ((eobp (eobp))
         (article (or article (gnus-summary-article-number)))
-        (arts (gnus-data-find-list article (gnus-data-list 'rev)))
+        (data (gnus-data-find-list article (gnus-data-list 'rev)))
         result)
     (when (and (not eobp)
               (or (not gnus-summary-check-current)
                   (not unread)
-                  (not (gnus-data-unread-p (car arts)))))
-      (setq arts (cdr arts)))
+                  (not (gnus-data-unread-p (car data)))))
+      (setq data (cdr data)))
     (when (setq result
                (if unread
                    (progn
-                     (while arts
-                       (when (gnus-data-unread-p (car arts))
-                         (setq result (car arts)
-                               arts nil))
-                       (setq arts (cdr arts)))
+                     (while data
+                        (unless (memq (gnus-data-number (car data))
+                                      (cond ((eq gnus-auto-goto-ignores 'always-undownloaded)
+                                             gnus-newsgroup-undownloaded)
+                                            (gnus-plugged
+                                             nil)
+                                            ((eq gnus-auto-goto-ignores 'unfetched)
+                                             gnus-newsgroup-unfetched)
+                                            ((eq gnus-auto-goto-ignores 'undownloaded)
+                                             gnus-newsgroup-undownloaded)))
+                          (when (gnus-data-unread-p (car data))
+                            (setq result (car data)
+                                  data nil)))
+                       (setq data (cdr data)))
                      result)
-                 (car arts)))
+                 (car data)))
       (goto-char (gnus-data-pos result))
       (gnus-data-number result))))
 
@@ -6087,23 +6154,23 @@ Also do horizontal recentering."
 If `gnus-auto-center-summary' is nil, or the article buffer isn't
 displayed, no centering will be performed."
   ;; Suggested by earle@mahendo.JPL.NASA.GOV (Greg Earle).
-;; Recenter only when requested.  Suggested by popovich@park.cs.columbia.edu.
+  ;; Recenter only when requested.  Suggested by popovich@park.cs.columbia.edu.
   (interactive)
-  (let* ((top (cond ((< (window-height) 4) 0)
-                   ((< (window-height) 7) 1)
-                   (t (if (numberp gnus-auto-center-summary)
-                          gnus-auto-center-summary
-                        2))))
-        (height (1- (window-height)))
-        (bottom (save-excursion (goto-char (point-max))
-                                (forward-line (- height))
-                                (point)))
-        (window (get-buffer-window (current-buffer))))
-    ;; The user has to want it.
-    (when gnus-auto-center-summary
+  ;; The user has to want it.
+  (when gnus-auto-center-summary
+    (let* ((top (cond ((< (window-height) 4) 0)
+                     ((< (window-height) 7) 1)
+                     (t (if (numberp gnus-auto-center-summary)
+                            gnus-auto-center-summary
+                          2))))
+          (height (1- (window-height)))
+          (bottom (save-excursion (goto-char (point-max))
+                                  (forward-line (- height))
+                                  (point)))
+          (window (get-buffer-window (current-buffer))))
       (when (get-buffer-window gnus-article-buffer)
        ;; Only do recentering when the article buffer is displayed,
-      ;; Set the window start to either `bottom', which is the biggest
+       ;; Set the window start to either `bottom', which is the biggest
        ;; possible valid number, or the second line from the top,
        ;; whichever is the least.
        (let ((top-pos (save-excursion (forward-line (- top)) (point))))
@@ -6434,14 +6501,13 @@ If FORCE (the prefix), also save the .newsrc file(s)."
   (interactive)
   (let* ((group gnus-newsgroup-name)
         (gnus-group-is-exiting-p t)
+        (gnus-group-is-exiting-without-update-p t)
         (quit-config (gnus-group-quit-config group)))
     (when (or no-questions
              gnus-expert-user
              (gnus-y-or-n-p "Discard changes to this group and exit? "))
       (gnus-async-halt-prefetch)
-      (mapcar 'funcall
-             (delq 'gnus-summary-expire-articles
-                   (copy-sequence gnus-summary-prepare-exit-hook)))
+      (run-hooks 'gnus-summary-prepare-exit-hook)
       (when (gnus-buffer-live-p gnus-article-buffer)
        (save-excursion
          (set-buffer gnus-article-buffer)
@@ -6464,8 +6530,7 @@ If FORCE (the prefix), also save the .newsrc file(s)."
        (gnus-summary-clear-local-variables)
        (let ((gnus-summary-local-variables gnus-newsgroup-variables))
          (gnus-summary-clear-local-variables))
-       (when (get-buffer gnus-summary-buffer)
-         (kill-buffer gnus-summary-buffer)))
+       (gnus-kill-buffer gnus-summary-buffer))
       (unless gnus-single-article-buffer
        (setq gnus-article-current nil))
       (when gnus-use-trees
@@ -6635,7 +6700,7 @@ in."
 (defun gnus-summary-next-group (&optional no-article target-group backward)
   "Exit current newsgroup and then select next unread newsgroup.
 If prefix argument NO-ARTICLE is non-nil, no article is selected
-initially.  If NEXT-GROUP, go to this group.  If BACKWARD, go to
+initially.  If TARGET-GROUP, go to this group.  If BACKWARD, go to
 previous group instead."
   (interactive "P")
   ;; Stop pre-fetching.
@@ -6643,6 +6708,11 @@ previous group instead."
   (let ((current-group gnus-newsgroup-name)
        (current-buffer (current-buffer))
        entered)
+    ;; First we semi-exit this group to update Xrefs and all variables.
+    ;; We can't do a real exit, because the window conf must remain
+    ;; the same in case the user is prompted for info, and we don't
+    ;; want the window conf to change before that...
+    (gnus-summary-exit t)
     (while (not entered)
       ;; Then we find what group we are supposed to enter.
       (set-buffer gnus-group-buffer)
@@ -6667,20 +6737,10 @@ previous group instead."
        (let ((unreads (gnus-group-group-unread)))
          (if (and (or (eq t unreads)
                       (and unreads (not (zerop unreads))))
-                  (progn
-                    ;; Now we semi-exit this group to update Xrefs
-                    ;; and all variables.  We can't do a real exit,
-                    ;; because the window conf must remain the same
-                    ;; in case the user is prompted for info, and we
-                    ;; don't want the window conf to change before
-                    ;; that...
-                    (when (gnus-buffer-live-p current-buffer)
-                      (set-buffer current-buffer)
-                      (gnus-summary-exit t))
-                    (gnus-summary-read-group
-                     target-group nil no-article
-                     (and (buffer-name current-buffer) current-buffer)
-                     nil backward)))
+                  (gnus-summary-read-group
+                   target-group nil no-article
+                   (and (buffer-name current-buffer) current-buffer)
+                   nil backward))
              (setq entered t)
            (setq current-group target-group
                  target-group nil)))))))
@@ -6694,42 +6754,55 @@ If prefix argument NO-ARTICLE is non-nil, no article is selected initially."
 ;; Walking around summary lines.
 
 (defun gnus-summary-first-subject (&optional unread undownloaded unseen)
-  "Go to the first unread subject.
-If UNREAD is non-nil, go to the first unread article.
-Returns the article selected or nil if there are no unread articles."
+  "Go to the first subject satisfying any non-nil constraint.
+If UNREAD is non-nil, the article should be unread.
+If UNDOWNLOADED is non-nil, the article should be undownloaded.
+If UNSEED is non-nil, the article should be unseen.
+Returns the article selected or nil if there are no matching articles."
   (interactive "P")
-  (prog1
-      (cond
-       ;; Empty summary.
-       ((null gnus-newsgroup-data)
-       (gnus-message 3 "No articles in the group")
-       nil)
-       ;; Pick the first article.
-       ((not unread)
-       (goto-char (gnus-data-pos (car gnus-newsgroup-data)))
-       (gnus-data-number (car gnus-newsgroup-data)))
-       ;; No unread articles.
-       ((null gnus-newsgroup-unreads)
-       (gnus-message 3 "No more unread articles")
-       nil)
-       ;; Find the first unread article.
-       (t
-       (let ((data gnus-newsgroup-data))
-         (while (and data
-                     (and (not (and undownloaded
-                                    (memq (car data)
-                                          gnus-newsgroup-undownloaded)))
-                          (if unseen
-                              (or (not (memq
-                                        (gnus-data-number (car data))
-                                        gnus-newsgroup-unseen))
-                                  (not (gnus-data-unread-p (car data))))
-                            (not (gnus-data-unread-p (car data))))))
-           (setq data (cdr data)))
-         (when data
-           (goto-char (gnus-data-pos (car data)))
-           (gnus-data-number (car data))))))
-    (gnus-summary-position-point)))
+  (cond
+   ;; Empty summary.
+   ((null gnus-newsgroup-data)
+    (gnus-message 3 "No articles in the group")
+    nil)
+   ;; Pick the first article.
+   ((not (or unread undownloaded unseen))
+    (goto-char (gnus-data-pos (car gnus-newsgroup-data)))
+    (gnus-data-number (car gnus-newsgroup-data)))
+   ;; Find the first unread article.
+   (t
+    (let ((data gnus-newsgroup-data))
+      (while (and data
+                  (let ((num (gnus-data-number (car data))))
+                    (or (memq num gnus-newsgroup-unfetched)
+                        (not (or (and unread
+                                      (memq num gnus-newsgroup-unreads))
+                                 (and undownloaded
+                                      (memq num gnus-newsgroup-undownloaded))
+                                 (and unseen
+                                      (memq num gnus-newsgroup-unseen)))))))
+        (setq data (cdr data)))
+      (prog1 
+          (if data
+              (progn
+                (goto-char (gnus-data-pos (car data)))
+                (gnus-data-number (car data)))
+            (gnus-message 3 "No more%s articles"
+                          (let* ((r (when unread " unread"))
+                                 (d (when undownloaded " undownloaded"))
+                                 (s (when unseen " unseen"))
+                                 (l (delq nil (list r d s))))
+                            (cond ((= 3 (length l))
+                                   (concat r "," d ", or" s))
+                                  ((= 2 (length l))
+                                   (concat (car l) ", or" (cadr l)))
+                                  ((= 1 (length l))
+                                   (car l))
+                                  (t
+                                   ""))))
+            nil
+            )
+        (gnus-summary-position-point))))))
 
 (defun gnus-summary-next-subject (n &optional unread dont-display)
   "Go to next N'th summary line.
@@ -6777,7 +6850,7 @@ If optional argument UNREAD is non-nil, only unread article is selected."
       (gnus-summary-goto-subject article t)))
   (gnus-summary-limit (append articles gnus-newsgroup-limit))
   (gnus-summary-position-point))
-  
 (defun gnus-summary-goto-subject (article &optional force silent)
   "Go the subject line of ARTICLE.
 If FORCE, also allow jumping to articles not currently shown."
@@ -6886,6 +6959,7 @@ be displayed."
        'old))))
 
 (defun gnus-summary-force-verify-and-decrypt ()
+  "Display buttons for signed/encrypted parts and verify/decrypt them."
   (interactive)
   (let ((mm-verify-option 'known)
        (mm-decrypt-option 'known)
@@ -7063,7 +7137,8 @@ If STOP is non-nil, just stop when reaching the end of the message."
          (gnus-summary-display-article article)
        (when article-window
          (gnus-eval-in-buffer-window gnus-article-buffer
-           (setq endp (gnus-article-next-page lines)))
+           (setq endp (or (gnus-article-next-page lines)
+                          (gnus-article-only-boring-p))))
          (when endp
            (cond (stop
                   (gnus-message 3 "End of message"))
@@ -7184,19 +7259,20 @@ Return nil if there are no unread articles."
 Return nil if there are no unseen articles."
   (interactive)
   (prog1
-      (when (gnus-summary-first-subject t t t)
+      (when (gnus-summary-first-subject nil nil t)
        (gnus-summary-show-thread)
-       (gnus-summary-first-subject t t t))
+       (gnus-summary-first-subject nil nil t))
     (gnus-summary-position-point)))
 
 (defun gnus-summary-first-unseen-or-unread-subject ()
-  "Place the point on the subject line of the first unseen article.
-Return nil if there are no unseen articles."
+  "Place the point on the subject line of the first unseen article or,
+if all article have been seen, on the subject line of the first unread
+article."
   (interactive)
   (prog1
-      (unless (when (gnus-summary-first-subject t t t)
+      (unless (when (gnus-summary-first-subject nil nil t)
                (gnus-summary-show-thread)
-               (gnus-summary-first-subject t t t))
+               (gnus-summary-first-subject nil nil t))
        (when (gnus-summary-first-subject t)
          (gnus-summary-show-thread)
          (gnus-summary-first-subject t)))
@@ -7918,16 +7994,21 @@ of what's specified by the `gnus-refer-thread-limit' variable."
   (let ((id (mail-header-id (gnus-summary-article-header)))
        (limit (if limit (prefix-numeric-value limit)
                 gnus-refer-thread-limit)))
-    ;; We want to fetch LIMIT *old* headers, but we also have to
-    ;; re-fetch all the headers in the current buffer, because many of
-    ;; them may be undisplayed.  So we adjust LIMIT.
-    (when (numberp limit)
-      (incf limit (- gnus-newsgroup-end gnus-newsgroup-begin)))
     (unless (eq gnus-fetch-old-headers 'invisible)
       (gnus-message 5 "Fetching headers for %s..." gnus-newsgroup-name)
       ;; Retrieve the headers and read them in.
-      (if (eq (gnus-retrieve-headers
-              (list gnus-newsgroup-end) gnus-newsgroup-name limit)
+      (if (eq (if (numberp limit)
+                 (gnus-retrieve-headers
+                  (list (min
+                         (+ (mail-header-number
+                             (gnus-summary-article-header))
+                            limit)
+                         gnus-newsgroup-end))
+                  gnus-newsgroup-name (* limit 2))
+               ;; gnus-refer-thread-limit is t, i.e. fetch _all_
+               ;; headers.
+               (gnus-retrieve-headers (list gnus-newsgroup-end)
+                                      gnus-newsgroup-name limit))
              'nov)
          (gnus-build-all-threads)
        (error "Can't fetch thread from backends that don't support NOV"))
@@ -7967,9 +8048,10 @@ of what's specified by the `gnus-refer-thread-limit' variable."
        ;; We fetch the article.
        (catch 'found
          (dolist (gnus-override-method (gnus-refer-article-methods))
-           (gnus-check-server gnus-override-method)
-           ;; Fetch the header, and display the article.
-           (when (setq number (gnus-summary-insert-subject message-id))
+           (when (and (gnus-check-server gnus-override-method)
+                      ;; Fetch the header,
+                      (setq number (gnus-summary-insert-subject message-id)))
+             ;; and display the article.
              (gnus-summary-select-article nil nil nil number)
              (throw 'found t)))
          (gnus-message 3 "Couldn't fetch article %s" message-id)))))))
@@ -8177,6 +8259,12 @@ Optional argument BACKWARD means do search for backward.
        (gnus-use-article-prefetch nil)
        (gnus-xmas-force-redisplay nil) ;Inhibit XEmacs redisplay.
        (gnus-use-trees nil)            ;Inhibit updating tree buffer.
+       (gnus-visual nil)
+       (gnus-keep-backlog nil)
+       (gnus-break-pages nil)
+       (gnus-summary-display-arrow nil)
+       (gnus-updated-mode-lines nil)
+       (gnus-auto-center-summary nil)
        (sum (current-buffer))
        (gnus-display-mime-function nil)
        (found nil)
@@ -8517,7 +8605,7 @@ If ARG is a negative number, hide the unwanted header lines."
                      (1- (point))
                    (point-max))))
        (insert-buffer-substring gnus-original-article-buffer s e)
-       (article-decode-encoded-words)
+       (run-hooks 'gnus-article-decode-hook)
        (if hidden
            (let ((gnus-treat-hide-headers nil)
                  (gnus-treat-hide-boring-headers nil))
@@ -8732,7 +8820,14 @@ ACTION can be either `move' (the default), `crosspost' or `copy'."
        ((eq art-group 'junk)
        (when (eq action 'move)
          (gnus-summary-mark-article article gnus-canceled-mark)
-         (gnus-message 4 "Deleted article %s" article)))
+         (gnus-message 4 "Deleted article %s" article)
+         ;; run the delete hook
+         (run-hook-with-args 'gnus-summary-article-delete-hook
+                             action
+                             (gnus-data-header
+                              (assoc article (gnus-data-list nil)))
+                             gnus-newsgroup-name nil
+                             select-method)))
        (t
        (let* ((pto-group (gnus-group-prefixed-name
                           (car art-group) to-method))
@@ -8810,11 +8905,20 @@ ACTION can be either `move' (the default), `crosspost' or `copy'."
              (gnus-request-article-this-buffer article gnus-newsgroup-name)
              (nnheader-replace-header "Xref" new-xref)
              (gnus-request-replace-article
-              article gnus-newsgroup-name (current-buffer)))))
+              article gnus-newsgroup-name (current-buffer))))
+
+         ;; run the move/copy/crosspost/respool hook
+         (run-hook-with-args 'gnus-summary-article-move-hook 
+                             action
+                             (gnus-data-header 
+                              (assoc article (gnus-data-list nil)))
+                             gnus-newsgroup-name
+                             to-newsgroup
+                             select-method))
 
        ;;;!!!Why is this necessary?
        (set-buffer gnus-summary-buffer)
-
+       
        (gnus-summary-goto-subject article)
        (when (eq action 'move)
          (gnus-summary-mark-article article gnus-canceled-mark))))
@@ -8986,8 +9090,9 @@ This will be the case if the article has both been mailed and posted."
 (defun gnus-summary-expire-articles (&optional now)
   "Expire all articles that are marked as expirable in the current group."
   (interactive)
-  (when (gnus-check-backend-function
-        'request-expire-articles gnus-newsgroup-name)
+  (when (and (not gnus-group-is-exiting-without-update-p)
+            (gnus-check-backend-function
+             'request-expire-articles gnus-newsgroup-name))
     ;; This backend supports expiry.
     (let* ((total (gnus-group-total-expirable-p gnus-newsgroup-name))
           (expirable (if total
@@ -9031,7 +9136,14 @@ This will be the case if the article has both been mailed and posted."
              (dolist (article expirable)
                (when (and (not (memq article es))
                           (gnus-data-find article))
-                 (gnus-summary-mark-article article gnus-canceled-mark))))))
+                 (gnus-summary-mark-article article gnus-canceled-mark)
+                 (run-hook-with-args 'gnus-summary-article-expire-hook
+                                     'delete
+                                     (gnus-data-header
+                                      (assoc article (gnus-data-list nil)))
+                                     gnus-newsgroup-name
+                                     nil
+                                     nil))))))
        (gnus-message 6 "Expiring articles...done")))))
 
 (defun gnus-summary-expire-articles-now ()
@@ -9080,6 +9192,12 @@ delete these instead."
        ;; after all.
        (unless (memq (car articles) not-deleted)
          (gnus-summary-mark-article (car articles) gnus-canceled-mark))
+       (let* ((article (car articles))
+              (id (mail-header-id (gnus-data-header 
+                                   (assoc article (gnus-data-list nil))))))
+         (run-hook-with-args 'gnus-summary-article-delete-hook
+                             'delete id gnus-newsgroup-name nil
+                             nil))
        (setq articles (cdr articles)))
       (when not-deleted
        (gnus-message 4 "Couldn't delete articles %s" not-deleted)))
@@ -9428,6 +9546,8 @@ ARTICLE can also be a list of articles."
   (interactive (list (gnus-summary-article-number)))
   (let ((articles (if (listp article) article (list article))))
     (dolist (article articles)
+      (unless (numberp article)
+       (error "%s is not a number" article))
       (push article gnus-newsgroup-replied)
       (let ((buffer-read-only nil))
        (when (gnus-summary-goto-subject article nil t)
@@ -9687,7 +9807,7 @@ If NO-EXPIRE, auto-expiry will be inhibited."
   t)
 
 (defun gnus-summary-update-download-mark (article)
-  "Update the secondary (read, process, cache) mark."
+  "Update the download mark."
   (gnus-summary-update-mark
    (cond ((memq article gnus-newsgroup-undownloaded) 
           gnus-undownloaded-mark)
@@ -9975,7 +10095,11 @@ The number of articles marked as read is returned."
                  (setq gnus-newsgroup-marked nil
                        gnus-newsgroup-spam-marked nil
                        gnus-newsgroup-dormant nil))
-               (setq gnus-newsgroup-unreads gnus-newsgroup-downloadable))
+               (setq gnus-newsgroup-unreads
+                     (gnus-sorted-nunion
+                       (gnus-intersection gnus-newsgroup-unreads
+                                          gnus-newsgroup-downloadable)
+                       gnus-newsgroup-unfetched)))
            ;; We actually mark all articles as canceled, which we
            ;; have to do when using auto-expiry or adaptive scoring.
            (gnus-summary-show-all-threads)
@@ -9984,12 +10108,12 @@ The number of articles marked as read is returned."
                  (goto-char to-here)
                  (while (and
                          (gnus-summary-mark-article-as-read gnus-catchup-mark)
-                         (gnus-summary-find-next (not all) nil nil t))))
-             (when (gnus-summary-first-subject (not all) t)
+                         (gnus-summary-find-next (not all)))))
+             (when (gnus-summary-first-subject (not all))
                (while (and
                        (if to-here (< (point) to-here) t)
                        (gnus-summary-mark-article-as-read gnus-catchup-mark)
-                       (gnus-summary-find-next (not all) nil nil t)))))
+                       (gnus-summary-find-next (not all))))))
            (gnus-set-mode-line 'summary))
          t))
     (gnus-summary-position-point)))
@@ -10208,8 +10332,8 @@ Returns nil if no thread was there to be shown."
   (interactive)
   (let ((buffer-read-only nil)
        (orig (point))
-       ;; first goto end then to beg, to have point at beg after let
-       (end (progn (end-of-line) (point)))
+       (end (gnus-point-at-eol))
+       ;; Leave point at bol
        (beg (progn (beginning-of-line) (point))))
     (prog1
        ;; Any hidden lines here?
@@ -10960,8 +11084,8 @@ If REVERSE, save parts that do not match TYPE."
   ;; Added by Per Abrahamsen <amanda@iesd.auc.dk>.
   (when gnus-summary-selected-face
     (save-excursion
-      (let* ((beg (progn (beginning-of-line) (point)))
-            (end (progn (end-of-line) (point)))
+      (let* ((beg (gnus-point-at-bol))
+            (end (gnus-point-at-eol))
             ;; Fix by Mike Dugan <dugan@bucrf16.bu.edu>.
             (from (if (get-text-property beg gnus-mouse-face-prop)
                       beg