T-gnus 6.15.18 revision 00.
[elisp/gnus.git-] / lisp / gnus-sum.el
index a7dae60..6624e04 100644 (file)
@@ -1,5 +1,5 @@
 ;;; gnus-sum.el --- summary mode commands for Semi-gnus
-;; Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001
+;; Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
 ;;        Free Software Foundation, Inc.
 
 ;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
 
 ;;; Code:
 
-(eval-when-compile (require 'cl))
-(eval-when-compile (require 'gnus-clfns))
+(eval-when-compile
+  (require 'cl)
+  (require 'gnus-clfns)
+  (defvar tool-bar-map))
 
 (require 'gnus)
 (require 'gnus-group)
 
 (autoload 'gnus-summary-limit-include-cached "gnus-cache" nil t)
 (autoload 'gnus-cache-write-active "gnus-cache")
-(autoload 'gnus-set-summary-default-charset "gnus-i18n" nil t)
 (autoload 'gnus-mailing-list-insinuate "gnus-ml" nil t)
 (autoload 'turn-on-gnus-mailing-list-mode "gnus-ml" nil t)
 (autoload 'mm-uu-dissect "mm-uu")
+(autoload 'gnus-article-outlook-deuglify-article "deuglify"
+  "Deuglify broken Outlook (Express) articles and redisplay."
+  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.
@@ -118,6 +125,11 @@ given by the `gnus-summary-same-subject' variable.)"
                 (const adopt)
                 (const empty)))
 
+(defcustom gnus-summary-make-false-root-always nil
+  "Always make a false dummy root."
+  :group 'gnus-thread
+  :type 'boolean)
+
 (defcustom gnus-summary-gather-exclude-subject "^ *$\\|^(none)$"
   "*A regexp to match subjects to be excluded from loose thread gathering.
 As loose thread gathering is done on subjects only, that means that
@@ -145,13 +157,14 @@ comparing subjects."
   "List of functions taking a string argument that simplify subjects.
 The functions are applied recursively.
 
-Useful functions to put in this list include: `gnus-simplify-subject-re',
-`gnus-simplify-subject-fuzzy' and `gnus-simplify-whitespace'."
+Useful functions to put in this list include:
+`gnus-simplify-subject-re', `gnus-simplify-subject-fuzzy',
+`gnus-simplify-whitespace', and `gnus-simplify-all-whitespace'."
   :group 'gnus-thread
   :type '(repeat function))
 
 (defcustom gnus-simplify-ignored-prefixes nil
-  "*Regexp, matches for which are removed from subject lines when simplifying fuzzily."
+  "*Remove matches for this regexp from subject lines when simplifying fuzzily."
   :group 'gnus-thread
   :type '(choice (const :tag "off" nil)
                 regexp))
@@ -193,7 +206,7 @@ This applies to marking commands as well as other commands that
 the end of an article.
 
 If nil, the marking commands do NOT go to the next unread article
-(they go to the next article instead).  If `never', commands that
+\(they go to the next article instead).  If `never', commands that
 usually go to the next unread article, will go to the next article,
 whether it is read or not."
   :group 'gnus-summary-marks
@@ -246,6 +259,7 @@ simplification is selected."
 
 (defcustom gnus-thread-hide-subtree nil
   "*If non-nil, hide all threads initially.
+This can be a predicate specifier which says which threads to hide.
 If threads are hidden, you have to run the command
 `gnus-summary-show-thread' by hand or use `gnus-select-article-hook'
 to expose hidden threads."
@@ -306,13 +320,16 @@ This variable can either be the symbols `first' (place point on the
 first subject), `unread' (place point on the subject line of the first
 unread article), `best' (place point on the subject line of the
 higest-scored article), `unseen' (place point on the subject line of
-the first unseen article), or a function to be called to place point on
-some subject line.."
+the first unseen article), 'unseen-or-unread' (place 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), or a function to be called to
+place point on some subject line."
   :group 'gnus-group-select
   :type '(choice (const best)
                 (const unread)
                 (const first)
-                (const unseen)))
+                (const unseen)
+                (const unseen-or-unread)))
 
 (defcustom gnus-dont-select-after-jump-to-other-group nil
   "If non-nil, don't select the first unread article after entering the
@@ -325,13 +342,13 @@ or not."
 (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)
@@ -347,6 +364,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
@@ -364,6 +398,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
@@ -440,6 +477,11 @@ this variable specifies group names."
   :group 'gnus-summary-marks
   :type 'character)
 
+(defcustom gnus-spam-mark ?$
+  "*Mark used for spam articles."
+  :group 'gnus-summary-marks
+  :type 'character)
+
 (defcustom gnus-souped-mark ?F
   "*Mark used for souped articles."
   :group 'gnus-summary-marks
@@ -515,11 +557,16 @@ this variable specifies group names."
   :group 'gnus-summary-marks
   :type 'character)
 
-(defcustom gnus-undownloaded-mark ?@
+(defcustom gnus-undownloaded-mark ?-
   "*Mark used for articles that weren't downloaded."
   :group 'gnus-summary-marks
   :type 'character)
 
+(defcustom gnus-downloaded-mark ?+
+  "*Mark used for articles that were downloaded."
+  :group 'gnus-summary-marks
+  :type 'character)
+
 (defcustom gnus-downloadable-mark ?%
   "*Mark used for articles that are to be downloaded."
   :group 'gnus-summary-marks
@@ -592,12 +639,16 @@ list of parameters to that command."
   :type 'boolean)
 
 (defcustom gnus-summary-dummy-line-format
-  "  %(:                          :%) %S\n"
+  "   %(:                             :%) %S\n"
   "*The format specification for the dummy roots in the summary buffer.
 It works along the same lines as a normal formatting string,
 with some simple extensions.
 
-%S  The subject"
+%S  The subject
+
+General format specifiers can also be used.
+See `(gnus)Formatting Variables'."
+  :link '(custom-manual "(gnus)Formatting Variables")
   :group 'gnus-threading
   :type 'string)
 
@@ -655,7 +706,8 @@ was sent, sorting by number means sorting by arrival time.)
 
 Ready-made functions include `gnus-article-sort-by-number',
 `gnus-article-sort-by-author', `gnus-article-sort-by-subject',
-`gnus-article-sort-by-date' and `gnus-article-sort-by-score'.
+`gnus-article-sort-by-date', `gnus-article-sort-by-random'
+and `gnus-article-sort-by-score'.
 
 When threading is turned on, the variable `gnus-thread-sort-functions'
 controls how articles are sorted."
@@ -665,6 +717,7 @@ controls how articles are sorted."
                         (function-item gnus-article-sort-by-subject)
                         (function-item gnus-article-sort-by-date)
                         (function-item gnus-article-sort-by-score)
+                        (function-item gnus-article-sort-by-random)
                         (function :tag "other"))))
 
 (defcustom gnus-thread-sort-functions '(gnus-thread-sort-by-number)
@@ -682,7 +735,10 @@ was sent, sorting by number means sorting by arrival time.)
 
 Ready-made functions include `gnus-thread-sort-by-number',
 `gnus-thread-sort-by-author', `gnus-thread-sort-by-subject',
-`gnus-thread-sort-by-date', `gnus-thread-sort-by-score' and
+`gnus-thread-sort-by-date', `gnus-thread-sort-by-score',
+`gnus-thread-sort-by-most-recent-number',
+`gnus-thread-sort-by-most-recent-date',
+`gnus-thread-sort-by-random', and
 `gnus-thread-sort-by-total-score' (see `gnus-thread-score-function').
 
 When threading is turned off, the variable
@@ -694,6 +750,7 @@ When threading is turned off, the variable
                         (function-item gnus-thread-sort-by-date)
                         (function-item gnus-thread-sort-by-score)
                         (function-item gnus-thread-sort-by-total-score)
+                        (function-item gnus-thread-sort-by-random)
                         (function :tag "other"))))
 
 (defcustom gnus-thread-score-function '+
@@ -774,21 +831,21 @@ 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
-       (lambda ()
-         (mapcar (lambda (header)
-                    (mail-header-set-subject
-                     header
-                     (gnus-simplify-subject
-                      (mail-header-subject header) 're-only)))
-                 gnus-newsgroup-headers))))"
+ (add-hook gnus-select-group-hook
+          (lambda ()
+            (mapcar (lambda (header)
+                      (mail-header-set-subject
+                       header
+                       (gnus-simplify-subject
+                        (mail-header-subject header) 're-only)))
+                    gnus-newsgroup-headers)))"
   :group 'gnus-group-select
   :type 'hook)
 
 (defcustom gnus-select-article-hook nil
   "*A hook called when an article is selected."
   :group 'gnus-summary-choose
+  :options '(gnus-agent-fetch-selected-article)
   :type 'hook)
 
 (defcustom gnus-visual-mark-article-hook
@@ -799,7 +856,7 @@ is not run if `gnus-visual' is nil."
   :group 'gnus-summary-visual
   :type 'hook)
 
-(defcustom gnus-parse-headers-hook '(gnus-set-summary-default-charset)
+(defcustom gnus-parse-headers-hook '(gnus-summary-inherit-default-charset)
   "*A hook called before parsing the headers."
   :group 'gnus-various
   :type 'hook)
@@ -838,6 +895,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))
@@ -851,43 +923,40 @@ automatically when it is selected."
   :group 'gnus-summary-visual
   :type 'face)
 
+(defvar gnus-tmp-downloaded nil)
+
 (defcustom gnus-summary-highlight
-  '(((= mark gnus-canceled-mark)
+  '(((eq mark gnus-canceled-mark)
      . gnus-summary-cancelled-face)
+    ((and uncached (> score default-high))
+     . gnus-summary-high-undownloaded-face)
+    ((and uncached (< score default-low))
+     . gnus-summary-low-undownloaded-face)
+    (uncached
+     . gnus-summary-normal-undownloaded-face)
     ((and (> score default-high)
-         (or (= mark gnus-dormant-mark)
-             (= mark gnus-ticked-mark)))
+         (or (eq mark gnus-dormant-mark)
+             (eq mark gnus-ticked-mark)))
      . gnus-summary-high-ticked-face)
     ((and (< score default-low)
-         (or (= mark gnus-dormant-mark)
-             (= mark gnus-ticked-mark)))
+         (or (eq mark gnus-dormant-mark)
+             (eq mark gnus-ticked-mark)))
      . gnus-summary-low-ticked-face)
-    ((or (= mark gnus-dormant-mark)
-        (= mark gnus-ticked-mark))
+    ((or (eq mark gnus-dormant-mark)
+        (eq mark gnus-ticked-mark))
      . gnus-summary-normal-ticked-face)
-    ((and (> score default-high) (= mark gnus-ancient-mark))
+    ((and (> score default-high) (eq mark gnus-ancient-mark))
      . gnus-summary-high-ancient-face)
-    ((and (< score default-low) (= mark gnus-ancient-mark))
+    ((and (< score default-low) (eq mark gnus-ancient-mark))
      . gnus-summary-low-ancient-face)
-    ((= mark gnus-ancient-mark)
+    ((eq mark gnus-ancient-mark)
      . gnus-summary-normal-ancient-face)
-    ((and (> score default-high) (= mark gnus-unread-mark))
+    ((and (> score default-high) (eq mark gnus-unread-mark))
      . gnus-summary-high-unread-face)
-    ((and (< score default-low) (= mark gnus-unread-mark))
+    ((and (< score default-low) (eq mark gnus-unread-mark))
      . gnus-summary-low-unread-face)
-    ((= mark gnus-unread-mark)
+    ((eq mark gnus-unread-mark)
      . gnus-summary-normal-unread-face)
-    ((and (> score default-high) (memq mark (list gnus-downloadable-mark
-                                                 gnus-undownloaded-mark)))
-     . gnus-summary-high-unread-face)
-    ((and (< score default-low) (memq mark (list gnus-downloadable-mark
-                                                gnus-undownloaded-mark)))
-     . gnus-summary-low-unread-face)
-    ((and (memq mark (list gnus-downloadable-mark gnus-undownloaded-mark))
-         (memq article gnus-newsgroup-unreads))
-     . gnus-summary-normal-unread-face)
-    ((memq mark (list gnus-downloadable-mark gnus-undownloaded-mark))
-     . gnus-summary-normal-read-face)
     ((> score default-high)
      . gnus-summary-high-read-face)
     ((< score default-low)
@@ -916,13 +985,16 @@ 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
   (mime-find-field-decoder 'From 'nov)
   "Variable that says which function should be used to decode a string with encoded words.")
 
-(defcustom gnus-extra-headers nil
+(defcustom gnus-extra-headers '(To Newsgroups)
   "*Extra headers to parse."
   :version "21.1"
   :group 'gnus-summary
@@ -1027,17 +1099,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."
-  :group 'gnus-summary
-  :type 'regexp)
-
-
-(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)
 
@@ -1051,9 +1116,28 @@ that were fetched.  Say, for nnultimate groups."
 
 (defcustom gnus-summary-muttprint-program "muttprint"
   "Command (and optional arguments) used to run Muttprint."
+  :version "21.3"
   :group 'gnus-summary
   :type 'string)
 
+(defcustom gnus-article-loose-mime nil
+  "If non-nil, don't require MIME-Version header.
+Some brain-damaged MUA/MTA, e.g. Lotus Domino 5.0.6 clients, does not
+supply the MIME-Version header or deliberately strip it From the mail.
+Set it to non-nil, Gnus will treat some articles as MIME even if
+the MIME-Version header is missed."
+  :version "21.3"
+  :type 'boolean
+  :group 'gnus-article-mime)
+
+(defcustom gnus-article-emulate-mime t
+  "If non-nil, use MIME emulation for uuencode and the like.
+This means that Gnus will search message bodies for text that look
+like uuencoded bits, yEncoded bits, and so on, and present that using
+the normal Gnus MIME machinery."
+  :type 'boolean
+  :group 'gnus-article-mime)
+
 ;;; Internal variables
 
 (defvar gnus-summary-display-cache nil)
@@ -1063,7 +1147,6 @@ that were fetched.  Say, for nnultimate groups."
 (defvar gnus-article-ignored-charsets nil)
 (defvar gnus-scores-exclude-files nil)
 (defvar gnus-page-broken nil)
-(defvar gnus-inhibit-mime-unbuttonizing nil)
 
 (defvar gnus-original-article nil)
 (defvar gnus-article-internal-prepare-hook nil)
@@ -1077,9 +1160,6 @@ that were fetched.  Say, for nnultimate groups."
 (defvar gnus-summary-save-parts-type-history nil)
 (defvar gnus-summary-save-parts-last-directory nil)
 
-(defvar gnus-summary-save-parts-type-history nil)
-(defvar gnus-summary-save-parts-last-directory nil)
-
 ;; Avoid highlighting in kill files.
 (defvar gnus-summary-inhibit-highlight nil)
 (defvar gnus-newsgroup-selected-overlay nil)
@@ -1115,7 +1195,9 @@ that were fetched.  Say, for nnultimate groups."
     (?M ,(macroexpand '(mail-header-id gnus-tmp-header)) ?s)
     (?r ,(macroexpand '(mail-header-references gnus-tmp-header)) ?s)
     (?c (or (mail-header-chars gnus-tmp-header) 0) ?d)
+    (?k (gnus-summary-line-message-size gnus-tmp-header) ?s)
     (?L gnus-tmp-lines ?s)
+    (?O gnus-tmp-downloaded ?c)
     (?I gnus-tmp-indentation ?s)
     (?T (if (= gnus-tmp-level 0) "" (make-string (frame-width) ? )) ?s)
     (?R gnus-tmp-replied ?c)
@@ -1163,6 +1245,7 @@ the type of the variable (string, integer, character, etc).")
     (?u gnus-tmp-user-defined ?s)
     (?d (length gnus-newsgroup-dormant) ?d)
     (?t (length gnus-newsgroup-marked) ?d)
+    (?h (length gnus-newsgroup-spam-marked) ?d)
     (?r (length gnus-newsgroup-reads) ?d)
     (?z (gnus-summary-article-score gnus-tmp-article-number) ?d)
     (?E gnus-newsgroup-expunged-tally ?d)
@@ -1179,6 +1262,8 @@ end position and text.")
 (defvar gnus-last-shell-command nil
   "Default shell command on article.")
 
+(defvar gnus-newsgroup-agentized nil
+  "Locally bound in each summary buffer to indicate whether the server has been agentized.")
 (defvar gnus-newsgroup-begin nil)
 (defvar gnus-newsgroup-end nil)
 (defvar gnus-newsgroup-last-rmail nil)
@@ -1194,10 +1279,10 @@ end position and text.")
 (defvar gnus-newsgroup-limits nil)
 
 (defvar gnus-newsgroup-unreads nil
-  "List of unread articles in the current newsgroup.")
+  "Sorted list of unread articles in the current newsgroup.")
 
 (defvar gnus-newsgroup-unselected nil
-  "List of unselected unread articles in the current newsgroup.")
+  "Sorted list of unselected unread articles in the current newsgroup.")
 
 (defvar gnus-newsgroup-reads nil
   "Alist of read articles and article marks in the current newsgroup.")
@@ -1205,13 +1290,16 @@ end position and text.")
 (defvar gnus-newsgroup-expunged-tally nil)
 
 (defvar gnus-newsgroup-marked nil
-  "List of ticked articles in the current newsgroup (a subset of unread art).")
+  "Sorted list of ticked articles in the current newsgroup (a subset of unread art).")
+
+(defvar gnus-newsgroup-spam-marked nil
+  "List of ranges of articles that have been marked as spam.")
 
 (defvar gnus-newsgroup-killed nil
   "List of ranges of articles that have been through the scoring process.")
 
 (defvar gnus-newsgroup-cached nil
-  "List of articles that come from the article cache.")
+  "Sorted list of articles that come from the article cache.")
 
 (defvar gnus-newsgroup-saved nil
   "List of articles that have been saved.")
@@ -1228,16 +1316,22 @@ end position and text.")
   "List of articles that have are recent in the current newsgroup.")
 
 (defvar gnus-newsgroup-expirable nil
-  "List of articles in the current newsgroup that can be expired.")
+  "Sorted list of articles in the current newsgroup that can be expired.")
 
 (defvar gnus-newsgroup-processable nil
   "List of articles in the current newsgroup that can be processed.")
 
 (defvar gnus-newsgroup-downloadable nil
-  "List of articles in the current newsgroup that can be processed.")
+  "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.")
@@ -1246,7 +1340,7 @@ end position and text.")
   "List of articles in the current newsgroup that have bookmarks.")
 
 (defvar gnus-newsgroup-dormant nil
-  "List of dormant articles in the current newsgroup.")
+  "Sorted list of dormant articles in the current newsgroup.")
 
 (defvar gnus-newsgroup-unseen nil
   "List of unseen articles in the current newsgroup.")
@@ -1295,12 +1389,14 @@ end position and text.")
     gnus-newsgroup-last-folder gnus-newsgroup-last-file
     gnus-newsgroup-auto-expire gnus-newsgroup-unreads
     gnus-newsgroup-unselected gnus-newsgroup-marked
+    gnus-newsgroup-spam-marked
     gnus-newsgroup-reads gnus-newsgroup-saved
     gnus-newsgroup-replied gnus-newsgroup-forwarded
     gnus-newsgroup-recent
     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
@@ -1344,25 +1440,44 @@ buffers. For example:
 ")
 
 ;; Byte-compiler warning.
-(eval-when-compile (defvar gnus-article-mode-map))
+(eval-when-compile
+  ;; Bind features so that require will believe that gnus-sum has
+  ;; already been loaded (avoids infinite recursion)
+  (let ((features (cons 'gnus-sum features)))
+    ;; Several of the declarations in gnus-sum are needed to load the
+    ;; following files. Right now, these definitions have been
+    ;; compiled but not defined (evaluated).  We could either do a
+    ;; eval-and-compile about all of the declarations or evaluate the
+    ;; source file.
+    (if (boundp 'gnus-newsgroup-variables)
+        nil
+      (load "gnus-sum.el" t t t))
+    (require 'gnus)
+    (require 'gnus-agent)
+    (require 'gnus-art)))
 
 ;; Subject simplification.
 
 (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."
+  (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."
@@ -1440,7 +1555,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))
@@ -1456,7 +1571,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)
@@ -1481,372 +1596,461 @@ 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
-    "=" 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
-    "\M-t" gnus-summary-toggle-mime
-    "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-article-toggle-headers
-    "g" gnus-summary-show-article
-    "l" gnus-summary-goto-last-article
-    "v" gnus-summary-preview-mime-message
-    "\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
-    "\C-c\C-n" gnus-namazu-search
-    "*" 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
-
-    "V" gnus-summary-score-map
-    "X" gnus-uu-extract-map
-    "S" gnus-summary-send-map)
+;; 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
+  "\M-t" gnus-summary-toggle-mime
+  "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
+  "v" gnus-summary-preview-mime-message
+  "\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
+  "\C-c\C-n" gnus-namazu-search
+  "*" 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
+
+  "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
-    "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)
-
-  (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
-    "J" gnus-summary-jump-to-other-group
-    "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
-    "Z" gnus-article-decode-HZ
-    "f" gnus-article-display-x-face
-    "l" gnus-summary-stop-page-breaking
-    "r" gnus-summary-caesar-message
-    "t" gnus-article-toggle-headers
-    "g" gnus-summary-toggle-smiley
-    "u" gnus-article-treat-unfold-headers
-    "n" gnus-article-treat-fold-newsgroups
-    "v" gnus-summary-verbose-headers
-    "m" gnus-summary-toggle-mime
-    "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-hide-map "W" gnus-summary-wash-map)
-    "a" gnus-article-hide
-    "h" gnus-article-toggle-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-display-map "D" gnus-summary-wash-map)
-    "x" gnus-article-display-x-face
-    "s" gnus-summary-toggle-smiley
-    "f" gnus-treat-from-picon
-    "m" gnus-treat-mail-picon
-    "n" gnus-treat-newsgroups-picon)
-
-  (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)
-
-  (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-externalize-part
-    "E" gnus-article-encrypt-body
-    "i" gnus-article-inline-part
-    "|" gnus-article-pipe-part))
+(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
+  "J" gnus-summary-jump-to-other-group
+  "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
+  "Z" gnus-article-decode-HZ
+  "h" gnus-article-wash-html
+  "u" gnus-article-unsplit-urls
+  "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
+  "m" gnus-summary-toggle-mime
+  "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-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)
 
+(defconst gnus-summary-menu-maxlen 20)
+
+(defun gnus-summary-menu-split (menu)
+  ;; If we have lots of elements, divide them into groups of 20
+  ;; and make a pane (or submenu) for each one.
+  (if (> (length menu) (/ (* gnus-summary-menu-maxlen 3) 2))
+      (let ((menu menu) sublists next
+           (i 1))
+       (while menu
+         ;; Pull off the next gnus-summary-menu-maxlen elements
+         ;; and make them the next element of sublist.
+         (setq next (nthcdr gnus-summary-menu-maxlen menu))
+         (if next
+             (setcdr (nthcdr (1- gnus-summary-menu-maxlen) menu)
+                     nil))
+         (setq sublists (cons (cons (format "%s ... %s" (aref (car menu) 0)
+                                            (aref (car (last menu)) 0)) menu)
+                              sublists))
+         (setq i (1+ i))
+         (setq menu next))
+       (nreverse sublists))
+    ;; Few elements--put them all in one pane.
+    menu))
+
 (defun gnus-summary-make-menu-bar ()
   (gnus-turn-off-edit-menu 'summary)
 
@@ -1885,11 +2089,10 @@ increase the score of each group you read."
     (let ((innards
           `(("Hide"
              ["All" gnus-article-hide t]
-             ["Headers" gnus-article-toggle-headers t]
+             ["Headers" gnus-article-hide-headers t]
              ["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"
@@ -1905,11 +2108,33 @@ increase the score of each group you read."
              ["Lapsed" gnus-article-date-lapsed t]
              ["User-defined" gnus-article-date-user t])
             ("Display"
-             ["Toggle smiley" gnus-summary-toggle-smiley t]
+             ["Remove images" gnus-article-remove-images t]
+             ["Toggle smiley" gnus-treat-smiley t]
              ["Show X-Face" gnus-article-display-x-face t]
              ["Show picons in From" gnus-treat-from-picon t]
              ["Show picons in mail headers" gnus-treat-mail-picon t]
-             ["Show picons in news headers" gnus-treat-newsgroups-picon t])
+             ["Show picons in news headers" gnus-treat-newsgroups-picon t]
+             ("View as different encoding"
+              ,@(gnus-summary-menu-split
+                 (mapcar
+                  (lambda (cs)
+                    ;; Since easymenu under FSF Emacs doesn't allow lambda
+                    ;; forms for menu commands, we should provide intern'ed
+                    ;; function symbols.
+                    (let ((command (intern (format "\
+gnus-summary-show-article-from-menu-as-charset-%s" cs))))
+                      (fset command
+                            `(lambda ()
+                               (interactive)
+                               (let ((gnus-summary-show-article-charset-alist
+                                      '((1 . ,cs))))
+                                 (gnus-summary-show-article 1))))
+                      `[,(symbol-name cs) ,command t]))
+                  (sort (if (fboundp 'coding-system-list)
+                            (coding-system-list)
+                          ;;(mapcar 'car mm-mime-mule-charset-alist)
+                          )
+                        'string<)))))
             ("Washing"
              ("Remove Blanks"
               ["Leading" gnus-article-strip-leading-blank-lines t]
@@ -1931,7 +2156,8 @@ increase the score of each group you read."
              ["Rot 13" gnus-summary-caesar-message
               ,@(if (featurep 'xemacs) '(t)
                   '(:help "\"Caesar rotate\" article by 13"))]
-             ["Unix pipe" gnus-summary-pipe-message t]
+             ["Morse decode" gnus-summary-morse-message t]
+             ["Unix pipe..." gnus-summary-pipe-message t]
              ["Add buttons" gnus-article-add-buttons t]
              ["Add buttons to head" gnus-article-add-buttons-to-head t]
              ["Stop page breaking" gnus-summary-stop-page-breaking t]
@@ -1940,8 +2166,17 @@ increase the score of each group you read."
              ["Toggle header" gnus-summary-toggle-header t]
              ["Unfold headers" gnus-article-treat-unfold-headers t]
              ["Fold newsgroups" gnus-article-treat-fold-newsgroups t]
+             ["Html" gnus-article-wash-html t]
+             ["URLs" gnus-article-unsplit-urls t]
              ["Verify X-PGP-Sig" gnus-article-verify-x-pgp-sig t]
-             ["HZ" gnus-article-decode-HZ t])
+             ["HZ" gnus-article-decode-HZ t]
+             ("(Outlook) Deuglify"
+              ["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])
+             )
             ("Output"
              ["Save in default format" gnus-summary-save-article
               ,@(if (featurep 'xemacs) '(t)
@@ -1967,8 +2202,12 @@ increase the score of each group you read."
              ["Crosspost article..." gnus-summary-crosspost-article
               (gnus-check-backend-function
                'request-replace-article gnus-newsgroup-name)]
-             ["Import file..." gnus-summary-import-article t]
-             ["Create article..." gnus-summary-create-article t]
+             ["Import file..." gnus-summary-import-article
+              (gnus-check-backend-function
+               'request-accept-article gnus-newsgroup-name)]
+             ["Create article..." gnus-summary-create-article
+              (gnus-check-backend-function
+               'request-accept-article gnus-newsgroup-name)]
              ["Check if posted" gnus-summary-article-posted-p t]
              ["Edit article" gnus-summary-edit-article
               (not (gnus-group-read-only-p))]
@@ -2005,7 +2244,7 @@ increase the score of each group you read."
             ["Fetch article with id..." gnus-summary-refer-article t]
             ["Setup Mailing List Params" gnus-mailing-list-insinuate t]
             ["Redisplay" gnus-summary-show-article t]
-            ["Raw article" gnus-summary-show-raw-article t])))
+            ["Raw article" gnus-summary-show-raw-article :keys "C-u g"])))
       (easy-menu-define
        gnus-summary-article-menu gnus-summary-mode-map ""
        (cons "Article" innards))
@@ -2023,6 +2262,7 @@ increase the score of each group you read."
     (easy-menu-define
      gnus-summary-thread-menu gnus-summary-mode-map ""
      '("Threads"
+       ["Find all messages in thread" gnus-summary-refer-thread t]
        ["Toggle threading" gnus-summary-toggle-threads t]
        ["Hide threads" gnus-summary-hide-all-threads t]
        ["Show threads" gnus-summary-show-all-threads t]
@@ -2060,11 +2300,16 @@ increase the score of each group you read."
        ["Wide reply and yank" gnus-summary-wide-reply-with-original
        ,@(if (featurep 'xemacs) '(t)
            '(:help "Mail a reply, quoting this article"))]
+       ["Very wide reply" gnus-summary-very-wide-reply t]
+       ["Very wide reply and yank" gnus-summary-very-wide-reply-with-original
+       ,@(if (featurep 'xemacs) '(t)
+           '(:help "Mail a very wide reply, quoting this article"))]
        ["Mail forward" gnus-summary-mail-forward t]
        ["Post forward" gnus-summary-post-forward t]
        ["Digest and mail" gnus-summary-digest-mail-forward t]
        ["Digest and post" gnus-summary-digest-post-forward t]
        ["Resend message" gnus-summary-resend-message t]
+       ["Resend message edit" gnus-summary-resend-message-edit t]
        ["Send bounced mail" gnus-summary-resend-bounced-mail t]
        ["Send a mail" gnus-summary-mail-other-window t]
        ["Create a local message" gnus-summary-news-other-window t]
@@ -2103,7 +2348,8 @@ increase the score of each group you read."
        ["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]
@@ -2118,11 +2364,12 @@ increase the score of each group you read."
        ["Author..." gnus-summary-limit-to-author t]
        ["Age..." gnus-summary-limit-to-age t]
        ["Extra..." gnus-summary-limit-to-extra t]
-       ["Score" gnus-summary-limit-to-score t]
+       ["Score..." gnus-summary-limit-to-score t]
        ["Display Predicate" gnus-summary-limit-to-display-predicate t]
        ["Unread" gnus-summary-limit-to-unread t]
+       ["Unseen" gnus-summary-limit-to-unseen t]
        ["Non-dormant" gnus-summary-limit-exclude-dormant t]
-       ["Articles" gnus-summary-limit-to-articles t]
+       ["Next articles" gnus-summary-limit-to-articles t]
        ["Pop limit" gnus-summary-pop-limit t]
        ["Show dormant" gnus-summary-limit-include-dormant t]
        ["Hide childless dormant"
@@ -2136,8 +2383,8 @@ increase the score of each group you read."
        ["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]
@@ -2149,7 +2396,8 @@ increase the score of each group you read."
         ["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)
@@ -2181,10 +2429,17 @@ increase the score of each group you read."
        ["Sort by score" gnus-summary-sort-by-score t]
        ["Sort by lines" gnus-summary-sort-by-lines t]
        ["Sort by characters" gnus-summary-sort-by-chars t]
+       ["Randomize" gnus-summary-sort-by-random t]
        ["Original sort" gnus-summary-sort-by-original t])
        ("Help"
        ["Fetch group FAQ" gnus-summary-fetch-faq t]
        ["Describe group" gnus-summary-describe-group t]
+       ["Fetch charter" gnus-group-fetch-charter
+        ,@(if (featurep 'xemacs) nil
+            '(:help "Display the charter of the current group"))]
+       ["Fetch control message" gnus-group-fetch-control
+        ,@(if (featurep 'xemacs) nil
+            '(:help "Display the archived control message for the current group"))]
        ["Read manual" gnus-info-find-node t])
        ("Modes"
        ["Pick and read" gnus-pick-mode t]
@@ -2192,11 +2447,12 @@ increase the score of each group you read."
        ("Regeneration"
        ["Regenerate" gnus-summary-prepare t]
        ["Insert cached articles" gnus-summary-insert-cached-articles t]
+       ["Insert dormant articles" gnus-summary-insert-dormant-articles t]
        ["Toggle threading" gnus-summary-toggle-threads t])
        ["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]
@@ -2598,6 +2854,7 @@ The following commands are available:
 (defun gnus-article-read-p (article)
   "Say whether ARTICLE is read or not."
   (not (or (memq article gnus-newsgroup-marked)
+          (memq article gnus-newsgroup-spam-marked)
           (memq article gnus-newsgroup-unreads)
           (memq article gnus-newsgroup-unselected)
           (memq article gnus-newsgroup-dormant))))
@@ -2606,7 +2863,7 @@ The following commands are available:
 
 (defmacro gnus-summary-article-number ()
   "The article number of the article on the current line.
-If there isn's an article number here, then we return the current
+If there isn't an article number here, then we return the current
 article number."
   '(progn
      (gnus-summary-skip-intangible)
@@ -2688,6 +2945,7 @@ article number."
 This is all marks except unread, ticked, dormant, and expirable."
   (not (or (= mark gnus-unread-mark)
           (= mark gnus-ticked-mark)
+          (= mark gnus-spam-mark)
           (= mark gnus-dormant-mark)
           (= mark gnus-expirable-mark))))
 
@@ -2699,10 +2957,10 @@ time; i.e., when generating the summary lines.  After that,
 marks of articles."
   `(cond
     ((memq ,number gnus-newsgroup-unsendable) gnus-unsendable-mark)
-    ((memq ,number gnus-newsgroup-undownloaded) gnus-undownloaded-mark)
     ((memq ,number gnus-newsgroup-downloadable) gnus-downloadable-mark)
     ((memq ,number gnus-newsgroup-unreads) gnus-unread-mark)
     ((memq ,number gnus-newsgroup-marked) gnus-ticked-mark)
+    ((memq ,number gnus-newsgroup-spam-marked) gnus-spam-mark)
     ((memq ,number gnus-newsgroup-dormant) gnus-dormant-mark)
     ((memq ,number gnus-newsgroup-expirable) gnus-expirable-mark)
     (t (or (cdr (assq ,number gnus-newsgroup-reads))
@@ -2804,13 +3062,14 @@ 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)))
+  (let ((buffer (gnus-summary-buffer-name group))
+       (dead-name (concat "*Dead Summary "
+                          (gnus-group-decoded-name group) "*")))
+    ;; If a dead summary buffer exists, we kill it.
+    (when (gnus-buffer-live-p dead-name)
+      (gnus-kill-buffer dead-name))
     (if (get-buffer buffer)
        (progn
          (set-buffer buffer)
@@ -2838,6 +3097,7 @@ buffer that was in action when the last article was fetched."
     (setq gnus-summary-buffer (current-buffer))
     (let ((name gnus-newsgroup-name)
          (marked gnus-newsgroup-marked)
+         (spam gnus-newsgroup-spam-marked)
          (unread gnus-newsgroup-unreads)
          (headers gnus-current-headers)
          (data gnus-newsgroup-data)
@@ -2860,6 +3120,7 @@ buffer that was in action when the last article was fetched."
        (set-buffer gnus-group-buffer)
        (setq gnus-newsgroup-name name
              gnus-newsgroup-marked marked
+             gnus-newsgroup-spam-marked spam
              gnus-newsgroup-unreads unread
              gnus-current-headers headers
              gnus-newsgroup-data data
@@ -2917,31 +3178,33 @@ buffer that was in action when the last article was fetched."
     (let ((gnus-replied-mark 129)
          (gnus-score-below-mark 130)
          (gnus-score-over-mark 130)
-         (gnus-download-mark 131)
+         (gnus-undownloaded-mark 131)
          (spec gnus-summary-line-format-spec)
          gnus-visual pos)
       (save-excursion
        (gnus-set-work-buffer)
        (let ((gnus-summary-line-format-spec spec)
-             (gnus-newsgroup-downloadable '((0 . t))))
+             (gnus-newsgroup-downloadable '(0)))
          (gnus-summary-insert-line
           (make-full-mail-header 0 "" "nobody"
                                  "05 Apr 2001 23:33:09 +0400"
                                  "" "" 0 0 "" nil)
-          0 nil 128 t nil "" nil 1)
+          0 nil t 128 t nil "" nil 1)
          (goto-char (point-min))
          (setq pos (list (cons 'unread (and (search-forward "\200" nil t)
-                                            (- (point) 2)))))
+                                            (- (point) (point-min) 1)))))
          (goto-char (point-min))
          (push (cons 'replied (and (search-forward "\201" nil t)
-                                   (- (point) 2)))
+                                   (- (point) (point-min) 1)))
                pos)
          (goto-char (point-min))
-         (push (cons 'score (and (search-forward "\202" nil t) (- (point) 2)))
+         (push (cons 'score (and (search-forward "\202" nil t)
+                                 (- (point) (point-min) 1)))
                pos)
          (goto-char (point-min))
          (push (cons 'download
-                     (and (search-forward "\203" nil t) (- (point) 2)))
+                     (and (search-forward "\203" nil t)
+                          (- (point) (point-min) 1)))
                pos)))
       (setq gnus-summary-mark-positions pos))))
 
@@ -2970,15 +3233,16 @@ buffer that was in action when the last article was fetched."
            (cond
             ((setq to (cdr (assq 'To extra-headers)))
              (concat "-> "
-                     (gnus-summary-extract-address-component
-                      (funcall gnus-decode-encoded-word-function to))))
+                     (inline
+                       (gnus-summary-extract-address-component
+                        (funcall gnus-decode-encoded-word-function to)))))
             ((setq newsgroups (cdr (assq 'Newsgroups extra-headers)))
              (concat "=> " newsgroups)))))
-     (gnus-summary-extract-address-component gnus-tmp-from))))
+     (inline (gnus-summary-extract-address-component gnus-tmp-from)))))
 
 (defun gnus-summary-insert-line (gnus-tmp-header
                                 gnus-tmp-level gnus-tmp-current
-                                gnus-tmp-unread gnus-tmp-replied
+                                undownloaded gnus-tmp-unread gnus-tmp-replied
                                 gnus-tmp-expirable gnus-tmp-subject-or-nil
                                 &optional gnus-tmp-dummy gnus-tmp-score
                                 gnus-tmp-process)
@@ -3007,6 +3271,13 @@ buffer that was in action when the last article was fetched."
                ((memq gnus-tmp-number gnus-newsgroup-unseen)
                 gnus-unseen-mark)
                (t gnus-no-mark)))
+        (gnus-tmp-downloaded
+         (cond (undownloaded 
+                 gnus-undownloaded-mark)
+                (gnus-newsgroup-agentized
+                 gnus-downloaded-mark)
+                (t
+                 gnus-no-mark)))
         (gnus-tmp-from (mail-header-from gnus-tmp-header))
         (gnus-tmp-name
          (cond
@@ -3100,6 +3371,18 @@ the thread are to be displayed."
          gnus-empty-thread-mark)
       number)))
 
+(defsubst gnus-summary-line-message-size (head)
+  "Return pretty-printed version of message size.
+This function is intended to be used in
+`gnus-summary-line-format-alist'."
+  (let ((c (or (mail-header-chars head) -1)))
+    (cond ((< c 0) "n/a")              ; chars not available
+         ((< c (* 1000 10)) (format "%1.1fk" (/ c 1024.0)))
+         ((< c (* 1000 100)) (format "%dk" (/ c 1024.0)))
+         ((< c (* 1000 10000)) (format "%1.1fM" (/ c (* 1024.0 1024))))
+         (t (format "%dM" (/ c (* 1024.0 1024)))))))
+
+
 (defun gnus-summary-set-local-parameters (group)
   "Go through the local params of GROUP and set all variable specs in that list."
   (let ((params (gnus-group-find-parameter group))
@@ -3251,7 +3534,7 @@ If SHOW-ALL is non-nil, already read articles are also listed."
              (let ((gnus-newsgroup-dormant nil))
                (gnus-summary-initial-limit show-all))
            (gnus-summary-initial-limit show-all))
-       ;; When untreaded, all articles are always shown.
+       ;; When unthreaded, all articles are always shown.
        (setq gnus-newsgroup-limit
              (mapcar
               (lambda (header) (mail-header-number header))
@@ -3287,9 +3570,7 @@ If SHOW-ALL is non-nil, already read articles are also listed."
        ;; Hide conversation thread subtrees.  We cannot do this in
        ;; gnus-summary-prepare-hook since kill processing may not
        ;; work with hidden articles.
-       (and gnus-show-threads
-            gnus-thread-hide-subtree
-            (gnus-summary-hide-all-threads))
+       (gnus-summary-maybe-hide-threads)
        (when kill-buffer
          (gnus-kill-or-deaden-summary kill-buffer))
        (gnus-summary-auto-select-subject)
@@ -3300,12 +3581,17 @@ If SHOW-ALL is non-nil, already read articles are also listed."
                 gnus-auto-select-first)
            (progn
              (gnus-configure-windows 'summary)
-             (gnus-summary-goto-article (gnus-summary-article-number)))
+             (let ((art (gnus-summary-article-number)))
+               (unless (and (not gnus-plugged)
+                            (or (memq art gnus-newsgroup-undownloaded)
+                                (memq art gnus-newsgroup-downloadable)))
+                 (gnus-summary-goto-article art))))
          ;; Don't select any articles.
          (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)))
@@ -3316,6 +3602,8 @@ If SHOW-ALL is non-nil, already read articles are also listed."
        ;; Mark this buffer as "prepared".
        (setq gnus-newsgroup-prepared t)
        (gnus-run-hooks 'gnus-summary-prepared-hook)
+       (unless (gnus-ephemeral-group-p group)
+         (gnus-group-update-group group))
        t)))))
 
 (defun gnus-summary-auto-select-subject ()
@@ -3328,6 +3616,8 @@ If SHOW-ALL is non-nil, already read articles are also listed."
     (gnus-summary-first-unread-subject))
    ((eq gnus-auto-select-subject 'unseen)
     (gnus-summary-first-unseen-subject))
+   ((eq gnus-auto-select-subject 'unseen-or-unread)
+    (gnus-summary-first-unseen-or-unread-subject))
    ((eq gnus-auto-select-subject 'first)
     ;; Do nothing.
     )
@@ -3415,7 +3705,16 @@ If SHOW-ALL is non-nil, already read articles are also listed."
                (setcdr prev (cdr threads))
                (setq threads prev))
            ;; Enter this thread into the hash table.
-           (gnus-sethash subject threads hashtb)))
+           (gnus-sethash subject
+                         (if gnus-summary-make-false-root-always
+                             (progn
+                               ;; If you want a dummy root above all
+                               ;; threads...
+                               (setcar threads (list whole-subject
+                                                     (car threads)))
+                               threads)
+                           threads)
+                         hashtb)))
        (setq prev threads)
        (setq threads (cdr threads)))
       result)))
@@ -3430,7 +3729,7 @@ If SHOW-ALL is non-nil, already read articles are also listed."
     (while threads
       (when (setq references (mail-header-references (caar threads)))
        (setq id (mail-header-id (caar threads))
-             ids (gnus-split-references references)
+             ids (inline (gnus-split-references references))
              entered nil)
        (while (setq ref (pop ids))
          (setq ids (delete ref ids))
@@ -3529,13 +3828,13 @@ if it was already present.
 
 If `gnus-summary-ignore-duplicates' is nil then duplicate Message-IDs
 will not be entered in the DEPENDENCIES table.  Otherwise duplicate
-Message-IDs will be renamed be renamed to a unique Message-ID before
-being entered.
+Message-IDs will be renamed to a unique Message-ID before being
+entered.
 
 Returns HEADER if it was entered in the DEPENDENCIES.  Returns nil otherwise."
   (let* ((id (mail-header-id header))
         (id-dep (and id (intern id dependencies)))
-        ref ref-dep ref-header)
+        parent-id ref ref-dep ref-header replaced)
     ;; Enter this `header' in the `dependencies' table.
     (cond
      ((not id-dep)
@@ -3552,7 +3851,8 @@ Returns HEADER if it was entered in the DEPENDENCIES.  Returns nil otherwise."
      (force-new
       ;; Overrides an existing entry;
       ;; just set the header part of the entry.
-      (setcar (symbol-value id-dep) header))
+      (setcar (symbol-value id-dep) header)
+      (setq replaced t))
 
      ;; Renames the existing `header' to a unique Message-ID.
      ((not gnus-summary-ignore-duplicates)
@@ -3575,9 +3875,10 @@ Returns HEADER if it was entered in the DEPENDENCIES.  Returns nil otherwise."
               (or (mail-header-xref header) "")))
       (setq header nil)))
 
-    (when header
-      ;; First check if that we are not creating a References loop.
-      (setq ref (gnus-parent-id (mail-header-references header)))
+    (when (and header (not replaced))
+      ;; First check that we are not creating a References loop.
+      (setq parent-id (gnus-parent-id (mail-header-references header)))
+      (setq ref parent-id)
       (while (and ref
                  (setq ref-dep (intern-soft ref dependencies))
                  (boundp ref-dep)
@@ -3587,10 +3888,10 @@ Returns HEADER if it was entered in the DEPENDENCIES.  Returns nil otherwise."
            ;; root article.
            (progn
              (mail-header-set-references (car (symbol-value id-dep)) "none")
-             (setq ref nil))
+             (setq ref nil)
+             (setq parent-id nil))
          (setq ref (gnus-parent-id (mail-header-references ref-header)))))
-      (setq ref (gnus-parent-id (mail-header-references header)))
-      (setq ref-dep (intern (or ref "none") dependencies))
+      (setq ref-dep (intern (or parent-id "none") dependencies))
       (if (boundp ref-dep)
          (setcdr (symbol-value ref-dep)
                  (nconc (cdr (symbol-value ref-dep))
@@ -3598,6 +3899,11 @@ Returns HEADER if it was entered in the DEPENDENCIES.  Returns nil otherwise."
        (set ref-dep (list nil (symbol-value id-dep)))))
     header))
 
+(defun gnus-extract-message-id-from-in-reply-to (string)
+  (if (string-match "<[^>]+>" string)
+      (substring string (match-beginning 0) (match-end 0))
+    nil))
+
 (defun gnus-build-sparse-threads ()
   (let ((headers gnus-newsgroup-headers)
        (mail-parse-charset gnus-newsgroup-charset)
@@ -3674,7 +3980,7 @@ Returns HEADER if it was entered in the DEPENDENCIES.  Returns nil otherwise."
 (defsubst gnus-nov-parse-line (number dependencies &optional force-new)
   (let ((eol (gnus-point-at-eol))
        (buffer (current-buffer))
-       header)
+       header references in-reply-to)
 
     ;; overview: [num subject from date id refs chars lines misc]
     (unwind-protect
@@ -3701,6 +4007,12 @@ Returns HEADER if it was entered in the DEPENDENCIES.  Returns nil otherwise."
 
       (widen))
 
+    (when (and (string= references "")
+              (setq in-reply-to (mail-header-extra header))
+              (setq in-reply-to (cdr (assq 'In-Reply-To in-reply-to))))
+      (mail-header-set-references
+       header (gnus-extract-message-id-from-in-reply-to in-reply-to)))
+
     (when gnus-alter-header-function
       (funcall gnus-alter-header-function header))
     (gnus-dependencies-add-header header dependencies force-new)))
@@ -3735,7 +4047,9 @@ the id of the parent article (if any)."
          (push header gnus-newsgroup-headers)
          (if (memq number gnus-newsgroup-unselected)
              (progn
-               (push number gnus-newsgroup-unreads)
+               (setq gnus-newsgroup-unreads
+                     (gnus-add-to-sorted-list gnus-newsgroup-unreads
+                                              number))
                (setq gnus-newsgroup-unselected
                      (delq number gnus-newsgroup-unselected)))
            (push number gnus-newsgroup-ancient)))))))
@@ -3761,7 +4075,9 @@ the id of the parent article (if any)."
              (if (memq (setq article (mail-header-number header))
                        gnus-newsgroup-unselected)
                  (progn
-                   (push article gnus-newsgroup-unreads)
+                   (setq gnus-newsgroup-unreads
+                         (gnus-add-to-sorted-list
+                          gnus-newsgroup-unreads article))
                    (setq gnus-newsgroup-unselected
                          (delq article gnus-newsgroup-unselected)))
                (push article gnus-newsgroup-ancient)))
@@ -3778,38 +4094,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 (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."
@@ -4047,11 +4366,11 @@ If LINE, insert the rebuilt thread starting on line LINE."
   (if (not gnus-thread-sort-functions)
       threads
     (gnus-message 8 "Sorting threads...")
-    (prog1
-       (gnus-sort-threads-1
+    (let ((max-lisp-eval-depth 5000))
+      (prog1 (gnus-sort-threads-1
         threads
         (gnus-make-sort-function gnus-thread-sort-functions))
-      (gnus-message 8 "Sorting threads...done"))))
+        (gnus-message 8 "Sorting threads...done")))))
 
 (defun gnus-sort-articles (articles)
   "Sort ARTICLES."
@@ -4083,6 +4402,15 @@ using some other form will lead to serious barfage."
   (gnus-article-sort-by-number
    (gnus-thread-header h1) (gnus-thread-header h2)))
 
+(defsubst gnus-article-sort-by-random (h1 h2)
+  "Sort articles by article number."
+  (zerop (random 2)))
+
+(defun gnus-thread-sort-by-random (h1 h2)
+  "Sort threads by root article number."
+  (gnus-article-sort-by-random
+   (gnus-thread-header h1) (gnus-thread-header h2)))
+
 (defsubst gnus-article-sort-by-lines (h1 h2)
   "Sort articles by article Lines header."
   (< (mail-header-lines h1)
@@ -4165,15 +4493,47 @@ Unscored articles will be counted as having a score of zero."
 
 (defun gnus-thread-total-score (thread)
   ;; This function find the total score of THREAD.
-  (cond ((null thread)
-        0)
-       ((consp thread)
-        (if (stringp (car thread))
-            (apply gnus-thread-score-function 0
-                   (mapcar 'gnus-thread-total-score-1 (cdr thread)))
-          (gnus-thread-total-score-1 thread)))
-       (t
-        (gnus-thread-total-score-1 (list thread)))))
+  (cond
+   ((null thread)
+    0)
+   ((consp thread)
+    (if (stringp (car thread))
+       (apply gnus-thread-score-function 0
+              (mapcar 'gnus-thread-total-score-1 (cdr thread)))
+      (gnus-thread-total-score-1 thread)))
+   (t
+    (gnus-thread-total-score-1 (list thread)))))
+
+(defun gnus-thread-sort-by-most-recent-number (h1 h2)
+  "Sort threads such that the thread with the most recently arrived article comes first."
+  (> (gnus-thread-highest-number h1) (gnus-thread-highest-number h2)))
+
+(defun gnus-thread-highest-number (thread)
+  "Return the highest article number in THREAD."
+  (apply 'max (mapcar (lambda (header)
+                       (mail-header-number header))
+                     (message-flatten-list thread))))
+
+(defun gnus-thread-sort-by-most-recent-date (h1 h2)
+  "Sort threads such that the thread with the most recently dated article comes first."
+  (> (gnus-thread-latest-date h1) (gnus-thread-latest-date h2)))
+
+(defun gnus-thread-latest-date (thread)
+  "Return the highest article date in THREAD."
+  (let ((previous-time 0))
+    (apply 'max
+          (mapcar
+           (lambda (header)
+             (setq previous-time
+                   (time-to-seconds
+                    (condition-case ()
+                        (mail-header-parse-date (mail-header-date header))
+                      (error previous-time)))))
+           (sort
+            (message-flatten-list thread)
+            (lambda (h1 h2)
+              (< (mail-header-number h1)
+                 (mail-header-number h2))))))))
 
 (defun gnus-thread-total-score-1 (root)
   ;; This function find the total score of the thread below ROOT.
@@ -4203,20 +4563,32 @@ Unscored articles will be counted as having a score of zero."
 
 (defvar gnus-tmp-thread-tree-header-string "")
 
-(defvar gnus-sum-thread-tree-root "> "
+(defcustom gnus-sum-thread-tree-root "> "
   "With %B spec, used for the root of a thread.
-If nil, use subject instead.")
-(defvar gnus-sum-thread-tree-single-indent ""
+If nil, use subject instead."
+  :type 'string
+  :group 'gnus-thread)
+(defcustom gnus-sum-thread-tree-single-indent ""
   "With %B spec, used for a thread with just one message.
-If nil, use subject instead.")
-(defvar gnus-sum-thread-tree-vertical "| "
-  "With %B spec, used for drawing a vertical line.")
-(defvar gnus-sum-thread-tree-indent "  "
-  "With %B spec, used for indenting.")
-(defvar gnus-sum-thread-tree-leaf-with-other "+-> "
-  "With %B spec, used for a leaf with brothers.")
-(defvar gnus-sum-thread-tree-single-leaf "\\-> "
-  "With %B spec, used for a leaf without brothers.")
+If nil, use subject instead."
+  :type 'string
+  :group 'gnus-thread)
+(defcustom gnus-sum-thread-tree-vertical "| "
+  "With %B spec, used for drawing a vertical line."
+  :type 'string
+  :group 'gnus-thread)
+(defcustom gnus-sum-thread-tree-indent "  "
+  "With %B spec, used for indenting."
+  :type 'string
+  :group 'gnus-thread)
+(defcustom gnus-sum-thread-tree-leaf-with-other "+-> "
+  "With %B spec, used for a leaf with brothers."
+  :type 'string
+  :group 'gnus-thread)
+(defcustom gnus-sum-thread-tree-single-leaf "\\-> "
+  "With %B spec, used for a leaf without brothers."
+  :type 'string
+  :group 'gnus-thread)
 
 (defun gnus-summary-prepare-threads (threads)
   "Prepare summary buffer from THREADS and indentation LEVEL.
@@ -4230,16 +4602,19 @@ or a straight list of headers."
   (let ((gnus-tmp-level 0)
        (default-score (or gnus-summary-default-score 0))
        (gnus-visual-p (gnus-visual-p 'summary-highlight 'highlight))
+       (building-line-count gnus-summary-display-while-building)
+       (building-count (integerp gnus-summary-display-while-building))
        thread number subject stack state gnus-tmp-gathered beg-match
-       new-roots gnus-tmp-new-adopts thread-end
-       gnus-tmp-header gnus-tmp-unread
+       new-roots gnus-tmp-new-adopts thread-end simp-subject
+       gnus-tmp-header gnus-tmp-unread gnus-tmp-downloaded
        gnus-tmp-replied gnus-tmp-subject-or-nil
        gnus-tmp-dummy gnus-tmp-indentation gnus-tmp-lines gnus-tmp-score
        gnus-tmp-score-char gnus-tmp-from gnus-tmp-name
        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
@@ -4249,6 +4624,8 @@ or a straight list of headers."
 
       ;; Do the threaded display.
 
+      (if gnus-summary-display-while-building
+         (switch-to-buffer (buffer-name)))
       (while (or threads stack gnus-tmp-new-adopts new-roots)
 
        (if (and (= gnus-tmp-level 0)
@@ -4320,7 +4697,8 @@ or a straight list of headers."
              (setq gnus-tmp-level -1)))
 
          (setq number (mail-header-number gnus-tmp-header)
-               subject (mail-header-subject gnus-tmp-header))
+               subject (mail-header-subject gnus-tmp-header)
+               simp-subject (gnus-simplify-subject-fully subject))
 
          (cond
           ;; If the thread has changed subject, we might want to make
@@ -4328,8 +4706,7 @@ or a straight list of headers."
           ((and (null gnus-thread-ignore-subject)
                 (not (zerop gnus-tmp-level))
                 gnus-tmp-prev-subject
-                (not (inline
-                       (gnus-subject-equal gnus-tmp-prev-subject subject))))
+                (not (string= gnus-tmp-prev-subject simp-subject)))
            (setq new-roots (nconc new-roots (list (car thread)))
                  thread-end t
                  gnus-tmp-header nil))
@@ -4360,7 +4737,9 @@ or a straight list of headers."
            (setq gnus-newsgroup-unreads
                  (delq number gnus-newsgroup-unreads))
            (if gnus-newsgroup-auto-expire
-               (push number gnus-newsgroup-expirable)
+               (setq gnus-newsgroup-expirable
+                     (gnus-add-to-sorted-list
+                      gnus-newsgroup-expirable number))
              (push (cons number gnus-low-score-mark)
                    gnus-newsgroup-reads))))
 
@@ -4388,15 +4767,13 @@ or a straight list of headers."
             (cond
              ((and gnus-thread-ignore-subject
                    gnus-tmp-prev-subject
-                   (not (inline (gnus-subject-equal
-                                 gnus-tmp-prev-subject subject))))
+                   (not (string= gnus-tmp-prev-subject simp-subject)))
               subject)
              ((zerop gnus-tmp-level)
               (if (and (eq gnus-summary-make-false-root 'empty)
                        (memq number gnus-tmp-gathered)
                        gnus-tmp-prev-subject
-                       (inline (gnus-subject-equal
-                                gnus-tmp-prev-subject subject)))
+                       (string= gnus-tmp-prev-subject simp-subject))
                   gnus-summary-same-subject
                 subject))
              (t gnus-summary-same-subject)))
@@ -4436,6 +4813,13 @@ or a straight list of headers."
                   ((memq number gnus-newsgroup-unseen)
                    gnus-unseen-mark)
                   (t gnus-no-mark))
+            gnus-tmp-downloaded
+             (cond ((memq number gnus-newsgroup-undownloaded) 
+                    gnus-undownloaded-mark)
+                   (gnus-newsgroup-agentized
+                    gnus-downloaded-mark)
+                   (t
+                    gnus-no-mark))
             gnus-tmp-from (mail-header-from gnus-tmp-header)
             gnus-tmp-name
             (cond
@@ -4448,6 +4832,8 @@ or a straight list of headers."
               (substring gnus-tmp-from
                          (1+ (match-beginning 0)) (1- (match-end 0))))
              (t gnus-tmp-from))
+
+            ;; Do the %B string
             gnus-tmp-thread-tree-header-string
             (cond
              ((not gnus-show-threads) "")
@@ -4472,16 +4858,16 @@ 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)
              (forward-line 1))
 
-           (setq gnus-tmp-prev-subject subject)))
+           (setq gnus-tmp-prev-subject simp-subject)))
 
        (when (nth 1 thread)
          (push (list (max 0 gnus-tmp-level)
@@ -4491,6 +4877,17 @@ or a straight list of headers."
        (push (if (nth 1 thread) 1 0) tree-stack)
        (incf gnus-tmp-level)
        (setq threads (if thread-end nil (cdar thread)))
+       (if gnus-summary-display-while-building
+           (if building-count
+               (progn
+                 ;; use a set frequency
+                 (setq building-line-count (1- building-line-count))
+                 (when (= building-line-count 0)
+                   (sit-for 0)
+                   (setq building-line-count
+                         gnus-summary-display-while-building)))
+             ;; always
+             (sit-for 0)))
        (unless threads
          (setq gnus-tmp-level 0)))))
   (gnus-message 7 "Generating summary...done"))
@@ -4524,6 +4921,7 @@ or a straight list of headers."
              gnus-newsgroup-data)
        (gnus-summary-insert-line
         header 0 number
+        (memq number gnus-newsgroup-undownloaded)
         mark (memq number gnus-newsgroup-replied)
         (memq number gnus-newsgroup-expirable)
         (mail-header-subject header) nil
@@ -4599,16 +4997,28 @@ 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)))
 
+    (when gnus-agent
+      ;; The agent may be storing articles that are no longer in the
+      ;; server's active range.  If that is the case, the active range
+      ;; needs to be expanded such that the agent's articles can be
+      ;; included in the summary.
+      (let* ((gnus-command-method (gnus-find-method-for-group group))
+             (alist (gnus-agent-load-alist group))
+             (active (gnus-active group)))
+        (if (and (car alist)
+                 (< (caar alist) (car active)))
+            (gnus-set-active group (cons (caar alist) (cdr active))))))
+
     (setq gnus-newsgroup-name group
          gnus-newsgroup-unselected nil
          gnus-newsgroup-unreads (gnus-list-of-unread-articles group))
@@ -4652,8 +5062,9 @@ If SELECT-ARTICLES, only select those articles from GROUP."
       (setq cached gnus-newsgroup-cached))
 
     (setq gnus-newsgroup-unreads
-         (gnus-set-difference
-          (gnus-set-difference gnus-newsgroup-unreads gnus-newsgroup-marked)
+         (gnus-sorted-ndifference
+          (gnus-sorted-ndifference gnus-newsgroup-unreads
+                                   gnus-newsgroup-marked)
           gnus-newsgroup-dormant))
 
     (setq gnus-newsgroup-processable nil)
@@ -4663,12 +5074,9 @@ If SELECT-ARTICLES, only select those articles from GROUP."
     ;; Adjust and set lists of article marks.
     (when info
       (gnus-adjust-marked-articles info))
-
     (if (setq articles select-articles)
        (setq gnus-newsgroup-unselected
-             (gnus-sorted-intersection
-              gnus-newsgroup-unreads
-              (gnus-sorted-complement gnus-newsgroup-unreads articles)))
+             (gnus-sorted-difference gnus-newsgroup-unreads articles))
       (setq articles (gnus-articles-to-read group read-all)))
 
     (cond
@@ -4682,6 +5090,7 @@ If SELECT-ARTICLES, only select those articles from GROUP."
            (gnus-make-hashtable (length articles)))
       (gnus-set-global-variables)
       ;; Retrieve the headers and read them in.
+
       (setq gnus-newsgroup-headers (gnus-fetch-headers articles))
 
       ;; Kludge to avoid having cached articles nixed out in virtual groups.
@@ -4700,20 +5109,13 @@ If SELECT-ARTICLES, only select those articles from GROUP."
                    gnus-newsgroup-headers))
       (setq gnus-newsgroup-articles fetched-articles)
       (setq gnus-newsgroup-unreads
-           (gnus-set-sorted-intersection
+           (gnus-sorted-nintersection
             gnus-newsgroup-unreads fetched-articles))
-
-      ;; The `seen' marks are treated specially.
-      (if (not gnus-newsgroup-seen)
-         (setq gnus-newsgroup-unseen gnus-newsgroup-articles)
-       (dolist (article gnus-newsgroup-articles)
-         (unless (gnus-member-of-range article gnus-newsgroup-seen)
-           (push article gnus-newsgroup-unseen)))
-       (setq gnus-newsgroup-unseen (nreverse gnus-newsgroup-unseen)))
+      (gnus-compute-unseen-list)
 
       ;; Removed marked articles that do not exist.
       (gnus-update-missing-marks
-       (gnus-sorted-complement fetched-articles articles))
+       (gnus-sorted-difference articles fetched-articles))
       ;; We might want to build some more threads first.
       (when (and gnus-fetch-old-headers
                 (eq gnus-headers-retrieved-by 'nov))
@@ -4742,28 +5144,41 @@ If SELECT-ARTICLES, only select those articles from GROUP."
       ;; GROUP is successfully selected.
       (or gnus-newsgroup-headers t)))))
 
+(defun gnus-compute-unseen-list ()
+  ;; The `seen' marks are treated specially.
+  (if (not gnus-newsgroup-seen)
+      (setq gnus-newsgroup-unseen gnus-newsgroup-articles)
+    (setq gnus-newsgroup-unseen
+         (gnus-inverse-list-range-intersection
+          gnus-newsgroup-articles gnus-newsgroup-seen))))
+
 (defun gnus-summary-display-make-predicate (display)
   (require 'gnus-agent)
   (when (= (length display) 1)
     (setq display (car display)))
   (unless gnus-summary-display-cache
-    (dolist (elem (append (list (cons 'read 'read)
-                               (cons 'unseen 'unseen))
+    (dolist (elem (append '((unread . unread)
+                           (read . read)
+                           (unseen . unseen))
                          gnus-article-mark-lists))
       (push (cons (cdr elem)
                  (gnus-byte-compile
                   `(lambda () (gnus-article-marked-p ',(cdr elem)))))
            gnus-summary-display-cache)))
-  (let ((gnus-category-predicate-alist gnus-summary-display-cache))
+  (let ((gnus-category-predicate-alist gnus-summary-display-cache)
+       (gnus-category-predicate-cache gnus-summary-display-cache))
     (gnus-get-predicate display)))
 
 ;; Uses the dynamically bound `number' variable.
-(defvar number)
+(eval-when-compile
+  (defvar number))
 (defun gnus-article-marked-p (type &optional article)
   (let ((article (or article number)))
     (cond
      ((eq type 'tick)
       (memq article gnus-newsgroup-marked))
+     ((eq type 'spam)
+      (memq article gnus-newsgroup-spam-marked))
      ((eq type 'unsend)
       (memq article gnus-newsgroup-unsendable))
      ((eq type 'undownload)
@@ -4800,13 +5215,15 @@ If SELECT-ARTICLES, only select those articles from GROUP."
 
 (defun gnus-articles-to-read (group &optional read-all)
   "Find out what articles the user wants to read."
-  (let* ((articles
+  (let* ((display (gnus-group-find-parameter group 'display))
+        (articles
          ;; Select all articles if `read-all' is non-nil, or if there
          ;; are no unread articles.
          (if (or read-all
                  (and (zerop (length gnus-newsgroup-marked))
                       (zerop (length gnus-newsgroup-unreads)))
-                 (eq gnus-newsgroup-display 'gnus-not-ignore))
+                 ;; Fetch all if the predicate is non-nil.
+                 gnus-newsgroup-display)
              ;; We want to select the headers for all the articles in
              ;; the group, so we select either all the active
              ;; articles in the group, or (if that's nil), the
@@ -4815,9 +5232,9 @@ If SELECT-ARTICLES, only select those articles from GROUP."
               (gnus-uncompress-range (gnus-active group))
               (gnus-cache-articles-in-group group))
            ;; Select only the "normal" subset of articles.
-           (sort (append gnus-newsgroup-dormant gnus-newsgroup-marked
-                         (copy-sequence gnus-newsgroup-unreads))
-                 '<)))
+           (gnus-sorted-nunion
+            (gnus-sorted-union gnus-newsgroup-dormant gnus-newsgroup-marked)
+            gnus-newsgroup-unreads)))
         (scored-list (gnus-killed-articles gnus-newsgroup-killed articles))
         (scored (length scored-list))
         (number (length articles))
@@ -4827,26 +5244,30 @@ If SELECT-ARTICLES, only select those articles from GROUP."
          (cond
           ((numberp read-all)
            read-all)
+          ((numberp gnus-newsgroup-display)
+           gnus-newsgroup-display)
           (t
            (condition-case ()
                (cond
                 ((and (or (<= scored marked) (= scored number))
-                      (natnump gnus-large-newsgroup)
+                      (numberp gnus-large-newsgroup)
                       (> number gnus-large-newsgroup))
                  (let* ((cursor-in-echo-area nil)
+                        (initial (gnus-parameter-large-newsgroup-initial
+                                  gnus-newsgroup-name))
                         (input
-                         (read-from-minibuffer
+                         (read-string
                           (format
-                           "How many articles from %s (max %d): "
+                           "How many articles from %s (%s %d): "
                            (gnus-limit-string
                             (gnus-group-decoded-name gnus-newsgroup-name)
                             35)
+                           (if initial "max" "default")
                            number)
-                          (cons (number-to-string gnus-large-newsgroup)
-                                0))))
-                   (if (string-match "^[ \t]*$" input)
-                       number
-                     input)))
+                          (if initial
+                              (cons (number-to-string initial)
+                                    0)))))
+                   (if (string-match "^[ \t]*$" input) number input)))
                 ((and (> scored marked) (< scored number)
                       (> (- scored number) 20))
                  (let ((input
@@ -4877,14 +5298,12 @@ If SELECT-ARTICLES, only select those articles from GROUP."
          ;; Select the N most recent articles.
          (setq articles (nthcdr (- number select) articles))))
       (setq gnus-newsgroup-unselected
-           (gnus-sorted-intersection
-            gnus-newsgroup-unreads
-            (gnus-sorted-complement gnus-newsgroup-unreads articles)))
+           (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)))
 
@@ -4956,8 +5375,8 @@ If SELECT-ARTICLES, only select those articles from GROUP."
        ((eq mark-type 'range)
        (cond
         ((eq mark 'seen)
-         ;; T-gnus change: Fix the record for `seen' if it looks like
-         ;; (seen NUM1 . NUM2).  It should be (seen (NUM1 . NUM2)).
+         ;; Fix the record for `seen' if it looks like (seen NUM1 . NUM2).
+         ;; It should be (seen (NUM1 . NUM2)).
          (when (numberp (cddr marks))
            (setcdr marks (list (cdr marks))))
          (setq articles (cdr marks))
@@ -5257,7 +5676,8 @@ The resulting hash table is returned, or nil if no Xrefs were found."
        ;; Update the number of unread articles.
        (setcar entry num)
        ;; Update the group buffer.
-       (gnus-group-update-group group t)))))
+       (unless (gnus-ephemeral-group-p group)
+         (gnus-group-update-group group t))))))
 
 (defvar gnus-newsgroup-none-id 0)
 
@@ -5447,29 +5867,24 @@ Return a list of headers that match SEQUENCE (see
       ;; Allow the user to mangle the headers before parsing them.
       (gnus-run-hooks 'gnus-parse-headers-hook)
       (goto-char (point-min))
-      (while (not (eobp))
-       (condition-case ()
-           (while (and (or sequence allp)
-                       (not (eobp)))
-             (setq number (read cur))
-             (when (not allp)
-               (while (and sequence
-                           (< (car sequence) number))
-                 (setq sequence (cdr sequence))))
-             (when (and (or allp
-                            (and sequence
-                                 (eq number (car sequence))))
-                        (progn
-                          (setq sequence (cdr sequence))
-                          (setq header (inline
-                                         (gnus-nov-parse-line
-                                          number dependencies force-new)))))
-               (push header headers))
-             (forward-line 1))
-         (error
-          (gnus-error 4 "Strange nov line (%d)"
-                      (count-lines (point-min) (point)))))
-       (forward-line 1))
+      (gnus-parse-without-error
+       (while (and (or sequence allp)
+                   (not (eobp)))
+         (setq number (read cur))
+         (when (not allp)
+           (while (and sequence
+                       (< (car sequence) number))
+             (setq sequence (cdr sequence))))
+         (when (and (or allp
+                        (and sequence
+                             (eq number (car sequence))))
+                    (progn
+                      (setq sequence (cdr sequence))
+                      (setq header (inline
+                                     (gnus-nov-parse-line
+                                      number dependencies force-new)))))
+           (push header headers))
+         (forward-line 1)))
       ;; A common bug in inn is that if you have posted an article and
       ;; then retrieves the active file, it will answer correctly --
       ;; the new article is included.  However, a NOV entry for the
@@ -5505,8 +5920,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)
@@ -5668,53 +6082,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
-                                        (eq gnus-undownloaded-mark
-                                            (gnus-data-mark (car arts))))
-                                   (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))))
 
@@ -5765,18 +6194,18 @@ 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.
   (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
@@ -5868,13 +6297,13 @@ displayed, no centering will be performed."
         (marked (gnus-info-marks info))
         (active (gnus-active group)))
     (and info active
-        (gnus-set-difference
-         (gnus-sorted-complement
-          (gnus-uncompress-range active)
-          (gnus-list-of-unread-articles group))
-         (append
-          (gnus-uncompress-range (cdr (assq 'dormant marked)))
-          (gnus-uncompress-range (cdr (assq 'tick marked))))))))
+        (gnus-list-range-difference
+         (gnus-list-range-difference
+          (gnus-sorted-complement
+           (gnus-uncompress-range active)
+           (gnus-list-of-unread-articles group))
+          (cdr (assq 'dormant marked)))
+         (cdr (assq 'tick marked))))))
 
 ;; Various summary commands
 
@@ -5910,20 +6339,37 @@ displayed, no centering will be performed."
 
 (defun gnus-summary-toggle-truncation (&optional arg)
   "Toggle truncation of summary lines.
-With arg, turn line truncation on iff arg is positive."
+With arg, turn line truncation on if arg is positive."
   (interactive "P")
   (setq truncate-lines
        (if (null arg) (not truncate-lines)
          (> (prefix-numeric-value arg) 0)))
   (redraw-display))
 
+(defun gnus-summary-find-for-reselect ()
+  "Return the number of an article to stay on across a reselect.
+The current article is considered, then following articles, then previous
+articles.  An article is sought which is not cancelled and isn't a temporary
+insertion from another group.  If there's no such then return a dummy 0."
+  (let (found)
+    (dolist (rev '(nil t))
+      (unless found      ; don't demand the reverse list if we don't need it
+        (let ((data (gnus-data-find-list
+                     (gnus-summary-article-number) (gnus-data-list rev))))
+          (while (and data (not found))
+            (if (and (< 0 (gnus-data-number (car data)))
+                     (not (eq gnus-canceled-mark (gnus-data-mark (car data)))))
+                (setq found (gnus-data-number (car data))))
+            (setq data (cdr data))))))
+    (or found 0)))
+
 (defun gnus-summary-reselect-current-group (&optional all rescan)
   "Exit and then reselect the current newsgroup.
 The prefix argument ALL means to select all articles."
   (interactive "P")
   (when (gnus-ephemeral-group-p gnus-newsgroup-name)
     (error "Ephemeral groups can't be reselected"))
-  (let ((current-subject (gnus-summary-article-number))
+  (let ((current-subject (gnus-summary-find-for-reselect))
        (group gnus-newsgroup-name))
     (setq gnus-newsgroup-begin nil)
     (gnus-summary-exit)
@@ -5951,13 +6397,10 @@ The prefix argument ALL means to select all articles."
        (when gnus-newsgroup-kill-headers
          (setq gnus-newsgroup-killed
                (gnus-compress-sequence
-                (nconc
-                 (gnus-set-sorted-intersection
-                  (gnus-uncompress-range gnus-newsgroup-killed)
-                  (setq gnus-newsgroup-unselected
-                        (sort gnus-newsgroup-unselected '<)))
-                 (setq gnus-newsgroup-unreads
-                       (sort gnus-newsgroup-unreads '<)))
+                (gnus-sorted-union
+                 (gnus-list-range-intersection
+                  gnus-newsgroup-unselected gnus-newsgroup-killed)
+                 gnus-newsgroup-unreads)
                 t)))
        (unless (listp (cdr gnus-newsgroup-killed))
          (setq gnus-newsgroup-killed (list gnus-newsgroup-killed)))
@@ -5967,7 +6410,8 @@ The prefix argument ALL means to select all articles."
            (set-buffer gnus-group-buffer)
            (gnus-undo-force-boundary))
          (gnus-update-read-articles
-          group (append gnus-newsgroup-unreads gnus-newsgroup-unselected))
+          group (gnus-sorted-union
+                 gnus-newsgroup-unreads gnus-newsgroup-unselected))
          ;; Set the current article marks.
          (let ((gnus-newsgroup-scored
                 (if (and (not gnus-save-score)
@@ -6003,6 +6447,7 @@ If FORCE (the prefix), also save the .newsrc file(s)."
   (gnus-async-halt-prefetch)
   (let* ((group gnus-newsgroup-name)
         (quit-config (gnus-group-quit-config gnus-newsgroup-name))
+        (gnus-group-is-exiting-p t)
         (mode major-mode)
         (group-point nil)
         (buf (current-buffer)))
@@ -6071,7 +6516,10 @@ If FORCE (the prefix), also save the .newsrc file(s)."
        (set-buffer gnus-group-buffer)
        (gnus-summary-clear-local-variables)
        (let ((gnus-summary-local-variables gnus-newsgroup-variables))
-         (gnus-summary-clear-local-variables)))
+         (gnus-summary-clear-local-variables))
+       ;; Return to group mode buffer.
+       (when (eq mode 'gnus-summary-mode)
+         (gnus-kill-buffer buf)))
       (setq gnus-current-select-method gnus-select-method)
       (pop-to-buffer gnus-group-buffer)
       (if (not quit-config)
@@ -6086,9 +6534,6 @@ If FORCE (the prefix), also save the .newsrc file(s)."
              (set-window-start (selected-window) (point))
              (goto-char group-point)))
        (gnus-handle-ephemeral-exit quit-config))
-      ;; Return to group mode buffer.
-      (when (eq mode 'gnus-summary-mode)
-       (gnus-kill-buffer buf))
       ;; Clear the current group name.
       (unless quit-config
        (setq gnus-newsgroup-name nil)))))
@@ -6098,14 +6543,14 @@ If FORCE (the prefix), also save the .newsrc file(s)."
   "Quit reading current newsgroup without updating read article info."
   (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)
       ;; If we have several article buffers, we kill them at exit.
       (unless gnus-single-article-buffer
        (gnus-kill-buffer gnus-article-buffer)
@@ -6121,8 +6566,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
@@ -6134,6 +6578,8 @@ If FORCE (the prefix), also save the .newsrc file(s)."
       (gnus-configure-windows 'group 'force)
       ;; Clear the current group name.
       (setq gnus-newsgroup-name nil)
+      (unless (gnus-ephemeral-group-p group)
+       (gnus-group-update-group group))
       (when (equal (gnus-group-group-name) group)
        (gnus-group-next-unread-group 1))
       (when quit-config
@@ -6177,7 +6623,9 @@ The state which existed when entering the ephemeral is reset."
   (let ((gnus-break-pages nil)
        (gnus-show-mime t))
     (gnus-summary-select-article gnus-show-all-headers t))
-  (select-window (get-buffer-window gnus-article-buffer)))
+  (let ((w (get-buffer-window gnus-article-buffer)))
+    (when w
+      (select-window (get-buffer-window gnus-article-buffer)))))
 
 ;;; Dead summaries.
 
@@ -6188,10 +6636,11 @@ The state which existed when entering the ephemeral is reset."
   (suppress-keymap gnus-dead-summary-mode-map)
   (substitute-key-definition
    'undefined 'gnus-summary-wake-up-the-dead gnus-dead-summary-mode-map)
-  (let ((keys '("\C-d" "\r" "\177" [delete])))
-    (while keys
-      (define-key gnus-dead-summary-mode-map
-       (pop keys) 'gnus-summary-wake-up-the-dead))))
+  (dolist (key '("\C-d" "\r" "\177" [delete]))
+    (define-key gnus-dead-summary-mode-map
+      key 'gnus-summary-wake-up-the-dead))
+  (dolist (key '("q" "Q"))
+    (define-key gnus-dead-summary-mode-map key 'bury-buffer)))
 
 (defvar gnus-dead-summary-mode nil
   "Minor mode for Gnus summary buffers.")
@@ -6237,17 +6686,20 @@ The state which existed when entering the ephemeral is reset."
        (set-buffer buffer)
        (gnus-kill-buffer gnus-article-buffer)
        (gnus-kill-buffer gnus-original-article-buffer)))
-    (cond (gnus-kill-summary-on-exit
-          (when (and gnus-use-trees
-                     (gnus-buffer-exists-p buffer))
-            (save-excursion
-              (set-buffer buffer)
-              (gnus-tree-close gnus-newsgroup-name)))
-          (gnus-kill-buffer buffer))
-         ((gnus-buffer-exists-p buffer)
-          (save-excursion
-            (set-buffer buffer)
-            (gnus-deaden-summary))))))
+    (cond
+     ;; Kill the buffer.
+     (gnus-kill-summary-on-exit
+      (when (and gnus-use-trees
+                (gnus-buffer-exists-p buffer))
+       (save-excursion
+         (set-buffer buffer)
+         (gnus-tree-close gnus-newsgroup-name)))
+      (gnus-kill-buffer buffer))
+     ;; Deaden the buffer.
+     ((gnus-buffer-exists-p buffer)
+      (save-excursion
+       (set-buffer buffer)
+       (gnus-deaden-summary))))))
 
 (defun gnus-summary-wake-up-the-dead (&rest args)
   "Wake up the dead summary buffer."
@@ -6270,7 +6722,7 @@ in."
    (list
     (when current-prefix-arg
       (completing-read
-       "Faq dir: " (and (listp gnus-group-faq-directory)
+       "FAQ dir: " (and (listp gnus-group-faq-directory)
                        (mapcar (lambda (file) (list file))
                                gnus-group-faq-directory))))))
   (let (gnus-faq-buffer)
@@ -6294,7 +6746,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.
@@ -6331,10 +6783,10 @@ previous group instead."
        (let ((unreads (gnus-group-group-unread)))
          (if (and (or (eq t unreads)
                       (and unreads (not (zerop unreads))))
-                  (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)))))))
@@ -6348,39 +6800,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
-                                    (eq gnus-undownloaded-mark
-                                        (gnus-data-mark (car data)))))
-                          (not (and unseen
-                                    (memq (car data) gnus-newsgroup-unseen)))
-                          (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.
@@ -6421,10 +6889,20 @@ If optional argument UNREAD is non-nil, only unread article is selected."
   (interactive "p")
   (gnus-summary-next-subject (- n) t))
 
+(defun gnus-summary-goto-subjects (articles)
+  "Insert the subject header for ARTICLES in the current buffer."
+  (save-excursion
+    (dolist (article articles)
+      (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."
   (interactive "nArticle number: ")
+  (unless (numberp article)
+    (error "Article %s is not a number" article))
   (let ((b (point))
        (data (gnus-data-find article)))
     ;; We read in the article if we have to.
@@ -6466,7 +6944,8 @@ Given a prefix, will force an `article' buffer configuration."
   (when (gnus-buffer-live-p gnus-article-buffer)
     (with-current-buffer gnus-article-buffer
       (setq gnus-article-charset gnus-newsgroup-charset)
-      (setq gnus-article-ignored-charsets gnus-newsgroup-ignored-charsets)))
+      (setq gnus-article-ignored-charsets gnus-newsgroup-ignored-charsets)
+      (set-buffer-multibyte t)))
   (if (null article)
       nil
     (prog1
@@ -6519,19 +6998,19 @@ be displayed."
          ;; The requested article is different from the current article.
          (progn
            (gnus-summary-display-article article all-headers)
-           (when (or all-headers gnus-show-all-headers)
-             (gnus-article-show-all-headers))
            (gnus-article-set-window-start
             (cdr (assq article gnus-newsgroup-bookmarks)))
            article)
-       (when (or all-headers gnus-show-all-headers)
-         (gnus-article-show-all-headers))
        '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))
+       (mm-decrypt-option 'known)
+       (gnus-buttonized-mime-types (append (list "multipart/signed"
+                                                 "multipart/encrypted")
+                                           gnus-buttonized-mime-types)))
     (gnus-summary-select-article nil 'force)))
 
 (defun gnus-summary-set-current-mark (&optional current-mark)
@@ -6605,7 +7084,7 @@ If BACKWARD, the previous article is selected instead of the next."
   (let ((keystrokes '((?\C-n (gnus-group-next-unread-group 1))
                      (?\C-p (gnus-group-prev-unread-group 1))))
        (cursor-in-echo-area t)
-       keve key group ended)
+       keve key group ended prompt)
     (save-excursion
       (set-buffer gnus-group-buffer)
       (goto-char start)
@@ -6614,19 +7093,20 @@ If BACKWARD, the previous article is selected instead of the next."
                (gnus-summary-best-group gnus-newsgroup-name)
              (gnus-summary-search-group backward gnus-keep-same-level))))
     (while (not ended)
-      (gnus-message
-       5 "No more%s articles%s" (if unread " unread" "")
-       (if (and group
-               (not (gnus-ephemeral-group-p gnus-newsgroup-name)))
-          (format " (Type %s for %s [%s])"
-                  (single-key-description cmd) group
-                  (car (gnus-gethash group gnus-newsrc-hashtb)))
-        (format " (Type %s to exit %s)"
-                (single-key-description cmd)
-                gnus-newsgroup-name)))
+      (setq prompt
+           (format
+            "No more%s articles%s " (if unread " unread" "")
+            (if (and group
+                     (not (gnus-ephemeral-group-p gnus-newsgroup-name)))
+                (format " (Type %s for %s [%s])"
+                        (single-key-description cmd) group
+                        (car (gnus-gethash group gnus-newsrc-hashtb)))
+              (format " (Type %s to exit %s)"
+                      (single-key-description cmd)
+                      gnus-newsgroup-name))))
       ;; Confirm auto selection.
-      (setq key (car (setq keve (gnus-read-event-char))))
-      (setq ended t)
+      (setq key (car (setq keve (gnus-read-event-char prompt)))
+           ended t)
       (cond
        ((assq key keystrokes)
        (let ((obuf (current-buffer)))
@@ -6669,14 +7149,16 @@ If UNREAD is non-nil, only unread articles are selected."
    (and gnus-auto-select-same
        (gnus-summary-article-subject))))
 
-(defun gnus-summary-next-page (&optional lines circular)
+(defun gnus-summary-next-page (&optional lines circular stop)
   "Show next page of the selected article.
 If at the end of the current article, select the next article.
 LINES says how many lines should be scrolled up.
 
 If CIRCULAR is non-nil, go to the start of the article instead of
 selecting the next article when reaching the end of the current
-article."
+article.
+
+If STOP is non-nil, just stop when reaching the end of the message."
   (interactive "P")
   (setq gnus-summary-buffer (current-buffer))
   (gnus-set-global-variables)
@@ -6700,9 +7182,12 @@ article."
          (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 (circular
+           (cond (stop
+                  (gnus-message 3 "End of message"))
+                 (circular
                   (gnus-summary-beginning-of-article))
                  (lines
                   (gnus-message 3 "End of message"))
@@ -6819,9 +7304,23 @@ 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 or,
+if all article have been seen, on the subject line of the first unread
+article."
+  (interactive)
+  (prog1
+      (unless (when (gnus-summary-first-subject nil nil t)
+               (gnus-summary-show-thread)
+               (gnus-summary-first-subject nil nil t))
+       (when (gnus-summary-first-subject t)
+         (gnus-summary-show-thread)
+         (gnus-summary-first-subject t)))
     (gnus-summary-position-point)))
 
 (defun gnus-summary-first-article ()
@@ -6997,8 +7496,9 @@ articles that are younger than AGE days."
         days)
      (while (not days-got)
        (setq days (if younger
-                     (read-string "Limit to articles within (in days): ")
-                   (read-string "Limit to articles older than (in days): ")))
+                     (read-string "Limit to articles younger than (in days, older when negative): ")
+                   (read-string
+                    "Limit to articles older than (in days, younger when negative): ")))
        (when (> (length days) 0)
         (setq days (read days)))
        (if (numberp days)
@@ -7035,7 +7535,7 @@ articles that are younger than AGE days."
   (interactive
    (let ((header
          (intern
-          (gnus-completing-read
+          (gnus-completing-read-with-default
            (symbol-name (car gnus-extra-headers))
            (if current-prefix-arg
                "Exclude extra header:"
@@ -7086,7 +7586,7 @@ If ALL is non-nil, limit strictly to unread articles."
      ;; Concat all the marks that say that an article is read and have
      ;; those removed.
      (list gnus-del-mark gnus-read-mark gnus-ancient-mark
-          gnus-killed-mark gnus-kill-file-mark
+          gnus-killed-mark gnus-spam-mark gnus-kill-file-mark
           gnus-low-score-mark gnus-expirable-mark
           gnus-canceled-mark gnus-catchup-mark gnus-sparse-mark
           gnus-duplicate-mark gnus-souped-mark)
@@ -7094,7 +7594,7 @@ If ALL is non-nil, limit strictly to unread articles."
 
 (defalias 'gnus-summary-delete-marked-with 'gnus-summary-limit-exclude-marks)
 (make-obsolete 'gnus-summary-delete-marked-with
-              'gnus-summary-limit-exlude-marks)
+              'gnus-summary-limit-exclude-marks)
 
 (defun gnus-summary-limit-exclude-marks (marks &optional reverse)
   "Exclude articles that are marked with MARKS (e.g. \"DK\").
@@ -7138,6 +7638,13 @@ Returns how many articles were removed."
        (gnus-summary-limit articles)
       (gnus-summary-position-point))))
 
+(defun gnus-summary-limit-to-unseen ()
+  "Limit to unseen articles."
+  (interactive)
+  (prog1
+      (gnus-summary-limit gnus-newsgroup-unseen)
+    (gnus-summary-position-point)))
+
 (defun gnus-summary-limit-include-thread (id)
   "Display all the hidden articles that is in the thread with ID in it.
 When called interactively, ID is the Message-ID of the current
@@ -7162,6 +7669,14 @@ article."
        (gnus-summary-limit (nconc articles gnus-newsgroup-limit))
       (gnus-summary-position-point))))
 
+(defun gnus-summary-insert-dormant-articles ()
+  "Insert all the dormat articles for this group into the current buffer."
+  (interactive)
+  (let ((gnus-verbose (max 6 gnus-verbose)))
+    (if (not gnus-newsgroup-dormant)
+       (gnus-message 3 "No cached articles for this group")
+      (gnus-summary-goto-subjects gnus-newsgroup-dormant))))
+
 (defun gnus-summary-limit-include-dormant ()
   "Display all the hidden articles that are marked as dormant.
 Note that this command only works on a subset of the articles currently
@@ -7208,15 +7723,17 @@ fetched for this group."
   "Mark all unread excluded articles as read.
 If ALL, mark even excluded ticked and dormants as read."
   (interactive "P")
-  (let ((articles (gnus-sorted-complement
+  (setq gnus-newsgroup-limit (sort gnus-newsgroup-limit '<))
+  (let ((articles (gnus-sorted-ndifference
                   (sort
                    (mapcar (lambda (h) (mail-header-number h))
                            gnus-newsgroup-headers)
                    '<)
-                  (sort gnus-newsgroup-limit '<)))
+                  gnus-newsgroup-limit))
        article)
     (setq gnus-newsgroup-unreads
-         (gnus-intersection gnus-newsgroup-unreads gnus-newsgroup-limit))
+         (gnus-sorted-intersection gnus-newsgroup-unreads
+                                   gnus-newsgroup-limit))
     (if all
        (setq gnus-newsgroup-dormant nil
              gnus-newsgroup-marked nil
@@ -7246,9 +7763,7 @@ If ALL, mark even excluded ticked and dormants as read."
     ;; according to the new limit.
     (gnus-summary-prepare)
     ;; Hide any threads, possibly.
-    (and gnus-show-threads
-        gnus-thread-hide-subtree
-        (gnus-summary-hide-all-threads))
+    (gnus-summary-maybe-hide-threads)
     ;; Try to return to the article you were at, or one in the
     ;; neighborhood.
     (when data
@@ -7368,7 +7883,8 @@ fetch-old-headers verbiage, and so on."
   ;; will really go down to a leaf article first, before slowly
   ;; working its way up towards the root.
   (when thread
-    (let ((children
+    (let* ((max-lisp-eval-depth 5000)
+          (children
           (if (cdr thread)
               (apply '+ (mapcar 'gnus-summary-limit-children
                                 (cdr thread)))
@@ -7523,16 +8039,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"))
@@ -7572,15 +8093,16 @@ 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)))))))
 
 (defun gnus-refer-article-methods ()
-  "Return a list of referrable methods."
+  "Return a list of referable methods."
   (cond
    ;; No method, so we default to current and native.
    ((null gnus-refer-article-method)
@@ -7638,8 +8160,8 @@ to guess what the document format is."
        (set-buffer gnus-original-article-buffer)
        ;; Have the digest group inherit the main mail address of
        ;; the parent article.
-       (when (setq to-address (or (message-fetch-field "reply-to")
-                                  (message-fetch-field "from")))
+       (when (setq to-address (or (gnus-fetch-field "reply-to")
+                                  (gnus-fetch-field "from")))
          (setq params (append
                        (list (cons 'to-address
                                    (funcall gnus-decode-encoded-word-function
@@ -7661,7 +8183,10 @@ to guess what the document format is."
                (gnus-group-read-ephemeral-group
                 name `(nndoc ,name (nndoc-address ,(get-buffer dig))
                              (nndoc-article-type
-                              ,(if force 'mbox 'guess))) t))
+                              ,(if force 'mbox 'guess)))
+                t nil nil nil
+                `((adapt-file . ,(gnus-score-file-name gnus-newsgroup-name
+                                                       "ADAPT")))))
              ;; Make all postings to this group go to the parent group.
              (nconc (gnus-info-params (gnus-get-info name))
                     params)
@@ -7861,6 +8386,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))
        (found nil)
        point treated)
@@ -8014,12 +8545,19 @@ article.  If BACKWARD (the prefix) is non-nil, search backward instead."
   ;; We don't want to change current point nor window configuration.
   (save-excursion
     (save-window-excursion
-      (gnus-message 6 "Executing %s..." (key-description command))
-      ;; We'd like to execute COMMAND interactively so as to give arguments.
-      (gnus-execute header regexp
-                   `(call-interactively ',(key-binding command))
-                   backward)
-      (gnus-message 6 "Executing %s...done" (key-description command)))))
+      (let (gnus-visual
+           gnus-treat-strip-trailing-blank-lines
+           gnus-treat-strip-leading-blank-lines
+           gnus-treat-strip-multiple-blank-lines
+           gnus-treat-hide-boring-headers
+           gnus-treat-fold-newsgroups
+           gnus-article-prepare-hook)
+       (gnus-message 6 "Executing %s..." (key-description command))
+       ;; We'd like to execute COMMAND interactively so as to give arguments.
+       (gnus-execute header regexp
+                     `(call-interactively ',(key-binding command))
+                     backward)
+       (gnus-message 6 "Executing %s...done" (key-description command))))))
 
 (defun gnus-summary-beginning-of-article ()
   "Scroll the article back to the beginning."
@@ -8076,6 +8614,7 @@ to save in."
          (copy-to-buffer buffer (point-min) (point-max))
          (set-buffer buffer)
          (gnus-article-delete-invisible-text)
+         (gnus-remove-text-with-property 'gnus-decoration)
          (when (gnus-visual-p 'article-highlight 'highlight)
            ;; Copy-to-buffer doesn't copy overlay.  So redo
            ;; highlight.
@@ -8116,17 +8655,15 @@ are `C-u g'."
   (cond
    ((numberp arg)
     (gnus-summary-show-article t)
-    (let ((gnus-newsgroup-charset
-          (or (cdr (assq arg gnus-summary-show-article-charset-alist))
-              (mm-read-coding-system
-               "View as charset: "
-               (save-excursion
-                 (set-buffer gnus-article-buffer)
-                 (let ((coding-systems
-                        (detect-coding-region (point) (point-max))))
-                   (or (car-safe coding-systems)
-                       coding-systems))))))
-         (gnus-newsgroup-ignored-charsets 'gnus-all))
+    (let* ((gnus-newsgroup-charset
+           (or (cdr (assq arg gnus-summary-show-article-charset-alist))
+               (mm-read-coding-system
+                "View as charset: " ;; actually it is coding system.
+                (save-excursion
+                  (set-buffer gnus-article-buffer)
+                  (mm-detect-coding-region (point) (point-max))))))
+          (default-mime-charset gnus-newsgroup-charset)
+          (gnus-newsgroup-ignored-charsets 'gnus-all))
       (gnus-summary-select-article nil 'force)
       (let ((deps gnus-newsgroup-dependencies)
            head header lines)
@@ -8197,36 +8734,38 @@ If ARG is a negative number, turn header display off."
 If ARG is a positive number, show the entire header.
 If ARG is a negative number, hide the unwanted header lines."
   (interactive "P")
-  (save-excursion
-    (set-buffer gnus-article-buffer)
-    (save-restriction
+  (let ((window (and (gnus-buffer-live-p gnus-article-buffer)
+                    (get-buffer-window gnus-article-buffer t))))
+    (with-current-buffer gnus-article-buffer
+      (widen)
+      (article-narrow-to-head)
       (let* ((buffer-read-only nil)
             (inhibit-point-motion-hooks t)
-            hidden e)
-       (setq hidden
-             (if (numberp arg)
-                 (>= arg 0)
-               (save-restriction
-                 (article-narrow-to-head)
-                 (gnus-article-hidden-text-p 'headers))))
-       (goto-char (point-min))
-       (when (search-forward "\n\n" nil t)
-         (delete-region (point-min) (1- (point))))
-       (goto-char (point-min))
-       (save-excursion
-         (set-buffer gnus-original-article-buffer)
-         (goto-char (point-min))
-         (setq e (1- (or (search-forward "\n\n" nil t) (point-max)))))
-       (insert-buffer-substring gnus-original-article-buffer 1 e)
-       (save-restriction
-         (narrow-to-region (point-min) (point))
-         (article-decode-encoded-words)
-         (if  hidden
-             (let ((gnus-treat-hide-headers nil)
-                   (gnus-treat-hide-boring-headers nil))
-               (gnus-delete-wash-type 'headers)
-               (gnus-treat-article 'head))
-           (gnus-treat-article 'head)))
+            (hidden (if (numberp arg)
+                        (>= arg 0)
+                      (gnus-article-hidden-text-p 'headers)))
+            s e)
+       (delete-region (point-min) (point-max))
+       (with-current-buffer gnus-original-article-buffer
+         (goto-char (setq s (point-min)))
+         (setq e (if (search-forward "\n\n" nil t)
+                     (1- (point))
+                   (point-max))))
+       (insert-buffer-substring gnus-original-article-buffer s e)
+       (run-hooks 'gnus-article-decode-hook)
+       (if hidden
+           (let ((gnus-treat-hide-headers nil)
+                 (gnus-treat-hide-boring-headers nil))
+             (gnus-delete-wash-type 'headers)
+             (gnus-treat-article 'head))
+         (gnus-treat-article 'head))
+       (widen)
+       (if window
+           (set-window-start window (goto-char (point-min))))
+       (setq gnus-page-broken
+             (when gnus-break-pages
+               (gnus-narrow-to-page)
+               t))
        (gnus-set-mode-line 'article)))))
 
 (defun gnus-summary-show-all-headers ()
@@ -8259,6 +8798,31 @@ forward."
          (message-caesar-buffer-body arg)
          (set-window-start (get-buffer-window (current-buffer)) start))))))
 
+(autoload 'unmorse-region "morse"
+  "Convert morse coded text in region to ordinary ASCII text."
+  t)
+
+(defun gnus-summary-morse-message (&optional arg)
+  "Morse decode the current article."
+  (interactive "P")
+  (gnus-summary-select-article)
+  (let ((mail-header-separator ""))
+    (gnus-eval-in-buffer-window gnus-article-buffer
+      (save-excursion
+       (save-restriction
+         (widen)
+         (let ((pos (window-start))
+               buffer-read-only)
+           (goto-char (point-min))
+           (when (message-goto-body)
+             (gnus-narrow-to-body))
+           (goto-char (point-min))
+           (while (re-search-forward "·" (point-max) t)
+             (replace-match "."))
+           (unmorse-region (point-min) (point-max))
+           (widen)
+           (set-window-start (get-buffer-window (current-buffer)) pos)))))))
+
 (defun gnus-summary-stop-page-breaking ()
   "Stop page breaking in the current article."
   (interactive)
@@ -8282,6 +8846,10 @@ If TO-NEWSGROUP is string, do not prompt for a newsgroup to move to.
 If SELECT-METHOD is non-nil, do not move to a specific newsgroup, but
 re-spool using this method.
 
+When called interactively with TO-NEWSGROUP being nil, the value of
+the variable `gnus-move-split-methods' is used for finding a default
+for the target newsgroup.
+
 For this function to work, both the current newsgroup and the
 newsgroup that you want to move to have to support the `request-move'
 and `request-accept' functions.
@@ -8315,14 +8883,21 @@ ACTION can be either `move' (the default), `crosspost' or `copy'."
        art-group to-method new-xref article to-groups)
     (unless (assq action names)
       (error "Unknown action %s" action))
-    ;; We have to select an article to give
-    ;; `gnus-read-move-group-name' an opportunity to suggest an
-    ;; appropriate default.
-    (unless (gnus-buffer-live-p gnus-original-article-buffer)
-      (gnus-summary-select-article nil nil nil (car articles)))
     ;; Read the newsgroup name.
     (when (and (not to-newsgroup)
               (not select-method))
+      (if (and gnus-move-split-methods
+              (not
+               (and (memq gnus-current-article articles)
+                    (gnus-buffer-live-p gnus-original-article-buffer))))
+         ;; When `gnus-move-split-methods' is non-nil, we have to
+         ;; select an article to give `gnus-read-move-group-name' an
+         ;; opportunity to suggest an appropriate default.  However,
+         ;; we needn't render or mark the article.
+         (let ((gnus-display-mime-function nil)
+               (gnus-article-prepare-hook nil)
+               (gnus-mark-article-hook nil))
+           (gnus-summary-select-article nil nil nil (car articles))))
       (setq to-newsgroup
            (gnus-read-move-group-name
             (cadr (assq action names))
@@ -8405,7 +8980,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))
@@ -8473,9 +9055,8 @@ ACTION can be either `move' (the default), `crosspost' or `copy'."
                       to-group (cdar marks) (list to-article) info)))
                  (setq marks (cdr marks)))
 
-               (gnus-request-set-mark to-group (list (list (list to-article)
-                                                           'add
-                                                           to-marks))))
+               (gnus-request-set-mark
+                to-group (list (list (list to-article) 'add to-marks))))
 
              (gnus-dribble-enter
               (concat "(gnus-group-set-info '"
@@ -8490,11 +9071,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))))
@@ -8512,6 +9102,9 @@ ACTION can be either `move' (the default), `crosspost' or `copy'."
 (defun gnus-summary-copy-article (&optional n to-newsgroup select-method)
   "Move the current article to a different newsgroup.
 If TO-NEWSGROUP is string, do not prompt for a newsgroup to move to.
+When called interactively, if TO-NEWSGROUP is nil, use the value of
+the variable `gnus-move-split-methods' for finding a default target
+newsgroup.
 If SELECT-METHOD is non-nil, do not move to a specific newsgroup, but
 re-spool using this method."
   (interactive "P")
@@ -8528,6 +9121,15 @@ If nil, use to the current newsgroup method."
   :type 'symbol
   :group 'gnus-summary-mail)
 
+(defcustom gnus-summary-display-while-building nil
+  "If not-nil, show and update the summary buffer as it's being built.
+If the value is t, update the buffer after every line is inserted.  If
+the value is an integer (N), update the display every N lines."
+  :group 'gnus-thread
+  :type '(choice (const :tag "off" nil)
+                number
+                (const :tag "frequently" t)))
+
 (defun gnus-summary-respool-article (&optional n method)
   "Respool the current article.
 The article will be squeezed through the mail spooling process again,
@@ -8550,7 +9152,7 @@ latter case, they will be copied into the relevant groups."
                                  (car (gnus-find-method-for-group
                                        gnus-newsgroup-name)))))
                (method
-                (gnus-completing-read
+                (gnus-completing-read-with-default
                  methname "What backend do you want to use when respooling?"
                  methods nil t nil 'gnus-mail-method-history))
                ms)
@@ -8654,8 +9256,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
@@ -8696,12 +9299,17 @@ This will be the case if the article has both been mailed and posted."
          ;; really expired articles as nonexistent.
          (unless (eq es expirable)     ;If nothing was expired, we don't mark.
            (let ((gnus-use-cache nil))
-             (while expirable
-               (unless (memq (car expirable) es)
-                 (when (gnus-data-find (car expirable))
-                   (gnus-summary-mark-article
-                    (car expirable) gnus-canceled-mark)))
-               (setq expirable (cdr expirable))))))
+             (dolist (article expirable)
+               (when (and (not (memq article es))
+                          (gnus-data-find article))
+                 (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 ()
@@ -8732,6 +9340,7 @@ delete these instead."
     (error "Couldn't open server"))
   ;; Compute the list of articles to delete.
   (let ((articles (sort (copy-sequence (gnus-summary-work-articles n)) '<))
+       (nnmail-expiry-target 'delete)
        not-deleted)
     (if (and gnus-novice-user
             (not (gnus-yes-or-no-p
@@ -8749,6 +9358,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)))
@@ -8837,10 +9452,7 @@ groups."
                    (insert ".\n")
                    (let ((nntp-server-buffer (current-buffer)))
                      (setq header (car (gnus-get-newsgroup-headers
-                                        (save-excursion
-                                          (set-buffer gnus-summary-buffer)
-                                          gnus-newsgroup-dependencies)
-                                        t))))
+                                        nil t))))
                    (save-excursion
                      (set-buffer gnus-summary-buffer)
                      (gnus-data-set-header
@@ -8884,13 +9496,6 @@ groups."
   (execute-kbd-macro (concat (this-command-keys) key))
   (gnus-article-edit-done))
 
-(defun gnus-summary-toggle-smiley (&optional arg)
-  "Toggle the display of smilies as small graphical icons."
-  (interactive "P")
-  (save-excursion
-    (set-buffer gnus-article-buffer)
-    (gnus-article-smiley-display arg)))
-
 ;;; Respooling
 
 (defun gnus-summary-respool-query (&optional silent trace)
@@ -9046,12 +9651,21 @@ the actual number of articles marked is returned."
   (interactive "p")
   (gnus-summary-mark-forward n gnus-expirable-mark))
 
+(defun gnus-summary-mark-as-spam (n)
+  "Mark N articles forward as spam.
+If N is negative, mark backward instead.  The difference between N and
+the actual number of articles marked is returned."
+  (interactive "p")
+  (gnus-summary-mark-forward n gnus-spam-mark))
+
 (defun gnus-summary-mark-article-as-replied (article)
   "Mark ARTICLE as replied to and update the summary line.
 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)
@@ -9076,10 +9690,7 @@ ARTICLE can also be a list of articles."
            (not (equal gnus-newsgroup-name (car gnus-article-current))))
     (error "No current article selected"))
   ;; Remove old bookmark, if one exists.
-  (let ((old (assq article gnus-newsgroup-bookmarks)))
-    (when old
-      (setq gnus-newsgroup-bookmarks
-           (delq old gnus-newsgroup-bookmarks))))
+  (gnus-pull article gnus-newsgroup-bookmarks)
   ;; Set the new bookmark, which is on the form
   ;; (article-number . line-number-in-body).
   (push
@@ -9089,8 +9700,7 @@ ARTICLE can also be a list of articles."
           (count-lines
            (min (point)
                 (save-excursion
-                  (goto-char (point-min))
-                  (search-forward "\n\n" nil t)
+                  (article-goto-body)
                   (point)))
            (point))))
    gnus-newsgroup-bookmarks)
@@ -9100,13 +9710,10 @@ ARTICLE can also be a list of articles."
   "Remove the bookmark from the current article."
   (interactive (list (gnus-summary-article-number)))
   ;; Remove old bookmark, if one exists.
-  (let ((old (assq article gnus-newsgroup-bookmarks)))
-    (if old
-       (progn
-         (setq gnus-newsgroup-bookmarks
-               (delq old gnus-newsgroup-bookmarks))
-         (gnus-message 6 "Removed bookmark."))
-      (gnus-message 6 "No bookmark in current article."))))
+  (if (not (assq article gnus-newsgroup-bookmarks))
+      (gnus-message 6 "No bookmark in current article.")
+    (gnus-pull article gnus-newsgroup-bookmarks)
+    (gnus-message 6 "Removed bookmark.")))
 
 ;; Suggested by Daniel Quinlan <quinlan@best.com>.
 (defun gnus-summary-mark-as-dormant (n)
@@ -9145,14 +9752,14 @@ the actual number of articles marked is returned."
 If N is negative, mark backwards instead.  Mark with MARK, ?r by default.
 The difference between N and the actual number of articles marked is
 returned.
-Iff NO-EXPIRE, auto-expiry will be inhibited."
+If NO-EXPIRE, auto-expiry will be inhibited."
   (interactive "p")
   (gnus-summary-show-thread)
   (let ((backward (< n 0))
        (gnus-summary-goto-unread
         (and gnus-summary-goto-unread
              (not (eq gnus-summary-goto-unread 'never))
-             (not (memq mark (list gnus-unread-mark
+             (not (memq mark (list gnus-unread-mark gnus-spam-mark
                                    gnus-ticked-mark gnus-dormant-mark)))))
        (n (abs n))
        (mark (or mark gnus-del-mark)))
@@ -9176,6 +9783,7 @@ Iff NO-EXPIRE, auto-expiry will be inhibited."
   (let ((article (gnus-summary-article-number)))
     (setq gnus-newsgroup-unreads (delq article gnus-newsgroup-unreads))
     (setq gnus-newsgroup-marked (delq article gnus-newsgroup-marked))
+    (setq gnus-newsgroup-spam-marked (delq article gnus-newsgroup-spam-marked))
     (setq gnus-newsgroup-dormant (delq article gnus-newsgroup-dormant))
     (push (cons article mark) gnus-newsgroup-reads)
     ;; Possibly remove from cache, if that is used.
@@ -9207,15 +9815,27 @@ Iff NO-EXPIRE, auto-expiry will be inhibited."
            (gnus-error 1 "Can't mark negative article numbers")
            nil)
        (setq gnus-newsgroup-marked (delq article gnus-newsgroup-marked))
+       (setq gnus-newsgroup-spam-marked
+             (delq article gnus-newsgroup-spam-marked))
        (setq gnus-newsgroup-dormant (delq article gnus-newsgroup-dormant))
        (setq gnus-newsgroup-expirable (delq article gnus-newsgroup-expirable))
        (setq gnus-newsgroup-reads (delq article gnus-newsgroup-reads))
        (cond ((= mark gnus-ticked-mark)
-              (push article gnus-newsgroup-marked))
+              (setq gnus-newsgroup-marked
+                    (gnus-add-to-sorted-list gnus-newsgroup-marked
+                                             article)))
+             ((= mark gnus-spam-mark)
+              (setq gnus-newsgroup-spam-marked
+                    (gnus-add-to-sorted-list gnus-newsgroup-spam-marked
+                                             article)))
              ((= mark gnus-dormant-mark)
-              (push article gnus-newsgroup-dormant))
+              (setq gnus-newsgroup-dormant
+                    (gnus-add-to-sorted-list gnus-newsgroup-dormant
+                                             article)))
              (t
-              (push article gnus-newsgroup-unreads)))
+              (setq gnus-newsgroup-unreads
+                    (gnus-add-to-sorted-list gnus-newsgroup-unreads
+                                             article))))
        (gnus-pull article gnus-newsgroup-reads)
 
        ;; See whether the article is to be put in the cache.
@@ -9239,7 +9859,7 @@ Four MARK strings are reserved: `? ' (unread), `?!' (ticked),
 If MARK is nil, then the default character `?r' is used.
 If ARTICLE is nil, then the article on the current line will be
 marked.
-Iff NO-EXPIRE, auto-expiry will be inhibited."
+If NO-EXPIRE, auto-expiry will be inhibited."
   ;; The mark might be a string.
   (when (stringp mark)
     (setq mark (aref mark 0)))
@@ -9260,6 +9880,7 @@ Iff NO-EXPIRE, auto-expiry will be inhibited."
        (error "No article on current line"))
       (if (not (if (or (= mark gnus-unread-mark)
                       (= mark gnus-ticked-mark)
+                      (= mark gnus-spam-mark)
                       (= mark gnus-dormant-mark))
                   (gnus-mark-article-as-unread article mark)
                 (gnus-mark-article-as-read article mark)))
@@ -9305,6 +9926,19 @@ Iff NO-EXPIRE, auto-expiry will be inhibited."
     (gnus-run-hooks 'gnus-summary-update-hook))
   t)
 
+(defun gnus-summary-update-download-mark (article)
+  "Update the download mark."
+  (gnus-summary-update-mark
+   (cond ((memq article gnus-newsgroup-undownloaded) 
+          gnus-undownloaded-mark)
+         (gnus-newsgroup-agentized
+          gnus-downloaded-mark)
+         (t
+          gnus-no-mark))
+   'download)
+  (gnus-summary-update-line t)
+  t)
+
 (defun gnus-summary-update-mark (mark type)
   (let ((forward (cdr (assq type gnus-summary-mark-positions)))
        (buffer-read-only nil))
@@ -9327,12 +9961,14 @@ Iff NO-EXPIRE, auto-expiry will be inhibited."
   "Enter ARTICLE in the pertinent lists and remove it from others."
   ;; Make the article expirable.
   (let ((mark (or mark gnus-del-mark)))
-    (if (= mark gnus-expirable-mark)
-       (push article gnus-newsgroup-expirable)
-      (setq gnus-newsgroup-expirable (delq article gnus-newsgroup-expirable)))
+    (setq gnus-newsgroup-expirable
+         (if (= mark gnus-expirable-mark)
+             (gnus-add-to-sorted-list gnus-newsgroup-expirable article)
+           (delq article gnus-newsgroup-expirable)))
     ;; Remove from unread and marked lists.
     (setq gnus-newsgroup-unreads (delq article gnus-newsgroup-unreads))
     (setq gnus-newsgroup-marked (delq article gnus-newsgroup-marked))
+    (setq gnus-newsgroup-spam-marked (delq article gnus-newsgroup-spam-marked))
     (setq gnus-newsgroup-dormant (delq article gnus-newsgroup-dormant))
     (push (cons article mark) gnus-newsgroup-reads)
     ;; Possibly remove from cache, if that is used.
@@ -9348,6 +9984,7 @@ Iff NO-EXPIRE, auto-expiry will be inhibited."
          (gnus-error 1 "Can't mark negative article numbers")
          nil)
       (setq gnus-newsgroup-marked (delq article gnus-newsgroup-marked)
+           gnus-newsgroup-spam-marked (delq article gnus-newsgroup-spam-marked)
            gnus-newsgroup-dormant (delq article gnus-newsgroup-dormant)
            gnus-newsgroup-expirable (delq article gnus-newsgroup-expirable)
            gnus-newsgroup-unreads (delq article gnus-newsgroup-unreads))
@@ -9357,11 +9994,18 @@ Iff NO-EXPIRE, auto-expiry will be inhibited."
        (gnus-dup-unsuppress-article article))
 
       (cond ((= mark gnus-ticked-mark)
-            (push article gnus-newsgroup-marked))
+            (setq gnus-newsgroup-marked
+                  (gnus-add-to-sorted-list gnus-newsgroup-marked article)))
+           ((= mark gnus-spam-mark)
+            (setq gnus-newsgroup-spam-marked
+                  (gnus-add-to-sorted-list gnus-newsgroup-spam-marked
+                                           article)))
            ((= mark gnus-dormant-mark)
-            (push article gnus-newsgroup-dormant))
+            (setq gnus-newsgroup-dormant
+                  (gnus-add-to-sorted-list gnus-newsgroup-dormant article)))
            (t
-            (push article gnus-newsgroup-unreads)))
+            (setq gnus-newsgroup-unreads
+                  (gnus-add-to-sorted-list gnus-newsgroup-unreads article))))
       (gnus-pull article gnus-newsgroup-reads)
       t)))
 
@@ -9569,8 +10213,13 @@ The number of articles marked as read is returned."
              (progn
                (when all
                  (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)
@@ -9579,12 +10228,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)))
@@ -9614,7 +10263,9 @@ If ALL is non-nil, also mark ticked and dormant articles as read."
   (gnus-summary-position-point))
 
 (defun gnus-summary-catchup-all (&optional quietly)
-  "Mark all articles in this newsgroup as read."
+  "Mark all articles in this newsgroup as read.
+This command is dangerous.  Normally, you want \\[gnus-summary-catchup]
+instead, which marks only unread articles as read."
   (interactive "P")
   (gnus-summary-catchup t quietly))
 
@@ -9631,7 +10282,9 @@ If QUIETLY is non-nil, no questions will be asked."
       (gnus-summary-exit))))
 
 (defun gnus-summary-catchup-all-and-exit (&optional quietly)
-  "Mark all articles in this newsgroup as read, and then exit."
+  "Mark all articles in this newsgroup as read, and then exit.
+This command is dangerous.  Normally, you want \\[gnus-summary-catchup-and-exit]
+instead, which marks only unread articles as read."
   (interactive "P")
   (gnus-summary-catchup-and-exit t quietly))
 
@@ -9799,8 +10452,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?
@@ -9809,18 +10462,49 @@ Returns nil if no thread was there to be shown."
       (goto-char orig)
       (gnus-summary-position-point))))
 
-(defun gnus-summary-hide-all-threads ()
-  "Hide all thread subtrees."
+(defun gnus-summary-maybe-hide-threads ()
+  "If requested, hide the threads that should be hidden."
+  (when (and gnus-show-threads
+            gnus-thread-hide-subtree)
+    (gnus-summary-hide-all-threads
+     (if (or (consp gnus-thread-hide-subtree)
+            (gnus-functionp gnus-thread-hide-subtree))
+        (gnus-make-predicate gnus-thread-hide-subtree)
+       nil))))
+
+;;; Hiding predicates.
+
+(defun gnus-article-unread-p (header)
+  (memq (mail-header-number header) gnus-newsgroup-unreads))
+
+(defun gnus-article-unseen-p (header)
+  (memq (mail-header-number header) gnus-newsgroup-unseen))
+
+(defun gnus-map-articles (predicate articles)
+  "Map PREDICATE over ARTICLES and return non-nil if any predicate is non-nil."
+  (apply 'gnus-or (mapcar predicate
+                         (mapcar 'gnus-summary-article-header articles))))
+
+(defun gnus-summary-hide-all-threads (&optional predicate)
+  "Hide all thread subtrees.
+If PREDICATE is supplied, threads that satisfy this predicate
+will not be hidden."
   (interactive)
   (save-excursion
     (goto-char (point-min))
-    (gnus-summary-hide-thread)
-    (while (zerop (gnus-summary-next-thread 1 t))
-      (gnus-summary-hide-thread)))
+    (let ((end nil))
+      (while (not end)
+       (when (or (not predicate)
+                 (gnus-map-articles
+                  predicate (gnus-summary-article-children)))
+           (gnus-summary-hide-thread))
+       (setq end (not (zerop (gnus-summary-next-thread 1 t)))))))
   (gnus-summary-position-point))
 
 (defun gnus-summary-hide-thread ()
   "Hide thread subtrees.
+If PREDICATE is supplied, threads that satisfy this predicate
+will not be hidden.
 Returns nil if no threads were there to be hidden."
   (interactive)
   (let ((buffer-read-only nil)
@@ -9969,6 +10653,12 @@ Argument REVERSE means reverse order."
   (interactive "P")
   (gnus-summary-sort 'number reverse))
 
+(defun gnus-summary-sort-by-random (&optional reverse)
+  "Randomize the order in the summary buffer.
+Argument REVERSE means to randomize in reverse order."
+  (interactive "P")
+  (gnus-summary-sort 'random reverse))
+
 (defun gnus-summary-sort-by-author (&optional reverse)
   "Sort the summary buffer by author name alphabetically.
 If `case-fold-search' is non-nil, case of letters is ignored.
@@ -10016,8 +10706,7 @@ Argument REVERSE means reverse order."
     ;; We do the sorting by regenerating the threads.
     (gnus-summary-prepare)
     ;; Hide subthreads if needed.
-    (when (and gnus-show-threads gnus-thread-hide-subtree)
-      (gnus-summary-hide-all-threads))))
+    (gnus-summary-maybe-hide-threads)))
 
 (defun gnus-summary-sort (predicate reverse)
   "Sort summary buffer by PREDICATE.  REVERSE means reverse order."
@@ -10040,8 +10729,7 @@ Argument REVERSE means reverse order."
     ;; We do the sorting by regenerating the threads.
     (gnus-summary-prepare)
     ;; Hide subthreads if needed.
-    (when (and gnus-show-threads gnus-thread-hide-subtree)
-      (gnus-summary-hide-all-threads))))
+    (gnus-summary-maybe-hide-threads)))
 
 ;; Summary saving commands.
 
@@ -10083,20 +10771,22 @@ The variable `gnus-default-article-saver' specifies the saver function."
     (gnus-set-mode-line 'summary)
     n))
 
-(defun gnus-summary-pipe-output (&optional arg)
+(defun gnus-summary-pipe-output (&optional arg headers)
   "Pipe the current article to a subprocess.
 If N is a positive number, pipe the N next articles.
 If N is a negative number, pipe the N previous articles.
 If N is nil and any articles have been marked with the process mark,
-pipe those articles instead."
-  (interactive "P")
+pipe those articles instead.
+If HEADERS (the symbolic prefix), include the headers, too."
+  (interactive (gnus-interactive "P\ny"))
   (require 'gnus-art)
-  (let ((gnus-default-article-saver 'gnus-summary-save-in-pipe))
+  (let ((gnus-default-article-saver 'gnus-summary-save-in-pipe)
+       (gnus-save-all-headers (or headers gnus-save-all-headers)))
     (gnus-summary-save-article arg t))
   (let ((buffer (get-buffer "*Shell Command Output*")))
-    (if (and buffer
-            (with-current-buffer buffer (> (point-max) (point-min))))
-       (gnus-configure-windows 'pipe))))
+    (when (and buffer
+              (not (zerop (buffer-size buffer))))
+      (gnus-configure-windows 'pipe))))
 
 (defun gnus-summary-save-article-mail (&optional arg)
   "Append the current article to an mail file.
@@ -10233,23 +10923,26 @@ save those articles instead."
         (to-newsgroup
          (cond
           ((null split-name)
-           (gnus-completing-read default prom
-                                 gnus-active-hashtb
-                                 'gnus-valid-move-group-p
-                                 nil prefix
-                                 'gnus-group-history))
+           (gnus-completing-read-with-default
+            default prom
+            gnus-active-hashtb
+            'gnus-valid-move-group-p
+            nil prefix
+            'gnus-group-history))
           ((= 1 (length split-name))
-           (gnus-completing-read (car split-name) prom
-                                 gnus-active-hashtb
-                                 'gnus-valid-move-group-p
-                                 nil nil
-                                 'gnus-group-history))
+           (gnus-completing-read-with-default
+            (car split-name) prom
+            gnus-active-hashtb
+            'gnus-valid-move-group-p
+            nil nil
+            'gnus-group-history))
           (t
-           (gnus-completing-read nil prom
-                                 (mapcar (lambda (el) (list el))
-                                         (nreverse split-name))
-                                 nil nil nil
-                                 'gnus-group-history))))
+           (gnus-completing-read-with-default
+            nil prom
+            (mapcar (lambda (el) (list el))
+                    (nreverse split-name))
+            nil nil nil
+            'gnus-group-history))))
         (to-method (gnus-server-to-method (gnus-group-method to-newsgroup))))
     (when to-newsgroup
       (if (or (string= to-newsgroup "")
@@ -10289,7 +10982,9 @@ If REVERSE, save parts that do not match TYPE."
     (save-excursion
       (set-buffer gnus-article-buffer)
       (let ((handles (or gnus-article-mime-handles
-                        (mm-dissect-buffer) (mm-uu-dissect))))
+                        (mm-dissect-buffer nil gnus-article-loose-mime)
+                        (and gnus-article-emulate-mime
+                             (mm-uu-dissect)))))
        (when handles
          (gnus-summary-save-parts-1 type dir handles reverse)
          (unless gnus-article-mime-handles ;; Don't destroy this case.
@@ -10376,7 +11071,9 @@ If REVERSE, save parts that do not match TYPE."
          (gnus-data-enter
           after-article gnus-reffed-article-number
           gnus-unread-mark b (car pslist) 0 (- e b))
-         (push gnus-reffed-article-number gnus-newsgroup-unreads)
+         (setq gnus-newsgroup-unreads
+               (gnus-add-to-sorted-list gnus-newsgroup-unreads
+                                        gnus-reffed-article-number))
          (setq gnus-reffed-article-number (1- gnus-reffed-article-number))
          (setq pslist (cdr pslist)))))))
 
@@ -10507,8 +11204,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
@@ -10535,43 +11232,55 @@ If REVERSE, save parts that do not match TYPE."
           (setq gnus-newsgroup-selected-overlay (gnus-make-overlay from to))
           'face gnus-summary-selected-face))))))
 
-;; New implementation by Christian Limpach <Christian.Limpach@nice.ch>.
+(defvar gnus-summary-highlight-line-cached nil)
+(defvar gnus-summary-highlight-line-trigger nil)
+
+(defun gnus-summary-highlight-line-0 ()
+  (if (and (eq gnus-summary-highlight-line-trigger 
+               gnus-summary-highlight)
+           gnus-summary-highlight-line-cached)
+      gnus-summary-highlight-line-cached
+    (setq gnus-summary-highlight-line-trigger gnus-summary-highlight
+          gnus-summary-highlight-line-cached
+          (let* ((cond (list 'cond))
+                 (c cond)
+                 (list gnus-summary-highlight))
+            (while list
+              (setcdr c (cons (list (caar list) (list 'quote (cdar list)))
+                             nil))
+              (setq c (cdr c)
+                    list (cdr list)))
+            (gnus-byte-compile (list 'lambda nil cond))))))
+
 (defun gnus-summary-highlight-line ()
   "Highlight current line according to `gnus-summary-highlight'."
-  (let* ((list gnus-summary-highlight)
-        (p (point))
-        (end (progn (end-of-line) (point)))
-        ;; now find out where the line starts and leave point there.
-        (beg (progn (beginning-of-line) (point)))
-        (article (gnus-summary-article-number))
-        (score (or (cdr (assq (or article gnus-current-article)
+  (let* ((beg (gnus-point-at-bol))
+        (article (or (gnus-summary-article-number) gnus-current-article))
+        (score (or (cdr (assq article
                               gnus-newsgroup-scored))
                    gnus-summary-default-score 0))
         (mark (or (gnus-summary-article-mark) gnus-unread-mark))
-        (inhibit-read-only t))
-    ;; Eval the cars of the lists until we find a match.
-    (let ((default gnus-summary-default-score)
-         (default-high gnus-summary-default-high-score)
-         (default-low gnus-summary-default-low-score))
-      (while (and list
-                 (not (eval (caar list))))
-       (setq list (cdr list))))
-    (let ((face (cdar list)))
+        (inhibit-read-only t)
+        (default gnus-summary-default-score)
+        (default-high gnus-summary-default-high-score)
+        (default-low gnus-summary-default-low-score)
+        (uncached (memq article gnus-newsgroup-undownloaded))
+        (downloaded (not uncached)))
+    (let ((face (funcall (gnus-summary-highlight-line-0))))
       (unless (eq face (get-text-property beg 'face))
        (gnus-put-text-property-excluding-characters-with-faces
-        beg end 'face
+        beg (gnus-point-at-eol) 'face
         (setq face (if (boundp face) (symbol-value face) face)))
        (when gnus-summary-highlight-line-function
-         (funcall gnus-summary-highlight-line-function article face))))
-    (goto-char p)))
+         (funcall gnus-summary-highlight-line-function article face))))))
 
 (defun gnus-update-read-articles (group unread &optional compute)
-  "Update the list of read articles in GROUP."
+  "Update the list of read articles in GROUP.
+UNREAD is a sorted list."
   (let* ((active (or gnus-newsgroup-active (gnus-active group)))
         (entry (gnus-gethash group gnus-newsrc-hashtb))
         (info (nth 2 entry))
         (prev 1)
-        (unread (sort (copy-sequence unread) '<))
         read)
     (if (or (not info) (not active))
        ;; There is no info on this group if it was, in fact,
@@ -10693,46 +11402,29 @@ If REVERSE, save parts that do not match TYPE."
 ;;;
 
 (defun gnus-mime-extract-message/rfc822 (entity situation)
-  (let (group article num cwin swin cur)
-    (with-temp-buffer
-      (mime-insert-entity-content entity)
-      (setq group (or (cdr (assq 'group situation))
-                     (completing-read "Group: "
-                                      gnus-active-hashtb
-                                      nil
-                                      (gnus-read-active-file-p)
-                                      gnus-newsgroup-name))
-           article (gnus-request-accept-article group)))
-    (when (and (consp article)
-              (numberp (setq article (cdr article))))
-      (setq num (1+ (or (cdr (assq 'number situation)) 0))
-           cwin (get-buffer-window (current-buffer) t))
-      (save-window-excursion
-       (if (setq swin (get-buffer-window gnus-summary-buffer t))
-           (select-window swin)
-         (set-buffer gnus-summary-buffer))
-       (setq cur gnus-current-article)
-       (forward-line num)
-       (let (gnus-show-threads)
-         (gnus-summary-goto-subject article t))
-       (gnus-summary-clear-mark-forward 1)
-       (gnus-summary-goto-subject cur))
-      (when (and cwin (window-frame cwin))
-       (select-frame (window-frame cwin)))
-      (when (boundp 'mime-acting-situation-to-override)
-       (set-alist 'mime-acting-situation-to-override
-                  'group
-                  group)
-       (set-alist 'mime-acting-situation-to-override
-                  'after-method
-                  `(progn
-                     (save-current-buffer
-                       (set-buffer gnus-group-buffer)
-                       (gnus-activate-group ,group))
-                     (gnus-summary-goto-article ,cur
-                                                gnus-show-all-headers)))
-       (set-alist 'mime-acting-situation-to-override
-                  'number num)))))
+  "Burst a forwarded article."
+  (save-excursion
+    (set-buffer gnus-summary-buffer)
+    (let* ((group (completing-read "Group: " gnus-active-hashtb nil t
+                                  gnus-newsgroup-name 'gnus-group-history))
+          (gnus-group-marked (list group))
+          article info)
+      (with-temp-buffer
+       (mime-insert-entity-content entity)
+       (setq article (gnus-request-accept-article group)))
+      (when (and (consp article)
+                (numberp (setq article (cdr article))))
+       (setq info (gnus-get-info group))
+       (gnus-info-set-read info
+                           (gnus-remove-from-range (gnus-info-read info)
+                                                   (list article)))
+       (when (string-equal group gnus-newsgroup-name)
+         (forward-line 1)
+         (let (gnus-show-threads)
+           (gnus-summary-goto-subject article t))
+         (gnus-summary-clear-mark-forward 1))
+       (set-buffer gnus-group-buffer)
+       (gnus-group-get-new-news-this-group nil t)))))
 
 (mime-add-condition
  'action '((type . message)(subtype . rfc822)
@@ -10773,20 +11465,52 @@ If REVERSE, save parts that do not match TYPE."
 ;;; @ end
 ;;;
 
+(defun gnus-summary-inherit-default-charset ()
+  "Import `default-mime-charset' from summary buffer.
+Also take care of `default-mime-charset-unlimited' if the LIMIT version
+of FLIM is used."
+  (if (buffer-live-p gnus-summary-buffer)
+      (let (d-m-c d-m-c-u)
+       (with-current-buffer gnus-summary-buffer
+         (setq d-m-c (if (local-variable-p 'default-mime-charset
+                                           gnus-summary-buffer)
+                         default-mime-charset
+                       t)
+               ;; LIMIT
+               d-m-c-u (if (local-variable-p 'default-mime-charset-unlimited
+                                             gnus-summary-buffer)
+                           (symbol-value 'default-mime-charset-unlimited)
+                         t)))
+       (if (eq t d-m-c)
+           (kill-local-variable 'default-mime-charset)
+         (set (make-local-variable 'default-mime-charset) d-m-c))
+       (if (eq t d-m-c-u)
+           (kill-local-variable 'default-mime-charset-unlimited)
+         (set (make-local-variable 'default-mime-charset-unlimited)
+              d-m-c-u)))))
+
 (defun gnus-summary-setup-default-charset ()
   "Setup newsgroup default charset."
-  (if (equal gnus-newsgroup-name "nndraft:drafts")
-      (setq gnus-newsgroup-charset nil)
-    (let* ((ignored-charsets
-           (or gnus-newsgroup-ephemeral-ignored-charsets
-               (append
-                (and gnus-newsgroup-name
-                     (gnus-parameter-ignored-charsets gnus-newsgroup-name))
-                gnus-newsgroup-ignored-charsets))))
+  (if (member gnus-newsgroup-name '("nndraft:delayed" "nndraft:drafts"))
+      (progn
+       (setq gnus-newsgroup-charset nil)
+       (set (make-local-variable 'default-mime-charset) nil)
+       (when (boundp 'default-mime-charset-unlimited);; LIMIT
+         (set (make-local-variable 'default-mime-charset-unlimited) nil)))
+    (let ((ignored-charsets
+          (or gnus-newsgroup-ephemeral-ignored-charsets
+              (append
+               (and gnus-newsgroup-name
+                    (gnus-parameter-ignored-charsets gnus-newsgroup-name))
+               gnus-newsgroup-ignored-charsets)))
+         charset)
       (setq gnus-newsgroup-charset
            (or gnus-newsgroup-ephemeral-charset
-               (and gnus-newsgroup-name
-                    (gnus-parameter-charset gnus-newsgroup-name))
+               (when (and gnus-newsgroup-name
+                          (setq charset (gnus-parameter-charset
+                                         gnus-newsgroup-name)))
+                 (make-local-variable 'default-mime-charset)
+                 (setq default-mime-charset charset))
                gnus-default-charset))
       (set (make-local-variable 'gnus-newsgroup-ignored-charsets)
           ignored-charsets))))
@@ -11011,9 +11735,10 @@ returned."
 
 (defun gnus-summary-insert-articles (articles)
   (when (setq articles
-             (gnus-set-difference articles
-                                  (mapcar (lambda (h) (mail-header-number h))
-                                          gnus-newsgroup-headers)))
+             (gnus-sorted-difference articles
+                                     (mapcar (lambda (h)
+                                               (mail-header-number h))
+                                             gnus-newsgroup-headers)))
     (setq gnus-newsgroup-headers
          (merge 'list
                 gnus-newsgroup-headers
@@ -11051,60 +11776,92 @@ If ALL is non-nil, already read articles become readable.
 If ALL is a number, fetch this number of articles."
   (interactive "P")
   (prog1
-      (let ((old (mapcar 'car gnus-newsgroup-data))
-           (i (car gnus-newsgroup-active))
+      (let ((old (sort (mapcar 'car gnus-newsgroup-data) '<))
            older len)
-       (while (<= i (cdr gnus-newsgroup-active))
-         (or (memq i old) (push i older))
-         (incf i))
-       (setq len (length older))
+       (setq older
+             ;; Some nntp servers lie about their active range.  When
+             ;; this happens, the active range can be in the millions.
+             ;; Use a compressed range to avoid creating a huge list.
+             (gnus-range-difference (list gnus-newsgroup-active) old))
+       (setq len (gnus-range-length older))
        (cond
         ((null older) nil)
         ((numberp all)
          (if (< all len)
-             (setq older (subseq older 0 all))))
-        (all nil)
+             (let ((older-range (nreverse older)))
+               (setq older nil)
+
+               (while (> all 0)
+                 (let* ((r (pop older-range))
+                        (min (if (numberp r) r (car r)))
+                        (max (if (numberp r) r (cdr r))))
+                   (while (and (<= min max)
+                               (> all 0))
+                     (push max older)
+                     (setq all (1- all)
+                           max (1- max))))))
+           (setq older (gnus-uncompress-range older))))
+        (all
+         (setq older (gnus-uncompress-range older)))
         (t
-         (if (and (numberp gnus-large-newsgroup)
+         (when (and (numberp gnus-large-newsgroup)
                   (> len gnus-large-newsgroup))
-             (let ((input
-                    (read-string
-                     (format
-                      "How many articles from %s (default %d): "
-                      (gnus-limit-string
-                       (gnus-group-decoded-name gnus-newsgroup-name) 35)
-                      len))))
+             (let* ((cursor-in-echo-area nil)
+                    (initial (gnus-parameter-large-newsgroup-initial
+                              gnus-newsgroup-name))
+                    (input
+                     (read-string
+                      (format
+                       "How many articles from %s (%s %d): "
+                       (gnus-limit-string
+                        (gnus-group-decoded-name gnus-newsgroup-name) 35)
+                       (if initial "max" "default")
+                       len)
+                      (if initial
+                          (cons (number-to-string initial)
+                                0)))))
                (unless (string-match "^[ \t]*$" input)
                  (setq all (string-to-number input))
                  (if (< all len)
-                     (setq older (subseq older 0 all))))))))
+                     (let ((older-range (nreverse older)))
+                       (setq older nil)
+
+                       (while (> all 0)
+                         (let* ((r (pop older-range))
+                                (min (if (numberp r) r (car r)))
+                                (max (if (numberp r) r (cdr r))))
+                           (while (and (<= min max)
+                                       (> all 0))
+                             (push max older)
+                             (setq all (1- all)
+                                   max (1- max))))))))))
+         (setq older (gnus-uncompress-range older))))
        (if (not older)
            (message "No old news.")
          (gnus-summary-insert-articles older)
-         (gnus-summary-limit (gnus-union older old))))
+         (gnus-summary-limit (gnus-sorted-nunion old older))))
     (gnus-summary-position-point)))
 
 (defun gnus-summary-insert-new-articles ()
   "Insert all new articles in this group."
   (interactive)
   (prog1
-      (let ((old (mapcar 'car gnus-newsgroup-data))
+      (let ((old (sort (mapcar 'car gnus-newsgroup-data) '<))
            (old-active gnus-newsgroup-active)
            (nnmail-fetched-sources (list t))
            i new)
        (setq gnus-newsgroup-active
              (gnus-activate-group gnus-newsgroup-name 'scan))
-       (setq i (1+ (cdr old-active)))
-       (while (<= i (cdr gnus-newsgroup-active))
+       (setq i (cdr gnus-newsgroup-active))
+       (while (> i (cdr old-active))
          (push i new)
-         (incf i))
+         (decf i))
        (if (not new)
            (message "No gnus is bad news.")
-         (setq new (nreverse new))
          (gnus-summary-insert-articles new)
          (setq gnus-newsgroup-unreads
-               (append gnus-newsgroup-unreads new))
-         (gnus-summary-limit (gnus-union old new))))
+               (gnus-sorted-nunion gnus-newsgroup-unreads new))
+         (gnus-summary-limit (gnus-sorted-nunion old new))))
     (gnus-summary-position-point)))
 
 (gnus-summary-make-all-marking-commands)