diff lisp/gnus/gnus-sum.el @ 85712:a3c27999decb

Update Gnus to No Gnus 0.7 from the Gnus CVS trunk Revision: emacs@sv.gnu.org/emacs--devo--0--patch-911
author Miles Bader <miles@gnu.org>
date Sun, 28 Oct 2007 09:18:39 +0000
parents f6c37512dd9e
children d3e87ee5aa0e
line wrap: on
line diff
--- a/lisp/gnus/gnus-sum.el	Sun Oct 28 04:58:17 2007 +0000
+++ b/lisp/gnus/gnus-sum.el	Sun Oct 28 09:18:39 2007 +0000
@@ -62,19 +62,31 @@
   :group 'gnus-summary-exit
   :type 'boolean)
 
+(defcustom gnus-summary-next-group-on-exit t
+  "If non-nil, go to the next unread newsgroup on summary exit.
+See `gnus-group-goto-unread'."
+  :link '(custom-manual "(gnus)Group Maneuvering")
+  :group 'gnus-summary-exit
+  :version "23.0" ;; No Gnus
+  :type 'boolean)
+
 (defcustom gnus-fetch-old-headers nil
   "*Non-nil means that Gnus will try to build threads by grabbing old headers.
-If an unread article in the group refers to an older, already read (or
-just marked as read) article, the old article will not normally be
-displayed in the Summary buffer.  If this variable is t, Gnus
-will attempt to grab the headers to the old articles, and thereby
-build complete threads.  If it has the value `some', only enough
-headers to connect otherwise loose threads will be displayed.  This
-variable can also be a number.  In that case, no more than that number
-of old headers will be fetched.  If it has the value `invisible', all
+If an unread article in the group refers to an older, already
+read (or just marked as read) article, the old article will not
+normally be displayed in the Summary buffer.  If this variable is
+t, Gnus will attempt to grab the headers to the old articles, and
+thereby build complete threads.  If it has the value `some', all
+old headers will be fetched but only enough headers to connect
+otherwise loose threads will be displayed.  This variable can
+also be a number.  In that case, no more than that number of old
+headers will be fetched.  If it has the value `invisible', all
 old headers will be fetched, but none will be displayed.
 
-The server has to support NOV for any of this to work."
+The server has to support NOV for any of this to work.
+
+This feature can seriously impact performance it ignores all
+locally cached header entries."
   :group 'gnus-thread
   :type '(choice (const :tag "off" nil)
 		 (const :tag "on" t)
@@ -83,7 +95,7 @@
 		 number
 		 (sexp :menu-tag "other" t)))
 
-(defcustom gnus-refer-thread-limit 200
+(defcustom gnus-refer-thread-limit 500
   "*The number of old headers to fetch when doing \\<gnus-summary-mode-map>\\[gnus-summary-refer-thread].
 If t, fetch all the available old headers."
   :group 'gnus-thread
@@ -366,6 +378,28 @@
   :group 'gnus-summary-maneuvering
   :type 'boolean)
 
+(defcustom gnus-auto-select-on-ephemeral-exit 'next-noselect
+  "What article should be selected after exiting an ephemeral group.
+Valid values include:
+
+`next'
+  Select the next article.
+`next-unread'
+  Select the next unread article.
+`next-noselect'
+  Move the cursor to the next article.  This is the default.
+`next-unread-noselect'
+  Move the cursor to the next unread article.
+
+If it has any other value or there is no next (unread) article, the
+article selected before entering to the ephemeral group will appear."
+  :version "23.0" ;; No Gnus
+  :group 'gnus-summary-maneuvering
+  :type '(choice :format "%{%t%}:\n %[Value Menu%] %v"
+		 (const next) (const next-unread)
+		 (const next-noselect) (const next-unread-noselect)
+		 (sexp :tag "other" :value nil)))
+
 (defcustom gnus-auto-goto-ignores 'unfetched
   "*Says how to handle unfetched articles when maneuvering.
 
@@ -391,7 +425,7 @@
   :group 'gnus-summary-maneuvering
   :type 'boolean)
 
-(defcustom gnus-auto-center-summary t
+(defcustom gnus-auto-center-summary 2
   "*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."
@@ -438,6 +472,13 @@
 			 (cons :value ("" "") regexp (repeat string))
 			 (sexp :value nil))))
 
+(defcustom gnus-move-group-prefix-function 'gnus-group-real-prefix
+  "Function used to compute default prefix for article move/copy/etc prompts.
+The function should take one argument, a group name, and return a
+string with the suggested prefix."
+  :group 'gnus-summary-mail
+  :type 'function)
+
 ;; FIXME: Although the custom type is `character' for the following variables,
 ;; using multibyte characters (Latin-1, UTF-8) doesn't work.  -- rs
 
@@ -697,6 +738,40 @@
   :group 'gnus-score-default
   :type 'integer)
 
+(defun gnus-widget-reversible-match (widget value)
+  "Ignoring WIDGET, convert VALUE to internal form.
+VALUE should have the form `FOO' or `(not FOO)', where FOO is an symbol."
+  ;; (debug value)
+  (or (symbolp value)
+      (and (listp value)
+           (eq (length value) 2)
+           (eq (nth 0 value) 'not)
+           (symbolp (nth 1 value)))))
+
+(defun gnus-widget-reversible-to-internal (widget value)
+  "Ignoring WIDGET, convert VALUE to internal form.
+VALUE should have the form `FOO' or `(not FOO)', where FOO is an atom.
+FOO is converted to (FOO nil) and (not FOO) is converted to (FOO t)."
+  ;; (debug value)
+  (if (atom value)
+      (list value nil)
+    (list (nth 1 value) t)))
+
+(defun gnus-widget-reversible-to-external (widget value)
+  "Ignoring WIDGET, convert VALUE to external form.
+VALUE should have the form `(FOO nil)' or `(FOO t)', where FOO is an atom.
+\(FOO  nil) is converted to FOO and (FOO t) is converted to (not FOO)."
+  ;; (debug value)
+  (if (nth 1 value)
+      (list 'not (nth 0 value))
+    (nth 0 value)))
+
+(define-widget 'gnus-widget-reversible 'group
+  "A `group' that convert values."
+  :match 'gnus-widget-reversible-match
+  :value-to-internal 'gnus-widget-reversible-to-internal
+  :value-to-external 'gnus-widget-reversible-to-external)
+
 (defcustom gnus-article-sort-functions '(gnus-article-sort-by-number)
   "*List of functions used for sorting articles in the summary buffer.
 
@@ -709,6 +784,9 @@
 very similar.  (Sorting by date means sorting by the time the message
 was sent, sorting by number means sorting by arrival time.)
 
+Each item can also be a list `(not F)' where F is a function;
+this reverses the sort order.
+
 Ready-made functions include `gnus-article-sort-by-number',
 `gnus-article-sort-by-author', `gnus-article-sort-by-subject',
 `gnus-article-sort-by-date', `gnus-article-sort-by-random'
@@ -717,13 +795,16 @@
 When threading is turned on, the variable `gnus-thread-sort-functions'
 controls how articles are sorted."
   :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)
-			 (function-item gnus-article-sort-by-date)
-			 (function-item gnus-article-sort-by-score)
-			 (function-item gnus-article-sort-by-random)
-			 (function :tag "other"))))
+  :type '(repeat (gnus-widget-reversible
+                  (choice (function-item gnus-article-sort-by-number)
+                          (function-item gnus-article-sort-by-author)
+                          (function-item gnus-article-sort-by-subject)
+                          (function-item gnus-article-sort-by-date)
+                          (function-item gnus-article-sort-by-score)
+                          (function-item gnus-article-sort-by-random)
+                          (function :tag "other"))
+                  (boolean :tag "Reverse order"))))
+
 
 (defcustom gnus-thread-sort-functions '(gnus-thread-sort-by-number)
   "*List of functions used for sorting threads in the summary buffer.
@@ -738,25 +819,34 @@
 very similar.  (Sorting by date means sorting by the time the message
 was sent, sorting by number means sorting by arrival time.)
 
+Each list item can also be a list `(not F)' where F is a
+function; this specifies reversed sort order.
+
 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',
-`gnus-thread-sort-by-most-recent-number',
-`gnus-thread-sort-by-most-recent-date',
-`gnus-thread-sort-by-random', and
-`gnus-thread-sort-by-total-score' (see `gnus-thread-score-function').
+`gnus-thread-sort-by-author', `gnus-thread-sort-by-recipient'
+`gnus-thread-sort-by-subject', `gnus-thread-sort-by-date',
+`gnus-thread-sort-by-score', `gnus-thread-sort-by-most-recent-number',
+`gnus-thread-sort-by-most-recent-date', `gnus-thread-sort-by-random',
+and `gnus-thread-sort-by-total-score' (see
+`gnus-thread-score-function').
 
 When threading is turned off, the variable
 `gnus-article-sort-functions' controls how articles are sorted."
   :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)
-			 (function-item gnus-thread-sort-by-date)
-			 (function-item gnus-thread-sort-by-score)
-			 (function-item gnus-thread-sort-by-total-score)
-			 (function-item gnus-thread-sort-by-random)
-			 (function :tag "other"))))
+  :type '(repeat
+          (gnus-widget-reversible
+           (choice (function-item gnus-thread-sort-by-number)
+                   (function-item gnus-thread-sort-by-author)
+                   (function-item gnus-thread-sort-by-recipient)
+                   (function-item gnus-thread-sort-by-subject)
+                   (function-item gnus-thread-sort-by-date)
+                   (function-item gnus-thread-sort-by-score)
+                   (function-item gnus-thread-sort-by-most-recent-number)
+                   (function-item gnus-thread-sort-by-most-recent-date)
+                   (function-item gnus-thread-sort-by-random)
+                   (function-item gnus-thread-sort-by-total-score)
+                   (function :tag "other"))
+           (boolean :tag "Reverse order"))))
 
 (defcustom gnus-thread-score-function '+
   "*Function used for calculating the total score of a thread.
@@ -1016,10 +1106,29 @@
   (and user-mail-address
        (not (string= user-mail-address ""))
        (regexp-quote user-mail-address))
-  "*Regexp of From headers that may be suppressed in favor of To headers."
+  "*From headers that may be suppressed in favor of To headers.
+This can be a regexp or a list of regexps."
   :version "21.1"
   :group 'gnus-summary
-  :type 'regexp)
+  :type '(choice regexp
+		 (repeat :tag "Regexp List" regexp)))
+
+(defsubst gnus-ignored-from-addresses ()
+  (gmm-regexp-concat gnus-ignored-from-addresses))
+
+(defcustom gnus-summary-to-prefix "-> "
+  "*String prefixed to the To field in the summary line when
+using `gnus-ignored-from-addresses'."
+  :version "22.1"
+  :group 'gnus-summary
+  :type 'string)
+
+(defcustom gnus-summary-newsgroup-prefix "=> "
+  "*String prefixed to the Newsgroup field in the summary
+line when using `gnus-ignored-from-addresses'."
+  :version "22.1"
+  :group 'gnus-summary
+  :type 'string)
 
 (defcustom gnus-newsgroup-ignored-charsets '(unknown-8bit x-unknown)
   "List of charsets that should be ignored.
@@ -1127,12 +1236,12 @@
   :group 'gnus-summary
   :type 'string)
 
-(defcustom gnus-article-loose-mime nil
+(defcustom gnus-article-loose-mime t
   "If non-nil, don't require MIME-Version header.
 Some brain-damaged MUA/MTA, e.g. Lotus Domino 5.0.6 clients, does not
 supply the MIME-Version header or deliberately strip it from the mail.
-Set it to non-nil, Gnus will treat some articles as MIME even if
-the MIME-Version header is missed."
+If non-nil (the default), Gnus will treat some articles as MIME
+even if the MIME-Version header is missing."
   :version "22.1"
   :type 'boolean
   :group 'gnus-article-mime)
@@ -1214,7 +1323,6 @@
     (?\< (make-string (max 0 (- 20 gnus-tmp-level)) ? ) ?s)
     (?i gnus-tmp-score ?d)
     (?z gnus-tmp-score-char ?c)
-    (?l (bbb-grouplens-score gnus-tmp-header) ?s)
     (?V (gnus-thread-total-score (and (boundp 'thread) (car thread))) ?d)
     (?U gnus-tmp-unread ?c)
     (?f (gnus-summary-from-or-to-or-newsgroups gnus-tmp-header gnus-tmp-from)
@@ -1463,7 +1571,6 @@
         nil
       (load "gnus-sum.el" t t t))
     (require 'gnus)
-    (require 'gnus-agent)
     (require 'gnus-art)))
 
 ;; MIME stuff.
@@ -1490,19 +1597,15 @@
 	       (eq gnus-newsgroup-name
 		   (car gnus-decode-encoded-word-methods-cache)))
     (setq gnus-decode-encoded-word-methods-cache (list gnus-newsgroup-name))
-    (mapcar (lambda (x)
-	      (if (symbolp x)
-		  (nconc gnus-decode-encoded-word-methods-cache (list x))
-		(if (and gnus-newsgroup-name
-			 (string-match (car x) gnus-newsgroup-name))
-		    (nconc gnus-decode-encoded-word-methods-cache
-			   (list (cdr x))))))
-	    gnus-decode-encoded-word-methods))
-  (let ((xlist gnus-decode-encoded-word-methods-cache))
-    (pop xlist)
-    (while xlist
-      (setq string (funcall (pop xlist) string))))
-  string)
+    (dolist (method gnus-decode-encoded-word-methods)
+      (if (symbolp method)
+	  (nconc gnus-decode-encoded-word-methods-cache (list method))
+	(if (and gnus-newsgroup-name
+		 (string-match (car method) gnus-newsgroup-name))
+	    (nconc gnus-decode-encoded-word-methods-cache
+		   (list (cdr method)))))))
+  (dolist (method (cdr gnus-decode-encoded-word-methods-cache) string)
+    (setq string (funcall method string))))
 
 ;; Subject simplification.
 
@@ -1574,8 +1677,8 @@
       (setq modified-tick (buffer-modified-tick))
       (cond
        ((listp gnus-simplify-subject-fuzzy-regexp)
-	(mapcar 'gnus-simplify-buffer-fuzzy-step
-		gnus-simplify-subject-fuzzy-regexp))
+	(mapc '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 "^ *\\[[-+?*!][-+?*!]\\] *")
@@ -1612,8 +1715,8 @@
    ((eq gnus-summary-gather-subject-limit 'fuzzy)
     (gnus-simplify-subject-fuzzy subject))
    ((numberp gnus-summary-gather-subject-limit)
-    (gnus-limit-string (gnus-simplify-subject-re subject)
-		       gnus-summary-gather-subject-limit))
+    (truncate-string-to-width (gnus-simplify-subject-re subject)
+			      gnus-summary-gather-subject-limit))
    (t
     subject)))
 
@@ -1665,6 +1768,8 @@
   "," gnus-summary-best-unread-article
   "\M-s" gnus-summary-search-article-forward
   "\M-r" gnus-summary-search-article-backward
+  "\M-S" gnus-summary-repeat-search-article-forward
+  "\M-R" gnus-summary-repeat-search-article-backward
   "<" gnus-summary-beginning-of-article
   ">" gnus-summary-end-of-article
   "j" gnus-summary-goto-article
@@ -1704,6 +1809,7 @@
   "\C-c\C-s\C-l" gnus-summary-sort-by-lines
   "\C-c\C-s\C-c" gnus-summary-sort-by-chars
   "\C-c\C-s\C-a" gnus-summary-sort-by-author
+  "\C-c\C-s\C-t" gnus-summary-sort-by-recipient
   "\C-c\C-s\C-s" gnus-summary-sort-by-subject
   "\C-c\C-s\C-d" gnus-summary-sort-by-date
   "\C-c\C-s\C-i" gnus-summary-sort-by-score
@@ -1795,6 +1901,8 @@
 (gnus-define-keys (gnus-summary-limit-map "/" gnus-summary-mode-map)
   "/" gnus-summary-limit-to-subject
   "n" gnus-summary-limit-to-articles
+  "b" gnus-summary-limit-to-bodies
+  "h" gnus-summary-limit-to-headers
   "w" gnus-summary-pop-limit
   "s" gnus-summary-limit-to-subject
   "a" gnus-summary-limit-to-author
@@ -1814,7 +1922,11 @@
   "c" gnus-summary-limit-exclude-childless-dormant
   "C" gnus-summary-limit-mark-excluded-as-read
   "o" gnus-summary-insert-old-articles
-  "N" gnus-summary-insert-new-articles)
+  "N" gnus-summary-insert-new-articles
+  "S" gnus-summary-limit-to-singletons
+  "r" gnus-summary-limit-to-replied
+  "R" gnus-summary-limit-to-recipient
+  "A" gnus-summary-limit-to-address)
 
 (gnus-define-keys (gnus-summary-goto-map "G" gnus-summary-mode-map)
   "n" gnus-summary-next-unread-article
@@ -1834,11 +1946,13 @@
 
 (gnus-define-keys (gnus-summary-thread-map "T" gnus-summary-mode-map)
   "k" gnus-summary-kill-thread
+  "E" gnus-summary-expire-thread
   "l" gnus-summary-lower-thread
   "i" gnus-summary-raise-thread
   "T" gnus-summary-toggle-threads
   "t" gnus-summary-rethread-current
   "^" gnus-summary-reparent-thread
+  "\M-^" gnus-summary-reparent-children
   "s" gnus-summary-show-thread
   "S" gnus-summary-show-all-threads
   "h" gnus-summary-hide-thread
@@ -1854,7 +1968,8 @@
 (gnus-define-keys (gnus-summary-buffer-map "Y" gnus-summary-mode-map)
   "g" gnus-summary-prepare
   "c" gnus-summary-insert-cached-articles
-  "d" gnus-summary-insert-dormant-articles)
+  "d" gnus-summary-insert-dormant-articles
+  "t" gnus-summary-insert-ticked-articles)
 
 (gnus-define-keys (gnus-summary-exit-map "Z" gnus-summary-mode-map)
   "c" gnus-summary-catchup-and-exit
@@ -1863,6 +1978,7 @@
   "Q" gnus-summary-exit
   "Z" gnus-summary-exit
   "n" gnus-summary-catchup-and-goto-next-group
+  "p" gnus-summary-catchup-and-goto-prev-group
   "R" gnus-summary-reselect-current-group
   "G" gnus-summary-rescan-group
   "N" gnus-summary-next-group
@@ -1889,6 +2005,7 @@
   "g" gnus-summary-show-article
   "s" gnus-summary-isearch-article
   "P" gnus-summary-print-article
+  "S" gnus-sticky-article
   "M" gnus-mailing-list-insinuate
   "t" gnus-article-babel)
 
@@ -1899,11 +2016,13 @@
   "e" gnus-article-emphasize
   "w" gnus-article-fill-cited-article
   "Q" gnus-article-fill-long-lines
+  "L" gnus-article-toggle-truncate-lines
   "C" gnus-article-capitalize-sentences
   "c" gnus-article-remove-cr
   "q" gnus-article-de-quoted-unreadable
   "6" gnus-article-de-base64-unreadable
   "Z" gnus-article-decode-HZ
+  "A" gnus-article-treat-ansi-sequences
   "h" gnus-article-wash-html
   "u" gnus-article-unsplit-urls
   "s" gnus-summary-force-verify-and-decrypt
@@ -1916,7 +2035,8 @@
   "v" gnus-summary-verbose-headers
   "a" gnus-article-strip-headers-in-body ;; mnemonic: wash archive
   "p" gnus-article-verify-x-pgp-sig
-  "d" gnus-article-treat-dumbquotes)
+  "d" gnus-article-treat-dumbquotes
+  "i" gnus-summary-idna-message)
 
 (gnus-define-keys (gnus-summary-wash-deuglify-map "Y" gnus-summary-wash-map)
   ;; mnemonic: deuglif*Y*
@@ -2028,9 +2148,15 @@
   "m" gnus-summary-repair-multipart
   "v" gnus-article-view-part
   "o" gnus-article-save-part
+  "O" gnus-article-save-part-and-strip
+  "r" gnus-article-replace-part
+  "d" gnus-article-delete-part
+  "t" gnus-article-view-part-as-type
+  "j" gnus-article-jump-to-part
   "c" gnus-article-copy-part
   "C" gnus-article-view-part-as-charset
   "e" gnus-article-view-part-externally
+  "H" gnus-article-browse-html-article
   "E" gnus-article-encrypt-body
   "i" gnus-article-inline-part
   "|" gnus-article-pipe-part)
@@ -2174,11 +2300,13 @@
 	       ["Repair multipart" gnus-summary-repair-multipart t]
 	       ["Pipe part..." gnus-article-pipe-part t]
 	       ["Inline part" gnus-article-inline-part t]
+	       ["View part as type..." gnus-article-view-part-as-type t]
 	       ["Encrypt body" gnus-article-encrypt-body
 		:active (not (gnus-group-read-only-p))
 	       ,@(if (featurep 'xemacs) nil
 		   '(:help "Encrypt the message body on disk"))]
 	       ["View part externally" gnus-article-view-part-externally t]
+	       ["View HTML parts in browser" gnus-article-browse-html-article t]
 	       ["View part with charset..." gnus-article-view-part-as-charset t]
 	       ["Copy part" gnus-article-copy-part t]
 	       ["Save part..." gnus-article-save-part t]
@@ -2233,6 +2361,7 @@
 	      ["Emphasis" gnus-article-emphasize t]
 	      ["Word wrap" gnus-article-fill-cited-article t]
 	      ["Fill long lines" gnus-article-fill-long-lines t]
+	      ["Toggle truncate long lines" gnus-article-toggle-truncate-lines t]
 	      ["Capitalize sentences" gnus-article-capitalize-sentences t]
 	      ["Remove CR" gnus-article-remove-cr t]
 	      ["Quoted-Printable" gnus-article-de-quoted-unreadable t]
@@ -2240,6 +2369,7 @@
 	      ["Rot 13" gnus-summary-caesar-message
 	       ,@(if (featurep 'xemacs) '(t)
 		   '(:help "\"Caesar rotate\" article by 13"))]
+	      ["De-IDNA" gnus-summary-idna-message t]
 	      ["Morse decode" gnus-summary-morse-message t]
 	      ["Unix pipe..." gnus-summary-pipe-message t]
 	      ["Add buttons" gnus-article-add-buttons t]
@@ -2253,6 +2383,7 @@
 	      ["Unsplit URLs" gnus-article-unsplit-urls t]
 	      ["Verify X-PGP-Sig" gnus-article-verify-x-pgp-sig t]
 	      ["Decode HZ" gnus-article-decode-HZ t]
+	      ["ANSI sequences" gnus-article-treat-ansi-sequences t]
 	      ("(Outlook) Deuglify"
 	       ["Unwrap lines" gnus-article-outlook-unwrap-lines t]
 	       ["Repair attribution" gnus-article-outlook-repair-attribution t]
@@ -2322,6 +2453,7 @@
 	      ["Remove article" gnus-cache-remove-article t])
 	     ["Translate" gnus-article-babel t]
 	     ["Select article buffer" gnus-summary-select-article-buffer t]
+	     ["Make article buffer sticky" gnus-sticky-article t]
 	     ["Enter digest buffer" gnus-summary-enter-digest-group t]
 	     ["Isearch article..." gnus-summary-isearch-article t]
 	     ["Beginning of the article" gnus-summary-beginning-of-article t]
@@ -2362,6 +2494,7 @@
 	["Go up thread" gnus-summary-up-thread t]
 	["Top of thread" gnus-summary-top-thread t]
 	["Mark thread as read" gnus-summary-kill-thread t]
+	["Mark thread as expired" gnus-summary-expire-thread t]
 	["Lower thread score" gnus-summary-lower-thread t]
 	["Raise thread score" gnus-summary-raise-thread t]
 	["Rethread current" gnus-summary-rethread-current t]))
@@ -2450,12 +2583,16 @@
 	 ["Marks..." gnus-summary-limit-to-marks t]
 	 ["Subject..." gnus-summary-limit-to-subject t]
 	 ["Author..." gnus-summary-limit-to-author t]
+	 ["Recipient..." gnus-summary-limit-to-recipient t]
+	 ["Address..." gnus-summary-limit-to-address t]
 	 ["Age..." gnus-summary-limit-to-age t]
 	 ["Extra..." gnus-summary-limit-to-extra t]
 	 ["Score..." gnus-summary-limit-to-score t]
 	 ["Display Predicate" gnus-summary-limit-to-display-predicate t]
 	 ["Unread" gnus-summary-limit-to-unread t]
 	 ["Unseen" gnus-summary-limit-to-unseen t]
+	 ["Singletons" gnus-summary-limit-to-singletons t]
+	 ["Replied" gnus-summary-limit-to-replied t]
 	 ["Non-dormant" gnus-summary-limit-exclude-dormant t]
 	 ["Next or process marked articles" gnus-summary-limit-to-articles t]
 	 ["Pop limit" gnus-summary-pop-limit t]
@@ -2469,6 +2606,7 @@
 	 ["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]
+	 ["Invert marks" gnus-uu-invert-processable t]
 	 ["Mark above" gnus-uu-mark-over t]
 	 ["Mark series" gnus-uu-mark-series t]
 	 ["Mark region" gnus-uu-mark-region (gnus-mark-active-p)]
@@ -2512,6 +2650,7 @@
 	("Sort"
 	 ["Sort by number" gnus-summary-sort-by-number t]
 	 ["Sort by author" gnus-summary-sort-by-author t]
+	 ["Sort by recipient" gnus-summary-sort-by-recipient 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]
@@ -2536,6 +2675,7 @@
 	 ["Regenerate" gnus-summary-prepare t]
 	 ["Insert cached articles" gnus-summary-insert-cached-articles t]
 	 ["Insert dormant articles" gnus-summary-insert-dormant-articles t]
+	 ["Insert ticked articles" gnus-summary-insert-ticked-articles t]
 	 ["Toggle threading" gnus-summary-toggle-threads t])
 	["See old articles" gnus-summary-insert-old-articles t]
 	["See new articles" gnus-summary-insert-new-articles t]
@@ -2559,6 +2699,7 @@
 	      '(:help "Mark unread articles in this group as read, then exit"))]
 	 ["Catchup all and exit" gnus-summary-catchup-all-and-exit t]
 	 ["Catchup and goto next" gnus-summary-catchup-and-goto-next-group t]
+	 ["Catchup and goto prev" gnus-summary-catchup-and-goto-prev-group t]
 	 ["Exit group" gnus-summary-exit
 	  ,@(if (featurep 'xemacs) '(t)
 	      '(:help "Exit current group, return to group selection mode"))]
@@ -2602,7 +2743,7 @@
 		 (const :tag "Retro look"  gnus-summary-tool-bar-retro)
 		 (repeat :tag "User defined list" gmm-tool-bar-item)
 		 (symbol))
-  :version "22.1" ;; Gnus 5.10.9
+  :version "23.0" ;; No Gnus
   :initialize 'custom-initialize-default
   :set 'gnus-summary-tool-bar-update
   :group 'gnus-summary)
@@ -2653,7 +2794,7 @@
 
 See `gmm-tool-bar-from-list' for the format of the list."
   :type '(repeat gmm-tool-bar-item)
-  :version "22.1" ;; Gnus 5.10.9
+  :version "23.0" ;; No Gnus
   :initialize 'custom-initialize-default
   :set 'gnus-summary-tool-bar-update
   :group 'gnus-summary)
@@ -2688,7 +2829,7 @@
 
 See `gmm-tool-bar-from-list' for the format of the list."
   :type '(repeat gmm-tool-bar-item)
-  :version "22.1" ;; Gnus 5.10.9
+  :version "23.0" ;; No Gnus
   :initialize 'custom-initialize-default
   :set 'gnus-summary-tool-bar-update
   :group 'gnus-summary)
@@ -2699,7 +2840,7 @@
 
 See `gmm-tool-bar-from-list' for the format of the list."
   :type 'gmm-tool-bar-zap-list
-  :version "22.1" ;; Gnus 5.10.9
+  :version "23.0" ;; No Gnus
   :initialize 'custom-initialize-default
   :set 'gnus-summary-tool-bar-update
   :group 'gnus-summary)
@@ -2838,12 +2979,13 @@
 \\{gnus-summary-mode-map}"
   (interactive)
   (kill-all-local-variables)
+  (let ((gnus-summary-local-variables gnus-newsgroup-variables))
+    (gnus-summary-make-local-variables))
+  (gnus-summary-make-local-variables)
+  (setq gnus-newsgroup-name group)
   (when (gnus-visual-p 'summary-menu 'menu)
     (gnus-summary-make-menu-bar)
     (gnus-summary-make-tool-bar))
-  (gnus-summary-make-local-variables)
-  (let ((gnus-summary-local-variables gnus-newsgroup-variables))
-    (gnus-summary-make-local-variables))
   (gnus-make-thread-indent-array)
   (gnus-simplify-mode-line)
   (setq major-mode 'gnus-summary-mode)
@@ -2851,13 +2993,13 @@
   (make-local-variable 'minor-mode-alist)
   (use-local-map gnus-summary-mode-map)
   (buffer-disable-undo)
-  (setq buffer-read-only t)		;Disable modification
+  (setq buffer-read-only t		;Disable modification
+	show-trailing-whitespace nil)
   (setq truncate-lines t)
   (setq selective-display t)
   (setq selective-display-ellipses t)	;Display `...'
   (gnus-summary-set-display-table)
   (gnus-set-default-directory)
-  (setq gnus-newsgroup-name group)
   (make-local-variable 'gnus-summary-line-format)
   (make-local-variable 'gnus-summary-line-format-spec)
   (make-local-variable 'gnus-summary-dummy-line-format)
@@ -2890,9 +3032,9 @@
   (let ((locals gnus-summary-local-variables))
     (while locals
       (if (consp (car locals))
-	  (and (vectorp (caar locals))
+	  (and (symbolp (caar locals))
 	       (set (caar locals) nil))
-	(and (vectorp (car locals))
+	(and (symbolp (car locals))
 	     (set (car locals) nil)))
       (setq locals (cdr locals)))))
 
@@ -2964,10 +3106,9 @@
 	    (setq gnus-newsgroup-data (nconc list gnus-newsgroup-data))
 	    (when offset
 	      (gnus-data-update-list odata offset)))
-      ;; Find the last element in the list to be spliced into the main
+	;; Find the last element in the list to be spliced into the main
 	;; list.
-	(while (cdr list)
-	  (setq list (cdr list)))
+	(setq list (last list))
 	(if (not data)
 	    (progn
 	      (setcdr list gnus-newsgroup-data)
@@ -3283,10 +3424,11 @@
       (gnus-summary-mode group)
       (when gnus-carpal
 	(gnus-carpal-setup-buffer 'summary))
-      (unless gnus-single-article-buffer
-	(make-local-variable 'gnus-article-buffer)
-	(make-local-variable 'gnus-article-current)
-	(make-local-variable 'gnus-original-article-buffer))
+      (when (gnus-group-quit-config group)
+	(set (make-local-variable 'gnus-single-article-buffer) nil))
+      (make-local-variable 'gnus-article-buffer)
+      (make-local-variable 'gnus-article-current)
+      (make-local-variable 'gnus-original-article-buffer)
       (setq gnus-newsgroup-name group)
       ;; Set any local variables in the group parameters.
       (gnus-summary-set-local-parameters gnus-newsgroup-name)
@@ -3319,8 +3461,7 @@
 	    (push (eval (car locals)) vlist))
 	  (setq locals (cdr locals)))
 	(setq vlist (nreverse vlist)))
-      (save-excursion
-	(set-buffer gnus-group-buffer)
+      (with-current-buffer gnus-group-buffer
 	(setq gnus-newsgroup-name name
 	      gnus-newsgroup-marked marked
 	      gnus-newsgroup-spam-marked spam
@@ -3444,25 +3585,33 @@
 
 (defun gnus-summary-from-or-to-or-newsgroups (header gnus-tmp-from)
   (let ((mail-parse-charset gnus-newsgroup-charset)
+	(ignored-from-addresses (gnus-ignored-from-addresses))
 	; Is it really necessary to do this next part for each summary line?
 	; Luckily, doesn't seem to slow things down much.
 	(mail-parse-ignored-charsets
-	 (save-excursion (set-buffer gnus-summary-buffer)
-			 gnus-newsgroup-ignored-charsets)))
+	 (with-current-buffer gnus-summary-buffer
+	   gnus-newsgroup-ignored-charsets)))
     (or
-     (and gnus-ignored-from-addresses
-	  (string-match gnus-ignored-from-addresses gnus-tmp-from)
+     (and ignored-from-addresses
+	  (string-match ignored-from-addresses gnus-tmp-from)
 	  (let ((extra-headers (mail-header-extra header))
 		to
 		newsgroups)
 	    (cond
 	     ((setq to (cdr (assq 'To extra-headers)))
-	      (concat "-> "
+	      (concat gnus-summary-to-prefix
 		      (inline
 			(gnus-summary-extract-address-component
 			 (funcall gnus-decode-encoded-address-function to)))))
-	     ((setq newsgroups (cdr (assq 'Newsgroups extra-headers)))
-	      (concat "=> " newsgroups)))))
+	     ((setq newsgroups
+		    (or
+		     (cdr (assq 'Newsgroups extra-headers))
+		     (and
+		      (memq 'Newsgroups gnus-extra-headers)
+                      (eq (car (gnus-find-method-for-group
+                                gnus-newsgroup-name)) 'nntp)
+		      (gnus-group-real-name gnus-newsgroup-name))))
+	      (concat gnus-summary-newsgroup-prefix newsgroups)))))
      (inline (gnus-summary-extract-address-component gnus-tmp-from)))))
 
 (defun gnus-summary-insert-line (gnus-tmp-header
@@ -3613,12 +3762,8 @@
 
 (defun gnus-summary-set-local-parameters (group)
   "Go through the local params of GROUP and set all variable specs in that list."
-  (let ((params (gnus-group-find-parameter group))
-	(vars '(quit-config))           ; Ignore quit-config.
-	elem)
-    (while params
-      (setq elem (car params)
-	    params (cdr params))
+  (let ((vars '(quit-config)))          ; Ignore quit-config.
+    (dolist (elem (gnus-group-find-parameter group))
       (and (consp elem)			; Has to be a cons.
 	   (consp (cdr elem))		; The cdr has to be a list.
 	   (symbolp (car elem))		; Has to be a symbol in there.
@@ -4140,21 +4285,19 @@
 	  (erase-buffer)))
       (kill-buffer (current-buffer)))
     ;; Sort over trustworthiness.
-    (mapcar
-     (lambda (relation)
-       (when (gnus-dependencies-add-header
-	      (make-full-mail-header
-	       gnus-reffed-article-number
-	       (nth 3 relation) "" (or (nth 4 relation) "")
-	       (nth 1 relation)
-	       (or (nth 2 relation) "") 0 0 "")
-	      gnus-newsgroup-dependencies nil)
-	 (push gnus-reffed-article-number gnus-newsgroup-limit)
-	 (push gnus-reffed-article-number gnus-newsgroup-sparse)
-	 (push (cons gnus-reffed-article-number gnus-sparse-mark)
-	       gnus-newsgroup-reads)
-	 (decf gnus-reffed-article-number)))
-     (sort relations 'car-less-than-car))
+    (dolist (relation (sort relations 'car-less-than-car))
+      (when (gnus-dependencies-add-header
+	     (make-full-mail-header
+	      gnus-reffed-article-number
+	      (nth 3 relation) "" (or (nth 4 relation) "")
+	      (nth 1 relation)
+	      (or (nth 2 relation) "") 0 0 "")
+	     gnus-newsgroup-dependencies nil)
+	(push gnus-reffed-article-number gnus-newsgroup-limit)
+	(push gnus-reffed-article-number gnus-newsgroup-sparse)
+	(push (cons gnus-reffed-article-number gnus-sparse-mark)
+	      gnus-newsgroup-reads)
+	(decf gnus-reffed-article-number)))
     (gnus-message 7 "Making sparse threads...done")))
 
 (defun gnus-build-old-threads ()
@@ -4182,13 +4325,12 @@
   "Translate STRING into something that doesn't contain weird characters."
   (mm-subst-char-in-string
    ?\r ?\-
-   (mm-subst-char-in-string
-    ?\n ?\- string)))
+   (mm-subst-char-in-string ?\n ?\- string t) t))
 
 ;; This function has to be called with point after the article number
 ;; on the beginning of the line.
 (defsubst gnus-nov-parse-line (number dependencies &optional force-new)
-  (let ((eol (gnus-point-at-eol))
+  (let ((eol (point-at-eol))
 	(buffer (current-buffer))
 	header references in-reply-to)
 
@@ -4213,7 +4355,7 @@
 			       (setq x (nnheader-nov-field))))
 		   (error x))
 		 (nnheader-nov-field)	; date
-		 (nnheader-nov-read-message-id)	; id
+		 (nnheader-nov-read-message-id number)	; id
 		 (setq references (nnheader-nov-field))	; refs
 		 (nnheader-nov-read-integer) ; chars
 		 (nnheader-nov-read-integer) ; lines
@@ -4287,8 +4429,7 @@
 	    (setq article (read (current-buffer))
 		  header (gnus-nov-parse-line article dependencies)))
 	  (when header
-	    (save-excursion
-	      (set-buffer gnus-summary-buffer)
+	    (with-current-buffer gnus-summary-buffer
 	      (push header gnus-newsgroup-headers)
 	      (if (memq (setq article (mail-header-number header))
 			gnus-newsgroup-unselected)
@@ -4385,7 +4526,7 @@
 	(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 old-pos (point-at-bol))
     (setq current (save-excursion
 		    (and (re-search-backward "[\r\n]" nil t)
 			 (gnus-summary-article-number))))
@@ -4567,9 +4708,9 @@
       (gnus-summary-show-thread)
       (gnus-data-remove
        number
-       (- (gnus-point-at-bol)
+       (- (point-at-bol)
 	  (prog1
-	      (1+ (gnus-point-at-eol))
+	      (1+ (point-at-eol))
 	    (gnus-delete-line)))))))
 
 (defun gnus-sort-threads-recursive (threads func)
@@ -4689,6 +4830,23 @@
   (gnus-article-sort-by-author
    (gnus-thread-header h1)  (gnus-thread-header h2)))
 
+(defsubst gnus-article-sort-by-recipient (h1 h2)
+  "Sort articles by recipient."
+  (gnus-string<
+   (let ((extract (funcall
+		   gnus-extract-address-components
+		   (or (cdr (assq 'To (mail-header-extra h1))) ""))))
+     (or (car extract) (cadr extract)))
+   (let ((extract (funcall
+		   gnus-extract-address-components
+		   (or (cdr (assq 'To (mail-header-extra h2))) ""))))
+     (or (car extract) (cadr extract)))))
+
+(defun gnus-thread-sort-by-recipient (h1 h2)
+  "Sort threads by root recipient."
+  (gnus-article-sort-by-recipient
+   (gnus-thread-header h1) (gnus-thread-header h2)))
+
 (defsubst gnus-article-sort-by-subject (h1 h2)
   "Sort articles by root subject."
   (gnus-string<
@@ -4809,33 +4967,39 @@
   :version "22.1"
   :type '(radio (const :format "%v  " nil) string)
   :group 'gnus-thread)
+
 (defcustom gnus-sum-thread-tree-false-root "> "
   "With %B spec, used for a false root of a thread.
 If nil, use subject instead."
   :version "22.1"
   :type '(radio (const :format "%v  " nil) string)
   :group 'gnus-thread)
+
 (defcustom gnus-sum-thread-tree-single-indent ""
   "With %B spec, used for a thread with just one message.
 If nil, use subject instead."
   :version "22.1"
   :type '(radio (const :format "%v  " nil) string)
   :group 'gnus-thread)
+
 (defcustom gnus-sum-thread-tree-vertical "| "
   "With %B spec, used for drawing a vertical line."
   :version "22.1"
   :type 'string
   :group 'gnus-thread)
+
 (defcustom gnus-sum-thread-tree-indent "  "
   "With %B spec, used for indenting."
   :version "22.1"
   :type 'string
   :group 'gnus-thread)
+
 (defcustom gnus-sum-thread-tree-leaf-with-other "+-> "
   "With %B spec, used for a leaf with brothers."
   :version "22.1"
   :type 'string
   :group 'gnus-thread)
+
 (defcustom gnus-sum-thread-tree-single-leaf "\\-> "
   "With %B spec, used for a leaf without brothers."
   :version "22.1"
@@ -5194,23 +5358,20 @@
 		  gnus-list-identifiers))
 	changed subject)
     (when regexp
+      (setq regexp (concat "^\\(?:R[Ee]: +\\)*\\(" regexp " *\\)"))
       (dolist (header gnus-newsgroup-headers)
 	(setq subject (mail-header-subject header)
 	      changed nil)
-	(while (string-match
-		(concat "^\\(R[Ee]: +\\)*\\(" regexp " *\\)")
-		subject)
+	(while (string-match regexp subject)
 	  (setq subject
-		(concat (substring subject 0 (match-beginning 2))
+		(concat (substring subject 0 (match-beginning 1))
 			(substring subject (match-end 0)))
 		changed t))
-	(when (and changed
-		   (string-match
-		    "^\\(\\(R[Ee]: +\\)+\\)R[Ee]: +" subject))
-	  (setq subject
-		(concat (substring subject 0 (match-beginning 1))
-			(substring subject (match-end 1)))))
 	(when changed
+	  (when (string-match "^\\(\\(?:R[Ee]: +\\)+\\)R[Ee]: +" subject)
+	    (setq subject
+		  (concat (substring subject 0 (match-beginning 1))
+			  (substring subject (match-end 1)))))
 	  (mail-header-set-subject header subject))))))
 
 (defun gnus-fetch-headers (articles)
@@ -5238,33 +5399,37 @@
   "Select newsgroup GROUP.
 If READ-ALL is non-nil, all articles in the group are selected.
 If SELECT-ARTICLES, only select those articles from GROUP."
-  (let* ((entry (gnus-gethash group gnus-newsrc-hashtb))
+  (let* ((entry (gnus-group-entry group))
 	 ;;!!! Dirty hack; should be removed.
 	 (gnus-summary-ignore-duplicates
 	  (if (eq (car (gnus-find-method-for-group group)) 'nnvirtual)
 	      t
 	    gnus-summary-ignore-duplicates))
 	 (info (nth 2 entry))
-	 articles fetched-articles cached)
+	 charset articles fetched-articles cached)
 
     (unless (gnus-check-server
 	     (set (make-local-variable 'gnus-current-select-method)
 		  (gnus-find-method-for-group group)))
       (error "Couldn't open server"))
+    (setq charset (gnus-group-name-charset gnus-current-select-method group))
 
     (or (and entry (not (eq (car entry) t))) ; Either it's active...
 	(gnus-activate-group group)	; Or we can activate it...
 	(progn				; Or we bug out.
 	  (when (equal major-mode 'gnus-summary-mode)
 	    (gnus-kill-buffer (current-buffer)))
-	  (error "Couldn't activate group %s: %s"
-		 (gnus-group-decoded-name group) (gnus-status-message group))))
+	  (error
+	   "Couldn't activate group %s: %s"
+	   (mm-decode-coding-string group charset)
+	   (mm-decode-coding-string (gnus-status-message group) charset))))
 
     (unless (gnus-request-group group t)
-      (when (equal major-mode 'gnus-summary-mode)
-	(gnus-kill-buffer (current-buffer)))
-      (error "Couldn't request group %s: %s"
-	     (gnus-group-decoded-name group) (gnus-status-message group)))
+	(when (equal major-mode 'gnus-summary-mode)
+	  (gnus-kill-buffer (current-buffer)))
+	(error "Couldn't request group %s: %s"
+	       (mm-decode-coding-string group charset)
+	       (mm-decode-coding-string (gnus-status-message group) charset)))
 
     (when gnus-agent
       (gnus-agent-possibly-alter-active group (gnus-active group) info)
@@ -5387,7 +5552,8 @@
       (setq gnus-newsgroup-auto-expire
 	    (gnus-group-auto-expirable-p group))
       ;; Set up the article buffer now, if necessary.
-      (unless gnus-single-article-buffer
+      (unless (and gnus-single-article-buffer
+		   (equal gnus-article-buffer "*Article*"))
 	(gnus-article-setup-buffer))
       ;; First and last article in this newsgroup.
       (when gnus-newsgroup-headers
@@ -5521,9 +5687,7 @@
 			  (read-string
 			   (format
 			    "How many articles from %s (%s %d): "
-			    (gnus-limit-string
-			     (gnus-group-decoded-name gnus-newsgroup-name)
-			     35)
+			    (gnus-group-decoded-name gnus-newsgroup-name)
 			    (if initial "max" "default")
 			    number)
 			   (if initial
@@ -5849,7 +6013,7 @@
 (defun gnus-mark-xrefs-as-read (from-newsgroup headers unreads)
   "Look through all the headers and mark the Xrefs as read."
   (let ((virtual (gnus-virtual-group-p from-newsgroup))
-	name entry info xref-hashtb idlist method nth4)
+	name info xref-hashtb idlist method nth4)
     (save-excursion
       (set-buffer gnus-group-buffer)
       (when (setq xref-hashtb
@@ -5860,8 +6024,7 @@
 	     (setq idlist (symbol-value group))
 	     ;; Dead groups are not updated.
 	     (and (prog1
-		      (setq entry (gnus-gethash name gnus-newsrc-hashtb)
-			    info (nth 2 entry))
+		      (setq info (gnus-get-info name))
 		    (when (stringp (setq nth4 (gnus-info-method info)))
 		      (setq nth4 (gnus-server-to-method nth4))))
 		  ;; Only do the xrefs if the group has the same
@@ -5883,7 +6046,7 @@
 	 xref-hashtb)))))
 
 (defun gnus-compute-read-articles (group articles)
-  (let* ((entry (gnus-gethash group gnus-newsrc-hashtb))
+  (let* ((entry (gnus-group-entry group))
 	 (info (nth 2 entry))
 	 (active (gnus-active group))
 	 ninfo)
@@ -5920,14 +6083,13 @@
 (defun gnus-group-make-articles-read (group articles)
   "Update the info of GROUP to say that ARTICLES are read."
   (let* ((num 0)
-	 (entry (gnus-gethash group gnus-newsrc-hashtb))
+	 (entry (gnus-group-entry group))
 	 (info (nth 2 entry))
 	 (active (gnus-active group))
 	 range)
     (when entry
       (setq range (gnus-compute-read-articles group articles))
-      (save-excursion
-	(set-buffer gnus-group-buffer)
+      (with-current-buffer gnus-group-buffer
 	(gnus-undo-register
 	  `(progn
 	     (gnus-info-set-marks ',info ',(gnus-info-marks info) t)
@@ -5966,9 +6128,9 @@
   (let ((cur nntp-server-buffer)
 	(dependencies
 	 (or dependencies
-	     (save-excursion (set-buffer gnus-summary-buffer)
-			     gnus-newsgroup-dependencies)))
-	headers id end ref
+	     (with-current-buffer gnus-summary-buffer
+	       gnus-newsgroup-dependencies)))
+	headers id end ref number
 	(mail-parse-charset gnus-newsgroup-charset)
 	(mail-parse-ignored-charsets
 	 (save-excursion (condition-case nil
@@ -6001,7 +6163,7 @@
 	   (vector
 	    ;; Number.
 	    (prog1
-		(read cur)
+		(setq number (read cur))
 	      (end-of-line)
 	      (setq p (point))
 	      (narrow-to-region (point)
@@ -6038,7 +6200,7 @@
 					     (match-end 1))
 			 ;; If there was no message-id, we just fake one
 			 ;; to make subsequent routines simpler.
-			 (nnheader-generate-fake-message-id))))
+			 (nnheader-generate-fake-message-id number))))
 	    ;; References.
 	    (progn
 	      (goto-char p)
@@ -6185,8 +6347,8 @@
 (defun gnus-article-get-xrefs ()
   "Fill in the Xref value in `gnus-current-headers', if necessary.
 This is meant to be called in `gnus-article-internal-prepare-hook'."
-  (let ((headers (save-excursion (set-buffer gnus-summary-buffer)
-				 gnus-current-headers)))
+  (let ((headers (with-current-buffer gnus-summary-buffer
+		   gnus-current-headers)))
     (or (not gnus-use-cross-reference)
 	(not headers)
 	(and (mail-header-xref headers)
@@ -6201,7 +6363,7 @@
 			   (looking-at "Xref:"))
 		      (search-forward "\nXref:" nil t))
 	      (goto-char (1+ (match-end 0)))
-	      (setq xref (buffer-substring (point) (gnus-point-at-eol)))
+	      (setq xref (buffer-substring (point) (point-at-eol)))
 	      (mail-header-set-xref headers xref)))))))
 
 (defun gnus-summary-insert-subject (id &optional old-header use-old-header)
@@ -6229,9 +6391,9 @@
 	  (goto-char (gnus-data-pos d))
 	  (gnus-data-remove
 	   number
-	   (- (gnus-point-at-bol)
+	   (- (point-at-bol)
 	      (prog1
-		  (1+ (gnus-point-at-eol))
+		  (1+ (point-at-eol))
 		(gnus-delete-line))))))
       ;; Remove list identifiers from subject.
       (when gnus-list-identifiers
@@ -6345,8 +6507,7 @@
 (defun gnus-summary-process-mark-set (set)
   "Make SET into the current process marked articles."
   (gnus-summary-unmark-all-processable)
-  (while set
-    (gnus-summary-set-process-mark (pop set))))
+  (mapc 'gnus-summary-set-process-mark set))
 
 ;;; Searching and stuff
 
@@ -6362,8 +6523,7 @@
 (defun gnus-summary-best-group (&optional exclude-group)
   "Find the name of the best unread group.
 If EXCLUDE-GROUP, do not go to this group."
-  (save-excursion
-    (set-buffer gnus-group-buffer)
+  (with-current-buffer gnus-group-buffer
     (save-excursion
       (gnus-group-best-unread-group exclude-group))))
 
@@ -6494,7 +6654,7 @@
 		      ((< (window-height) 7) 1)
 		      (t (if (numberp gnus-auto-center-summary)
 			     gnus-auto-center-summary
-			   2))))
+                           (/ (1- (window-height)) 2)))))
 	   (height (1- (window-height)))
 	   (bottom (save-excursion (goto-char (point-max))
 				   (forward-line (- height))
@@ -6508,7 +6668,7 @@
 	(let ((top-pos (save-excursion (forward-line (- top)) (point))))
 	  (if (> bottom top-pos)
 	      ;; Keep the second line from the top visible
-	      (set-window-start window top-pos t)
+	      (set-window-start window top-pos)
 	    ;; Try to keep the bottom line visible; if it's partially
 	    ;; obscured, either scroll one more line to make it fully
 	    ;; visible, or revert to using TOP-POS.
@@ -6552,7 +6712,8 @@
 (defun gnus-list-of-unread-articles (group)
   (let* ((read (gnus-info-read (gnus-get-info group)))
 	 (active (or (gnus-active group) (gnus-activate-group group)))
-	 (last (cdr active))
+	 (last (or (cdr active)
+		   (error "Group %s couldn't be activated " group)))
 	 (bottom (if gnus-newsgroup-maximum-articles
 		     (max (car active)
 			  (- last gnus-newsgroup-maximum-articles -1))
@@ -6752,8 +6913,7 @@
 	  (setq gnus-newsgroup-killed (list gnus-newsgroup-killed)))
 	(let ((headers gnus-newsgroup-headers))
 	  ;; Set the new ranges of read articles.
-	  (save-excursion
-	    (set-buffer gnus-group-buffer)
+	  (with-current-buffer gnus-group-buffer
 	    (gnus-undo-force-boundary))
 	  (gnus-update-read-articles
 	   group (gnus-sorted-union
@@ -6813,8 +6973,13 @@
     (gnus-run-hooks 'gnus-summary-prepare-exit-hook)
     ;; If we have several article buffers, we kill them at exit.
     (unless gnus-single-article-buffer
-      (gnus-kill-buffer gnus-original-article-buffer)
-      (setq gnus-article-current nil))
+      (when (gnus-buffer-live-p gnus-article-buffer)
+	(with-current-buffer gnus-article-buffer
+	  ;; Don't kill sticky article buffers
+	  (unless (eq major-mode 'gnus-sticky-article-mode)
+	    (gnus-kill-buffer gnus-article-buffer)
+	    (setq gnus-article-current nil))))
+      (gnus-kill-buffer gnus-original-article-buffer))
     (when gnus-use-cache
       (gnus-cache-possibly-remove-articles)
       (gnus-cache-save-buffers))
@@ -6838,6 +7003,7 @@
       (gnus-group-jump-to-group group))
     (gnus-run-hooks 'gnus-summary-exit-hook)
     (unless (or quit-config
+		(not gnus-summary-next-group-on-exit)
 		;; If this group has disappeared from the summary
 		;; buffer, don't skip forwards.
 		(not (string= group (gnus-group-group-name))))
@@ -6845,11 +7011,6 @@
     (setq group-point (point))
     (if temporary
 	nil				;Nothing to do.
-      ;; If we have several article buffers, we kill them at exit.
-      (unless gnus-single-article-buffer
-	(gnus-kill-buffer gnus-article-buffer)
-	(gnus-kill-buffer gnus-original-article-buffer)
-	(setq gnus-article-current nil))
       (set-buffer buf)
       (if (not gnus-kill-summary-on-exit)
 	  (progn
@@ -6864,12 +7025,6 @@
 	  (gnus-summary-clear-local-variables))
 	(when (get-buffer gnus-article-buffer)
 	  (bury-buffer gnus-article-buffer))
-	;; We clear the global counterparts of the buffer-local
-	;; variables as well, just to be on the safe side.
-	(set-buffer gnus-group-buffer)
-	(gnus-summary-clear-local-variables)
-	(let ((gnus-summary-local-variables gnus-newsgroup-variables))
-	  (gnus-summary-clear-local-variables))
 	;; Return to group mode buffer.
 	(when (eq mode 'gnus-summary-mode)
 	  (gnus-kill-buffer buf)))
@@ -6919,10 +7074,6 @@
 	(gnus-summary-clear-local-variables)
 	(let ((gnus-summary-local-variables gnus-newsgroup-variables))
 	  (gnus-summary-clear-local-variables))
-	(set-buffer gnus-group-buffer)
-	(gnus-summary-clear-local-variables)
-	(let ((gnus-summary-local-variables gnus-newsgroup-variables))
-	  (gnus-summary-clear-local-variables))
 	(gnus-kill-buffer gnus-summary-buffer))
       (unless gnus-single-article-buffer
 	(setq gnus-article-current nil))
@@ -6961,19 +7112,26 @@
 	     (gnus-set-global-variables))))
     (if (or (eq (cdr quit-config) 'article)
 	    (eq (cdr quit-config) 'pick))
-	(progn
-	  ;; The current article may be from the ephemeral group
-	  ;; thus it is best that we reload this article
-	  ;;
-	  ;; If we're exiting from a large digest, this can be
-	  ;; extremely slow.  So, it's better not to reload it. -- jh.
-	  ;;(gnus-summary-show-article)
-	  (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))
     (when (eq major-mode 'gnus-summary-mode)
-      (gnus-summary-next-subject 1 nil t)
+      (if (memq gnus-auto-select-on-ephemeral-exit '(next-noselect
+						     next-unread-noselect))
+	  (when (zerop (cond ((eq gnus-auto-select-on-ephemeral-exit
+				  'next-noselect)
+			      (gnus-summary-next-subject 1 nil t))
+			     ((eq gnus-auto-select-on-ephemeral-exit
+				  'next-unread-noselect)
+			      (gnus-summary-next-subject 1 t t))))
+	    ;; Hide the article buffer which displays the article different
+	    ;; from the one that the cursor points to in the summary buffer.
+	    (gnus-configure-windows 'summary 'force))
+	(cond ((eq gnus-auto-select-on-ephemeral-exit 'next)
+	       (gnus-summary-next-subject 1))
+	      ((eq gnus-auto-select-on-ephemeral-exit 'next-unread)
+	       (gnus-summary-next-subject 1 t))))
       (gnus-summary-recenter)
       (gnus-summary-position-point))))
 
@@ -7004,7 +7162,7 @@
 	  (if (null arg) (not gnus-dead-summary-mode)
 	    (> (prefix-numeric-value arg) 0)))
     (when gnus-dead-summary-mode
-      (gnus-add-minor-mode
+      (add-minor-mode
        'gnus-dead-summary-mode " Dead" gnus-dead-summary-mode-map))))
 
 (defun gnus-deaden-summary ()
@@ -7012,8 +7170,7 @@
   ;; Kill any previous dead summary buffer.
   (when (and gnus-dead-summary
 	     (buffer-name gnus-dead-summary))
-    (save-excursion
-      (set-buffer gnus-dead-summary)
+    (with-current-buffer gnus-dead-summary
       (when gnus-dead-summary-mode
 	(kill-buffer (current-buffer)))))
   ;; Make this the current dead summary.
@@ -7032,8 +7189,7 @@
   (save-excursion
     (when (and (buffer-name buffer)
 	       (not gnus-single-article-buffer))
-      (save-excursion
-	(set-buffer buffer)
+      (with-current-buffer buffer
 	(gnus-kill-buffer gnus-article-buffer)
 	(gnus-kill-buffer gnus-original-article-buffer)))
     (cond
@@ -7073,7 +7229,7 @@
     (when current-prefix-arg
       (completing-read
        "FAQ dir: " (and (listp gnus-group-faq-directory)
-			(mapcar (lambda (file) (list file))
+			(mapcar 'list
 				gnus-group-faq-directory))))))
   (let (gnus-faq-buffer)
     (when (setq gnus-faq-buffer
@@ -7287,15 +7443,15 @@
 
 (defun gnus-summary-display-article (article &optional all-header)
   "Display ARTICLE in article buffer."
-  (when (gnus-buffer-live-p gnus-article-buffer)
-    (with-current-buffer gnus-article-buffer
-      (mm-enable-multibyte)))
+  (unless (and (gnus-buffer-live-p gnus-article-buffer)
+	       (with-current-buffer gnus-article-buffer
+		 (eq major-mode 'gnus-article-mode)))
+    (gnus-article-setup-buffer))
   (gnus-set-global-variables)
-  (when (gnus-buffer-live-p gnus-article-buffer)
-    (with-current-buffer gnus-article-buffer
-      (setq gnus-article-charset gnus-newsgroup-charset)
-      (setq gnus-article-ignored-charsets gnus-newsgroup-ignored-charsets)
-      (mm-enable-multibyte)))
+  (with-current-buffer gnus-article-buffer
+    (setq gnus-article-charset gnus-newsgroup-charset)
+    (setq gnus-article-ignored-charsets gnus-newsgroup-ignored-charsets)
+    (mm-enable-multibyte))
   (if (null article)
       nil
     (prog1
@@ -7402,8 +7558,7 @@
       (gnus-summary-jump-to-group gnus-newsgroup-name))
     (let ((cmd last-command-char)
 	  (point
-	   (save-excursion
-	     (set-buffer gnus-group-buffer)
+	   (with-current-buffer gnus-group-buffer
 	     (point)))
 	  (group
 	   (if (eq gnus-keep-same-level 'best)
@@ -7456,7 +7611,7 @@
 		 (format " (Type %s for %s [%s])"
 			 (single-key-description cmd)
 			 (gnus-group-decoded-name group)
-			 (car (gnus-gethash group gnus-newsrc-hashtb)))
+			 (gnus-group-unread group))
 	       (format " (Type %s to exit %s)"
 		       (single-key-description cmd)
 		       (gnus-group-decoded-name gnus-newsgroup-name)))))
@@ -7844,6 +7999,123 @@
 	 current-prefix-arg))
   (gnus-summary-limit-to-subject from "from" not-matching))
 
+(defun gnus-summary-limit-to-recipient (recipient &optional not-matching)
+  "Limit the summary buffer to articles with the given RECIPIENT.
+
+If NOT-MATCHING, exclude RECIPIENT.
+
+To and Cc headers are checked.  You need to include them in
+`nnmail-extra-headers'."
+  ;; Unlike `rmail-summary-by-recipients', doesn't include From.
+  (interactive
+   (list (read-string (format "%s recipient (regexp): "
+			      (if current-prefix-arg "Exclude" "Limit to")))
+	 current-prefix-arg))
+  (when (not (equal "" recipient))
+    (prog1 (let* ((to
+		   (if (memq 'To nnmail-extra-headers)
+		       (gnus-summary-find-matching
+			(cons 'extra 'To) recipient 'all nil nil
+			not-matching)
+		     (gnus-message
+		      1 "`To' isn't present in `nnmail-extra-headers'")
+		     (sit-for 1)
+		     nil))
+		  (cc
+		   (if (memq 'Cc nnmail-extra-headers)
+		       (gnus-summary-find-matching
+			(cons 'extra 'Cc) recipient 'all nil nil
+			not-matching)
+		     (gnus-message
+		      1 "`Cc' isn't present in `nnmail-extra-headers'")
+		     (sit-for 1)
+		     nil))
+		  (articles
+		   (if not-matching
+		       ;; We need the numbers that are in both lists:
+		       (mapcar (lambda (a)
+				 (and (memq a to) a))
+			       cc)
+		     (nconc to cc))))
+	     (unless articles
+	       (error "Found no matches for \"%s\"" recipient))
+	     (gnus-summary-limit articles))
+      (gnus-summary-position-point))))
+
+(defun gnus-summary-limit-to-address (address &optional not-matching)
+  "Limit the summary buffer to articles with the given ADDRESS.
+
+If NOT-MATCHING, exclude ADDRESS.
+
+To, Cc and From headers are checked.  You need to include `To' and `Cc'
+in `nnmail-extra-headers'."
+  (interactive
+   (list (read-string (format "%s address (regexp): "
+			      (if current-prefix-arg "Exclude" "Limit to")))
+	 current-prefix-arg))
+  (when (not (equal "" address))
+    (prog1 (let* ((to
+		   (if (memq 'To nnmail-extra-headers)
+		       (gnus-summary-find-matching
+			(cons 'extra 'To) address 'all nil nil
+			not-matching)
+		     (gnus-message
+		      1 "`To' isn't present in `nnmail-extra-headers'")
+		     (sit-for 1)
+		     t))
+		  (cc
+		   (if (memq 'Cc nnmail-extra-headers)
+		       (gnus-summary-find-matching
+			(cons 'extra 'Cc) address 'all nil nil
+			not-matching)
+		     (gnus-message
+		      1 "`Cc' isn't present in `nnmail-extra-headers'")
+		     (sit-for 1)
+		     t))
+		  (from
+		   (gnus-summary-find-matching "from" address
+					       'all nil nil not-matching))
+		  (articles
+		   (if not-matching
+		       ;; We need the numbers that are in all lists:
+		       (if (eq cc t)
+			   (if (eq to t)
+			       from
+			     (mapcar (lambda (a) (car (memq a from))) to))
+			 (if (eq to t)
+			     (mapcar (lambda (a) (car (memq a from))) cc)
+			   (mapcar (lambda (a) (car (memq a from)))
+				   (mapcar (lambda (a) (car (memq a to)))
+					   cc))))
+		     (nconc (if (eq to t) nil to)
+			    (if (eq cc t) nil cc)
+			    from))))
+	     (unless articles
+	       (error "Found no matches for \"%s\"" address))
+	     (gnus-summary-limit articles))
+      (gnus-summary-position-point))))
+
+(defun gnus-summary-limit-strange-charsets-predicate (header)
+  (let ((string (concat (mail-header-subject header)
+			(mail-header-from header)))
+	charset found)
+    (dotimes (i (1- (length string)))
+      (setq charset (format "%s" (char-charset (aref string (1+ i)))))
+      (when (string-match "unicode\\|big\\|japanese" charset)
+	(setq found t)))
+    found))
+
+(defun gnus-summary-limit-to-predicate (predicate)
+  "Limit to articles where PREDICATE returns non-nil.
+PREDICATE will be called with the header structures of the
+articles."
+  (let ((articles nil)
+	(case-fold-search t))
+    (dolist (header gnus-newsgroup-headers)
+      (when (funcall predicate header)
+	(push (mail-header-number header) articles)))
+    (gnus-summary-limit (nreverse articles))))
+
 (defun gnus-summary-limit-to-age (age &optional younger-p)
   "Limit the summary buffer to articles that are older than (or equal) AGE days.
 If YOUNGER-P (the prefix) is non-nil, limit the summary buffer to
@@ -7862,10 +8134,9 @@
        (if (numberp days)
 	   (progn
 	     (setq days-got t)
-	     (if (< days 0)
-		 (progn
-		   (setq younger (not younger))
-		   (setq days (* days -1)))))
+	     (when (< days 0)
+	       (setq younger (not younger))
+	       (setq days (* days -1))))
 	 (message "Please enter a number.")
 	 (sleep-for 1)))
      (list days younger)))
@@ -7950,6 +8221,81 @@
 	   gnus-duplicate-mark gnus-souped-mark)
      'reverse)))
 
+(defun gnus-summary-limit-to-headers (match &optional reverse)
+  "Limit the summary buffer to articles that have headers that match MATCH.
+If REVERSE (the prefix), limit to articles that don't match."
+  (interactive "sMatch headers (regexp): \nP")
+  (gnus-summary-limit-to-bodies match reverse t))
+
+(defun gnus-summary-limit-to-bodies (match &optional reverse headersp)
+  "Limit the summary buffer to articles that have bodies that match MATCH.
+If REVERSE (the prefix), limit to articles that don't match."
+  (interactive "sMatch body (regexp): \nP")
+  (let ((articles nil)
+	(gnus-select-article-hook nil)	;Disable hook.
+	(gnus-article-prepare-hook nil)
+	(gnus-use-article-prefetch nil)
+	(gnus-keep-backlog nil)
+	(gnus-break-pages nil)
+	(gnus-summary-display-arrow nil)
+	(gnus-updated-mode-lines nil)
+	(gnus-auto-center-summary nil)
+	(gnus-display-mime-function nil))
+    (dolist (data gnus-newsgroup-data)
+      (let (gnus-mark-article-hook)
+	(gnus-summary-select-article t t nil (gnus-data-number data)))
+      (save-excursion
+	(set-buffer gnus-article-buffer)
+	(article-goto-body)
+	(let* ((case-fold-search t)
+	       (found (if headersp
+			  (re-search-backward match nil t)
+			(re-search-forward match nil t))))
+	  (when (or (and found
+			 (not reverse))
+		    (and (not found)
+			 reverse))
+	    (push (gnus-data-number data) articles)))))
+    (if (not articles)
+	(message "No messages matched")
+      (gnus-summary-limit articles)))
+  (gnus-summary-position-point))
+
+(defun gnus-summary-limit-to-singletons (&optional threadsp)
+  "Limit the summary buffer to articles that aren't part on any thread.
+If THREADSP (the prefix), limit to articles that are in threads."
+  (interactive "P")
+  (let ((articles nil)
+	thread-articles
+	threads)
+    (dolist (thread gnus-newsgroup-threads)
+      (if (stringp (car thread))
+	  (dolist (thread (cdr thread))
+	    (push thread threads))
+	(push thread threads)))
+    (dolist (thread threads)
+      (setq thread-articles (gnus-articles-in-thread thread))
+      (when (or (and threadsp
+		     (> (length thread-articles) 1))
+		(and (not threadsp)
+		     (= (length thread-articles) 1)))
+	(setq articles (nconc thread-articles articles))))
+    (if (not articles)
+	(message "No messages matched")
+      (gnus-summary-limit articles))
+    (gnus-summary-position-point)))
+
+(defun gnus-summary-limit-to-replied (&optional unreplied)
+  "Limit the summary buffer to replied articles.
+If UNREPLIED (the prefix), limit to unreplied articles."
+  (interactive "P")
+  (if unreplied
+      (gnus-summary-limit
+       (gnus-set-difference gnus-newsgroup-articles
+	gnus-newsgroup-replied))
+    (gnus-summary-limit gnus-newsgroup-replied))
+  (gnus-summary-position-point))
+
 (defalias 'gnus-summary-delete-marked-with 'gnus-summary-limit-exclude-marks)
 (make-obsolete 'gnus-summary-delete-marked-with
 	       'gnus-summary-limit-exclude-marks)
@@ -8035,6 +8381,14 @@
 	(gnus-message 3 "No dormant articles for this group")
       (gnus-summary-goto-subjects gnus-newsgroup-dormant))))
 
+(defun gnus-summary-insert-ticked-articles ()
+  "Insert ticked articles for this group into the current buffer."
+  (interactive)
+  (let ((gnus-verbose (max 6 gnus-verbose)))
+    (if (not gnus-newsgroup-marked)
+	(gnus-message 3 "No ticked articles for this group")
+      (gnus-summary-goto-subjects gnus-newsgroup-marked))))
+
 (defun gnus-summary-limit-include-dormant ()
   "Display all the hidden articles that are marked as dormant.
 Note that this command only works on a subset of the articles currently
@@ -8295,13 +8649,12 @@
 	    (and gnus-newsgroup-display
 		 (not (funcall gnus-newsgroup-display)))
 	    ;; Check NoCeM things.
-	    (if (and gnus-use-nocem
-		     (gnus-nocem-unwanted-article-p
-		      (mail-header-id (car thread))))
-		(progn
-		  (setq gnus-newsgroup-unreads
-			(delq number gnus-newsgroup-unreads))
-		  t))))
+	    (when (and gnus-use-nocem
+		       (gnus-nocem-unwanted-article-p
+			(mail-header-id (car thread))))
+	      (setq gnus-newsgroup-unreads
+		    (delq number gnus-newsgroup-unreads))
+	      t)))
 	  ;; Nope, invisible article.
 	  0
 	;; Ok, this article is to be visible, so we add it to the limit
@@ -8513,8 +8866,7 @@
     (let* ((name (format "%s-%d"
 			 (gnus-group-prefixed-name
 			  gnus-newsgroup-name (list 'nndoc ""))
-			 (save-excursion
-			   (set-buffer gnus-summary-buffer)
+			 (with-current-buffer gnus-summary-buffer
 			   gnus-current-article)))
 	   (ogroup gnus-newsgroup-name)
 	   (params (append (gnus-info-params (gnus-get-info ogroup))
@@ -8572,12 +8924,11 @@
 documents as newsgroups.
 Obeys the standard process/prefix convention."
   (interactive "P")
-  (let* ((articles (gnus-summary-work-articles n))
-	 (ogroup gnus-newsgroup-name)
+  (let* ((ogroup gnus-newsgroup-name)
 	 (params (append (gnus-info-params (gnus-get-info ogroup))
 			 (list (cons 'to-group ogroup))))
-	 article group egroup groups vgroup)
-    (while (setq article (pop articles))
+	 group egroup groups vgroup)
+    (dolist (article (gnus-summary-work-articles n))
       (setq group (format "%s-%d" gnus-newsgroup-name article))
       (gnus-summary-remove-process-mark article)
       (when (gnus-summary-display-article article)
@@ -8588,7 +8939,7 @@
 	    ;; the wrong guess.
 	    (message-narrow-to-head)
 	    (goto-char (point-min))
-	    (delete-matching-lines "^\\(Path\\):\\|^From ")
+	    (delete-matching-lines "^Path:\\|^From ")
 	    (widen)
 	    (if (setq egroup
 		      (gnus-group-read-ephemeral-group
@@ -8627,6 +8978,20 @@
       (widen)
       (isearch-forward regexp-p))))
 
+(defun gnus-summary-repeat-search-article-forward ()
+  "Repeat the previous search forwards."
+  (interactive)
+  (unless gnus-last-search-regexp
+    (error "No previous search"))
+  (gnus-summary-search-article-forward gnus-last-search-regexp))
+
+(defun gnus-summary-repeat-search-article-backward ()
+  "Repeat the previous search backwards."
+  (interactive)
+  (unless gnus-last-search-regexp
+    (error "No previous search"))
+  (gnus-summary-search-article-forward gnus-last-search-regexp t))
+
 (defun gnus-summary-search-article-forward (regexp &optional backward)
   "Search for an article containing REGEXP forward.
 If BACKWARD, search backward instead."
@@ -8929,8 +9294,7 @@
 	   (or (cdr (assq arg gnus-summary-show-article-charset-alist))
 	       (mm-read-coding-system
 		"View as charset: " ;; actually it is coding system.
-		(save-excursion
-		  (set-buffer gnus-article-buffer)
+		(with-current-buffer gnus-article-buffer
 		  (mm-detect-coding-region (point) (point-max))))))
 	  (gnus-newsgroup-ignored-charsets 'gnus-all))
       (gnus-summary-select-article nil 'force)
@@ -9054,8 +9418,8 @@
 
 (defun gnus-summary-caesar-message (&optional arg)
   "Caesar rotate the current article by 13.
-The numerical prefix specifies how many places to rotate each letter
-forward."
+With a non-numerical prefix, also rotate headers.  A numerical
+prefix specifies how many places to rotate each letter forward."
   (interactive "P")
   (gnus-summary-select-article)
   (let ((mail-header-separator ""))
@@ -9064,14 +9428,38 @@
 	(widen)
 	(let ((start (window-start))
 	      buffer-read-only)
-	  (message-caesar-buffer-body arg)
+	  (if (equal arg '(4))
+	      (message-caesar-buffer-body nil t)
+	    (message-caesar-buffer-body arg))
 	  (set-window-start (get-buffer-window (current-buffer)) start)))))
   ;; Create buttons and stuff...
   (gnus-treat-article nil))
 
-(autoload 'unmorse-region "morse"
-  "Convert morse coded text in region to ordinary ASCII text."
-  t)
+(defun gnus-summary-idna-message (&optional arg)
+  "Decode IDNA encoded domain names in the current articles.
+IDNA encoded domain names looks like `xn--bar'.  If a string
+remain unencoded after running this function, it is likely an
+invalid IDNA string (`xn--bar' is invalid).
+
+You must have GNU Libidn (`http://www.gnu.org/software/libidn/')
+installed for this command to work."
+  (interactive "P")
+  (if (not (and (condition-case nil (require 'idna)
+		  (file-error))
+		(mm-coding-system-p 'utf-8)
+		(executable-find (symbol-value 'idna-program))))
+      (gnus-message
+       5 "GNU Libidn not installed properly (`idn' or `idna.el' missing)")
+    (gnus-summary-select-article)
+    (let ((mail-header-separator ""))
+      (gnus-eval-in-buffer-window gnus-article-buffer
+	(save-restriction
+	  (widen)
+	  (let ((start (window-start))
+		buffer-read-only)
+	    (while (re-search-forward "\\(xn--[-0-9a-z]+\\)" nil t)
+	      (replace-match (idna-to-unicode (match-string 1))))
+	    (set-window-start (get-buffer-window (current-buffer)) start)))))))
 
 (defun gnus-summary-morse-message (&optional arg)
   "Morse decode the current article."
@@ -9088,7 +9476,7 @@
 	    (when (message-goto-body)
 	      (gnus-narrow-to-body))
 	    (goto-char (point-min))
-	    (while (re-search-forward "·" (point-max) t)
+	    (while (search-forward "·" (point-max) t)
 	      (replace-match "."))
 	    (unmorse-region (point-min) (point-max))
 	    (widen)
@@ -9141,14 +9529,16 @@
   (let ((articles (gnus-summary-work-articles n))
 	(prefix (if (gnus-check-backend-function
 		     'request-move-article gnus-newsgroup-name)
-		    (gnus-group-real-prefix gnus-newsgroup-name)
+		    (funcall gnus-move-group-prefix-function
+			     gnus-newsgroup-name)
 		  ""))
 	(names '((move "Move" "Moving")
 		 (copy "Copy" "Copying")
 		 (crosspost "Crosspost" "Crossposting")))
 	(copy-buf (save-excursion
 		    (nnheader-set-temp-buffer " *copy article*")))
-	art-group to-method new-xref article to-groups)
+	art-group to-method new-xref article to-groups
+	articles-to-update-marks encoded)
     (unless (assq action names)
       (error "Unknown action %s" action))
     ;; Read the newsgroup name.
@@ -9166,15 +9556,27 @@
 		(gnus-article-prepare-hook nil)
 		(gnus-mark-article-hook nil))
 	    (gnus-summary-select-article nil nil nil (car articles))))
-      (setq to-newsgroup
-	    (gnus-read-move-group-name
-	     (cadr (assq action names))
-	     (symbol-value (intern (format "gnus-current-%s-group" action)))
-	     articles prefix))
-      (set (intern (format "gnus-current-%s-group" action)) to-newsgroup))
-    (setq to-method (or select-method
-			(gnus-server-to-method
-			 (gnus-group-method to-newsgroup))))
+      (setq to-newsgroup (gnus-read-move-group-name
+			  (cadr (assq action names))
+			  (symbol-value
+			   (intern (format "gnus-current-%s-group" action)))
+			  articles prefix)
+	    encoded to-newsgroup
+	    to-method (gnus-server-to-method (gnus-group-method to-newsgroup)))
+      (set (intern (format "gnus-current-%s-group" action))
+	   (mm-decode-coding-string
+	    to-newsgroup
+	    (gnus-group-name-charset to-method to-newsgroup))))
+    (unless to-method
+      (setq to-method (or select-method
+			  (gnus-server-to-method
+			   (gnus-group-method to-newsgroup)))))
+    (setq to-newsgroup
+	  (or encoded
+	      (and to-newsgroup
+		   (mm-encode-coding-string
+		    to-newsgroup
+		    (gnus-group-name-charset to-method to-newsgroup)))))
     ;; Check the method we are to move this article to...
     (unless (gnus-check-backend-function
 	     'request-accept-article (car to-method))
@@ -9183,7 +9585,9 @@
       (error "Can't open server %s" (car to-method)))
     (gnus-message 6 "%s to %s: %s..."
 		  (caddr (assq action names))
-		  (or (car select-method) to-newsgroup) articles)
+		  (or (car select-method)
+		      (gnus-group-decoded-name to-newsgroup))
+		  articles)
     (while articles
       (setq article (pop articles))
       (setq
@@ -9193,20 +9597,30 @@
 	((eq action 'move)
 	 ;; Remove this article from future suppression.
 	 (gnus-dup-unsuppress-article article)
-	 (gnus-request-move-article
-	  article			; Article to move
-	  gnus-newsgroup-name		; From newsgroup
-	  (nth 1 (gnus-find-method-for-group
-		  gnus-newsgroup-name)) ; Server
-	  (list 'gnus-request-accept-article
-		to-newsgroup (list 'quote select-method)
-		(not articles) t)	; Accept form
-	  (not articles)))		; Only save nov last time
+	 (let* ((from-method (gnus-find-method-for-group
+			      gnus-newsgroup-name))
+		(to-method (or select-method
+			       (gnus-find-method-for-group to-newsgroup)))
+		(move-is-internal (gnus-method-equal from-method to-method)))
+	   (gnus-request-move-article
+	    article			; Article to move
+	    gnus-newsgroup-name		; From newsgroup
+	    (nth 1 (gnus-find-method-for-group
+		    gnus-newsgroup-name)) ; Server
+	    (list 'gnus-request-accept-article
+		  to-newsgroup (list 'quote select-method)
+		  (not articles) t)	; Accept form
+	    (not articles)		; Only save nov last time
+	    move-is-internal)))		; is this move internal?
 	;; Copy the article.
 	((eq action 'copy)
 	 (save-excursion
 	   (set-buffer copy-buf)
 	   (when (gnus-request-article-this-buffer article gnus-newsgroup-name)
+	     (save-restriction
+	       (nnheader-narrow-to-headers)
+	       (dolist (hdr gnus-copy-article-ignored-headers)
+		 (message-remove-header hdr t)))
 	     (gnus-request-accept-article
 	      to-newsgroup select-method (not articles) t))))
 	;; Crosspost the article.
@@ -9259,9 +9673,7 @@
        (t
 	(let* ((pto-group (gnus-group-prefixed-name
 			   (car art-group) to-method))
-	       (entry
-		(gnus-gethash pto-group gnus-newsrc-hashtb))
-	       (info (nth 2 entry))
+	       (info (gnus-get-info pto-group))
 	       (to-group (gnus-info-group info))
 	       to-marks)
 	  ;; Update the group that has been moved to.
@@ -9353,7 +9765,9 @@
 	(gnus-summary-goto-subject article)
 	(when (eq action 'move)
 	  (gnus-summary-mark-article article gnus-canceled-mark))))
-      (gnus-summary-remove-process-mark article))
+      (push article articles-to-update-marks))
+
+    (apply 'gnus-summary-remove-process-mark articles-to-update-marks)
     ;; Re-activate all groups that have been moved to.
     (save-excursion
       (set-buffer gnus-group-buffer)
@@ -9629,10 +10043,10 @@
 	(unless (memq (car articles) not-deleted)
 	  (gnus-summary-mark-article (car articles) gnus-canceled-mark))
 	(let* ((article (car articles))
-	       (id (mail-header-id (gnus-data-header
-				    (assoc article (gnus-data-list nil))))))
+	       (ghead  (gnus-data-header
+				    (assoc article (gnus-data-list nil)))))
 	  (run-hook-with-args 'gnus-summary-article-delete-hook
-			      'delete id gnus-newsgroup-name nil
+			      'delete ghead gnus-newsgroup-name nil
 			      nil))
 	(setq articles (cdr articles)))
       (when not-deleted
@@ -9705,7 +10119,16 @@
 		  (message-options message-options)
 		  (message-options-set-recipient)
 		  (mail-parse-ignored-charsets
-		   ',gnus-newsgroup-ignored-charsets))
+		   ',gnus-newsgroup-ignored-charsets)
+		  (rfc2047-header-encoding-alist
+		   ',(let ((charset (gnus-group-name-charset
+				     (gnus-find-method-for-group
+				      gnus-newsgroup-name)
+				     gnus-newsgroup-name)))
+		       (append (list (cons "Newsgroups" charset)
+				     (cons "Followup-To" charset)
+				     (cons "Xref" charset))
+			       rfc2047-header-encoding-alist))))
 	      ,(if (not raw) '(progn
 				(mml-to-mime)
 				(mml-destroy-buffers)
@@ -10013,8 +10436,7 @@
   ;; (article-number . line-number-in-body).
   (push
    (cons article
-	 (save-excursion
-	   (set-buffer gnus-article-buffer)
+	 (with-current-buffer gnus-article-buffer
 	   (count-lines
 	    (min (point)
 		 (save-excursion
@@ -10051,13 +10473,15 @@
     (gnus-summary-goto-subject article)
     (gnus-summary-update-secondary-mark article)))
 
-(defun gnus-summary-remove-process-mark (article)
-  "Remove the process mark from ARTICLE and update the summary line."
-  (setq gnus-newsgroup-processable (delq article gnus-newsgroup-processable))
-  (when (gnus-summary-goto-subject article)
-    (gnus-summary-show-thread)
-    (gnus-summary-goto-subject article)
-    (gnus-summary-update-secondary-mark article)))
+(defun gnus-summary-remove-process-mark (&rest articles)
+  "Remove the process mark from ARTICLES and update the summary line."
+  (dolist (article articles)
+    (setq gnus-newsgroup-processable (delq article gnus-newsgroup-processable))
+    (when (gnus-summary-goto-subject article)
+      (gnus-summary-show-thread)
+      (gnus-summary-goto-subject article)
+      (gnus-summary-update-secondary-mark article)))
+  t)
 
 (defun gnus-summary-set-saved-mark (article)
   "Set the process mark on ARTICLE and update the summary line."
@@ -10258,7 +10682,7 @@
 (defun gnus-summary-update-mark (mark type)
   (let ((forward (cdr (assq type gnus-summary-mark-positions)))
 	(buffer-read-only nil))
-    (re-search-backward "[\n\r]" (gnus-point-at-bol) 'move-to-limit)
+    (re-search-backward "[\n\r]" (point-at-bol) 'move-to-limit)
     (when forward
       (when (looking-at "\r")
 	(incf forward))
@@ -10501,9 +10925,8 @@
 	(goto-char (point-min))
 	(push gnus-newsgroup-limit gnus-newsgroup-limits)
 	(setq gnus-newsgroup-limit (copy-sequence gnus-newsgroup-limit))
-	(mapcar (lambda (x) (push (mail-header-number x)
-				  gnus-newsgroup-limit))
-		headers)
+	(dolist (x headers)
+	  (push (mail-header-number x) gnus-newsgroup-limit))
 	(gnus-summary-prepare-unthreaded (nreverse headers))
 	(goto-char (point-min))
 	(gnus-summary-position-point)
@@ -10628,6 +11051,15 @@
     (gnus-summary-catchup all))
   (gnus-summary-next-group))
 
+(defun gnus-summary-catchup-and-goto-prev-group (&optional all)
+  "Mark all articles in this group as read and select the previous group.
+If given a prefix, mark all articles, unread as well as ticked, as
+read."
+  (interactive "P")
+  (save-excursion
+    (gnus-summary-catchup all))
+  (gnus-summary-next-group nil nil t))
+
 ;;;
 ;;; with article
 ;;;
@@ -10720,41 +11152,51 @@
     (error "The current newsgroup does not support article editing"))
   (unless (<= (length gnus-newsgroup-processable) 1)
     (error "No more than one article may be marked"))
-  (save-window-excursion
-    (let ((gnus-article-buffer " *reparent*")
-	  (current-article (gnus-summary-article-number))
-	  ;; First grab the marked article, otherwise one line up.
-	  (parent-article (if (not (null gnus-newsgroup-processable))
-			      (car gnus-newsgroup-processable)
-			    (save-excursion
-			      (if (eq (forward-line -1) 0)
-				  (gnus-summary-article-number)
-				(error "Beginning of summary buffer"))))))
-      (unless (not (eq current-article parent-article))
-	(error "An article may not be self-referential"))
-      (let ((message-id (mail-header-id
-			 (gnus-summary-article-header parent-article))))
-	(unless (and message-id (not (equal message-id "")))
-	  (error "No message-id in desired parent"))
-	(gnus-with-article current-article
-	  (save-restriction
-	    (goto-char (point-min))
-	    (message-narrow-to-head)
-	    (if (re-search-forward "^References: " nil t)
-		(progn
-		  (re-search-forward "^[^ \t]" nil t)
-		  (forward-line -1)
-		  (end-of-line)
-		  (insert " " message-id))
-	      (insert "References: " message-id "\n"))))
-	(set-buffer gnus-summary-buffer)
-	(gnus-summary-unmark-all-processable)
-	(gnus-summary-update-article current-article)
-	(if (gnus-summary-goto-subject (cdr gnus-article-current) nil t)
+  (let ((child (gnus-summary-article-number))
+	;; First grab the marked article, otherwise one line up.
+	(parent (if (not (null gnus-newsgroup-processable))
+		    (car gnus-newsgroup-processable)
+		  (save-excursion
+		    (if (eq (forward-line -1) 0)
+			(gnus-summary-article-number)
+		      (error "Beginning of summary buffer"))))))
+    (gnus-summary-reparent-children parent (list child))))
+
+(defun gnus-summary-reparent-children (parent children)
+  "Make PARENT the parent of CHILDREN.
+When called interactively, PARENT is the current article and CHILDREN
+are the process-marked articles."
+  (interactive
+   (list (gnus-summary-article-number)
+	 (gnus-summary-work-articles nil)))
+  (dolist (child children)
+    (save-window-excursion
+      (let ((gnus-article-buffer " *reparent*"))
+	(unless (not (eq parent child))
+	  (error "An article may not be self-referential"))
+	(let ((message-id (mail-header-id
+			   (gnus-summary-article-header parent))))
+	  (unless (and message-id (not (equal message-id "")))
+	    (error "No message-id in desired parent"))
+	  (gnus-with-article child
+	    (save-restriction
+	      (goto-char (point-min))
+	      (message-narrow-to-head)
+	      (if (re-search-forward "^References: " nil t)
+		  (progn
+		    (re-search-forward "^[^ \t]" nil t)
+		    (forward-line -1)
+		    (end-of-line)
+		    (insert " " message-id))
+		(insert "References: " message-id "\n"))))
+	  (set-buffer gnus-summary-buffer)
+	  (gnus-summary-unmark-all-processable)
+	  (gnus-summary-update-article child)
+	  (when (gnus-summary-goto-subject (cdr gnus-article-current) nil t)
 	    (gnus-summary-update-secondary-mark (cdr gnus-article-current)))
-	(gnus-summary-rethread-current)
-	(gnus-message 3 "Article %d is now the child of article %d"
-		      current-article parent-article)))))
+	  (gnus-summary-rethread-current)
+	  (gnus-message 3 "Article %d is now the child of article %d"
+			child parent))))))
 
 (defun gnus-summary-toggle-threads (&optional arg)
   "Toggle showing conversation threads.
@@ -10783,7 +11225,7 @@
   (interactive)
   (let ((buffer-read-only nil)
 	(orig (point))
-	(end (gnus-point-at-eol))
+	(end (point-at-eol))
 	;; Leave point at bol
 	(beg (progn (beginning-of-line) (point))))
     (prog1
@@ -10947,14 +11389,21 @@
   (while (gnus-summary-go-up-thread))
   (gnus-summary-article-number))
 
+(defun gnus-summary-expire-thread ()
+  "Mark articles under current thread as expired."
+  (interactive)
+  (gnus-summary-kill-thread 0))
+
 (defun gnus-summary-kill-thread (&optional unmark)
   "Mark articles under current thread as read.
 If the prefix argument is positive, remove any kinds of marks.
+If the prefix argument is zero, mark thread as expired.
 If the prefix argument is negative, tick articles instead."
   (interactive "P")
   (when unmark
     (setq unmark (prefix-numeric-value unmark)))
-  (let ((articles (gnus-summary-articles-in-thread)))
+  (let ((articles (gnus-summary-articles-in-thread))
+	(hide (or (null unmark) (= unmark 0))))
     (save-excursion
       ;; Expand the thread.
       (gnus-summary-show-thread)
@@ -10965,15 +11414,17 @@
 	       (gnus-summary-mark-article-as-read gnus-killed-mark))
 	      ((> unmark 0)
 	       (gnus-summary-mark-article-as-unread gnus-unread-mark))
+	      ((= unmark 0)
+	       (gnus-summary-mark-article-as-unread gnus-expirable-mark))
 	      (t
 	       (gnus-summary-mark-article-as-unread gnus-ticked-mark)))
 	(setq articles (cdr articles))))
-    ;; Hide killed subtrees.
-    (and (null unmark)
+    ;; Hide killed subtrees when hide is true.
+    (and hide
 	 gnus-thread-hide-killed
 	 (gnus-summary-hide-thread))
-    ;; If marked as read, go to next unread subject.
-    (when (null unmark)
+    ;; If hide is t, go to next unread subject.
+    (when hide
       ;; Go to next unread subject.
       (gnus-summary-next-subject 1 t)))
   (gnus-set-mode-line 'summary))
@@ -10999,6 +11450,13 @@
   (interactive "P")
   (gnus-summary-sort 'author reverse))
 
+(defun gnus-summary-sort-by-recipient (&optional reverse)
+  "Sort the summary buffer by recipient name alphabetically.
+If `case-fold-search' is non-nil, case of letters is ignored.
+Argument REVERSE means reverse order."
+  (interactive "P")
+  (gnus-summary-sort 'recipient reverse))
+
 (defun gnus-summary-sort-by-subject (&optional reverse)
   "Sort the summary buffer by subject alphabetically.  `Re:'s are ignored.
 If `case-fold-search' is non-nil, case of letters is ignored.
@@ -11287,46 +11745,51 @@
 		      (format "these %d articles" (length articles))
 		    "this article")))
 	 (to-newsgroup
-	  (cond
-	   ((null split-name)
-	    (gnus-completing-read-with-default
-	     default prom
-	     gnus-active-hashtb
-	     'gnus-valid-move-group-p
-	     nil prefix
-	     'gnus-group-history))
-	   ((= 1 (length split-name))
-	    (gnus-completing-read-with-default
-	     (car split-name) prom
-	     gnus-active-hashtb
-	     'gnus-valid-move-group-p
-	     nil nil
-	     'gnus-group-history))
-	   (t
-	    (gnus-completing-read-with-default
-	     nil prom
-	     (mapcar (lambda (el) (list el))
-		     (nreverse split-name))
-	     nil nil nil
-	     'gnus-group-history))))
-	 (to-method (gnus-server-to-method (gnus-group-method to-newsgroup))))
+	  (let (active group)
+	    (when (or (null split-name) (= 1 (length split-name)))
+	      (setq active (gnus-make-hashtable (length gnus-active-hashtb)))
+	      (mapatoms (lambda (symbol)
+			  (setq group (symbol-name symbol))
+			  (when (string-match "[^\000-\177]" group)
+			    (setq group (gnus-group-decoded-name group)))
+			  (set (intern group active) group))
+			gnus-active-hashtb))
+	    (cond
+	     ((null split-name)
+	      (gnus-completing-read-with-default
+	       default prom active 'gnus-valid-move-group-p nil prefix
+	       'gnus-group-history))
+	     ((= 1 (length split-name))
+	      (gnus-completing-read-with-default
+	       (car split-name) prom active 'gnus-valid-move-group-p nil nil
+	       'gnus-group-history))
+	     (t
+	      (gnus-completing-read-with-default
+	       nil prom (mapcar 'list (nreverse split-name)) nil nil nil
+	       'gnus-group-history)))))
+	 (to-method (gnus-server-to-method (gnus-group-method to-newsgroup)))
+	 encoded)
     (when to-newsgroup
       (if (or (string= to-newsgroup "")
 	      (string= to-newsgroup prefix))
 	  (setq to-newsgroup default))
       (unless to-newsgroup
 	(error "No group name entered"))
-      (or (gnus-active to-newsgroup)
-	  (gnus-activate-group to-newsgroup nil nil to-method)
+      (setq encoded (mm-encode-coding-string
+		     to-newsgroup
+		     (gnus-group-name-charset to-method to-newsgroup)))
+      (or (gnus-active encoded)
+	  (gnus-activate-group encoded nil nil to-method)
 	  (if (gnus-y-or-n-p (format "No such group: %s.  Create it? "
 				     to-newsgroup))
-	      (or (and (gnus-request-create-group to-newsgroup to-method)
-		       (gnus-activate-group
-			to-newsgroup nil nil to-method)
-		       (gnus-subscribe-group to-newsgroup))
+	      (or (and (gnus-request-create-group encoded to-method)
+		       (gnus-activate-group encoded nil nil to-method)
+		       (gnus-subscribe-group encoded))
 		  (error "Couldn't create group %s" to-newsgroup)))
-	  (error "No such group: %s" to-newsgroup)))
-    to-newsgroup))
+	  (error "No such group: %s" to-newsgroup))
+      encoded)))
+
+(defvar gnus-summary-save-parts-counter)
 
 (defun gnus-summary-save-parts (type dir n &optional reverse)
   "Save parts matching TYPE to DIR.
@@ -11350,7 +11813,8 @@
       (let ((handles (or gnus-article-mime-handles
 			 (mm-dissect-buffer nil gnus-article-loose-mime)
 			 (and gnus-article-emulate-mime
-			      (mm-uu-dissect)))))
+			      (mm-uu-dissect))))
+	    (gnus-summary-save-parts-counter 1))
 	(when handles
 	  (gnus-summary-save-parts-1 type dir handles reverse)
 	  (unless gnus-article-mime-handles ;; Don't destroy this case.
@@ -11372,10 +11836,11 @@
 		       (mm-handle-disposition handle) 'filename)
 		      (mail-content-type-get
 		       (mm-handle-type handle) 'name)
-		      (concat gnus-newsgroup-name
-			      "." (number-to-string
-				   (cdr gnus-article-current))))))
+		      (format "%s.%d.%d" gnus-newsgroup-name
+			      (cdr gnus-article-current)
+			      gnus-summary-save-parts-counter))))
 		   dir)))
+	(incf gnus-summary-save-parts-counter)
 	(unless (file-exists-p file)
 	  (mm-save-part-to-file handle file))))))
 
@@ -11414,7 +11879,7 @@
 				(lambda (f)
 				  (if (equal f " ")
 				      f
-				    (mm-quote-arg f)))
+				    (shell-quote-argument f)))
 				files " ")))))
 	  (setq ps (cdr ps)))))
     (if (and gnus-view-pseudos (not not-view))
@@ -11530,11 +11995,14 @@
 	    ()				; Malformed head.
 	  (unless (gnus-summary-article-sparse-p (mail-header-number header))
 	    (when (and (stringp id)
-		       (not (string= (gnus-group-real-name group)
-				     (car where))))
-	      ;; If we fetched by Message-ID and the article came
-	      ;; from a different group, we fudge some bogus article
-	      ;; numbers for this article.
+		       (or
+			(not (string= (gnus-group-real-name group)
+				      (car where)))
+			(not (gnus-server-equal gnus-override-method
+						(gnus-group-method group)))))
+	      ;; If we fetched by Message-ID and the article came from
+	      ;; a different group (or server), we fudge some bogus
+	      ;; article numbers for this article.
 	      (mail-header-set-number header gnus-reffed-article-number))
 	    (save-excursion
 	      (set-buffer gnus-summary-buffer)
@@ -11566,8 +12034,8 @@
   ;; Added by Per Abrahamsen <amanda@iesd.auc.dk>.
   (when gnus-summary-selected-face
     (save-excursion
-      (let* ((beg (gnus-point-at-bol))
-	     (end (gnus-point-at-eol))
+      (let* ((beg (point-at-bol))
+	     (end (point-at-eol))
 	     ;; Fix by Mike Dugan <dugan@bucrf16.bu.edu>.
 	     (from (if (get-text-property beg gnus-mouse-face-prop)
 		       beg
@@ -11616,7 +12084,7 @@
 
 (defun gnus-summary-highlight-line ()
   "Highlight current line according to `gnus-summary-highlight'."
-  (let* ((beg (gnus-point-at-bol))
+  (let* ((beg (point-at-bol))
 	 (article (or (gnus-summary-article-number) gnus-current-article))
 	 (score (or (cdr (assq article
 			       gnus-newsgroup-scored))
@@ -11632,7 +12100,7 @@
     (let ((face (funcall (gnus-summary-highlight-line-0))))
       (unless (eq face (get-text-property beg 'face))
 	(gnus-put-text-property-excluding-characters-with-faces
-	 beg (gnus-point-at-eol) 'face
+	 beg (point-at-eol) 'face
 	 (setq face (if (boundp face) (symbol-value face) face)))
 	(when gnus-summary-highlight-line-function
 	  (funcall gnus-summary-highlight-line-function article face))))))
@@ -11640,11 +12108,10 @@
 (defun gnus-update-read-articles (group unread &optional compute)
   "Update the list of read articles in GROUP.
 UNREAD is a sorted list."
-  (let* ((active (or gnus-newsgroup-active (gnus-active group)))
-	 (entry (gnus-gethash group gnus-newsrc-hashtb))
-	 (info (nth 2 entry))
-	 (prev 1)
-	 read)
+  (let ((active (or gnus-newsgroup-active (gnus-active group)))
+	(info (gnus-get-info group))
+	(prev 1)
+	read)
     (if (or (not info) (not active))
 	;; There is no info on this group if it was, in fact,
 	;; killed.  Gnus stores no information on killed groups, so
@@ -11712,8 +12179,7 @@
     (dolist (buffer (buffer-list))
       (when (and (setq buffer (buffer-name buffer))
 		 (string-match "Summary" buffer)
-		 (save-excursion
-		   (set-buffer buffer)
+		 (with-current-buffer buffer
 		   ;; We check that this is, indeed, a summary buffer.
 		   (and (eq major-mode 'gnus-summary-mode)
 			;; Also make sure this isn't bogus.
@@ -11774,7 +12240,7 @@
     (insert "Mime-Version: 1.0\n")
     (widen)
     (when (search-forward "\n--" nil t)
-      (let ((separator (buffer-substring (point) (gnus-point-at-eol))))
+      (let ((separator (buffer-substring (point) (point-at-eol))))
 	(message-narrow-to-head)
 	(message-remove-header "Content-Type")
 	(goto-char (point-max))
@@ -11885,12 +12351,24 @@
     (when gnus-suppress-duplicates
       (gnus-dup-suppress-articles))
 
-    ;; We might want to build some more threads first.
-    (when (and gnus-fetch-old-headers
-	       (eq gnus-headers-retrieved-by 'nov))
-      (if (eq gnus-fetch-old-headers 'invisible)
-	  (gnus-build-all-threads)
-	(gnus-build-old-threads)))
+    (if (and gnus-fetch-old-headers
+	     (eq gnus-headers-retrieved-by 'nov))
+	;; We might want to build some more threads first.
+	(if (eq gnus-fetch-old-headers 'invisible)
+	    (gnus-build-all-threads)
+	  (gnus-build-old-threads))
+      ;; Mark the inserted articles that are unread as unread.
+      (setq gnus-newsgroup-unreads
+	    (gnus-sorted-nunion
+	     gnus-newsgroup-unreads
+	     (gnus-sorted-nintersection
+	      (gnus-list-of-unread-articles gnus-newsgroup-name)
+	      articles)))
+      ;; Mark the inserted articles as selected so that the information
+      ;; of the marks having been changed by a user may be updated when
+      ;; exiting this group.  See `gnus-summary-update-info'.
+      (dolist (art articles)
+	(setq gnus-newsgroup-unselected (delq art gnus-newsgroup-unselected))))
     ;; Let the Gnus agent mark articles as read.
     (when gnus-agent
       (gnus-agent-get-undownloaded-list))
@@ -11950,8 +12428,7 @@
 		      (read-string
 		       (format
 			"How many articles from %s (%s %d): "
-			(gnus-limit-string
-			 (gnus-group-decoded-name gnus-newsgroup-name) 35)
+			(gnus-group-decoded-name gnus-newsgroup-name)
 			(if initial "max" "default")
 			len)
 		       (if initial
@@ -11994,7 +12471,7 @@
 	  (push i new)
 	  (decf i))
 	(if (not new)
-	    (message "No gnus is bad news.")
+	    (message "No gnus is bad news")
 	  (gnus-summary-insert-articles new)
 	  (setq gnus-newsgroup-unreads
 		(gnus-sorted-nunion gnus-newsgroup-unreads new))