Protect against non-existant colour names.
[gnus] / lisp / gnus-sum.el
index 2eedc07..ff85d45 100644 (file)
@@ -1310,6 +1310,7 @@ the normal Gnus MIME machinery."
 (defvar gnus-article-decoded-p nil)
 (defvar gnus-article-charset nil)
 (defvar gnus-article-ignored-charsets nil)
+(defvar gnus-article-original-subject nil)
 (defvar gnus-scores-exclude-files nil)
 (defvar gnus-page-broken nil)
 
@@ -1335,6 +1336,7 @@ the normal Gnus MIME machinery."
 (defvar gnus-current-copy-group nil)
 (defvar gnus-current-crosspost-group nil)
 (defvar gnus-newsgroup-display nil)
+(defvar gnus-newsgroup-original-name nil)
 
 (defvar gnus-newsgroup-dependencies nil)
 (defvar gnus-newsgroup-adaptive nil)
@@ -2061,6 +2063,7 @@ increase the score of each group you read."
   "D" gnus-summary-enter-digest-group
   "R" gnus-summary-refer-references
   "T" gnus-summary-refer-thread
+  "W" gnus-warp-to-article
   "g" gnus-summary-show-article
   "s" gnus-summary-isearch-article
   "P" gnus-summary-print-article
@@ -2095,6 +2098,7 @@ increase the score of each group you read."
   "a" gnus-article-strip-headers-in-body ;; mnemonic: wash archive
   "p" gnus-article-verify-x-pgp-sig
   "d" gnus-article-treat-dumbquotes
+  "U" gnus-article-treat-non-ascii
   "i" gnus-summary-idna-message)
 
 (gnus-define-keys (gnus-summary-wash-deuglify-map "Y" gnus-summary-wash-map)
@@ -2132,7 +2136,7 @@ increase the score of each group you read."
   "d" gnus-article-display-face
   "s" gnus-treat-smiley
   "D" gnus-article-remove-images
-  "W" gnus-html-show-images
+  "W" gnus-article-show-images
   "f" gnus-treat-from-picon
   "m" gnus-treat-mail-picon
   "n" gnus-treat-newsgroups-picon
@@ -2419,6 +2423,7 @@ gnus-summary-show-article-from-menu-as-charset-%s" cs))))
                gnus-article-remove-leading-whitespace t])
              ["Overstrike" gnus-article-treat-overstrike t]
              ["Dumb quotes" gnus-article-treat-dumbquotes t]
+             ["Non-ASCII" gnus-article-treat-non-ascii t]
              ["Emphasis" gnus-article-emphasize t]
              ["Word wrap" gnus-article-fill-cited-article t]
              ["Fill long lines" gnus-article-fill-long-lines t]
@@ -5468,7 +5473,7 @@ or a straight list of headers."
                          (substring subject (match-end 1)))))
          (mail-header-set-subject header subject))))))
 
-(defun gnus-fetch-headers (articles)
+(defun gnus-fetch-headers (articles &optional limit force-new dependencies)
   "Fetch headers of ARTICLES."
   (let ((name (gnus-group-decoded-name gnus-newsgroup-name)))
     (gnus-message 5 "Fetching headers for %s..." name)
@@ -5477,16 +5482,17 @@ or a straight list of headers."
                (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))))
