Synch with Gnus.
[elisp/gnus.git-] / lisp / gnus-sum.el
index f97399d..6c3e5c4 100644 (file)
@@ -49,6 +49,7 @@
   (autoload 'pgg-verify-region "pgg" nil t))
 
 (autoload 'gnus-summary-limit-include-cached "gnus-cache" nil t)
+(autoload 'gnus-cache-write-active "gnus-cache")
 (autoload 'gnus-set-summary-default-charset "gnus-i18n" nil t)
 
 (defcustom gnus-kill-summary-on-exit t
@@ -789,7 +790,7 @@ 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) 
+    ((and (memq article gnus-newsgroup-incorporated)
          (= mark gnus-unread-mark))
      . gnus-summary-incorporated-face)
     ((= mark gnus-unread-mark)
@@ -871,7 +872,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
@@ -887,7 +888,7 @@ 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)
 
@@ -930,6 +931,20 @@ For example: ((1 . cn-gb-2312) (2 . big5))."
   :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))
+
+(defcustom gnus-summary-save-parts-default-mime "image/.*"
+  "*A regexp to match MIME parts when saving multiple parts of a message
+with gnus-summary-save-parts (X m). This regexp will be used by default
+when prompting the user for which type of files to save."
+  :group 'gnus-summary
+  :type 'regexp)
+
+
 ;;; Internal variables
 
 (defvar gnus-article-mime-handles nil)
@@ -947,6 +962,9 @@ For example: ((1 . cn-gb-2312) (2 . big5))."
 (defvar gnus-sort-gathered-threads-function 'gnus-thread-sort-by-number
   "Function called to sort the articles within a thread after it has been gathered together.")
 
+(defvar gnus-summary-save-parts-type-history nil)
+(defvar gnus-summary-save-parts-last-directory nil)
+
 ;; Avoid highlighting in kill files.
 (defvar gnus-summary-inhibit-highlight nil)
 (defvar gnus-newsgroup-selected-overlay nil)
@@ -1003,9 +1021,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)
@@ -1156,6 +1174,7 @@ end position and text.")
     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
@@ -1175,7 +1194,7 @@ end position and text.")
 ;; 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)
@@ -1228,7 +1247,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" " ")
@@ -1463,7 +1482,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)
@@ -1825,8 +1844,8 @@ increase the score of each group you read."
        ["Wide reply and yank" gnus-summary-wide-reply-with-original t]
        ["Mail forward" gnus-summary-mail-forward t]
        ["Post forward" gnus-summary-post-forward t]
-       ["Digest and mail" gnus-summary-mail-digest t]
-       ["Digest and post" gnus-summary-post-digest t]
+       ["Digest and mail" gnus-uu-digest-mail-forward t]
+       ["Digest and post" gnus-uu-digest-post-forward t]
        ["Resend message" gnus-summary-resend-message t]
        ["Send bounced mail" gnus-summary-resend-bounced-mail t]
        ["Send a mail" gnus-summary-mail-other-window t]
@@ -2435,12 +2454,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.
 
