;;; 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
:type '(repeat symbol)
:group 'gnus-charset)
+(defcustom gnus-newsgroup-maximum-articles nil
+ "The maximum number of articles a newsgroup.
+If this is a number, old articles in a newsgroup exceeding this number
+are silently ignored. If it is nil, no article is ignored. Note that
+setting this variable to a number might prevent you from reading very
+old articles."
+ :group 'gnus-group-select
+ :version "22.2"
+ :type '(choice (const :tag "No limit" nil)
+ integer))
+
(gnus-define-group-parameter
ignored-charsets
:type list
(defvar gnus-newsgroup-last-mail nil)
(defvar gnus-newsgroup-last-folder nil)
(defvar gnus-newsgroup-last-file nil)
+(defvar gnus-newsgroup-last-directory nil)
(defvar gnus-newsgroup-auto-expire nil)
(defvar gnus-newsgroup-active nil)
gnus-newsgroup-begin gnus-newsgroup-end
gnus-newsgroup-last-rmail gnus-newsgroup-last-mail
gnus-newsgroup-last-folder gnus-newsgroup-last-file
+ gnus-newsgroup-last-directory
gnus-newsgroup-auto-expire gnus-newsgroup-unreads
gnus-newsgroup-unselected gnus-newsgroup-marked
gnus-newsgroup-spam-marked
((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
"g" gnus-summary-show-article
"s" gnus-summary-isearch-article
"P" gnus-summary-print-article
+ "S" gnus-sticky-article
"M" gnus-mailing-list-insinuate
"t" gnus-article-babel)
"e" gnus-article-emphasize
"w" gnus-article-fill-cited-article
"Q" gnus-article-fill-long-lines
+ "L" gnus-article-toggle-truncate-lines
"C" gnus-article-capitalize-sentences
"c" gnus-article-remove-cr
"q" gnus-article-de-quoted-unreadable
"r" gnus-summary-save-article-rmail
"f" gnus-summary-save-article-file
"b" gnus-summary-save-article-body-file
+ "B" gnus-summary-write-article-body-file
"h" gnus-summary-save-article-folder
"v" gnus-summary-save-article-vm
"p" gnus-summary-pipe-output
"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
"e" gnus-article-view-part-externally
+ "H" gnus-article-browse-html-article
"E" gnus-article-encrypt-body
"i" gnus-article-inline-part
"|" gnus-article-pipe-part)
["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
'(:help "Encrypt the message body on disk"))]
["View part externally" gnus-article-view-part-externally t]
+ ["View HTML parts in browser" gnus-article-browse-html-article t]
["View part with charset..." gnus-article-view-part-as-charset t]
["Copy part" gnus-article-copy-part t]
["Save part..." gnus-article-save-part t]
["Emphasis" gnus-article-emphasize t]
["Word wrap" gnus-article-fill-cited-article t]
["Fill long lines" gnus-article-fill-long-lines t]
+ ["Toggle truncate long lines" gnus-article-toggle-truncate-lines t]
["Capitalize sentences" gnus-article-capitalize-sentences t]
["Remove CR" gnus-article-remove-cr t]
["Quoted-Printable" gnus-article-de-quoted-unreadable t]
["Remove article" gnus-cache-remove-article t])
["Translate" gnus-article-babel t]
["Select article buffer" gnus-summary-select-article-buffer t]
+ ["Make article buffer sticky" gnus-sticky-article t]
["Enter digest buffer" gnus-summary-enter-digest-group t]
["Isearch article..." gnus-summary-isearch-article t]
["Beginning of the article" gnus-summary-beginning-of-article t]
["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]
(gnus-summary-mode group)
(when gnus-carpal
(gnus-carpal-setup-buffer 'summary))
- (unless gnus-single-article-buffer
- (make-local-variable 'gnus-article-buffer)
- (make-local-variable 'gnus-article-current)
- (make-local-variable 'gnus-original-article-buffer))
+ (when (gnus-group-quit-config group)
+ (set (make-local-variable 'gnus-single-article-buffer) nil))
+ (make-local-variable 'gnus-article-buffer)
+ (make-local-variable 'gnus-article-current)
+ (make-local-variable 'gnus-original-article-buffer)
(setq gnus-newsgroup-name group)
;; Set any local variables in the group parameters.
(gnus-summary-set-local-parameters gnus-newsgroup-name)
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)
t
gnus-summary-ignore-duplicates))
(info (nth 2 entry))
- articles fetched-articles cached)
+ charset articles fetched-articles cached)
(unless (gnus-check-server
(set (make-local-variable 'gnus-current-select-method)
(gnus-find-method-for-group group)))
(error "Couldn't open server"))
+ (setq charset (gnus-group-name-charset gnus-current-select-method group))
(or (and entry (not (eq (car entry) t))) ; Either it's active...
(gnus-activate-group group) ; Or we can activate it...
(progn ; Or we bug out.
(when (equal major-mode 'gnus-summary-mode)
(gnus-kill-buffer (current-buffer)))
- (error "Couldn't activate group %s: %s"
- group (gnus-status-message group))))
+ (error
+ "Couldn't activate group %s: %s"
+ (mm-decode-coding-string group charset)
+ (mm-decode-coding-string (gnus-status-message group) charset))))
(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)))
+ (when (equal major-mode 'gnus-summary-mode)
+ (gnus-kill-buffer (current-buffer)))
+ (error "Couldn't request group %s: %s"
+ (mm-decode-coding-string group charset)
+ (mm-decode-coding-string (gnus-status-message group) charset)))
(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
;; articles in the group, or (if that's nil), the
;; articles in the cache.
(or
- (gnus-uncompress-range (gnus-active group))
+ (if gnus-newsgroup-maximum-articles
+ (let ((active (gnus-active group)))
+ (gnus-uncompress-range
+ (cons (max (car active)
+ (- (cdr active)
+ gnus-newsgroup-maximum-articles
+ -1))
+ (cdr active))))
+ (gnus-uncompress-range (gnus-active group)))
(gnus-cache-articles-in-group group))
;; Select only the "normal" subset of articles.
(gnus-sorted-nunion
(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.
(active (or (gnus-active group) (gnus-activate-group group)))
(last (or (cdr active)
(error "Group %s couldn't be activated " group)))
+ (bottom (if gnus-newsgroup-maximum-articles
+ (max (car active)
+ (- last gnus-newsgroup-maximum-articles -1))
+ (car active)))
first nlast unread)
;; If none are read, then all are unread.
(if (not read)
- (setq first (car active))
+ (setq first bottom)
;; If the range of read articles is a single range, then the
;; first unread article is the article after the last read
;; article. Sounds logical, doesn't it?
(if (and (not (listp (cdr read)))
- (or (< (car read) (car active))
+ (or (< (car read) bottom)
(progn (setq read (list read))
nil)))
- (setq first (max (car active) (1+ (cdr read))))
+ (setq first (max bottom (1+ (cdr read))))
;; `read' is a list of ranges.
(when (/= (setq nlast (or (and (numberp (car read)) (car read))
(caar read)))
1)
- (setq first (car active)))
+ (setq first bottom))
(while read
(when first
(while (< first nlast)
(gnus-list-range-difference
(gnus-list-range-difference
(gnus-sorted-complement
- (gnus-uncompress-range active)
+ (gnus-uncompress-range
+ (if gnus-newsgroup-maximum-articles
+ (cons (max (car active)
+ (- (cdr active)
+ gnus-newsgroup-maximum-articles
+ -1))
+ (cdr active))
+ active))
(gnus-list-of-unread-articles group))
(cdr (assq 'dormant marked)))
(cdr (assq 'tick marked))))))
(let* ((read (gnus-info-read (gnus-get-info group)))
(active (or (gnus-active group) (gnus-activate-group group)))
(last (cdr active))
+ (bottom (if gnus-newsgroup-maximum-articles
+ (max (car active)
+ (- last gnus-newsgroup-maximum-articles -1))
+ (car active)))
first nlast unread)
;; If none are read, then all are unread.
(if (not read)
- (setq first (car active))
+ (setq first bottom)
;; If the range of read articles is a single range, then the
;; first unread article is the article after the last read
;; article. Sounds logical, doesn't it?
(if (and (not (listp (cdr read)))
- (or (< (car read) (car active))
+ (or (< (car read) bottom)
(progn (setq read (list read))
nil)))
- (setq first (max (car active) (1+ (cdr read))))
+ (setq first (max bottom (1+ (cdr read))))
;; `read' is a list of ranges.
(when (/= (setq nlast (or (and (numberp (car read)) (car read))
(caar read)))
1)
- (setq first (car active)))
+ (setq first bottom))
(while read
(when first
(push (cons first nlast) unread))
(gnus-run-hooks 'gnus-summary-prepare-exit-hook)
;; If we have several article buffers, we kill them at exit.
(unless gnus-single-article-buffer
- (gnus-kill-buffer gnus-original-article-buffer)
- (setq gnus-article-current nil))
+ (when (gnus-buffer-live-p gnus-article-buffer)
+ (with-current-buffer gnus-article-buffer
+ ;; Don't kill sticky article buffers
+ (unless (eq major-mode 'gnus-sticky-article-mode)
+ (gnus-kill-buffer gnus-article-buffer)
+ (setq gnus-article-current nil))))
+ (gnus-kill-buffer gnus-original-article-buffer))
(when gnus-use-cache
(gnus-cache-possibly-remove-articles)
(gnus-cache-save-buffers))
(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))))
(setq group-point (point))
(if temporary
nil ;Nothing to do.
- ;; If we have several article buffers, we kill them at exit.
- (unless gnus-single-article-buffer
- (gnus-kill-buffer gnus-article-buffer)
- (gnus-kill-buffer gnus-original-article-buffer)
- (setq gnus-article-current nil))
(set-buffer buf)
(if (not gnus-kill-summary-on-exit)
(progn
(gnus-set-global-variables))))
(if (or (eq (cdr quit-config) 'article)
(eq (cdr quit-config) 'pick))
- (progn
- ;; The current article may be from the ephemeral group
- ;; thus it is best that we reload this article
- ;;
- ;; If we're exiting from a large digest, this can be
- ;; extremely slow. So, it's better not to reload it. -- jh.
- ;;(gnus-summary-show-article)
- (if (and (boundp 'gnus-pick-mode) (symbol-value 'gnus-pick-mode))
- (gnus-configure-windows 'pick 'force)
- (gnus-configure-windows (cdr quit-config) 'force)))
+ (if (and (boundp 'gnus-pick-mode) (symbol-value 'gnus-pick-mode))
+ (gnus-configure-windows 'pick 'force)
+ (gnus-configure-windows (cdr quit-config) 'force))
(gnus-configure-windows