+                      (or limit
+                          ;; 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))
+            articles force-new dependencies gnus-newsgroup-name t)
+         (gnus-get-newsgroup-headers dependencies force-new))
       (gnus-message 5 "Fetching headers for %s...done" name))))
 
 (defun gnus-select-newsgroup (group &optional read-all select-articles)
@@ -8835,46 +8841,39 @@ fetch LIMIT (the numerical prefix) old headers. If LIMIT is nil
 fetch what's specified by the `gnus-refer-thread-limit'
 variable."
   (interactive "P")
+  (gnus-warp-to-article)
   (let ((id (mail-header-id (gnus-summary-article-header)))
-       (subject (gnus-simplify-subject
-                 (mail-header-subject (gnus-summary-article-header))))
-       (refs (split-string (or (mail-header-references
-                                (gnus-summary-article-header)) "")))
-       (gnus-summary-ignore-duplicates t)
        (gnus-inhibit-demon t)
+       (gnus-agent nil)
+       (gnus-summary-ignore-duplicates t)
        (gnus-read-all-available-headers t)
        (limit (if limit (prefix-numeric-value limit)
                 gnus-refer-thread-limit)))
-    (if  (gnus-check-backend-function 'request-thread gnus-newsgroup-name)
-       (setq gnus-newsgroup-headers
-             (gnus-merge 'list
-                         gnus-newsgroup-headers
-                         (gnus-request-thread id)
-                         'gnus-article-sort-by-number))
-      (unless (eq gnus-fetch-old-headers 'invisible)
-       (gnus-message 5 "Fetching headers for %s..." gnus-newsgroup-name)
-       ;;      Retrieve the headers and read them in.
-       (if (numberp limit)
-           (gnus-retrieve-headers
-            (list (min
-                   (+ (mail-header-number
-                       (gnus-summary-article-header))
-                      limit)
-                   gnus-newsgroup-end))
-            gnus-newsgroup-name (* limit 2))
-         ;; gnus-refer-thread-limit is t, i.e. fetch _all_
-         ;; headers.
-         (gnus-retrieve-headers (list gnus-newsgroup-end)
-                                gnus-newsgroup-name limit)
-         (gnus-message 5 "Fetching headers for %s...done"
-                       gnus-newsgroup-name))))
-    (when (eq gnus-headers-retrieved-by 'nov)
-      ;; might as well restrict the headers to the relevant ones. this
-      ;; should save time when building threads.
-      (with-current-buffer nntp-server-buffer
-       (goto-char (point-min))
-       (keep-lines (regexp-opt (append refs (list id subject)))))
-      (gnus-build-all-threads))
+    (setq gnus-newsgroup-headers
+         (gnus-merge
+          'list gnus-newsgroup-headers
+          (if (gnus-check-backend-function
+               'request-thread gnus-newsgroup-name)
+              (gnus-request-thread id)
+            (let* ((last (if (numberp limit)
+                             (min (+ (mail-header-number
+                                      (gnus-summary-article-header))
+                                     limit)
+                                  gnus-newsgroup-highest)
+                           gnus-newsgroup-highest))
+                   (subject (gnus-simplify-subject
+                             (mail-header-subject
+                              (gnus-summary-article-header))))
+                   (refs (split-string (or (mail-header-references
+                                            (gnus-summary-article-header))
+                                           "")))
+                   (gnus-parse-headers-hook
+                    (lambda () (goto-char (point-min))
+                      (keep-lines
+                       (regexp-opt (append refs (list id subject)))))))
+              (gnus-fetch-headers (list last) (if (numberp limit)
+                                                  (* 2 limit) limit) t)))
+          'gnus-article-sort-by-number))
     (gnus-summary-limit-include-thread id)))
 
 (defun gnus-summary-refer-article (message-id)
@@ -9706,196 +9705,210 @@ ACTION can be either `move' (the default), `crosspost' or `copy'."
                  articles)
     (while articles
       (setq article (pop articles))
-      (setq
-       art-group
-       (cond
-       ;; Move the article.
-       ((eq action 'move)
-        ;; Remove this article from future suppression.
-        (gnus-dup-unsuppress-article article)
-        (let* ((from-method (gnus-find-method-for-group
-                             gnus-newsgroup-name))
-               (to-method (or select-method
-                              (gnus-find-method-for-group to-newsgroup)))
-               (move-is-internal (gnus-server-equal from-method to-method)))
-          (gnus-request-move-article
-           article                     ; Article to move
-           gnus-newsgroup-name         ; From newsgroup
-           (nth 1 (gnus-find-method-for-group
-                   gnus-newsgroup-name)) ; Server
-           (list 'gnus-request-accept-article
-                 to-newsgroup (list 'quote select-method)
-                 (not articles) t)     ; Accept form
-           (not articles)              ; Only save nov last time
-           (and move-is-internal
-                to-newsgroup           ; Not respooling
-                (gnus-group-real-name to-newsgroup))))) ; Is this move internal?
-       ;; Copy the article.
-       ((eq action 'copy)
-        (with-current-buffer copy-buf
-          (when (gnus-request-article-this-buffer article gnus-newsgroup-name)
-            (save-restriction
-              (nnheader-narrow-to-headers)
-              (dolist (hdr gnus-copy-article-ignored-headers)
-                (message-remove-header hdr t)))
-            (gnus-request-accept-article
-             to-newsgroup select-method (not articles) t))))
-       ;; Crosspost the article.
-       ((eq action 'crosspost)
-        (let ((xref (message-tokenize-header
-                     (mail-header-xref (gnus-summary-article-header article))
-                     " ")))
-          (setq new-xref (concat (gnus-group-real-name gnus-newsgroup-name)
-                                 ":" (number-to-string article)))
-          (unless xref
-            (setq xref (list (system-name))))
-          (setq new-xref
-                (concat
-                 (mapconcat 'identity
-                            (delete "Xref:" (delete new-xref xref))
-                            " ")
-                 " " new-xref))
+      (let ((gnus-newsgroup-original-name gnus-newsgroup-name)
+           (gnus-article-original-subject
+            (mail-header-subject
+             (gnus-data-header (assoc article (gnus-data-list nil))))))
+       (setq
+        art-group
+        (cond
+         ;; Move the article.
+         ((eq action 'move)
+          ;; Remove this article from future suppression.
+          (gnus-dup-unsuppress-article article)
+          (let* ((from-method (gnus-find-method-for-group
+                               gnus-newsgroup-name))
+                 (to-method (or select-method
+                                (gnus-find-method-for-group to-newsgroup)))
+                 (move-is-internal (gnus-server-equal from-method to-method)))
+            (gnus-request-move-article
+             article                   ; Article to move
+             gnus-newsgroup-name       ; From newsgroup
+             (nth 1 (gnus-find-method-for-group
+                     gnus-newsgroup-name)) ; Server
+             (list 'gnus-request-accept-article
+                   to-newsgroup (list 'quote select-method)
+                   (not articles) t)   ; Accept form
+             (not articles)            ; Only save nov last time
+             (and move-is-internal
+                  to-newsgroup         ; Not respooling
+                                       ; Is this move internal?
+                  (gnus-group-real-name to-newsgroup)))))
+         ;; Copy the article.
+         ((eq action 'copy)
           (with-current-buffer copy-buf
-            ;; First put the article in the destination group.
-            (gnus-request-article-this-buffer article gnus-newsgroup-name)
-            (when (consp (setq art-group
-                               (gnus-request-accept-article
-                                to-newsgroup select-method (not articles) t)))
-              (setq new-xref (concat new-xref " " (car art-group)
-                                     ":"
-                                     (number-to-string (cdr art-group))))
-              ;; Now we have the new Xrefs header, so we insert
-              ;; it and replace the new article.
-              (nnheader-replace-header "Xref" new-xref)
-              (gnus-request-replace-article
-               (cdr art-group) to-newsgroup (current-buffer) t)
-              art-group))))))
-      (cond
-       ((not art-group)
-       (gnus-message 1 "Couldn't %s article %s: %s"
-                     (cadr (assq action names)) article
-                     (nnheader-get-report (car to-method))))
-       ((eq art-group 'junk)
-       (when (eq action 'move)
-         (gnus-summary-mark-article article gnus-canceled-mark)
-         (gnus-message 4 "Deleted article %s" article)
-         ;; run the delete hook
-         (run-hook-with-args 'gnus-summary-article-delete-hook
-                             action
-                             (gnus-data-header
-                              (assoc article (gnus-data-list nil)))
-                             gnus-newsgroup-name nil
-                             select-method)))
-       (t
-       (let* ((pto-group (gnus-group-prefixed-name
-                          (car art-group) to-method))
-              (info (gnus-get-info pto-group))
-              (to-group (gnus-info-group info))
-              to-marks)
-         ;; Update the group that has been moved to.
-         (when (and info
-                    (memq action '(move copy)))
-           (unless (member to-group to-groups)
-             (push to-group to-groups))
-
-           (unless (memq article gnus-newsgroup-unreads)
-             (push 'read to-marks)
-             (gnus-info-set-read
-              info (gnus-add-to-range (gnus-info-read info)
-                                      (list (cdr art-group)))))
-
-           ;; See whether the article is to be put in the cache.
-           (let* ((expirable (gnus-group-auto-expirable-p to-group))
-                  (marks (if expirable
-                             gnus-article-mark-lists
-                           (delete '(expirable . expire)
-                                   (copy-sequence gnus-article-mark-lists))))
-                  (to-article (cdr art-group)))
-
-             ;; Enter the article into the cache in the new group,
-             ;; if that is required.
-             (when gnus-use-cache
-               (gnus-cache-possibly-enter-article
-                to-group to-article
-                (memq article gnus-newsgroup-marked)
-                (memq article gnus-newsgroup-dormant)
-                (memq article gnus-newsgroup-unreads)))
-
-             (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)))
-                 ;; Mark this article as read in this group.
-                 (push (cons to-article gnus-read-mark) gnus-newsgroup-reads)
-                 ;; Increase the active status of this group.
-                 (setcdr (gnus-active to-group) to-article)
-                 (setcdr gnus-newsgroup-active to-article))
-
-               (while marks
-                 (when (eq (gnus-article-mark-to-type (cdar marks)) 'list)
-                   (when (memq article (symbol-value
-                                        (intern (format "gnus-newsgroup-%s"
-                                                        (caar marks)))))
-                     (push (cdar marks) to-marks)
-                     ;; If the other group is the same as this group,
-                     ;; then we have to add the mark to the list.
-                     (when (equal to-group gnus-newsgroup-name)
-                       (set (intern (format "gnus-newsgroup-%s" (caar marks)))
-                            (cons to-article
-                                  (symbol-value
-                                   (intern (format "gnus-newsgroup-%s"
-                                                   (caar marks)))))))
-                     ;; Copy the marks to other group.
-                     (gnus-add-marked-articles
-                      to-group (cdar marks) (list to-article) info)))
-                 (setq marks (cdr marks)))
-
-               (when (and expirable
-                          gnus-mark-copied-or-moved-articles-as-expirable
-                          (not (memq 'expire to-marks)))
-                 ;; Mark this article as expirable.
-                 (push 'expire to-marks)
-                 (when (equal to-group gnus-newsgroup-name)
-                   (push to-article gnus-newsgroup-expirable))
-                 ;; Copy the expirable mark to other group.
-                 (gnus-add-marked-articles
-                  to-group 'expire (list to-article) info))
-
-               (when to-marks
-                 (gnus-request-set-mark
-                  to-group (list (list (list to-article) 'add to-marks)))))
-
-             (gnus-dribble-enter
-              (concat "(gnus-group-set-info '"
-                      (gnus-prin1-to-string (gnus-get-info to-group))
-                      ")"))))
-
-         ;; Update the Xref header in this article to point to
-         ;; the new crossposted article we have just created.
-         (when (eq action 'crosspost)
-           (with-current-buffer copy-buf
-             (gnus-request-article-this-buffer article gnus-newsgroup-name)
-             (nnheader-replace-header "Xref" new-xref)
-             (gnus-request-replace-article
-              article gnus-newsgroup-name (current-buffer) t)))
-
-         ;; run the move/copy/crosspost/respool hook
-         (run-hook-with-args 'gnus-summary-article-move-hook
-                             action
-                             (gnus-data-header
-                              (assoc article (gnus-data-list nil)))
-                             gnus-newsgroup-name
-                             to-newsgroup
-                             select-method))
-
-       ;;;!!!Why is this necessary?
-       (set-buffer gnus-summary-buffer)
-
-       (when (eq action 'move)
-         (save-excursion
-           (gnus-summary-goto-subject article)
-           (gnus-summary-mark-article article gnus-canceled-mark)))))
-      (push article articles-to-update-marks))
+            (when (gnus-request-article-this-buffer article
+                                                    gnus-newsgroup-name)
+              (save-restriction
+                (nnheader-narrow-to-headers)
+                (dolist (hdr gnus-copy-article-ignored-headers)
+                  (message-remove-header hdr t)))
+              (gnus-request-accept-article
+               to-newsgroup select-method (not articles) t))))
+         ;; Crosspost the article.
+         ((eq action 'crosspost)
+          (let ((xref (message-tokenize-header
+                       (mail-header-xref (gnus-summary-article-header
+                                          article))
+                       " ")))
+            (setq new-xref (concat (gnus-group-real-name gnus-newsgroup-name)
+                                   ":" (number-to-string article)))
+            (unless xref
+              (setq xref (list (system-name))))
+            (setq new-xref
+                  (concat
+                   (mapconcat 'identity
+                              (delete "Xref:" (delete new-xref xref))
+                              " ")
+                   " " new-xref))
+            (with-current-buffer copy-buf
+              ;; First put the article in the destination group.
+              (gnus-request-article-this-buffer article gnus-newsgroup-name)
+              (when (consp (setq art-group
+                                 (gnus-request-accept-article
+                                  to-newsgroup select-method (not articles)
+                                  t)))
+                (setq new-xref (concat new-xref " " (car art-group)
+                                       ":"
+                                       (number-to-string (cdr art-group))))
+                ;; Now we have the new Xrefs header, so we insert
+                ;; it and replace the new article.
+                (nnheader-replace-header "Xref" new-xref)
+                (gnus-request-replace-article
+                 (cdr art-group) to-newsgroup (current-buffer) t)
+                art-group))))))
+       (cond
+        ((not art-group)
+         (gnus-message 1 "Couldn't %s article %s: %s"
+                       (cadr (assq action names)) article
+                       (nnheader-get-report (car to-method))))
+        ((eq art-group 'junk)
+         (when (eq action 'move)
+           (gnus-summary-mark-article article gnus-canceled-mark)
+           (gnus-message 4 "Deleted article %s" article)
+           ;; run the delete hook
+           (run-hook-with-args 'gnus-summary-article-delete-hook
+                               action
+                               (gnus-data-header
+                                (assoc article (gnus-data-list nil)))
+                               gnus-newsgroup-original-name nil
+                               select-method)))
+        (t
+         (let* ((pto-group (gnus-group-prefixed-name
+                            (car art-group) to-method))
+                (info (gnus-get-info pto-group))
+                (to-group (gnus-info-group info))
+                to-marks)
+           ;; Update the group that has been moved to.
+           (when (and info
+                      (memq action '(move copy)))
+             (unless (member to-group to-groups)
+               (push to-group to-groups))
+
+             (unless (memq article gnus-newsgroup-unreads)
+               (push 'read to-marks)
+               (gnus-info-set-read
+                info (gnus-add-to-range (gnus-info-read info)
+                                        (list (cdr art-group)))))
+
+             ;; See whether the article is to be put in the cache.
+             (let* ((expirable (gnus-group-auto-expirable-p to-group))
+                    (marks (if expirable
+                               gnus-article-mark-lists
+                             (delete '(expirable . expire)
+                                     (copy-sequence
+                                      gnus-article-mark-lists))))
+                    (to-article (cdr art-group)))
+
+               ;; Enter the article into the cache in the new group,
+               ;; if that is required.
+               (when gnus-use-cache
+                 (gnus-cache-possibly-enter-article
+                  to-group to-article
+                  (memq article gnus-newsgroup-marked)
+                  (memq article gnus-newsgroup-dormant)
+                  (memq article gnus-newsgroup-unreads)))
+
+               (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)))
+                   ;; Mark this article as read in this group.
+                   (push (cons to-article gnus-read-mark)
+                         gnus-newsgroup-reads)
+                   ;; Increase the active status of this group.
+                   (setcdr (gnus-active to-group) to-article)
+                   (setcdr gnus-newsgroup-active to-article))
+
+                 (while marks
+                   (when (eq (gnus-article-mark-to-type (cdar marks)) 'list)
+                     (when (memq article (symbol-value
+                                          (intern (format "gnus-newsgroup-%s"
+                                                          (caar marks)))))
+                       (push (cdar marks) to-marks)
+                       ;; If the other group is the same as this group,
+                       ;; then we have to add the mark to the list.
+                       (when (equal to-group gnus-newsgroup-name)
+                         (set (intern (format "gnus-newsgroup-%s"
+                                              (caar marks)))
+                              (cons to-article
+                                    (symbol-value
+                                     (intern (format "gnus-newsgroup-%s"
+                                                     (caar marks)))))))
+                       ;; Copy the marks to other group.
+                       (gnus-add-marked-articles
+                        to-group (cdar marks) (list to-article) info)))
+                   (setq marks (cdr marks)))
+
+                 (when (and expirable
+                            gnus-mark-copied-or-moved-articles-as-expirable
+                            (not (memq 'expire to-marks)))
+                   ;; Mark this article as expirable.
+                   (push 'expire to-marks)
+                   (when (equal to-group gnus-newsgroup-name)
+                     (push to-article gnus-newsgroup-expirable))
+                   ;; Copy the expirable mark to other group.
+                   (gnus-add-marked-articles
+                    to-group 'expire (list to-article) info))
+
+                 (when to-marks
+                   (gnus-request-set-mark
+                    to-group (list (list (list to-article) 'add to-marks)))))
+
+               (gnus-dribble-enter
+                (concat "(gnus-group-set-info '"
+                        (gnus-prin1-to-string (gnus-get-info to-group))
+                        ")"))))
+
+           ;; Update the Xref header in this article to point to
+           ;; the new crossposted article we have just created.
+           (when (eq action 'crosspost)
+             (with-current-buffer copy-buf
+               (gnus-request-article-this-buffer article gnus-newsgroup-name)
+               (nnheader-replace-header "Xref" new-xref)
+               (gnus-request-replace-article
+                article gnus-newsgroup-name (current-buffer) t)))
+
+           ;; run the move/copy/crosspost/respool hook
+           (let ((header (gnus-data-header
+                          (assoc article (gnus-data-list nil)))))
+             (mail-header-set-subject header gnus-article-original-subject)
+             (run-hook-with-args 'gnus-summary-article-move-hook
+                                 action
+                                 (gnus-data-header
+                                  (assoc article (gnus-data-list nil)))
+                                 gnus-newsgroup-original-name
+                                 to-newsgroup
+                                 select-method)))
+
+         ;;;!!!Why is this necessary?
+         (set-buffer gnus-summary-buffer)
+
+         (when (eq action 'move)
+           (save-excursion
+             (gnus-summary-goto-subject article)
+             (gnus-summary-mark-article article gnus-canceled-mark)))))
+       (push article articles-to-update-marks)))
 
     (save-excursion
       (apply 'gnus-summary-remove-process-mark articles-to-update-marks))