Synch with Gnus.
[elisp/gnus.git-] / lisp / gnus-sum.el
index 7c38845..affdb84 100644 (file)
@@ -949,6 +949,8 @@ when prompting the user for which type of files to save."
 
 (defvar gnus-article-mime-handles nil)
 (defvar gnus-article-decoded-p nil)
+(defvar gnus-article-charset nil)
+(defvar gnus-article-ignored-charsets nil)
 (defvar gnus-scores-exclude-files nil)
 (defvar gnus-page-broken nil)
 (defvar gnus-inhibit-mime-unbuttonizing nil)
@@ -1151,6 +1153,8 @@ end position and text.")
 (defvar gnus-newsgroup-ephemeral-charset nil)
 (defvar gnus-newsgroup-ephemeral-ignored-charsets nil)
 
+(defvar gnus-article-before-search nil)
+
 (defconst gnus-summary-local-variables
   '(gnus-newsgroup-name
     gnus-newsgroup-begin gnus-newsgroup-end
@@ -1188,6 +1192,9 @@ end position and text.")
     gnus-newsgroup-incorporated)
   "Variables that are buffer-local to the summary buffers.")
 
+(defvar gnus-newsgroup-variables nil
+  "Variables that have separate values in the newsgroups.")
+
 ;; Byte-compiler warning.
 (defvar gnus-article-mode-map)
 
@@ -1662,7 +1669,9 @@ increase the score of each group you read."
     "v" gnus-article-view-part
     "o" gnus-article-save-part
     "c" gnus-article-copy-part
+    "C" gnus-article-view-part-as-charset
     "e" gnus-article-externalize-part
+    "E" gnus-article-encrypt-body
     "i" gnus-article-inline-part
     "|" gnus-article-pipe-part))
 
@@ -2093,6 +2102,8 @@ The following commands are available:
     (gnus-summary-make-menu-bar))
   (kill-all-local-variables)
   (gnus-summary-make-local-variables)
+  (let ((gnus-summary-local-variables gnus-newsgroup-variables))
+    (gnus-summary-make-local-variables))
   (gnus-make-thread-indent-array)
   (gnus-simplify-mode-line)
   (setq major-mode 'gnus-summary-mode)
@@ -2533,7 +2544,15 @@ buffer that was in action when the last article was fetched."
          (gac gnus-article-current)
          (reffed gnus-reffed-article-number)
          (score-file gnus-current-score-file)
-         (default-charset gnus-newsgroup-charset))
+         (default-charset gnus-newsgroup-charset)
+         vlist)
+      (let ((locals gnus-newsgroup-variables))
+       (while locals
+         (if (consp (car locals))
+             (push (eval (caar locals)) vlist)
+           (push (eval (car locals)) vlist))
+         (setq locals (cdr locals)))
+       (setq vlist (nreverse vlist)))
       (save-excursion
        (set-buffer gnus-group-buffer)
        (setq gnus-newsgroup-name name
@@ -2548,6 +2567,12 @@ buffer that was in action when the last article was fetched."
              gnus-reffed-article-number reffed
              gnus-current-score-file score-file
              gnus-newsgroup-charset default-charset)
+       (let ((locals gnus-newsgroup-variables))
+         (while locals
+           (if (consp (car locals))
+               (set (caar locals) (pop vlist))
+             (set (car locals) (pop vlist)))
+           (setq locals (cdr locals))))
        ;; The article buffer also has local variables.
        (when (gnus-buffer-live-p gnus-article-buffer)
          (set-buffer gnus-article-buffer)
@@ -2676,9 +2701,8 @@ buffer that was in action when the last article was fetched."
          (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
@@ -4065,9 +4089,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
@@ -4772,19 +4795,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
@@ -4805,7 +4829,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
@@ -4819,9 +4843,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)
@@ -4851,7 +4873,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)
@@ -4860,16 +4882,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)
@@ -5507,12 +5525,16 @@ If FORCE (the prefix), also save the .newsrc file(s)."
        ;; not garbage-collected, it seems.  This would the lead to en
        ;; ever-growing Emacs.
        (gnus-summary-clear-local-variables)
+       (let ((gnus-summary-local-variables gnus-newsgroup-variables))
+         (gnus-summary-clear-local-variables))
        (when (get-buffer gnus-article-buffer)
          (bury-buffer gnus-article-buffer))
        ;; We clear the global counterparts of the buffer-local
        ;; variables as well, just to be on the safe side.
        (set-buffer gnus-group-buffer)
        (gnus-summary-clear-local-variables)
