;;; Code:
(eval-when-compile (require 'cl))
+(eval-when-compile (require 'gnus-clfns))
(require 'gnus)
(require 'gnus-group)
:type 'character)
(defcustom gnus-souped-mark ?F
- "*Mark used for killed articles."
+ "*Mark used for souped articles."
:group 'gnus-summary-marks
:type 'character)
:group 'gnus-summary-marks
:type 'character)
+(defcustom gnus-forwarded-mark ?O
+ "*Mark used for articles that have been forwarded."
+ :group 'gnus-summary-marks
+ :type 'character)
+
(defcustom gnus-cached-mark ?*
"*Mark used for articles that are in the cache."
:group 'gnus-summary-marks
(defcustom gnus-article-sort-functions '(gnus-article-sort-by-number)
"*List of functions used for sorting articles in the summary buffer.
-This variable is only used when not using a threaded display."
+
+Each function takes two articles and returns non-nil if the first
+article should be sorted before the other. If you use more than one
+function, the primary sort function should be the last. You should
+probably always include `gnus-article-sort-by-number' in the list of
+sorting functions -- preferably first. Also note that sorting by date
+is often much slower than sorting by number, and the sorting order is
+very similar. (Sorting by date means sorting by the time the message
+was sent, sorting by number means sorting by arrival time.)
+
+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'.
+
+When threading is turned on, the variable `gnus-thread-sort-functions'
+controls how articles are sorted."
:group 'gnus-summary-sort
:type '(repeat (choice (function-item gnus-article-sort-by-number)
(function-item gnus-article-sort-by-author)
"*List of functions used for sorting threads in the summary buffer.
By default, threads are sorted by article number.
-Each function takes two threads and return non-nil if the first thread
-should be sorted before the other. If you use more than one function,
-the primary sort function should be the last. You should probably
-always include `gnus-thread-sort-by-number' in the list of sorting
-functions -- preferably first.
+Each function takes two threads and returns non-nil if the first
+thread should be sorted before the other. If you use more than one
+function, the primary sort function should be the last. You should
+probably always include `gnus-thread-sort-by-number' in the list of
+sorting functions -- preferably first. Also note that sorting by date
+is often much slower than sorting by number, and the sorting order is
+very similar. (Sorting by date means sorting by the time the message
+was sent, sorting by number means sorting by arrival time.)
Ready-made functions include `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' and
-`gnus-thread-sort-by-total-score' (see `gnus-thread-score-function')."
+`gnus-thread-sort-by-total-score' (see `gnus-thread-score-function').
+
+When threading is turned off, the variable
+`gnus-article-sort-functions' controls how articles are sorted."
:group 'gnus-summary-sort
:type '(repeat (choice (function-item gnus-thread-sort-by-number)
(function-item gnus-thread-sort-by-author)
:group 'gnus-summary
:type 'regexp)
-(defcustom gnus-group-charset-alist
- '(("^hk\\>\\|^tw\\>\\|\\<big5\\>" cn-big5)
- ("^cn\\>\\|\\<chinese\\>" cn-gb-2312)
- ("^fj\\>\\|^japan\\>" iso-2022-jp-2)
- ("^tnn\\>\\|^pin\\>\\|^sci.lang.japan" iso-2022-7bit)
- ("^relcom\\>" koi8-r)
- ("^fido7\\>" koi8-r)
- ("^\\(cz\\|hun\\|pl\\|sk\\|hr\\)\\>" iso-8859-2)
- ("^israel\\>" iso-8859-1)
- ("^han\\>" euc-kr)
- ("^alt.chinese.text.big5\\>" chinese-big5)
- ("^soc.culture.vietnamese\\>" vietnamese-viqr)
- ("^\\(comp\\|rec\\|alt\\|sci\\|soc\\|news\\|gnu\\|bofh\\)\\>" iso-8859-1)
- (".*" iso-8859-1))
- "Alist of regexps (to match group names) and default charsets to be used when reading."
- :type '(repeat (list (regexp :tag "Group")
- (symbol :tag "Charset")))
- :group 'gnus-charset)
-
(defcustom gnus-newsgroup-ignored-charsets '(unknown-8bit x-unknown)
"List of charsets that should be ignored.
When these charsets are used in the \"charset\" parameter, the
:type '(repeat symbol)
:group 'gnus-charset)
-(defcustom gnus-group-ignored-charsets-alist
- '(("alt\\.chinese\\.text" iso-8859-1))
- "Alist of regexps (to match group names) and charsets that should be ignored.
+(gnus-define-group-parameter
+ ignored-charsets
+ :type list
+ :function-document
+ "Return the ignored charsets of GROUP."
+ :variable gnus-group-ignored-charsets-alist
+ :variable-default
+ '(("alt\\.chinese\\.text" iso-8859-1))
+ :variable-document
+ "Alist of regexps (to match group names) and charsets that should be ignored.
When these charsets are used in the \"charset\" parameter, the
default charset will be used instead."
- :type '(repeat (cons (regexp :tag "Group")
- (repeat symbol)))
- :group 'gnus-charset)
+ :variable-group gnus-charset
+ :variable-type '(repeat (cons (regexp :tag "Group")
+ (repeat symbol)))
+ :parameter-type '(choice :tag "Ignored charsets"
+ :value nil
+ (repeat (symbol)))
+ :parameter-document "\
+List of charsets that should be ignored.
+
+When these charsets are used in the \"charset\" parameter, the
+default charset will be used instead.")
(defcustom gnus-group-highlight-words-alist nil
"Alist of group regexps and highlight regexps.
(defcustom gnus-alter-articles-to-read-function nil
"Function to be called to alter the list of articles to be selected."
- :type 'function
+ :type '(choice (const nil) function)
:group 'gnus-summary)
(defcustom gnus-orphan-score 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)
- (?L gnus-tmp-lines ?d)
+ (?L gnus-tmp-lines ?s)
(?I gnus-tmp-indentation ?s)
(?T (if (= gnus-tmp-level 0) "" (make-string (frame-width) ? )) ?s)
(?R gnus-tmp-replied ?c)
(defvar gnus-newsgroup-replied nil
"List of articles that have been replied to in the current newsgroup.")
+(defvar gnus-newsgroup-forwarded nil
+ "List of articles that have been forwarded in the current newsgroup.")
+
(defvar gnus-newsgroup-expirable nil
"List of articles in the current newsgroup that can be expired.")
gnus-newsgroup-auto-expire gnus-newsgroup-unreads
gnus-newsgroup-unselected gnus-newsgroup-marked
gnus-newsgroup-reads gnus-newsgroup-saved
- gnus-newsgroup-replied gnus-newsgroup-expirable
+ gnus-newsgroup-replied gnus-newsgroup-forwarded
+ gnus-newsgroup-expirable
gnus-newsgroup-processable gnus-newsgroup-killed
gnus-newsgroup-downloadable gnus-newsgroup-undownloaded
gnus-newsgroup-unsendable
(defsubst gnus-simplify-subject-re (subject)
"Remove \"Re:\" from subject lines."
- (if (string-match "^[Rr][Ee]: *" subject)
+ (if (string-match message-subject-re-regexp subject)
(substring subject (match-end 0))
subject))
(put 'gnus-summary-mode 'mode-class 'special)
+(defvar gnus-article-commands-menu)
+
(when t
;; Non-orthogonal keys
"\C-c\C-s\C-s" gnus-summary-sort-by-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
"=" gnus-summary-expand-window
"\C-x\C-s" gnus-summary-reselect-current-group
"\M-g" gnus-summary-rescan-group
"x" gnus-summary-limit-to-extra
"E" gnus-summary-limit-include-expunged
"c" gnus-summary-limit-exclude-childless-dormant
- "C" gnus-summary-limit-mark-excluded-as-read)
+ "C" gnus-summary-limit-mark-excluded-as-read
+ "o" gnus-summary-insert-old-articles
+ "N" gnus-summary-insert-new-articles)
(gnus-define-keys (gnus-summary-goto-map "G" gnus-summary-mode-map)
"n" gnus-summary-next-unread-article
"t" gnus-article-toggle-headers
"v" gnus-summary-verbose-headers
"m" gnus-summary-toggle-mime
- "H" gnus-article-strip-headers-in-body
+ "a" gnus-article-strip-headers-in-body ;; mnemonic: wash archive
"p" gnus-article-verify-x-pgp-sig
"d" gnus-article-treat-dumbquotes
"s" gnus-smiley-display)
"a" gnus-article-strip-blank-lines
"A" gnus-article-strip-all-blank-lines
"s" gnus-article-strip-leading-space
- "e" gnus-article-strip-trailing-space)
+ "e" gnus-article-strip-trailing-space
+ "w" gnus-article-remove-leading-whitespace)
(gnus-define-keys (gnus-summary-help-map "H" gnus-summary-mode-map)
"v" gnus-version
"q" gnus-summary-respool-query
"t" gnus-summary-respool-trace
"i" gnus-summary-import-article
+ "I" gnus-summary-create-article
"p" gnus-summary-article-posted-p)
(gnus-define-keys (gnus-summary-save-map "O" gnus-summary-mode-map)
"i" gnus-article-inline-part
"|" gnus-article-pipe-part))
+(defvar gnus-article-post-menu nil)
+
(defun gnus-summary-make-menu-bar ()
(gnus-turn-off-edit-menu 'summary)
["All of the above" gnus-article-strip-blank-lines t]
["All" gnus-article-strip-all-blank-lines t]
["Leading space" gnus-article-strip-leading-space t]
- ["Trailing space" gnus-article-strip-trailing-space t])
+ ["Trailing space" gnus-article-strip-trailing-space t]
+ ["Leading space in headers"
+ gnus-article-remove-leading-whitespace t])
["Overstrike" gnus-article-treat-overstrike t]
["Dumb quotes" gnus-article-treat-dumbquotes t]
["Emphasis" gnus-article-emphasize t]
["CR" gnus-article-remove-cr t]
["Show X-Face" gnus-article-display-x-face t]
["Rot 13" gnus-summary-caesar-message
- ,@(if (featurep 'xemacs) nil
+ ,@(if (featurep 'xemacs) '(t)
'(:help "\"Caesar rotate\" article by 13"))]
["Unix pipe" gnus-summary-pipe-message t]
["Add buttons" gnus-article-add-buttons t]
["HZ" gnus-article-decode-HZ t])
("Output"
["Save in default format" gnus-summary-save-article
- ,@(if (featurep 'xemacs) nil
+ ,@(if (featurep 'xemacs) '(t)
'(:help "Save article using default method"))]
["Save in file" gnus-summary-save-article-file
- ,@(if (featurep 'xemacs) nil
+ ,@(if (featurep 'xemacs) '(t)
'(:help "Save article in file"))]
["Save in Unix mail format" gnus-summary-save-article-mail t]
["Save in MH folder" gnus-summary-save-article-folder t]
(gnus-check-backend-function
'request-replace-article gnus-newsgroup-name)]
["Import file..." gnus-summary-import-article t]
+ ["Create article..." gnus-summary-create-article t]
["Check if posted" gnus-summary-article-posted-p t]
["Edit article" gnus-summary-edit-article
(not (gnus-group-read-only-p))]
'request-expire-articles gnus-newsgroup-name)])
("Extract"
["Uudecode" gnus-uu-decode-uu
- ,@(if (featurep 'xemacs) nil
+ ,@(if (featurep 'xemacs) '(t)
'(:help "Decode uuencoded article(s)"))]
["Uudecode and save" gnus-uu-decode-uu-and-save t]
["Unshar" gnus-uu-decode-unshar t]
gnus-summary-article-menu gnus-summary-mode-map ""
(cons "Article" innards))
- (easy-menu-define
- gnus-article-commands-menu gnus-article-mode-map ""
- (cons "Commands" innards)))
+ (if (not (keymapp gnus-summary-article-menu))
+ (easy-menu-define
+ gnus-article-commands-menu gnus-article-mode-map ""
+ (cons "Commands" innards))
+ ;; in Emacs, don't share menu.
+ (setq gnus-article-commands-menu
+ (copy-keymap gnus-summary-article-menu))
+ (define-key gnus-article-mode-map [menu-bar commands]
+ (cons "Commands" gnus-article-commands-menu))))
(easy-menu-define
gnus-summary-thread-menu gnus-summary-mode-map ""
gnus-summary-post-menu gnus-summary-mode-map ""
`("Post"
["Post an article" gnus-summary-post-news
- ,@(if (featurep 'xemacs) nil
+ ,@(if (featurep 'xemacs) '(t)
'(:help "Post an article"))]
["Followup" gnus-summary-followup
- ,@(if (featurep 'xemacs) nil
+ ,@(if (featurep 'xemacs) '(t)
'(:help "Post followup to this article"))]
["Followup and yank" gnus-summary-followup-with-original
- ,@(if (featurep 'xemacs) nil
+ ,@(if (featurep 'xemacs) '(t)
'(:help "Post followup to this article, quoting its contents"))]
["Supersede article" gnus-summary-supersede-article t]
["Cancel article" gnus-summary-cancel-article
- ,@(if (featurep 'xemacs) nil
+ ,@(if (featurep 'xemacs) '(t)
'(:help "Cancel an article you posted"))]
["Reply" gnus-summary-reply t]
["Reply and yank" gnus-summary-reply-with-original t]
["Wide reply" gnus-summary-wide-reply t]
["Wide reply and yank" gnus-summary-wide-reply-with-original
- ,@(if (featurep 'xemacs) nil
+ ,@(if (featurep 'xemacs) '(t)
'(:help "Mail a 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]
+ ["Digest and mail" gnus-summary-digest-mail-forward t]
+ ["Digest and post" gnus-summary-digest-post-forward t]
["Resend message" gnus-summary-resend-message t]
["Send bounced mail" gnus-summary-resend-bounced-mail t]
["Send a mail" gnus-summary-mail-other-window t]
["Uuencode and post" gnus-uu-post-news
- ,@(if (featurep 'xemacs) nil
+ ,@(if (featurep 'xemacs) '(t)
'(:help "Post a uuencoded article"))]
["Followup via news" gnus-summary-followup-to-mail t]
["Followup via news and yank"
;;["Send bounced" gnus-resend-bounced-mail t])
))
+ (cond
+ ((not (keymapp gnus-summary-post-menu))
+ (setq gnus-article-post-menu gnus-summary-post-menu))
+ ((not gnus-article-post-menu)
+ ;; Don't share post menu.
+ (setq gnus-article-post-menu
+ (copy-keymap gnus-summary-post-menu))))
+ (define-key gnus-article-mode-map [menu-bar post]
+ (cons "Post" gnus-article-post-menu))
+
(easy-menu-define
gnus-summary-misc-menu gnus-summary-mode-map ""
`("Misc"
gnus-summary-kill-same-subject-and-select t]
["Mark same subject" gnus-summary-kill-same-subject t]
["Catchup" gnus-summary-catchup
- ,@(if (featurep 'xemacs) nil
+ ,@(if (featurep 'xemacs) '(t)
'(:help "Mark unread articles in this group as read"))]
["Catchup all" gnus-summary-catchup-all t]
["Catchup to here" gnus-summary-catchup-to-here t]
gnus-summary-limit-exclude-childless-dormant t]
;;["Hide thread" gnus-summary-limit-exclude-thread t]
["Hide marked" gnus-summary-limit-exclude-marks t]
- ["Show expunged" gnus-summary-show-all-expunged t])
+ ["Show expunged" gnus-summary-limit-include-expunged t])
("Process Mark"
["Set mark" gnus-summary-mark-as-processable t]
["Remove mark" gnus-summary-unmark-as-processable t]
["Save" gnus-summary-save-process-mark t]))
("Scroll article"
["Page forward" gnus-summary-next-page
- ,@(if (featurep 'xemacs) nil
+ ,@(if (featurep 'xemacs) '(t)
'(:help "Show next page of article"))]
["Page backward" gnus-summary-prev-page
- ,@(if (featurep 'xemacs) nil
+ ,@(if (featurep 'xemacs) '(t)
'(:help "Show previous page of article"))]
["Line forward" gnus-summary-scroll-up t])
("Move"
["Sort by date" gnus-summary-sort-by-date t]
["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])
+ ["Sort by characters" gnus-summary-sort-by-chars 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]
["Regenerate" gnus-summary-prepare t]
["Insert cached articles" gnus-summary-insert-cached-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]
["Filter articles..." gnus-summary-execute-command t]
["Run command on subjects..." gnus-summary-universal-argument t]
["Search articles forward..." gnus-summary-search-article-forward t]
["Send a bug report" gnus-bug t]
("Exit"
["Catchup and exit" gnus-summary-catchup-and-exit
- ,@(if (featurep 'xemacs) nil
+ ,@(if (featurep 'xemacs) '(t)
'(:help "Mark unread articles in this group as read, then exit"))]
["Catchup all and exit" gnus-summary-catchup-all-and-exit t]
["Catchup and goto next" gnus-summary-catchup-and-goto-next-group t]
["Exit group" gnus-summary-exit
- ,@(if (featurep 'xemacs) nil
+ ,@(if (featurep 'xemacs) '(t)
'(:help "Exit current group, return to group selection mode"))]
["Exit group without updating" gnus-summary-exit-no-update t]
["Exit and goto next group" gnus-summary-next-group t]
(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)))
(defun gnus-set-global-variables ()
(let ((gnus-summary-line-format-spec spec)
(gnus-newsgroup-downloadable '((0 . t))))
(gnus-summary-insert-line
- (make-full-mail-header 0 "" "nobody" "" "" "" 0 0 "" nil)
+ (make-full-mail-header 0 "" "nobody"
+ "05 Apr 2001 23:33:09 +0400"
+ "" "" 0 0 "" nil)
0 nil 128 t nil "" nil 1)
(goto-char (point-min))
(setq pos (list (cons 'unread (and (search-forward "\200" nil t)
(when (string= gnus-tmp-name "")
(setq gnus-tmp-name gnus-tmp-from))
(unless (numberp gnus-tmp-lines)
- (setq gnus-tmp-lines 0))
+ (setq gnus-tmp-lines -1))
+ (when (= gnus-tmp-lines -1)
+ (setq gnus-tmp-lines "?"))
(gnus-put-text-property-excluding-characters-with-faces
(point)
(progn (eval gnus-summary-line-format-spec) (point))
;; (when (and (not (gnus-group-native-p group))
;; (not (gnus-gethash group gnus-newsrc-hashtb)))
;; (error "Dead non-native groups can't be entered"))
- (gnus-message 5 "Retrieving newsgroup: %s..." group)
+ (gnus-message 5 "Retrieving newsgroup: %s..."
+ (gnus-group-decoded-name group))
(let* ((new-group (gnus-summary-setup-buffer group))
(quit-config (gnus-group-quit-config group))
(did-select (and new-group (gnus-select-newsgroup
(gnus-handle-ephemeral-exit quit-config)))
(let ((grpinfo (gnus-get-info group)))
(if (null (gnus-info-read grpinfo))
- (gnus-message 3 "Group %s contains no messages" group)
+ (gnus-message 3 "Group %s contains no messages"
+ (gnus-group-decoded-name group))
(gnus-message 3 "Can't select group")))
nil)
;; The user did a `C-g' while prompting for number of articles,
(gnus-active gnus-newsgroup-name)))
;; You can change the summary buffer in some way with this hook.
(gnus-run-hooks 'gnus-select-group-hook)
- ;; Set any local variables in the group parameters.
- (gnus-summary-set-local-parameters gnus-newsgroup-name)
(gnus-update-format-specifications
nil 'summary 'summary-mode 'summary-dummy)
(gnus-update-summary-mark-positions)
gnus-cached-mark)
((memq number gnus-newsgroup-replied)
gnus-replied-mark)
+ ((memq number gnus-newsgroup-forwarded)
+ gnus-forwarded-mark)
((memq number gnus-newsgroup-saved)
gnus-saved-mark)
(t gnus-no-mark))
(when (string= gnus-tmp-name "")
(setq gnus-tmp-name gnus-tmp-from))
(unless (numberp gnus-tmp-lines)
- (setq gnus-tmp-lines 0))
+ (setq gnus-tmp-lines -1))
+ (when (= gnus-tmp-lines -1)
+ (setq gnus-tmp-lines "?"))
(gnus-put-text-property
(point)
(progn (eval gnus-summary-line-format-spec) (point))
(when changed
(mail-header-set-subject header subject))))))
+(defun gnus-fetch-headers (articles)
+ "Fetch headers of ARTICLES."
+ (let ((name (gnus-group-decoded-name gnus-newsgroup-name)))
+ (gnus-message 5 "Fetching headers for %s..." name)
+ (prog1
+ ;;;!!! FIXME: temporary fix for an infloop on nnimap.
+ (if (eq 'nnimap (car (gnus-find-method-for-group name)))
+ (if (eq 'nov
+ (setq gnus-headers-retrieved-by
+ (gnus-retrieve-headers
+ articles gnus-newsgroup-name
+ ;; We might want to fetch old headers, but
+ ;; not if there is only 1 article.
+ (and (or (and
+ (not (eq gnus-fetch-old-headers 'some))
+ (not (numberp gnus-fetch-old-headers)))
+ (> (length articles) 1))
+ gnus-fetch-old-headers))))
+ (gnus-get-newsgroup-headers-xover
+ articles nil nil gnus-newsgroup-name t)
+ (gnus-get-newsgroup-headers))
+ (gnus-retrieve-parsed-headers
+ articles gnus-newsgroup-name
+ ;; We might want to fetch old headers, but
+ ;; not if there is only 1 article.
+ (and (or (and (not (eq gnus-fetch-old-headers 'some))
+ (not (numberp gnus-fetch-old-headers)))
+ (> (length articles) 1))
+ gnus-fetch-old-headers)))
+ (gnus-message 5 "Fetching headers for %s...done" name))))
+
(defun gnus-select-newsgroup (group &optional read-all select-articles)
"Select newsgroup GROUP.
If READ-ALL is non-nil, all articles in the group are selected.
(gnus-make-hashtable (length articles)))
(gnus-set-global-variables)
;; Retrieve the headers and read them in.
- (gnus-message 5 "Fetching headers for %s..." gnus-newsgroup-name)
- (setq gnus-newsgroup-headers
- (gnus-retrieve-parsed-headers
- articles gnus-newsgroup-name
- ;; We might want to fetch old headers, but
- ;; not if there is only 1 article.
- (and (or (and (not (eq gnus-fetch-old-headers 'some))
- (not (numberp gnus-fetch-old-headers)))
- (> (length articles) 1))
- gnus-fetch-old-headers)))
- (gnus-message 5 "Fetching headers for %s...done" gnus-newsgroup-name)
+ (setq gnus-newsgroup-headers (gnus-fetch-headers articles))
;; Suppress duplicates?
(when gnus-suppress-duplicates
(let* ((mformat (symbol-value
(intern
(format "gnus-%s-mode-line-format-spec" where))))
- (gnus-tmp-group-name (gnus-group-name-decode
- gnus-newsgroup-name
- (gnus-group-name-charset
- nil
- gnus-newsgroup-name)))
+ (gnus-tmp-group-name (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))
(goto-char p)
(if (search-forward "\nchars: " nil t)
(if (numberp (setq chars (ignore-errors (read cur))))
- chars 0)
- 0))
+ chars -1)
+ -1))
;; Lines.
(progn
(goto-char p)
(if (search-forward "\nlines: " nil t)
(if (numberp (setq lines (ignore-errors (read cur))))
- lines 0)
- 0))
+ lines -1)
+ -1))
;; Xref.
(progn
(goto-char p)
(let ((gnus-nov-is-evil t))
(nconc
(nreverse headers)
- (gnus-retrieve-parsed-headers sequence group)
- ))))))
+ ;;;!!! FIXME: temporary fix for an infloop on nnimap.
+ (if (eq 'nnimap (car (gnus-find-method-for-group group)))
+ (when (gnus-retrieve-headers sequence group)
+ (gnus-get-newsgroup-headers))
+ (gnus-retrieve-parsed-headers sequence group))))))))
(defun gnus-article-get-xrefs ()
"Fill in the Xref value in `gnus-current-headers', if necessary.
(setq gnus-article-current nil))
(set-buffer buf)
(if (not gnus-kill-summary-on-exit)
- (gnus-deaden-summary)
+ (progn
+ (gnus-deaden-summary)
+ (setq mode nil))
;; We set all buffer-local variables to nil. It is unclear why
;; this is needed, but if we don't, buffer-local variables are
;; not garbage-collected, it seems. This would the lead to en
(set-buffer gnus-group-buffer)
(gnus-summary-clear-local-variables)
(let ((gnus-summary-local-variables gnus-newsgroup-variables))
- (gnus-summary-clear-local-variables))
- ;; Return to group mode buffer.
- (when (eq mode 'gnus-summary-mode)
- (gnus-kill-buffer buf)))
+ (gnus-summary-clear-local-variables)))
(setq gnus-current-select-method gnus-select-method)
(pop-to-buffer gnus-group-buffer)
(if (not quit-config)
(set-window-start (selected-window) (point))
(goto-char group-point)))
(gnus-handle-ephemeral-exit quit-config))
+ ;; Return to group mode buffer.
+ (when (eq mode 'gnus-summary-mode)
+ (gnus-kill-buffer buf))
;; Clear the current group name.
(unless quit-config
(setq gnus-newsgroup-name nil)))))
(require 'gnus-async)
(require 'gnus-art)
(let ((gnus-select-article-hook nil) ;Disable hook.
- (gnus-article-display-hook nil)
(gnus-article-prepare-hook nil)
(gnus-mark-article-hook nil) ;Inhibit marking as read.
(gnus-use-article-prefetch nil)
(list (let ((completion-ignore-case t))
(completing-read
"Header name: "
- (mapcar (lambda (string) (list string))
- '("Number" "Subject" "From" "Lines" "Date"
- "Message-ID" "Xref" "References" "Body"))
+ (mapcar (lambda (header) (list (format "%s" header)))
+ (append
+ '("Number" "Subject" "From" "Lines" "Date"
+ "Message-ID" "Xref" "References" "Body")
+ gnus-extra-headers))
nil 'require-match))
(read-string "Regexp: ")
(read-key-sequence "Command: ")
(copy-to-buffer buffer (point-min) (point-max))
(set-buffer buffer)
(gnus-article-delete-invisible-text)
+ (when (gnus-visual-p 'article-highlight 'highlight)
+ ;; Copy-to-buffer doesn't copy overlay. So redo
+ ;; highlight.
+ (let ((gnus-article-buffer buffer))
+ (gnus-article-highlight-citation t)
+ (gnus-article-highlight-signature)))
(let ((ps-left-header
(list
(concat "("
(mail-header-date gnus-current-headers) ")"))))
(gnus-run-hooks 'gnus-ps-print-hook)
(save-excursion
- (ps-spool-buffer-with-faces))))
+ (if window-system
+ (ps-spool-buffer-with-faces)
+ (ps-spool-buffer)))))
(kill-buffer buffer))))
(gnus-summary-remove-process-mark article))
(ps-despool filename))
(require 'gnus-art)
;; Bind the article treatment functions to nil.
(let ((gnus-have-all-headers t)
- gnus-article-display-hook
gnus-article-prepare-hook
gnus-article-decode-hook
gnus-break-pages
- gnus-show-mime)
+ gnus-show-mime
+ (gnus-inhibit-treatment t))
(gnus-summary-select-article nil 'force))))
(gnus-summary-goto-subject gnus-current-article)
(gnus-summary-position-point))
(defun gnus-summary-show-all-headers ()
"Make all header lines visible."
(interactive)
- (gnus-article-show-all-headers))
+ (gnus-summary-toggle-header 1))
(defun gnus-summary-toggle-mime (&optional arg)
"Toggle MIME processing.
(gnus-summary-move-article n nil method)
(gnus-summary-copy-article n nil method)))
-(defun gnus-summary-import-article (file)
+(defun gnus-summary-import-article (file &optional edit)
"Import an arbitrary file into a mail newsgroup."
- (interactive "fImport file: ")
+ (interactive "fImport file: \nP")
(let ((group gnus-newsgroup-name)
(now (current-time))
- atts lines)
+ atts lines group-art)
(unless (gnus-check-backend-function 'request-accept-article group)
(error "%s does not support article importing" group))
(or (file-readable-p file)
lines (count-lines (point-min) (point-max)))
(insert "From: " (read-string "From: ") "\n"
"Subject: " (read-string "Subject: ") "\n"
- "Date: " (message-make-date (nth 5 atts))
- "\n"
+ "Date: " (message-make-date (nth 5 atts)) "\n"
"Message-ID: " (message-make-message-id) "\n"
"Lines: " (int-to-string lines) "\n"
"Chars: " (int-to-string (nth 7 atts)) "\n\n"))
- (gnus-request-accept-article group nil t)
- (kill-buffer (current-buffer)))))
+ (setq group-art (gnus-request-accept-article group nil t))
+ (kill-buffer (current-buffer)))
+ (setq gnus-newsgroup-active (gnus-activate-group group))
+ (forward-line 1)
+ (gnus-summary-goto-article (cdr group-art) nil t)
+ (when edit
+ (gnus-summary-edit-article))))
+
+(defun gnus-summary-create-article ()
+ "Create an article in a mail newsgroup."
+ (interactive)
+ (let ((group gnus-newsgroup-name)
+ (now (current-time))
+ group-art)
+ (unless (gnus-check-backend-function 'request-accept-article group)
+ (error "%s does not support article importing" group))
+ (save-excursion
+ (set-buffer (gnus-get-buffer-create " *import file*"))
+ (erase-buffer)
+ (goto-char (point-min))
+ ;; This doesn't look like an article, so we fudge some headers.
+ (insert "From: " (read-string "From: ") "\n"
+ "Subject: " (read-string "Subject: ") "\n"
+ "Date: " (message-make-date now) "\n"
+ "Message-ID: " (message-make-message-id) "\n")
+ (setq group-art (gnus-request-accept-article group nil t))
+ (kill-buffer (current-buffer)))
+ (setq gnus-newsgroup-active (gnus-activate-group group))
+ (forward-line 1)
+ (gnus-summary-goto-article (cdr group-art) nil t)
+ (gnus-summary-edit-article)))
(defun gnus-summary-article-posted-p ()
"Say whether the current (mail) article is available from news as well.
If N is negative, mark backward instead. If UNMARK is non-nil, remove
the process mark instead. The difference between N and the actual
number of articles marked is returned."
- (interactive "p")
- (let ((backward (< n 0))
- (n (abs n)))
- (while (and
- (> n 0)
- (if unmark
+ (interactive "P")
+ (if (and (null n) (gnus-region-active-p))
+ (gnus-uu-mark-region (region-beginning) (region-end) unmark)
+ (setq n (prefix-numeric-value n))
+ (let ((backward (< n 0))
+ (n (abs n)))
+ (while (and
+ (> n 0)
+ (if unmark
(gnus-summary-remove-process-mark
(gnus-summary-article-number))
- (gnus-summary-set-process-mark (gnus-summary-article-number)))
- (zerop (gnus-summary-next-subject (if backward -1 1) nil t)))
- (setq n (1- n)))
- (when (/= 0 n)
- (gnus-message 7 "No more articles"))
- (gnus-summary-recenter)
- (gnus-summary-position-point)
- n))
+ (gnus-summary-set-process-mark (gnus-summary-article-number)))
+ (zerop (gnus-summary-next-subject (if backward -1 1) nil t)))
+ (setq n (1- n)))
+ (when (/= 0 n)
+ (gnus-message 7 "No more articles"))
+ (gnus-summary-recenter)
+ (gnus-summary-position-point)
+ n)))
(defun gnus-summary-unmark-as-processable (n)
"Remove the process mark from the next N articles.
If N is negative, unmark backward instead. The difference between N and
the actual number of articles unmarked is returned."
- (interactive "p")
+ (interactive "P")
(gnus-summary-mark-as-processable n t))
(defun gnus-summary-unmark-all-processable ()
(error "No such mark type: %s" type)
(setq var (intern (format "gnus-newsgroup-%s" type)))
(set var (cons article (symbol-value var)))
- (if (memq type '(processable cached replied saved))
+ (if (memq type '(processable cached replied forwarded saved))
(gnus-summary-update-secondary-mark article)
;;; !!! This is bobus. We should find out what primary
;;; !!! mark we want to set.
(gnus-summary-mark-forward n gnus-expirable-mark))
(defun gnus-summary-mark-article-as-replied (article)
- "Mark ARTICLE replied and update the summary line."
- (push article gnus-newsgroup-replied)
- (let ((buffer-read-only nil))
- (when (gnus-summary-goto-subject article nil t)
- (gnus-summary-update-secondary-mark article))))
+ "Mark ARTICLE as replied to and update the summary line.
+ARTICLE can also be a list of articles."
+ (interactive (list (gnus-summary-article-number)))
+ (let ((articles (if (listp article) article (list article))))
+ (dolist (article articles)
+ (push article gnus-newsgroup-replied)
+ (let ((buffer-read-only nil))
+ (when (gnus-summary-goto-subject article nil t)
+ (gnus-summary-update-secondary-mark article))))))
+
+(defun gnus-summary-mark-article-as-forwarded (article)
+ "Mark ARTICLE as forwarded and update the summary line.
+ARTICLE can also be a list of articles."
+ (let ((articles (if (listp article) article (list article))))
+ (dolist (article articles)
+ (push article gnus-newsgroup-forwarded)
+ (let ((buffer-read-only nil))
+ (when (gnus-summary-goto-subject article nil t)
+ (gnus-summary-update-secondary-mark article))))))
(defun gnus-summary-set-bookmark (article)
"Set a bookmark in current article."
gnus-cached-mark)
((memq article gnus-newsgroup-replied)
gnus-replied-mark)
+ ((memq article gnus-newsgroup-forwarded)
+ gnus-forwarded-mark)
((memq article gnus-newsgroup-saved)
gnus-saved-mark)
(t gnus-no-mark))
(let ((scored gnus-newsgroup-scored)
headers h)
(while scored
- (unless (gnus-number-to-header (caar scored))
- (and (setq h (gnus-summary-article-header (caar scored)))
+ (unless (gnus-summary-article-header (caar scored))
+ (and (setq h (gnus-number-to-header (caar scored)))
(< (cdar scored) gnus-summary-expunge-below)
(push h headers)))
(setq scored (cdr scored)))
(when (not no-error)
(error "No expunged articles hidden"))
(goto-char (point-min))
+ (push gnus-newsgroup-limit gnus-newsgroup-limits)
+ (setq gnus-newsgroup-limit (copy-sequence gnus-newsgroup-limit))
+ (mapcar (lambda (x) (push (mail-header-number x)
+ gnus-newsgroup-limit))
+ headers)
(gnus-summary-prepare-unthreaded (nreverse headers))
(goto-char (point-min))
(gnus-summary-position-point)
(defun gnus-summary-catchup-and-exit (&optional all quietly)
"Mark all unread articles in this group as read, then exit.
-If prefix argument ALL is non-nil, all articles are marked as read."
+If prefix argument ALL is non-nil, all articles are marked as read.
+If QUIETLY is non-nil, no questions will be asked."
(interactive "P")
(when (gnus-summary-catchup all quietly nil 'fast)
;; Select next newsgroup or exit.
(defun gnus-summary-up-thread (n)
"Go up thread N steps.
-If N is negative, go up instead.
+If N is negative, go down instead.
Returns the difference between N and how many steps down that were
taken."
(interactive "p")
(interactive "P")
(gnus-summary-sort 'chars reverse))
+(defun gnus-summary-sort-by-original (&optional reverse)
+ "Sort the summary buffer using the default sorting method.
+Argument REVERSE means reverse order."
+ (interactive "P")
+ (let* ((buffer-read-only)
+ (gnus-summary-prepare-hook nil))
+ ;; We do the sorting by regenerating the threads.
+ (gnus-summary-prepare)
+ ;; Hide subthreads if needed.
+ (when (and gnus-show-threads gnus-thread-hide-subtree)
+ (gnus-summary-hide-all-threads))))
+
(defun gnus-summary-sort (predicate reverse)
"Sort summary buffer by PREDICATE. REVERSE means reverse order."
(let* ((thread (intern (format "gnus-thread-sort-by-%s" predicate)))
"Setup newsgroup default charset."
(if (equal gnus-newsgroup-name "nndraft:drafts")
(setq gnus-newsgroup-charset nil)
- (let* ((name (and gnus-newsgroup-name
- (gnus-group-real-name gnus-newsgroup-name)))
- (ignored-charsets
+ (let* ((ignored-charsets
(or gnus-newsgroup-ephemeral-ignored-charsets
(append
(and gnus-newsgroup-name
- (or (gnus-group-find-parameter gnus-newsgroup-name
- 'ignored-charsets t)
- (let ((alist gnus-group-ignored-charsets-alist)
- elem (charsets nil))
- (while (setq elem (pop alist))
- (when (and name
- (string-match (car elem) name))
- (setq alist nil
- charsets (cdr elem))))
- charsets)))
+ (gnus-parameter-ignored-charsets gnus-newsgroup-name))
gnus-newsgroup-ignored-charsets))))
(setq gnus-newsgroup-charset
(or gnus-newsgroup-ephemeral-charset
(and gnus-newsgroup-name
- (or (gnus-group-find-parameter gnus-newsgroup-name 'charset)
- (let ((alist gnus-group-charset-alist)
- elem charset)
- (while (setq elem (pop alist))
- (when (and name
- (string-match (car elem) name))
- (setq alist nil
- charset (cadr elem))))
- charset)))
+ (gnus-parameter-charset gnus-newsgroup-name))
gnus-default-charset))
(set (make-local-variable 'gnus-newsgroup-ignored-charsets)
ignored-charsets))))
(gnus-set-mode-line 'summary)
n))
+(defun gnus-summary-insert-articles (articles)
+ (when (setq articles
+ (gnus-set-difference articles
+ (mapcar (lambda (h) (mail-header-number h))
+ gnus-newsgroup-headers)))
+ (setq gnus-newsgroup-headers
+ (merge 'list
+ gnus-newsgroup-headers
+ (gnus-fetch-headers articles)
+ 'gnus-article-sort-by-number))
+ ;; Suppress duplicates?
+ (when gnus-suppress-duplicates
+ (gnus-dup-suppress-articles))
+
+ ;; We might want to build some more threads first.
+ (when (and gnus-fetch-old-headers
+ (eq gnus-headers-retrieved-by 'nov))
+ (if (eq gnus-fetch-old-headers 'invisible)
+ (gnus-build-all-threads)
+ (gnus-build-old-threads)))
+ ;; Let the Gnus agent mark articles as read.
+ (when gnus-agent
+ (gnus-agent-get-undownloaded-list))
+ ;; Remove list identifiers from subject
+ (when gnus-list-identifiers
+ (gnus-summary-remove-list-identifiers))
+ ;; First and last article in this newsgroup.
+ (when gnus-newsgroup-headers
+ (setq gnus-newsgroup-begin
+ (mail-header-number (car gnus-newsgroup-headers))
+ gnus-newsgroup-end
+ (mail-header-number
+ (gnus-last-element gnus-newsgroup-headers))))
+ (when gnus-use-scoring
+ (gnus-possibly-score-headers))))
+
+(defun gnus-summary-insert-old-articles (&optional all)
+ "Insert all old articles in this group.
+If ALL is non-nil, already read articles become readable.
+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))
+ older len)
+ (while (<= i (cdr gnus-newsgroup-active))
+ (or (memq i old) (push i older))
+ (incf i))
+ (setq len (length older))
+ (cond
+ ((null older) nil)
+ ((numberp all)
+ (if (< all len)
+ (setq older (subseq older 0 all))))
+ (all nil)
+ (t
+ (if (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))))
+ (unless (string-match "^[ \t]*$" input)
+ (setq all (string-to-number input))
+ (if (< all len)
+ (setq older (subseq older 0 all))))))))
+ (if (not older)
+ (message "No old news.")
+ (gnus-summary-insert-articles older)
+ (gnus-summary-limit (gnus-union older old))))
+ (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))
+ (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))
+ (push i new)
+ (incf i))
+ (if (not new)
+ (message "No gnus is bad news.")
+ (gnus-summary-insert-articles new)
+ (setq gnus-newsgroup-unreads
+ (append gnus-newsgroup-unreads new))
+ (gnus-summary-limit (gnus-union old new))))
+ (gnus-summary-position-point)))
+
(gnus-summary-make-all-marking-commands)
(gnus-ems-redefine)