Synch with `t-gnus-6_14'.
[elisp/gnus.git-] / lisp / gnus-sum.el
index 31d99d9..3d3f5e9 100644 (file)
@@ -1,8 +1,11 @@
-;;; gnus-sum.el --- summary mode commands for Gnus
-;; Copyright (C) 1996,97,98,99 Free Software Foundation, Inc.
+;;; gnus-sum.el --- summary mode commands for Semi-gnus
+;; Copyright (C) 1996, 1997, 1998, 1999, 2000
+;;        Free Software Foundation, Inc.
 
 ;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
-;; Keywords: news
+;;         MORIOKA Tomohiko <morioka@jaist.ac.jp>
+;;         Katsumi Yamaoka  <yamaoka@jpl.org>
+;; Keywords: mail, news, MIME
 
 ;; This file is part of GNU Emacs.
 
 (require 'gnus-int)
 (require 'gnus-undo)
 (require 'gnus-util)
-(require 'mm-decode)
+(require 'mime-view)
+
+(eval-when-compile
+  (require 'mime-play)
+  (require 'static))
+
+(eval-and-compile
+  (autoload 'gnus-cache-articles-in-group "gnus-cache")
+  (autoload 'pgg-decrypt-region "pgg" nil t)
+  (autoload 'pgg-verify-region "pgg" nil t))
+
 (autoload 'gnus-summary-limit-include-cached "gnus-cache" nil t)
+(autoload 'gnus-set-summary-default-charset "gnus-i18n" nil t)
 
 (defcustom gnus-kill-summary-on-exit t
   "*If non-nil, kill the summary buffer when you exit from it.
@@ -172,9 +186,11 @@ This variable will only be used if the value of
 This applies to marking commands as well as other commands that
 \"naturally\" select the next article, like, for instance, `SPC' at
 the end of an article.
-If nil, only the marking commands will go to the next (un)read 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, the marking commands do NOT go to the next unread article
+(they go to the next article instead).  If `never', commands that
+usually go to the next unread article, will go to the next article,
+whether it is read or not."
   :group 'gnus-summary-marks
   :link '(custom-manual "(gnus)Setting Marks")
   :type '(choice (const :tag "off" nil)
@@ -274,6 +290,14 @@ in some newsgroups, set the variable to nil in
                 (function-item gnus-summary-first-unread-article)
                 (function-item gnus-summary-best-unread-article)))
 
+(defcustom gnus-dont-select-after-jump-to-other-group nil
+  "If non-nil, don't select the first unread article after entering the
+other group by the command `gnus-summary-jump-to-other-group'.  If nil,
+it is depend on the value of `gnus-auto-select-first' whether to select
+or not."
+  :group 'gnus-group-select
+  :type 'boolean)
+
 (defcustom gnus-auto-select-next t
   "*If non-nil, offer to go to the next group from the end of the previous.
 If the value is t and the next newsgroup is empty, Gnus will exit
@@ -340,6 +364,13 @@ variable."
   :group 'gnus-article-various
   :type 'boolean)
 
+(defcustom gnus-show-mime t
+  "*If non-nil, do mime processing of articles.
+The articles will simply be fed to the function given by
+`gnus-article-display-method-for-mime'."
+  :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."
@@ -690,13 +721,14 @@ is not run if `gnus-visual' is nil."
   :group 'gnus-summary-visual
   :type 'hook)
 
-(defcustom gnus-parse-headers-hook nil
+(defcustom gnus-parse-headers-hook '(gnus-set-summary-default-charset)
   "*A hook called before parsing the headers."
   :group 'gnus-various
   :type 'hook)
 
 (defcustom gnus-exit-group-hook nil
-  "*A hook called when exiting (not quitting) summary mode."
+  "*A hook called when exiting summary mode.
+This hook is not called from the non-updating exit commands like `Q'."
   :group 'gnus-various
   :type 'hook)
 
@@ -757,6 +789,9 @@ automatically when it is selected."
      . gnus-summary-high-unread-face)
     ((and (< score default) (= mark gnus-unread-mark))
      . gnus-summary-low-unread-face)
