2006-04-30 Andreas Seltenreich <uwi7@rz.uni-karlsruhe.de>
[gnus] / lisp / gnus-sum.el
index 980c54b..5b2bb85 100644 (file)
@@ -87,7 +87,7 @@ locally cached header entries."
                 number
                 (sexp :menu-tag "other" t)))
 
-(defcustom gnus-refer-thread-limit 200
+(defcustom gnus-refer-thread-limit 500
   "*The number of old headers to fetch when doing \\<gnus-summary-mode-map>\\[gnus-summary-refer-thread].
 If t, fetch all the available old headers."
   :group 'gnus-thread
@@ -1712,6 +1712,8 @@ increase the score of each group you read."
   "," gnus-summary-best-unread-article
   "\M-s" gnus-summary-search-article-forward
   "\M-r" gnus-summary-search-article-backward
+  "\M-S" gnus-summary-repeat-search-article-forward
+  "\M-R" gnus-summary-repeat-search-article-backward
   "<" gnus-summary-beginning-of-article
   ">" gnus-summary-end-of-article
   "j" gnus-summary-goto-article
@@ -1843,6 +1845,7 @@ increase the score of each group you read."
 (gnus-define-keys (gnus-summary-limit-map "/" gnus-summary-mode-map)
   "/" gnus-summary-limit-to-subject
   "n" gnus-summary-limit-to-articles
+  "b" gnus-summary-limit-to-bodies
   "w" gnus-summary-pop-limit
   "s" gnus-summary-limit-to-subject
   "a" gnus-summary-limit-to-author
@@ -1889,6 +1892,7 @@ increase the score of each group you read."
   "T" gnus-summary-toggle-threads
   "t" gnus-summary-rethread-current
   "^" gnus-summary-reparent-thread
+  "\M-^" gnus-summary-reparent-children
   "s" gnus-summary-show-thread
   "S" gnus-summary-show-all-threads
   "h" gnus-summary-hide-thread
@@ -2083,6 +2087,7 @@ increase the score of each group you read."
   "O" gnus-article-save-part-and-strip
   "r" gnus-article-replace-part
   "d" gnus-article-delete-part
+  "t" gnus-article-view-part-as-type
   "j" gnus-article-jump-to-part
   "c" gnus-article-copy-part
   "C" gnus-article-view-part-as-charset
@@ -2230,6 +2235,7 @@ increase the score of each group you read."
               ["Repair multipart" gnus-summary-repair-multipart t]
               ["Pipe part..." gnus-article-pipe-part t]
               ["Inline part" gnus-article-inline-part t]
+              ["View part as type..." gnus-article-view-part-as-type t]
               ["Encrypt body" gnus-article-encrypt-body
                :active (not (gnus-group-read-only-p))
               ,@(if (featurep 'xemacs) nil
@@ -2700,10 +2706,14 @@ Pre-defined symbols include `gnus-summary-tool-bar-gnome' and
      :visible (gnus-check-backend-function 'request-expire-articles
                                           gnus-newsgroup-name))
     (gnus-summary-mark-as-spam
-     "mail/spam" t :visible (spam-group-ham-contents-p gnus-newsgroup-name)
+     "mail/spam" t
+     :visible (and (fboundp 'spam-group-ham-contents-p)
+                  (spam-group-ham-contents-p gnus-newsgroup-name))
      :help "Mark as spam")
     (gnus-summary-mark-as-read-forward
-     "mail/not-spam" nil :visible (spam-group-spam-contents-p gnus-newsgroup-name))
+     "mail/not-spam" nil
+     :visible (and (fboundp 'spam-group-spam-contents-p)
+                  (spam-group-spam-contents-p gnus-newsgroup-name)))
     ;;
     (gnus-summary-exit "exit")
     (gmm-customize-mode "preferences" t :help "Edit mode preferences")
@@ -2763,6 +2773,8 @@ See `gmm-tool-bar-from-list' for the format of the list."
   :set 'gnus-summary-tool-bar-update
   :group 'gnus-summary)
 
+(defvar image-load-path)
+
 (defun gnus-summary-make-tool-bar (&optional force)
   "Make a summary mode tool bar from `gnus-summary-tool-bar'.
 When FORCE, rebuild the tool bar."
@@ -2771,9 +2783,12 @@ When FORCE, rebuild the tool bar."
             tool-bar-mode
             (or (not gnus-summary-tool-bar-map) force))
     (let* ((load-path
-           (gmm-image-load-path "gnus" "mail/save.xpm" 'load-path))
-          (image-load-path
-           (gmm-image-load-path "gnus" "mail/save.xpm" 'image-load-path))
+           (gmm-image-load-path-for-library "gnus"
+                                            "mail/save.xpm"
+                                            nil t))
+           (image-load-path (cons (car load-path)
+                                  (when (boundp 'image-load-path)
+                                    image-load-path)))
           (map (gmm-tool-bar-from-list gnus-summary-tool-bar
                                        gnus-summary-tool-bar-zap-list
                                        'gnus-summary-mode-map)))
@@ -3294,7 +3309,7 @@ display only a single character."
     ;; We keep TAB as well.
     (aset table ?\t nil)
     ;; We nix out any glyphs 127 through 255, or 127 through 159 in
-    ;; Emacs 23, that are not set already.
+    ;; Emacs 23 (unicode), that are not set already.
     (let ((i (if (ignore-errors (= (make-char 'latin-iso8859-1 160) 160))
                 160
               256)))
@@ -3513,7 +3528,14 @@ buffer that was in action when the last article was fetched."
                      (inline
                        (gnus-summary-extract-address-component
                         (funcall gnus-decode-encoded-word-function to)))))
-            ((setq newsgroups (cdr (assq 'Newsgroups extra-headers)))
+            ((setq newsgroups
+                   (or
+                    (cdr (assq 'Newsgroups extra-headers))
+                    (and
+                     (memq 'Newsgroups gnus-extra-headers)
+                      (eq (car (gnus-find-method-for-group
+                                gnus-newsgroup-name)) 'nntp)
+                     (gnus-group-real-name gnus-newsgroup-name))))
              (concat gnus-summary-newsgroup-prefix newsgroups)))))
      (inline (gnus-summary-extract-address-component gnus-tmp-from)))))
 
@@ -6161,7 +6183,8 @@ Return a list of headers that match SEQUENCE (see
        (allp (cond
               ((eq gnus-read-all-available-headers t)
                t)
-              ((stringp gnus-read-all-available-headers)
+              ((and (stringp gnus-read-all-available-headers)
+                    group)
                (string-match gnus-read-all-available-headers group))
               (t
                nil)))
@@ -7983,6 +8006,38 @@ If ALL is non-nil, limit strictly to unread articles."
           gnus-duplicate-mark gnus-souped-mark)
      'reverse)))
 
+(defun gnus-summary-limit-to-bodies (match &optional reverse)
+  "Limit the summary buffer to articles that have bodies that match MATCH.
+If REVERSE (the prefix), limit to articles that don't match."
+  (interactive "sMatch body (regexp): \nP")
+  (let ((articles nil)
+       (gnus-select-article-hook nil)  ;Disable hook.
+       (gnus-article-prepare-hook nil)
+       (gnus-use-article-prefetch nil)
+       (gnus-keep-backlog nil)
+       (gnus-break-pages nil)
+       (gnus-summary-display-arrow nil)
+       (gnus-updated-mode-lines nil)
+       (gnus-auto-center-summary nil)
+       (gnus-display-mime-function nil))
+    (dolist (data gnus-newsgroup-data)
+      (let (gnus-mark-article-hook)
+       (gnus-summary-select-article t t nil (gnus-data-number data)))
+      (save-excursion
+       (set-buffer gnus-article-buffer)
+       (article-goto-body)
+       (let* ((case-fold-search t)
+              (found (re-search-forward match nil t)))
+         (when (or (and found
+                        (not reverse))
+                   (and (not found)
+                        reverse))
+           (push (gnus-data-number data) articles)))))
+    (if (not articles)
+       (message "No messages matched")
+      (gnus-summary-limit articles)))
+  (gnus-summary-position-point))
+
 (defun gnus-summary-limit-to-replied (&optional unreplied)
   "Limit the summary buffer to replied articles.
 If UNREPLIED (the prefix), limit to unreplied articles."
@@ -8667,6 +8722,20 @@ If REGEXP-P (the prefix) is non-nil, do regexp isearch."
       (widen)
       (isearch-forward regexp-p))))
 
+(defun gnus-summary-repeat-search-article-forward ()
+  "Repeat the previous search forwards."
+  (interactive)
+  (unless gnus-last-search-regexp
+    (error "No previous search"))
+  (gnus-summary-search-article-forward gnus-last-search-regexp))
+
+(defun gnus-summary-repeat-search-article-backward ()
+  "Repeat the previous search backwards."
+  (interactive)
+  (unless gnus-last-search-regexp
+    (error "No previous search"))
+  (gnus-summary-search-article-forward gnus-last-search-regexp t))
+
 (defun gnus-summary-search-article-forward (regexp &optional backward)
   "Search for an article containing REGEXP forward.
 If BACKWARD, search backward instead."
@@ -9134,10 +9203,6 @@ installed for this command to work."
              (replace-match (idna-to-unicode (match-string 1))))
            (set-window-start (get-buffer-window (current-buffer)) start)))))))
 
-(autoload 'unmorse-region "morse"
-  "Convert morse coded text in region to ordinary ASCII text."
-  t)
-
 (defun gnus-summary-morse-message (&optional arg)
   "Morse decode the current article."
   (interactive "P")
@@ -9661,7 +9726,7 @@ deleted forever, right now."
   (interactive)
   (or gnus-expert-user
       (gnus-yes-or-no-p
-       "Are you really, really, really sure you want to delete all these messages? ")
+       "Are you really, really sure you want to delete all expirable messages? ")
       (error "Phew!"))
   (gnus-summary-expire-articles t))
 
@@ -10805,41 +10870,51 @@ is non-nil or the Subject: of both articles are the same."
     (error "The current newsgroup does not support article editing"))
   (unless (<= (length gnus-newsgroup-processable) 1)
     (error "No more than one article may be marked"))
-  (save-window-excursion
-    (let ((gnus-article-buffer " *reparent*")
-         (current-article (gnus-summary-article-number))
-         ;; First grab the marked article, otherwise one line up.
-         (parent-article (if (not (null gnus-newsgroup-processable))
-                             (car gnus-newsgroup-processable)
-                           (save-excursion
-                             (if (eq (forward-line -1) 0)
-                                 (gnus-summary-article-number)
-                               (error "Beginning of summary buffer"))))))
-      (unless (not (eq current-article parent-article))
-       (error "An article may not be self-referential"))
-      (let ((message-id (mail-header-id
-                        (gnus-summary-article-header parent-article))))
-       (unless (and message-id (not (equal message-id "")))
-         (error "No message-id in desired parent"))
-       (gnus-with-article current-article
-         (save-restriction
-           (goto-char (point-min))
-           (message-narrow-to-head)
-           (if (re-search-forward "^References: " nil t)
-               (progn
-                 (re-search-forward "^[^ \t]" nil t)
-                 (forward-line -1)
-                 (end-of-line)
-                 (insert " " message-id))
-             (insert "References: " message-id "\n"))))
-       (set-buffer gnus-summary-buffer)
-       (gnus-summary-unmark-all-processable)
-       (gnus-summary-update-article current-article)
-       (if (gnus-summary-goto-subject (cdr gnus-article-current) nil t)
+  (let ((child (gnus-summary-article-number))
+       ;; First grab the marked article, otherwise one line up.
+       (parent (if (not (null gnus-newsgroup-processable))
+                   (car gnus-newsgroup-processable)
+                 (save-excursion
+                   (if (eq (forward-line -1) 0)
+                       (gnus-summary-article-number)
+                     (error "Beginning of summary buffer"))))))
+    (gnus-summary-reparent-children parent (list child))))
+
+(defun gnus-summary-reparent-children (parent children)
+  "Make PARENT the parent of CHILDREN.
+When called interactively, PARENT is is current article and
+CHILDREN are the process-marked articles."
+  (interactive
+   (list (gnus-summary-article-number)
+        (gnus-summary-work-articles nil)))
+  (dolist (child children)
+    (save-window-excursion
+      (let ((gnus-article-buffer " *reparent*"))
+       (unless (not (eq parent child))
+         (error "An article may not be self-referential"))
+       (let ((message-id (mail-header-id
+                          (gnus-summary-article-header parent))))
+         (unless (and message-id (not (equal message-id "")))
+           (error "No message-id in desired parent"))
+         (gnus-with-article child
+           (save-restriction
+             (goto-char (point-min))
+             (message-narrow-to-head)
+             (if (re-search-forward "^References: " nil t)
+                 (progn
+                   (re-search-forward "^[^ \t]" nil t)
+                   (forward-line -1)
+                   (end-of-line)
+                   (insert " " message-id))
+               (insert "References: " message-id "\n"))))
+         (set-buffer gnus-summary-buffer)
+         (gnus-summary-unmark-all-processable)
+         (gnus-summary-update-article child)
+         (when (gnus-summary-goto-subject (cdr gnus-article-current) nil t)
            (gnus-summary-update-secondary-mark (cdr gnus-article-current)))
-       (gnus-summary-rethread-current)
-       (gnus-message 3 "Article %d is now the child of article %d"
-                     current-article parent-article)))))
+         (gnus-summary-rethread-current)
+         (gnus-message 3 "Article %d is now the child of article %d"
+                       child parent))))))
 
 (defun gnus-summary-toggle-threads (&optional arg)
   "Toggle showing conversation threads.
@@ -10899,7 +10974,9 @@ Returns nil if no thread was there to be shown."
 (defun gnus-map-articles (predicate articles)
   "Map PREDICATE over ARTICLES and return non-nil if any predicate is non-nil."
   (apply 'gnus-or (mapcar predicate
-                         (mapcar 'gnus-summary-article-header articles))))
+                         (mapcar (lambda (number)
+                                   (gnus-summary-article-header number))
+                                 articles))))
 
 (defun gnus-summary-hide-all-threads (&optional predicate)
   "Hide all thread subtrees.
@@ -11384,6 +11461,8 @@ save those articles instead."
          (error "No such group: %s" to-newsgroup)))
     to-newsgroup))
 
+(defvar gnus-summary-save-parts-counter)
+
 (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."
@@ -11406,7 +11485,8 @@ If REVERSE, save parts that do not match TYPE."
       (let ((handles (or gnus-article-mime-handles
                         (mm-dissect-buffer nil gnus-article-loose-mime)
                         (and gnus-article-emulate-mime
-                             (mm-uu-dissect)))))
+                             (mm-uu-dissect))))
+           (gnus-summary-save-parts-counter 1))
        (when handles
          (gnus-summary-save-parts-1 type dir handles reverse)
          (unless gnus-article-mime-handles ;; Don't destroy this case.
@@ -11428,10 +11508,11 @@ If REVERSE, save parts that do not match TYPE."
                       (mm-handle-disposition handle) 'filename)
                      (mail-content-type-get
                       (mm-handle-type handle) 'name)
-                     (concat gnus-newsgroup-name
-                             "." (number-to-string
-                                  (cdr gnus-article-current))))))
+                     (format "%s.%d.%d" gnus-newsgroup-name
+                             (cdr gnus-article-current)
+                             gnus-summary-save-parts-counter))))
                   dir)))
+       (incf gnus-summary-save-parts-counter)
        (unless (file-exists-p file)
          (mm-save-part-to-file handle file))))))
 
@@ -11586,11 +11667,14 @@ If REVERSE, save parts that do not match TYPE."
            ()                          ; Malformed head.
          (unless (gnus-summary-article-sparse-p (mail-header-number header))
            (when (and (stringp id)
-                      (not (string= (gnus-group-real-name group)
-                                    (car where))))
-             ;; If we fetched by Message-ID and the article came
-             ;; from a different group, we fudge some bogus article
-             ;; numbers for this article.
+                      (or
+                       (not (string= (gnus-group-real-name group)
+                                     (car where)))
+                       (not (gnus-server-equal gnus-override-method
+                                               (gnus-group-method group)))))
+             ;; If we fetched by Message-ID and the article came from
+             ;; a different group (or server), we fudge some bogus
+             ;; article numbers for this article.
              (mail-header-set-number header gnus-reffed-article-number))
            (save-excursion
              (set-buffer gnus-summary-buffer)