(autoload 'gnus-mailing-list-insinuate "gnus-ml" nil t)
(autoload 'turn-on-gnus-mailing-list-mode "gnus-ml" nil t)
(autoload 'mm-uu-dissect "mm-uu")
+(autoload 'gnus-article-outlook-deuglify-article "deuglify"
+ "Deuglify broken Outlook (Express) articles and redisplay."
+ t)
(defcustom gnus-kill-summary-on-exit t
"*If non-nil, kill the summary buffer when you exit from it.
(const adopt)
(const empty)))
+(defcustom gnus-summary-make-false-root-always t
+ "Always make a false dummy root."
+ :group 'gnus-thread
+ :type 'boolean)
+
(defcustom gnus-summary-gather-exclude-subject "^ *$\\|^(none)$"
"*A regexp to match subjects to be excluded from loose thread gathering.
As loose thread gathering is done on subjects only, that means that
"List of functions taking a string argument that simplify subjects.
The functions are applied recursively.
-Useful functions to put in this list include: `gnus-simplify-subject-re',
-`gnus-simplify-subject-fuzzy' and `gnus-simplify-whitespace'."
+Useful functions to put in this list include:
+`gnus-simplify-subject-re', `gnus-simplify-subject-fuzzy',
+`gnus-simplify-whitespace', and `gnus-simplify-all-whitespace'."
:group 'gnus-thread
:type '(repeat function))
(defcustom gnus-simplify-ignored-prefixes nil
- "*Regexp, matches for which are removed from subject lines when simplifying fuzzily."
+ "*Remove matches for this regexp from subject lines when simplifying fuzzily."
:group 'gnus-thread
:type '(choice (const :tag "off" nil)
regexp))
the end of an article.
If nil, the marking commands do NOT go to the next unread article
-(they go to the next article instead). If `never', commands that
+\(they go to the next article instead). If `never', commands that
usually go to the next unread article, will go to the next article,
whether it is read or not."
:group 'gnus-summary-marks
first subject), `unread' (place point on the subject line of the first
unread article), `best' (place point on the subject line of the
higest-scored article), `unseen' (place point on the subject line of
-the first unseen article), or a function to be called to place point on
-some subject line.."
+the first unseen article), 'unseen-or-unread' (place point on the subject
+line of the first unseen article or, if all article have been seen, on the
+subject line of the first unread article), or a function to be called to
+place point on some subject line."
:group 'gnus-group-select
:type '(choice (const best)
(const unread)
(const first)
- (const unseen)))
+ (const unseen)
+ (const unseen-or-unread)))
(defcustom gnus-auto-select-next t
"*If non-nil, offer to go to the next group from the end of the previous.
:group 'gnus-summary-marks
:type 'character)
+(defcustom gnus-spam-mark ?H
+ "*Mark used for spam articles."
+ :group 'gnus-summary-marks
+ :type 'character)
+
(defcustom gnus-souped-mark ?F
"*Mark used for souped articles."
:group 'gnus-summary-marks
:group 'gnus-summary-marks
:type 'character)
-(defcustom gnus-undownloaded-mark ?@
+(defcustom gnus-undownloaded-mark ?-
"*Mark used for articles that weren't downloaded."
:group 'gnus-summary-marks
:type 'character)
+(defcustom gnus-downloaded-mark ?+
+ "*Mark used for articles that were downloaded."
+ :group 'gnus-summary-marks
+ :type 'character)
+
(defcustom gnus-downloadable-mark ?%
"*Mark used for articles that are to be downloaded."
:group 'gnus-summary-marks
:type 'boolean)
(defcustom gnus-summary-dummy-line-format
- " %(: :%) %S\n"
+ " %(: :%) %S\n"
"*The format specification for the dummy roots in the summary buffer.
It works along the same lines as a normal formatting string,
with some simple extensions.
%S The subject
-General format specifiers can also be used.
-See (gnus)Formatting Variables."
+General format specifiers can also be used.
+See `(gnus)Formatting Variables'."
:link '(custom-manual "(gnus)Formatting Variables")
:group 'gnus-threading
:type 'string)
Ready-made functions include `gnus-article-sort-by-number',
`gnus-article-sort-by-author', `gnus-article-sort-by-subject',
-`gnus-article-sort-by-date' and `gnus-article-sort-by-score'.
+`gnus-article-sort-by-date', `gnus-article-sort-by-random'
+and `gnus-article-sort-by-score'.
When threading is turned on, the variable `gnus-thread-sort-functions'
controls how articles are sorted."
(function-item gnus-article-sort-by-subject)
(function-item gnus-article-sort-by-date)
(function-item gnus-article-sort-by-score)
+ (function-item gnus-article-sort-by-random)
(function :tag "other"))))
(defcustom gnus-thread-sort-functions '(gnus-thread-sort-by-number)
`gnus-thread-sort-by-author', `gnus-thread-sort-by-subject',
`gnus-thread-sort-by-date', `gnus-thread-sort-by-score',
`gnus-thread-sort-by-most-recent-number',
-`gnus-thread-sort-by-most-recent-date', and
+`gnus-thread-sort-by-most-recent-date',
+`gnus-thread-sort-by-random', and
`gnus-thread-sort-by-total-score' (see `gnus-thread-score-function').
When threading is turned off, the variable
(function-item gnus-thread-sort-by-date)
(function-item gnus-thread-sort-by-score)
(function-item gnus-thread-sort-by-total-score)
+ (function-item gnus-thread-sort-by-random)
(function :tag "other"))))
(defcustom gnus-thread-score-function '+
:group 'gnus-summary-visual
:type 'face)
+(defvar gnus-tmp-downloaded nil)
+
(defcustom gnus-summary-highlight
- '(((= mark gnus-canceled-mark)
+ '(((eq mark gnus-canceled-mark)
. gnus-summary-cancelled-face)
+ ((and uncached (> score default-high))
+ . gnus-summary-high-uncached-face)
+ ((and uncached (< score default-low))
+ . gnus-summary-low-uncached-face)
+ (uncached
+ . gnus-summary-normal-uncached-face)
((and (> score default-high)
- (or (= mark gnus-dormant-mark)
- (= mark gnus-ticked-mark)))
+ (or (eq mark gnus-dormant-mark)
+ (eq mark gnus-ticked-mark)))
. gnus-summary-high-ticked-face)
((and (< score default-low)
- (or (= mark gnus-dormant-mark)
- (= mark gnus-ticked-mark)))
+ (or (eq mark gnus-dormant-mark)
+ (eq mark gnus-ticked-mark)))
. gnus-summary-low-ticked-face)
- ((or (= mark gnus-dormant-mark)
- (= mark gnus-ticked-mark))
+ ((or (eq mark gnus-dormant-mark)
+ (eq mark gnus-ticked-mark))
. gnus-summary-normal-ticked-face)
- ((and (> score default-high) (= mark gnus-ancient-mark))
+ ((and (> score default-high) (eq mark gnus-ancient-mark))
. gnus-summary-high-ancient-face)
- ((and (< score default-low) (= mark gnus-ancient-mark))
+ ((and (< score default-low) (eq mark gnus-ancient-mark))
. gnus-summary-low-ancient-face)
- ((= mark gnus-ancient-mark)
+ ((eq mark gnus-ancient-mark)
. gnus-summary-normal-ancient-face)
- ((and (> score default-high) (= mark gnus-unread-mark))
+ ((and (> score default-high) (eq mark gnus-unread-mark))
. gnus-summary-high-unread-face)
- ((and (< score default-low) (= mark gnus-unread-mark))
+ ((and (< score default-low) (eq mark gnus-unread-mark))
. gnus-summary-low-unread-face)
- ((= mark gnus-unread-mark)
+ ((eq mark gnus-unread-mark)
. gnus-summary-normal-unread-face)
- ((and (> score default-high) (memq mark (list gnus-downloadable-mark
- gnus-undownloaded-mark)))
- . gnus-summary-high-unread-face)
- ((and (< score default-low) (memq mark (list gnus-downloadable-mark
- gnus-undownloaded-mark)))
- . gnus-summary-low-unread-face)
- ((and (memq mark (list gnus-downloadable-mark gnus-undownloaded-mark))
- (memq article gnus-newsgroup-unreads))
- . gnus-summary-normal-unread-face)
- ((memq mark (list gnus-downloadable-mark gnus-undownloaded-mark))
- . gnus-summary-normal-read-face)
((> score default-high)
. gnus-summary-high-read-face)
((< score default-low)
:type '(choice (const nil)
integer))
-(defcustom gnus-summary-save-parts-default-mime "image/.*"
- "*A regexp to match MIME parts when saving multiple parts of a message
-with gnus-summary-save-parts (X m). This regexp will be used by default
-when prompting the user for which type of files to save."
- :group 'gnus-summary
- :type 'regexp)
-
-
(defcustom gnus-summary-save-parts-default-mime "image/.*"
"*A regexp to match MIME parts when saving multiple parts of a message
with gnus-summary-save-parts (X m). This regexp will be used by default
(defcustom gnus-summary-muttprint-program "muttprint"
"Command (and optional arguments) used to run Muttprint."
+ :version "21.3"
:group 'gnus-summary
:type 'string)
+(defcustom gnus-article-loose-mime nil
+ "If non-nil, don't require MIME-Version header.
+Some brain-damaged MUA/MTA, e.g. Lotus Domino 5.0.6 clients, does not
+supply the MIME-Version header or deliberately strip it From the mail.
+Set it to non-nil, Gnus will treat some articles as MIME even if
+the MIME-Version header is missed."
+ :version "21.3"
+ :type 'boolean
+ :group 'gnus-article)
+
;;; Internal variables
(defvar gnus-summary-display-cache nil)
(defvar gnus-article-ignored-charsets nil)
(defvar gnus-scores-exclude-files nil)
(defvar gnus-page-broken nil)
-(defvar gnus-inhibit-mime-unbuttonizing nil)
(defvar gnus-original-article nil)
(defvar gnus-article-internal-prepare-hook nil)
(defvar gnus-summary-save-parts-type-history nil)
(defvar gnus-summary-save-parts-last-directory nil)
-(defvar gnus-summary-save-parts-type-history nil)
-(defvar gnus-summary-save-parts-last-directory nil)
-
;; Avoid highlighting in kill files.
(defvar gnus-summary-inhibit-highlight nil)
(defvar gnus-newsgroup-selected-overlay nil)
(?M ,(macroexpand '(mail-header-id gnus-tmp-header)) ?s)
(?r ,(macroexpand '(mail-header-references gnus-tmp-header)) ?s)
(?c (or (mail-header-chars gnus-tmp-header) 0) ?d)
+ (?k (gnus-summary-line-message-size gnus-tmp-header) ?s)
(?L gnus-tmp-lines ?s)
+ (?O gnus-tmp-downloaded ?c)
(?I gnus-tmp-indentation ?s)
(?T (if (= gnus-tmp-level 0) "" (make-string (frame-width) ? )) ?s)
(?R gnus-tmp-replied ?c)
(?u gnus-tmp-user-defined ?s)
(?d (length gnus-newsgroup-dormant) ?d)
(?t (length gnus-newsgroup-marked) ?d)
+ (?h (length gnus-newsgroup-spam-marked) ?d)
(?r (length gnus-newsgroup-reads) ?d)
(?z (gnus-summary-article-score gnus-tmp-article-number) ?d)
(?E gnus-newsgroup-expunged-tally ?d)
(defvar gnus-last-shell-command nil
"Default shell command on article.")
+(defvar gnus-newsgroup-agentized nil
+ "Locally bound in each summary buffer to indicate whether the server has been agentized.")
(defvar gnus-newsgroup-begin nil)
(defvar gnus-newsgroup-end nil)
(defvar gnus-newsgroup-last-rmail nil)
(defvar gnus-newsgroup-limits nil)
(defvar gnus-newsgroup-unreads nil
- "List of unread articles in the current newsgroup.")
+ "Sorted list of unread articles in the current newsgroup.")
(defvar gnus-newsgroup-unselected nil
- "List of unselected unread articles in the current newsgroup.")
+ "Sorted list of unselected unread articles in the current newsgroup.")
(defvar gnus-newsgroup-reads nil
"Alist of read articles and article marks in the current newsgroup.")
(defvar gnus-newsgroup-expunged-tally nil)
(defvar gnus-newsgroup-marked nil
- "List of ticked articles in the current newsgroup (a subset of unread art).")
+ "Sorted list of ticked articles in the current newsgroup (a subset of unread art).")
+
+(defvar gnus-newsgroup-spam-marked nil
+ "List of ranges of articles that have been marked as spam.")
(defvar gnus-newsgroup-killed nil
"List of ranges of articles that have been through the scoring process.")
(defvar gnus-newsgroup-cached nil
- "List of articles that come from the article cache.")
+ "Sorted list of articles that come from the article cache.")
(defvar gnus-newsgroup-saved nil
"List of articles that have been saved.")
"List of articles that have are recent in the current newsgroup.")
(defvar gnus-newsgroup-expirable nil
- "List of articles in the current newsgroup that can be expired.")
+ "Sorted list of articles in the current newsgroup that can be expired.")
(defvar gnus-newsgroup-processable nil
"List of articles in the current newsgroup that can be processed.")
(defvar gnus-newsgroup-downloadable nil
- "List of articles in the current newsgroup that can be processed.")
+ "Sorted list of articles in the current newsgroup that can be processed.")
(defvar gnus-newsgroup-undownloaded nil
"List of articles in the current newsgroup that haven't been downloaded..")
"List of articles in the current newsgroup that have bookmarks.")
(defvar gnus-newsgroup-dormant nil
- "List of dormant articles in the current newsgroup.")
+ "Sorted list of dormant articles in the current newsgroup.")
(defvar gnus-newsgroup-unseen nil
"List of unseen articles in the current newsgroup.")
gnus-newsgroup-last-folder gnus-newsgroup-last-file
gnus-newsgroup-auto-expire gnus-newsgroup-unreads
gnus-newsgroup-unselected gnus-newsgroup-marked
+ gnus-newsgroup-spam-marked
gnus-newsgroup-reads gnus-newsgroup-saved
gnus-newsgroup-replied gnus-newsgroup-forwarded
gnus-newsgroup-recent
(setq mystr (substring mystr 0 (match-beginning 0))))
mystr))
+(defun gnus-simplify-all-whitespace (str)
+ "Remove all whitespace from STR."
+ (let ((mystr str))
+ (while (string-match "[ \t\n]+" mystr)
+ (setq mystr (replace-match "" nil nil mystr)))
+ mystr))
+
(defsubst gnus-simplify-subject-re (subject)
"Remove \"Re:\" from subject lines."
(if (string-match message-subject-re-regexp subject)
"\C-c\C-s\C-d" gnus-summary-sort-by-date
"\C-c\C-s\C-i" gnus-summary-sort-by-score
"\C-c\C-s\C-o" gnus-summary-sort-by-original
+ "\C-c\C-s\C-r" gnus-summary-sort-by-random
"=" gnus-summary-expand-window
"\C-x\C-s" gnus-summary-reselect-current-group
"\M-g" gnus-summary-rescan-group
"T" gnus-summary-limit-include-thread
"d" gnus-summary-limit-exclude-dormant
"t" gnus-summary-limit-to-age
+ "." gnus-summary-limit-to-unseen
"x" gnus-summary-limit-to-extra
"p" gnus-summary-limit-to-display-predicate
"E" gnus-summary-limit-include-expunged
"6" gnus-article-de-base64-unreadable
"Z" gnus-article-decode-HZ
"h" gnus-article-wash-html
+ "u" gnus-article-unsplit-urls
"s" gnus-summary-force-verify-and-decrypt
"f" gnus-article-display-x-face
"l" gnus-summary-stop-page-breaking
"r" gnus-summary-caesar-message
+ "m" gnus-summary-morse-message
"t" gnus-summary-toggle-header
"g" gnus-treat-smiley
"v" gnus-summary-verbose-headers
"a" gnus-article-strip-headers-in-body ;; mnemonic: wash archive
"p" gnus-article-verify-x-pgp-sig
- "d" gnus-article-treat-dumbquotes)
+ "d" gnus-article-treat-dumbquotes
+ "k" gnus-article-outlook-deuglify-article)
(gnus-define-keys (gnus-summary-wash-hide-map "W" gnus-summary-wash-map)
"a" gnus-article-hide
"f" gnus-summary-fetch-faq
"d" gnus-summary-describe-group
"h" gnus-summary-describe-briefly
- "i" gnus-info-find-node)
+ "i" gnus-info-find-node
+ "c" gnus-group-fetch-charter
+ "C" gnus-group-fetch-control)
(gnus-define-keys (gnus-summary-backend-map "B" gnus-summary-mode-map)
"e" gnus-summary-expire-articles
"o" gnus-article-save-part
"c" gnus-article-copy-part
"C" gnus-article-view-part-as-charset
- "e" gnus-article-externalize-part
+ "e" gnus-article-view-part-externally
"E" gnus-article-encrypt-body
"i" gnus-article-inline-part
- "|" gnus-article-pipe-part))
+ "|" gnus-article-pipe-part)
+
+ (gnus-define-keys (gnus-uu-mark-map "P" gnus-summary-mark-map)
+ "p" gnus-summary-mark-as-processable
+ "u" gnus-summary-unmark-as-processable
+ "U" gnus-summary-unmark-all-processable
+ "v" gnus-uu-mark-over
+ "s" gnus-uu-mark-series
+ "r" gnus-uu-mark-region
+ "g" gnus-uu-unmark-region
+ "R" gnus-uu-mark-by-regexp
+ "G" gnus-uu-unmark-by-regexp
+ "t" gnus-uu-mark-thread
+ "T" gnus-uu-unmark-thread
+ "a" gnus-uu-mark-all
+ "b" gnus-uu-mark-buffer
+ "S" gnus-uu-mark-sparse
+ "k" gnus-summary-kill-process-mark
+ "y" gnus-summary-yank-process-mark
+ "w" gnus-summary-save-process-mark
+ "i" gnus-uu-invert-processable)
+
+ (gnus-define-keys (gnus-uu-extract-map "X" gnus-summary-mode-map)
+ ;;"x" gnus-uu-extract-any
+ "m" gnus-summary-save-parts
+ "u" gnus-uu-decode-uu
+ "U" gnus-uu-decode-uu-and-save
+ "s" gnus-uu-decode-unshar
+ "S" gnus-uu-decode-unshar-and-save
+ "o" gnus-uu-decode-save
+ "O" gnus-uu-decode-save
+ "b" gnus-uu-decode-binhex
+ "B" gnus-uu-decode-binhex
+ "p" gnus-uu-decode-postscript
+ "P" gnus-uu-decode-postscript-and-save)
+
+ (gnus-define-keys
+ (gnus-uu-extract-view-map "v" gnus-uu-extract-map)
+ "u" gnus-uu-decode-uu-view
+ "U" gnus-uu-decode-uu-and-save-view
+ "s" gnus-uu-decode-unshar-view
+ "S" gnus-uu-decode-unshar-and-save-view
+ "o" gnus-uu-decode-save-view
+ "O" gnus-uu-decode-save-view
+ "b" gnus-uu-decode-binhex-view
+ "B" gnus-uu-decode-binhex-view
+ "p" gnus-uu-decode-postscript-view
+ "P" gnus-uu-decode-postscript-and-save-view))
(defvar gnus-article-post-menu nil)
+(defconst gnus-summary-menu-maxlen 20)
+
+(defun gnus-summary-menu-split (menu)
+ ;; If we have lots of elements, divide them into groups of 20
+ ;; and make a pane (or submenu) for each one.
+ (if (> (length menu) (/ (* gnus-summary-menu-maxlen 3) 2))
+ (let ((menu menu) sublists next
+ (i 1))
+ (while menu
+ ;; Pull off the next gnus-summary-menu-maxlen elements
+ ;; and make them the next element of sublist.
+ (setq next (nthcdr gnus-summary-menu-maxlen menu))
+ (if next
+ (setcdr (nthcdr (1- gnus-summary-menu-maxlen) menu)
+ nil))
+ (setq sublists (cons (cons (format "%s ... %s" (aref (car menu) 0)
+ (aref (car (last menu)) 0)) menu)
+ sublists))
+ (setq i (1+ i))
+ (setq menu next))
+ (nreverse sublists))
+ ;; Few elements--put them all in one pane.
+ menu))
+
(defun gnus-summary-make-menu-bar ()
(gnus-turn-off-edit-menu 'summary)
["Charset" gnus-article-decode-charset t]
["QP" gnus-article-de-quoted-unreadable t]
["Base64" gnus-article-de-base64-unreadable t]
+ ["View MIME buttons" gnus-summary-display-buttonized t]
["View all" gnus-mime-view-all-parts t]
["Verify and Decrypt" gnus-summary-force-verify-and-decrypt t]
- ["Encrypt body" gnus-article-encrypt-body t])
+ ["Encrypt body" gnus-article-encrypt-body t]
+ ["Extract all parts" gnus-summary-save-parts t])
("Date"
["Local" gnus-article-date-local t]
["ISO8601" gnus-article-date-iso8601 t]
["Show X-Face" gnus-article-display-x-face t]
["Show picons in From" gnus-treat-from-picon t]
["Show picons in mail headers" gnus-treat-mail-picon t]
- ["Show picons in news headers" gnus-treat-newsgroups-picon t])
+ ["Show picons in news headers" gnus-treat-newsgroups-picon t]
+ ("View as different encoding"
+ ,@(gnus-summary-menu-split
+ (mapcar
+ (lambda (cs)
+ ;; Since easymenu under FSF Emacs doesn't allow lambda
+ ;; forms for menu commands, we should provide intern'ed
+ ;; function symbols.
+ (let ((command (intern (format "\
+gnus-summary-show-article-from-menu-as-charset-%s" cs))))
+ (fset command
+ `(lambda ()
+ (interactive)
+ (let ((gnus-summary-show-article-charset-alist
+ '((1 . ,cs))))
+ (gnus-summary-show-article 1))))
+ `[,(symbol-name cs) ,command t]))
+ (sort (if (fboundp 'coding-system-list)
+ (coding-system-list)
+ (mapcar 'car mm-mime-mule-charset-alist))
+ 'string<)))))
("Washing"
("Remove Blanks"
["Leading" gnus-article-strip-leading-blank-lines t]
["Rot 13" gnus-summary-caesar-message
,@(if (featurep 'xemacs) '(t)
'(:help "\"Caesar rotate\" article by 13"))]
- ["Unix pipe" gnus-summary-pipe-message t]
+ ["Morse decode" gnus-summary-morse-message t]
+ ["Unix pipe..." gnus-summary-pipe-message t]
["Add buttons" gnus-article-add-buttons t]
["Add buttons to head" gnus-article-add-buttons-to-head t]
["Stop page breaking" gnus-summary-stop-page-breaking t]
["Unfold headers" gnus-article-treat-unfold-headers t]
["Fold newsgroups" gnus-article-treat-fold-newsgroups t]
["Html" gnus-article-wash-html t]
+ ["URLs" gnus-article-unsplit-urls t]
["Verify X-PGP-Sig" gnus-article-verify-x-pgp-sig t]
- ["HZ" gnus-article-decode-HZ t])
+ ["HZ" gnus-article-decode-HZ t]
+ ["OutlooK deuglify" gnus-article-outlook-deuglify-article t]
+ )
("Output"
["Save in default format" gnus-summary-save-article
,@(if (featurep 'xemacs) '(t)
["Unshar and save" gnus-uu-decode-unshar-and-save t]
["Save" gnus-uu-decode-save t]
["Binhex" gnus-uu-decode-binhex t]
- ["Postscript" gnus-uu-decode-postscript t])
+ ["Postscript" gnus-uu-decode-postscript t]
+ ["All MIME parts" gnus-summary-save-parts t])
("Cache"
["Enter article" gnus-cache-enter-article t]
["Remove article" gnus-cache-remove-article t])
["Wide reply and yank" gnus-summary-wide-reply-with-original
,@(if (featurep 'xemacs) '(t)
'(:help "Mail a reply, quoting this article"))]
- ["Very wide reply" gnus-summary-very-wide-reply t]
- ["Very wide reply and yank" gnus-summary-very-wide-reply-with-original
- ,@(if (featurep 'xemacs) '(t)
- '(:help "Mail a very wide reply, quoting this article"))]
+ ["Very wide reply" gnus-summary-very-wide-reply t]
+ ["Very wide reply and yank" gnus-summary-very-wide-reply-with-original
+ ,@(if (featurep 'xemacs) '(t)
+ '(:help "Mail a very wide reply, quoting this article"))]
["Mail forward" gnus-summary-mail-forward t]
["Post forward" gnus-summary-post-forward t]
["Digest and mail" gnus-uu-digest-mail-forward t]
["Digest and post" gnus-uu-digest-post-forward t]
["Resend message" gnus-summary-resend-message t]
+ ["Resend message edit" gnus-summary-resend-message-edit t]
["Send bounced mail" gnus-summary-resend-bounced-mail t]
["Send a mail" gnus-summary-mail-other-window t]
["Create a local message" gnus-summary-news-other-window t]
["Author..." gnus-summary-limit-to-author t]
["Age..." gnus-summary-limit-to-age t]
["Extra..." gnus-summary-limit-to-extra t]
- ["Score" gnus-summary-limit-to-score 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]
["Non-dormant" gnus-summary-limit-exclude-dormant t]
- ["Articles" gnus-summary-limit-to-articles t]
+ ["Next 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"
["Sort by score" gnus-summary-sort-by-score t]
["Sort by lines" gnus-summary-sort-by-lines t]
["Sort by characters" gnus-summary-sort-by-chars t]
+ ["Randomize" gnus-summary-sort-by-random t]
["Original sort" gnus-summary-sort-by-original t])
("Help"
["Fetch group FAQ" gnus-summary-fetch-faq t]
["Describe group" gnus-summary-describe-group t]
+ ["Fetch charter" gnus-group-fetch-charter
+ ,@(if (featurep 'xemacs) nil
+ '(:help "Display the charter of the current group"))]
+ ["Fetch control message" gnus-group-fetch-control
+ ,@(if (featurep 'xemacs) nil
+ '(:help "Display the archived control message for the current group"))]
["Read manual" gnus-info-find-node t])
("Modes"
["Pick and read" gnus-pick-mode t]
(defun gnus-article-read-p (article)
"Say whether ARTICLE is read or not."
(not (or (memq article gnus-newsgroup-marked)
+ (memq article gnus-newsgroup-spam-marked)
(memq article gnus-newsgroup-unreads)
(memq article gnus-newsgroup-unselected)
(memq article gnus-newsgroup-dormant))))
(defmacro gnus-summary-article-number ()
"The article number of the article on the current line.
-If there isn's an article number here, then we return the current
+If there isn't an article number here, then we return the current
article number."
'(progn
(gnus-summary-skip-intangible)
marks of articles."
`(cond
((memq ,number gnus-newsgroup-unsendable) gnus-unsendable-mark)
- ((memq ,number gnus-newsgroup-undownloaded) gnus-undownloaded-mark)
((memq ,number gnus-newsgroup-downloadable) gnus-downloadable-mark)
((memq ,number gnus-newsgroup-unreads) gnus-unread-mark)
((memq ,number gnus-newsgroup-marked) gnus-ticked-mark)
+ ((memq ,number gnus-newsgroup-spam-marked) gnus-spam-mark)
((memq ,number gnus-newsgroup-dormant) gnus-dormant-mark)
((memq ,number gnus-newsgroup-expirable) gnus-expirable-mark)
(t (or (cdr (assq ,number gnus-newsgroup-reads))
(setq gnus-summary-buffer (current-buffer))
(let ((name gnus-newsgroup-name)
(marked gnus-newsgroup-marked)
+ (spam gnus-newsgroup-spam-marked)
(unread gnus-newsgroup-unreads)
(headers gnus-current-headers)
(data gnus-newsgroup-data)
(set-buffer gnus-group-buffer)
(setq gnus-newsgroup-name name
gnus-newsgroup-marked marked
+ gnus-newsgroup-spam-marked spam
gnus-newsgroup-unreads unread
gnus-current-headers headers
gnus-newsgroup-data data
(let ((gnus-replied-mark 129)
(gnus-score-below-mark 130)
(gnus-score-over-mark 130)
- (gnus-download-mark 131)
+ (gnus-downloaded-mark 131)
(spec gnus-summary-line-format-spec)
gnus-visual pos)
(save-excursion
(gnus-set-work-buffer)
(let ((gnus-summary-line-format-spec spec)
- (gnus-newsgroup-downloadable '((0 . t))))
+ (gnus-newsgroup-downloadable '(0)))
(gnus-summary-insert-line
[0 "" "" "05 Apr 2001 23:33:09 +0400" "" "" 0 0 "" nil]
- 0 nil 128 t nil "" nil 1)
+ 0 nil nil 128 t nil "" nil 1)
(goto-char (point-min))
(setq pos (list (cons 'unread (and (search-forward "\200" nil t)
- (- (point) 2)))))
+ (- (point) (point-min) 1)))))
(goto-char (point-min))
(push (cons 'replied (and (search-forward "\201" nil t)
- (- (point) 2)))
+ (- (point) (point-min) 1)))
pos)
(goto-char (point-min))
- (push (cons 'score (and (search-forward "\202" nil t) (- (point) 2)))
+ (push (cons 'score (and (search-forward "\202" nil t)
+ (- (point) (point-min) 1)))
pos)
(goto-char (point-min))
(push (cons 'download
- (and (search-forward "\203" nil t) (- (point) 2)))
+ (and (search-forward "\203" nil t)
+ (- (point) (point-min) 1)))
pos)))
(setq gnus-summary-mark-positions pos))))
(defun gnus-summary-insert-line (gnus-tmp-header
gnus-tmp-level gnus-tmp-current
- gnus-tmp-unread gnus-tmp-replied
+ undownloaded gnus-tmp-unread gnus-tmp-replied
gnus-tmp-expirable gnus-tmp-subject-or-nil
&optional gnus-tmp-dummy gnus-tmp-score
gnus-tmp-process)
((memq gnus-tmp-number gnus-newsgroup-unseen)
gnus-unseen-mark)
(t gnus-no-mark)))
+ (gnus-tmp-downloaded
+ (cond (undownloaded
+ gnus-undownloaded-mark)
+ (gnus-newsgroup-agentized
+ gnus-downloaded-mark)
+ (t
+ gnus-no-mark)))
(gnus-tmp-from (mail-header-from gnus-tmp-header))
(gnus-tmp-name
(cond
gnus-empty-thread-mark)
number)))
+(defsubst gnus-summary-line-message-size (head)
+ "Return pretty-printed version of message size.
+This function is intended to be used in
+`gnus-summary-line-format-alist', which see."
+ (let ((c (or (mail-header-chars head) -1)))
+ (cond ((< c 0) "n/a") ; chars not available
+ ((< c (* 1000 10)) (format "%1.1fk" (/ c 1024.0)))
+ ((< c (* 1000 100)) (format "%dk" (/ c 1024.0)))
+ ((< c (* 1000 10000)) (format "%1.1fM" (/ c (* 1024.0 1024))))
+ (t (format "%dM" (/ c (* 1024.0 1024)))))))
+
+
(defun gnus-summary-set-local-parameters (group)
"Go through the local params of GROUP and set all variable specs in that list."
(let ((params (gnus-group-find-parameter group))
(let ((gnus-newsgroup-dormant nil))
(gnus-summary-initial-limit show-all))
(gnus-summary-initial-limit show-all))
- ;; When untreaded, all articles are always shown.
+ ;; When unthreaded, all articles are always shown.
(setq gnus-newsgroup-limit
(mapcar
(lambda (header) (mail-header-number header))
(gnus-summary-first-unread-subject))
((eq gnus-auto-select-subject 'unseen)
(gnus-summary-first-unseen-subject))
+ ((eq gnus-auto-select-subject 'unseen-or-unread)
+ (gnus-summary-first-unseen-or-unread-subject))
((eq gnus-auto-select-subject 'first)
;; Do nothing.
)
(setcdr prev (cdr threads))
(setq threads prev))
;; Enter this thread into the hash table.
- (gnus-sethash subject threads hashtb)))
+ (gnus-sethash subject
+ (if gnus-summary-make-false-root-always
+ (progn
+ ;; If you want a dummy root above all
+ ;; threads...
+ (setcar threads (list whole-subject
+ (car threads)))
+ threads)
+ threads)
+ hashtb)))
(setq prev threads)
(setq threads (cdr threads)))
result)))
(setq threads nil)
(throw 'infloop t))
(unless (car (symbol-value refs))
- ;; These threads do not refer back to any other articles,
- ;; so they're roots.
+ ;; These threads do not refer back to any other
+ ;; articles, so they're roots.
(setq threads (append (cdr (symbol-value refs)) threads))))
gnus-newsgroup-dependencies)))
threads))
If `gnus-summary-ignore-duplicates' is nil then duplicate Message-IDs
will not be entered in the DEPENDENCIES table. Otherwise duplicate
-Message-IDs will be renamed be renamed to a unique Message-ID before
-being entered.
+Message-IDs will be renamed to a unique Message-ID before being
+entered.
Returns HEADER if it was entered in the DEPENDENCIES. Returns nil otherwise."
(let* ((id (mail-header-id header))
(id-dep (and id (intern id dependencies)))
- ref ref-dep ref-header)
+ parent-id ref ref-dep ref-header replaced)
;; Enter this `header' in the `dependencies' table.
(cond
((not id-dep)
(force-new
;; Overrides an existing entry;
;; just set the header part of the entry.
- (setcar (symbol-value id-dep) header))
+ (setcar (symbol-value id-dep) header)
+ (setq replaced t))
;; Renames the existing `header' to a unique Message-ID.
((not gnus-summary-ignore-duplicates)
(or (mail-header-xref header) "")))
(setq header nil)))
- (when header
- ;; First check if that we are not creating a References loop.
- (setq ref (gnus-parent-id (mail-header-references header)))
+ (when (and header (not replaced))
+ ;; First check that we are not creating a References loop.
+ (setq parent-id (gnus-parent-id (mail-header-references header)))
+ (setq ref parent-id)
(while (and ref
(setq ref-dep (intern-soft ref dependencies))
(boundp ref-dep)
;; root article.
(progn
(mail-header-set-references (car (symbol-value id-dep)) "none")
- (setq ref nil))
+ (setq ref nil)
+ (setq parent-id nil))
(setq ref (gnus-parent-id (mail-header-references ref-header)))))
- (setq ref (gnus-parent-id (mail-header-references header)))
- (setq ref-dep (intern (or ref "none") dependencies))
+ (setq ref-dep (intern (or parent-id "none") dependencies))
(if (boundp ref-dep)
(setcdr (symbol-value ref-dep)
(nconc (cdr (symbol-value ref-dep))
(set ref-dep (list nil (symbol-value id-dep)))))
header))
+(defun gnus-extract-message-id-from-in-reply-to (string)
+ (if (string-match "<[^>]+>" string)
+ (substring string (match-beginning 0) (match-end 0))
+ nil))
+
(defun gnus-build-sparse-threads ()
(let ((headers gnus-newsgroup-headers)
(mail-parse-charset gnus-newsgroup-charset)
(defsubst gnus-nov-parse-line (number dependencies &optional force-new)
(let ((eol (gnus-point-at-eol))
(buffer (current-buffer))
- header)
+ header references in-reply-to)
;; overview: [num subject from date id refs chars lines misc]
(unwind-protect
- (progn
+ (let (x)
(narrow-to-region (point) eol)
(unless (eobp)
(forward-char))
(setq header
(make-full-mail-header
number ; number
- (funcall gnus-decode-encoded-word-function
- (nnheader-nov-field)) ; subject
- (funcall gnus-decode-encoded-word-function
- (nnheader-nov-field)) ; from
+ (condition-case () ; subject
+ (funcall gnus-decode-encoded-word-function
+ (setq x (nnheader-nov-field)))
+ (error x))
+ (condition-case () ; from
+ (funcall gnus-decode-encoded-word-function
+ (setq x (nnheader-nov-field)))
+ (error x))
(nnheader-nov-field) ; date
(nnheader-nov-read-message-id) ; id
- (nnheader-nov-field) ; refs
+ (setq references (nnheader-nov-field)) ; refs
(nnheader-nov-read-integer) ; chars
(nnheader-nov-read-integer) ; lines
(unless (eobp)
(widen))
+ (when (and (string= references "")
+ (setq in-reply-to (mail-header-extra header))
+ (setq in-reply-to (cdr (assq 'In-Reply-To in-reply-to))))
+ (mail-header-set-references
+ header (gnus-extract-message-id-from-in-reply-to in-reply-to)))
+
(when gnus-alter-header-function
(funcall gnus-alter-header-function header))
(gnus-dependencies-add-header header dependencies force-new)))
(push header gnus-newsgroup-headers)
(if (memq number gnus-newsgroup-unselected)
(progn
- (push number gnus-newsgroup-unreads)
+ (setq gnus-newsgroup-unreads
+ (gnus-add-to-sorted-list gnus-newsgroup-unreads
+ number))
(setq gnus-newsgroup-unselected
(delq number gnus-newsgroup-unselected)))
(push number gnus-newsgroup-ancient)))))))
(if (memq (setq article (mail-header-number header))
gnus-newsgroup-unselected)
(progn
- (push article gnus-newsgroup-unreads)
+ (setq gnus-newsgroup-unreads
+ (gnus-add-to-sorted-list
+ gnus-newsgroup-unreads article))
(setq gnus-newsgroup-unselected
(delq article gnus-newsgroup-unselected)))
(push article gnus-newsgroup-ancient)))
(level (gnus-summary-thread-level)))
(gnus-delete-line)
(gnus-summary-insert-line
- header level nil (gnus-article-mark article)
+ header level nil
+ (memq article gnus-newsgroup-undownloaded)
+ (gnus-article-mark article)
(memq article gnus-newsgroup-replied)
(memq article gnus-newsgroup-expirable)
;; Only insert the Subject string when it's different
(if (not gnus-thread-sort-functions)
threads
(gnus-message 8 "Sorting threads...")
- (prog1
- (gnus-sort-threads-1
+ (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"))))
+ (gnus-message 8 "Sorting threads...done")))))
(defun gnus-sort-articles (articles)
"Sort ARTICLES."
(gnus-article-sort-by-number
(gnus-thread-header h1) (gnus-thread-header h2)))
+(defsubst gnus-article-sort-by-random (h1 h2)
+ "Sort articles by article number."
+ (zerop (random 2)))
+
+(defun gnus-thread-sort-by-random (h1 h2)
+ "Sort threads by root article number."
+ (gnus-article-sort-by-random
+ (gnus-thread-header h1) (gnus-thread-header h2)))
+
(defsubst gnus-article-sort-by-lines (h1 h2)
"Sort articles by article Lines header."
(< (mail-header-lines h1)
(defun gnus-thread-latest-date (thread)
"Return the highest article date in THREAD."
(let ((previous-time 0))
- (apply 'max (mapcar
- (lambda (header)
- (setq previous-time
- (time-to-seconds
- (mail-header-parse-date
- (condition-case ()
- (mail-header-date header)
- (error previous-time))))))
- (sort
- (message-flatten-list thread)
- (lambda (h1 h2)
- (< (mail-header-number h1)
- (mail-header-number h2))))))))
+ (apply 'max
+ (mapcar
+ (lambda (header)
+ (setq previous-time
+ (time-to-seconds
+ (condition-case ()
+ (mail-header-parse-date (mail-header-date header))
+ (error previous-time)))))
+ (sort
+ (message-flatten-list thread)
+ (lambda (h1 h2)
+ (< (mail-header-number h1)
+ (mail-header-number h2))))))))
(defun gnus-thread-total-score-1 (root)
;; This function find the total score of the thread below ROOT.
(defvar gnus-tmp-thread-tree-header-string "")
-(defvar gnus-sum-thread-tree-root "> "
+(defcustom gnus-sum-thread-tree-root "> "
"With %B spec, used for the root of a thread.
-If nil, use subject instead.")
-(defvar gnus-sum-thread-tree-single-indent ""
+If nil, use subject instead."
+ :type 'string
+ :group 'gnus-thread)
+(defcustom gnus-sum-thread-tree-single-indent ""
"With %B spec, used for a thread with just one message.
-If nil, use subject instead.")
-(defvar gnus-sum-thread-tree-vertical "| "
- "With %B spec, used for drawing a vertical line.")
-(defvar gnus-sum-thread-tree-indent " "
- "With %B spec, used for indenting.")
-(defvar gnus-sum-thread-tree-leaf-with-other "+-> "
- "With %B spec, used for a leaf with brothers.")
-(defvar gnus-sum-thread-tree-single-leaf "\\-> "
- "With %B spec, used for a leaf without brothers.")
+If nil, use subject instead."
+ :type 'string
+ :group 'gnus-thread)
+(defcustom gnus-sum-thread-tree-vertical "| "
+ "With %B spec, used for drawing a vertical line."
+ :type 'string
+ :group 'gnus-thread)
+(defcustom gnus-sum-thread-tree-indent " "
+ "With %B spec, used for indenting."
+ :type 'string
+ :group 'gnus-thread)
+(defcustom gnus-sum-thread-tree-leaf-with-other "+-> "
+ "With %B spec, used for a leaf with brothers."
+ :type 'string
+ :group 'gnus-thread)
+(defcustom gnus-sum-thread-tree-single-leaf "\\-> "
+ "With %B spec, used for a leaf without brothers."
+ :type 'string
+ :group 'gnus-thread)
(defun gnus-summary-prepare-threads (threads)
"Prepare summary buffer from THREADS and indentation LEVEL.
(let ((gnus-tmp-level 0)
(default-score (or gnus-summary-default-score 0))
(gnus-visual-p (gnus-visual-p 'summary-highlight 'highlight))
+ (building-line-count gnus-summary-display-while-building)
+ (building-count (integerp gnus-summary-display-while-building))
thread number subject stack state gnus-tmp-gathered beg-match
- new-roots gnus-tmp-new-adopts thread-end
- gnus-tmp-header gnus-tmp-unread
+ new-roots gnus-tmp-new-adopts thread-end simp-subject
+ gnus-tmp-header gnus-tmp-unread gnus-tmp-downloaded
gnus-tmp-replied gnus-tmp-subject-or-nil
gnus-tmp-dummy gnus-tmp-indentation gnus-tmp-lines gnus-tmp-score
gnus-tmp-score-char gnus-tmp-from gnus-tmp-name
;; Do the threaded display.
+ (if gnus-summary-display-while-building
+ (switch-to-buffer (buffer-name)))
(while (or threads stack gnus-tmp-new-adopts new-roots)
(if (and (= gnus-tmp-level 0)
(setq gnus-tmp-level -1)))
(setq number (mail-header-number gnus-tmp-header)
- subject (mail-header-subject gnus-tmp-header))
+ subject (mail-header-subject gnus-tmp-header)
+ simp-subject (gnus-simplify-subject-fully subject))
(cond
;; If the thread has changed subject, we might want to make
((and (null gnus-thread-ignore-subject)
(not (zerop gnus-tmp-level))
gnus-tmp-prev-subject
- (not (inline
- (gnus-subject-equal gnus-tmp-prev-subject subject))))
+ (not (string= gnus-tmp-prev-subject simp-subject)))
(setq new-roots (nconc new-roots (list (car thread)))
thread-end t
gnus-tmp-header nil))
(setq gnus-newsgroup-unreads
(delq number gnus-newsgroup-unreads))
(if gnus-newsgroup-auto-expire
- (push number gnus-newsgroup-expirable)
+ (setq gnus-newsgroup-expirable
+ (gnus-add-to-sorted-list
+ gnus-newsgroup-expirable number))
(push (cons number gnus-low-score-mark)
gnus-newsgroup-reads))))
(cond
((and gnus-thread-ignore-subject
gnus-tmp-prev-subject
- (not (inline (gnus-subject-equal
- gnus-tmp-prev-subject subject))))
+ (not (string= gnus-tmp-prev-subject simp-subject)))
subject)
((zerop gnus-tmp-level)
(if (and (eq gnus-summary-make-false-root 'empty)
(memq number gnus-tmp-gathered)
gnus-tmp-prev-subject
- (inline (gnus-subject-equal
- gnus-tmp-prev-subject subject)))
+ (string= gnus-tmp-prev-subject simp-subject))
gnus-summary-same-subject
subject))
(t gnus-summary-same-subject)))
((memq number gnus-newsgroup-unseen)
gnus-unseen-mark)
(t gnus-no-mark))
+ gnus-tmp-downloaded
+ (cond ((memq number gnus-newsgroup-undownloaded)
+ gnus-undownloaded-mark)
+ (gnus-newsgroup-agentized
+ gnus-downloaded-mark)
+ (t
+ gnus-no-mark))
gnus-tmp-from (mail-header-from gnus-tmp-header)
gnus-tmp-name
(cond
(gnus-run-hooks 'gnus-summary-update-hook)
(forward-line 1))
- (setq gnus-tmp-prev-subject subject)))
+ (setq gnus-tmp-prev-subject simp-subject)))
(when (nth 1 thread)
(push (list (max 0 gnus-tmp-level)
(push (if (nth 1 thread) 1 0) tree-stack)
(incf gnus-tmp-level)
(setq threads (if thread-end nil (cdar thread)))
+ (if gnus-summary-display-while-building
+ (if building-count
+ (progn
+ ;; use a set frequency
+ (setq building-line-count (1- building-line-count))
+ (when (= building-line-count 0)
+ (sit-for 0)
+ (setq building-line-count
+ gnus-summary-display-while-building)))
+ ;; always
+ (sit-for 0)))
(unless threads
(setq gnus-tmp-level 0)))))
(gnus-message 7 "Generating summary...done"))
gnus-newsgroup-data)
(gnus-summary-insert-line
header 0 number
+ (memq number gnus-newsgroup-undownloaded)
mark (memq number gnus-newsgroup-replied)
(memq number gnus-newsgroup-expirable)
(mail-header-subject header) nil
(setq cached gnus-newsgroup-cached))
(setq gnus-newsgroup-unreads
- (gnus-set-difference
- (gnus-set-difference gnus-newsgroup-unreads gnus-newsgroup-marked)
+ (gnus-sorted-ndifference
+ (gnus-sorted-ndifference gnus-newsgroup-unreads
+ gnus-newsgroup-marked)
gnus-newsgroup-dormant))
(setq gnus-newsgroup-processable nil)
;; Adjust and set lists of article marks.
(when info
(gnus-adjust-marked-articles info))
-
(if (setq articles select-articles)
(setq gnus-newsgroup-unselected
- (gnus-sorted-intersection
- gnus-newsgroup-unreads
- (gnus-sorted-complement gnus-newsgroup-unreads articles)))
+ (gnus-sorted-difference gnus-newsgroup-unreads articles))
(setq articles (gnus-articles-to-read group read-all)))
(cond
(gnus-make-hashtable (length articles)))
(gnus-set-global-variables)
;; Retrieve the headers and read them in.
+
(setq gnus-newsgroup-headers (gnus-fetch-headers articles))
;; Kludge to avoid having cached articles nixed out in virtual groups.
gnus-newsgroup-headers))
(setq gnus-newsgroup-articles fetched-articles)
(setq gnus-newsgroup-unreads
- (gnus-set-sorted-intersection
+ (gnus-sorted-nintersection
gnus-newsgroup-unreads fetched-articles))
-
- ;; The `seen' marks are treated specially.
- (if (not gnus-newsgroup-seen)
- (setq gnus-newsgroup-unseen gnus-newsgroup-articles)
- (dolist (article gnus-newsgroup-articles)
- (unless (gnus-member-of-range article gnus-newsgroup-seen)
- (push article gnus-newsgroup-unseen)))
- (setq gnus-newsgroup-unseen (nreverse gnus-newsgroup-unseen)))
+ (gnus-compute-unseen-list)
;; Removed marked articles that do not exist.
(gnus-update-missing-marks
- (gnus-sorted-complement fetched-articles articles))
+ (gnus-sorted-difference articles fetched-articles))
;; We might want to build some more threads first.
(when (and gnus-fetch-old-headers
(eq gnus-headers-retrieved-by 'nov))
;; GROUP is successfully selected.
(or gnus-newsgroup-headers t)))))
+(defun gnus-compute-unseen-list ()
+ ;; The `seen' marks are treated specially.
+ (if (not gnus-newsgroup-seen)
+ (setq gnus-newsgroup-unseen gnus-newsgroup-articles)
+ (setq gnus-newsgroup-unseen
+ (gnus-inverse-list-range-intersection
+ gnus-newsgroup-articles gnus-newsgroup-seen))))
+
(defun gnus-summary-display-make-predicate (display)
(require 'gnus-agent)
(when (= (length display) 1)
(setq display (car display)))
(unless gnus-summary-display-cache
- (dolist (elem (append (list (cons 'read 'read)
- (cons 'unseen 'unseen))
+ (dolist (elem (append '((unread . unread)
+ (read . read)
+ (unseen . unseen))
gnus-article-mark-lists))
(push (cons (cdr elem)
(gnus-byte-compile
`(lambda () (gnus-article-marked-p ',(cdr elem)))))
gnus-summary-display-cache)))
- (let ((gnus-category-predicate-alist gnus-summary-display-cache))
+ (let ((gnus-category-predicate-alist gnus-summary-display-cache)
+ (gnus-category-predicate-cache gnus-summary-display-cache))
(gnus-get-predicate display)))
;; Uses the dynamically bound `number' variable.
-(defvar number)
+(eval-when-compile
+ (defvar number))
(defun gnus-article-marked-p (type &optional article)
(let ((article (or article number)))
(cond
((eq type 'tick)
(memq article gnus-newsgroup-marked))
+ ((eq type 'spam)
+ (memq article gnus-newsgroup-spam-marked))
((eq type 'unsend)
(memq article gnus-newsgroup-unsendable))
((eq type 'undownload)
(defun gnus-articles-to-read (group &optional read-all)
"Find out what articles the user wants to read."
- (let* ((articles
+ (let* ((display (gnus-group-find-parameter group 'display))
+ (articles
;; Select all articles if `read-all' is non-nil, or if there
;; are no unread articles.
(if (or read-all
(and (zerop (length gnus-newsgroup-marked))
(zerop (length gnus-newsgroup-unreads)))
- (eq gnus-newsgroup-display 'gnus-not-ignore))
+ ;; Fetch all if the predicate is non-nil.
+ gnus-newsgroup-display)
;; We want to select the headers for all the articles in
;; the group, so we select either all the active
;; articles in the group, or (if that's nil), the
(gnus-uncompress-range (gnus-active group))
(gnus-cache-articles-in-group group))
;; Select only the "normal" subset of articles.
- (sort (append gnus-newsgroup-dormant gnus-newsgroup-marked
- (copy-sequence gnus-newsgroup-unreads))
- '<)))
+ (gnus-sorted-nunion
+ (gnus-sorted-union gnus-newsgroup-dormant gnus-newsgroup-marked)
+ gnus-newsgroup-unreads)))
(scored-list (gnus-killed-articles gnus-newsgroup-killed articles))
(scored (length scored-list))
(number (length articles))
(cond
((numberp read-all)
read-all)
+ ((numberp gnus-newsgroup-display)
+ gnus-newsgroup-display)
(t
(condition-case ()
(cond
((and (or (<= scored marked) (= scored number))
(numberp gnus-large-newsgroup)
(> number gnus-large-newsgroup))
- (let ((input
- (read-string
- (format
- "How many articles from %s (default %d): "
- (gnus-limit-string
- (gnus-group-decoded-name gnus-newsgroup-name)
- 35)
- number))))
+ (let* ((cursor-in-echo-area nil)
+ (initial (gnus-parameter-large-newsgroup-initial
+ gnus-newsgroup-name))
+ (input
+ (read-string
+ (format
+ "How many articles from %s (%s %d): "
+ (gnus-limit-string
+ (gnus-group-decoded-name gnus-newsgroup-name)
+ 35)
+ (if initial "max" "default")
+ number)
+ (if initial
+ (cons (number-to-string initial)
+ 0)))))
(if (string-match "^[ \t]*$" input) number input)))
((and (> scored marked) (< scored number)
(> (- scored number) 20))
;; Select the N most recent articles.
(setq articles (nthcdr (- number select) articles))))
(setq gnus-newsgroup-unselected
- (gnus-sorted-intersection
- gnus-newsgroup-unreads
- (gnus-sorted-complement gnus-newsgroup-unreads articles)))
+ (gnus-sorted-difference gnus-newsgroup-unreads articles))
(when gnus-alter-articles-to-read-function
(setq gnus-newsgroup-unreads
(sort
((eq mark-type 'range)
(cond
((eq mark 'seen)
+ ;; Fix the record for `seen' if it looks like (seen NUM1 . NUM2).
+ ;; It should be (seen (NUM1 . NUM2)).
+ (when (numberp (cddr marks))
+ (setcdr marks (list (cdr marks))))
(setq articles (cdr marks))
(while (and articles
(or (and (consp (car articles))
;; Allow the user to mangle the headers before parsing them.
(gnus-run-hooks 'gnus-parse-headers-hook)
(goto-char (point-min))
- (while (not (eobp))
- (condition-case ()
- (while (and (or sequence allp)
- (not (eobp)))
- (setq number (read cur))
- (when (not allp)
- (while (and sequence
- (< (car sequence) number))
- (setq sequence (cdr sequence))))
- (when (and (or allp
- (and sequence
- (eq number (car sequence))))
- (progn
- (setq sequence (cdr sequence))
- (setq header (inline
- (gnus-nov-parse-line
- number dependencies force-new)))))
- (push header headers))
- (forward-line 1))
- (error
- (gnus-error 4 "Strange nov line (%d)"
- (count-lines (point-min) (point)))))
- (forward-line 1))
+ (gnus-parse-without-error
+ (while (and (or sequence allp)
+ (not (eobp)))
+ (setq number (read cur))
+ (when (not allp)
+ (while (and sequence
+ (< (car sequence) number))
+ (setq sequence (cdr sequence))))
+ (when (and (or allp
+ (and sequence
+ (eq number (car sequence))))
+ (progn
+ (setq sequence (cdr sequence))
+ (setq header (inline
+ (gnus-nov-parse-line
+ number dependencies force-new)))))
+ (push header headers))
+ (forward-line 1)))
;; A common bug in inn is that if you have posted an article and
;; then retrieves the active file, it will answer correctly --
;; the new article is included. However, a NOV entry for the
(progn
(while arts
(when (or (and undownloaded
- (eq gnus-undownloaded-mark
- (gnus-data-mark (car arts))))
+ (memq (car arts) gnus-newsgroup-undownloaded))
(gnus-data-unread-p (car arts)))
(setq result (car arts)
arts nil))
(marked (gnus-info-marks info))
(active (gnus-active group)))
(and info active
- (gnus-set-difference
- (gnus-sorted-complement
- (gnus-uncompress-range active)
- (gnus-list-of-unread-articles group))
- (append
- (gnus-uncompress-range (cdr (assq 'dormant marked)))
- (gnus-uncompress-range (cdr (assq 'tick marked))))))))
+ (gnus-list-range-difference
+ (gnus-list-range-difference
+ (gnus-sorted-complement
+ (gnus-uncompress-range active)
+ (gnus-list-of-unread-articles group))
+ (cdr (assq 'dormant marked)))
+ (cdr (assq 'tick marked))))))
;; Various summary commands
(defun gnus-summary-toggle-truncation (&optional arg)
"Toggle truncation of summary lines.
-With arg, turn line truncation on iff arg is positive."
+With arg, turn line truncation on if arg is positive."
(interactive "P")
(setq truncate-lines
(if (null arg) (not truncate-lines)
(> (prefix-numeric-value arg) 0)))
(redraw-display))
+(defun gnus-summary-find-uncancelled ()
+ "Return the number of an uncancelled article.
+The current article is considered, then following articles, then previous
+articles. If all articles are cancelled then return a dummy 0."
+ (let (found)
+ (dolist (rev '(nil t))
+ (unless found ; don't demand the reverse list if we don't need it
+ (let ((data (gnus-data-find-list
+ (gnus-summary-article-number) (gnus-data-list rev))))
+ (while (and data (not found))
+ (if (not (eq gnus-canceled-mark (gnus-data-mark (car data))))
+ (setq found (gnus-data-number (car data))))
+ (setq data (cdr data))))))
+ (or found 0)))
+
(defun gnus-summary-reselect-current-group (&optional all rescan)
"Exit and then reselect the current newsgroup.
The prefix argument ALL means to select all articles."
(interactive "P")
(when (gnus-ephemeral-group-p gnus-newsgroup-name)
(error "Ephemeral groups can't be reselected"))
- (let ((current-subject (gnus-summary-article-number))
+ (let ((current-subject (gnus-summary-find-uncancelled))
(group gnus-newsgroup-name))
(setq gnus-newsgroup-begin nil)
(gnus-summary-exit)
(when gnus-newsgroup-kill-headers
(setq gnus-newsgroup-killed
(gnus-compress-sequence
- (nconc
- (gnus-set-sorted-intersection
- (gnus-uncompress-range gnus-newsgroup-killed)
- (setq gnus-newsgroup-unselected
- (sort gnus-newsgroup-unselected '<)))
- (setq gnus-newsgroup-unreads
- (sort gnus-newsgroup-unreads '<)))
+ (gnus-sorted-union
+ (gnus-list-range-intersection
+ gnus-newsgroup-unselected gnus-newsgroup-killed)
+ gnus-newsgroup-unreads)
t)))
(unless (listp (cdr gnus-newsgroup-killed))
(setq gnus-newsgroup-killed (list gnus-newsgroup-killed)))
(set-buffer gnus-group-buffer)
(gnus-undo-force-boundary))
(gnus-update-read-articles
- group (append gnus-newsgroup-unreads gnus-newsgroup-unselected))
+ group (gnus-sorted-union
+ gnus-newsgroup-unreads gnus-newsgroup-unselected))
;; Set the current article marks.
(let ((gnus-newsgroup-scored
(if (and (not gnus-save-score)
(list
(when current-prefix-arg
(completing-read
- "Faq dir: " (and (listp gnus-group-faq-directory)
+ "FAQ dir: " (and (listp gnus-group-faq-directory)
(mapcar (lambda (file) (list file))
gnus-group-faq-directory))))))
(let (gnus-faq-buffer)
(let ((current-group gnus-newsgroup-name)
(current-buffer (current-buffer))
entered)
- ;; First we semi-exit this group to update Xrefs and all variables.
- ;; We can't do a real exit, because the window conf must remain
- ;; the same in case the user is prompted for info, and we don't
- ;; want the window conf to change before that...
- (gnus-summary-exit t)
(while (not entered)
;; Then we find what group we are supposed to enter.
(set-buffer gnus-group-buffer)
(let ((unreads (gnus-group-group-unread)))
(if (and (or (eq t unreads)
(and unreads (not (zerop unreads))))
- (gnus-summary-read-group
- target-group nil no-article
- (and (buffer-name current-buffer) current-buffer)
- nil backward))
+ (progn
+ ;; Now we semi-exit this group to update Xrefs
+ ;; and all variables. We can't do a real exit,
+ ;; because the window conf must remain the same
+ ;; in case the user is prompted for info, and we
+ ;; don't want the window conf to change before
+ ;; that...
+ (when (gnus-buffer-live-p current-buffer)
+ (set-buffer current-buffer)
+ (gnus-summary-exit t))
+ (gnus-summary-read-group
+ target-group nil no-article
+ (and (buffer-name current-buffer) current-buffer)
+ nil backward)))
(setq entered t)
(setq current-group target-group
target-group nil)))))))
(let ((data gnus-newsgroup-data))
(while (and data
(and (not (and undownloaded
- (eq gnus-undownloaded-mark
- (gnus-data-mark (car data)))))
+ (memq (car data) gnus-newsgroup-undownloaded)))
(if unseen
(or (not (memq
(gnus-data-number (car data))
"Go the subject line of ARTICLE.
If FORCE, also allow jumping to articles not currently shown."
(interactive "nArticle number: ")
+ (unless (numberp article)
+ (error "Article %s is not a number" article))
(let ((b (point))
(data (gnus-data-find article)))
;; We read in the article if we have to.
(with-current-buffer gnus-article-buffer
(if (not gnus-article-decoded-p) ;; a local variable
(mm-disable-multibyte))))
-;;; Hidden headers are not hidden text any more.
-;; (when (or all-headers gnus-show-all-headers)
-;; (gnus-article-show-all-headers))
(gnus-article-set-window-start
(cdr (assq article gnus-newsgroup-bookmarks)))
article)
-;; (when (or all-headers gnus-show-all-headers)
-;; (gnus-article-show-all-headers))
'old))))
(defun gnus-summary-force-verify-and-decrypt ()
(interactive)
(let ((mm-verify-option 'known)
- (mm-decrypt-option 'known))
+ (mm-decrypt-option 'known)
+ (gnus-buttonized-mime-types (append (list "multipart/signed"
+ "multipart/encrypted")
+ gnus-buttonized-mime-types)))
(gnus-summary-select-article nil 'force)))
(defun gnus-summary-set-current-mark (&optional current-mark)
(and gnus-auto-select-same
(gnus-summary-article-subject))))
-(defun gnus-summary-next-page (&optional lines circular)
+(defun gnus-summary-next-page (&optional lines circular stop)
"Show next page of the selected article.
If at the end of the current article, select the next article.
LINES says how many lines should be scrolled up.
If CIRCULAR is non-nil, go to the start of the article instead of
selecting the next article when reaching the end of the current
-article."
+article.
+
+If STOP is non-nil, just stop when reaching the end of the message."
(interactive "P")
(setq gnus-summary-buffer (current-buffer))
(gnus-set-global-variables)
(gnus-eval-in-buffer-window gnus-article-buffer
(setq endp (gnus-article-next-page lines)))
(when endp
- (cond (circular
+ (cond (stop
+ (gnus-message 3 "End of message"))
+ (circular
(gnus-summary-beginning-of-article))
(lines
(gnus-message 3 "End of message"))
(gnus-summary-first-subject t t t))
(gnus-summary-position-point)))
+(defun gnus-summary-first-unseen-or-unread-subject ()
+ "Place the point on the subject line of the first unseen article.
+Return nil if there are no unseen articles."
+ (interactive)
+ (prog1
+ (unless (when (gnus-summary-first-subject t t t)
+ (gnus-summary-show-thread)
+ (gnus-summary-first-subject t t t))
+ (when (gnus-summary-first-subject t)
+ (gnus-summary-show-thread)
+ (gnus-summary-first-subject t)))
+ (gnus-summary-position-point)))
+
(defun gnus-summary-first-article ()
"Select the first article.
Return nil if there are no articles."
days)
(while (not days-got)
(setq days (if younger
- (read-string "Limit to articles within (in days): ")
- (read-string "Limit to articles older than (in days): ")))
+ (read-string "Limit to articles younger than (in days, older when negative): ")
+ (read-string
+ "Limit to articles older than (in days, younger when negative): ")))
(when (> (length days) 0)
(setq days (read days)))
(if (numberp days)
- (progn
+ (progn
(setq days-got t)
(if (< days 0)
- (progn
+ (progn
(setq younger (not younger))
(setq days (* days -1)))))
(message "Please enter a number.")
(interactive
(let ((header
(intern
- (gnus-completing-read
+ (gnus-completing-read-with-default
(symbol-name (car gnus-extra-headers))
(if current-prefix-arg
"Exclude extra header:"
;; Concat all the marks that say that an article is read and have
;; those removed.
(list gnus-del-mark gnus-read-mark gnus-ancient-mark
- gnus-killed-mark gnus-kill-file-mark
+ gnus-killed-mark gnus-spam-mark gnus-kill-file-mark
gnus-low-score-mark gnus-expirable-mark
gnus-canceled-mark gnus-catchup-mark gnus-sparse-mark
gnus-duplicate-mark gnus-souped-mark)
(defalias 'gnus-summary-delete-marked-with 'gnus-summary-limit-exclude-marks)
(make-obsolete 'gnus-summary-delete-marked-with
- 'gnus-summary-limit-exlude-marks)
+ 'gnus-summary-limit-exclude-marks)
(defun gnus-summary-limit-exclude-marks (marks &optional reverse)
"Exclude articles that are marked with MARKS (e.g. \"DK\").
(gnus-summary-limit articles)
(gnus-summary-position-point))))
+(defun gnus-summary-limit-to-unseen ()
+ "Limit to unseen articles."
+ (interactive)
+ (prog1
+ (gnus-summary-limit gnus-newsgroup-unseen)
+ (gnus-summary-position-point)))
+
(defun gnus-summary-limit-include-thread (id)
"Display all the hidden articles that is in the thread with ID in it.
When called interactively, ID is the Message-ID of the current
"Mark all unread excluded articles as read.
If ALL, mark even excluded ticked and dormants as read."
(interactive "P")
- (let ((articles (gnus-sorted-complement
+ (setq gnus-newsgroup-limit (sort gnus-newsgroup-limit '<))
+ (let ((articles (gnus-sorted-ndifference
(sort
(mapcar (lambda (h) (mail-header-number h))
gnus-newsgroup-headers)
'<)
- (sort gnus-newsgroup-limit '<)))
+ gnus-newsgroup-limit))
article)
(setq gnus-newsgroup-unreads
- (gnus-intersection gnus-newsgroup-unreads gnus-newsgroup-limit))
+ (gnus-sorted-intersection gnus-newsgroup-unreads
+ gnus-newsgroup-limit))
(if all
(setq gnus-newsgroup-dormant nil
gnus-newsgroup-marked nil
;; will really go down to a leaf article first, before slowly
;; working its way up towards the root.
(when thread
- (let ((children
+ (let* ((max-lisp-eval-depth 5000)
+ (children
(if (cdr thread)
(apply '+ (mapcar 'gnus-summary-limit-children
(cdr thread)))
(gnus-message 3 "Couldn't fetch article %s" message-id)))))))
(defun gnus-refer-article-methods ()
- "Return a list of referrable methods."
+ "Return a list of referable methods."
(cond
;; No method, so we default to current and native.
((null gnus-refer-article-method)
(set-buffer gnus-original-article-buffer)
;; Have the digest group inherit the main mail address of
;; the parent article.
- (when (setq to-address (or (message-fetch-field "reply-to")
- (message-fetch-field "from")))
+ (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
;; We don't want to change current point nor window configuration.
(save-excursion
(save-window-excursion
- (gnus-message 6 "Executing %s..." (key-description command))
-;; We'd like to execute COMMAND interactively so as to give arguments.
- (gnus-execute header regexp
- `(call-interactively ',(key-binding command))
- backward)
- (gnus-message 6 "Executing %s...done" (key-description command)))))
+ (let (gnus-visual
+ gnus-treat-strip-trailing-blank-lines
+ gnus-treat-strip-leading-blank-lines
+ gnus-treat-strip-multiple-blank-lines
+ gnus-treat-hide-boring-headers
+ gnus-treat-fold-newsgroups
+ gnus-article-prepare-hook)
+ (gnus-message 6 "Executing %s..." (key-description command))
+ ;; We'd like to execute COMMAND interactively so as to give arguments.
+ (gnus-execute header regexp
+ `(call-interactively ',(key-binding command))
+ backward)
+ (gnus-message 6 "Executing %s...done" (key-description command))))))
(defun gnus-summary-beginning-of-article ()
"Scroll the article back to the beginning."
(copy-to-buffer buffer (point-min) (point-max))
(set-buffer buffer)
(gnus-article-delete-invisible-text)
+ (gnus-remove-text-with-property 'gnus-decoration)
(when (gnus-visual-p 'article-highlight 'highlight)
;; Copy-to-buffer doesn't copy overlay. So redo
;; highlight.
defined in `gnus-summary-show-article-charset-alist', or the charset
input.
If ARG (the prefix) is non-nil and not a number, show the raw article
-without any article massaging functions being run. Normally, the key strokes
+without any article massaging functions being run. Normally, the key strokes
are `C-u g'."
(interactive "P")
(cond
If ARG is a positive number, show the entire header.
If ARG is a negative number, hide the unwanted header lines."
(interactive "P")
- (save-excursion
- (set-buffer gnus-article-buffer)
- (save-restriction
+ (let ((window (and (gnus-buffer-live-p gnus-article-buffer)
+ (get-buffer-window gnus-article-buffer t))))
+ (with-current-buffer gnus-article-buffer
+ (widen)
+ (article-narrow-to-head)
(let* ((buffer-read-only nil)
(inhibit-point-motion-hooks t)
- hidden e)
- (setq hidden
- (if (numberp arg)
- (>= arg 0)
- (save-restriction
- (article-narrow-to-head)
- (gnus-article-hidden-text-p 'headers))))
- (goto-char (point-min))
- (when (search-forward "\n\n" nil t)
- (delete-region (point-min) (1- (point))))
- (goto-char (point-min))
- (save-excursion
- (set-buffer gnus-original-article-buffer)
- (goto-char (point-min))
- (setq e (1- (or (search-forward "\n\n" nil t) (point-max)))))
- (insert-buffer-substring gnus-original-article-buffer 1 e)
- (save-restriction
- (narrow-to-region (point-min) (point))
- (article-decode-encoded-words)
- (if hidden
- (let ((gnus-treat-hide-headers nil)
- (gnus-treat-hide-boring-headers nil))
- (gnus-delete-wash-type 'headers)
- (gnus-treat-article 'head))
- (gnus-treat-article 'head)))
+ (hidden (if (numberp arg)
+ (>= arg 0)
+ (gnus-article-hidden-text-p 'headers)))
+ s e)
+ (delete-region (point-min) (point-max))
+ (with-current-buffer gnus-original-article-buffer
+ (goto-char (setq s (point-min)))
+ (setq e (if (search-forward "\n\n" nil t)
+ (1- (point))
+ (point-max))))
+ (insert-buffer-substring gnus-original-article-buffer s e)
+ (article-decode-encoded-words)
+ (if hidden
+ (let ((gnus-treat-hide-headers nil)
+ (gnus-treat-hide-boring-headers nil))
+ (gnus-delete-wash-type 'headers)
+ (gnus-treat-article 'head))
+ (gnus-treat-article 'head))
+ (widen)
+ (if window
+ (set-window-start window (goto-char (point-min))))
+ (setq gnus-page-broken
+ (when gnus-break-pages
+ (gnus-narrow-to-page)
+ t))
(gnus-set-mode-line 'article)))))
(defun gnus-summary-show-all-headers ()
(message-caesar-buffer-body arg)
(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")
+ (gnus-summary-select-article)
+ (let ((mail-header-separator ""))
+ (gnus-eval-in-buffer-window gnus-article-buffer
+ (save-excursion
+ (save-restriction
+ (widen)
+ (let ((pos (window-start))
+ buffer-read-only)
+ (goto-char (point-min))
+ (when (message-goto-body)
+ (gnus-narrow-to-body))
+ (goto-char (point-min))
+ (while (re-search-forward "·" (point-max) t)
+ (replace-match "."))
+ (unmorse-region (point-min) (point-max))
+ (widen)
+ (set-window-start (get-buffer-window (current-buffer)) pos)))))))
+
(defun gnus-summary-stop-page-breaking ()
"Stop page breaking in the current article."
(interactive)
If SELECT-METHOD is non-nil, do not move to a specific newsgroup, but
re-spool using this method.
+When called interactively with TO-NEWSGROUP being nil, the value of
+the variable `gnus-move-split-methods' is used for finding a default
+for the target newsgroup.
+
For this function to work, both the current newsgroup and the
newsgroup that you want to move to have to support the `request-move'
and `request-accept' functions.
art-group to-method new-xref article to-groups)
(unless (assq action names)
(error "Unknown action %s" action))
- ;; We have to select an article to give
- ;; `gnus-read-move-group-name' an opportunity to suggest an
- ;; appropriate default.
- (unless (gnus-buffer-live-p gnus-original-article-buffer)
- (let ((gnus-display-mime-function nil)
- (gnus-article-prepare-hook nil))
- (gnus-summary-select-article nil nil nil (car articles))))
;; Read the newsgroup name.
(when (and (not to-newsgroup)
(not select-method))
+ (if (and gnus-move-split-methods
+ (not
+ (and (memq gnus-current-article articles)
+ (gnus-buffer-live-p gnus-original-article-buffer))))
+ ;; When `gnus-move-split-methods' is non-nil, we have to
+ ;; select an article to give `gnus-read-move-group-name' an
+ ;; opportunity to suggest an appropriate default. However,
+ ;; we needn't render or mark the article.
+ (let ((gnus-display-mime-function nil)
+ (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))
to-group (cdar marks) (list to-article) info)))
(setq marks (cdr marks)))
- (gnus-request-set-mark to-group (list (list (list to-article)
- 'add
- to-marks))))
+ (gnus-request-set-mark
+ to-group (list (list (list to-article) 'add to-marks))))
(gnus-dribble-enter
(concat "(gnus-group-set-info '"
(defun gnus-summary-copy-article (&optional n to-newsgroup select-method)
"Move the current article to a different newsgroup.
If TO-NEWSGROUP is string, do not prompt for a newsgroup to move to.
+When called interactively, if TO-NEWSGROUP is nil, use the value of
+the variable `gnus-move-split-methods' for finding a default target
+newsgroup.
If SELECT-METHOD is non-nil, do not move to a specific newsgroup, but
re-spool using this method."
(interactive "P")
:type 'symbol
:group 'gnus-summary-mail)
+(defcustom gnus-summary-display-while-building nil
+ "If not-nil, show and update the summary buffer as it's being built.
+If the value is t, update the buffer after every line is inserted. If
+the value is an integer (N), update the display every N lines."
+ :group 'gnus-thread
+ :type '(choice (const :tag "off" nil)
+ number
+ (const :tag "frequently" t)))
+
(defun gnus-summary-respool-article (&optional n method)
"Respool the current article.
The article will be squeezed through the mail spooling process again,
(car (gnus-find-method-for-group
gnus-newsgroup-name)))))
(method
- (gnus-completing-read
+ (gnus-completing-read-with-default
methname "What backend do you want to use when respooling?"
methods nil t nil 'gnus-mail-method-history))
ms)
;; really expired articles as nonexistent.
(unless (eq es expirable) ;If nothing was expired, we don't mark.
(let ((gnus-use-cache nil))
- (while expirable
- (unless (memq (car expirable) es)
- (when (gnus-data-find (car expirable))
- (gnus-summary-mark-article
- (car expirable) gnus-canceled-mark)))
- (setq expirable (cdr expirable))))))
+ (dolist (article expirable)
+ (when (and (not (memq article es))
+ (gnus-data-find article))
+ (gnus-summary-mark-article article gnus-canceled-mark))))))
(gnus-message 6 "Expiring articles...done")))))
(defun gnus-summary-expire-articles-now ()
(error "Couldn't open server"))
;; Compute the list of articles to delete.
(let ((articles (sort (copy-sequence (gnus-summary-work-articles n)) '<))
+ (nnmail-expiry-target 'delete)
not-deleted)
(if (and gnus-novice-user
(not (gnus-yes-or-no-p
(setq gnus-article-mime-handles nil))))))
(t
(setq force t)))
- (when (and raw (not force) (equal gnus-newsgroup-name "nndraft:drafts"))
- (error "Can't edit the raw article in group nndraft:drafts"))
+ (when (and raw (not force)
+ (member gnus-newsgroup-name '("nndraft:delayed"
+ "nndraft:drafts"
+ "nndraft:queue")))
+ (error "Can't edit the raw article in group %s"
+ gnus-newsgroup-name))
(save-excursion
(set-buffer gnus-summary-buffer)
(let ((mail-parse-charset gnus-newsgroup-charset)
(when (and (not raw) (gnus-buffer-live-p gnus-article-buffer))
(with-current-buffer gnus-article-buffer
(mm-enable-multibyte)))
- (if (equal gnus-newsgroup-name "nndraft:drafts")
+ (if (member gnus-newsgroup-name '("nndraft:delayed" "nndraft:drafts"))
(setq raw t))
(gnus-article-edit-article
(if raw 'ignore
(insert ".\n")
(let ((nntp-server-buffer (current-buffer)))
(setq header (car (gnus-get-newsgroup-headers
- (save-excursion
- (set-buffer gnus-summary-buffer)
- gnus-newsgroup-dependencies)
- t))))
+ nil t))))
(save-excursion
(set-buffer gnus-summary-buffer)
(gnus-data-set-header
(interactive "p")
(gnus-summary-mark-forward n gnus-expirable-mark))
+(defun gnus-summary-mark-as-spam (n)
+ "Mark N articles forward as spam.
+If N is negative, mark backward instead. The difference between N and
+the actual number of articles marked is returned."
+ (interactive "p")
+ (gnus-summary-mark-forward n gnus-spam-mark))
+
(defun gnus-summary-mark-article-as-replied (article)
"Mark ARTICLE as replied to and update the summary line.
ARTICLE can also be a list of articles."
If N is negative, mark backwards instead. Mark with MARK, ?r by default.
The difference between N and the actual number of articles marked is
returned.
-Iff NO-EXPIRE, auto-expiry will be inhibited."
+If NO-EXPIRE, auto-expiry will be inhibited."
(interactive "p")
(gnus-summary-show-thread)
(let ((backward (< n 0))
(let ((article (gnus-summary-article-number)))
(setq gnus-newsgroup-unreads (delq article gnus-newsgroup-unreads))
(setq gnus-newsgroup-marked (delq article gnus-newsgroup-marked))
+ (setq gnus-newsgroup-spam-marked (delq article gnus-newsgroup-spam-marked))
(setq gnus-newsgroup-dormant (delq article gnus-newsgroup-dormant))
(push (cons article mark) gnus-newsgroup-reads)
;; Possibly remove from cache, if that is used.
(gnus-error 1 "Can't mark negative article numbers")
nil)
(setq gnus-newsgroup-marked (delq article gnus-newsgroup-marked))
+ (setq gnus-newsgroup-spam-marked
+ (delq article gnus-newsgroup-spam-marked))
(setq gnus-newsgroup-dormant (delq article gnus-newsgroup-dormant))
(setq gnus-newsgroup-expirable (delq article gnus-newsgroup-expirable))
(setq gnus-newsgroup-reads (delq article gnus-newsgroup-reads))
(cond ((= mark gnus-ticked-mark)
- (push article gnus-newsgroup-marked))
+ (setq gnus-newsgroup-marked
+ (gnus-add-to-sorted-list gnus-newsgroup-marked
+ article)))
+ ((= mark gnus-spam-mark)
+ (setq gnus-newsgroup-spam-marked
+ (gnus-add-to-sorted-list gnus-newsgroup-spam-marked
+ article)))
((= mark gnus-dormant-mark)
- (push article gnus-newsgroup-dormant))
+ (setq gnus-newsgroup-dormant
+ (gnus-add-to-sorted-list gnus-newsgroup-dormant
+ article)))
(t
- (push article gnus-newsgroup-unreads)))
+ (setq gnus-newsgroup-unreads
+ (gnus-add-to-sorted-list gnus-newsgroup-unreads
+ article))))
(gnus-pull article gnus-newsgroup-reads)
;; See whether the article is to be put in the cache.
If MARK is nil, then the default character `?r' is used.
If ARTICLE is nil, then the article on the current line will be
marked.
-Iff NO-EXPIRE, auto-expiry will be inhibited."
+If NO-EXPIRE, auto-expiry will be inhibited."
;; The mark might be a string.
(when (stringp mark)
(setq mark (aref mark 0)))
(error "No article on current line"))
(if (not (if (or (= mark gnus-unread-mark)
(= mark gnus-ticked-mark)
+ (= mark gnus-spam-mark)
(= mark gnus-dormant-mark))
(gnus-mark-article-as-unread article mark)
(gnus-mark-article-as-read article mark)))
(gnus-run-hooks 'gnus-summary-update-hook))
t)
+(defun gnus-summary-update-download-mark (article)
+ "Update the secondary (read, process, cache) mark."
+ (gnus-summary-update-mark
+ (cond ((memq article gnus-newsgroup-undownloaded)
+ gnus-undownloaded-mark)
+ (gnus-newsgroup-agentized
+ gnus-downloaded-mark)
+ (t
+ gnus-no-mark))
+ 'download)
+ (gnus-summary-update-line t)
+ t)
+
(defun gnus-summary-update-mark (mark type)
(let ((forward (cdr (assq type gnus-summary-mark-positions)))
(buffer-read-only nil))
"Enter ARTICLE in the pertinent lists and remove it from others."
;; Make the article expirable.
(let ((mark (or mark gnus-del-mark)))
- (if (= mark gnus-expirable-mark)
- (push article gnus-newsgroup-expirable)
- (setq gnus-newsgroup-expirable (delq article gnus-newsgroup-expirable)))
+ (setq gnus-newsgroup-expirable
+ (if (= mark gnus-expirable-mark)
+ (gnus-add-to-sorted-list gnus-newsgroup-expirable article)
+ (delq article gnus-newsgroup-expirable)))
;; Remove from unread and marked lists.
(setq gnus-newsgroup-unreads (delq article gnus-newsgroup-unreads))
(setq gnus-newsgroup-marked (delq article gnus-newsgroup-marked))
+ (setq gnus-newsgroup-spam-marked (delq article gnus-newsgroup-spam-marked))
(setq gnus-newsgroup-dormant (delq article gnus-newsgroup-dormant))
(push (cons article mark) gnus-newsgroup-reads)
;; Possibly remove from cache, if that is used.
(gnus-error 1 "Can't mark negative article numbers")
nil)
(setq gnus-newsgroup-marked (delq article gnus-newsgroup-marked)
+ gnus-newsgroup-spam-marked (delq article gnus-newsgroup-spam-marked)
gnus-newsgroup-dormant (delq article gnus-newsgroup-dormant)
gnus-newsgroup-expirable (delq article gnus-newsgroup-expirable)
gnus-newsgroup-unreads (delq article gnus-newsgroup-unreads))
(gnus-dup-unsuppress-article article))
(cond ((= mark gnus-ticked-mark)
- (push article gnus-newsgroup-marked))
+ (setq gnus-newsgroup-marked
+ (gnus-add-to-sorted-list gnus-newsgroup-marked article)))
+ ((= mark gnus-spam-mark)
+ (setq gnus-newsgroup-spam-marked
+ (gnus-add-to-sorted-list gnus-newsgroup-spam-marked
+ article)))
((= mark gnus-dormant-mark)
- (push article gnus-newsgroup-dormant))
+ (setq gnus-newsgroup-dormant
+ (gnus-add-to-sorted-list gnus-newsgroup-dormant article)))
(t
- (push article gnus-newsgroup-unreads)))
+ (setq gnus-newsgroup-unreads
+ (gnus-add-to-sorted-list gnus-newsgroup-unreads article))))
(gnus-pull article gnus-newsgroup-reads)
t)))
(progn
(when all
(setq gnus-newsgroup-marked nil
+ gnus-newsgroup-spam-marked nil
gnus-newsgroup-dormant nil))
(setq gnus-newsgroup-unreads gnus-newsgroup-downloadable))
;; We actually mark all articles as canceled, which we
(gnus-summary-position-point))
(defun gnus-summary-catchup-all (&optional quietly)
- "Mark all articles in this newsgroup as read."
+ "Mark all articles in this newsgroup as read.
+This command is dangerous. Normally, you want \\[gnus-summary-catchup]
+instead, which marks only unread articles as read."
(interactive "P")
(gnus-summary-catchup t quietly))
(gnus-summary-exit))))
(defun gnus-summary-catchup-all-and-exit (&optional quietly)
- "Mark all articles in this newsgroup as read, and then exit."
+ "Mark all articles in this newsgroup as read, and then exit.
+This command is dangerous. Normally, you want \\[gnus-summary-catchup-and-exit]
+instead, which marks only unread articles as read."
(interactive "P")
(gnus-summary-catchup-and-exit t quietly))
(interactive "P")
(gnus-summary-sort 'number reverse))
+(defun gnus-summary-sort-by-random (&optional reverse)
+ "Randomize the order in the summary buffer.
+Argument REVERSE means to randomize in reverse order."
+ (interactive "P")
+ (gnus-summary-sort 'random reverse))
+
(defun gnus-summary-sort-by-author (&optional reverse)
"Sort the summary buffer by author name alphabetically.
If `case-fold-search' is non-nil, case of letters is ignored.
(gnus-set-mode-line 'summary)
n))
-(defun gnus-summary-pipe-output (&optional arg)
+(defun gnus-summary-pipe-output (&optional arg headers)
"Pipe the current article to a subprocess.
If N is a positive number, pipe the N next articles.
If N is a negative number, pipe the N previous articles.
If N is nil and any articles have been marked with the process mark,
-pipe those articles instead."
- (interactive "P")
+pipe those articles instead.
+If HEADERS (the symbolic prefix), include the headers, too."
+ (interactive (gnus-interactive "P\ny"))
(require 'gnus-art)
- (let ((gnus-default-article-saver 'gnus-summary-save-in-pipe))
+ (let ((gnus-default-article-saver 'gnus-summary-save-in-pipe)
+ (gnus-save-all-headers (or headers gnus-save-all-headers)))
(gnus-summary-save-article arg t))
(let ((buffer (get-buffer "*Shell Command Output*")))
- (if (and buffer
- (with-current-buffer buffer (> (point-max) (point-min))))
- (gnus-configure-windows 'pipe))))
+ (when (and buffer
+ (not (zerop (buffer-size buffer))))
+ (gnus-configure-windows 'pipe))))
(defun gnus-summary-save-article-mail (&optional arg)
"Append the current article to an mail file.
(to-newsgroup
(cond
((null split-name)
- (gnus-completing-read default prom
- gnus-active-hashtb
- 'gnus-valid-move-group-p
- nil prefix
- 'gnus-group-history))
+ (gnus-completing-read-with-default
+ default prom
+ gnus-active-hashtb
+ 'gnus-valid-move-group-p
+ nil prefix
+ 'gnus-group-history))
((= 1 (length split-name))
- (gnus-completing-read (car split-name) prom
- gnus-active-hashtb
- 'gnus-valid-move-group-p
- nil nil
- 'gnus-group-history))
+ (gnus-completing-read-with-default
+ (car split-name) prom
+ gnus-active-hashtb
+ 'gnus-valid-move-group-p
+ nil nil
+ 'gnus-group-history))
(t
- (gnus-completing-read nil prom
- (mapcar (lambda (el) (list el))
- (nreverse split-name))
- nil nil nil
- 'gnus-group-history))))
+ (gnus-completing-read-with-default
+ nil prom
+ (mapcar (lambda (el) (list el))
+ (nreverse split-name))
+ nil nil nil
+ 'gnus-group-history))))
(to-method (gnus-server-to-method (gnus-group-method to-newsgroup))))
(when to-newsgroup
(if (or (string= to-newsgroup "")
(save-excursion
(set-buffer gnus-article-buffer)
(let ((handles (or gnus-article-mime-handles
- (mm-dissect-buffer) (mm-uu-dissect))))
+ (mm-dissect-buffer nil gnus-article-loose-mime)
+ (mm-uu-dissect))))
(when handles
(gnus-summary-save-parts-1 type dir handles reverse)
(unless gnus-article-mime-handles ;; Don't destroy this case.
(gnus-data-enter
after-article gnus-reffed-article-number
gnus-unread-mark b (car pslist) 0 (- e b))
- (push gnus-reffed-article-number gnus-newsgroup-unreads)
+ (setq gnus-newsgroup-unreads
+ (gnus-add-to-sorted-list gnus-newsgroup-unreads
+ gnus-reffed-article-number))
(setq gnus-reffed-article-number (1- gnus-reffed-article-number))
(setq pslist (cdr pslist)))))))
(setq gnus-newsgroup-selected-overlay (gnus-make-overlay from to))
'face gnus-summary-selected-face))))))
-;; New implementation by Christian Limpach <Christian.Limpach@nice.ch>.
+(defvar gnus-summary-highlight-line-cached nil)
+(defvar gnus-summary-highlight-line-trigger nil)
+
+(defun gnus-summary-highlight-line-0 ()
+ (if (and (eq gnus-summary-highlight-line-trigger
+ gnus-summary-highlight)
+ gnus-summary-highlight-line-cached)
+ gnus-summary-highlight-line-cached
+ (setq gnus-summary-highlight-line-trigger gnus-summary-highlight
+ gnus-summary-highlight-line-cached
+ (let* ((cond (list 'cond))
+ (c cond)
+ (list gnus-summary-highlight))
+ (while list
+ (setcdr c (cons (list (caar list) (list 'quote (cdar list))) nil))
+ (setq c (cdr c)
+ list (cdr list)))
+ (gnus-byte-compile (list 'lambda nil cond))))))
+
(defun gnus-summary-highlight-line ()
"Highlight current line according to `gnus-summary-highlight'."
- (let* ((list gnus-summary-highlight)
- (p (point))
- (end (progn (end-of-line) (point)))
- ;; now find out where the line starts and leave point there.
- (beg (progn (beginning-of-line) (point)))
- (article (gnus-summary-article-number))
- (score (or (cdr (assq (or article gnus-current-article)
+ (let* ((beg (gnus-point-at-bol))
+ (article (or (gnus-summary-article-number) gnus-current-article))
+ (score (or (cdr (assq article
gnus-newsgroup-scored))
gnus-summary-default-score 0))
(mark (or (gnus-summary-article-mark) gnus-unread-mark))
- (inhibit-read-only t))
- ;; Eval the cars of the lists until we find a match.
- (let ((default gnus-summary-default-score)
- (default-high gnus-summary-default-high-score)
- (default-low gnus-summary-default-low-score))
- (while (and list
- (not (eval (caar list))))
- (setq list (cdr list))))
- (let ((face (cdar list)))
+ (inhibit-read-only t)
+ (default gnus-summary-default-score)
+ (default-high gnus-summary-default-high-score)
+ (default-low gnus-summary-default-low-score)
+ (uncached (memq article gnus-newsgroup-undownloaded))
+ (downloaded (not uncached)))
+ (let ((face (funcall (gnus-summary-highlight-line-0))))
(unless (eq face (get-text-property beg 'face))
(gnus-put-text-property-excluding-characters-with-faces
- beg end 'face
+ beg (gnus-point-at-eol) 'face
(setq face (if (boundp face) (symbol-value face) face)))
(when gnus-summary-highlight-line-function
- (funcall gnus-summary-highlight-line-function article face))))
- (goto-char p)))
+ (funcall gnus-summary-highlight-line-function article face))))))
(defun gnus-update-read-articles (group unread &optional compute)
- "Update the list of read articles in GROUP."
+ "Update the list of read articles in GROUP.
+UNREAD is a sorted list."
(let* ((active (or gnus-newsgroup-active (gnus-active group)))
(entry (gnus-gethash group gnus-newsrc-hashtb))
(info (nth 2 entry))
(prev 1)
- (unread (sort (copy-sequence unread) '<))
read)
(if (or (not info) (not active))
;; There is no info on this group if it was, in fact,
(defun gnus-summary-setup-default-charset ()
"Setup newsgroup default charset."
- (if (equal gnus-newsgroup-name "nndraft:drafts")
+ (if (member gnus-newsgroup-name '("nndraft:delayed" "nndraft:drafts"))
(setq gnus-newsgroup-charset nil)
(let* ((ignored-charsets
(or gnus-newsgroup-ephemeral-ignored-charsets
(defun gnus-summary-insert-articles (articles)
(when (setq articles
- (gnus-set-difference articles
- (mapcar (lambda (h) (mail-header-number h))
- gnus-newsgroup-headers)))
+ (gnus-sorted-difference articles
+ (mapcar (lambda (h)
+ (mail-header-number h))
+ gnus-newsgroup-headers)))
(setq gnus-newsgroup-headers
(merge 'list
gnus-newsgroup-headers
If ALL is a number, fetch this number of articles."
(interactive "P")
(prog1
- (let ((old (mapcar 'car gnus-newsgroup-data))
- (i (car gnus-newsgroup-active))
+ (let ((old (sort (mapcar 'car gnus-newsgroup-data) '<))
older len)
- (while (<= i (cdr gnus-newsgroup-active))
- (or (memq i old) (push i older))
- (incf i))
- (setq len (length older))
+ (setq older
+ ;; Some nntp servers lie about their active range. When
+ ;; this happens, the active range can be in the millions.
+ ;; Use a compressed range to avoid creating a huge list.
+ (gnus-range-difference (list gnus-newsgroup-active) old))
+ (setq len (gnus-range-length older))
(cond
((null older) nil)
((numberp all)
(if (< all len)
- (setq older (subseq older 0 all))))
- (all nil)
+ (let ((older-range (nreverse older)))
+ (setq older nil)
+
+ (while (> all 0)
+ (let* ((r (pop older-range))
+ (min (if (numberp r) r (car r)))
+ (max (if (numberp r) r (cdr r))))
+ (while (and (<= min max)
+ (> all 0))
+ (push max older)
+ (setq all (1- all)
+ max (1- max))))))
+ (setq older (gnus-uncompress-range older))))
+ (all
+ (setq older (gnus-uncompress-range older)))
(t
- (if (and (numberp gnus-large-newsgroup)
+ (when (and (numberp gnus-large-newsgroup)
(> len gnus-large-newsgroup))
- (let ((input
- (read-string
- (format
- "How many articles from %s (default %d): "
- (gnus-limit-string
- (gnus-group-decoded-name gnus-newsgroup-name) 35)
- len))))
+ (let* ((cursor-in-echo-area nil)
+ (initial (gnus-parameter-large-newsgroup-initial
+ gnus-newsgroup-name))
+ (input
+ (read-string
+ (format
+ "How many articles from %s (%s %d): "
+ (gnus-limit-string
+ (gnus-group-decoded-name gnus-newsgroup-name) 35)
+ (if initial "max" "default")
+ len)
+ (if initial
+ (cons (number-to-string initial)
+ 0)))))
(unless (string-match "^[ \t]*$" input)
(setq all (string-to-number input))
(if (< all len)
- (setq older (subseq older 0 all))))))))
+ (let ((older-range (nreverse older)))
+ (setq older nil)
+
+ (while (> all 0)
+ (let* ((r (pop older-range))
+ (min (if (numberp r) r (car r)))
+ (max (if (numberp r) r (cdr r))))
+ (while (and (<= min max)
+ (> all 0))
+ (push max older)
+ (setq all (1- all)
+ max (1- max))))))))))
+ (setq older (gnus-uncompress-range older))))
(if (not older)
(message "No old news.")
- (let ((gnus-fetch-old-headers t))
- (gnus-summary-insert-articles older))
- (gnus-summary-limit (gnus-union older old))))
+ (gnus-summary-insert-articles older)
+ (gnus-summary-limit (gnus-sorted-nunion old older))))
(gnus-summary-position-point)))
(defun gnus-summary-insert-new-articles ()
"Insert all new articles in this group."
(interactive)
(prog1
- (let ((old (mapcar 'car gnus-newsgroup-data))
+ (let ((old (sort (mapcar 'car gnus-newsgroup-data) '<))
(old-active gnus-newsgroup-active)
(nnmail-fetched-sources (list t))
i new)
(setq gnus-newsgroup-active
(gnus-activate-group gnus-newsgroup-name 'scan))
- (setq i (1+ (cdr old-active)))
- (while (<= i (cdr gnus-newsgroup-active))
+ (setq i (cdr gnus-newsgroup-active))
+ (while (> i (cdr old-active))
(push i new)
- (incf i))
+ (decf i))
(if (not new)
(message "No gnus is bad news.")
- (setq new (nreverse new))
(gnus-summary-insert-articles new)
(setq gnus-newsgroup-unreads
- (append gnus-newsgroup-unreads new))
- (gnus-summary-limit (gnus-union old new))))
+ (gnus-sorted-nunion gnus-newsgroup-unreads new))
+ (gnus-summary-limit (gnus-sorted-nunion old new))))
(gnus-summary-position-point)))
(gnus-summary-make-all-marking-commands)