*** empty log message ***
[gnus] / lisp / gnus-sum.el
index 5528d24..19ab7e6 100644 (file)
@@ -1,5 +1,5 @@
 ;;; gnus-sum.el --- summary mode commands for Gnus
 ;;; gnus-sum.el --- summary mode commands for Gnus
-;; Copyright (C) 1996 Free Software Foundation, Inc.
+;; Copyright (C) 1996,97 Free Software Foundation, Inc.
 
 ;; Author: Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
 ;; Keywords: news
 
 ;; Author: Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
 ;; Keywords: news
 (require 'gnus-int)
 (require 'gnus-undo)
 
 (require 'gnus-int)
 (require 'gnus-undo)
 
-(defgroup gnus-summary nil
-  "Summary buffers."
-  :group 'gnus)
-
 (defcustom gnus-kill-summary-on-exit t
   "*If non-nil, kill the summary buffer when you exit from it.
 If nil, the summary will become a \"*Dead Summary*\" buffer, and
 it will be killed sometime later."
 (defcustom gnus-kill-summary-on-exit t
   "*If non-nil, kill the summary buffer when you exit from it.
 If nil, the summary will become a \"*Dead Summary*\" buffer, and
 it will be killed sometime later."
-  :group 'gnus-summary
+  :group 'gnus-summary-exit
   :type 'boolean)
 
 (defcustom gnus-fetch-old-headers nil
   :type 'boolean)
 
 (defcustom gnus-fetch-old-headers nil
@@ -55,7 +51,7 @@ This variable can also be a number.  In that case, no more than that
 number of old headers will be fetched.
 
 The server has to support NOV for any of this to work."
 number of old headers will be fetched.
 
 The server has to support NOV for any of this to work."
-  :group 'gnus-summary
+  :group 'gnus-thread
   :type '(choice (const :tag "off" nil)
                 (const some)
                 number
   :type '(choice (const :tag "off" nil)
                 (const some)
                 number
@@ -83,7 +79,7 @@ the parent and mark all the step-children as such.
 If this variable is `empty', the \"children\" are printed with empty
 subject fields.         (Or rather, they will be printed with a string
 given by the `gnus-summary-same-subject' variable.)"
 If this variable is `empty', the \"children\" are printed with empty
 subject fields.         (Or rather, they will be printed with a string
 given by the `gnus-summary-same-subject' variable.)"
-  :group 'gnus-summary
+  :group 'gnus-thread
   :type '(choice (const :tag "off" nil)
                 (const none)
                 (const dummy)
   :type '(choice (const :tag "off" nil)
                 (const none)
                 (const dummy)
@@ -95,7 +91,7 @@ given by the `gnus-summary-same-subject' variable.)"
 As loose thread gathering is done on subjects only, that means that
 there can be many false gatherings performed.  By rooting out certain
 common subjects, gathering might become saner."
 As loose thread gathering is done on subjects only, that means that
 there can be many false gatherings performed.  By rooting out certain
 common subjects, gathering might become saner."
-  :group 'gnus-summary
+  :group 'gnus-thread
   :type 'regexp)
 
 (defcustom gnus-summary-gather-subject-limit nil
   :type 'regexp)
 
 (defcustom gnus-summary-gather-subject-limit nil
@@ -108,14 +104,14 @@ same few characters will be incorrectly gathered.
 
 If this variable is `fuzzy', Gnus will use a fuzzy algorithm when
 comparing subjects."
 
 If this variable is `fuzzy', Gnus will use a fuzzy algorithm when
 comparing subjects."
-  :group 'gnus-summary
+  :group 'gnus-thread
   :type '(choice (const :tag "off" nil)
                 (const fuzzy)
                 (sexp :menu-tag "on" t)))
 
 (defcustom gnus-simplify-ignored-prefixes nil
   "*Regexp, matches for which are removed from subject lines when simplifying fuzzily."
   :type '(choice (const :tag "off" nil)
                 (const fuzzy)
                 (sexp :menu-tag "on" t)))
 
 (defcustom gnus-simplify-ignored-prefixes nil
   "*Regexp, matches for which are removed from subject lines when simplifying fuzzily."
-  :group 'gnus-summary
+  :group 'gnus-thread
   :type '(choice (const :tag "off" nil)
                 regexp))
 
   :type '(choice (const :tag "off" nil)
                 regexp))
 
@@ -124,7 +120,7 @@ comparing subjects."
 If `some', only fill in the gaps that are needed to tie loose threads
 together.  If `more', fill in all leaf nodes that Gnus can find.  If
 non-nil and non-`some', fill in all gaps that Gnus manages to guess."
 If `some', only fill in the gaps that are needed to tie loose threads
 together.  If `more', fill in all leaf nodes that Gnus can find.  If
 non-nil and non-`some', fill in all gaps that Gnus manages to guess."
-  :group 'gnus-summary
+  :group 'gnus-thread
   :type '(choice (const :tag "off" nil)
                 (const some)
                 (const more)
   :type '(choice (const :tag "off" nil)
                 (const some)
                 (const more)
@@ -136,7 +132,7 @@ There are two pre-defined functions: `gnus-gather-threads-by-subject',
 which only takes Subjects into consideration; and
 `gnus-gather-threads-by-references', which compared the References
 headers of the articles to find matches."
 which only takes Subjects into consideration; and
 `gnus-gather-threads-by-references', which compared the References
 headers of the articles to find matches."
-  :group 'gnus-summary
+  :group 'gnus-thread
   :type '(set (function-item gnus-gather-threads-by-subject)
              (function-item gnus-gather-threads-by-references)
              (function :tag "other")))
   :type '(set (function-item gnus-gather-threads-by-subject)
              (function-item gnus-gather-threads-by-references)
              (function :tag "other")))
@@ -146,14 +142,16 @@ headers of the articles to find matches."
   "*String indicating that the current article has the same subject as the previous.
 This variable will only be used if the value of
 `gnus-summary-make-false-root' is `empty'."
   "*String indicating that the current article has the same subject as the previous.
 This variable will only be used if the value of
 `gnus-summary-make-false-root' is `empty'."
-  :group 'gnus-summary
+  :group 'gnus-summary-format
   :type 'string)
 
 (defcustom gnus-summary-goto-unread t
   :type 'string)
 
 (defcustom gnus-summary-goto-unread t
-  "*If non-nil, marking commands will go to the next unread article.
-If `never', \\<gnus-summary-mode-map>\\[gnus-summary-next-page] will go to the next article,
-whether it is read or not."
-  :group 'gnus-summary
+  "*If t, marking commands will go to the next unread article.
+If `never', commands that usually go to the next unread article, will
+go to the next article, whether it is read or not.
+If nil, only the marking commands will go to the next (un)read article."
+  :group 'gnus-summary-marks
+  :link '(custom-manual "(gnus)Setting Marks")
   :type '(choice (const :tag "off" nil)
                 (const never)
                 (sexp :menu-tag "on" t)))
   :type '(choice (const :tag "off" nil)
                 (const never)
                 (sexp :menu-tag "on" t)))
@@ -161,7 +159,7 @@ whether it is read or not."
 (defcustom gnus-summary-default-score 0
   "*Default article score level.
 If this variable is nil, scoring will be disabled."
 (defcustom gnus-summary-default-score 0
   "*Default article score level.
 If this variable is nil, scoring will be disabled."
-  :group 'gnus-summary
+  :group 'gnus-score-default
   :type '(choice (const :tag "disable")
                 integer))
 
   :type '(choice (const :tag "disable")
                 integer))
 
@@ -169,7 +167,7 @@ If this variable is nil, scoring will be disabled."
   "*Fuzziness factor for the zcore in the summary buffer.
 Articles with scores closer than this to `gnus-summary-default-score'
 will not be marked."
   "*Fuzziness factor for the zcore in the summary buffer.
 Articles with scores closer than this to `gnus-summary-default-score'
 will not be marked."
-  :group 'gnus-summary
+  :group 'gnus-summary-format
   :type 'integer)
 
 (defcustom gnus-simplify-subject-fuzzy-regexp nil
   :type 'integer)
 
 (defcustom gnus-simplify-subject-fuzzy-regexp nil
@@ -177,12 +175,12 @@ will not be marked."
 This can either be a regular expression or list of regular expressions
 that will be removed from subject strings if fuzzy subject
 simplification is selected."
 This can either be a regular expression or list of regular expressions
 that will be removed from subject strings if fuzzy subject
 simplification is selected."
-  :group 'gnus-summary
+  :group 'gnus-thread
   :type '(repeat regexp))
 
 (defcustom gnus-show-threads t
   "*If non-nil, display threads in summary mode."
   :type '(repeat regexp))
 
 (defcustom gnus-show-threads t
   "*If non-nil, display threads in summary mode."
-  :group 'gnus-summary
+  :group 'gnus-thread
   :type 'boolean)
 
 (defcustom gnus-thread-hide-subtree nil
   :type 'boolean)
 
 (defcustom gnus-thread-hide-subtree nil
@@ -190,19 +188,19 @@ simplification is selected."
 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."
 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."
-  :group 'gnus-summary
+  :group 'gnus-thread
   :type 'boolean)
 
 (defcustom gnus-thread-hide-killed t
   "*If non-nil, hide killed threads automatically."
   :type 'boolean)
 
 (defcustom gnus-thread-hide-killed t
   "*If non-nil, hide killed threads automatically."
-  :group 'gnus-summary
+  :group 'gnus-thread
   :type 'boolean)
 
 (defcustom gnus-thread-ignore-subject nil
   "*If non-nil, ignore subjects and do all threading based on the Reference header.
 If nil, which is the default, articles that have different subjects
 from their parents will start separate threads."
   :type 'boolean)
 
 (defcustom gnus-thread-ignore-subject nil
   "*If non-nil, ignore subjects and do all threading based on the Reference header.
 If nil, which is the default, articles that have different subjects
 from their parents will start separate threads."
-  :group 'gnus-summary
+  :group 'gnus-thread
   :type 'boolean)
 
 (defcustom gnus-thread-operation-ignore-subject t
   :type 'boolean)
 
 (defcustom gnus-thread-operation-ignore-subject t
@@ -214,19 +212,19 @@ If this variable is nil, articles in the same thread with different
 subjects will not be included in the operation in question.  If this
 variable is `fuzzy', only articles that have subjects that are fuzzily
 equal will be included."
 subjects will not be included in the operation in question.  If this
 variable is `fuzzy', only articles that have subjects that are fuzzily
 equal will be included."
-  :group 'gnus-summary
+  :group 'gnus-thread
   :type '(choice (const :tag "off" nil)
                 (const fuzzy)
                 (sexp :tag "on" t)))
 
 (defcustom gnus-thread-indent-level 4
   "*Number that says how much each sub-thread should be indented."
   :type '(choice (const :tag "off" nil)
                 (const fuzzy)
                 (sexp :tag "on" t)))
 
 (defcustom gnus-thread-indent-level 4
   "*Number that says how much each sub-thread should be indented."
-  :group 'gnus-summary
+  :group 'gnus-thread
   :type 'integer)
 
 (defcustom gnus-auto-extend-newsgroup t
   "*If non-nil, extend newsgroup forward and backward when requested."
   :type 'integer)
 
 (defcustom gnus-auto-extend-newsgroup t
   "*If non-nil, extend newsgroup forward and backward when requested."
-  :group 'gnus-summary
+  :group 'gnus-summary-choose
   :type 'boolean)
 
 (defcustom gnus-auto-select-first t
   :type 'boolean)
 
 (defcustom gnus-auto-select-first t
@@ -238,7 +236,7 @@ article.
 If you want to prevent automatic selection of the first unread article
 in some newsgroups, set the variable to nil in
 `gnus-select-group-hook'."
 If you want to prevent automatic selection of the first unread article
 in some newsgroups, set the variable to nil in
 `gnus-select-group-hook'."
-  :group 'gnus-summary
+  :group 'gnus-group-select
   :type '(choice (const :tag "none" nil)
                 (const best)
                 (sexp :menu-tag "first" t)))
   :type '(choice (const :tag "none" nil)
                 (const best)
                 (sexp :menu-tag "first" t)))
@@ -254,7 +252,7 @@ newsgroup will be selected without any confirmation, and if it is
 confirmation if you are located on the last article in the group.
 Finally, if this variable is `slightly-quietly', the `Z n' command
 will go to the next group without confirmation."
 confirmation if you are located on the last article in the group.
 Finally, if this variable is `slightly-quietly', the `Z n' command
 will go to the next group without confirmation."
-  :group 'gnus-summary
+  :group 'gnus-summary-maneuvering
   :type '(choice (const :tag "off" nil)
                 (const quietly)
                 (const almost-quietly)
   :type '(choice (const :tag "off" nil)
                 (const quietly)
                 (const almost-quietly)
@@ -263,65 +261,59 @@ will go to the next group without confirmation."
 
 (defcustom gnus-auto-select-same nil
   "*If non-nil, select the next article with the same subject."
 
 (defcustom gnus-auto-select-same nil
   "*If non-nil, select the next article with the same subject."
-  :group 'gnus-summary
+  :group 'gnus-summary-maneuvering
   :type 'boolean)
 
 (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
 current article is unread."
   :type 'boolean)
 
 (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
 current article is unread."
-  :group 'gnus-summary
+  :group 'gnus-summary-maneuvering
   :type 'boolean)
 
 (defcustom gnus-auto-center-summary t
   "*If non-nil, always center the current summary buffer.
 In particular, if `vertical' do only vertical recentering.  If non-nil
 and non-`vertical', do both horizontal and vertical recentering."
   :type 'boolean)
 
 (defcustom gnus-auto-center-summary t
   "*If non-nil, always center the current summary buffer.
 In particular, if `vertical' do only vertical recentering.  If non-nil
 and non-`vertical', do both horizontal and vertical recentering."
-  :group 'gnus-summary
-  :type '(choice (const "none" nil)
+  :group 'gnus-summary-maneuvering
+  :type '(choice (const :tag "none" nil)
                 (const vertical)
                 (sexp :menu-tag "both" t)))
 
 (defcustom gnus-show-all-headers nil
   "*If non-nil, don't hide any headers."
                 (const vertical)
                 (sexp :menu-tag "both" t)))
 
 (defcustom gnus-show-all-headers nil
   "*If non-nil, don't hide any headers."
-  :group 'gnus-summary
+  :group 'gnus-article-hiding
+  :group 'gnus-article-headers
   :type 'boolean)
 
 (defcustom gnus-single-article-buffer t
   "*If non-nil, display all articles in the same buffer.
 If nil, each group will get its own article buffer."
   :type 'boolean)
 
 (defcustom gnus-single-article-buffer t
   "*If non-nil, display all articles in the same buffer.
 If nil, each group will get its own article buffer."
-  :group 'gnus-summary
+  :group 'gnus-article-various
   :type 'boolean)
 
 (defcustom gnus-break-pages t
   "*If non-nil, do page breaking on articles.
 The page delimiter is specified by the `gnus-page-delimiter'
 variable."
   :type 'boolean)
 
 (defcustom gnus-break-pages t
   "*If non-nil, do page breaking on articles.
 The page delimiter is specified by the `gnus-page-delimiter'
 variable."
-  :group 'gnus-summary
+  :group 'gnus-article-various
   :type 'boolean)
 
 (defcustom gnus-show-mime nil
   "*If non-nil, do mime processing of articles.
 The articles will simply be fed to the function given by
 `gnus-show-mime-method'."
   :type 'boolean)
 
 (defcustom gnus-show-mime nil
   "*If non-nil, do mime processing of articles.
 The articles will simply be fed to the function given by
 `gnus-show-mime-method'."
-  :group 'gnus-summary
+  :group 'gnus-article-mime
   :type 'boolean)
 
 (defcustom gnus-move-split-methods nil
   "*Variable used to suggest where articles are to be moved to.
 It uses the same syntax as the `gnus-split-methods' variable."
   :type 'boolean)
 
 (defcustom gnus-move-split-methods nil
   "*Variable used to suggest where articles are to be moved to.
 It uses the same syntax as the `gnus-split-methods' variable."
-  :group 'gnus-summary
+  :group 'gnus-summary-mail
   :type '(repeat (choice (list function)
                         (cons regexp (repeat string))
                         sexp)))
 
   :type '(repeat (choice (list function)
                         (cons regexp (repeat string))
                         sexp)))
 
-;; Mark variables suggested by Thomas Michanek
-;; <Thomas.Michanek@telelogic.se>.
-
-(defgroup gnus-summary-marks nil
-  "Marks used in summary buffers."
-  :group 'gnus-summary)
-
 (defcustom gnus-unread-mark ? 
   "*Mark used for unread articles."
   :group 'gnus-summary-marks
 (defcustom gnus-unread-mark ? 
   "*Mark used for unread articles."
   :group 'gnus-summary-marks
@@ -434,14 +426,14 @@ It uses the same syntax as the `gnus-split-methods' variable."
 
 (defcustom gnus-view-pseudo-asynchronously nil
   "*If non-nil, Gnus will view pseudo-articles asynchronously."
 
 (defcustom gnus-view-pseudo-asynchronously nil
   "*If non-nil, Gnus will view pseudo-articles asynchronously."
-  :group 'gnus-summary
+  :group 'gnus-extract-view
   :type 'boolean)
 
 (defcustom gnus-view-pseudos nil
   "*If `automatic', pseudo-articles will be viewed automatically.
 If `not-confirm', pseudos will be viewed automatically, and the user
 will not be asked to confirm the command."
   :type 'boolean)
 
 (defcustom gnus-view-pseudos nil
   "*If `automatic', pseudo-articles will be viewed automatically.
 If `not-confirm', pseudos will be viewed automatically, and the user
 will not be asked to confirm the command."
-  :group 'gnus-summary
+  :group 'gnus-extract-view
   :type '(choice (const :tag "off" nil)
                 (const automatic)
                 (const not-confirm)))
   :type '(choice (const :tag "off" nil)
                 (const automatic)
                 (const not-confirm)))
@@ -450,12 +442,12 @@ will not be asked to confirm the command."
   "*If non-nil, one pseudo-article will be created for each file to be viewed.
 If nil, all files that use the same viewing command will be given as a
 list of parameters to that command."
   "*If non-nil, one pseudo-article will be created for each file to be viewed.
 If nil, all files that use the same viewing command will be given as a
 list of parameters to that command."
-  :group 'gnus-summary
+  :group 'gnus-extract-view
   :type 'boolean)
 
 (defcustom gnus-insert-pseudo-articles t
   "*If non-nil, insert pseudo-articles when decoding articles."
   :type 'boolean)
 
 (defcustom gnus-insert-pseudo-articles t
   "*If non-nil, insert pseudo-articles when decoding articles."
-  :group 'gnus-summary
+  :group 'gnus-extract-view
   :type 'boolean)
 
 (defcustom gnus-summary-dummy-line-format
   :type 'boolean)
 
 (defcustom gnus-summary-dummy-line-format
@@ -465,7 +457,7 @@ It works along the same lines as a normal formatting string,
 with some simple extensions.
 
 %S  The subject"
 with some simple extensions.
 
 %S  The subject"
-  :group 'gnus-summary
+  :group 'gnus-threading
   :type 'string)
 
 (defcustom gnus-summary-mode-line-format "Gnus: %%b [%A] %Z"
   :type 'string)
 
 (defcustom gnus-summary-mode-line-format "Gnus: %%b [%A] %Z"
@@ -487,20 +479,20 @@ with some simple extensions:
 %d  Number of dormant articles
 %r  Number of articles that have been marked as read in this session
 %E  Number of articles expunged by the score files"
 %d  Number of dormant articles
 %r  Number of articles that have been marked as read in this session
 %E  Number of articles expunged by the score files"
-  :group 'gnus-summary
+  :group 'gnus-summary-format
   :type 'string)
 
 (defcustom gnus-summary-mark-below 0
   "*Mark all articles with a score below this variable as read.
 This variable is local to each summary buffer and usually set by the
 score file."
   :type 'string)
 
 (defcustom gnus-summary-mark-below 0
   "*Mark all articles with a score below this variable as read.
 This variable is local to each summary buffer and usually set by the
 score file."
-  :group 'gnus-summary
+  :group 'gnus-score-default
   :type 'integer)
 
 (defcustom gnus-article-sort-functions '(gnus-article-sort-by-number)
   "*List of functions used for sorting articles in the summary buffer.
 This variable is only used when not using a threaded display."
   :type 'integer)
 
 (defcustom gnus-article-sort-functions '(gnus-article-sort-by-number)
   "*List of functions used for sorting articles in the summary buffer.
 This variable is only used when not using a threaded display."
-  :group 'gnus-summary
+  :group 'gnus-summary-sort
   :type '(repeat (choice (function-item gnus-article-sort-by-number)
                         (function-item gnus-article-sort-by-author)
                         (function-item gnus-article-sort-by-subject)
   :type '(repeat (choice (function-item gnus-article-sort-by-number)
                         (function-item gnus-article-sort-by-author)
                         (function-item gnus-article-sort-by-subject)
@@ -522,7 +514,7 @@ 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-total-score' (see `gnus-thread-score-function')."
 `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-total-score' (see `gnus-thread-score-function')."
-  :group 'gnus-summary
+  :group 'gnus-summary-sort
   :type '(repeat (choice (function-item gnus-thread-sort-by-number)
                         (function-item gnus-thread-sort-by-author)
                         (function-item gnus-thread-sort-by-subject)
   :type '(repeat (choice (function-item gnus-thread-sort-by-number)
                         (function-item gnus-thread-sort-by-author)
                         (function-item gnus-thread-sort-by-subject)
@@ -538,12 +530,12 @@ The function is called with the scores of the article and each
 subthread and should then return the score of the thread.
 
 Some functions you can use are `+', `max', or `min'."
 subthread and should then return the score of the thread.
 
 Some functions you can use are `+', `max', or `min'."
-  :group 'gnus-summary
+  :group 'gnus-summary-sort
   :type 'function)
 
 (defcustom gnus-summary-expunge-below nil
   "All articles that have a score less than this variable will be expunged."
   :type 'function)
 
 (defcustom gnus-summary-expunge-below nil
   "All articles that have a score less than this variable will be expunged."
-  :group 'gnus-summary
+  :group 'gnus-score-default
   :type '(choice (const :tag "off" nil)
                 integer))
 
   :type '(choice (const :tag "off" nil)
                 integer))
 
@@ -551,37 +543,39 @@ Some functions you can use are `+', `max', or `min'."
   "All threads that have a total score less than this variable will be expunged.
 See `gnus-thread-score-function' for en explanation of what a
 \"thread score\" is."
   "All threads that have a total score less than this variable will be expunged.
 See `gnus-thread-score-function' for en explanation of what a
 \"thread score\" is."
-  :group 'gnus-summary
+  :group 'gnus-treading
+  :group 'gnus-score-default
   :type '(choice (const :tag "off" nil)
                 integer))
 
 (defcustom gnus-summary-mode-hook nil
   "*A hook for Gnus summary mode.
 This hook is run before any variables are set in the summary buffer."
   :type '(choice (const :tag "off" nil)
                 integer))
 
 (defcustom gnus-summary-mode-hook nil
   "*A hook for Gnus summary mode.
 This hook is run before any variables are set in the summary buffer."
-  :group 'gnus-summary
+  :group 'gnus-summary-various
   :type 'hook)
 
 (defcustom gnus-summary-menu-hook nil
   "*Hook run after the creation of the summary mode menu."
   :type 'hook)
 
 (defcustom gnus-summary-menu-hook nil
   "*Hook run after the creation of the summary mode menu."
-  :group 'gnus-summary
+  :group 'gnus-summary-visual
   :type 'hook)
 
 (defcustom gnus-summary-exit-hook nil
   :type 'hook)
 
 (defcustom gnus-summary-exit-hook nil
-  "*A hook called on exit from the summary buffer."
-  :group 'gnus-summary
+  "*A hook called on exit from the summary buffer.
+It will be called with point in the group buffer."
+  :group 'gnus-summary-exit
   :type 'hook)
 
 (defcustom gnus-summary-prepare-hook nil
   "*A hook called after the summary buffer has been generated.
 If you want to modify the summary buffer, you can use this hook."
   :type 'hook)
 
 (defcustom gnus-summary-prepare-hook nil
   "*A hook called after the summary buffer has been generated.
 If you want to modify the summary buffer, you can use this hook."
-  :group 'gnus-summary
+  :group 'gnus-summary-various
   :type 'hook)
 
 (defcustom gnus-summary-generate-hook nil
   "*A hook run just before generating the summary buffer.
 This hook is commonly used to customize threading variables and the
 like."
   :type 'hook)
 
 (defcustom gnus-summary-generate-hook nil
   "*A hook run just before generating the summary buffer.
 This hook is commonly used to customize threading variables and the
 like."
-  :group 'gnus-summary
+  :group 'gnus-summary-various
   :type 'hook)
 
 (defcustom gnus-select-group-hook nil
   :type 'hook)
 
 (defcustom gnus-select-group-hook nil
@@ -600,12 +594,12 @@ following hook:
                      (gnus-simplify-subject
                       (mail-header-subject header) 're-only)))
                  gnus-newsgroup-headers))))"
                      (gnus-simplify-subject
                       (mail-header-subject header) 're-only)))
                  gnus-newsgroup-headers))))"
-  :group 'gnus-summary
+  :group 'gnus-group-select
   :type 'hook)
 
 (defcustom gnus-select-article-hook nil
   "*A hook called when an article is selected."
   :type 'hook)
 
 (defcustom gnus-select-article-hook nil
   "*A hook called when an article is selected."
-  :group 'gnus-summary
+  :group 'gnus-summary-choose
   :type 'hook)
 
 (defcustom gnus-visual-mark-article-hook
   :type 'hook)
 
 (defcustom gnus-visual-mark-article-hook
@@ -613,18 +607,18 @@ following hook:
   "*Hook run after selecting an article in the summary buffer.
 It is meant to be used for highlighting the article in some way.  It
 is not run if `gnus-visual' is nil."
   "*Hook run after selecting an article in the summary buffer.
 It is meant to be used for highlighting the article in some way.  It
 is not run if `gnus-visual' is nil."
-  :group 'gnus-summary
+  :group 'gnus-summary-visual
   :type 'hook)
 
   :type 'hook)
 
-(defcustom gnus-parse-headers-hook 
+(defcustom gnus-parse-headers-hook
   (list 'gnus-decode-rfc1522)
   "*A hook called before parsing the headers."
   (list 'gnus-decode-rfc1522)
   "*A hook called before parsing the headers."
-  :group 'gnus-summary
+  :group 'gnus-various
   :type 'hook)
 
 (defcustom gnus-exit-group-hook nil
   "*A hook called when exiting (not quitting) summary mode."
   :type 'hook)
 
 (defcustom gnus-exit-group-hook nil
   "*A hook called when exiting (not quitting) summary mode."
-  :group 'gnus-summary
+  :group 'gnus-various
   :type 'hook)
 
 (defcustom gnus-summary-update-hook
   :type 'hook)
 
 (defcustom gnus-summary-update-hook
@@ -635,154 +629,32 @@ The hook will not be called if `gnus-visual' is nil.
 The default function `gnus-summary-highlight-line' will
 highlight the line according to the `gnus-summary-highlight'
 variable."
 The default function `gnus-summary-highlight-line' will
 highlight the line according to the `gnus-summary-highlight'
 variable."
-  :group 'gnus-summary
+  :group 'gnus-summary-visual
   :type 'hook)
 
 (defcustom gnus-mark-article-hook '(gnus-summary-mark-read-and-unread-as-read)
   "*A hook called when an article is selected for the first time.
 The hook is intended to mark an article as read (or unread)
 automatically when it is selected."
   :type 'hook)
 
 (defcustom gnus-mark-article-hook '(gnus-summary-mark-read-and-unread-as-read)
   "*A hook called when an article is selected for the first time.
 The hook is intended to mark an article as read (or unread)
 automatically when it is selected."
-  :group 'gnus-summary
+  :group 'gnus-summary-choose
   :type 'hook)
 
 (defcustom gnus-group-no-more-groups-hook nil
   "*A hook run when returning to group mode having no more (unread) groups."
   :type 'hook)
 
 (defcustom gnus-group-no-more-groups-hook nil
   "*A hook run when returning to group mode having no more (unread) groups."
-  :group 'gnus-summary
+  :group 'gnus-group-select
   :type 'hook)
 
   :type 'hook)
 
-(defface gnus-summary-selected-face '((t 
-                                      (:underline t)))
-  "Face used for selected articles.")
+(defcustom gnus-ps-print-hook nil
+  "*A hook run before ps-printing something from Gnus."
+  :group 'gnus-summary
+  :type 'hook)
 
 (defcustom gnus-summary-selected-face 'gnus-summary-selected-face
   "Face used for highlighting the current article in the summary buffer."
 
 (defcustom gnus-summary-selected-face 'gnus-summary-selected-face
   "Face used for highlighting the current article in the summary buffer."
-  :group 'gnus-summary
+  :group 'gnus-summary-visual
   :type 'face)
 
   :type 'face)
 
-(defface gnus-summary-cancelled-face 
-  '((((class color))
-     (:foreground "yellow" :background "black")))
-  "Face used for cancelled articles.")
-
-(defface gnus-summary-high-ticked-face
-  '((((class color)
-      (background dark))
-     (:foreground "pink" :bold t))
-    (((class color)
-      (background light))
-     (:foreground "firebrick" :bold t))
-    (t 
-     (:bold t)))
-  "Face used for high interest ticked articles.")
-
-(defface gnus-summary-low-ticked-face
-  '((((class color)
-      (background dark))
-     (:foreground "pink" :italic t))
-    (((class color)
-      (background light))
-     (:foreground "firebrick" :italic t))
-    (t 
-     (:italic t)))
-  "Face used for low interest ticked articles.")
-
-(defface gnus-summary-normal-ticked-face
-  '((((class color)
-      (background dark))
-     (:foreground "pink"))
-    (((class color)
-      (background light))
-     (:foreground "firebrick"))
-    (t 
-     ()))
-  "Face used for normal interest ticked articles.")
-  
-(defface gnus-summary-high-ancient-face
-  '((((class color)
-      (background dark))
-     (:foreground "SkyBlue" :bold t))
-    (((class color)
-      (background light))
-     (:foreground "RoyalBlue" :bold t))
-    (t 
-     (:bold t)))
-  "Face used for high interest ancient articles.")
-
-(defface gnus-summary-low-ancient-face
-  '((((class color)
-      (background dark))
-     (:foreground "SkyBlue" :italic t))
-    (((class color)
-      (background light))
-     (:foreground "RoyalBlue" :italic t))
-    (t 
-     (:italic t)))
-  "Face used for low interest ancient articles.")
-
-(defface gnus-summary-normal-ancient-face
-  '((((class color)
-      (background dark))
-     (:foreground "SkyBlue"))
-    (((class color)
-      (background light))
-     (:foreground "RoyalBlue"))
-    (t 
-     ()))
-  "Face used for normal interest ancient articles.")
-  
-(defface gnus-summary-high-unread-face
-  '((t 
-     (:bold t)))
-  "Face used for high interest unread articles.")
-
-(defface gnus-summary-low-unread-face
-  '((t 
-     (:italic t)))
-  "Face used for low interest unread articles.")
-
-(defface gnus-summary-normal-unread-face
-  '((t 
-     ()))
-  "Face used for normal interest unread articles.")
-  
-(defface gnus-summary-high-read-face
-  '((((class color)
-      (background dark))
-     (:foreground "PaleGreen"
-                 :bold t))
-    (((class color)
-      (background light))
-     (:foreground "DarkGreen"
-                 :bold t))
-    (t 
-     (:bold t)))
-  "Face used for high interest read articles.")
-
-(defface gnus-summary-low-read-face
-  '((((class color)
-      (background dark))
-     (:foreground "PaleGreen"
-                 :italic t))
-    (((class color)
-      (background light))
-     (:foreground "DarkGreen"
-                 :italic t))
-    (t 
-     (:italic t)))
-  "Face used for low interest read articles.")
-
-(defface gnus-summary-normal-read-face
-  '((((class color)
-      (background dark))
-     (:foreground "PaleGreen"))
-    (((class color)
-      (background light))
-     (:foreground "DarkGreen"))
-    (t 
-     ()))
-  "Face used for normal interest read articles.")
-
-(defcustom gnus-summary-highlight 
+(defcustom gnus-summary-highlight
   '(((= mark gnus-canceled-mark)
      . gnus-summary-cancelled-face)
     ((and (> score default)
   '(((= mark gnus-canceled-mark)
      . gnus-summary-cancelled-face)
     ((and (> score default)
@@ -808,13 +680,13 @@ automatically when it is selected."
      . gnus-summary-low-unread-face)
     ((and (= mark gnus-unread-mark))
      . gnus-summary-normal-unread-face)
      . gnus-summary-low-unread-face)
     ((and (= mark gnus-unread-mark))
      . gnus-summary-normal-unread-face)
-    ((> score default) 
+    ((> score default)
      . gnus-summary-high-read-face)
      . gnus-summary-high-read-face)
-    ((< score default) 
+    ((< score default)
      . gnus-summary-low-read-face)
      . gnus-summary-low-read-face)
-    (t 
+    (t
      . gnus-summary-normal-read-face))
      . gnus-summary-normal-read-face))
-  "Controls the highlighting of summary buffer lines. 
+  "Controls the highlighting of summary buffer lines.
 
 A list of (FORM . FACE) pairs.  When deciding how a a particular
 summary line should be displayed, each form is evaluated.  The content
 
 A list of (FORM . FACE) pairs.  When deciding how a a particular
 summary line should be displayed, each form is evaluated.  The content
@@ -825,17 +697,18 @@ You can use the following variables in the FORM field.
 
 score:   The articles score
 default: The default article score.
 
 score:   The articles score
 default: The default article score.
-below:   The score below which articles are automatically marked as read. 
+below:   The score below which articles are automatically marked as read.
 mark:    The articles mark."
 mark:    The articles mark."
-  :group 'gnus-summary
+  :group 'gnus-summary-visual
   :type '(repeat (cons (sexp :tag "Form" nil)
                       face)))
 
   :type '(repeat (cons (sexp :tag "Form" nil)
                       face)))
 
+
 ;;; Internal variables
 
 (defvar gnus-scores-exclude-files nil)
 
 ;;; Internal variables
 
 (defvar gnus-scores-exclude-files nil)
 
-(defvar gnus-summary-display-table 
+(defvar gnus-summary-display-table
   ;; Change the display table. Odd characters have a tendency to mess
   ;; up nicely formatted displays - we make all possible glyphs
   ;; display only a single character.
   ;; Change the display table. Odd characters have a tendency to mess
   ;; up nicely formatted displays - we make all possible glyphs
   ;; display only a single character.
@@ -1093,55 +966,43 @@ If RE-ONLY is non-nil, strip leading `Re:'s only."
 
 ;; Remove any leading "re:"s, any trailing paren phrases, and simplify
 ;; all whitespace.
 
 ;; Remove any leading "re:"s, any trailing paren phrases, and simplify
 ;; all whitespace.
-;; Written by Stainless Steel Rat <ratinox@ccs.neu.edu>.
+(defsubst gnus-simplify-buffer-fuzzy-step (regexp &optional newtext)
+  (goto-char (point-min))
+  (while (re-search-forward regexp nil t)
+      (replace-match (or newtext ""))))
+
 (defun gnus-simplify-buffer-fuzzy ()
 (defun gnus-simplify-buffer-fuzzy ()
-  (let ((case-fold-search t))
-    (goto-char (point-min))
-    (while (search-forward "\t" nil t)
-      (replace-match " " t t))
-    (goto-char (point-min))
-    (re-search-forward "^ *\\(re\\|fwd\\)[[{(^0-9]*[])}]?[:;] *" nil t)
-    (goto-char (match-beginning 0))
-    (while (or
-           (looking-at "^ *\\(re\\|fwd\\)[[{(^0-9]*[])}]?[:;] *")
-           (looking-at "^[[].*: .*[]]$"))
-      (goto-char (point-min))
-      (while (re-search-forward "^ *\\(re\\|fwd\\)[[{(^0-9]*[])}]?[:;] *"
-                               nil t)
-       (replace-match "" t t))
-      (goto-char (point-min))
-      (while (re-search-forward "^[[].*: .*[]]$" nil t)
-       (goto-char (match-end 0))
-       (delete-char -1)
-       (delete-region
-        (progn (goto-char (match-beginning 0)))
-        (re-search-forward ":"))))
-    (goto-char (point-min))
-    (while (re-search-forward " *[[{(][^()\n]*[]})] *$" nil t)
-      (replace-match "" t t))
-    (goto-char (point-min))
-    (while (re-search-forward "  +" nil t)
-      (replace-match " " t t))
-    (goto-char (point-min))
-    (while (re-search-forward " $" nil t)
-      (replace-match "" t t))
-    (goto-char (point-min))
-    (while (re-search-forward "^ +" nil t)
-      (replace-match "" t t))
-    (goto-char (point-min))
-    (when gnus-simplify-subject-fuzzy-regexp
-      (if (listp gnus-simplify-subject-fuzzy-regexp)
-         (let ((list gnus-simplify-subject-fuzzy-regexp))
-           (while list
-             (goto-char (point-min))
-             (while (re-search-forward (car list) nil t)
-               (replace-match "" t t))
-             (setq list (cdr list))))
-       (while (re-search-forward gnus-simplify-subject-fuzzy-regexp nil t)
-         (replace-match "" t t))))))
+  "Simplify string in the buffer fuzzily.
+The string in the accessible portion of the current buffer is simplified.
+It is assumed to be a single-line subject.
+Whitespace is generally cleaned up, and miscellaneous leading/trailing
+matter is removed.  Additional things can be deleted by setting
+gnus-simplify-subject-fuzzy-regexp."
+  (let ((case-fold-search t)
+       (modified-tick))
+    (gnus-simplify-buffer-fuzzy-step "\t" " ")
+
+    (while (not (eq modified-tick (buffer-modified-tick)))
+      (setq modified-tick (buffer-modified-tick))
+      (cond
+       ((listp gnus-simplify-subject-fuzzy-regexp)
+       (mapcar 'gnus-simplify-buffer-fuzzy-step
+               gnus-simplify-subject-fuzzy-regexp))
+       (gnus-simplify-subject-fuzzy-regexp
+       (gnus-simplify-buffer-fuzzy-step gnus-simplify-subject-fuzzy-regexp)))
+      (gnus-simplify-buffer-fuzzy-step "^ *\\[[-+?*!][-+?*!]\\] *")
+      (gnus-simplify-buffer-fuzzy-step
+       "^ *\\(re\\|fw\\|fwd\\)[[{(^0-9]*[])}]?[:;] *")
+      (gnus-simplify-buffer-fuzzy-step "^[[].*:\\( .*\\)[]]$" "\\1"))
+
+    (gnus-simplify-buffer-fuzzy-step " *[[{(][^()\n]*[]})] *$")
+    (gnus-simplify-buffer-fuzzy-step "  +" " ")
+    (gnus-simplify-buffer-fuzzy-step " $")
+    (gnus-simplify-buffer-fuzzy-step "^ +")))
 
 (defun gnus-simplify-subject-fuzzy (subject)
 
 (defun gnus-simplify-subject-fuzzy (subject)
-  "Simplify a subject string fuzzily."
+  "Simplify a subject string fuzzily.
+See gnus-simplify-buffer-fuzzy for details."
   (save-excursion
     (gnus-set-work-buffer)
     (let ((case-fold-search t))
   (save-excursion
     (gnus-set-work-buffer)
     (let ((case-fold-search t))
@@ -1150,7 +1011,7 @@ If RE-ONLY is non-nil, strip leading `Re:'s only."
       (buffer-string))))
 
 (defsubst gnus-simplify-subject-fully (subject)
       (buffer-string))))
 
 (defsubst gnus-simplify-subject-fully (subject)
-  "Simplify a subject string according to the user's wishes."
+  "Simplify a subject string according to gnus-summary-gather-subject-limit."
   (cond
    ((null gnus-summary-gather-subject-limit)
     (gnus-simplify-subject-re subject))
   (cond
    ((null gnus-summary-gather-subject-limit)
     (gnus-simplify-subject-re subject))
@@ -1173,30 +1034,6 @@ simple-first is t, first argument is already simplified."
     (equal s1
           (gnus-simplify-subject-fully s2)))))
 
     (equal s1
           (gnus-simplify-subject-fully s2)))))
 
-(defun gnus-offer-save-summaries ()
-  "Offer to save all active summary buffers."
-  (save-excursion
-    (let ((buflist (buffer-list))
-         buffers bufname)
-      ;; Go through all buffers and find all summaries.
-      (while buflist
-       (and (setq bufname (buffer-name (car buflist)))
-            (string-match "Summary" bufname)
-            (save-excursion
-              (set-buffer bufname)
-              ;; We check that this is, indeed, a summary buffer.
-              (and (eq major-mode 'gnus-summary-mode)
-                   ;; Also make sure this isn't bogus.
-                   gnus-newsgroup-prepared))
-            (push bufname buffers))
-       (setq buflist (cdr buflist)))
-      ;; Go through all these summary buffers and offer to save them.
-      (when buffers
-       (map-y-or-n-p
-        "Update summary buffer %s? "
-        (lambda (buf) (set-buffer buf) (gnus-summary-exit))
-        buffers)))))
-
 (defun gnus-summary-bubble-group ()
   "Increase the score of the current group.
 This is a handy function to add to `gnus-summary-exit-hook' to
 (defun gnus-summary-bubble-group ()
   "Increase the score of the current group.
 This is a handy function to add to `gnus-summary-exit-hook' to
@@ -1264,6 +1101,7 @@ increase the score of each group you read."
     "?" 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
     "?" 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-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-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
@@ -1353,7 +1191,7 @@ increase the score of each group you read."
     "v" gnus-summary-limit-to-score
     "D" gnus-summary-limit-include-dormant
     "d" gnus-summary-limit-exclude-dormant
     "v" gnus-summary-limit-to-score
     "D" gnus-summary-limit-include-dormant
     "d" gnus-summary-limit-exclude-dormant
-    ;;  "t" gnus-summary-limit-exclude-thread
+    "t" gnus-summary-limit-to-age
     "E" gnus-summary-limit-include-expunged
     "c" gnus-summary-limit-exclude-childless-dormant
     "C" gnus-summary-limit-mark-excluded-as-read)
     "E" gnus-summary-limit-include-expunged
     "c" gnus-summary-limit-exclude-childless-dormant
     "C" gnus-summary-limit-mark-excluded-as-read)
@@ -1394,7 +1232,7 @@ increase the score of each group you read."
     "\M-#" gnus-uu-unmark-thread)
 
   (gnus-define-keys (gnus-summary-buffer-map "Y" gnus-summary-mode-map)
     "\M-#" gnus-uu-unmark-thread)
 
   (gnus-define-keys (gnus-summary-buffer-map "Y" gnus-summary-mode-map)
-    "g" gnus-summary-prepare 
+    "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-insert-cached-articles)
 
   (gnus-define-keys (gnus-summary-exit-map "Z" gnus-summary-mode-map)
@@ -1407,6 +1245,7 @@ increase the score of each group you read."
     "R" gnus-summary-reselect-current-group
     "G" gnus-summary-rescan-group
     "N" gnus-summary-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)
     "P" gnus-summary-prev-group)
 
   (gnus-define-keys (gnus-summary-article-map "A" gnus-summary-mode-map)
@@ -1424,7 +1263,8 @@ increase the score of each group you read."
     "r" gnus-summary-refer-parent-article
     "R" gnus-summary-refer-references
     "g" gnus-summary-show-article
     "r" gnus-summary-refer-parent-article
     "R" gnus-summary-refer-references
     "g" gnus-summary-show-article
-    "s" gnus-summary-isearch-article)
+    "s" gnus-summary-isearch-article
+    "P" gnus-summary-print-article)
 
   (gnus-define-keys (gnus-summary-wash-map "W" gnus-summary-mode-map)
     "b" gnus-article-add-buttons
 
   (gnus-define-keys (gnus-summary-wash-map "W" gnus-summary-mode-map)
     "b" gnus-article-add-buttons
@@ -1439,7 +1279,8 @@ increase the score of each group you read."
     "r" gnus-summary-caesar-message
     "t" gnus-article-hide-headers
     "v" gnus-summary-verbose-headers
     "r" gnus-summary-caesar-message
     "t" gnus-article-hide-headers
     "v" gnus-summary-verbose-headers
-    "m" gnus-summary-toggle-mime)
+    "m" gnus-summary-toggle-mime
+    "h" gnus-article-treat-html)
 
   (gnus-define-keys (gnus-summary-wash-hide-map "W" gnus-summary-wash-map)
     "a" gnus-article-hide
 
   (gnus-define-keys (gnus-summary-wash-hide-map "W" gnus-summary-wash-map)
     "a" gnus-article-hide
@@ -1462,7 +1303,8 @@ increase the score of each group you read."
     "u" gnus-article-date-ut
     "l" gnus-article-date-local
     "e" gnus-article-date-lapsed
     "u" gnus-article-date-ut
     "l" gnus-article-date-local
     "e" gnus-article-date-lapsed
-    "o" gnus-article-date-original)
+    "o" gnus-article-date-original
+    "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
 
   (gnus-define-keys (gnus-summary-wash-empty-map "E" gnus-summary-wash-map)
     "t" gnus-article-remove-trailing-blank-lines
@@ -1494,6 +1336,7 @@ increase the score of each group you read."
   (gnus-define-keys (gnus-summary-save-map "O" gnus-summary-mode-map)
     "o" gnus-summary-save-article
     "m" gnus-summary-save-article-mail
   (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
     "r" gnus-summary-save-article-rmail
     "f" gnus-summary-save-article-file
     "b" gnus-summary-save-article-body-file
@@ -1513,7 +1356,8 @@ increase the score of each group you read."
       "Score"
       (nconc
        (list
       "Score"
       (nconc
        (list
-       ["Enter score..." gnus-summary-score-entry t])
+       ["Enter score..." gnus-summary-score-entry t]
+       ["Customize" gnus-score-customize t])
        (gnus-make-score-map 'increase)
        (gnus-make-score-map 'lower)
        '(("Mark"
        (gnus-make-score-map 'increase)
        (gnus-make-score-map 'lower)
        '(("Mark"
@@ -1536,51 +1380,51 @@ increase the score of each group you read."
 
     '(("Default header"
        ["Ask" (gnus-score-set-default 'gnus-score-default-header nil)
 
     '(("Default header"
        ["Ask" (gnus-score-set-default 'gnus-score-default-header nil)
-       :style radio 
+       :style radio
        :selected (null gnus-score-default-header)]
        ["From" (gnus-score-set-default 'gnus-score-default-header 'a)
        :selected (null gnus-score-default-header)]
        ["From" (gnus-score-set-default 'gnus-score-default-header 'a)
-       :style radio 
+       :style radio
        :selected (eq gnus-score-default-header 'a)]
        ["Subject" (gnus-score-set-default 'gnus-score-default-header 's)
        :selected (eq gnus-score-default-header 'a)]
        ["Subject" (gnus-score-set-default 'gnus-score-default-header 's)
-       :style radio 
+       :style radio
        :selected (eq gnus-score-default-header 's)]
        ["Article body"
        (gnus-score-set-default 'gnus-score-default-header 'b)
        :selected (eq gnus-score-default-header 's)]
        ["Article body"
        (gnus-score-set-default 'gnus-score-default-header 'b)
-       :style radio 
+       :style radio
        :selected (eq gnus-score-default-header 'b )]
        ["All headers"
        (gnus-score-set-default 'gnus-score-default-header 'h)
        :selected (eq gnus-score-default-header 'b )]
        ["All headers"
        (gnus-score-set-default 'gnus-score-default-header 'h)
-       :style radio 
+       :style radio
        :selected (eq gnus-score-default-header 'h )]
        ["Message-ID" (gnus-score-set-default 'gnus-score-default-header 'i)
        :selected (eq gnus-score-default-header 'h )]
        ["Message-ID" (gnus-score-set-default 'gnus-score-default-header 'i)
-       :style radio 
+       :style radio
        :selected (eq gnus-score-default-header 'i )]
        ["Thread" (gnus-score-set-default 'gnus-score-default-header 't)
        :selected (eq gnus-score-default-header 'i )]
        ["Thread" (gnus-score-set-default 'gnus-score-default-header 't)
-       :style radio 
+       :style radio
        :selected (eq gnus-score-default-header 't )]
        ["Crossposting"
        (gnus-score-set-default 'gnus-score-default-header 'x)
        :selected (eq gnus-score-default-header 't )]
        ["Crossposting"
        (gnus-score-set-default 'gnus-score-default-header 'x)
-       :style radio 
+       :style radio
        :selected (eq gnus-score-default-header 'x )]
        ["Lines" (gnus-score-set-default 'gnus-score-default-header 'l)
        :selected (eq gnus-score-default-header 'x )]
        ["Lines" (gnus-score-set-default 'gnus-score-default-header 'l)
-       :style radio 
+       :style radio
        :selected (eq gnus-score-default-header 'l )]
        ["Date" (gnus-score-set-default 'gnus-score-default-header 'd)
        :selected (eq gnus-score-default-header 'l )]
        ["Date" (gnus-score-set-default 'gnus-score-default-header 'd)
-       :style radio 
+       :style radio
        :selected (eq gnus-score-default-header 'd )]
        ["Followups to author"
        (gnus-score-set-default 'gnus-score-default-header 'f)
        :selected (eq gnus-score-default-header 'd )]
        ["Followups to author"
        (gnus-score-set-default 'gnus-score-default-header 'f)
-       :style radio 
+       :style radio
        :selected (eq gnus-score-default-header 'f )])
       ("Default type"
        ["Ask" (gnus-score-set-default 'gnus-score-default-type nil)
        :selected (eq gnus-score-default-header 'f )])
       ("Default type"
        ["Ask" (gnus-score-set-default 'gnus-score-default-type nil)
-       :style radio 
+       :style radio
        :selected (null gnus-score-default-type)]
        ;; The `:active' key is commented out in the following,
        ;; because the GNU Emacs hack to support radio buttons use
        :selected (null gnus-score-default-type)]
        ;; The `:active' key is commented out in the following,
        ;; because the GNU Emacs hack to support radio buttons use
-       ;; active to indicate which button is selected.  
+       ;; active to indicate which button is selected.
        ["Substring" (gnus-score-set-default 'gnus-score-default-type 's)
        ["Substring" (gnus-score-set-default 'gnus-score-default-type 's)
-       :style radio 
+       :style radio
        ;; :active (not (memq gnus-score-default-header '(l d)))
        :selected (eq gnus-score-default-type 's)]
        ["Regexp" (gnus-score-set-default 'gnus-score-default-type 'r)
        ;; :active (not (memq gnus-score-default-header '(l d)))
        :selected (eq gnus-score-default-type 's)]
        ["Regexp" (gnus-score-set-default 'gnus-score-default-type 'r)
@@ -1592,34 +1436,34 @@ increase the score of each group you read."
        ;; :active (not (memq gnus-score-default-header '(l d)))
        :selected (eq gnus-score-default-type 'e)]
        ["Fuzzy" (gnus-score-set-default 'gnus-score-default-type 'f)
        ;; :active (not (memq gnus-score-default-header '(l d)))
        :selected (eq gnus-score-default-type 'e)]
        ["Fuzzy" (gnus-score-set-default 'gnus-score-default-type 'f)
-       :style radio 
+       :style radio
        ;; :active (not (memq gnus-score-default-header '(l d)))
        :selected (eq gnus-score-default-type 'f)]
        ["Before date" (gnus-score-set-default 'gnus-score-default-type 'b)
        ;; :active (not (memq gnus-score-default-header '(l d)))
        :selected (eq gnus-score-default-type 'f)]
        ["Before date" (gnus-score-set-default 'gnus-score-default-type 'b)
-       :style radio 
+       :style radio
        ;; :active (eq (gnus-score-default-header 'd))
        :selected (eq gnus-score-default-type 'b)]
        ["At date" (gnus-score-set-default 'gnus-score-default-type 'n)
        ;; :active (eq (gnus-score-default-header 'd))
        :selected (eq gnus-score-default-type 'b)]
        ["At date" (gnus-score-set-default 'gnus-score-default-type 'n)
-       :style radio 
+       :style radio
        ;; :active (eq (gnus-score-default-header 'd))
        :selected (eq gnus-score-default-type 'n)]
        ["After date" (gnus-score-set-default 'gnus-score-default-type 'a)
        ;; :active (eq (gnus-score-default-header 'd))
        :selected (eq gnus-score-default-type 'n)]
        ["After date" (gnus-score-set-default 'gnus-score-default-type 'a)
-       :style radio 
+       :style radio
        ;; :active (eq (gnus-score-default-header 'd))
        :selected (eq gnus-score-default-type 'a)]
        ["Less than number"
        (gnus-score-set-default 'gnus-score-default-type '<)
        ;; :active (eq (gnus-score-default-header 'd))
        :selected (eq gnus-score-default-type 'a)]
        ["Less than number"
        (gnus-score-set-default 'gnus-score-default-type '<)
-       :style radio 
+       :style radio
        ;; :active (eq (gnus-score-default-header 'l))
        :selected (eq gnus-score-default-type '<)]
        ["Equal to number"
        (gnus-score-set-default 'gnus-score-default-type '=)
        ;; :active (eq (gnus-score-default-header 'l))
        :selected (eq gnus-score-default-type '<)]
        ["Equal to number"
        (gnus-score-set-default 'gnus-score-default-type '=)
-       :style radio 
+       :style radio
        ;; :active (eq (gnus-score-default-header 'l))
        :selected (eq gnus-score-default-type '=)]
        ;; :active (eq (gnus-score-default-header 'l))
        :selected (eq gnus-score-default-type '=)]
-       ["Greater than number" 
+       ["Greater than number"
        (gnus-score-set-default 'gnus-score-default-type '>)
        (gnus-score-set-default 'gnus-score-default-type '>)
-       :style radio 
+       :style radio
        ;; :active (eq (gnus-score-default-header 'l))
        :selected (eq gnus-score-default-type '>)])
       ["Default fold" gnus-score-default-fold-toggle
        ;; :active (eq (gnus-score-default-header 'l))
        :selected (eq gnus-score-default-type '>)])
       ["Default fold" gnus-score-default-fold-toggle
@@ -1637,7 +1481,7 @@ increase the score of each group you read."
        (gnus-score-set-default 'gnus-score-default-duration 't)
        :style radio
        :selected (eq gnus-score-default-duration 't)]
        (gnus-score-set-default 'gnus-score-default-duration 't)
        :style radio
        :selected (eq gnus-score-default-duration 't)]
-       ["Immediate" 
+       ["Immediate"
        (gnus-score-set-default 'gnus-score-default-duration 'i)
        :style radio
        :selected (eq gnus-score-default-duration 'i)]))
        (gnus-score-set-default 'gnus-score-default-duration 'i)
        :style radio
        :selected (eq gnus-score-default-duration 'i)]))
@@ -1661,8 +1505,9 @@ increase the score of each group you read."
        ["Local" gnus-article-date-local t]
        ["UT" gnus-article-date-ut t]
        ["Original" gnus-article-date-original t]
        ["Local" gnus-article-date-local t]
        ["UT" gnus-article-date-ut t]
        ["Original" gnus-article-date-original t]
-       ["Lapsed" gnus-article-date-lapsed t])
-       ("Filter"
+       ["Lapsed" gnus-article-date-lapsed t]
+       ["User-defined" gnus-article-date-user t])
+       ("Washing"
        ("Remove Blanks"
         ["Leading" gnus-article-strip-leading-blank-lines t]
         ["Multiple" gnus-article-strip-multiple-blank-lines t]
        ("Remove Blanks"
         ["Leading" gnus-article-strip-leading-blank-lines t]
         ["Multiple" gnus-article-strip-multiple-blank-lines t]
@@ -1674,7 +1519,9 @@ increase the score of each group you read."
        ["CR" gnus-article-remove-cr t]
        ["Show X-Face" gnus-article-display-x-face t]
        ["Quoted-Printable" gnus-article-de-quoted-unreadable t]
        ["CR" gnus-article-remove-cr t]
        ["Show X-Face" gnus-article-display-x-face t]
        ["Quoted-Printable" gnus-article-de-quoted-unreadable t]
+       ["UnHTMLize" gnus-article-treat-html t]
        ["Rot 13" gnus-summary-caesar-message t]
        ["Rot 13" gnus-summary-caesar-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]
        ["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]
@@ -1685,12 +1532,14 @@ increase the score of each group you read."
        ["Save in default format" gnus-summary-save-article t]
        ["Save in file" gnus-summary-save-article-file t]
        ["Save in Unix mail format" gnus-summary-save-article-mail t]
        ["Save in default format" gnus-summary-save-article t]
        ["Save in file" gnus-summary-save-article-file t]
        ["Save in Unix mail format" gnus-summary-save-article-mail t]
+       ["Write to file" gnus-summary-write-article-mail t]
        ["Save in MH folder" gnus-summary-save-article-folder t]
        ["Save in VM folder" gnus-summary-save-article-vm t]
        ["Save in RMAIL mbox" gnus-summary-save-article-rmail t]
        ["Save body in file" gnus-summary-save-article-body-file t]
        ["Pipe through a filter" gnus-summary-pipe-output t]
        ["Save in MH folder" gnus-summary-save-article-folder t]
        ["Save in VM folder" gnus-summary-save-article-vm t]
        ["Save in RMAIL mbox" gnus-summary-save-article-rmail t]
        ["Save body in file" gnus-summary-save-article-body-file t]
        ["Pipe through a filter" gnus-summary-pipe-output t]
-       ["Add to SOUP packet" gnus-soup-add-article t])
+       ["Add to SOUP packet" gnus-soup-add-article t]
+       ["Print" gnus-summary-print-article t])
        ("Backend"
        ["Respool article..." gnus-summary-respool-article t]
        ["Move article..." gnus-summary-move-article
        ("Backend"
        ["Respool article..." gnus-summary-respool-article t]
        ["Move article..." gnus-summary-move-article
@@ -1719,10 +1568,11 @@ increase the score of each group you read."
        ["Save" gnus-uu-decode-save t]
        ["Binhex" gnus-uu-decode-binhex t]
        ["Postscript" gnus-uu-decode-postscript t])
        ["Save" gnus-uu-decode-save t]
        ["Binhex" gnus-uu-decode-binhex t]
        ["Postscript" gnus-uu-decode-postscript t])
+       ("Cache"
+       ["Enter article" gnus-cache-enter-article t]
+       ["Remove article" gnus-cache-remove-article t])
        ["Enter digest buffer" gnus-summary-enter-digest-group t]
        ["Isearch article..." gnus-summary-isearch-article t]
        ["Enter digest buffer" gnus-summary-enter-digest-group t]
        ["Isearch article..." gnus-summary-isearch-article t]
-       ["Search articles forward..." gnus-summary-search-article-forward t]
-       ["Search articles backward..." gnus-summary-search-article-backward t]
        ["Beginning of the article" gnus-summary-beginning-of-article t]
        ["End of the article" gnus-summary-end-of-article t]
        ["Fetch parent of article" gnus-summary-refer-parent-article t]
        ["Beginning of the article" gnus-summary-beginning-of-article t]
        ["End of the article" gnus-summary-end-of-article t]
        ["Fetch parent of article" gnus-summary-refer-parent-article t]
@@ -1759,6 +1609,8 @@ increase the score of each group you read."
        ["Cancel article" gnus-summary-cancel-article t]
        ["Reply" gnus-summary-reply t]
        ["Reply and yank" gnus-summary-reply-with-original t]
        ["Cancel article" gnus-summary-cancel-article t]
        ["Reply" gnus-summary-reply t]
        ["Reply and yank" gnus-summary-reply-with-original t]
+       ["Wide reply" gnus-summary-wide-reply t]
+       ["Wide reply and yank" gnus-summary-wide-reply-with-original t]
        ["Mail forward" gnus-summary-mail-forward t]
        ["Post forward" gnus-summary-post-forward t]
        ["Digest and mail" gnus-uu-digest-mail-forward t]
        ["Mail forward" gnus-summary-mail-forward t]
        ["Post forward" gnus-summary-post-forward t]
        ["Digest and mail" gnus-uu-digest-mail-forward t]
@@ -1767,6 +1619,9 @@ increase the score of each group you read."
        ["Send bounced mail" gnus-summary-resend-bounced-mail t]
        ["Send a mail" gnus-summary-mail-other-window t]
        ["Uuencode and post" gnus-uu-post-news t]
        ["Send bounced mail" gnus-summary-resend-bounced-mail t]
        ["Send a mail" gnus-summary-mail-other-window t]
        ["Uuencode and post" gnus-uu-post-news t]
+       ["Followup via news" gnus-summary-followup-to-mail t]
+       ["Followup via news and yank"
+       gnus-summary-followup-to-mail-with-original t]
        ;;("Draft"
        ;;["Send" gnus-summary-send-draft t]
        ;;["Send bounced" gnus-resend-bounced-mail t])
        ;;("Draft"
        ;;["Send" gnus-summary-send-draft t]
        ;;["Send bounced" gnus-resend-bounced-mail t])
@@ -1775,56 +1630,56 @@ increase the score of each group you read."
     (easy-menu-define
      gnus-summary-misc-menu gnus-summary-mode-map ""
      '("Misc"
     (easy-menu-define
      gnus-summary-misc-menu gnus-summary-mode-map ""
      '("Misc"
-       ("Mark"
-       ("Read"
-        ["Mark as read" gnus-summary-mark-as-read-forward t]
-        ["Mark same subject and select"
-         gnus-summary-kill-same-subject-and-select t]
-        ["Mark same subject" gnus-summary-kill-same-subject t]
-        ["Catchup" gnus-summary-catchup t]
-        ["Catchup all" gnus-summary-catchup-all t]
-        ["Catchup to here" gnus-summary-catchup-to-here t]
-        ["Catchup region" gnus-summary-mark-region-as-read t]
-        ["Mark excluded" gnus-summary-limit-mark-excluded-as-read t])
-       ("Various"
-        ["Tick" gnus-summary-tick-article-forward t]
-        ["Mark as dormant" gnus-summary-mark-as-dormant t]
-        ["Remove marks" gnus-summary-clear-mark-forward t]
-        ["Set expirable mark" gnus-summary-mark-as-expirable t]
-        ["Set bookmark" gnus-summary-set-bookmark t]
-        ["Remove bookmark" gnus-summary-remove-bookmark t])
-       ("Limit"
-        ["Marks..." gnus-summary-limit-to-marks t]
-        ["Subject..." gnus-summary-limit-to-subject t]
-        ["Author..." gnus-summary-limit-to-author t]
-        ["Score" gnus-summary-limit-to-score t]
-        ["Unread" gnus-summary-limit-to-unread t]
-        ["Non-dormant" gnus-summary-limit-exclude-dormant t]
-        ["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" 
-         gnus-summary-limit-exclude-childless-dormant t]
-        ;;["Hide thread" gnus-summary-limit-exclude-thread t]
-        ["Show expunged" gnus-summary-show-all-expunged t])
-       ("Process mark"
-        ["Set mark" gnus-summary-mark-as-processable t]
-        ["Remove mark" gnus-summary-unmark-as-processable t]
-        ["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]
-        ["Mark by regexp..." gnus-uu-mark-by-regexp t]
-        ["Mark all" gnus-uu-mark-all t]
-        ["Mark buffer" gnus-uu-mark-buffer t]
-        ["Mark sparse" gnus-uu-mark-sparse t]
-        ["Mark thread" gnus-uu-mark-thread t]
-        ["Unmark thread" gnus-uu-unmark-thread t]
-        ("Process Mark Sets"
-         ["Kill" gnus-summary-kill-process-mark t]
-         ["Yank" gnus-summary-yank-process-mark
-          gnus-newsgroup-process-stack]
-         ["Save" gnus-summary-save-process-mark t])))
+       ("Mark Read"
+       ["Mark as read" gnus-summary-mark-as-read-forward t]
+       ["Mark same subject and select"
+        gnus-summary-kill-same-subject-and-select t]
+       ["Mark same subject" gnus-summary-kill-same-subject t]
+       ["Catchup" gnus-summary-catchup t]
+       ["Catchup all" gnus-summary-catchup-all t]
+       ["Catchup to here" gnus-summary-catchup-to-here t]
+       ["Catchup region" gnus-summary-mark-region-as-read t]
+       ["Mark excluded" gnus-summary-limit-mark-excluded-as-read t])
+       ("Mark Various"
+       ["Tick" gnus-summary-tick-article-forward t]
+       ["Mark as dormant" gnus-summary-mark-as-dormant t]
+       ["Remove marks" gnus-summary-clear-mark-forward t]
+       ["Set expirable mark" gnus-summary-mark-as-expirable t]
+       ["Set bookmark" gnus-summary-set-bookmark t]
+       ["Remove bookmark" gnus-summary-remove-bookmark t])
+       ("Mark Limit"
+       ["Marks..." gnus-summary-limit-to-marks t]
+       ["Subject..." gnus-summary-limit-to-subject t]
+       ["Author..." gnus-summary-limit-to-author t]
+       ["Age..." gnus-summary-limit-to-age t]
+       ["Score" gnus-summary-limit-to-score t]
+       ["Unread" gnus-summary-limit-to-unread t]
+       ["Non-dormant" gnus-summary-limit-exclude-dormant t]
+       ["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"
+        gnus-summary-limit-exclude-childless-dormant t]
+       ;;["Hide thread" gnus-summary-limit-exclude-thread t]
+       ["Show expunged" gnus-summary-show-all-expunged t])
+       ("Process Mark"
+       ["Set mark" gnus-summary-mark-as-processable t]
+       ["Remove mark" gnus-summary-unmark-as-processable t]
+       ["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]
+       ["Mark by regexp..." gnus-uu-mark-by-regexp t]
+       ["Mark all" gnus-uu-mark-all t]
+       ["Mark buffer" gnus-uu-mark-buffer t]
+       ["Mark sparse" gnus-uu-mark-sparse t]
+       ["Mark thread" gnus-uu-mark-thread t]
+       ["Unmark thread" gnus-uu-unmark-thread t]
+       ("Process Mark Sets"
+        ["Kill" gnus-summary-kill-process-mark t]
+        ["Yank" gnus-summary-yank-process-mark
+         gnus-newsgroup-process-stack]
+        ["Save" gnus-summary-save-process-mark t]))
        ("Scroll article"
        ["Page forward" gnus-summary-next-page t]
        ["Page backward" gnus-summary-prev-page t]
        ("Scroll article"
        ["Page forward" gnus-summary-next-page t]
        ["Page backward" gnus-summary-prev-page t]
@@ -1849,25 +1704,28 @@ increase the score of each group you read."
        ["Sort by author" gnus-summary-sort-by-author t]
        ["Sort by subject" gnus-summary-sort-by-subject t]
        ["Sort by date" gnus-summary-sort-by-date t]
        ["Sort by author" gnus-summary-sort-by-author t]
        ["Sort by subject" gnus-summary-sort-by-subject t]
        ["Sort by date" gnus-summary-sort-by-date t]
-       ["Sort by score" gnus-summary-sort-by-score t])
+       ["Sort by score" gnus-summary-sort-by-score t]
+       ["Sort by lines" gnus-summary-sort-by-lines t])
        ("Help"
        ["Fetch group FAQ" gnus-summary-fetch-faq t]
        ["Describe group" gnus-summary-describe-group t]
        ["Read manual" gnus-info-find-node t])
        ("Help"
        ["Fetch group FAQ" gnus-summary-fetch-faq t]
        ["Describe group" gnus-summary-describe-group t]
        ["Read manual" gnus-info-find-node t])
-       ("Cache"
-       ["Enter article" gnus-cache-enter-article t]
-       ["Remove article" gnus-cache-remove-article t])
        ("Modes"
        ["Pick and read" gnus-pick-mode t]
        ["Binary" gnus-binary-mode t])
        ("Modes"
        ["Pick and read" gnus-pick-mode t]
        ["Binary" gnus-binary-mode t])
+       ("Regeneration"
+       ["Regenerate" gnus-summary-prepare t]
+       ["Insert cached articles" gnus-summary-insert-cached-articles t]
+       ["Toggle threading" gnus-summary-toggle-threads t])
        ["Filter articles..." gnus-summary-execute-command t]
        ["Run command on subjects..." gnus-summary-universal-argument t]
        ["Filter articles..." gnus-summary-execute-command t]
        ["Run command on subjects..." 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]
        ["Expand window" gnus-summary-expand-window t]
        ["Expire expirable articles" gnus-summary-expire-articles
        (gnus-check-backend-function
         'request-expire-articles gnus-newsgroup-name)]
        ["Toggle line truncation" gnus-summary-toggle-truncation t]
        ["Expand window" gnus-summary-expand-window t]
        ["Expire expirable articles" gnus-summary-expire-articles
        (gnus-check-backend-function
         'request-expire-articles gnus-newsgroup-name)]
-       ["Regenerate buffer" gnus-summary-prepare t]
        ["Edit local kill file" gnus-summary-edit-local-kill t]
        ["Edit main kill file" gnus-summary-edit-global-kill t]
        ("Exit"
        ["Edit local kill file" gnus-summary-edit-local-kill t]
        ["Edit main kill file" gnus-summary-edit-global-kill t]
        ("Exit"
@@ -1879,7 +1737,8 @@ increase the score of each group you read."
        ["Exit and goto next group" gnus-summary-next-group t]
        ["Exit and goto prev group" gnus-summary-prev-group t]
        ["Reselect group" gnus-summary-reselect-current-group t]
        ["Exit and goto next group" gnus-summary-next-group t]
        ["Exit and goto prev group" gnus-summary-prev-group t]
        ["Reselect group" gnus-summary-reselect-current-group t]
-       ["Rescan group" gnus-summary-rescan-group t])))
+       ["Rescan group" gnus-summary-rescan-group t]
+       ["Update dribble" gnus-summary-save-newsrc t])))
 
     (run-hooks 'gnus-summary-menu-hook)))
 
 
     (run-hooks 'gnus-summary-menu-hook)))
 
@@ -1911,8 +1770,8 @@ increase the score of each group you read."
                   ("permanent" nil)
                   ("immediate" now)))
          header)
                   ("permanent" nil)
                   ("immediate" now)))
          header)
-      (list 
-       (apply 
+      (list
+       (apply
        'nconc
        (list
         (if (eq type 'lower)
        'nconc
        (list
         (if (eq type 'lower)
@@ -1921,17 +1780,17 @@ increase the score of each group you read."
        (let (outh)
          (while headers
            (setq header (car headers))
        (let (outh)
          (while headers
            (setq header (car headers))
-           (setq outh 
-                 (cons 
-                  (apply 
+           (setq outh
+                 (cons
+                  (apply
                    'nconc
                    (list (car header))
                    (let ((ts (cdr (assoc (nth 2 header) types)))
                          outt)
                      (while ts
                        (setq outt
                    'nconc
                    (list (car header))
                    (let ((ts (cdr (assoc (nth 2 header) types)))
                          outt)
                      (while ts
                        (setq outt
-                             (cons 
-                              (apply 
+                             (cons
+                              (apply
                                'nconc
                                (list (caar ts))
                                (let ((ps perms)
                                'nconc
                                (list (caar ts))
                                (let ((ps perms)
@@ -1949,7 +1808,7 @@ increase the score of each group you read."
                                                     (string= (nth 1 header)
                                                              "body"))
                                                 ""
                                                     (string= (nth 1 header)
                                                              "body"))
                                                 ""
-                                              (list 'gnus-summary-header 
+                                              (list 'gnus-summary-header
                                                     (nth 1 header)))
                                             (list 'quote (nth 1 (car ts)))
                                             (list 'gnus-score-default nil)
                                                     (nth 1 header)))
                                             (list 'quote (nth 1 (car ts)))
                                             (list 'gnus-score-default nil)
@@ -1989,8 +1848,7 @@ The following commands are available:
 
 \\{gnus-summary-mode-map}"
   (interactive)
 
 \\{gnus-summary-mode-map}"
   (interactive)
-  (when (and menu-bar-mode
-            (gnus-visual-p 'summary-menu 'menu))
+  (when (gnus-visual-p 'summary-menu 'menu)
     (gnus-summary-make-menu-bar))
   (kill-all-local-variables)
   (gnus-summary-make-local-variables)
     (gnus-summary-make-menu-bar))
   (kill-all-local-variables)
   (gnus-summary-make-local-variables)
@@ -2011,11 +1869,11 @@ The following commands are available:
   (make-local-variable 'gnus-summary-line-format)
   (make-local-variable 'gnus-summary-line-format-spec)
   (make-local-variable 'gnus-summary-mark-positions)
   (make-local-variable 'gnus-summary-line-format)
   (make-local-variable 'gnus-summary-line-format-spec)
   (make-local-variable 'gnus-summary-mark-positions)
-  (gnus-update-format-specifications nil 'summary 'summary-mode 'summary-dummy)
-  (gnus-update-summary-mark-positions)
-  (gnus-make-local-hook 'post-command-hook)
+  (make-local-hook 'post-command-hook)
   (gnus-add-hook 'post-command-hook 'gnus-clear-inboxes-moved nil t)
   (gnus-add-hook 'post-command-hook 'gnus-clear-inboxes-moved nil t)
-  (run-hooks 'gnus-summary-mode-hook))
+  (run-hooks 'gnus-summary-mode-hook)
+  (gnus-update-format-specifications nil 'summary 'summary-mode 'summary-dummy)
+  (gnus-update-summary-mark-positions))
 
 (defun gnus-summary-make-local-variables ()
   "Make all the local summary buffer variables."
 
 (defun gnus-summary-make-local-variables ()
   "Make all the local summary buffer variables."
@@ -2068,6 +1926,9 @@ The following commands are available:
 (defmacro gnus-data-header (data)
   `(nth 3 ,data))
 
 (defmacro gnus-data-header (data)
   `(nth 3 ,data))
 
+(defmacro gnus-data-set-header (data header)
+  `(setf (nth 3 ,data) ,header))
+
 (defmacro gnus-data-level (data)
   `(nth 4 ,data))
 
 (defmacro gnus-data-level (data)
   `(nth 4 ,data))
 
@@ -2118,14 +1979,17 @@ The following commands are available:
        (setcdr list (cdr data))
        (setcdr data ilist)
        (when offset
        (setcdr list (cdr data))
        (setcdr data ilist)
        (when offset
-         (gnus-data-update-list (cdr data) offset)))
+         (gnus-data-update-list (cdr list) offset)))
       (setq gnus-newsgroup-data-reverse nil))))
 
 (defun gnus-data-remove (article &optional offset)
   (let ((data gnus-newsgroup-data))
     (if (= (gnus-data-number (car data)) article)
       (setq gnus-newsgroup-data-reverse nil))))
 
 (defun gnus-data-remove (article &optional offset)
   (let ((data gnus-newsgroup-data))
     (if (= (gnus-data-number (car data)) article)
-       (setq gnus-newsgroup-data (cdr gnus-newsgroup-data)
-             gnus-newsgroup-data-reverse nil)
+       (progn
+         (setq gnus-newsgroup-data (cdr gnus-newsgroup-data)
+               gnus-newsgroup-data-reverse nil)
+         (when offset
+           (gnus-data-update-list gnus-newsgroup-data offset)))
       (while (cdr data)
        (when (= (gnus-data-number (cadr data)) article)
          (setcdr data (cddr data))
       (while (cdr data)
        (when (= (gnus-data-number (cadr data)) article)
          (setcdr data (cddr data))
@@ -2163,6 +2027,14 @@ The following commands are available:
   "Say whether this article is a pseudo article or not."
   (not (vectorp (gnus-data-header (gnus-data-find article)))))
 
   "Say whether this article is a pseudo article or not."
   (not (vectorp (gnus-data-header (gnus-data-find article)))))
 
+(defmacro gnus-summary-article-sparse-p (article)
+  "Say whether this article is a sparse article or not."
+  ` (memq ,article gnus-newsgroup-sparse))
+
+(defmacro gnus-summary-article-ancient-p (article)
+  "Say whether this article is a sparse article or not."
+  `(memq ,article gnus-newsgroup-ancient))
+
 (defun gnus-article-parent-p (number)
   "Say whether this article is a parent or not."
   (let ((data (gnus-data-find-list number)))
 (defun gnus-article-parent-p (number)
   "Say whether this article is a parent or not."
   (let ((data (gnus-data-find-list number)))
@@ -2176,7 +2048,7 @@ The following commands are available:
         (level (gnus-data-level (car data)))
         children)
     (setq data (cdr data))
         (level (gnus-data-level (car data)))
         children)
     (setq data (cdr data))
-    (while (and data           
+    (while (and data
                (= (gnus-data-level (car data)) (1+ level)))
       (push (gnus-data-number (car data)) children)
       (setq data (cdr data)))
                (= (gnus-data-level (car data)) (1+ level)))
       (push (gnus-data-number (car data)) children)
       (setq data (cdr data)))
@@ -2293,7 +2165,6 @@ This is all marks except unread, ticked, dormant, and expirable."
 ;; Saving hidden threads.
 
 (put 'gnus-save-hidden-threads 'lisp-indent-function 0)
 ;; Saving hidden threads.
 
 (put 'gnus-save-hidden-threads 'lisp-indent-function 0)
-(put 'gnus-save-hidden-threads 'lisp-indent-hook 0)
 (put 'gnus-save-hidden-threads 'edebug-form-spec '(body))
 
 (defmacro gnus-save-hidden-threads (&rest forms)
 (put 'gnus-save-hidden-threads 'edebug-form-spec '(body))
 
 (defmacro gnus-save-hidden-threads (&rest forms)
@@ -2386,10 +2257,20 @@ This is all marks except unread, ticked, dormant, and expirable."
          (set-buffer gnus-article-buffer)
          (setq gnus-summary-buffer summary))))))
 
          (set-buffer gnus-article-buffer)
          (setq gnus-summary-buffer summary))))))
 
+(defun gnus-summary-article-unread-p (article)
+  "Say whether ARTICLE is unread or not."
+  (memq article gnus-newsgroup-unreads))
+
+(defun gnus-summary-first-article-p (&optional article)
+  "Return whether ARTICLE is the first article in the buffer."
+  (if (not (setq article (or article (gnus-summary-article-number))))
+      nil
+    (eq article (caar gnus-newsgroup-data))))
+
 (defun gnus-summary-last-article-p (&optional article)
   "Return whether ARTICLE is the last article in the buffer."
   (if (not (setq article (or article (gnus-summary-article-number))))
 (defun gnus-summary-last-article-p (&optional article)
   "Return whether ARTICLE is the last article in the buffer."
   (if (not (setq article (or article (gnus-summary-article-number))))
-      t                                        ; All non-existent numbers are the last article.  :-)
+      t                ; All non-existent numbers are the last article.  :-)
     (not (cdr (gnus-data-find-list article)))))
 
 (defun gnus-make-thread-indent-array ()
     (not (cdr (gnus-data-find-list article)))))
 
 (defun gnus-make-thread-indent-array ()
@@ -2413,10 +2294,8 @@ This is all marks except unread, ticked, dormant, and expirable."
     (let ((gnus-replied-mark 129)
          (gnus-score-below-mark 130)
          (gnus-score-over-mark 130)
     (let ((gnus-replied-mark 129)
          (gnus-score-below-mark 130)
          (gnus-score-over-mark 130)
-         (thread nil)
-         (gnus-visual nil)
          (spec gnus-summary-line-format-spec)
          (spec gnus-summary-line-format-spec)
-         pos)
+         thread gnus-visual pos)
       (save-excursion
        (gnus-set-work-buffer)
        (let ((gnus-summary-line-format-spec spec))
       (save-excursion
        (gnus-set-work-buffer)
        (let ((gnus-summary-line-format-spec spec))
@@ -2441,11 +2320,11 @@ This is all marks except unread, ticked, dormant, and expirable."
    (point) (progn (eval gnus-summary-dummy-line-format-spec) (point))
    (list 'gnus-number gnus-tmp-number 'gnus-intangible gnus-tmp-number)))
 
    (point) (progn (eval gnus-summary-dummy-line-format-spec) (point))
    (list 'gnus-number gnus-tmp-number 'gnus-intangible gnus-tmp-number)))
 
-(defun gnus-summary-insert-line (gnus-tmp-header 
-                                gnus-tmp-level gnus-tmp-current 
-                                gnus-tmp-unread gnus-tmp-replied 
+(defun gnus-summary-insert-line (gnus-tmp-header
+                                gnus-tmp-level gnus-tmp-current
+                                gnus-tmp-unread gnus-tmp-replied
                                 gnus-tmp-expirable gnus-tmp-subject-or-nil
                                 gnus-tmp-expirable gnus-tmp-subject-or-nil
-                                &optional gnus-tmp-dummy gnus-tmp-score 
+                                &optional gnus-tmp-dummy gnus-tmp-score
                                 gnus-tmp-process)
   (let* ((gnus-tmp-indentation (aref gnus-thread-indent-array gnus-tmp-level))
         (gnus-tmp-lines (mail-header-lines gnus-tmp-header))
                                 gnus-tmp-process)
   (let* ((gnus-tmp-indentation (aref gnus-thread-indent-array gnus-tmp-level))
         (gnus-tmp-lines (mail-header-lines gnus-tmp-header))
@@ -2468,15 +2347,15 @@ This is all marks except unread, ticked, dormant, and expirable."
         (gnus-tmp-from (mail-header-from gnus-tmp-header))
         (gnus-tmp-name
          (cond
         (gnus-tmp-from (mail-header-from gnus-tmp-header))
         (gnus-tmp-name
          (cond
-          ((string-match "(.+)" gnus-tmp-from)
-           (substring gnus-tmp-from
-                      (1+ (match-beginning 0)) (1- (match-end 0))))
           ((string-match "<[^>]+> *$" gnus-tmp-from)
            (let ((beg (match-beginning 0)))
              (or (and (string-match "^\"[^\"]*\"" gnus-tmp-from)
                       (substring gnus-tmp-from (1+ (match-beginning 0))
                                  (1- (match-end 0))))
                  (substring gnus-tmp-from 0 beg))))
           ((string-match "<[^>]+> *$" gnus-tmp-from)
            (let ((beg (match-beginning 0)))
              (or (and (string-match "^\"[^\"]*\"" gnus-tmp-from)
                       (substring gnus-tmp-from (1+ (match-beginning 0))
                                  (1- (match-end 0))))
                  (substring gnus-tmp-from 0 beg))))
+          ((string-match "(.+)" gnus-tmp-from)
+           (substring gnus-tmp-from
+                      (1+ (match-beginning 0)) (1- (match-end 0))))
           (t gnus-tmp-from)))
         (gnus-tmp-subject (mail-header-subject gnus-tmp-header))
         (gnus-tmp-number (mail-header-number gnus-tmp-header))
           (t gnus-tmp-from)))
         (gnus-tmp-subject (mail-header-subject gnus-tmp-header))
         (gnus-tmp-number (mail-header-number gnus-tmp-header))
@@ -2530,7 +2409,7 @@ This is all marks except unread, ticked, dormant, and expirable."
 (defvar gnus-tmp-new-adopts nil)
 
 (defun gnus-summary-number-of-articles-in-thread (thread &optional level char)
 (defvar gnus-tmp-new-adopts nil)
 
 (defun gnus-summary-number-of-articles-in-thread (thread &optional level char)
-  "Return the number of articles in THREAD.  
+  "Return the number of articles in THREAD.
 This may be 0 in some cases -- if none of the articles in
 the thread are to be displayed."
   (let* ((number
 This may be 0 in some cases -- if none of the articles in
 the thread are to be displayed."
   (let* ((number
@@ -2579,6 +2458,10 @@ the thread are to be displayed."
 If SHOW-ALL is non-nil, already read articles are also listed.
 If NO-ARTICLE is non-nil, no article is selected initially.
 If NO-DISPLAY, don't generate a summary buffer."
 If SHOW-ALL is non-nil, already read articles are also listed.
 If NO-ARTICLE is non-nil, no article is selected initially.
 If NO-DISPLAY, don't generate a summary buffer."
+  ;; Killed foreign groups can't be entered.
+  (when (and (not (gnus-group-native-p group))
+            (not (gnus-gethash group gnus-newsrc-hashtb)))
+    (error "Dead non-native groups can't be entered"))
   (gnus-message 5 "Retrieving newsgroup: %s..." group)
   (let* ((new-group (gnus-summary-setup-buffer group))
         (quit-config (gnus-group-quit-config group))
   (gnus-message 5 "Retrieving newsgroup: %s..." group)
   (let* ((new-group (gnus-summary-setup-buffer group))
         (quit-config (gnus-group-quit-config group))
@@ -2649,8 +2532,8 @@ If NO-DISPLAY, don't generate a summary buffer."
              (let ((gnus-newsgroup-dormant nil))
                (gnus-summary-initial-limit show-all))
            (gnus-summary-initial-limit show-all))
              (let ((gnus-newsgroup-dormant nil))
                (gnus-summary-initial-limit show-all))
            (gnus-summary-initial-limit show-all))
-       (setq gnus-newsgroup-limit 
-             (mapcar 
+       (setq gnus-newsgroup-limit
+             (mapcar
               (lambda (header) (mail-header-number header))
               gnus-newsgroup-headers)))
       ;; Generate the summary buffer.
               (lambda (header) (mail-header-number header))
               gnus-newsgroup-headers)))
       ;; Generate the summary buffer.
@@ -2755,7 +2638,7 @@ If NO-DISPLAY, don't generate a summary buffer."
         ;; Just remove the leading "Re:".
         (t
          (gnus-simplify-subject-re subject))))
         ;; Just remove the leading "Re:".
         (t
          (gnus-simplify-subject-re subject))))
-  
+
   (if (and gnus-summary-gather-exclude-subject
           (string-match gnus-summary-gather-exclude-subject subject))
       nil                              ; This article shouldn't be gathered
   (if (and gnus-summary-gather-exclude-subject
           (string-match gnus-summary-gather-exclude-subject subject))
       nil                              ; This article shouldn't be gathered
@@ -2772,13 +2655,13 @@ If NO-DISPLAY, don't generate a summary buffer."
   "Gather threads by looking at Subject headers."
   (if (not gnus-summary-make-false-root)
       threads
   "Gather threads by looking at Subject headers."
   (if (not gnus-summary-make-false-root)
       threads
-    (let ((hashtb (gnus-make-hashtable 1023))
+    (let ((hashtb (gnus-make-hashtable 1024))
          (prev threads)
          (result threads)
          subject hthread whole-subject)
       (while threads
        (setq subject (gnus-general-simplify-subject
          (prev threads)
          (result threads)
          subject hthread whole-subject)
       (while threads
        (setq subject (gnus-general-simplify-subject
-                      (setq whole-subject (mail-header-subject 
+                      (setq whole-subject (mail-header-subject
                                            (caar threads)))))
        (when subject
          (if (setq hthread (gnus-gethash subject hashtb))
                                            (caar threads)))))
        (when subject
          (if (setq hthread (gnus-gethash subject hashtb))
@@ -2802,8 +2685,8 @@ If NO-DISPLAY, don't generate a summary buffer."
 
 (defun gnus-gather-threads-by-references (threads)
   "Gather threads by looking at References headers."
 
 (defun gnus-gather-threads-by-references (threads)
   "Gather threads by looking at References headers."
-  (let ((idhashtb (gnus-make-hashtable 1023))
-       (thhashtb (gnus-make-hashtable 1023))
+  (let ((idhashtb (gnus-make-hashtable 1024))
+       (thhashtb (gnus-make-hashtable 1024))
        (prev threads)
        (result threads)
        ids references id gthread gid entered ref)
        (prev threads)
        (result threads)
        ids references id gthread gid entered ref)
@@ -2849,24 +2732,60 @@ If NO-DISPLAY, don't generate a summary buffer."
       (setq threads (cdr threads)))
     result))
 
       (setq threads (cdr threads)))
     result))
 
+(defun gnus-thread-loop-p (root thread)
+  "Say whether ROOT is in THREAD."
+  (let ((th (cdr thread)))
+    (while (and th
+               (not (eq (caar th) root)))
+      (pop th))
+    (if th
+       ;; We have found a loop.
+       (let (ref-dep)
+         (setcdr thread (delq (car th) (cdr thread)))
+         (if (boundp (setq ref-dep (intern "none"
+                                           gnus-newsgroup-dependencies)))
+             (setcdr (symbol-value ref-dep)
+                     (nconc (cdr (symbol-value ref-dep))
+                            (list (car th))))
+           (set ref-dep (list nil (car th))))
+         1)
+      ;; Recurse down into the sub-threads and look for loops.
+      (apply '+
+            (mapcar
+             (lambda (thread) (gnus-thread-loop-p root thread))
+             (cdr thread))))))
+
 (defun gnus-make-threads ()
   "Go through the dependency hashtb and find the roots.         Return all threads."
   (let (threads)
 (defun gnus-make-threads ()
   "Go through the dependency hashtb and find the roots.         Return all threads."
   (let (threads)
-    (mapatoms
-     (lambda (refs)
-       (unless (car (symbol-value refs))
-        ;; These threads do not refer back to any other articles,
-        ;; so they're roots.
-        (setq threads (append (cdr (symbol-value refs)) threads))))
-     gnus-newsgroup-dependencies)
+    (while (catch 'infloop
+            (mapatoms
+             (lambda (refs)
+               ;; Deal with self-referencing References loops.
+               (when (and (car (symbol-value refs))
+                          (not (zerop
+                                (apply
+                                 '+
+                                 (mapcar
+                                  (lambda (thread)
+                                    (gnus-thread-loop-p
+                                     (car (symbol-value refs)) thread))
+                                  (cdr (symbol-value refs)))))))
+                 (setq threads nil)
+                 (throw 'infloop t))
+               (unless (car (symbol-value refs))
+                 ;; These threads do not refer back to any other articles,
+                 ;; so they're roots.
+                 (setq threads (append (cdr (symbol-value refs)) threads))))
+             gnus-newsgroup-dependencies)))
     threads))
 
 (defun gnus-build-sparse-threads ()
   (let ((headers gnus-newsgroup-headers)
        (deps gnus-newsgroup-dependencies)
     threads))
 
 (defun gnus-build-sparse-threads ()
   (let ((headers gnus-newsgroup-headers)
        (deps gnus-newsgroup-dependencies)
-       header references generation relations 
+       header references generation relations
        cthread subject child end pthread relation)
        cthread subject child end pthread relation)
-    ;; First we create an alist of generations/relations, where 
+    ;; First we create an alist of generations/relations, where
     ;; generations is how much we trust the relation, and the relation
     ;; is parent/child.
     (gnus-message 7 "Making sparse threads...")
     ;; generations is how much we trust the relation, and the relation
     ;; is parent/child.
     (gnus-message 7 "Making sparse threads...")
@@ -2896,7 +2815,7 @@ If NO-DISPLAY, don't generate a summary buffer."
                (unless (car (symbol-value cthread))
                  ;; Make this article the parent of these threads.
                  (setcar (symbol-value cthread)
                (unless (car (symbol-value cthread))
                  ;; Make this article the parent of these threads.
                  (setcar (symbol-value cthread)
-                         (vector gnus-reffed-article-number 
+                         (vector gnus-reffed-article-number
                                  (cadddr relation)
                                  "" ""
                                  (cadr relation)
                                  (cadddr relation)
                                  "" ""
                                  (cadr relation)
@@ -2993,13 +2912,25 @@ If NO-DISPLAY, don't generate a summary buffer."
        header level nil (gnus-article-mark article)
        (memq article gnus-newsgroup-replied)
        (memq article gnus-newsgroup-expirable)
        header level nil (gnus-article-mark article)
        (memq article gnus-newsgroup-replied)
        (memq article gnus-newsgroup-expirable)
-       (mail-header-subject header)
+       ;; Only insert the Subject string when it's different
+       ;; from the previous Subject string.
+       (unless (gnus-subject-equal
+               (condition-case ()
+                   (mail-header-subject
+                    (gnus-data-header
+                     (cadr
+                      (gnus-data-find-list
+                       article
+                       (gnus-data-list t)))))
+                 (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))))))))
        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))))))))
-     
+
 (defun gnus-summary-update-article (article &optional iheader)
   "Update ARTICLE in the summary buffer."
   (set-buffer gnus-summary-buffer)
 (defun gnus-summary-update-article (article &optional iheader)
   "Update ARTICLE in the summary buffer."
   (set-buffer gnus-summary-buffer)
@@ -3010,7 +2941,7 @@ If NO-DISPLAY, don't generate a summary buffer."
         (references (mail-header-references header))
         (parent
          (gnus-id-to-thread
         (references (mail-header-references header))
         (parent
          (gnus-id-to-thread
-          (or (gnus-parent-id 
+          (or (gnus-parent-id
                (when (and references
                           (not (equal "" references)))
                  references))
                (when (and references
                           (not (equal "" references)))
                  references))
@@ -3034,11 +2965,12 @@ If NO-DISPLAY, don't generate a summary buffer."
 (defun gnus-rebuild-thread (id)
   "Rebuild the thread containing ID."
   (let ((buffer-read-only nil)
 (defun gnus-rebuild-thread (id)
   "Rebuild the thread containing ID."
   (let ((buffer-read-only nil)
-       current thread data)
+       old-pos current thread data)
     (if (not gnus-show-threads)
        (setq thread (list (car (gnus-id-to-thread id))))
       ;; Get the thread this article is part of.
       (setq thread (gnus-remove-thread id)))
     (if (not gnus-show-threads)
        (setq thread (list (car (gnus-id-to-thread id))))
       ;; Get the thread this article is part of.
       (setq thread (gnus-remove-thread id)))
+    (setq old-pos (gnus-point-at-bol))
     (setq current (save-excursion
                    (and (zerop (forward-line -1))
                         (gnus-summary-article-number))))
     (setq current (save-excursion
                    (and (zerop (forward-line -1))
                         (gnus-summary-article-number))))
@@ -3068,8 +3000,7 @@ If NO-DISPLAY, don't generate a summary buffer."
        (setq data (nreverse gnus-newsgroup-data))
        (setq threads gnus-newsgroup-threads))
       ;; We splice the new data into the data structure.
        (setq data (nreverse gnus-newsgroup-data))
        (setq threads gnus-newsgroup-threads))
       ;; We splice the new data into the data structure.
-      (gnus-data-enter-list current data)
-      (gnus-data-compute-positions)
+      (gnus-data-enter-list current data (- (point) old-pos))
       (setq gnus-newsgroup-threads (nconc threads gnus-newsgroup-threads)))))
 
 (defun gnus-number-to-header (number)
       (setq gnus-newsgroup-threads (nconc threads gnus-newsgroup-threads)))))
 
 (defun gnus-number-to-header (number)
@@ -3083,7 +3014,7 @@ If NO-DISPLAY, don't generate a summary buffer."
 
 (defun gnus-parent-headers (headers &optional generation)
   "Return the headers of the GENERATIONeth parent of HEADERS."
 
 (defun gnus-parent-headers (headers &optional generation)
   "Return the headers of the GENERATIONeth parent of HEADERS."
-  (unless generation 
+  (unless generation
     (setq generation 1))
   (let (references parent)
     (while (and headers (not (zerop generation)))
     (setq generation 1))
   (let (references parent)
     (while (and headers (not (zerop generation)))
@@ -3114,7 +3045,7 @@ If NO-DISPLAY, don't generate a summary buffer."
   (let ((level (gnus-summary-thread-level article))
        (refs (mail-header-references  (gnus-summary-article-header article)))
        particle)
   (let ((level (gnus-summary-thread-level article))
        (refs (mail-header-references  (gnus-summary-article-header article)))
        particle)
-    (cond 
+    (cond
      ((null level) nil)
      ((zerop level) t)
      ((null refs) t)
      ((null level) nil)
      ((zerop level) t)
      ((null refs) t)
@@ -3127,7 +3058,7 @@ If NO-DISPLAY, don't generate a summary buffer."
 (defun gnus-root-id (id)
   "Return the id of the root of the thread where ID appears."
   (let (last-id prev)
 (defun gnus-root-id (id)
   "Return the id of the root of the thread where ID appears."
   (let (last-id prev)
-    (while (and id (setq prev (car (gnus-gethash 
+    (while (and id (setq prev (car (gnus-gethash
                                    id gnus-newsgroup-dependencies))))
       (setq last-id id
            id (gnus-parent-id (mail-header-references prev))))
                                    id gnus-newsgroup-dependencies))))
       (setq last-id id
            id (gnus-parent-id (mail-header-references prev))))
@@ -3179,8 +3110,8 @@ If NO-DISPLAY, don't generate a summary buffer."
                  ;; If we use dummy roots, then we have to remove the
                  ;; dummy root as well.
                  (when (eq gnus-summary-make-false-root 'dummy)
                  ;; If we use dummy roots, then we have to remove the
                  ;; dummy root as well.
                  (when (eq gnus-summary-make-false-root 'dummy)
-                   ;; Uhm.
-                   )
+                   (gnus-delete-line)
+                   (gnus-data-compute-positions))
                  (setq thread (cdr thread))
                  (while thread
                    (gnus-remove-thread-1 (car thread))
                  (setq thread (cdr thread))
                  (while thread
                    (gnus-remove-thread-1 (car thread))
@@ -3189,16 +3120,19 @@ If NO-DISPLAY, don't generate a summary buffer."
 
 (defun gnus-remove-thread-1 (thread)
   "Remove the thread THREAD recursively."
 
 (defun gnus-remove-thread-1 (thread)
   "Remove the thread THREAD recursively."
-  (let ((number (mail-header-number (car thread)))
-       pos)
-    (when (setq pos (text-property-any
-                    (point-min) (point-max) 'gnus-number number))
-      (goto-char pos)
-      (gnus-delete-line)
-      (gnus-data-remove number))
-    (setq thread (cdr thread))
+  (let ((number (mail-header-number (pop thread)))
+       d)
+    (setq thread (reverse thread))
     (while thread
     (while thread
-      (gnus-remove-thread-1 (pop thread)))))
+      (gnus-remove-thread-1 (pop thread)))
+    (when (setq d (gnus-data-find number))
+      (goto-char (gnus-data-pos d))
+      (gnus-data-remove
+       number
+       (- (gnus-point-at-bol)
+         (prog1
+             (1+ (gnus-point-at-eol))
+           (gnus-delete-line)))))))
 
 (defun gnus-sort-threads (threads)
   "Sort THREADS."
 
 (defun gnus-sort-threads (threads)
   "Sort THREADS."
@@ -3215,7 +3149,7 @@ If NO-DISPLAY, don't generate a summary buffer."
     (gnus-message 7 "Sorting articles...")
     (prog1
        (setq gnus-newsgroup-headers
     (gnus-message 7 "Sorting articles...")
     (prog1
        (setq gnus-newsgroup-headers
-             (sort articles (gnus-make-sort-function 
+             (sort articles (gnus-make-sort-function
                              gnus-article-sort-functions)))
       (gnus-message 7 "Sorting articles...done"))))
 
                              gnus-article-sort-functions)))
       (gnus-message 7 "Sorting articles...done"))))
 
@@ -3239,6 +3173,16 @@ If NO-DISPLAY, don't generate a summary buffer."
   (gnus-article-sort-by-number
    (gnus-thread-header h1) (gnus-thread-header h2)))
 
   (gnus-article-sort-by-number
    (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)
+     (mail-header-lines h2)))
+
+(defun gnus-thread-sort-by-lines (h1 h2)
+  "Sort threads by root article Lines header."
+  (gnus-article-sort-by-lines
+   (gnus-thread-header h1) (gnus-thread-header h2)))
+
 (defsubst gnus-article-sort-by-author (h1 h2)
   "Sort articles by root author."
   (string-lessp
 (defsubst gnus-article-sort-by-author (h1 h2)
   "Sort articles by root author."
   (string-lessp
@@ -3269,9 +3213,9 @@ If NO-DISPLAY, don't generate a summary buffer."
 
 (defsubst gnus-article-sort-by-date (h1 h2)
   "Sort articles by root article date."
 
 (defsubst gnus-article-sort-by-date (h1 h2)
   "Sort articles by root article date."
-  (string-lessp
-   (inline (gnus-sortable-date (mail-header-date h1)))
-   (inline (gnus-sortable-date (mail-header-date h2)))))
+  (gnus-time-less
+   (gnus-date-get-time (mail-header-date h1))
+   (gnus-date-get-time (mail-header-date h2))))
 
 (defun gnus-thread-sort-by-date (h1 h2)
   "Sort threads by root article date."
 
 (defun gnus-thread-sort-by-date (h1 h2)
   "Sort threads by root article date."
@@ -3447,8 +3391,7 @@ or a straight list of headers."
                  gnus-tmp-header nil))
           ;; If the article lies outside the current limit,
           ;; then we do not display it.
                  gnus-tmp-header nil))
           ;; If the article lies outside the current limit,
           ;; then we do not display it.
-          ((and (not (memq number gnus-newsgroup-limit))
-                (not gnus-tmp-dummy-line))
+          ((not (memq number gnus-newsgroup-limit))
            (setq gnus-tmp-gathered
                  (nconc (mapcar
                          (lambda (h) (mail-header-number (car h)))
            (setq gnus-tmp-gathered
                  (nconc (mapcar
                          (lambda (h) (mail-header-number (car h)))
@@ -3468,8 +3411,8 @@ or a straight list of headers."
                        default-score)
                    gnus-summary-mark-below)
                 ;; Don't touch sparse articles.
                        default-score)
                    gnus-summary-mark-below)
                 ;; Don't touch sparse articles.
-                (not (memq number gnus-newsgroup-sparse))
-                (not (memq number gnus-newsgroup-ancient)))
+                (not (gnus-summary-article-sparse-p number))
+                (not (gnus-summary-article-ancient-p number)))
            (setq gnus-newsgroup-unreads
                  (delq number gnus-newsgroup-unreads))
            (if gnus-newsgroup-auto-expire
            (setq gnus-newsgroup-unreads
                  (delq number gnus-newsgroup-unreads))
            (if gnus-newsgroup-auto-expire
@@ -3543,15 +3486,15 @@ or a straight list of headers."
             gnus-tmp-from (mail-header-from gnus-tmp-header)
             gnus-tmp-name
             (cond
             gnus-tmp-from (mail-header-from gnus-tmp-header)
             gnus-tmp-name
             (cond
-             ((string-match "(.+)" gnus-tmp-from)
-              (substring gnus-tmp-from
-                         (1+ (match-beginning 0)) (1- (match-end 0))))
              ((string-match "<[^>]+> *$" gnus-tmp-from)
               (setq beg-match (match-beginning 0))
               (or (and (string-match "^\"[^\"]*\"" gnus-tmp-from)
                        (substring gnus-tmp-from (1+ (match-beginning 0))
                                   (1- (match-end 0))))
                   (substring gnus-tmp-from 0 beg-match)))
              ((string-match "<[^>]+> *$" gnus-tmp-from)
               (setq beg-match (match-beginning 0))
               (or (and (string-match "^\"[^\"]*\"" gnus-tmp-from)
                        (substring gnus-tmp-from (1+ (match-beginning 0))
                                   (1- (match-end 0))))
                   (substring gnus-tmp-from 0 beg-match)))
+             ((string-match "(.+)" gnus-tmp-from)
+              (substring gnus-tmp-from
+                         (1+ (match-beginning 0)) (1- (match-end 0))))
              (t gnus-tmp-from)))
            (when (string= gnus-tmp-name "")
              (setq gnus-tmp-name gnus-tmp-from))
              (t gnus-tmp-from)))
            (when (string= gnus-tmp-name "")
              (setq gnus-tmp-name gnus-tmp-from))
@@ -3580,6 +3523,8 @@ or a straight list of headers."
   "Generate an unthreaded summary buffer based on HEADERS."
   (let (header number mark)
 
   "Generate an unthreaded summary buffer based on HEADERS."
   (let (header number mark)
 
+    (beginning-of-line)
+
     (while headers
       ;; We may have to root out some bad articles...
       (when (memq (setq number (mail-header-number
     (while headers
       ;; We may have to root out some bad articles...
       (when (memq (setq number (mail-header-number
@@ -3590,7 +3535,7 @@ or a straight list of headers."
                   (< (or (cdr (assq number gnus-newsgroup-scored))
                          gnus-summary-default-score 0)
                      gnus-summary-mark-below)
                   (< (or (cdr (assq number gnus-newsgroup-scored))
                          gnus-summary-default-score 0)
                      gnus-summary-mark-below)
-                  (not (memq number gnus-newsgroup-ancient)))
+                  (not (gnus-summary-article-ancient-p number)))
          (setq gnus-newsgroup-unreads
                (delq number gnus-newsgroup-unreads))
          (if gnus-newsgroup-auto-expire
          (setq gnus-newsgroup-unreads
                (delq number gnus-newsgroup-unreads))
          (if gnus-newsgroup-auto-expire
@@ -3617,7 +3562,8 @@ If READ-ALL is non-nil, all articles in the group are selected."
         articles fetched-articles cached)
 
     (unless (gnus-check-server
         articles fetched-articles cached)
 
     (unless (gnus-check-server
-            (setq gnus-current-select-method (gnus-find-method-for-group group)))
+            (setq gnus-current-select-method
+                  (gnus-find-method-for-group group)))
       (error "Couldn't open server"))
 
     (or (and entry (not (eq (car entry) t))) ; Either it's active...
       (error "Couldn't open server"))
 
     (or (and entry (not (eq (car entry) t))) ; Either it's active...
@@ -3653,6 +3599,10 @@ If READ-ALL is non-nil, all articles in the group are selected."
 
     (setq gnus-newsgroup-processable nil)
 
 
     (setq gnus-newsgroup-processable nil)
 
+    (gnus-update-read-articles group gnus-newsgroup-unreads)
+    (unless (gnus-ephemeral-group-p gnus-newsgroup-name)
+      (gnus-group-update-group group))
+
     (setq articles (gnus-articles-to-read group read-all))
 
     (cond
     (setq articles (gnus-articles-to-read group read-all))
 
     (cond
@@ -3678,7 +3628,8 @@ If READ-ALL is non-nil, all articles in the group are selected."
                                     (not (eq gnus-fetch-old-headers 'some))
                                     (not (numberp gnus-fetch-old-headers)))
                                    (> (length articles) 1))))))
                                     (not (eq gnus-fetch-old-headers 'some))
                                     (not (numberp gnus-fetch-old-headers)))
                                    (> (length articles) 1))))))
-               (gnus-get-newsgroup-headers-xover articles)
+               (gnus-get-newsgroup-headers-xover
+                articles nil nil gnus-newsgroup-name t)
              (gnus-get-newsgroup-headers)))
       (gnus-message 5 "Fetching headers for %s...done" gnus-newsgroup-name)
 
              (gnus-get-newsgroup-headers)))
       (gnus-message 5 "Fetching headers for %s...done" gnus-newsgroup-name)
 
@@ -3722,7 +3673,7 @@ If READ-ALL is non-nil, all articles in the group are selected."
       ;; GROUP is successfully selected.
       (or gnus-newsgroup-headers t)))))
 
       ;; GROUP is successfully selected.
       (or gnus-newsgroup-headers t)))))
 
-(defun gnus-articles-to-read (group read-all)
+(defun gnus-articles-to-read (group &optional read-all)
   ;; Find out what articles the user wants to read.
   (let* ((articles
          ;; Select all articles if `read-all' is non-nil, or if there
   ;; Find out what articles the user wants to read.
   (let* ((articles
          ;; Select all articles if `read-all' is non-nil, or if there
@@ -3755,7 +3706,8 @@ If READ-ALL is non-nil, all articles in the group are selected."
                         (read-string
                          (format
                           "How many articles from %s (default %d): "
                         (read-string
                          (format
                           "How many articles from %s (default %d): "
-                          gnus-newsgroup-name number))))
+                          (gnus-limit-string gnus-newsgroup-name 35)
+                          number))))
                    (if (string-match "^[ \t]*$" input) number input)))
                 ((and (> scored marked) (< scored number)
                       (> (- scored number) 20))
                    (if (string-match "^[ \t]*$" input) number input)))
                 ((and (> scored marked) (< scored number)
                       (> (- scored number) 20))
@@ -3874,7 +3826,7 @@ If READ-ALL is non-nil, all articles in the group are selected."
                                                (car type))))))
          (push (cons (cdr type)
                      (if (memq (cdr type) uncompressed) list
                                                (car type))))))
          (push (cons (cdr type)
                      (if (memq (cdr type) uncompressed) list
-                       (gnus-compress-sequence 
+                       (gnus-compress-sequence
                         (set symbol (sort list '<)) t)))
                newmarked)))
 
                         (set symbol (sort list '<)) t)))
                newmarked)))
 
@@ -3927,12 +3879,21 @@ If WHERE is `summary', the summary mode line format will be used."
                    (gnus-mode-string-quote
                     (mail-header-subject gnus-current-headers))
                  ""))
                    (gnus-mode-string-quote
                     (mail-header-subject gnus-current-headers))
                  ""))
-              max-len
+              bufname-length max-len
               gnus-tmp-header);; passed as argument to any user-format-funcs
          (setq mode-string (eval mformat))
               gnus-tmp-header);; passed as argument to any user-format-funcs
          (setq mode-string (eval mformat))
+         (setq bufname-length (if (string-match "%b" mode-string)
+                                  (- (length
+                                      (buffer-name
+                                       (if (eq where 'summary)
+                                           nil
+                                         (get-buffer gnus-article-buffer))))
+                                     2)
+                                0))
          (setq max-len (max 4 (if gnus-mode-non-string-length
                                   (- (window-width)
          (setq max-len (max 4 (if gnus-mode-non-string-length
                                   (- (window-width)
-                                     gnus-mode-non-string-length)
+                                     gnus-mode-non-string-length
+                                     bufname-length)
                                 (length mode-string))))
          ;; We might have to chop a bit of the string off...
          (when (> (length mode-string) max-len)
                                 (length mode-string))))
          ;; We might have to chop a bit of the string off...
          (when (> (length mode-string) max-len)
@@ -3942,9 +3903,8 @@ If WHERE is `summary', the summary mode line format will be used."
          ;; Pad the mode string a bit.
          (setq mode-string (format (format "%%-%ds" max-len) mode-string))))
       ;; Update the mode line.
          ;; Pad the mode string a bit.
          (setq mode-string (format (format "%%-%ds" max-len) mode-string))))
       ;; Update the mode line.
-      (setq mode-line-buffer-identification 
-           (gnus-mode-line-buffer-identification
-            (list mode-string)))
+      (setq mode-line-buffer-identification
+           (gnus-mode-line-buffer-identification (list mode-string)))
       (set-buffer-modified-p t))))
 
 (defun gnus-create-xref-hashtb (from-newsgroup headers unreads)
       (set-buffer-modified-p t))))
 
 (defun gnus-create-xref-hashtb (from-newsgroup headers unreads)
@@ -3952,7 +3912,7 @@ If WHERE is `summary', the summary mode line format will be used."
 The resulting hash table is returned, or nil if no Xrefs were found."
   (let* ((virtual (gnus-virtual-group-p from-newsgroup))
         (prefix (if virtual "" (gnus-group-real-prefix from-newsgroup)))
 The resulting hash table is returned, or nil if no Xrefs were found."
   (let* ((virtual (gnus-virtual-group-p from-newsgroup))
         (prefix (if virtual "" (gnus-group-real-prefix from-newsgroup)))
-        (xref-hashtb (make-vector 63 0))
+        (xref-hashtb (gnus-make-hashtable))
         start group entry number xrefs header)
     (while headers
       (setq header (pop headers))
         start group entry number xrefs header)
     (while headers
       (setq header (pop headers))
@@ -4036,11 +3996,14 @@ The resulting hash table is returned, or nil if no Xrefs were found."
          (when (or (> id (cdr active))
                    (< id (car active)))
            (setq articles (delq id articles))))))
          (when (or (> id (cdr active))
                    (< id (car active)))
            (setq articles (delq id articles))))))
-    (gnus-undo-register
-      `(progn
-        (gnus-info-set-marks ,info ,(gnus-info-marks info))
-        (gnus-info-set-read ,info ,(gnus-info-read info))
-        (gnus-group-update-group group t)))
+    (save-excursion
+      (set-buffer gnus-group-buffer)
+      (gnus-undo-register
+       `(progn
+          (gnus-info-set-marks ',info ',(gnus-info-marks info) t)
+          (gnus-info-set-read ',info ',(gnus-info-read info))
+          (gnus-get-unread-articles-in-group ',info (gnus-active ,group))
+          (gnus-group-update-group ,group t))))
     ;; If the read list is nil, we init it.
     (and active
         (null (gnus-info-read info))
     ;; If the read list is nil, we init it.
     (and active
         (null (gnus-info-read info))
@@ -4082,9 +4045,6 @@ The resulting hash table is returned, or nil if no Xrefs were found."
                                            gnus-valid-select-methods)))
                 (equal (nth 1 m1) (nth 1 m2)))))))
 
                                            gnus-valid-select-methods)))
                 (equal (nth 1 m1) (nth 1 m2)))))))
 
-(defsubst gnus-header-value ()
-  (buffer-substring (match-end 0) (gnus-point-at-eol)))
-
 (defvar gnus-newsgroup-none-id 0)
 
 (defun gnus-get-newsgroup-headers (&optional dependencies force-new)
 (defvar gnus-newsgroup-none-id 0)
 
 (defun gnus-get-newsgroup-headers (&optional dependencies force-new)
@@ -4129,28 +4089,25 @@ The resulting hash table is returned, or nil if no Xrefs were found."
            (progn
              (goto-char p)
              (if (search-forward "\nsubject: " nil t)
            (progn
              (goto-char p)
              (if (search-forward "\nsubject: " nil t)
-                 (gnus-header-value) "(none)"))
+                 (nnheader-header-value) "(none)"))
            ;; From.
            (progn
              (goto-char p)
              (if (search-forward "\nfrom: " nil t)
            ;; From.
            (progn
              (goto-char p)
              (if (search-forward "\nfrom: " nil t)
-                 (gnus-header-value) "(nobody)"))
+                 (nnheader-header-value) "(nobody)"))
            ;; Date.
            (progn
              (goto-char p)
              (if (search-forward "\ndate: " nil t)
            ;; Date.
            (progn
              (goto-char p)
              (if (search-forward "\ndate: " nil t)
-                 (gnus-header-value) ""))
+                 (nnheader-header-value) ""))
            ;; Message-ID.
            (progn
              (goto-char p)
            ;; Message-ID.
            (progn
              (goto-char p)
-             (if (search-forward "\nmessage-id: " nil t)
-                 (setq id (gnus-header-value))
-               ;; If there was no message-id, we just fake one to make
-               ;; subsequent routines simpler.
-               (setq id (concat "none+"
-                                (int-to-string
-                                 (setq gnus-newsgroup-none-id
-                                       (1+ gnus-newsgroup-none-id)))))))
+             (setq id (if (search-forward "\nmessage-id: " nil t)
+                          (nnheader-header-value)
+                        ;; If there was no message-id, we just fake one
+                        ;; to make subsequent routines simpler.
+                        (nnheader-generate-fake-message-id))))
            ;; References.
            (progn
              (goto-char p)
            ;; References.
            (progn
              (goto-char p)
@@ -4158,7 +4115,7 @@ The resulting hash table is returned, or nil if no Xrefs were found."
                  (progn
                    (setq end (point))
                    (prog1
                  (progn
                    (setq end (point))
                    (prog1
-                       (gnus-header-value)
+                       (nnheader-header-value)
                      (setq ref
                            (buffer-substring
                             (progn
                      (setq ref
                            (buffer-substring
                             (progn
@@ -4172,11 +4129,11 @@ The resulting hash table is returned, or nil if no Xrefs were found."
                ;; were no references and the in-reply-to header looks
                ;; promising.
                (if (and (search-forward "\nin-reply-to: " nil t)
                ;; were no references and the in-reply-to header looks
                ;; promising.
                (if (and (search-forward "\nin-reply-to: " nil t)
-                        (setq in-reply-to (gnus-header-value))
+                        (setq in-reply-to (nnheader-header-value))
                         (string-match "<[^>]+>" in-reply-to))
                    (setq ref (substring in-reply-to (match-beginning 0)
                                         (match-end 0)))
                         (string-match "<[^>]+>" in-reply-to))
                    (setq ref (substring in-reply-to (match-beginning 0)
                                         (match-end 0)))
-                 (setq ref ""))))
+                 (setq ref nil))))
            ;; Chars.
            0
            ;; Lines.
            ;; Chars.
            0
            ;; Lines.
@@ -4190,7 +4147,7 @@ The resulting hash table is returned, or nil if no Xrefs were found."
            (progn
              (goto-char p)
              (and (search-forward "\nxref: " nil t)
            (progn
              (goto-char p)
              (and (search-forward "\nxref: " nil t)
-                  (gnus-header-value)))))
+                  (nnheader-header-value)))))
          (when (equal id ref)
            (setq ref nil))
          ;; We do the threading while we read the headers.  The
          (when (equal id ref)
            (setq ref nil))
          ;; We do the threading while we read the headers.  The
@@ -4201,22 +4158,18 @@ The resulting hash table is returned, or nil if no Xrefs were found."
          (if (boundp (setq id-dep (intern id dependencies)))
              (if (and (car (symbol-value id-dep))
                       (not force-new))
          (if (boundp (setq id-dep (intern id dependencies)))
              (if (and (car (symbol-value id-dep))
                       (not force-new))
-                 ;; An article with this Message-ID has already
-                 ;; been seen, so we ignore this one, except we add
-                 ;; any additional Xrefs (in case the two articles
-                 ;; came from different servers).
+                 ;; An article with this Message-ID has already been seen,
+                 ;; so we rename the Message-ID.
                  (progn
                  (progn
-                   (mail-header-set-xref
-                    (car (symbol-value id-dep))
-                    (concat (or (mail-header-xref
-                                 (car (symbol-value id-dep)))
-                                "")
-                            (or (mail-header-xref header) "")))
-                   (setq header nil))
+                   (set
+                    (setq id-dep (intern (setq id (nnmail-message-id))
+                                         dependencies))
+                    (list header))
+                   (mail-header-set-id header id))
                (setcar (symbol-value id-dep) header))
            (set id-dep (list header)))
                (setcar (symbol-value id-dep) header))
            (set id-dep (list header)))
-         (when header
-           (if (boundp (setq ref-dep (intern ref dependencies)))
+         (when  header
+           (if (boundp (setq ref-dep (intern (or ref "none") dependencies)))
                (setcdr (symbol-value ref-dep)
                        (nconc (cdr (symbol-value ref-dep))
                               (list (symbol-value id-dep))))
                (setcdr (symbol-value ref-dep)
                        (nconc (cdr (symbol-value ref-dep))
                               (list (symbol-value id-dep))))
@@ -4233,7 +4186,7 @@ The resulting hash table is returned, or nil if no Xrefs were found."
   '(prog1
        (if (= (following-char) ?\t)
           0
   '(prog1
        (if (= (following-char) ?\t)
           0
-        (let ((num (condition-case nil (read buffer) (error nil))))
+        (let ((num (ignore-errors (read buffer))))
           (if (numberp num) num 0)))
      (unless (eobp)
        (forward-char 1))))
           (if (numberp num) num 0)))
      (unless (eobp)
        (forward-char 1))))
@@ -4244,7 +4197,7 @@ The resulting hash table is returned, or nil if no Xrefs were found."
 (defmacro gnus-nov-field ()
   '(buffer-substring (point) (if (gnus-nov-skip-field) (1- (point)) eol)))
 
 (defmacro gnus-nov-field ()
   '(buffer-substring (point) (if (gnus-nov-skip-field) (1- (point)) eol)))
 
-(defvar gnus-nov-none-counter 0)
+;; (defvar gnus-nov-none-counter 0)
 
 ;; This function has to be called with point after the article number
 ;; on the beginning of the line.
 
 ;; This function has to be called with point after the article number
 ;; on the beginning of the line.
@@ -4254,39 +4207,38 @@ The resulting hash table is returned, or nil if no Xrefs were found."
        header ref id id-dep ref-dep)
 
     ;; overview: [num subject from date id refs chars lines misc]
        header ref id id-dep ref-dep)
 
     ;; overview: [num subject from date id refs chars lines misc]
-    (narrow-to-region (point) eol)
-    (unless (eobp)
-      (forward-char))
-
-    (setq header
-         (vector
-          number                       ; number
-          (gnus-nov-field)             ; subject
-          (gnus-nov-field)             ; from
-          (gnus-nov-field)             ; date
-          (setq id (or (gnus-nov-field)
-                       (concat "none+"
-                               (int-to-string
-                                (incf gnus-nov-none-counter))))) ; id
-          (progn
-            (let ((beg (point)))
-              (search-forward "\t" eol)
-              (if (search-backward ">" beg t)
-                  (setq ref
-                        (buffer-substring
-                         (1+ (point))
-                         (search-backward "<" beg t)))
-                (setq ref nil))
-              (goto-char beg))
-            (gnus-nov-field))          ; refs
-          (gnus-nov-read-integer)      ; chars
-          (gnus-nov-read-integer)      ; lines
-          (if (= (following-char) ?\n)
-              nil
-            (gnus-nov-field))          ; misc
-          ))
-
-    (widen)
+    (unwind-protect
+       (progn
+         (narrow-to-region (point) eol)
+         (unless (eobp)
+           (forward-char))
+
+         (setq header
+               (vector
+                number                 ; number
+                (gnus-nov-field)       ; subject
+                (gnus-nov-field)       ; from
+                (gnus-nov-field)       ; date
+                (setq id (or (gnus-nov-field)
+                             (nnheader-generate-fake-message-id))) ; id
+                (progn
+                  (let ((beg (point)))
+                    (search-forward "\t" eol)
+                    (if (search-backward ">" beg t)
+                        (setq ref
+                              (buffer-substring
+                               (1+ (point))
+                               (search-backward "<" beg t)))
+                      (setq ref nil))
+                    (goto-char beg))
+                  (gnus-nov-field))    ; refs
+                (gnus-nov-read-integer) ; chars
+                (gnus-nov-read-integer) ; lines
+                (if (= (following-char) ?\n)
+                    nil
+                  (gnus-nov-field))))) ; misc
+
+      (widen))
 
     ;; We build the thread tree.
     (when (equal id ref)
 
     ;; We build the thread tree.
     (when (equal id ref)
@@ -4296,17 +4248,13 @@ The resulting hash table is returned, or nil if no Xrefs were found."
        (if (and (car (symbol-value id-dep))
                 (not force-new))
            ;; An article with this Message-ID has already been seen,
        (if (and (car (symbol-value id-dep))
                 (not force-new))
            ;; An article with this Message-ID has already been seen,
-           ;; so we ignore this one, except we add any additional
-           ;; Xrefs (in case the two articles came from different
-           ;; servers.
+           ;; so we rename the Message-ID.
            (progn
            (progn
-             (mail-header-set-xref
-              (car (symbol-value id-dep))
-              (concat (or (mail-header-xref
-                           (car (symbol-value id-dep)))
-                          "")
-                      (or (mail-header-xref header) "")))
-             (setq header nil))
+             (set
+              (setq id-dep (intern (setq id (nnmail-message-id))
+                                   dependencies))
+              (list header))
+             (mail-header-set-id header id))
          (setcar (symbol-value id-dep) header))
       (set id-dep (list header)))
     (when header
          (setcar (symbol-value id-dep) header))
       (set id-dep (list header)))
     (when header
@@ -4318,8 +4266,9 @@ The resulting hash table is returned, or nil if no Xrefs were found."
     header))
 
 ;; Goes through the xover lines and returns a list of vectors
     header))
 
 ;; Goes through the xover lines and returns a list of vectors
-(defun gnus-get-newsgroup-headers-xover (sequence &optional 
-                                                 force-new dependencies)
+(defun gnus-get-newsgroup-headers-xover (sequence &optional
+                                                 force-new dependencies
+                                                 group also-fetch-heads)
   "Parse the news overview data in the server buffer, and return a
 list of headers that match SEQUENCE (see `nntp-retrieve-headers')."
   ;; Get the Xref when the users reads the articles since most/some
   "Parse the news overview data in the server buffer, and return a
 list of headers that match SEQUENCE (see `nntp-retrieve-headers')."
   ;; Get the Xref when the users reads the articles since most/some
@@ -4350,9 +4299,24 @@ list of headers that match SEQUENCE (see `nntp-retrieve-headers')."
                   (push header headers))
              (forward-line 1))
          (error
                   (push header headers))
              (forward-line 1))
          (error
-          (gnus-error 4 "Strange nov line")))
+          (gnus-error 4 "Strange nov line (%d)"
+                      (count-lines (point-min) (point)))))
        (forward-line 1))
        (forward-line 1))
-      (nreverse headers))))
+      ;; 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
+      ;; article may not have been generated yet, so this may fail.
+      ;; We work around this problem by retrieving the last few
+      ;; headers using HEAD.
+      (if (or (not also-fetch-heads)
+             (not sequence))
+         ;; We (probably) got all the headers.
+         (nreverse headers)
+       (let ((gnus-nov-is-evil t))
+         (nconc
+          (nreverse headers)
+          (when (gnus-retrieve-headers sequence group)
+            (gnus-get-newsgroup-headers))))))))
 
 (defun gnus-article-get-xrefs ()
   "Fill in the Xref value in `gnus-current-headers', if necessary.
 
 (defun gnus-article-get-xrefs ()
   "Fill in the Xref value in `gnus-current-headers', if necessary.
@@ -4381,18 +4345,20 @@ This is meant to be called in `gnus-article-internal-prepare-hook'."
   (let ((header (if (and old-header use-old-header)
                    old-header (gnus-read-header id)))
        (number (and (numberp id) id))
   (let ((header (if (and old-header use-old-header)
                    old-header (gnus-read-header id)))
        (number (and (numberp id) id))
-       pos)
+       pos d)
     (when header
       ;; Rebuild the thread that this article is part of and go to the
       ;; article we have fetched.
       (when (and (not gnus-show-threads)
                 old-header)
     (when header
       ;; Rebuild the thread that this article is part of and go to the
       ;; article we have fetched.
       (when (and (not gnus-show-threads)
                 old-header)
-       (when (setq pos (text-property-any
-                        (point-min) (point-max) 'gnus-number 
-                        (mail-header-number old-header)))
-         (goto-char pos)
-         (gnus-delete-line)
-         (gnus-data-remove (mail-header-number old-header))))
+       (when (setq d (gnus-data-find (mail-header-number old-header)))
+         (goto-char (gnus-data-pos d))
+         (gnus-data-remove
+          number
+          (- (gnus-point-at-bol)
+             (prog1
+                 (1+ (gnus-point-at-eol))
+               (gnus-delete-line))))))
       (when old-header
        (mail-header-set-number header (mail-header-number old-header)))
       (setq gnus-newsgroup-sparse
       (when old-header
        (mail-header-set-number header (mail-header-number old-header)))
       (setq gnus-newsgroup-sparse
@@ -4425,6 +4391,7 @@ taken into consideration."
   (cond
    (n
     ;; A numerical prefix has been given.
   (cond
    (n
     ;; A numerical prefix has been given.
+    (setq n (prefix-numeric-value n))
     (let ((backward (< n 0))
          (n (abs (prefix-numeric-value n)))
          articles article)
     (let ((backward (< n 0))
          (n (abs (prefix-numeric-value n)))
          articles article)
@@ -4438,9 +4405,7 @@ taken into consideration."
                   (gnus-summary-find-next nil article)))
          (decf n)))
       (nreverse articles)))
                   (gnus-summary-find-next nil article)))
          (decf n)))
       (nreverse articles)))
-   ((and (boundp 'transient-mark-mode)
-        transient-mark-mode
-        mark-active)
+   ((gnus-region-active-p)
     ;; Work on the region between point and mark.
     (let ((max (max (point) (mark)))
          articles article)
     ;; Work on the region between point and mark.
     (let ((max (max (point) (mark)))
          articles article)
@@ -4615,7 +4580,7 @@ displayed, no centering will be performed."
        ;; possible valid number, or the second line from the top,
        ;; whichever is the least.
        (set-window-start
        ;; possible valid number, or the second line from the top,
        ;; whichever is the least.
        (set-window-start
-        window (min bottom (save-excursion 
+        window (min bottom (save-excursion
                              (forward-line (- top)) (point)))))
       ;; Do horizontal recentering while we're at it.
       (when (and (get-buffer-window (current-buffer) t)
                              (forward-line (- top)) (point)))))
       ;; Do horizontal recentering while we're at it.
       (when (and (get-buffer-window (current-buffer) t)
@@ -4713,7 +4678,8 @@ displayed, no centering will be performed."
       (save-excursion
        (while articles
          (gnus-summary-goto-subject (setq article (pop articles)))
       (save-excursion
        (while articles
          (gnus-summary-goto-subject (setq article (pop articles)))
-         (command-execute func)
+         (let (gnus-newsgroup-processable)
+           (command-execute func))
          (gnus-summary-remove-process-mark article)))))
   (gnus-summary-position-point))
 
          (gnus-summary-remove-process-mark article)))))
   (gnus-summary-position-point))
 
@@ -4737,9 +4703,8 @@ The prefix argument ALL means to select all articles."
        (group gnus-newsgroup-name))
     (setq gnus-newsgroup-begin nil)
     (gnus-summary-exit)
        (group gnus-newsgroup-name))
     (setq gnus-newsgroup-begin nil)
     (gnus-summary-exit)
-    ;; We have to adjust the point of group mode buffer because the
-    ;; current point was moved to the next unread newsgroup by
-    ;; exiting.
+    ;; We have to adjust the point of group mode buffer because
+    ;; point was moved to the next unread newsgroup by exiting.
     (gnus-summary-jump-to-group group)
     (when rescan
       (save-excursion
     (gnus-summary-jump-to-group group)
     (when rescan
       (save-excursion
@@ -4752,42 +4717,53 @@ The prefix argument ALL means to select all articles."
   (interactive "P")
   (gnus-summary-reselect-current-group all t))
 
   (interactive "P")
   (gnus-summary-reselect-current-group all t))
 
-(defun gnus-summary-update-info ()
-  (let ((group gnus-newsgroup-name))
-    (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 '<)))
-            t)))
-    (unless (listp (cdr gnus-newsgroup-killed))
-      (setq gnus-newsgroup-killed (list gnus-newsgroup-killed)))
-    (let ((headers gnus-newsgroup-headers))
-      (run-hooks 'gnus-exit-group-hook)
-      (unless gnus-save-score
-       (setq gnus-newsgroup-scored nil))
-      ;; Set the new ranges of read articles.
-      (gnus-update-read-articles
-       group (append gnus-newsgroup-unreads gnus-newsgroup-unselected))
-      ;; Set the current article marks.
-      (gnus-update-marks)
-      ;; Do the cross-ref thing.
-      (when gnus-use-cross-reference
-       (gnus-mark-xrefs-as-read group headers gnus-newsgroup-unreads))
-      ;; Do adaptive scoring, and possibly save score files.
-      (when gnus-newsgroup-adaptive
-       (gnus-score-adaptive))
-      (when gnus-use-scoring
-       (gnus-score-save))
-      ;; Do not switch windows but change the buffer to work.
-      (set-buffer gnus-group-buffer)
-      (unless (gnus-ephemeral-group-p gnus-newsgroup-name)
-       (gnus-group-update-group group)))))
+(defun gnus-summary-update-info (&optional non-destructive)
+  (save-excursion
+    (let ((group gnus-newsgroup-name))
+      (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 '<)))
+              t)))
+      (unless (listp (cdr gnus-newsgroup-killed))
+       (setq gnus-newsgroup-killed (list gnus-newsgroup-killed)))
+      (let ((headers gnus-newsgroup-headers))
+       (when (and (not gnus-save-score)
+                  (not non-destructive))
+         (setq gnus-newsgroup-scored nil))
+       ;; Set the new ranges of read articles.
+       (gnus-update-read-articles
+        group (append gnus-newsgroup-unreads gnus-newsgroup-unselected))
+       ;; Set the current article marks.
+       (gnus-update-marks)
+       ;; Do the cross-ref thing.
+       (when gnus-use-cross-reference
+         (gnus-mark-xrefs-as-read group headers gnus-newsgroup-unreads))
+       ;; Do adaptive scoring, and possibly save score files.
+       (when gnus-newsgroup-adaptive
+         (gnus-score-adaptive))
+       (when gnus-use-scoring
+         (gnus-score-save))
+       ;; Do not switch windows but change the buffer to work.
+       (set-buffer gnus-group-buffer)
+       (unless (gnus-ephemeral-group-p gnus-newsgroup-name)
+         (gnus-group-update-group group))))))
+
+(defun gnus-summary-save-newsrc (&optional force)
+  "Save the current number of read/marked articles in the dribble buffer.
+The dribble buffer will then be saved.
+If FORCE (the prefix), also save the .newsrc file(s)."
+  (interactive "P")
+  (gnus-summary-update-info t)
+  (if force
+      (gnus-save-newsrc-file)
+    (gnus-dribble-save)))
 
 (defun gnus-summary-exit (&optional temporary)
   "Exit reading current newsgroup, and then return to group selection mode.
 
 (defun gnus-summary-exit (&optional temporary)
   "Exit reading current newsgroup, and then return to group selection mode.
@@ -4814,6 +4790,7 @@ gnus-exit-group-hook is called with no arguments if that value is non-nil."
       (gnus-tree-close group))
     ;; Make all changes in this group permanent.
     (unless quit-config
       (gnus-tree-close group))
     ;; Make all changes in this group permanent.
     (unless quit-config
+      (run-hooks 'gnus-exit-group-hook)
       (gnus-summary-update-info))
     (gnus-close-group group)
     ;; Make sure where I was, and go to next newsgroup.
       (gnus-summary-update-info))
     (gnus-close-group group)
     ;; Make sure where I was, and go to next newsgroup.
@@ -4868,7 +4845,7 @@ gnus-exit-group-hook is called with no arguments if that value is non-nil."
         (quit-config (gnus-group-quit-config group)))
     (when (or no-questions
              gnus-expert-user
         (quit-config (gnus-group-quit-config group)))
     (when (or no-questions
              gnus-expert-user
-             (gnus-y-or-n-p "Do you really wanna quit reading this group? "))
+             (gnus-y-or-n-p "Discard changes to this group and exit? "))
       ;; If we have several article buffers, we kill them at exit.
       (unless gnus-single-article-buffer
        (gnus-kill-buffer gnus-article-buffer)
       ;; If we have several article buffers, we kill them at exit.
       (unless gnus-single-article-buffer
        (gnus-kill-buffer gnus-article-buffer)
@@ -4924,7 +4901,11 @@ which existed when entering the ephemeral is reset."
           (if (and (boundp 'gnus-pick-mode) (symbol-value 'gnus-pick-mode))
               (gnus-configure-windows 'pick 'force)
             (gnus-configure-windows (cdr quit-config) 'force)))
           (if (and (boundp 'gnus-pick-mode) (symbol-value 'gnus-pick-mode))
               (gnus-configure-windows 'pick 'force)
             (gnus-configure-windows (cdr quit-config) 'force)))
-      (gnus-configure-windows (cdr quit-config) 'force))))
+      (gnus-configure-windows (cdr quit-config) 'force))
+    (when (eq major-mode 'gnus-summary-mode)
+      (gnus-summary-next-subject 1 nil t)
+      (gnus-summary-recenter)
+      (gnus-summary-position-point))))
 
 ;;; Dead summaries.
 
 
 ;;; Dead summaries.
 
@@ -5048,6 +5029,8 @@ initially.  If NEXT-GROUP, go to this group.  If BACKWARD, go to
 previous group instead."
   (interactive "P")
   (gnus-set-global-variables)
 previous group instead."
   (interactive "P")
   (gnus-set-global-variables)
+  ;; Stop pre-fetching.
+  (gnus-async-halt-prefetch)
   (let ((current-group gnus-newsgroup-name)
        (current-buffer (current-buffer))
        entered)
   (let ((current-group gnus-newsgroup-name)
        (current-buffer (current-buffer))
        entered)
@@ -5274,11 +5257,6 @@ If BACKWARD, the previous article is selected instead of the next."
    ;; If not, we try the first unread, if that is wanted.
    ((and subject
         gnus-auto-select-same
    ;; If not, we try the first unread, if that is wanted.
    ((and subject
         gnus-auto-select-same
-        ;; Make sure that we don't select the current article.
-        (not (eq (gnus-summary-article-number)
-                 (save-excursion
-                   (gnus-summary-first-subject t)
-                   (gnus-summary-article-number))))
         (gnus-summary-first-unread-article))
     (gnus-summary-position-point)
     (gnus-message 6 "Wrapped"))
         (gnus-summary-first-unread-article))
     (gnus-summary-position-point)
     (gnus-message 6 "Wrapped"))
@@ -5293,6 +5271,10 @@ If BACKWARD, the previous article is selected instead of the next."
     (unless (gnus-ephemeral-group-p gnus-newsgroup-name)
       (gnus-summary-jump-to-group gnus-newsgroup-name))
     (let ((cmd last-command-char)
     (unless (gnus-ephemeral-group-p gnus-newsgroup-name)
       (gnus-summary-jump-to-group gnus-newsgroup-name))
     (let ((cmd last-command-char)
+         (point
+          (save-excursion
+            (set-buffer gnus-group-buffer)
+            (point)))
          (group
           (if (eq gnus-keep-same-level 'best)
               (gnus-summary-best-group gnus-newsgroup-name)
          (group
           (if (eq gnus-keep-same-level 'best)
               (gnus-summary-best-group gnus-newsgroup-name)
@@ -5319,17 +5301,18 @@ If BACKWARD, the previous article is selected instead of the next."
                          "exiting"))
          (gnus-summary-next-group nil group backward)))
        (t
                          "exiting"))
          (gnus-summary-next-group nil group backward)))
        (t
-       (gnus-summary-walk-group-buffer
-        gnus-newsgroup-name cmd unread backward)))))))
+       (when (gnus-key-press-event-p last-input-event)
+         (gnus-summary-walk-group-buffer
+          gnus-newsgroup-name cmd unread backward point))))))))
 
 
-(defun gnus-summary-walk-group-buffer (from-group cmd unread backward)
+(defun gnus-summary-walk-group-buffer (from-group cmd unread backward start)
   (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)
     (save-excursion
       (set-buffer gnus-group-buffer)
   (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)
     (save-excursion
       (set-buffer gnus-group-buffer)
-      (gnus-summary-jump-to-group from-group)
+      (goto-char start)
       (setq group
            (if (eq gnus-keep-same-level 'best)
                (gnus-summary-best-group gnus-newsgroup-name)
       (setq group
  &nb