+       (let ((gnus-summary-local-variables gnus-newsgroup-variables))
+         (gnus-summary-clear-local-variables))
        ;; Return to group mode buffer.
        (when (eq mode 'gnus-summary-mode)
          (gnus-kill-buffer buf)))
@@ -5556,8 +5578,12 @@ If FORCE (the prefix), also save the .newsrc file(s)."
          (gnus-deaden-summary)
        (gnus-close-group group)
        (gnus-summary-clear-local-variables)
+       (let ((gnus-summary-local-variables gnus-newsgroup-variables))
+         (gnus-summary-clear-local-variables))
        (set-buffer gnus-group-buffer)
        (gnus-summary-clear-local-variables)
+       (let ((gnus-summary-local-variables gnus-newsgroup-variables))
+         (gnus-summary-clear-local-variables))
        (when (get-buffer gnus-summary-buffer)
          (kill-buffer gnus-summary-buffer)))
       (unless gnus-single-article-buffer
@@ -5893,6 +5919,10 @@ Given a prefix, will force an `article' buffer configuration."
 (defun gnus-summary-display-article (article &optional all-header)
   "Display ARTICLE in article buffer."
   (gnus-set-global-variables)
+  (when (gnus-buffer-live-p gnus-article-buffer)
+    (with-current-buffer gnus-article-buffer
+      (setq gnus-article-charset gnus-newsgroup-charset)
+      (setq gnus-article-ignored-charsets gnus-newsgroup-ignored-charsets)))
   (if (null article)
       nil
     (prog1
@@ -5954,6 +5984,12 @@ be displayed."
          (gnus-article-show-all-headers))
        'old))))
 
+(defun gnus-summary-force-verify-and-decrypt ()
+  (interactive)
+  (let ((mm-verify-option 'known)
+       (mm-decrypt-option 'known))
+    (gnus-summary-select-article nil 'force)))
+
 (defun gnus-summary-set-current-mark (&optional current-mark)
   "Obsolete function."
   nil)
@@ -6923,7 +6959,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)
@@ -7083,10 +7120,14 @@ If BACKWARD, search backward instead."
         current-prefix-arg))
   (if (string-equal regexp "")
       (setq regexp (or gnus-last-search-regexp ""))
-    (setq gnus-last-search-regexp regexp))
-  (if (gnus-summary-search-article regexp backward)
-      (gnus-summary-show-thread)
-    (error "Search failed: \"%s\"" regexp)))
+    (setq gnus-last-search-regexp regexp)
+    (setq gnus-article-before-search gnus-current-article))
+  ;; Intentionally set gnus-last-article.
+  (setq gnus-last-article gnus-article-before-search)
+  (let ((gnus-last-article gnus-last-article))
+    (if (gnus-summary-search-article regexp backward)
+       (gnus-summary-show-thread)
+      (error "Search failed: \"%s\"" regexp))))
 
 (defun gnus-summary-search-article-backward (regexp)
   "Search for an article containing REGEXP backward."
@@ -7406,7 +7447,26 @@ without any article massaging functions being run."
           (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))
@@ -7901,19 +7961,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 ()
@@ -7987,6 +8047,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
@@ -7999,10 +8061,31 @@ groups."
                                                 no-highlight)
   "Make edits to the current article permanent."
   (interactive)
+  (save-excursion
+    ;; The buffer restriction contains the entire article if it exists.
+    (when (article-goto-body)
+      (let ((lines (count-lines (point) (point-max)))
+           (length (- (point-max) (point)))
+           (case-fold-search t)
+           (body (copy-marker (point))))
+       (goto-char (point-min))
+       (when (re-search-forward "^content-length:[ \t]\\([0-9]+\\)" body t)
+         (delete-region (match-beginning 1) (match-end 1))
+         (insert (number-to-string length)))
+       (goto-char (point-min))
+       (when (re-search-forward
+              "^x-content-length:[ \t]\\([0-9]+\\)" body t)
+         (delete-region (match-beginning 1) (match-end 1))
+         (insert (number-to-string length)))
+       (goto-char (point-min))
+       (when (re-search-forward "^lines:[ \t]\\([0-9]+\\)" body t)
+         (delete-region (match-beginning 1) (match-end 1))
+         (insert (number-to-string lines))))))
   ;; Replace the article.
   (let ((buf (current-buffer)))
     (with-temp-buffer
       (insert-buffer-substring buf)
+      
       (if (and (not read-only)
               (not (gnus-request-replace-article
                     (cdr gnus-article-current) (car gnus-article-current)