+    ((and (memq article gnus-newsgroup-incorporated)
+         (= mark gnus-unread-mark))
+     . gnus-summary-incorporated-face)
     ((= mark gnus-unread-mark)
      . gnus-summary-normal-unread-face)
     ((and (> score default) (memq mark (list gnus-downloadable-mark
@@ -795,7 +830,8 @@ mark:    The articles mark."
 The function is called with one parameter, the article header vector,
 which it may alter in any way.")
 
-(defvar gnus-decode-encoded-word-function 'mail-decode-encoded-word-string
+(defvar gnus-decode-encoded-word-function
+  (mime-find-field-decoder 'From 'nov)
   "Variable that says which function should be used to decode a string with encoded words.")
 
 (defcustom gnus-extra-headers nil
@@ -835,7 +871,7 @@ default charset will be used instead."
   :type '(repeat symbol)
   :group 'gnus-charset)
 
-(defcustom gnus-group-ignored-charsets-alist 
+(defcustom gnus-group-ignored-charsets-alist
   '(("alt\\.chinese\\.text" iso-8859-1))
   "Alist of regexps (to match group names) and charsets that should be ignored.
 When these charsets are used in the \"charset\" parameter, the
@@ -851,10 +887,29 @@ This variable uses the same syntax as `gnus-emphasis-alist'."
                       (repeat (list (regexp :tag "Highlight regexp")
                                     (number :tag "Group for entire word" 0)
                                     (number :tag "Group for displayed part" 0)
-                                    (symbol :tag "Face" 
+                                    (symbol :tag "Face"
                                             gnus-emphasis-highlight-words)))))
   :group 'gnus-summary-visual)
 
+(defcustom gnus-use-wheel nil
+  "Use Intelli-mouse on summary movement"
+  :type 'boolean
+  :group 'gnus-summary-maneuvering)
+
+(defcustom gnus-wheel-scroll-amount '(5 . 1)
+  "Amount to scroll messages by spinning the mouse wheel.
+This is actually a cons cell, where the first item is the amount to scroll
+on a normal wheel event, and the second is the amount to scroll when the
+wheel is moved with the shift key depressed."
+  :type '(cons (integer :tag "Shift") integer)
+  :group 'gnus-summary-maneuvering)
+
+(defcustom gnus-wheel-edge-resistance 2
+  "How hard it should be to change the current article
+by moving the mouse over the edge of the article window."
+  :type 'integer
+  :group 'gnus-summary-maneuvering)
+
 (defcustom gnus-summary-show-article-charset-alist
   nil
   "Alist of number and charset.
@@ -870,6 +925,17 @@ For example: ((1 . cn-gb-2312) (2 . big5))."
   :type 'boolean
   :group 'gnus-summary-marks)
 
+(defcustom gnus-alter-articles-to-read-function nil
+  "Function to be called to alter the list of articles to be selected."
+  :type 'function
+  :group 'gnus-summary)
+
+(defcustom gnus-orphan-score nil
+  "*All orphans get this score added.  Set in the score file."
+  :group 'gnus-score-default
+  :type '(choice (const nil)
+                integer))
+
 ;;; Internal variables
 
 (defvar gnus-article-mime-handles nil)
@@ -908,9 +974,10 @@ For example: ((1 . cn-gb-2312) (2 . big5))."
     (?S ,(macroexpand '(mail-header-subject gnus-tmp-header)) ?s)
     (?s gnus-tmp-subject-or-nil ?s)
     (?n gnus-tmp-name ?s)
-    (?A (car (cdr (funcall gnus-extract-address-components gnus-tmp-from)))
-       ?s)
-    (?a (or (car (funcall gnus-extract-address-components gnus-tmp-from))
+    (?A (std11-address-string
+        (car (mime-entity-read-field gnus-tmp-header 'From))) ?s)
+    (?a (or (std11-full-name-string
+            (car (mime-entity-read-field gnus-tmp-header 'From)))
            gnus-tmp-from) ?s)
     (?F gnus-tmp-from ?s)
     (?x ,(macroexpand '(mail-header-xref gnus-tmp-header)) ?s)
@@ -942,9 +1009,9 @@ For example: ((1 . cn-gb-2312) (2 . big5))."
        ?c)
     (?u gnus-tmp-user-defined ?s)
     (?P (gnus-pick-line-number) ?d))
-  "An alist of format specifications that can appear in summary lines,
-and what variables they correspond with, along with the type of the
-variable (string, integer, character, etc).")
+  "An alist of format specifications that can appear in summary lines.
+These are paired with what variables they correspond with, along with
+the type of the variable (string, integer, character, etc).")
 
 (defvar gnus-summary-dummy-line-format-alist
   `((?S gnus-tmp-subject ?s)
@@ -972,6 +1039,11 @@ variable (string, integer, character, etc).")
 (defvar gnus-last-search-regexp nil
   "Default regexp for article search command.")
 
+(defvar gnus-summary-search-article-matched-data nil
+  "Last matched data of article search command.  It is the local variable
+in `gnus-article-buffer' which consists of the list of start position,
+end position and text.")
+
 (defvar gnus-last-shell-command nil
   "Default shell command on article.")
 
@@ -1041,6 +1113,9 @@ variable (string, integer, character, etc).")
 (defvar gnus-newsgroup-scored nil
   "List of scored articles in the current newsgroup.")
 
+(defvar gnus-newsgroup-incorporated nil
+  "List of incorporated articles in the current newsgroup.")
+
 (defvar gnus-newsgroup-headers nil
   "List of article headers in the current newsgroup.")
 
@@ -1087,6 +1162,7 @@ variable (string, integer, character, etc).")
     gnus-score-alist gnus-current-score-file
     (gnus-summary-expunge-below . global)
     (gnus-summary-mark-below . global)
+    (gnus-orphan-score . global)
     gnus-newsgroup-active gnus-scores-exclude-files
     gnus-newsgroup-history gnus-newsgroup-ancient
     gnus-newsgroup-sparse gnus-newsgroup-process-stack
@@ -1096,55 +1172,17 @@ variable (string, integer, character, etc).")
     gnus-cache-removable-articles gnus-newsgroup-cached
     gnus-newsgroup-data gnus-newsgroup-data-reverse
     gnus-newsgroup-limit gnus-newsgroup-limits
-    gnus-newsgroup-charset)
+    gnus-newsgroup-charset
+    gnus-newsgroup-incorporated)
   "Variables that are buffer-local to the summary buffers.")
 
 ;; Byte-compiler warning.
 (defvar gnus-article-mode-map)
 
-;; MIME stuff.
-
-(defvar gnus-decode-encoded-word-methods
-  '(mail-decode-encoded-word-string)
-  "List of methods used to decode encoded words.
-
-This variable is a list of FUNCTION or (REGEXP . FUNCTION).  If item is
-FUNCTION, FUNCTION will be apply to all newsgroups.  If item is a
-(REGEXP . FUNCTION), FUNCTION will be only apply to thes newsgroups
-whose names match REGEXP.
-
-For example:
-((\"chinese\" . gnus-decode-encoded-word-string-by-guess)
- mail-decode-encoded-word-string
- (\"chinese\" . rfc1843-decode-string))
-")
-
-(defvar gnus-decode-encoded-word-methods-cache nil)
-
-(defun gnus-multi-decode-encoded-word-string (string)
-  "Apply the functions from `gnus-encoded-word-methods' that match."
-  (unless (and gnus-decode-encoded-word-methods-cache
-              (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)
-
 ;; Subject simplification.
 
 (defun gnus-simplify-whitespace (str)
-  "Remove excessive whitespace."
+  "Remove excessive whitespace from STR."
   (let ((mystr str))
     ;; Multiple spaces.
     (while (string-match "[ \t][ \t]+" mystr)
@@ -1197,7 +1235,7 @@ 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."
+`gnus-simplify-subject-fuzzy-regexp'."
   (let ((case-fold-search t)
        (modified-tick))
     (gnus-simplify-buffer-fuzzy-step "\t" " ")
@@ -1321,6 +1359,8 @@ increase the score of each group you read."
     "\M-\C-h" gnus-summary-hide-thread
     "\M-\C-f" gnus-summary-next-thread
     "\M-\C-b" gnus-summary-prev-thread
+    [(meta down)] gnus-summary-next-thread
+    [(meta up)] gnus-summary-prev-thread
     "\M-\C-u" gnus-summary-up-thread
     "\M-\C-d" gnus-summary-down-thread
     "&" gnus-summary-execute-command
@@ -1341,6 +1381,7 @@ increase the score of each group you read."
     "\M-g" gnus-summary-rescan-group
     "w" gnus-summary-stop-page-breaking
     "\C-c\C-r" gnus-summary-caesar-message
+    "\M-t" gnus-summary-toggle-mime
     "f" gnus-summary-followup
     "F" gnus-summary-followup-with-original
     "C" gnus-summary-cancel-article
@@ -1362,9 +1403,10 @@ increase the score of each group you read."
     "a" gnus-summary-post-news
     "x" gnus-summary-limit-to-unread
     "s" gnus-summary-isearch-article
-    "t" gnus-summary-toggle-header
+    "t" gnus-article-toggle-headers
     "g" gnus-summary-show-article
     "l" gnus-summary-goto-last-article
+    "v" gnus-summary-preview-mime-message
     "\C-c\C-v\C-v" gnus-uu-decode-uu-view
     "\C-d" gnus-summary-enter-digest-group
     "\M-\C-d" gnus-summary-read-document
@@ -1380,9 +1422,6 @@ increase the score of each group you read."
     "\M-i" gnus-symbolic-argument
     "h" gnus-summary-select-article-buffer
 
-    "b" gnus-article-view-part
-    "\M-t" gnus-summary-toggle-display-buttonized
-
     "V" gnus-summary-score-map
     "X" gnus-uu-extract-map
     "S" gnus-summary-send-map)
@@ -1431,7 +1470,7 @@ increase the score of each group you read."
     "T" gnus-summary-limit-include-thread
     "d" gnus-summary-limit-exclude-dormant
     "t" gnus-summary-limit-to-age
-    "x" gnus-summary-limit-to-extra 
+    "x" gnus-summary-limit-to-extra
     "E" gnus-summary-limit-include-expunged
     "c" gnus-summary-limit-exclude-childless-dormant
     "C" gnus-summary-limit-mark-excluded-as-read)
@@ -1479,6 +1518,7 @@ increase the score of each group you read."
     "c" gnus-summary-catchup-and-exit
     "C" gnus-summary-catchup-all-and-exit
     "E" gnus-summary-exit-no-update
+    "J" gnus-summary-jump-to-other-group
     "Q" gnus-summary-exit
     "Z" gnus-summary-exit
     "n" gnus-summary-catchup-and-goto-next-group
@@ -1508,7 +1548,9 @@ increase the score of each group you read."
     "g" gnus-summary-show-article
     "s" gnus-summary-isearch-article
     "P" gnus-summary-print-article
-    "t" gnus-article-babel)
+    "t" gnus-article-babel
+    "d" gnus-summary-decrypt-article
+    "v" gnus-summary-verify-article)
 
   (gnus-define-keys (gnus-summary-wash-map "W" gnus-summary-mode-map)
     "b" gnus-article-add-buttons
@@ -1519,18 +1561,20 @@ increase the score of each group you read."
     "Q" gnus-article-fill-long-lines
     "C" gnus-article-capitalize-sentences
     "c" gnus-article-remove-cr
-    "q" gnus-article-de-quoted-unreadable
+    "Z" gnus-article-decode-HZ
     "f" gnus-article-display-x-face
     "l" gnus-summary-stop-page-breaking
     "r" gnus-summary-caesar-message
-    "t" gnus-article-hide-headers
+    "t" gnus-article-toggle-headers
     "v" gnus-summary-verbose-headers
+    "m" gnus-summary-toggle-mime
     "H" gnus-article-strip-headers-in-body
-    "d" gnus-article-treat-dumbquotes)
+    "d" gnus-article-treat-dumbquotes
+    "s" gnus-smiley-display)
 
   (gnus-define-keys (gnus-summary-wash-hide-map "W" gnus-summary-wash-map)
     "a" gnus-article-hide
-    "h" gnus-article-hide-headers
+    "h" gnus-article-toggle-headers
     "b" gnus-article-hide-boring-headers
     "s" gnus-article-hide-signature
     "c" gnus-article-hide-citation
@@ -1547,12 +1591,6 @@ increase the score of each group you read."
     "c" gnus-article-highlight-citation
     "s" gnus-article-highlight-signature)
 
-  (gnus-define-keys (gnus-summary-wash-mime-map "M" gnus-summary-wash-map)
-    "w" gnus-article-decode-mime-words
-    "c" gnus-article-decode-charset
-    "v" gnus-mime-view-all-parts
-    "b" gnus-article-view-part)
-
   (gnus-define-keys (gnus-summary-wash-time-map "T" gnus-summary-wash-map)
     "z" gnus-article-date-ut
     "u" gnus-article-date-ut
@@ -1654,7 +1692,7 @@ increase the score of each group you read."
     (let ((innards
            '(("Hide"
               ["All" gnus-article-hide t]
-              ["Headers" gnus-article-hide-headers t]
+              ["Headers" gnus-article-toggle-headers t]
               ["Signature" gnus-article-hide-signature t]
               ["Citation" gnus-article-hide-citation t]
              ["List identifiers" gnus-article-hide-list-identifiers t]
@@ -1666,11 +1704,6 @@ increase the score of each group you read."
               ["Headers" gnus-article-highlight-headers t]
               ["Signature" gnus-article-highlight-signature t]
               ["Citation" gnus-article-highlight-citation t])
-            ("MIME"
-             ["Words" gnus-article-decode-mime-words t]
-             ["Charset" gnus-article-decode-charset t]
-             ["QP" gnus-article-de-quoted-unreadable t]
-             ["View all" gnus-mime-view-all-parts t])
              ("Date"
               ["Local" gnus-article-date-local t]
               ["ISO8601" gnus-article-date-iso8601 t]
@@ -1695,14 +1728,15 @@ increase the score of each group you read."
              ["Capitalize sentences" gnus-article-capitalize-sentences t]
               ["CR" gnus-article-remove-cr t]
               ["Show X-Face" gnus-article-display-x-face t]
-              ["Quoted-Printable" gnus-article-de-quoted-unreadable 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]
+              ["Toggle MIME" gnus-summary-toggle-mime t]
               ["Verbose header" gnus-summary-verbose-headers t]
               ["Toggle header" gnus-summary-toggle-header t]
+             ["Toggle smileys" gnus-smiley-display t]
              ["HZ" gnus-article-decode-HZ t])
              ("Output"
               ["Save in default format" gnus-summary-save-article t]
@@ -2061,6 +2095,9 @@ The following commands are available:
   (gnus-summary-set-display-table)
   (gnus-set-default-directory)
   (setq gnus-newsgroup-name group)
+  (unless (gnus-news-group-p group)
+    (setq gnus-newsgroup-incorporated
+         (nnmail-new-mail-numbers (gnus-group-real-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)
@@ -2069,7 +2106,6 @@ The following commands are available:
   (make-local-hook 'pre-command-hook)
   (add-hook 'pre-command-hook 'gnus-set-global-variables nil t)
   (gnus-run-hooks 'gnus-summary-mode-hook)
-  (mm-enable-multibyte)
   (gnus-update-format-specifications nil 'summary 'summary-mode 'summary-dummy)
   (gnus-update-summary-mark-positions))
 
@@ -2122,7 +2158,7 @@ The following commands are available:
   `(nth 3 ,data))
 
 (defmacro gnus-data-set-header (data header)
-  `(setf (nth 3 ,data) ,header))
+  `(setcar (nthcdr 3 ,data) ,header))
 
 (defmacro gnus-data-level (data)
   `(nth 4 ,data))
@@ -2406,12 +2442,13 @@ marks of articles."
 
 (defun gnus-restore-hidden-threads-configuration (config)
   "Restore hidden threads configuration from CONFIG."
-  (let (point buffer-read-only)
-    (while (setq point (pop config))
-      (when (and (< point (point-max))
-                (goto-char point)
-                (eq (char-after) ?\n))
-       (subst-char-in-region point (1+ point) ?\n ?\r)))))
+  (save-excursion
+    (let (point buffer-read-only)
+      (while (setq point (pop config))
+       (when (and (< point (point-max))
+                  (goto-char point)
+                  (eq (char-after) ?\n))
+         (subst-char-in-region point (1+ point) ?\n ?\r))))))
 
 ;; Various summary mode internalish functions.
 
@@ -2421,9 +2458,10 @@ marks of articles."
   (gnus-summary-next-page nil t))
 
 (defun gnus-summary-set-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."
 
   ;; We start from the standard display table, if any.
   (let ((table (or (copy-sequence standard-display-table)
@@ -2467,9 +2505,9 @@ marks of articles."
       t)))
 
 (defun gnus-set-global-variables ()
-  ;; Set the global equivalents of the summary buffer-local variables
-  ;; to the latest values they had.  These reflect the summary buffer
-  ;; that was in action when the last article was fetched.
+  "Set the global equivalents of the buffer-local variables.
+They are set to the latest values they had.  These reflect the summary
+buffer that was in action when the last article was fetched."
   (when (eq major-mode 'gnus-summary-mode)
     (setq gnus-summary-buffer (current-buffer))
     (let ((name gnus-newsgroup-name)
@@ -2547,7 +2585,8 @@ marks of articles."
        (let ((gnus-summary-line-format-spec spec)
              (gnus-newsgroup-downloadable '((0 . t))))
          (gnus-summary-insert-line
-          [0 "" "" "" "" "" 0 0 "" nil]  0 nil 128 t nil "" nil 1)
+          (make-full-mail-header 0 "" "nobody" "" "" "" 0 0 "" nil)
+          0 nil 128 t nil "" nil 1)
          (goto-char (point-min))
          (setq pos (list (cons 'unread (and (search-forward "\200" nil t)
                                             (- (point) 2)))))
@@ -2574,10 +2613,8 @@ marks of articles."
 (defun gnus-summary-from-or-to-or-newsgroups (header)
   (let ((to (cdr (assq 'To (mail-header-extra header))))
        (newsgroups (cdr (assq 'Newsgroups (mail-header-extra header))))
-       (mail-parse-charset gnus-newsgroup-charset)
-       (mail-parse-ignored-charsets 
-        (save-excursion (set-buffer gnus-summary-buffer)
-                        gnus-newsgroup-ignored-charsets)))
+       (default-mime-charset (with-current-buffer gnus-summary-buffer
+                               default-mime-charset)))
     (cond
      ((and to
           gnus-ignored-from-addresses
@@ -2644,7 +2681,7 @@ marks of articles."
       (setq gnus-tmp-name gnus-tmp-from))
     (unless (numberp gnus-tmp-lines)
       (setq gnus-tmp-lines 0))
-    (gnus-put-text-property
+    (gnus-put-text-property-excluding-characters-with-faces
      (point)
      (progn (eval gnus-summary-line-format-spec) (point))
      'gnus-number gnus-tmp-number)
@@ -2654,7 +2691,7 @@ marks of articles."
       (forward-line 1))))
 
 (defun gnus-summary-update-line (&optional dont-update)
-  ;; Update summary line after change.
+  "Update summary line after change."
   (when (and gnus-summary-default-score
             (not gnus-summary-inhibit-highlight))
     (let* ((gnus-summary-inhibit-highlight t) ; Prevent recursion.
@@ -2758,6 +2795,26 @@ If NO-DISPLAY, don't generate a summary buffer."
        (setq group nil)))
     result))
 
+(defun gnus-summary-jump-to-other-group (group &optional show-all)
+  "Directly jump to the other GROUP from summary buffer.
+If SHOW-ALL is non-nil, already read articles are also listed."
+  (interactive
+   (if (eq gnus-summary-buffer (current-buffer))
+       (list (completing-read
+             "Group: " gnus-active-hashtb nil t
+             (when (and gnus-newsgroup-name
+                        (string-match "[.:][^.:]+$" gnus-newsgroup-name))
+               (substring gnus-newsgroup-name 0 (1+ (match-beginning 0))))
+             'gnus-group-history)
+            current-prefix-arg)
+     (error "%s must be invoked from a gnus summary buffer." this-command)))
+  (unless (or (zerop (length group))
+             (and gnus-newsgroup-name
+                  (string-equal gnus-newsgroup-name group)))
+    (gnus-summary-exit)
+    (gnus-summary-read-group group show-all
+                            gnus-dont-select-after-jump-to-other-group)))
+
 (defun gnus-summary-read-group-1 (group show-all no-article
                                        kill-buffer no-display
                                        &optional select-articles)
@@ -2965,7 +3022,8 @@ If NO-DISPLAY, don't generate a summary buffer."
   "Query where the respool algorithm would put this article."
   (interactive)
   (gnus-summary-select-article)
-  (message (gnus-general-simplify-subject (gnus-summary-article-subject))))
+  (message "%s"
+          (gnus-general-simplify-subject (gnus-summary-article-subject))))
 
 (defun gnus-gather-threads-by-subject (threads)
   "Gather threads by looking at Subject headers."
@@ -3256,38 +3314,31 @@ Returns HEADER if it was entered in the DEPENDENCIES.  Returns nil otherwise."
        header)
 
     ;; overview: [num subject from date id refs chars lines misc]
-    (unwind-protect
-       (progn
-         (narrow-to-region (point) eol)
-         (unless (eobp)
-           (forward-char))
-
-         (setq header
-               (make-full-mail-header
-                number                 ; number
-                (funcall gnus-decode-encoded-word-function
-                         (nnheader-nov-field)) ; subject
-                (funcall gnus-decode-encoded-word-function
-                         (nnheader-nov-field)) ; from
-                (nnheader-nov-field)   ; date
-                (nnheader-nov-read-message-id) ; id
-                (nnheader-nov-field)   ; refs
-                (nnheader-nov-read-integer) ; chars
-                (nnheader-nov-read-integer) ; lines
-                (unless (eobp)
-                  (nnheader-nov-field)) ; misc
-                (nnheader-nov-parse-extra)))) ; extra
-
-      (widen))
+    (unless (eobp)
+      (forward-char))
+
+    (setq header
+         (make-full-mail-header
+          number                               ; number
+          (nnheader-nov-field)                 ; subject
+          (nnheader-nov-field)                 ; from
+          (nnheader-nov-field)                 ; date
+          (nnheader-nov-read-message-id)       ; id
+          (nnheader-nov-field)                 ; refs
+          (nnheader-nov-read-integer)          ; chars
+          (nnheader-nov-read-integer)          ; lines
+          (unless (eobp)
+            (nnheader-nov-field))              ; misc
+          (nnheader-nov-parse-extra)))         ; extra
 
     (when gnus-alter-header-function
       (funcall gnus-alter-header-function header))
     (gnus-dependencies-add-header header dependencies force-new)))
 
 (defun gnus-build-get-header (id)
-  ;; Look through the buffer of NOV lines and find the header to
-  ;; ID.  Enter this line into the dependencies hash table, and return
-  ;; the id of the parent article (if any).
+  "Look through the buffer of NOV lines and find the header to ID.
+Enter this line into the dependencies hash table, and return
+the id of the parent article (if any)."
   (let ((deps gnus-newsgroup-dependencies)
        found header)
     (prog1
@@ -3369,17 +3420,19 @@ Returns HEADER if it was entered in the DEPENDENCIES.  Returns nil otherwise."
        (memq article gnus-newsgroup-expirable)
        ;; Only insert the Subject string when it's different
        ;; from the previous Subject string.
-       (if (gnus-subject-equal
-           (condition-case ()
-               (mail-header-subject
-                (gnus-data-header
-                 (cadr
-                  (gnus-data-find-list
-                   article
-                   (gnus-data-list t)))))
-             ;; Error on the side of excessive subjects.
-             (error ""))
-           (mail-header-subject header))
+       (if (and
+           gnus-show-threads
+           (gnus-subject-equal
+            (condition-case ()
+                (mail-header-subject
+                 (gnus-data-header
+                  (cadr
+                   (gnus-data-find-list
+                    article
+                    (gnus-data-list t)))))
+              ;; Error on the side of excessive subjects.
+              (error ""))
+            (mail-header-subject header)))
           ""
         (mail-header-subject header))
        nil (cdr (assq article gnus-newsgroup-scored))
@@ -3593,7 +3646,6 @@ If LINE, insert the rebuilt thread starting on line LINE."
                  (while thread
                    (gnus-remove-thread-1 (car thread))
                    (setq thread (cdr thread))))
-             (gnus-summary-show-all-threads)
              (gnus-remove-thread-1 thread))))))))
 
 (defun gnus-remove-thread-1 (thread)
@@ -3605,6 +3657,7 @@ If LINE, insert the rebuilt thread starting on line LINE."
       (gnus-remove-thread-1 (pop thread)))
     (when (setq d (gnus-data-find number))
       (goto-char (gnus-data-pos d))
+      (gnus-summary-show-thread)
       (gnus-data-remove
        number
        (- (gnus-point-at-bol)
@@ -3633,12 +3686,12 @@ If LINE, insert the rebuilt thread starting on line LINE."
 
 ;; Written by Hallvard B Furuseth <h.b.furuseth@usit.uio.no>.
 (defmacro gnus-thread-header (thread)
-  ;; Return header of first article in THREAD.
-  ;; Note that THREAD must never, ever be anything else than a variable -
-  ;; using some other form will lead to serious barfage.
+  "Return header of first article in THREAD.
+Note that THREAD must never, ever be anything else than a variable -
+using some other form will lead to serious barfage."
   (or (symbolp thread) (signal 'wrong-type-argument '(symbolp thread)))
   ;; (8% speedup to gnus-summary-prepare, just for fun :-)
-  (list 'byte-code "\10\211:\203\17\0\211@;\203\16\0A@@\207" 
+  (list 'byte-code "\10\211:\203\17\0\211@;\203\16\0A@@\207"
        (vector thread) 2))
 
 (defsubst gnus-article-sort-by-number (h1 h2)
@@ -3674,14 +3727,15 @@ If LINE, insert the rebuilt thread starting on line LINE."
 (defsubst gnus-article-sort-by-author (h1 h2)
   "Sort articles by root author."
   (string-lessp
-   (let ((extract (funcall
-                  gnus-extract-address-components
-                  (mail-header-from h1))))
-     (or (car extract) (cadr extract) ""))
-   (let ((extract (funcall
-                  gnus-extract-address-components
-                  (mail-header-from h2))))
-     (or (car extract) (cadr extract) ""))))
+   (let ((addr (car (mime-entity-read-field h1 'From))))
+     (or (std11-full-name-string addr)
+        (std11-address-string addr)
+        ""))
+   (let ((addr (car (mime-entity-read-field h2 'From))))
+     (or (std11-full-name-string addr)
+        (std11-address-string addr)
+        ""))
+   ))
 
 (defun gnus-thread-sort-by-author (h1 h2)
   "Sort threads by root author."
@@ -4055,13 +4109,17 @@ or a straight list of headers."
                    gnus-list-identifiers
                  (mapconcat 'identity gnus-list-identifiers " *\\|"))))
     (dolist (header gnus-newsgroup-headers)
-      (when (string-match (concat "\\(Re: +\\)?\\(" regexp " *\\)")
+      (when (string-match (concat "\\(\\(\\(Re: +\\)?\\(" regexp
+                                 " *\\)\\)+\\(Re: +\\)?\\)")
                          (mail-header-subject header))
        (mail-header-set-subject
         header (concat (substring (mail-header-subject header)
-                                  0 (match-beginning 2))
+                                  0 (match-beginning 1))
+                       (or
+                        (match-string 3 (mail-header-subject header))
+                        (match-string 5 (mail-header-subject header)))
                        (substring (mail-header-subject header)
-                                  (match-end 2))))))))
+                                  (match-end 1))))))))
 
 (defun gnus-select-newsgroup (group &optional read-all select-articles)
   "Select newsgroup GROUP.
@@ -4105,8 +4163,10 @@ If SELECT-ARTICLES, only select those articles from GROUP."
       (gnus-adjust-marked-articles info))
 
     ;; Kludge to avoid having cached articles nixed out in virtual groups.
-    (when (gnus-virtual-group-p group)
-      (setq cached gnus-newsgroup-cached))
+    (setq cached
+         (if (gnus-virtual-group-p group)
+             gnus-newsgroup-cached
+           (gnus-cache-articles-in-group group)))
 
     (setq gnus-newsgroup-unreads
          (gnus-set-difference
@@ -4137,26 +4197,16 @@ If SELECT-ARTICLES, only select those articles from GROUP."
       ;; Retrieve the headers and read them in.
       (gnus-message 5 "Fetching headers for %s..." gnus-newsgroup-name)
       (setq gnus-newsgroup-headers
-           (if (eq 'nov
-                   (setq gnus-headers-retrieved-by
-                         (gnus-retrieve-headers
-                          articles gnus-newsgroup-name
-                          ;; We might want to fetch old headers, but
-                          ;; not if there is only 1 article.
-                          (and (or (and
-                                    (not (eq gnus-fetch-old-headers 'some))
-                                    (not (numberp gnus-fetch-old-headers)))
-                                   (> (length articles) 1))
-                               gnus-fetch-old-headers))))
-               (gnus-get-newsgroup-headers-xover
-                articles nil nil gnus-newsgroup-name t)
-             (gnus-get-newsgroup-headers)))
+           (gnus-retrieve-parsed-headers
+            articles gnus-newsgroup-name
+            ;; We might want to fetch old headers, but
+            ;; not if there is only 1 article.
+            (and (or (and (not (eq gnus-fetch-old-headers 'some))
+                          (not (numberp gnus-fetch-old-headers)))
+                     (> (length articles) 1))
+                 gnus-fetch-old-headers)))
       (gnus-message 5 "Fetching headers for %s...done" gnus-newsgroup-name)
 
-      ;; Kludge to avoid having cached articles nixed out in virtual groups.
-      (when cached
-       (setq gnus-newsgroup-cached cached))
-
       ;; Suppress duplicates?
       (when gnus-suppress-duplicates
        (gnus-dup-suppress-articles))
@@ -4173,6 +4223,11 @@ If SELECT-ARTICLES, only select those articles from GROUP."
       ;; Removed marked articles that do not exist.
       (gnus-update-missing-marks
        (gnus-sorted-complement fetched-articles articles))
+
+      ;; Kludge to avoid having cached articles nixed out in virtual groups.
+      (when cached
+       (setq gnus-newsgroup-cached cached))
+
       ;; We might want to build some more threads first.
       (when (and gnus-fetch-old-headers
                 (eq gnus-headers-retrieved-by 'nov))
@@ -4202,7 +4257,7 @@ If SELECT-ARTICLES, only select those articles from GROUP."
       (or gnus-newsgroup-headers t)))))
 
 (defun gnus-articles-to-read (group &optional read-all)
-  ;; Find out what articles the user wants to read.
+  "Find out what articles the user wants to read."
   (let* ((articles
          ;; Select all articles if `read-all' is non-nil, or if there
          ;; are no unread articles.
@@ -4230,15 +4285,19 @@ If SELECT-ARTICLES, only select those articles from GROUP."
            (condition-case ()
                (cond
                 ((and (or (<= scored marked) (= scored number))
-                      (numberp gnus-large-newsgroup)
+                      (natnump gnus-large-newsgroup)
                       (> number gnus-large-newsgroup))
-                 (let ((input
-                        (read-string
-                         (format
-                          "How many articles from %s (default %d): "
-                          (gnus-limit-string gnus-newsgroup-name 35)
-                          number))))
-                   (if (string-match "^[ \t]*$" input) number input)))
+                 (let* ((cursor-in-echo-area nil)
+                        (input (read-from-minibuffer
+                                (format
+                                 "How many articles from %s (max %d): "
+                                 (gnus-limit-string gnus-newsgroup-name 35)
+                                 number)
+                                (cons (number-to-string gnus-large-newsgroup)
+                                      0))))
+                   (if (string-match "^[ \t]*$" input)
+                       number
+                     input)))
                 ((and (> scored marked) (< scored number)
                       (> (- scored number) 20))
                  (let ((input
@@ -4269,6 +4328,12 @@ If SELECT-ARTICLES, only select those articles from GROUP."
            (gnus-sorted-intersection
             gnus-newsgroup-unreads
             (gnus-sorted-complement gnus-newsgroup-unreads articles)))
+      (when gnus-alter-articles-to-read-function
+       (setq gnus-newsgroup-unreads
+             (sort
+              (funcall gnus-alter-articles-to-read-function
+                       gnus-newsgroup-name gnus-newsgroup-unreads)
+              '<)))
       articles)))
 
 (defun gnus-killed-articles (killed articles)
@@ -4377,12 +4442,17 @@ If SELECT-ARTICLES, only select those articles from GROUP."
 
        (unless (memq (cdr type) uncompressed)
          (setq list (gnus-compress-sequence (set symbol (sort list '<)) t)))
-       
+
        (when (gnus-check-backend-function
               'request-set-mark gnus-newsgroup-name)
+         ;; propagate flags to server, with the following exceptions:
          ;; uncompressed:s are not proper flags (they are cons cells)
          ;; cache is a internal gnus flag
-         (unless (memq (cdr type) (cons 'cache uncompressed))
+         ;; download are local to one gnus installation (well)
+         ;; unsend are for nndraft groups only
+         ;; xxx: generality of this?  this suits nnimap anyway
+         (unless (memq (cdr type) (append '(cache download unsend)
+                                          uncompressed))
            (let* ((old (cdr (assq (cdr type) (gnus-info-marks info))))
                   (del (gnus-remove-from-range (gnus-copy-sequence old) list))
                   (add (gnus-remove-from-range
@@ -4391,7 +4461,7 @@ If SELECT-ARTICLES, only select those articles from GROUP."
                (push (list add 'add (list (cdr type))) delta-marks))
              (when del
                (push (list del 'del (list (cdr type))) delta-marks)))))
-         
+
        (when list
          (push (cons (cdr type) list) newmarked)))
 
@@ -4399,7 +4469,7 @@ If SELECT-ARTICLES, only select those articles from GROUP."
        (unless (gnus-check-group gnus-newsgroup-name)
          (error "Can't open server for %s" gnus-newsgroup-name))
        (gnus-request-set-mark gnus-newsgroup-name delta-marks))
-         
+
       ;; Enter these new marks into the info of the group.
       (if (nthcdr 3 info)
          (setcar (nthcdr 3 info) newmarked)
@@ -4415,7 +4485,7 @@ If SELECT-ARTICLES, only select those articles from GROUP."
            (setcdr (nthcdr i info) nil)))))))
 
 (defun gnus-set-mode-line (where)
-  "This function sets the mode line of the article or summary buffers.
+  "Set the mode line of the article or summary buffers.
 If WHERE is `summary', the summary mode line format will be used."
   ;; Is this mode line one we keep updated?
   (when (and (memq where gnus-updated-mode-lines)
@@ -4431,7 +4501,11 @@ If WHERE is `summary', the summary mode line format will be used."
        (let* ((mformat (symbol-value
                         (intern
                          (format "gnus-%s-mode-line-format-spec" where))))
-              (gnus-tmp-group-name gnus-newsgroup-name)
+              (gnus-tmp-group-name (gnus-group-name-decode
+                                    gnus-newsgroup-name
+                                    (gnus-group-name-charset
+                                     nil
+                                     gnus-newsgroup-name)))
               (gnus-tmp-article-number (or gnus-current-article 0))
               (gnus-tmp-unread gnus-newsgroup-unreads)
               (gnus-tmp-unread-and-unticked (length gnus-newsgroup-unreads))
@@ -4470,7 +4544,7 @@ If WHERE is `summary', the summary mode line format will be used."
          ;; We might have to chop a bit of the string off...
          (when (> (length mode-string) max-len)
            (setq mode-string
-                 (concat (truncate-string-to-width mode-string (- max-len 3))
+                 (concat (gnus-truncate-string mode-string (- max-len 3))
                          "...")))
          ;; Pad the mode string a bit.
          (setq mode-string (format (format "%%-%ds" max-len) mode-string))))
@@ -4627,7 +4701,7 @@ The resulting hash table is returned, or nil if no Xrefs were found."
                             gnus-newsgroup-dependencies)))
        headers id end ref
        (mail-parse-charset gnus-newsgroup-charset)
-       (mail-parse-ignored-charsets 
+       (mail-parse-ignored-charsets
         (save-excursion (condition-case nil
                             (set-buffer gnus-summary-buffer)
                           (error))
@@ -4639,7 +4713,7 @@ The resulting hash table is returned, or nil if no Xrefs were found."
       (subst-char-in-region (point-min) (point-max) ?\r ?  t)
       (gnus-run-hooks 'gnus-parse-headers-hook)
       (let ((case-fold-search t)
-           in-reply-to header p lines chars)
+           in-reply-to header p lines chars ctype)
        (goto-char (point-min))
        ;; Search to the beginning of the next header.  Error messages
        ;; do not begin with 2 or 3.
@@ -4654,7 +4728,7 @@ The resulting hash table is returned, or nil if no Xrefs were found."
          ;; doesn't always go hand in hand.
          (setq
           header
-          (vector
+          (make-full-mail-header
            ;; Number.
            (prog1
                (read cur)
@@ -4668,21 +4742,20 @@ The resulting hash table is returned, or nil if no Xrefs were found."
            (progn
              (goto-char p)
              (if (search-forward "\nsubject: " nil t)
-                 (funcall gnus-decode-encoded-word-function
-                          (nnheader-header-value))
+                 (buffer-substring (match-end 0) (std11-field-end))
                "(none)"))
            ;; From.
            (progn
              (goto-char p)
              (if (search-forward "\nfrom: " nil t)
-                 (funcall gnus-decode-encoded-word-function
-                          (nnheader-header-value))
+                 (buffer-substring (match-end 0) (std11-field-end))
                "(nobody)"))
            ;; Date.
            (progn
              (goto-char p)
              (if (search-forward "\ndate: " nil t)
-                 (nnheader-header-value) ""))
+                 (buffer-substring (match-end 0) (std11-field-end))
+               ""))
            ;; Message-ID.
            (progn
              (goto-char p)
@@ -4702,11 +4775,11 @@ The resulting hash table is returned, or nil if no Xrefs were found."
                  (progn
                    (setq end (point))
                    (prog1
-                       (nnheader-header-value)
+                       (buffer-substring (match-end 0) (std11-field-end))
                      (setq ref
                            (buffer-substring
                             (progn
-                              (end-of-line)
+                               ;; (end-of-line)
                               (search-backward ">" end t)
                               (1+ (point)))
                             (progn
@@ -4716,7 +4789,9 @@ 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)
-                        (setq in-reply-to (nnheader-header-value))
+                        (setq in-reply-to
+                              (buffer-substring (match-end 0)
+                                                (std11-field-end)))
                         (string-match "<[^>]+>" in-reply-to))
                    (let (ref2)
                      (setq ref (substring in-reply-to (match-beginning 0)
@@ -4746,7 +4821,7 @@ The resulting hash table is returned, or nil if no Xrefs were found."
            (progn
              (goto-char p)
              (and (search-forward "\nxref: " nil t)
-                  (nnheader-header-value)))
+                  (buffer-substring (match-end 0) (std11-field-end))))
            ;; Extra.
            (when gnus-extra-headers
              (let ((extra gnus-extra-headers)
@@ -4755,10 +4830,18 @@ The resulting hash table is returned, or nil if no Xrefs were found."
                  (goto-char p)
                  (when (search-forward
                         (concat "\n" (symbol-name (car extra)) ": ") nil t)
-                   (push (cons (car extra) (nnheader-header-value))
+                   (push (cons (car extra)
+                               (buffer-substring (match-end 0)
+                                                 (std11-field-end)))
                          out))
                  (pop extra))
                out))))
+         (goto-char p)
+         (if (and (search-forward "\ncontent-type: " nil t)
+                  (setq ctype
+                        (buffer-substring (match-end 0) (std11-field-end))))
+             (mime-entity-set-content-type-internal
+              header (mime-parse-Content-Type ctype)))
          (when (equal id ref)
            (setq ref nil))
 
@@ -4779,8 +4862,9 @@ The resulting hash table is returned, or nil if no Xrefs were found."
 (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')."
+  "Parse the news overview data in the server buffer.
+Return a list of headers that match SEQUENCE (see
+`nntp-retrieve-headers')."
   ;; Get the Xref when the users reads the articles since most/some
   ;; NNTP servers do not include Xrefs when using XOVER.
   (setq gnus-article-internal-prepare-hook '(gnus-article-get-xrefs))
@@ -4828,8 +4912,8 @@ list of headers that match SEQUENCE (see `nntp-retrieve-headers')."
        (let ((gnus-nov-is-evil t))
          (nconc
           (nreverse headers)
-          (when (gnus-retrieve-headers sequence group)
-            (gnus-get-newsgroup-headers))))))))
+          (gnus-retrieve-parsed-headers sequence group)
+          ))))))
 
 (defun gnus-article-get-xrefs ()
   "Fill in the Xref value in `gnus-current-headers', if necessary.
@@ -4938,7 +5022,7 @@ current article will be taken into consideration."
       (let ((max (max (point) (mark)))
            articles article)
        (save-excursion
-         (goto-char (min (min (point) (mark))))
+         (goto-char (min (point) (mark)))
          (while
              (and
               (push (setq article (gnus-summary-article-number)) articles)
@@ -5109,6 +5193,7 @@ If `gnus-auto-center-summary' is nil, or the article buffer isn't
 displayed, no centering will be performed."
   ;; Suggested by earle@mahendo.JPL.NASA.GOV (Greg Earle).
   ;; Recenter only when requested.  Suggested by popovich@park.cs.columbia.edu.
+  (interactive)
   (let* ((top (cond ((< (window-height) 4) 0)
                    ((< (window-height) 7) 1)
                    (t (if (numberp gnus-auto-center-summary)
@@ -5264,7 +5349,10 @@ The prefix argument ALL means to select all articles."
     (gnus-summary-jump-to-group group)
     (when rescan
       (save-excursion
-       (gnus-group-get-new-news-this-group 1)))
+       (save-window-excursion
+         ;; Don't show group contents.
+         (set-window-start (selected-window) (point-max))
+         (gnus-group-get-new-news-this-group 1))))
     (gnus-group-read-group all t)
     (gnus-summary-goto-subject current-subject nil t)))
 
@@ -5328,10 +5416,6 @@ If FORCE (the prefix), also save the .newsrc file(s)."
 `gnus-exit-group-hook' is called with no arguments if that value is non-nil."
   (interactive)
   (gnus-set-global-variables)
-  (when (gnus-buffer-live-p gnus-article-buffer)
-    (save-excursion
-      (set-buffer gnus-article-buffer)
-      (mm-destroy-parts gnus-article-mime-handles)))
   (gnus-kill-save-kill-buffer)
   (gnus-async-halt-prefetch)
   (let* ((group gnus-newsgroup-name)
@@ -5407,7 +5491,14 @@ If FORCE (the prefix), also save the .newsrc file(s)."
       (if (not quit-config)
          (progn
            (goto-char group-point)
-           (gnus-configure-windows 'group 'force))
+           (gnus-configure-windows 'group 'force)
+           (unless (pos-visible-in-window-p)
+             (forward-line (/ (static-if (featurep 'xemacs)
+                                  (window-displayed-height)
+                                (1- (window-height)))
+                              -2))
+             (set-window-start (selected-window) (point))
+             (goto-char group-point)))
        (gnus-handle-ephemeral-exit quit-config))
       ;; Clear the current group name.
       (unless quit-config
@@ -5426,10 +5517,6 @@ If FORCE (the prefix), also save the .newsrc file(s)."
       (mapcar 'funcall
              (delq 'gnus-summary-expire-articles
                    (copy-sequence gnus-summary-prepare-exit-hook)))
-      (when (gnus-buffer-live-p gnus-article-buffer)
-       (save-excursion
-         (set-buffer gnus-article-buffer)
-         (mm-destroy-parts gnus-article-mime-handles)))
       ;; If we have several article buffers, we kill them at exit.
       (unless gnus-single-article-buffer
        (gnus-kill-buffer gnus-article-buffer)
@@ -5491,6 +5578,14 @@ The state which existed when entering the ephemeral is reset."
       (gnus-summary-recenter)
       (gnus-summary-position-point))))
 
+(defun gnus-summary-preview-mime-message ()
+  "MIME decode and play this message."
+  (interactive)
+  (let ((gnus-break-pages nil)
+       (gnus-show-mime t))
+    (gnus-summary-select-article gnus-show-all-headers t))
+  (select-window (get-buffer-window gnus-article-buffer)))
+
 ;;; Dead summaries.
 
 (defvar gnus-dead-summary-mode-map nil)
@@ -5537,7 +5632,8 @@ The state which existed when entering the ephemeral is reset."
       (rename-buffer
        (concat (substring name 0 (match-beginning 0)) "Dead "
               (substring name (match-beginning 0)))
-       t))))
+       t)
+      (bury-buffer))))
 
 (defun gnus-kill-or-deaden-summary (buffer)
   "Kill or deaden the summary BUFFER."
@@ -5773,6 +5869,9 @@ Given a prefix, will force an `article' buffer configuration."
        (if gnus-summary-display-article-function
            (funcall gnus-summary-display-article-function article all-header)
          (gnus-article-prepare article all-header))
+      (with-current-buffer gnus-article-buffer
+       (set (make-local-variable 'gnus-summary-search-article-matched-data)
+            nil))
       (gnus-run-hooks 'gnus-select-article-hook)
       (when (and gnus-current-article
                 (not (zerop gnus-current-article)))
@@ -5796,37 +5895,34 @@ be displayed."
     (set-buffer gnus-summary-buffer))
   (let ((article (or article (gnus-summary-article-number)))
        (all-headers (not (not all-headers))) ;Must be T or NIL.
-       gnus-summary-display-article-function
-       did)
+       gnus-summary-display-article-function)
     (and (not pseudo)
         (gnus-summary-article-pseudo-p article)
         (error "This is a pseudo-article"))
-    (prog1
-       (save-excursion
-         (set-buffer gnus-summary-buffer)
-         (if (or (and gnus-single-article-buffer
-                      (or (null gnus-current-article)
-                          (null gnus-article-current)
-                          (null (get-buffer gnus-article-buffer))
-                          (not (eq article (cdr gnus-article-current)))
-                          (not (equal (car gnus-article-current)
-                                      gnus-newsgroup-name))))
-                 (and (not gnus-single-article-buffer)
-                      (or (null gnus-current-article)
-                          (not (eq gnus-current-article article))))
-                 force)
-             ;; The requested article is different from the current article.
-             (prog1
-                 (gnus-summary-display-article article all-headers)
-               (setq did article)
-               (when (or all-headers gnus-show-all-headers)
-                 (gnus-article-show-all-headers)))
+    (save-excursion
+      (set-buffer gnus-summary-buffer)
+      (if (or (and gnus-single-article-buffer
+                  (or (null gnus-current-article)
+                      (null gnus-article-current)
+                      (null (get-buffer gnus-article-buffer))
+                      (not (eq article (cdr gnus-article-current)))
+                      (not (equal (car gnus-article-current)
+                                  gnus-newsgroup-name))))
+             (and (not gnus-single-article-buffer)
+                  (or (null gnus-current-article)
+                      (not (eq gnus-current-article article))))
+             force)
+         ;; The requested article is different from the current article.
+         (progn
+           (gnus-summary-display-article article all-headers)
            (when (or all-headers gnus-show-all-headers)
              (gnus-article-show-all-headers))
-           'old))
-      (when did
-       (gnus-article-set-window-start
-        (cdr (assq article gnus-newsgroup-bookmarks)))))))
+           (gnus-article-set-window-start
+            (cdr (assq article gnus-newsgroup-bookmarks)))
+           article)
+       (when (or all-headers gnus-show-all-headers)
+         (gnus-article-show-all-headers))
+       'old))))
 
 (defun gnus-summary-set-current-mark (&optional current-mark)
   "Obsolete function."
@@ -6278,12 +6374,12 @@ articles that are younger than AGE days."
    (let ((header
          (intern
           (gnus-completing-read
-           (symbol-name (car gnus-extra-headers))      
-           "Limit extra header:"       
-           (mapcar (lambda (x) 
+           (symbol-name (car gnus-extra-headers))
+           "Limit extra header:"
+           (mapcar (lambda (x)
                      (cons (symbol-name x) x))
                    gnus-extra-headers)
-           nil                 
+           nil
            t))))
      (list header
           (read-string (format "Limit to header %s (regexp): " header)))))
@@ -6930,12 +7026,16 @@ Obeys the standard process/prefix convention."
   "Do incremental search forward on the current article.
 If REGEXP-P (the prefix) is non-nil, do regexp isearch."
   (interactive "P")
-  (gnus-summary-select-article)
-  (gnus-configure-windows 'article)
-  (gnus-eval-in-buffer-window gnus-article-buffer
-    (save-restriction
-      (widen)
-      (isearch-forward regexp-p))))
+  (let* ((gnus-inhibit-treatment t)
+        (old (gnus-summary-select-article)))
+    (gnus-configure-windows 'article)
+    (gnus-eval-in-buffer-window gnus-article-buffer
+      (save-restriction
+       (widen)
+       (when (eq 'old old)
+         (gnus-article-show-all-headers))
+       (goto-char (point-min))
+       (isearch-forward regexp-p)))))
 
 (defun gnus-summary-search-article-forward (regexp &optional backward)
   "Search for an article containing REGEXP forward.
@@ -6965,6 +7065,84 @@ If BACKWARD, search backward instead."
                    "")))))
   (gnus-summary-search-article-forward regexp 'backward))
 
+(eval-when-compile
+  (defmacro gnus-summary-search-article-position-point (regexp backward)
+    "Dehighlight the last matched text and goto the beginning position."
+    (` (if (and gnus-summary-search-article-matched-data
+               (let ((text (caddr gnus-summary-search-article-matched-data))
+                     (inhibit-read-only t)
+                     buffer-read-only)
+                 (delete-region
+                  (goto-char (car gnus-summary-search-article-matched-data))
+                  (cadr gnus-summary-search-article-matched-data))
+                 (insert text)
+                 (string-match (, regexp) text)))
+          (if (, backward) (beginning-of-line) (end-of-line))
+        (goto-char (if (, backward) (point-max) (point-min))))))
+
+  (defmacro gnus-summary-search-article-highlight-goto-x-face (opoint)
+    "Place point where X-Face image is displayed."
+    (if (featurep 'xemacs)
+       (` (let ((end (if (search-forward "\n\n" nil t)
+                         (goto-char (1- (point)))
+                       (point-min)))
+                extent)
+            (or (search-backward "\n\n" nil t) (goto-char (point-min)))
+            (unless (and (re-search-forward "^From:" end t)
+                         (setq extent (extent-at (point)))
+                         (extent-begin-glyph extent))
+              (goto-char (, opoint)))))
+      (` (let ((end (if (search-forward "\n\n" nil t)
+                       (goto-char (1- (point)))
+                     (point-min))))
+          (goto-char
+           (or (text-property-any (or (search-backward "\n\n" nil t)
+                                      (point-min))
+                                  end 'x-face-mule-bitmap-image t)
+               (, opoint)))))))
+
+  (defmacro gnus-summary-search-article-highlight-matched-text
+    (backward treated x-face)
+    "Highlight matched text in the function `gnus-summary-search-article'."
+    (` (let ((start (set-marker (make-marker) (match-beginning 0)))
+            (end (set-marker (make-marker) (match-end 0)))
+            (inhibit-read-only t)
+            buffer-read-only)
+        (unless treated
+          (let ((,@
+                 (let ((items (mapcar 'car gnus-treatment-function-alist)))
+                   (mapcar
+                    (lambda (item) (setq items (delq item items)))
+                    '(gnus-treat-buttonize
+                      gnus-treat-fill-article
+                      gnus-treat-fill-long-lines
+                      gnus-treat-emphasize
+                      gnus-treat-highlight-headers
+                      gnus-treat-highlight-citation
+                      gnus-treat-highlight-signature
+                      gnus-treat-overstrike
+                      gnus-treat-display-xface
+                      gnus-treat-buttonize-head
+                      gnus-treat-decode-article-as-default-mime-charset))
+                   (static-if (featurep 'xemacs)
+                       items
+                     (cons '(x-face-mule-delete-x-face-field
+                             (quote never))
+                           items))))
+                (gnus-treat-display-xface
+                 (when (, x-face) gnus-treat-display-xface)))
+            (gnus-article-prepare-mime-display)))
+        (goto-char (if (, backward) start end))
+        (when (, x-face)
+          (gnus-summary-search-article-highlight-goto-x-face (point)))
+        (setq gnus-summary-search-article-matched-data
+              (list start end (buffer-substring start end)))
+        (unless (eq start end);; matched text has been deleted. :-<
+          (put-text-property start end 'face
+                             (or (find-face 'isearch)
+                                 'secondary-selection))))))
+  )
+
 (defun gnus-summary-search-article (regexp &optional backward)
   "Search for an article containing REGEXP.
 Optional argument BACKWARD means do search for backward.
@@ -6974,20 +7152,45 @@ Optional argument BACKWARD means do search for backward.
   (require 'gnus-async)
   (require 'gnus-art)
   (let ((gnus-select-article-hook nil) ;Disable hook.
+       (gnus-article-display-hook nil)
        (gnus-article-prepare-hook nil)
        (gnus-mark-article-hook nil)    ;Inhibit marking as read.
        (gnus-use-article-prefetch nil)
        (gnus-xmas-force-redisplay nil) ;Inhibit XEmacs redisplay.
        (gnus-use-trees nil)            ;Inhibit updating tree buffer.
        (sum (current-buffer))
-       (gnus-display-mime-function nil)
        (found nil)
-       point)
+       point treated)
     (gnus-save-hidden-threads
-      (gnus-summary-select-article)
+      (static-if (featurep 'xemacs)
+         (let ((gnus-inhibit-treatment t))
+           (setq treated (eq 'old (gnus-summary-select-article)))
+           (when (and treated
+                      (not (and (gnus-buffer-live-p gnus-article-buffer)
+                                (window-live-p (get-buffer-window
+                                                gnus-article-buffer t)))))
+             (gnus-summary-select-article nil t)
+             (setq treated nil)))
+       (let ((gnus-inhibit-treatment t)
+             (x-face-mule-delete-x-face-field 'never))
+         (setq treated (eq 'old (gnus-summary-select-article)))
+         (when (and treated
+                    (not
+                     (and (gnus-buffer-live-p gnus-article-buffer)
+                          (window-live-p (get-buffer-window
+                                          gnus-article-buffer t))
+                          (or (not (string-match "^\\^X-Face:" regexp))
+                              (with-current-buffer gnus-article-buffer
+                                gnus-summary-search-article-matched-data)))))
+           (gnus-summary-select-article nil t)
+           (setq treated nil))))
       (set-buffer gnus-article-buffer)
-      (when backward
-       (forward-line -1))
+      (widen)
+      (if treated
+         (progn
+           (gnus-article-show-all-headers)
+           (gnus-summary-search-article-position-point regexp backward))
+       (goto-char (if backward (point-max) (point-min))))
       (while (not found)
        (gnus-message 7 "Searching article: %d..." (cdr gnus-article-current))
        (if (if backward
@@ -6995,15 +7198,16 @@ Optional argument BACKWARD means do search for backward.
              (re-search-forward regexp nil t))
            ;; We found the regexp.
            (progn
+             (gnus-summary-search-article-highlight-matched-text
+              backward treated (string-match "^\\^X-Face:" regexp))
              (setq found 'found)
-             (beginning-of-line)
+             (forward-line
+              (/ (- 2 (window-height
+                       (get-buffer-window gnus-article-buffer t)))
+                 2))
              (set-window-start
               (get-buffer-window (current-buffer))
               (point))
-             (forward-line 1)
-             (set-window-point
-              (get-buffer-window (current-buffer))
-              (point))
              (set-buffer sum)
              (setq point (point)))
          ;; We didn't find it, so we go to the next article.
@@ -7018,7 +7222,9 @@ Optional argument BACKWARD means do search for backward.
              (unless (gnus-summary-article-sparse-p
                       (gnus-summary-article-number))
                (setq found nil)
-               (gnus-summary-select-article)
+               (let ((gnus-inhibit-treatment t))
+                 (gnus-summary-select-article))
+               (setq treated nil)
                (set-buffer gnus-article-buffer)
                (widen)
                (goto-char (if backward (point-max) (point-min))))))))
@@ -7155,15 +7361,15 @@ to save in."
 
 (defun gnus-summary-show-article (&optional arg)
   "Force re-fetching of the current article.
-If ARG (the prefix) is a number, show the article with the charset 
+If ARG (the prefix) is a number, show the article with the charset
 defined in `gnus-summary-show-article-charset-alist', or the charset
 inputed.
-If ARG (the prefix) is non-nil and not a number, show the raw article 
+If ARG (the prefix) is non-nil and not a number, show the raw article
 without any article massaging functions being run."
   (interactive "P")
-  (cond 
+  (cond
    ((numberp arg)
-    (let ((gnus-newsgroup-charset 
+    (let ((gnus-newsgroup-charset
           (or (cdr (assq arg gnus-summary-show-article-charset-alist))
               (read-coding-system "Charset: ")))
          (gnus-newsgroup-ignored-charsets 'gnus-all))
@@ -7178,15 +7384,11 @@ without any article massaging functions being run."
     (require 'gnus-art)
     ;; Bind the article treatment functions to nil.
     (let ((gnus-have-all-headers t)
+         gnus-article-display-hook
          gnus-article-prepare-hook
          gnus-article-decode-hook
-         gnus-display-mime-function
-         gnus-break-pages)
-      ;; Destroy any MIME parts.
-      (when (gnus-buffer-live-p gnus-article-buffer)
-       (save-excursion
-         (set-buffer gnus-article-buffer)
-         (mm-destroy-parts gnus-article-mime-handles)))
+         gnus-break-pages
+         gnus-show-mime)
       (gnus-summary-select-article nil 'force))))
   (gnus-summary-goto-subject gnus-current-article)
   (gnus-summary-position-point))
@@ -7218,7 +7420,7 @@ If ARG is a negative number, hide the unwanted header lines."
        (setq hidden
              (if (numberp arg)
                  (>= arg 0)
-               (save-restriction 
+               (save-restriction
                  (article-narrow-to-head)
                  (gnus-article-hidden-text-p 'headers))))
        (goto-char (point-min))
@@ -7236,14 +7438,27 @@ If ARG is a negative number, hide the unwanted header lines."
          (if  hidden
              (let ((gnus-treat-hide-headers nil)
                    (gnus-treat-hide-boring-headers nil))
+               (setq gnus-article-wash-types
+                     (delq 'headers gnus-article-wash-types))
                (gnus-treat-article 'head))
-           (gnus-treat-article 'head)))))))
+           (gnus-treat-article 'head)))
+       (gnus-set-mode-line 'article)))))
 
 (defun gnus-summary-show-all-headers ()
   "Make all header lines visible."
   (interactive)
   (gnus-article-show-all-headers))
 
+(defun gnus-summary-toggle-mime (&optional arg)
+  "Toggle MIME processing.
+If ARG is a positive number, turn MIME processing on."
+  (interactive "P")
+  (setq gnus-show-mime
+       (if (null arg)
+           (not gnus-show-mime)
+         (> (prefix-numeric-value arg) 0)))
+  (gnus-summary-select-article t 'force))
+
 (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
@@ -7304,12 +7519,18 @@ ACTION can be either `move' (the default), `crosspost' or `copy'."
                    'request-replace-article gnus-newsgroup-name)))
         (error "The current group does not support article editing")))
   (let ((articles (gnus-summary-work-articles n))
-       (prefix (gnus-group-real-prefix gnus-newsgroup-name))
+       (prefix (if (gnus-check-backend-function
+                   'request-move-article gnus-newsgroup-name)
+                   (gnus-group-real-prefix gnus-newsgroup-name)
+                 ""))
        (names '((move "Move" "Moving")
                 (copy "Copy" "Copying")
                 (crosspost "Crosspost" "Crossposting")))
        (copy-buf (save-excursion
                    (nnheader-set-temp-buffer " *copy article*")))
+       (default-marks gnus-article-mark-lists)
+       (no-expire-marks (delete '(expirable . expire)
+                                (copy-sequence gnus-article-mark-lists)))
        art-group to-method new-xref article to-groups)
     (unless (assq action names)
       (error "Unknown action %s" action))
@@ -7323,7 +7544,8 @@ ACTION can be either `move' (the default), `crosspost' or `copy'."
             articles prefix))
       (set (intern (format "gnus-current-%s-group" action)) to-newsgroup))
     (setq to-method (or select-method
-                       (gnus-group-name-to-method to-newsgroup)))
+                       (gnus-server-to-method
+                        (gnus-group-method to-newsgroup))))
     ;; Check the method we are to move this article to...
     (unless (gnus-check-backend-function
             'request-accept-article (car to-method))
@@ -7393,10 +7615,10 @@ ACTION can be either `move' (the default), `crosspost' or `copy'."
        (gnus-message 1 "Couldn't %s article %s: %s"
                      (cadr (assq action names)) article
                      (nnheader-get-report (car to-method))))
-       ((and (eq art-group 'junk)
-            (eq action 'move))
-       (gnus-summary-mark-article article gnus-canceled-mark)
-       (gnus-message 4 "Deleted article %s" article))
+       ((eq art-group 'junk)
+       (when (eq action 'move)
+         (gnus-summary-mark-article article gnus-canceled-mark)
+         (gnus-message 4 "Deleted article %s" article)))
        (t
        (let* ((pto-group (gnus-group-prefixed-name
                           (car art-group) to-method))
@@ -7418,7 +7640,9 @@ ACTION can be either `move' (the default), `crosspost' or `copy'."
                                       (list (cdr art-group)))))
 
            ;; See whether the article is to be put in the cache.
-           (let ((marks gnus-article-mark-lists)
+           (let ((marks (if (gnus-group-auto-expirable-p to-group)
+                            default-marks
+                          no-expire-marks))
                  (to-article (cdr art-group)))
 
              ;; Enter the article into the cache in the new group,
@@ -7426,11 +7650,15 @@ ACTION can be either `move' (the default), `crosspost' or `copy'."
              (when gnus-use-cache
                (gnus-cache-possibly-enter-article
                 to-group to-article
+                (let ((header (copy-sequence
+                               (gnus-summary-article-header article))))
+                  (mail-header-set-number header to-article)
+                  header)
                 (memq article gnus-newsgroup-marked)
                 (memq article gnus-newsgroup-dormant)
                 (memq article gnus-newsgroup-unreads)))
 
-             (when gnus-preserve-marks 
+             (when gnus-preserve-marks
                ;; Copy any marks over to the new group.
                (when (and (equal to-group gnus-newsgroup-name)
                           (not (memq article gnus-newsgroup-unreads)))
@@ -7573,7 +7801,7 @@ latter case, they will be copied into the relevant groups."
     (save-excursion
       (set-buffer (gnus-get-buffer-create " *import file*"))
       (erase-buffer)
-      (insert-file-contents file)
+      (nnheader-insert-file-contents file)
       (goto-char (point-min))
       (unless (nnheader-article-p)
        ;; This doesn't look like an article, so we fudge some headers.
@@ -7622,6 +7850,9 @@ This will be the case if the article has both been mailed and posted."
           (expiry-wait (if now 'immediate
                          (gnus-group-find-parameter
                           gnus-newsgroup-name 'expiry-wait)))
+          (nnmail-expiry-target
+           (or (gnus-group-find-parameter gnus-newsgroup-name 'expiry-target)
+               nnmail-expiry-target))
           es)
       (when expirable
        ;; There are expirable articles in this group, so we run them
@@ -7718,12 +7949,11 @@ groups."
        (error "The current newsgroup does not support article editing"))
       (gnus-summary-show-article t)
       (gnus-article-edit-article
-       'mime-to-mml
+       'ignore
        `(lambda (no-highlight)
          (let ((mail-parse-charset ',gnus-newsgroup-charset)
-               (mail-parse-ignored-charsets 
+               (mail-parse-ignored-charsets
                 ',gnus-newsgroup-ignored-charsets))
-           (mml-to-mime)
            (gnus-summary-edit-article-done
             ,(or (mail-header-references gnus-current-headers) "")
             ,(gnus-group-read-only-p) ,gnus-summary-buffer no-highlight)))))))
@@ -7741,7 +7971,7 @@ groups."
       (if (and (not read-only)
               (not (gnus-request-replace-article
                     (cdr gnus-article-current) (car gnus-article-current)
-                    (current-buffer) t)))
+                    (current-buffer) t)))
          (error "Couldn't replace article")
        ;; Update the summary buffer.
        (if (and references
@@ -8103,6 +8333,7 @@ Iff NO-EXPIRE, auto-expiry will be inhibited."
             (save-excursion
               (gnus-cache-possibly-enter-article
                gnus-newsgroup-name article
+               (gnus-summary-article-header article)
                (= mark gnus-ticked-mark)
                (= mark gnus-dormant-mark) (= mark gnus-unread-mark))))
 
@@ -8149,6 +8380,7 @@ Iff NO-EXPIRE, auto-expiry will be inhibited."
             (save-excursion
               (gnus-cache-possibly-enter-article
                gnus-newsgroup-name article
+               (gnus-summary-article-header article)
                (= mark gnus-ticked-mark)
                (= mark gnus-dormant-mark) (= mark gnus-unread-mark))))
 
@@ -8486,6 +8718,37 @@ read."
     (gnus-summary-catchup all))
   (gnus-summary-next-group))
 
+;;;
+;;; with article
+;;;
+
+(defmacro gnus-with-article (article &rest forms)
+  "Select ARTICLE and perform FORMS in the original article buffer.
+Then replace the article with the result."
+  `(progn
+     ;; We don't want the article to be marked as read.
+     (let (gnus-mark-article-hook)
+       (gnus-summary-select-article t t nil ,article))
+     (set-buffer gnus-original-article-buffer)
+     ,@forms
+     (if (not (gnus-check-backend-function
+              'request-replace-article (car gnus-article-current)))
+        (gnus-message 5 "Read-only group; not replacing")
+       (unless (gnus-request-replace-article
+               ,article (car gnus-article-current)
+               (current-buffer) t)
+        (error "Couldn't replace article")))
+     ;; The cache and backlog have to be flushed somewhat.
+     (when gnus-keep-backlog
+       (gnus-backlog-remove-article
+       (car gnus-article-current) (cdr gnus-article-current)))
+     (when gnus-use-cache
+       (gnus-cache-update-article
+       (car gnus-article-current) (cdr gnus-article-current)))))
+
+(put 'gnus-with-article 'lisp-indent-function 1)
+(put 'gnus-with-article 'edebug-form-spec '(form body))
+
 ;; Thread-based commands.
 
 (defun gnus-summary-articles-in-thread (&optional article)
@@ -8564,14 +8827,16 @@ is non-nil or the Subject: of both articles are the same."
        (unless (and message-id (not (equal message-id "")))
          (error "No message-id in desired parent"))
        (gnus-with-article current-article
-         (goto-char (point-min))
-         (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")))
+         (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)
@@ -8778,14 +9043,14 @@ Argument REVERSE means reverse order."
 
 (defun gnus-summary-sort-by-author (&optional reverse)
   "Sort the summary buffer by author name alphabetically.
-If case-fold-search is non-nil, case of letters is ignored.
+If `case-fold-search' is non-nil, case of letters is ignored.
 Argument REVERSE means reverse order."
   (interactive "P")
   (gnus-summary-sort 'author 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.
+If `case-fold-search' is non-nil, case of letters is ignored.
 Argument REVERSE means reverse order."
   (interactive "P")
   (gnus-summary-sort 'subject reverse))
@@ -8812,7 +9077,7 @@ Argument REVERSE means reverse order."
   "Sort the summary buffer by article length.
 Argument REVERSE means reverse order."
   (interactive "P")
-  (gnus-summary-sort 'chars reverse))  
+  (gnus-summary-sort 'chars reverse))
 
 (defun gnus-summary-sort (predicate reverse)
   "Sort summary buffer by PREDICATE.  REVERSE means reverse order."
@@ -8902,7 +9167,7 @@ If N is a negative number, save the N previous articles.
 If N is nil and any articles have been marked with the process mark,
 save those articles instead."
   (interactive "P")
-  (let ((gnus-default-article-saver 'rmail-output-to-rmail-file))
+  (let ((gnus-default-article-saver 'gnus-summary-save-in-rmail))
     (gnus-summary-save-article arg)))
 
 (defun gnus-summary-save-article-file (&optional arg)
@@ -9020,7 +9285,8 @@ save those articles instead."
                                  (mapcar (lambda (el) (list el))
                                          (nreverse split-name))
                                  nil nil nil
-                                 'gnus-group-history)))))
+                                 'gnus-group-history))))
+         (to-method (gnus-server-to-method (gnus-group-method to-newsgroup))))
     (when to-newsgroup
       (if (or (string= to-newsgroup "")
              (string= to-newsgroup prefix))
@@ -9028,25 +9294,23 @@ save those articles instead."
       (unless to-newsgroup
        (error "No group name entered"))
       (or (gnus-active to-newsgroup)
-         (gnus-activate-group to-newsgroup)
+         (gnus-activate-group to-newsgroup 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 (gnus-group-name-to-method to-newsgroup))
+             (or (and (gnus-request-create-group to-newsgroup to-method)
                       (gnus-activate-group
-                       to-newsgroup nil nil
-                       (gnus-group-name-to-method to-newsgroup))
+                       to-newsgroup nil nil to-method)
                       (gnus-subscribe-group to-newsgroup))
                  (error "Couldn't create group %s" to-newsgroup)))
          (error "No such group: %s" to-newsgroup)))
     to-newsgroup))
 
-(defun gnus-summary-save-parts (type dir n reverse)
+(defun gnus-summary-save-parts (type dir n &optional reverse)
   "Save parts matching TYPE to DIR.
 If REVERSE, save parts that do not match TYPE."
   (interactive
    (list (read-string "Save parts of type: " "image/.*")
-        (read-file-name "Save to directory: " t nil t)
+        (read-file-name "Save to directory: " nil nil t)
         current-prefix-arg))
   (gnus-summary-iterate n
     (let ((gnus-display-mime-function nil)
@@ -9071,7 +9335,9 @@ If REVERSE, save parts that do not match TYPE."
                    (or
                     (mail-content-type-get
                      (mm-handle-disposition handle) 'filename)
-                    (concat gnus-newsgroup-name "." gnus-current-article)))
+                    (concat gnus-newsgroup-name
+                            "." (number-to-string
+                                 (cdr gnus-article-current)))))
                   dir)))
        (unless (file-exists-p file)
          (mm-save-part-to-file handle file))))))
@@ -9111,7 +9377,7 @@ If REVERSE, save parts that do not match TYPE."
                                (lambda (f)
                                  (if (equal f " ")
                                      f
-                                   (mm-quote-arg f)))
+                                   (gnus-quote-arg-for-sh-or-csh f)))
                                files " ")))))
          (setq ps (cdr ps)))))
     (if (and gnus-view-pseudos (not not-view))
@@ -9265,8 +9531,8 @@ If REVERSE, save parts that do not match TYPE."
 ;;;
 
 (defun gnus-highlight-selected-summary ()
+  "Highlight selected article in summary buffer."
   ;; Added by Per Abrahamsen <amanda@iesd.auc.dk>.
-  ;; Highlight selected article in summary buffer
   (when gnus-summary-selected-face
     (save-excursion
       (let* ((beg (progn (beginning-of-line) (point)))
@@ -9412,13 +9678,126 @@ If REVERSE, save parts that do not match TYPE."
           (gnus-summary-exit))
         buffers)))))
 
+
+;;; @ for mime-partial
+;;;
+
+(defun gnus-request-partial-message ()
+  (save-excursion
+    (let ((number (gnus-summary-article-number))
+         (group gnus-newsgroup-name)
+         (mother gnus-article-buffer))
+      (set-buffer (get-buffer-create " *Partial Article*"))
+      (erase-buffer)
+      (setq mime-preview-buffer mother)
+      (gnus-request-article-this-buffer number group)
+      (mime-parse-buffer)
+      )))
+
+(autoload 'mime-combine-message/partial-pieces-automatically
+  "mime-partial"
+  "Internal method to combine message/partial messages automatically.")
+
+(mime-add-condition
+ 'action '((type . message)(subtype . partial)
+          (major-mode . gnus-original-article-mode)
+          (method . mime-combine-message/partial-pieces-automatically)
+          (summary-buffer-exp . gnus-summary-buffer)
+          (request-partial-message-method . gnus-request-partial-message)
+          ))
+
+
+;;; @ for message/rfc822
+;;;
+
+(defun gnus-mime-extract-message/rfc822 (entity situation)
+  (let (group article num cwin swin cur)
+    (with-temp-buffer
+      (mime-insert-entity-content entity)
+      (setq group (or (cdr (assq 'group situation))
+                     (completing-read "Group: "
+                                      gnus-active-hashtb
+                                      nil
+                                      (gnus-read-active-file-p)
+                                      gnus-newsgroup-name))
+           article (gnus-request-accept-article group)))
+    (when (and (consp article)
+              (numberp (setq article (cdr article))))
+      (setq num (1+ (or (cdr (assq 'number situation)) 0))
+           cwin (get-buffer-window (current-buffer) t))
+      (save-window-excursion
+       (if (setq swin (get-buffer-window gnus-summary-buffer t))
+           (select-window swin)
+         (set-buffer gnus-summary-buffer))
+       (setq cur gnus-current-article)
+       (forward-line num)
+       (let (gnus-show-threads)
+         (gnus-summary-goto-subject article t))
+       (gnus-summary-clear-mark-forward 1)
+       (gnus-summary-goto-subject cur))
+      (when (and cwin (window-frame cwin))
+       (select-frame (window-frame cwin)))
+      (when (boundp 'mime-acting-situation-to-override)
+       (set-alist 'mime-acting-situation-to-override
+                  'group
+                  group)
+       (set-alist 'mime-acting-situation-to-override
+                  'after-method
+                  `(progn
+                     (save-current-buffer
+                       (set-buffer gnus-group-buffer)
+                       (gnus-activate-group ,group))
+                     (gnus-summary-goto-article ,cur
+                                                gnus-show-all-headers)))
+       (set-alist 'mime-acting-situation-to-override
+                  'number num)))))
+
+(mime-add-condition
+ 'action '((type . message)(subtype . rfc822)
+          (major-mode . gnus-original-article-mode)
+          (method . gnus-mime-extract-message/rfc822)
+          (mode . "extract")
+          ))
+
+(mime-add-condition
+ 'action '((type . message)(subtype . news)
+          (major-mode . gnus-original-article-mode)
+          (method . gnus-mime-extract-message/rfc822)
+          (mode . "extract")
+          ))
+
+(defun gnus-mime-extract-multipart (entity situation)
+  (let ((children (mime-entity-children entity))
+       mime-acting-situation-to-override
+       f)
+    (while children
+      (mime-play-entity (car children)
+                       (cons (assq 'mode situation)
+                             mime-acting-situation-to-override))
+      (setq children (cdr children)))
+    (if (setq f (cdr (assq 'after-method
+                          mime-acting-situation-to-override)))
+       (eval f)
+      )))
+
+(mime-add-condition
+ 'action '((type . multipart)
+          (method . gnus-mime-extract-multipart)
+          (mode . "extract")
+          )
+ 'with-default)
+
+
+;;; @ end
+;;;
+
 (defun gnus-summary-setup-default-charset ()
   "Setup newsgroup default charset."
   (if (equal gnus-newsgroup-name "nndraft:drafts")
       (setq gnus-newsgroup-charset nil)
     (let* ((name (and gnus-newsgroup-name
                      (gnus-group-real-name gnus-newsgroup-name)))
-          (ignored-charsets 
+          (ignored-charsets
            (or gnus-newsgroup-ephemeral-ignored-charsets
                (append
                 (and gnus-newsgroup-name
@@ -9446,7 +9825,7 @@ If REVERSE, save parts that do not match TYPE."
                                     charset (cadr elem))))
                           charset)))
                gnus-default-charset))
-      (set (make-local-variable 'gnus-newsgroup-ignored-charsets) 
+      (set (make-local-variable 'gnus-newsgroup-ignored-charsets)
           ignored-charsets))))
 
 ;;;
@@ -9494,35 +9873,102 @@ treated as multipart/mixed."
     (gnus-summary-show-article)))
 
 ;;;
-;;; with article
+;;; Intelli-mouse commmands
 ;;;
 
-(defmacro gnus-with-article (article &rest forms)
-  "Select ARTICLE and perform FORMS in the original article buffer.
-Then replace the article with the result."
-  `(progn
-     ;; We don't want the article to be marked as read.
-     (let (gnus-mark-article-hook)
-       (gnus-summary-select-article t t nil ,article))
-     (set-buffer gnus-original-article-buffer)
-     ,@forms
-     (if (not (gnus-check-backend-function
-              'request-replace-article (car gnus-article-current)))
-        (gnus-message 5 "Read-only group; not replacing")
-       (unless (gnus-request-replace-article
-               ,article (car gnus-article-current)
-               (current-buffer) t)
-        (error "Couldn't replace article")))
-     ;; The cache and backlog have to be flushed somewhat.
-     (when gnus-keep-backlog
-       (gnus-backlog-remove-article
-       (car gnus-article-current) (cdr gnus-article-current)))
-     (when gnus-use-cache
-       (gnus-cache-update-article
-       (car gnus-article-current) (cdr gnus-article-current)))))
+(defun gnus-wheel-summary-scroll (event)
+  (interactive "e")
+  (let ((amount (if (memq 'shift (event-modifiers event))
+                   (car gnus-wheel-scroll-amount)
+                 (cdr gnus-wheel-scroll-amount)))
+       (direction (- (* (static-if (featurep 'xemacs)
+                            (event-button event)
+                          (cond ((eq 'mouse-4 (event-basic-type event))
+                                 4)
+                                ((eq 'mouse-5 (event-basic-type event))
+                                 5)))
+                        2) 9))
+       edge)
+    (gnus-summary-scroll-up (* amount direction))
+    (when (gnus-eval-in-buffer-window gnus-article-buffer
+           (save-restriction
+             (widen)
+             (and (if (< 0 direction)
+                      (gnus-article-next-page 0)
+                    (gnus-article-prev-page 0)
+                    (bobp))
+                  (if (setq edge (get-text-property
+                                  (point-min) 'gnus-wheel-edge))
+                      (setq edge (* edge direction))
+                    (setq edge -1))
+                  (or (plusp edge)
+                      (let ((buffer-read-only nil)
+                            (inhibit-read-only t))
+                        (put-text-property (point-min) (point-max)
+                                           'gnus-wheel-edge direction)
+                        nil))
+                  (or (> edge gnus-wheel-edge-resistance)
+                      (let ((buffer-read-only nil)
+                            (inhibit-read-only t))
+                        (put-text-property (point-min) (point-max)
+                                           'gnus-wheel-edge
+                                           (* (1+ edge) direction))
+                        nil))
+                  (eq last-command 'gnus-wheel-summary-scroll))))
+      (gnus-summary-next-article nil nil (minusp direction)))))
+
+(defun gnus-wheel-install ()
+  "Enable mouse wheel support on summary window."
+  (when gnus-use-wheel
+    (let ((keys
+          '([(mouse-4)] [(shift mouse-4)] [(mouse-5)] [(shift mouse-5)])))
+      (dolist (key keys)
+       (define-key gnus-summary-mode-map key
+         'gnus-wheel-summary-scroll)))))
+
+(add-hook 'gnus-summary-mode-hook 'gnus-wheel-install)
 
-(put 'gnus-with-article 'lisp-indent-function 1)
-(put 'gnus-with-article 'edebug-form-spec '(form body))
+;;;
+;;; Traditional PGP commmands
+;;;
+
+(defun gnus-summary-decrypt-article (&optional force)
+  "Decrypt the current article in traditional PGP way.
+This will have permanent effect only in mail groups.
+If FORCE is non-nil, allow editing of articles even in read-only
+groups."
+  (interactive "P")
+  (gnus-summary-select-article t)
+  (gnus-eval-in-buffer-window gnus-article-buffer
+    (save-excursion
+      (save-restriction
+       (widen)
+       (goto-char (point-min))
+       (unless (re-search-forward (car pgg-armor-header-lines) nil t)
+         (error "Not a traditional PGP message!"))
+       (let ((armor-start (match-beginning 0)))
+         (if (and (pgg-decrypt-region armor-start (point-max))
+                  (or force (not (gnus-group-read-only-p))))
+             (let ((inhibit-read-only t)
+                   buffer-read-only)
+               (delete-region armor-start
+                              (progn
+                                (re-search-forward "^-+END PGP" nil t)
+                                (beginning-of-line 2)
+                                (point)))
+               (insert-buffer-substring pgg-output-buffer))))))))
+
+(defun gnus-summary-verify-article ()
+  "Verify the current article in traditional PGP way."
+  (interactive)
+  (save-excursion
+    (set-buffer gnus-original-article-buffer)
+    (goto-char (point-min))
+    (unless (re-search-forward "^-+BEGIN PGP SIGNED MESSAGE" nil t)
+      (error "Not a traditional PGP message!"))
+    (re-search-forward "^-+END PGP" nil t)
+    (beginning-of-line 2)
+    (call-interactively (function pgg-verify-region))))
 
 ;;;
 ;;; Generic summary marking commands
@@ -9556,8 +10002,8 @@ Then replace the article with the result."
                   mark (car lway) lway name)))
        (setq func (eval func))
        (define-key map (nth 4 lway) func)))))
-      
-(defun gnus-summary-make-marking-command-1 (mark way lway name)      
+
+(defun gnus-summary-make-marking-command-1 (mark way lway name)
   `(defun ,(intern
            (format "gnus-summary-put-mark-as-%s%s"
                    name (if (eq way 'nomove)
@@ -9570,10 +10016,10 @@ If N, the prefix, then repeat N times.
 If N is negative, move in reverse order.
 The difference between N and the actual number of articles marked is
 returned."
-       name (cadr lway))
+       name (car (cdr lway)))
      (interactive "p")
      (gnus-summary-generic-mark n ,mark ',(nth 2 lway) ,(nth 3 lway))))
-    
+
 (defun gnus-summary-generic-mark (n mark move unread)
   "Mark N articles with MARK."
   (unless (eq major-mode 'gnus-summary-mode)