;;; gnus-sum.el --- summary mode commands for Gnus
;; Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
-;; 2005, 2006 Free Software Foundation, Inc.
+;; 2005, 2006, 2007 Free Software Foundation, Inc.
;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
;; Keywords: news
;; GNU Emacs is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
:group 'gnus-summary-exit
:type 'boolean)
+(defcustom gnus-summary-next-group-on-exit t
+ "If non-nil, go to the next unread newsgroup on summary exit.
+See `gnus-group-goto-unread'."
+ :link '(custom-manual "(gnus)Group Maneuvering")
+ :group 'gnus-summary-exit
+ :version "23.0" ;; No Gnus
+ :type 'boolean)
+
(defcustom gnus-fetch-old-headers nil
"*Non-nil means that Gnus will try to build threads by grabbing old headers.
If an unread article in the group refers to an older, already
If this variable is `adopt', Gnus will make one of the \"children\"
the parent and mark all the step-children as such.
If this variable is `empty', the \"children\" are printed with empty
-subject fields. (Or rather, they will be printed with a string
+subject fields. (Or rather, they will be printed with a string
given by the `gnus-summary-same-subject' variable.)"
:group 'gnus-thread
:type '(choice (const :tag "off" nil)
:type 'boolean)
(defcustom gnus-auto-select-first t
- "*If non-nil, select the article under point.
-Which article this is is controlled by the `gnus-auto-select-subject'
-variable.
+ "If non-nil, select an article on group entry.
+An article is selected automatically when entering a group
+e.g. with \\<gnus-group-mode-map>\\[gnus-group-read-group], or via `gnus-summary-next-page' or
+`gnus-summary-catchup-and-goto-next-group'.
+
+Which article is selected is controlled by the variable
+`gnus-auto-select-subject'.
If you want to prevent automatic selection of articles in some
newsgroups, set the variable to nil in `gnus-select-group-hook'."
+ ;; Commands include...
+ ;; \\<gnus-group-mode-map>\\[gnus-group-read-group]
+ ;; \\<gnus-summary-mode-map>\\[gnus-summary-next-page]
+ ;; \\<gnus-summary-mode-map>\\[gnus-summary-catchup-and-goto-next-group]
:group 'gnus-group-select
:type '(choice (const :tag "none" nil)
(sexp :menu-tag "first" t)))
:group 'gnus-summary-maneuvering
:type 'boolean)
+(defcustom gnus-auto-select-on-ephemeral-exit 'next-noselect
+ "What article should be selected after exiting an ephemeral group.
+Valid values include:
+
+`next'
+ Select the next article.
+`next-unread'
+ Select the next unread article.
+`next-noselect'
+ Move the cursor to the next article. This is the default.
+`next-unread-noselect'
+ Move the cursor to the next unread article.
+
+If it has any other value or there is no next (unread) article, the
+article selected before entering to the ephemeral group will appear."
+ :version "23.0" ;; No Gnus
+ :group 'gnus-summary-maneuvering
+ :type '(choice :format "%{%t%}:\n %[Value Menu%] %v"
+ (const next) (const next-unread)
+ (const next-noselect) (const next-unread-noselect)
+ (sexp :tag "other" :value nil)))
+
(defcustom gnus-auto-goto-ignores 'unfetched
"*Says how to handle unfetched articles when maneuvering.
. gnus-summary-normal-read))
"*Controls the highlighting of summary buffer lines.
-A list of (FORM . FACE) pairs. When deciding how a a particular
+A list of (FORM . FACE) pairs. When deciding how a particular
summary line should be displayed, each form is evaluated. The content
of the face field after the first true form is used. You can change
how those summary lines are displayed, by editing the face field.
You can use the following variables in the FORM field.
-score: The article's score
+score: The article's score.
default: The default article score.
default-high: The default score for high scored articles.
default-low: The default score for low scored articles.
:group 'gnus-summary)
(defvar gnus-decode-encoded-word-function 'mail-decode-encoded-word-string
- "Variable that says which function should be used to decode a string with encoded words.")
+ "Function used to decode a string with encoded words.")
+
+(defvar gnus-decode-encoded-address-function
+ 'mail-decode-encoded-address-string
+ "Function used to decode addresses with encoded words.")
(defcustom gnus-extra-headers '(To Newsgroups)
"*Extra headers to parse."
:type '(repeat symbol))
(defcustom gnus-ignored-from-addresses
- (and user-mail-address
+ (and user-mail-address
(not (string= user-mail-address ""))
(regexp-quote user-mail-address))
- "*Regexp of From headers that may be suppressed in favor of To headers."
+ "*From headers that may be suppressed in favor of To headers.
+This can be a regexp or a list of regexps."
:version "21.1"
:group 'gnus-summary
- :type 'regexp)
+ :type '(choice regexp
+ (repeat :tag "Regexp List" regexp)))
+
+(defsubst gnus-ignored-from-addresses ()
+ (gmm-regexp-concat gnus-ignored-from-addresses))
(defcustom gnus-summary-to-prefix "-> "
"*String prefixed to the To field in the summary line when
((eq gnus-summary-gather-subject-limit 'fuzzy)
(gnus-simplify-subject-fuzzy subject))
((numberp gnus-summary-gather-subject-limit)
- (gnus-limit-string (gnus-simplify-subject-re subject)
- gnus-summary-gather-subject-limit))
+ (truncate-string-to-width (gnus-simplify-subject-re subject)
+ gnus-summary-gather-subject-limit))
(t
subject)))
"/" gnus-summary-limit-to-subject
"n" gnus-summary-limit-to-articles
"b" gnus-summary-limit-to-bodies
+ "h" gnus-summary-limit-to-headers
"w" gnus-summary-pop-limit
"s" gnus-summary-limit-to-subject
"a" gnus-summary-limit-to-author
"C" gnus-summary-limit-mark-excluded-as-read
"o" gnus-summary-insert-old-articles
"N" gnus-summary-insert-new-articles
+ "S" gnus-summary-limit-to-singletons
"r" gnus-summary-limit-to-replied
- "R" gnus-summary-limit-to-recipient)
+ "R" gnus-summary-limit-to-recipient
+ "A" gnus-summary-limit-to-address)
(gnus-define-keys (gnus-summary-goto-map "G" gnus-summary-mode-map)
"n" gnus-summary-next-unread-article
(gnus-define-keys (gnus-summary-buffer-map "Y" gnus-summary-mode-map)
"g" gnus-summary-prepare
"c" gnus-summary-insert-cached-articles
- "d" gnus-summary-insert-dormant-articles)
+ "d" gnus-summary-insert-dormant-articles
+ "t" gnus-summary-insert-ticked-articles)
(gnus-define-keys (gnus-summary-exit-map "Z" gnus-summary-mode-map)
"c" gnus-summary-catchup-and-exit
["Subject..." gnus-summary-limit-to-subject t]
["Author..." gnus-summary-limit-to-author t]
["Recipient..." gnus-summary-limit-to-recipient t]
+ ["Address..." gnus-summary-limit-to-address t]
["Age..." gnus-summary-limit-to-age t]
["Extra..." gnus-summary-limit-to-extra t]
["Score..." gnus-summary-limit-to-score t]
["Display Predicate" gnus-summary-limit-to-display-predicate t]
["Unread" gnus-summary-limit-to-unread t]
["Unseen" gnus-summary-limit-to-unseen t]
+ ["Singletons" gnus-summary-limit-to-singletons t]
["Replied" gnus-summary-limit-to-replied t]
["Non-dormant" gnus-summary-limit-exclude-dormant t]
- ["Next articles" gnus-summary-limit-to-articles t]
+ ["Next or process marked articles" gnus-summary-limit-to-articles t]
["Pop limit" gnus-summary-pop-limit t]
["Show dormant" gnus-summary-limit-include-dormant t]
["Hide childless dormant"
["Regenerate" gnus-summary-prepare t]
["Insert cached articles" gnus-summary-insert-cached-articles t]
["Insert dormant articles" gnus-summary-insert-dormant-articles t]
+ ["Insert ticked articles" gnus-summary-insert-ticked-articles t]
["Toggle threading" gnus-summary-toggle-threads t])
["See old articles" gnus-summary-insert-old-articles t]
["See new articles" gnus-summary-insert-new-articles t]
t
(not (cdr (gnus-data-find-list article)))))
-(defun gnus-make-thread-indent-array ()
- (let ((n 200))
- (unless (and gnus-thread-indent-array
- (= gnus-thread-indent-level gnus-thread-indent-array-level))
- (setq gnus-thread-indent-array (make-vector 201 "")
- gnus-thread-indent-array-level gnus-thread-indent-level)
- (while (>= n 0)
- (aset gnus-thread-indent-array n
- (make-string (* n gnus-thread-indent-level) ? ))
- (setq n (1- n))))))
+(defun gnus-make-thread-indent-array (&optional n)
+ (when (or n
+ (progn (setq n 200) nil)
+ (null gnus-thread-indent-array)
+ (/= gnus-thread-indent-level gnus-thread-indent-array-level))
+ (setq gnus-thread-indent-array (make-vector (1+ n) "")
+ gnus-thread-indent-array-level gnus-thread-indent-level)
+ (while (>= n 0)
+ (aset gnus-thread-indent-array n
+ (make-string (* n gnus-thread-indent-level) ? ))
+ (setq n (1- n)))))
(defun gnus-update-summary-mark-positions ()
"Compute where the summary marks are to go."
(defun gnus-summary-from-or-to-or-newsgroups (header gnus-tmp-from)
(let ((mail-parse-charset gnus-newsgroup-charset)
+ (ignored-from-addresses (gnus-ignored-from-addresses))
; Is it really necessary to do this next part for each summary line?
; Luckily, doesn't seem to slow things down much.
(mail-parse-ignored-charsets
(with-current-buffer gnus-summary-buffer
gnus-newsgroup-ignored-charsets)))
(or
- (and gnus-ignored-from-addresses
- (string-match gnus-ignored-from-addresses gnus-tmp-from)
+ (and ignored-from-addresses
+ (string-match ignored-from-addresses gnus-tmp-from)
(let ((extra-headers (mail-header-extra header))
to
newsgroups)
(concat gnus-summary-to-prefix
(inline
(gnus-summary-extract-address-component
- (funcall gnus-decode-encoded-word-function to)))))
+ (funcall gnus-decode-encoded-address-function to)))))
((setq newsgroups
(or
(cdr (assq 'Newsgroups extra-headers))
gnus-tmp-expirable gnus-tmp-subject-or-nil
&optional gnus-tmp-dummy gnus-tmp-score
gnus-tmp-process)
+ (if (>= gnus-tmp-level (length gnus-thread-indent-array))
+ (gnus-make-thread-indent-array (max (* 2 (length gnus-thread-indent-array))
+ gnus-tmp-level)))
(let* ((gnus-tmp-indentation (aref gnus-thread-indent-array gnus-tmp-level))
(gnus-tmp-lines (mail-header-lines gnus-tmp-header))
(gnus-tmp-score (or gnus-tmp-score gnus-summary-default-score 0))
infloop))
(defun gnus-make-threads ()
- "Go through the dependency hashtb and find the roots. Return all threads."
+ "Go through the dependency hashtb and find the roots. Return all threads."
(let (threads)
(while (catch 'infloop
(mapatoms
(error x))
(condition-case () ; from
(gnus-remove-odd-characters
- (funcall gnus-decode-encoded-word-function
+ (funcall gnus-decode-encoded-address-function
(setq x (nnheader-nov-field))))
(error x))
(nnheader-nov-field) ; date
;; First go up in this thread until we find the root.
(setq last-id (gnus-root-id id)
headers (message-flatten-list (gnus-id-to-thread last-id)))
- ;; We have now found the real root of this thread. It might have
+ ;; We have now found the real root of this thread. It might have
;; been gathered into some loose thread, so we have to search
;; through the threads to find the thread we wanted.
(let ((threads gnus-newsgroup-threads)
(1+ (point-at-eol))
(gnus-delete-line)))))))
-(defun gnus-sort-threads-1 (threads func)
+(defun gnus-sort-threads-recursive (threads func)
(sort (mapcar (lambda (thread)
(cons (car thread)
(and (cdr thread)
- (gnus-sort-threads-1 (cdr thread) func))))
+ (gnus-sort-threads-recursive (cdr thread) func))))
threads) func))
+(defun gnus-sort-threads-loop (threads func)
+ (let* ((superthread (cons nil threads))
+ (stack (list (cons superthread threads)))
+ remaining-threads thread)
+ (while stack
+ (setq remaining-threads (cdr (car stack)))
+ (if remaining-threads
+ (progn (setq thread (car remaining-threads))
+ (setcdr (car stack) (cdr remaining-threads))
+ (if (cdr thread)
+ (push (cons thread (cdr thread)) stack)))
+ (setq thread (caar stack))
+ (setcdr thread (sort (cdr thread) func))
+ (pop stack)))
+ (cdr superthread)))
+
(defun gnus-sort-threads (threads)
"Sort THREADS."
(if (not gnus-thread-sort-functions)
threads
(gnus-message 8 "Sorting threads...")
- (let ((max-lisp-eval-depth 5000))
- (prog1 (gnus-sort-threads-1
- threads
- (gnus-make-sort-function gnus-thread-sort-functions))
- (gnus-message 8 "Sorting threads...done")))))
+ (prog1
+ (condition-case nil
+ (let ((max-lisp-eval-depth (max max-lisp-eval-depth 5000)))
+ (gnus-sort-threads-recursive
+ threads (gnus-make-sort-function gnus-thread-sort-functions)))
+ ;; Even after binding max-lisp-eval-depth, the recursive
+ ;; sorter might fail for very long threads. In that case,
+ ;; try using a (less well-tested) non-recursive sorter.
+ (error (gnus-sort-threads-loop
+ threads (gnus-make-sort-function
+ gnus-thread-sort-functions))))
+ (gnus-message 8 "Sorting threads...done"))))
(defun gnus-sort-articles (articles)
"Sort ARTICLES."
gnus-tmp-closing-bracket ?\>)
(setq gnus-tmp-opening-bracket ?\[
gnus-tmp-closing-bracket ?\]))
+ (if (>= gnus-tmp-level (length gnus-thread-indent-array))
+ (gnus-make-thread-indent-array
+ (max (* 2 (length gnus-thread-indent-array))
+ gnus-tmp-level)))
(setq
gnus-tmp-indentation
(aref gnus-thread-indent-array gnus-tmp-level)
(when (equal major-mode 'gnus-summary-mode)
(gnus-kill-buffer (current-buffer)))
(error "Couldn't activate group %s: %s"
- group (gnus-status-message group))))
+ (gnus-group-decoded-name group) (gnus-status-message group))))
(unless (gnus-request-group group t)
(when (equal major-mode 'gnus-summary-mode)
(gnus-kill-buffer (current-buffer)))
(error "Couldn't request group %s: %s"
- group (gnus-status-message group)))
+ (gnus-group-decoded-name group) (gnus-status-message group)))
(when gnus-agent
(gnus-agent-possibly-alter-active group (gnus-active group) info)
(setq gnus-newsgroup-auto-expire
(gnus-group-auto-expirable-p group))
;; Set up the article buffer now, if necessary.
- (unless gnus-single-article-buffer
+ (unless (and gnus-single-article-buffer
+ (equal gnus-article-buffer "*Article*"))
(gnus-article-setup-buffer))
;; First and last article in this newsgroup.
(when gnus-newsgroup-headers
(read-string
(format
"How many articles from %s (%s %d): "
- (gnus-limit-string
- (gnus-group-decoded-name gnus-newsgroup-name)
- 35)
+ (gnus-group-decoded-name gnus-newsgroup-name)
(if initial "max" "default")
number)
(if initial
(let* ((mformat (symbol-value
(intern
(format "gnus-%s-mode-line-format-spec" where))))
- (gnus-tmp-group-name (gnus-group-decoded-name
- gnus-newsgroup-name))
+ (gnus-tmp-group-name (gnus-mode-string-quote
+ (gnus-group-decoded-name
+ 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))
(let ((case-fold-search t)
in-reply-to header p lines chars)
(goto-char (point-min))
- ;; Search to the beginning of the next header. Error messages
+ ;; Search to the beginning of the next header. Error messages
;; do not begin with 2 or 3.
(while (re-search-forward "^[23][0-9]+ " nil t)
(setq id nil
;; This implementation of this function, with nine
;; search-forwards instead of the one re-search-forward and
;; a case (which basically was the old function) is actually
- ;; about twice as fast, even though it looks messier. You
+ ;; about twice as fast, even though it looks messier. You
;; can't have everything, I guess. Speed and elegance
;; doesn't always go hand in hand.
(setq
(progn
(goto-char p)
(if (search-forward "\nfrom:" nil t)
- (funcall gnus-decode-encoded-word-function
+ (funcall gnus-decode-encoded-address-function
(nnheader-header-value))
"(nobody)"))
;; Date.
(let ((top-pos (save-excursion (forward-line (- top)) (point))))
(if (> bottom top-pos)
;; Keep the second line from the top visible
- (set-window-start window top-pos t)
+ (set-window-start window top-pos)
;; Try to keep the bottom line visible; if it's partially
;; obscured, either scroll one more line to make it fully
;; visible, or revert to using TOP-POS.
(gnus-group-jump-to-group group))
(gnus-run-hooks 'gnus-summary-exit-hook)
(unless (or quit-config
+ (not gnus-summary-next-group-on-exit)
;; If this group has disappeared from the summary
;; buffer, don't skip forwards.
(not (string= group (gnus-group-group-name))))
(gnus-configure-windows (cdr quit-config) 'force))
(gnus-configure-windows (cdr quit-config) 'force))
(when (eq major-mode 'gnus-summary-mode)
+ (if (memq gnus-auto-select-on-ephemeral-exit '(next-noselect
+ next-unread-noselect))
+ (when (zerop (cond ((eq gnus-auto-select-on-ephemeral-exit
+ 'next-noselect)
+ (gnus-summary-next-subject 1 nil t))
+ ((eq gnus-auto-select-on-ephemeral-exit
+ 'next-unread-noselect)
+ (gnus-summary-next-subject 1 t t))))
+ ;; Hide the article buffer which displays the article different
+ ;; from the one that the cursor points to in the summary buffer.
+ (gnus-configure-windows 'summary 'force))
+ (cond ((eq gnus-auto-select-on-ephemeral-exit 'next)
+ (gnus-summary-next-subject 1))
+ ((eq gnus-auto-select-on-ephemeral-exit 'next-unread)
+ (gnus-summary-next-subject 1 t))))
(gnus-summary-recenter)
(gnus-summary-position-point))))
If SUBJECT, only articles with SUBJECT are selected.
If BACKWARD, the previous article is selected instead of the next."
(interactive "P")
+ ;; Make sure we are in the summary buffer.
+ (unless (eq major-mode 'gnus-summary-mode)
+ (set-buffer gnus-summary-buffer))
(cond
;; Is there such an article?
((and (gnus-summary-search-forward unread subject backward)
(gnus-summary-limit articles))
(gnus-summary-position-point))))
+(defun gnus-summary-limit-to-address (address &optional not-matching)
+ "Limit the summary buffer to articles with the given ADDRESS.
+
+If NOT-MATCHING, exclude ADDRESS.
+
+To, Cc and From headers are checked. You need to include `To' and `Cc'
+in `nnmail-extra-headers'."
+ (interactive
+ (list (read-string (format "%s address (regexp): "
+ (if current-prefix-arg "Exclude" "Limit to")))
+ current-prefix-arg))
+ (when (not (equal "" address))
+ (prog1 (let* ((to
+ (if (memq 'To nnmail-extra-headers)
+ (gnus-summary-find-matching
+ (cons 'extra 'To) address 'all nil nil
+ not-matching)
+ (gnus-message
+ 1 "`To' isn't present in `nnmail-extra-headers'")
+ (sit-for 1)
+ t))
+ (cc
+ (if (memq 'Cc nnmail-extra-headers)
+ (gnus-summary-find-matching
+ (cons 'extra 'Cc) address 'all nil nil
+ not-matching)
+ (gnus-message
+ 1 "`Cc' isn't present in `nnmail-extra-headers'")
+ (sit-for 1)
+ t))
+ (from
+ (gnus-summary-find-matching "from" address
+ 'all nil nil not-matching))
+ (articles
+ (if not-matching
+ ;; We need the numbers that are in all lists:
+ (if (eq cc t)
+ (if (eq to t)
+ from
+ (mapcar (lambda (a) (car (memq a from))) to))
+ (if (eq to t)
+ (mapcar (lambda (a) (car (memq a from))) cc)
+ (mapcar (lambda (a) (car (memq a from)))
+ (mapcar (lambda (a) (car (memq a to)))
+ cc))))
+ (nconc (if (eq to t) nil to)
+ (if (eq cc t) nil cc)
+ from))))
+ (unless articles
+ (error "Found no matches for \"%s\"" address))
+ (gnus-summary-limit articles))
+ (gnus-summary-position-point))))
+
+(defun gnus-summary-limit-strange-charsets-predicate (header)
+ (let ((string (concat (mail-header-subject header)
+ (mail-header-from header)))
+ charset found)
+ (dotimes (i (1- (length string)))
+ (setq charset (format "%s" (char-charset (aref string (1+ i)))))
+ (when (string-match "unicode\\|big\\|japanese" charset)
+ (setq found t)))
+ found))
+
+(defun gnus-summary-limit-to-predicate (predicate)
+ "Limit to articles where PREDICATE returns non-nil.
+PREDICATE will be called with the header structures of the
+articles."
+ (let ((articles nil)
+ (case-fold-search t))
+ (dolist (header gnus-newsgroup-headers)
+ (when (funcall predicate header)
+ (push (mail-header-number header) articles)))
+ (gnus-summary-limit (nreverse articles))))
+
(defun gnus-summary-limit-to-age (age &optional younger-p)
"Limit the summary buffer to articles that are older than (or equal) AGE days.
If YOUNGER-P (the prefix) is non-nil, limit the summary buffer to
gnus-duplicate-mark gnus-souped-mark)
'reverse)))
-(defun gnus-summary-limit-to-bodies (match &optional reverse)
+(defun gnus-summary-limit-to-headers (match &optional reverse)
+ "Limit the summary buffer to articles that have headers that match MATCH.
+If REVERSE (the prefix), limit to articles that don't match."
+ (interactive "sMatch headers (regexp): \nP")
+ (gnus-summary-limit-to-bodies match reverse t))
+
+(defun gnus-summary-limit-to-bodies (match &optional reverse headersp)
"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")
(set-buffer gnus-article-buffer)
(article-goto-body)
(let* ((case-fold-search t)
- (found (re-search-forward match nil t)))
+ (found (if headersp
+ (re-search-backward match nil t)
+ (re-search-forward match nil t))))
(when (or (and found
(not reverse))
(and (not found)
(gnus-summary-limit articles)))
(gnus-summary-position-point))
+(defun gnus-summary-limit-to-singletons (&optional threadsp)
+ "Limit the summary buffer to articles that aren't part on any thread.
+If THREADSP (the prefix), limit to articles that are in threads."
+ (interactive "P")
+ (let ((articles nil)
+ thread-articles
+ threads)
+ (dolist (thread gnus-newsgroup-threads)
+ (if (stringp (car thread))
+ (dolist (thread (cdr thread))
+ (push thread threads))
+ (push thread threads)))
+ (dolist (thread threads)
+ (setq thread-articles (gnus-articles-in-thread thread))
+ (when (or (and threadsp
+ (> (length thread-articles) 1))
+ (and (not threadsp)
+ (= (length thread-articles) 1)))
+ (setq articles (nconc thread-articles 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."
(interactive)
(let ((gnus-verbose (max 6 gnus-verbose)))
(if (not gnus-newsgroup-dormant)
- (gnus-message 3 "No cached articles for this group")
+ (gnus-message 3 "No dormant articles for this group")
(gnus-summary-goto-subjects gnus-newsgroup-dormant))))
+(defun gnus-summary-insert-ticked-articles ()
+ "Insert ticked articles for this group into the current buffer."
+ (interactive)
+ (let ((gnus-verbose (max 6 gnus-verbose)))
+ (if (not gnus-newsgroup-marked)
+ (gnus-message 3 "No ticked articles for this group")
+ (gnus-summary-goto-subjects gnus-newsgroup-marked))))
+
(defun gnus-summary-limit-include-dormant ()
"Display all the hidden articles that are marked as dormant.
Note that this command only works on a subset of the articles currently
;; will really go down to a leaf article first, before slowly
;; working its way up towards the root.
(when thread
- (let* ((max-lisp-eval-depth 5000)
+ (let* ((max-lisp-eval-depth (max 5000 max-lisp-eval-depth))
(children
(if (cdr thread)
(apply '+ (mapcar 'gnus-summary-limit-children
;; the parent article.
(when (setq to-address (or (gnus-fetch-field "reply-to")
(gnus-fetch-field "from")))
- (setq params (append
- (list (cons 'to-address
- (funcall gnus-decode-encoded-word-function
- to-address))))))
+ (setq params
+ (append
+ (list (cons 'to-address
+ (funcall gnus-decode-encoded-address-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
(defun gnus-summary-caesar-message (&optional arg)
"Caesar rotate the current article by 13.
-The numerical prefix specifies how many places to rotate each letter
-forward."
+With a non-numerical prefix, also rotate headers. A numerical
+prefix specifies how many places to rotate each letter forward."
(interactive "P")
(gnus-summary-select-article)
(let ((mail-header-separator ""))
(widen)
(let ((start (window-start))
buffer-read-only)
- (message-caesar-buffer-body arg)
+ (if (equal arg '(4))
+ (message-caesar-buffer-body nil t)
+ (message-caesar-buffer-body arg))
(set-window-start (get-buffer-window (current-buffer)) start)))))
;; Create buttons and stuff...
(gnus-treat-article nil))
(crosspost "Crosspost" "Crossposting")))
(copy-buf (save-excursion
(nnheader-set-temp-buffer " *copy article*")))
- art-group to-method new-xref article to-groups articles-to-update-marks)
+ art-group to-method new-xref article to-groups
+ articles-to-update-marks encoded)
(unless (assq action names)
(error "Unknown action %s" action))
;; Read the newsgroup name.
(gnus-article-prepare-hook nil)
(gnus-mark-article-hook nil))
(gnus-summary-select-article nil nil nil (car articles))))
- (setq to-newsgroup
- (gnus-read-move-group-name
- (cadr (assq action names))
- (symbol-value (intern (format "gnus-current-%s-group" action)))
- articles prefix))
- (set (intern (format "gnus-current-%s-group" action)) to-newsgroup))
- (setq to-method (or select-method
- (gnus-server-to-method
- (gnus-group-method to-newsgroup))))
+ (setq to-newsgroup (gnus-read-move-group-name
+ (cadr (assq action names))
+ (symbol-value
+ (intern (format "gnus-current-%s-group" action)))
+ articles prefix)
+ encoded to-newsgroup
+ to-method (gnus-server-to-method (gnus-group-method to-newsgroup)))
+ (set (intern (format "gnus-current-%s-group" action))
+ (mm-decode-coding-string
+ to-newsgroup
+ (gnus-group-name-charset to-method to-newsgroup))))
+ (unless to-method
+ (setq to-method (or select-method
+ (gnus-server-to-method
+ (gnus-group-method to-newsgroup)))))
+ (setq to-newsgroup (or encoded
+ (mm-encode-coding-string
+ to-newsgroup
+ (gnus-group-name-charset to-method to-newsgroup))))
;; Check the method we are to move this article to...
(unless (gnus-check-backend-function
'request-accept-article (car to-method))
(error "Can't open server %s" (car to-method)))
(gnus-message 6 "%s to %s: %s..."
(caddr (assq action names))
- (or (car select-method) to-newsgroup) articles)
+ (or (car select-method)
+ (gnus-group-decoded-name to-newsgroup))
+ articles)
(while articles
(setq article (pop articles))
(setq
(to-method (gnus-find-method-for-group
to-newsgroup))
(move-is-internal (gnus-method-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
- move-is-internal))) ; is this move internal?
+ (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
+ move-is-internal))) ; is this move internal?
;; Copy the article.
((eq action 'copy)
(save-excursion
(gnus-request-article-this-buffer article gnus-newsgroup-name)
(when (consp (setq art-group
(gnus-request-accept-article
- to-newsgroup select-method (not articles))))
+ to-newsgroup select-method (not articles) t)))
(setq new-xref (concat new-xref " " (car art-group)
":"
(number-to-string (cdr art-group))))
;; it and replace the new article.
(nnheader-replace-header "Xref" new-xref)
(gnus-request-replace-article
- (cdr art-group) to-newsgroup (current-buffer))
+ (cdr art-group) to-newsgroup (current-buffer) t)
art-group))))))
(cond
((not art-group)
(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))))
+ article gnus-newsgroup-name (current-buffer) t)))
;; run the move/copy/crosspost/respool hook
(run-hook-with-args 'gnus-summary-article-move-hook
;;;!!!Why is this necessary?
(set-buffer gnus-summary-buffer)
-
+
(gnus-summary-goto-subject article)
(when (eq action 'move)
(gnus-summary-mark-article article gnus-canceled-mark))))
(set-buffer gnus-group-buffer)
(let ((gnus-group-marked to-groups))
(gnus-group-get-new-news-this-group nil t)))
-
+
(gnus-kill-buffer copy-buf)
(gnus-summary-position-point)
(gnus-set-mode-line 'summary)))
(message-options message-options)
(message-options-set-recipient)
(mail-parse-ignored-charsets
- ',gnus-newsgroup-ignored-charsets))
+ ',gnus-newsgroup-ignored-charsets)
+ (rfc2047-header-encoding-alist
+ ',(let ((charset (gnus-group-name-charset
+ (gnus-find-method-for-group
+ gnus-newsgroup-name)
+ gnus-newsgroup-name)))
+ (append (list (cons "Newsgroups" charset)
+ (cons "Followup-To" charset)
+ (cons "Xref" charset))
+ rfc2047-header-encoding-alist))))
,(if (not raw) '(progn
(mml-to-mime)
(mml-destroy-buffers)
gnus-newsgroup-dormant nil))
(setq gnus-newsgroup-unreads
(gnus-sorted-nunion
- (gnus-intersection gnus-newsgroup-unreads
- gnus-newsgroup-downloadable)
- gnus-newsgroup-unfetched)))
+ (gnus-sorted-intersection gnus-newsgroup-unreads
+ gnus-newsgroup-downloadable)
+ (gnus-sorted-difference gnus-newsgroup-unfetched
+ gnus-newsgroup-cached))))
;; We actually mark all articles as canceled, which we
;; have to do when using auto-expiry or adaptive scoring.
(gnus-summary-show-all-threads)
(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."
+When called interactively, PARENT is the current article and CHILDREN
+are the process-marked articles."
(interactive
(list (gnus-summary-article-number)
(gnus-summary-work-articles nil)))
(mapcar 'list (nreverse split-name))
nil nil nil
'gnus-group-history))))
- (to-method (gnus-server-to-method (gnus-group-method to-newsgroup))))
+ (to-method (gnus-server-to-method (gnus-group-method to-newsgroup)))
+ encoded)
(when to-newsgroup
(if (or (string= to-newsgroup "")
(string= to-newsgroup prefix))
(setq to-newsgroup default))
(unless to-newsgroup
(error "No group name entered"))
- (or (gnus-active to-newsgroup)
- (gnus-activate-group to-newsgroup nil nil to-method)
+ (setq encoded (mm-encode-coding-string
+ to-newsgroup
+ (gnus-group-name-charset to-method to-newsgroup)))
+ (or (gnus-active encoded)
+ (gnus-activate-group encoded nil nil to-method)
(if (gnus-y-or-n-p (format "No such group: %s. Create it? "
to-newsgroup))
- (or (and (gnus-request-create-group to-newsgroup to-method)
- (gnus-activate-group
- to-newsgroup nil nil to-method)
- (gnus-subscribe-group to-newsgroup))
+ (or (and (gnus-request-create-group encoded to-method)
+ (gnus-activate-group encoded nil nil to-method)
+ (gnus-subscribe-group encoded))
(error "Couldn't create group %s" to-newsgroup)))
- (error "No such group: %s" to-newsgroup)))
- to-newsgroup))
+ (error "No such group: %s" to-newsgroup))
+ encoded)))
(defvar gnus-summary-save-parts-counter)
(read-string
(format
"How many articles from %s (%s %d): "
- (gnus-limit-string
- (gnus-group-decoded-name gnus-newsgroup-name) 35)
+ (gnus-group-decoded-name gnus-newsgroup-name)
(if initial "max" "default")
len)
(if initial