@@ -2450,9 +2470,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)
@@ -2496,9 +2517,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)
@@ -2655,9 +2676,8 @@ marks of articles."
          (cond
           ((string-match "<[^>]+> *$" gnus-tmp-from)
            (let ((beg (match-beginning 0)))
-             (or (and (string-match "^\"[^\"]*\"" gnus-tmp-from)
-                      (substring gnus-tmp-from (1+ (match-beginning 0))
-                                 (1- (match-end 0))))
+             (or (and (string-match "^\".+\"" gnus-tmp-from)
+                      (substring gnus-tmp-from 1 (1- (match-end 0))))
                  (substring gnus-tmp-from 0 beg))))
           ((string-match "(.+)" gnus-tmp-from)
            (substring gnus-tmp-from
@@ -2682,7 +2702,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.
@@ -3088,7 +3108,7 @@ If SHOW-ALL is non-nil, already read articles are also listed."
     result))
 
 (defun gnus-sort-gathered-threads (threads)
-  "Sort subtreads inside each gathered thread by article number."
+  "Sort subtreads inside each gathered thread by `gnus-sort-gathered-threads-function'."
   (let ((result threads))
     (while threads
       (when (stringp (caar threads))
@@ -3262,7 +3282,7 @@ Returns HEADER if it was entered in the DEPENDENCIES.  Returns nil otherwise."
     (mapcar
      (lambda (relation)
        (when (gnus-dependencies-add-header
-             (make-full-mail-header
+             (make-full-mail-header-from-decoded-header
               gnus-reffed-article-number
               (nth 3 relation) "" (or (nth 4 relation) "")
               (nth 1 relation)
@@ -3305,31 +3325,38 @@ Returns HEADER if it was entered in the DEPENDENCIES.  Returns nil otherwise."
        header)
 
     ;; overview: [num subject from date id refs chars lines misc]
-    (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
+    (unwind-protect
+       (progn
+         (narrow-to-region (point) eol)
+         (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)
+                  (if (looking-at "Xref: ")
+                      (goto-char (match-end 0)))
+                  (nnheader-nov-field))        ; Xref
+                (nnheader-nov-parse-extra))))  ; extra
+
+      (widen))
 
     (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
@@ -3656,13 +3683,22 @@ If LINE, insert the rebuilt thread starting on line LINE."
              (1+ (gnus-point-at-eol))
            (gnus-delete-line)))))))
 
+(defun gnus-sort-threads-1 (threads func)
+  (sort (mapcar (lambda (thread)
+                 (cons (car thread)
+                       (and (cdr thread)
+                            (gnus-sort-threads-1 (cdr thread) func))))
+               threads) func))
+
 (defun gnus-sort-threads (threads)
   "Sort THREADS."
   (if (not gnus-thread-sort-functions)
       threads
     (gnus-message 8 "Sorting threads...")
     (prog1
-       (sort threads (gnus-make-sort-function gnus-thread-sort-functions))
+       (gnus-sort-threads-1 
+        threads 
+        (gnus-make-sort-function gnus-thread-sort-functions))
       (gnus-message 8 "Sorting threads...done"))))
 
 (defun gnus-sort-articles (articles)
@@ -3677,12 +3713,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)
@@ -4028,9 +4064,8 @@ or a straight list of headers."
             (cond
              ((string-match "<[^>]+> *$" gnus-tmp-from)
               (setq beg-match (match-beginning 0))
-              (or (and (string-match "^\"[^\"]*\"" gnus-tmp-from)
-                       (substring gnus-tmp-from (1+ (match-beginning 0))
-                                  (1- (match-end 0))))
+              (or (and (string-match "^\".+\"" gnus-tmp-from)
+                       (substring gnus-tmp-from 1 (1- (match-end 0))))
                   (substring gnus-tmp-from 0 beg-match)))
              ((string-match "(.+)" gnus-tmp-from)
               (substring gnus-tmp-from
@@ -4100,13 +4135,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.
@@ -4244,7 +4283,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.
@@ -4295,7 +4334,9 @@ If SELECT-ARTICLES, only select those articles from GROUP."
                    (if (string-match "^[ \t]*$" input)
                        number input)))
                 (t number))
-             (quit nil))))))
+             (quit
+              (message "Quit getting the articles to read")
+              nil))))))
     (setq select (if (stringp select) (string-to-number select) select))
     (if (or (null select) (zerop select))
        select
@@ -4317,7 +4358,7 @@ If SELECT-ARTICLES, only select those articles from GROUP."
             (gnus-sorted-complement gnus-newsgroup-unreads articles)))
       (when gnus-alter-articles-to-read-function
        (setq gnus-newsgroup-unreads
-             (sort 
+             (sort
               (funcall gnus-alter-articles-to-read-function
                        gnus-newsgroup-name gnus-newsgroup-unreads)
               '<)))
@@ -4429,12 +4470,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
@@ -4443,7 +4489,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)))
 
@@ -4451,7 +4497,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)
@@ -4467,7 +4513,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)
@@ -4483,7 +4529,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))
@@ -4720,19 +4770,20 @@ The resulting hash table is returned, or nil if no Xrefs were found."
            (progn
              (goto-char p)
              (if (search-forward "\nsubject: " nil t)
-                 (buffer-substring (match-end 0) (std11-field-end))
+                 (nnheader-header-value)
                "(none)"))
            ;; From.
            (progn
              (goto-char p)
-             (if (search-forward "\nfrom: " nil t)
-                 (buffer-substring (match-end 0) (std11-field-end))
+             (if (or (search-forward "\nfrom: " nil t)
+                     (search-forward "\nfrom:" nil t))
+                 (nnheader-header-value)
                "(nobody)"))
            ;; Date.
            (progn
              (goto-char p)
              (if (search-forward "\ndate: " nil t)
-                 (buffer-substring (match-end 0) (std11-field-end))
+                 (nnheader-header-value)
                ""))
            ;; Message-ID.
            (progn
@@ -4753,7 +4804,7 @@ The resulting hash table is returned, or nil if no Xrefs were found."
                  (progn
                    (setq end (point))
                    (prog1
-                       (buffer-substring (match-end 0) (std11-field-end))
+                       (nnheader-header-value)
                      (setq ref
                            (buffer-substring
                             (progn
@@ -4767,9 +4818,7 @@ 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
-                              (buffer-substring (match-end 0)
-                                                (std11-field-end)))
+                        (setq in-reply-to (nnheader-header-value))
                         (string-match "<[^>]+>" in-reply-to))
                    (let (ref2)
                      (setq ref (substring in-reply-to (match-beginning 0)
@@ -4799,7 +4848,7 @@ The resulting hash table is returned, or nil if no Xrefs were found."
            (progn
              (goto-char p)
              (and (search-forward "\nxref: " nil t)
-                  (buffer-substring (match-end 0) (std11-field-end))))
+                  (nnheader-header-value)))
            ;; Extra.
            (when gnus-extra-headers
              (let ((extra gnus-extra-headers)
@@ -4808,16 +4857,12 @@ 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)
-                               (buffer-substring (match-end 0)
-                                                 (std11-field-end)))
-                         out))
+                   (push (cons (car extra) (nnheader-header-value)) 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))))
+                  (setq ctype (nnheader-header-value)))
              (mime-entity-set-content-type-internal
               header (mime-parse-Content-Type ctype)))
          (when (equal id ref)
@@ -4840,8 +4885,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))
@@ -5159,8 +5205,7 @@ articles with that subject.  If BACKWARD, search backward instead."
   "Center point in window and redisplay frame.
 Also do horizontal recentering."
   (interactive "P")
-  (when (and nil
-            gnus-auto-center-summary
+  (when (and gnus-auto-center-summary
             (not (eq gnus-auto-center-summary 'vertical)))
     (gnus-horizontal-recenter))
   (recenter n))
@@ -6352,12 +6397,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)))))
@@ -6871,7 +6916,8 @@ of what's specified by the `gnus-refer-thread-limit' variable."
    ((eq 'current gnus-refer-article-method)
     (list gnus-current-select-method))
    ;; List of select methods.
-   ((not (stringp (cadr gnus-refer-article-method)))
+   ((not (and (symbolp (car gnus-refer-article-method))
+             (assq (car gnus-refer-article-method) nnoo-definition-alist)))
     (let (out)
       (dolist (method gnus-refer-article-method)
        (push (if (eq 'current method)
@@ -6921,7 +6967,10 @@ to guess what the document format is."
        ;; the parent article.
        (when (setq to-address (or (message-fetch-field "reply-to")
                                   (message-fetch-field "from")))
-         (setq params (append (list (cons 'to-address to-address)))))
+         (setq params (append 
+                       (list (cons 'to-address 
+                                   (funcall gnus-decode-encoded-word-function
+                                            to-address))))))
        (setq dig (nnheader-set-temp-buffer " *gnus digest buffer*"))
        (insert-buffer-substring gnus-original-article-buffer)
        ;; Remove lines that may lead nndoc to misinterpret the
@@ -7339,19 +7388,38 @@ 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))
-      (gnus-summary-select-article nil 'force)))
+      (gnus-summary-select-article nil 'force)
+      (let ((deps gnus-newsgroup-dependencies)
+           head header)
+       (save-excursion
+         (set-buffer gnus-original-article-buffer)
+         (save-restriction
+           (message-narrow-to-head)
+           (setq head (buffer-string)))
+         (with-temp-buffer
+           (insert (format "211 %d Article retrieved.\n"
+                           (cdr gnus-article-current)))
+           (insert head)
+           (insert ".\n")
+           (let ((nntp-server-buffer (current-buffer)))
+             (setq header (car (gnus-get-newsgroup-headers deps t))))))
+       (gnus-data-set-header
+        (gnus-data-find (cdr gnus-article-current))
+        header)
+       (gnus-summary-update-article-line
+        (cdr gnus-article-current) header))))
    ((not arg)
     ;; Select the article the normal way.
     (gnus-summary-select-article nil 'force))
@@ -7398,7 +7466,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))
@@ -7636,7 +7704,7 @@ ACTION can be either `move' (the default), `crosspost' or `copy'."
                 (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)))
@@ -7828,6 +7896,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
@@ -7843,19 +7914,19 @@ This will be the case if the article has both been mailed and posted."
                (setq es (gnus-request-expire-articles
                          expirable gnus-newsgroup-name)))
            (setq es (gnus-request-expire-articles
-                     expirable gnus-newsgroup-name))))
-       (unless total
-         (setq gnus-newsgroup-expirable es))
-       ;; We go through the old list of expirable, and mark all
-       ;; really expired articles as nonexistent.
-       (unless (eq es expirable)       ;If nothing was expired, we don't mark.
-         (let ((gnus-use-cache nil))
-           (while expirable
-             (unless (memq (car expirable) es)
-               (when (gnus-data-find (car expirable))
-                 (gnus-summary-mark-article
-                  (car expirable) gnus-canceled-mark)))
-             (setq expirable (cdr expirable)))))
+                     expirable gnus-newsgroup-name)))
+         (unless total
+           (setq gnus-newsgroup-expirable es))
+         ;; We go through the old list of expirable, and mark all
+         ;; really expired articles as nonexistent.
+         (unless (eq es expirable)     ;If nothing was expired, we don't mark.
+           (let ((gnus-use-cache nil))
+             (while expirable
+               (unless (memq (car expirable) es)
+                 (when (gnus-data-find (car expirable))
+                   (gnus-summary-mark-article
+                    (car expirable) gnus-canceled-mark)))
+               (setq expirable (cdr expirable))))))
        (gnus-message 6 "Expiring articles...done")))))
 
 (defun gnus-summary-expire-articles-now ()
@@ -7882,6 +7953,8 @@ delete these instead."
   (unless (gnus-check-backend-function 'request-expire-articles
                                       gnus-newsgroup-name)
     (error "The current newsgroup does not support article deletion"))
+  (unless (gnus-check-server (gnus-find-method-for-group gnus-newsgroup-name))
+    (error "Couldn't open server"))
   ;; Compute the list of articles to delete.
   (let ((articles (sort (copy-sequence (gnus-summary-work-articles n)) '<))
        not-deleted)
@@ -7927,6 +8000,8 @@ groups."
        'ignore
        `(lambda (no-highlight)
          (let ((mail-parse-charset ',gnus-newsgroup-charset)
+               (message-options message-options)
+               (message-options-set-recipient)
                (mail-parse-ignored-charsets
                 ',gnus-newsgroup-ignored-charsets))
            (gnus-summary-edit-article-done
@@ -8802,14 +8877,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)
@@ -9016,14 +9093,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))
@@ -9050,7 +9127,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."
@@ -9061,6 +9138,8 @@ Argument REVERSE means reverse order."
              thread
            `(lambda (t1 t2)
               (,thread t2 t1))))
+        (gnus-sort-gathered-threads-function
+         gnus-thread-sort-functions)
         (gnus-article-sort-functions
          (if (not reverse)
              article
@@ -9194,7 +9273,7 @@ save those articles instead."
        (set-buffer gnus-original-article-buffer)
        (save-restriction
          (nnheader-narrow-to-headers)
-         (while methods
+         (while (and methods (not split-name))
            (goto-char (point-min))
            (setq method (pop methods))
            (setq match (car method))
@@ -9213,7 +9292,7 @@ save those articles instead."
                    (save-restriction
                      (widen)
                      (setq result (eval match)))))
-             (setq split-name (append (cdr method) split-name))
+             (setq split-name (cdr method))
              (cond ((stringp result)
                     (push (expand-file-name
                            result gnus-article-save-directory)
@@ -9282,8 +9361,14 @@ save those articles instead."
   "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: " nil nil t)
+   (list (read-string "Save parts of type: " 
+                     (or (car gnus-summary-save-parts-type-history)
+                         gnus-summary-save-parts-default-mime)
+                     'gnus-summary-save-parts-type-history)
+        (setq gnus-summary-save-parts-last-directory
+              (read-file-name "Save to directory: " 
+                              gnus-summary-save-parts-last-directory
+                              nil t))
         current-prefix-arg))
   (gnus-summary-iterate n
     (let ((gnus-display-mime-function nil)
@@ -9291,10 +9376,12 @@ If REVERSE, save parts that do not match TYPE."
       (gnus-summary-select-article))
     (save-excursion
       (set-buffer gnus-article-buffer)
-      (let ((handles (or (mm-dissect-buffer) (mm-uu-dissect))))
+      (let ((handles (or gnus-article-mime-handles
+                        (mm-dissect-buffer) (mm-uu-dissect))))
        (when handles
          (gnus-summary-save-parts-1 type dir handles reverse)
-         (mm-destroy-parts handles))))))
+         (unless gnus-article-mime-handles ;; Don't destroy this case.
+           (mm-destroy-parts handles)))))))
 
 (defun gnus-summary-save-parts-1 (type dir handle reverse)
   (if (stringp (car handle))
@@ -9308,7 +9395,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))))))
@@ -9502,8 +9591,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)))
@@ -9598,23 +9687,32 @@ If REVERSE, save parts that do not match TYPE."
       (if compute
          read
        (save-excursion
-         (set-buffer gnus-group-buffer)
-         (gnus-undo-register
-           `(progn
-              (gnus-info-set-marks ',info ',(gnus-info-marks info) t)
-              (gnus-info-set-read ',info ',(gnus-info-read info))
-              (gnus-get-unread-articles-in-group ',info (gnus-active ,group))
-              (gnus-group-update-group ,group t))))
-       ;; Propagate the read marks to the backend.
-       (if (gnus-check-backend-function 'request-set-mark group)
-           (let ((del (gnus-remove-from-range (gnus-info-read info) read))
-                 (add (gnus-remove-from-range read (gnus-info-read info))))
-             (when (or add del)
-               (unless (gnus-check-group group)
-                 (error "Can't open server for %s" group))
-               (gnus-request-set-mark
-                group (delq nil (list (if add (list add 'add '(read)))
-                                      (if del (list del 'del '(read)))))))))
+         (let (setmarkundo)
+           ;; Propagate the read marks to the backend.
+           (when (gnus-check-backend-function 'request-set-mark group)
+             (let ((del (gnus-remove-from-range (gnus-info-read info) read))
+                   (add (gnus-remove-from-range read (gnus-info-read info))))
+               (when (or add del)
+                 (unless (gnus-check-group group)
+                   (error "Can't open server for %s" group))
+                 (gnus-request-set-mark
+                  group (delq nil (list (if add (list add 'add '(read)))
+                                        (if del (list del 'del '(read))))))
+                 (setq setmarkundo
+                       `(gnus-request-set-mark
+                         ,group
+                         ',(delq nil (list
+                                      (if del (list del 'add '(read)))
+                                      (if add (list add 'del '(read))))))))))
+           (set-buffer gnus-group-buffer)
+           (gnus-undo-register
+             `(progn
+                (gnus-info-set-marks ',info ',(gnus-info-marks info) t)
+                (gnus-info-set-read ',info ',(gnus-info-read info))
+                (gnus-get-unread-articles-in-group ',info 
+                                                   (gnus-active ,group))
+                (gnus-group-update-group ,group t)
+                ,setmarkundo))))
        ;; Enter this list into the group info.
        (gnus-info-set-read info read)
        ;; Set the number of unread articles in gnus-newsrc-hashtb.
@@ -9683,40 +9781,31 @@ If REVERSE, save parts that do not match TYPE."
 
 (defun gnus-mime-extract-message/rfc822 (entity situation)
   (let (group article num cwin swin cur)
-    (with-current-buffer (mime-entity-buffer entity)
-      (save-restriction
-       (narrow-to-region (mime-entity-body-start entity)
-                         (mime-entity-body-end 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)
-             )
-       ))
+    (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)
-           )
+           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)
-         )
+         (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-goto-subject article t))
        (gnus-summary-clear-mark-forward 1)
-       (gnus-summary-goto-subject cur)
-       )
+       (gnus-summary-goto-subject cur))
       (when (and cwin (window-frame cwin))
-       (select-frame (window-frame cwin))
-       )
+       (select-frame (window-frame cwin)))
       (when (boundp 'mime-acting-situation-to-override)
        (set-alist 'mime-acting-situation-to-override
                   'group
@@ -9726,15 +9815,11 @@ If REVERSE, save parts that do not match TYPE."
                   `(progn
                      (save-current-buffer
                        (set-buffer gnus-group-buffer)
-                       (gnus-activate-group ,group)
-                       )
+                       (gnus-activate-group ,group))
                      (gnus-summary-goto-article ,cur
-                                                gnus-show-all-headers)
-                     ))
+                                                gnus-show-all-headers)))
        (set-alist 'mime-acting-situation-to-override
-                  'number num)
-       )
-      )))
+                  'number num)))))
 
 (mime-add-condition
  'action '((type . message)(subtype . rfc822)
@@ -9762,7 +9847,7 @@ If REVERSE, save parts that do not match TYPE."
     (if (setq f (cdr (assq 'after-method
                           mime-acting-situation-to-override)))
        (eval f)
-      )))  
+      )))
 
 (mime-add-condition
  'action '((type . multipart)
@@ -9781,7 +9866,7 @@ If REVERSE, save parts that do not match TYPE."
       (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
@@ -9809,7 +9894,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))))
 
 ;;;
@@ -9904,7 +9989,7 @@ treated as multipart/mixed."
 (defun gnus-wheel-install ()
   "Enable mouse wheel support on summary window."
   (when gnus-use-wheel
-    (let ((keys 
+    (let ((keys
           '([(mouse-4)] [(shift mouse-4)] [(mouse-5)] [(shift mouse-5)])))
       (dolist (key keys)
        (define-key gnus-summary-mode-map key
@@ -9933,10 +10018,10 @@ groups."
        (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) 
+             (let ((inhibit-read-only t)
                    buffer-read-only)
                (delete-region armor-start
-                              (progn 
+                              (progn
                                 (re-search-forward "^-+END PGP" nil t)
                                 (beginning-of-line 2)
                                 (point)))
@@ -9986,8 +10071,8 @@ groups."
                   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)
@@ -10003,7 +10088,7 @@ returned."
        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)