-;;; gnus-sum.el --- summary mode commands for Gnus
-;; Copyright (C) 1996,97,98 Free Software Foundation, Inc.
+;;; gnus-sum.el --- summary mode commands for Semi-gnus
+;; Copyright (C) 1996,97,98,99 Free Software Foundation, Inc.
;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
-;; Keywords: news
+;; MORIOKA Tomohiko <morioka@jaist.ac.jp>
+;; Katsumi Yamaoka <yamaoka@jpl.org>
+;; Keywords: mail, news, MIME
;; This file is part of GNU Emacs.
(require 'gnus-int)
(require 'gnus-undo)
(require 'gnus-util)
-(require 'mm-decode)
+(require 'mime-view)
+
+(eval-when-compile
+ (require 'mime-play)
+ ;; Avoid byte-compile warnings.
+ (defvar gnus-article-decoded-p)
+ (defvar gnus-decode-encoded-word-function)
+ )
+
+(eval-and-compile
+ (autoload 'gnus-cache-articles-in-group "gnus-cache"))
+
(autoload 'gnus-summary-limit-include-cached "gnus-cache" nil t)
+(autoload 'gnus-set-summary-default-charset "gnus-i18n" nil t)
(defcustom gnus-kill-summary-on-exit t
"*If non-nil, kill the summary buffer when you exit from it.
in the group. If t, select the first unread article.
This variable can also be a function to place point on a likely
-subject line. Useful values include `gnus-summary-first-unread-subject',
-`gnus-summary-first-unread-article' and
+subject line. Useful values include `gnus-summary-first-unread-subject',
+`gnus-summary-first-unread-article' and
`gnus-summary-best-unread-article'.
If you want to prevent automatic selection of the first unread article
:group 'gnus-article-various
:type 'boolean)
+(defcustom gnus-show-mime t
+ "*If non-nil, do mime processing of articles.
+The articles will simply be fed to the function given by
+`gnus-article-display-method-for-mime'."
+ :group 'gnus-article-mime
+ :type 'boolean)
+
(defcustom gnus-move-split-methods nil
"*Variable used to suggest where articles are to be moved to.
It uses the same syntax as the `gnus-split-methods' variable."
(cons :value ("" "") regexp (repeat string))
(sexp :value nil))))
-(defcustom gnus-unread-mark ?
+(defcustom gnus-unread-mark ? ;Whitespace
"*Mark used for unread articles."
:group 'gnus-summary-marks
:type 'character)
:group 'gnus-summary-marks
:type 'character)
-(defcustom gnus-empty-thread-mark ?
+(defcustom gnus-empty-thread-mark ? ;Whitespace
"*There is no thread under the article."
:group 'gnus-summary-marks
:type 'character)
:group 'gnus-extract-view
:type 'boolean)
+(defcustom gnus-auto-expirable-marks
+ (list gnus-killed-mark gnus-del-mark gnus-catchup-mark
+ gnus-low-score-mark gnus-ancient-mark gnus-read-mark
+ gnus-souped-mark gnus-duplicate-mark)
+ "*The list of marks converted into expiration if a group is auto-expirable."
+ :group 'gnus-summary
+ :type '(repeat character))
+
+(defcustom gnus-inhibit-user-auto-expire t
+ "*If non-nil, user marking commands will not mark an article as expirable, even if the group has auto-expire turned on."
+ :group 'gnus-summary
+ :type 'boolean)
+
(defcustom gnus-view-pseudos nil
"*If `automatic', pseudo-articles will be viewed automatically.
If `not-confirm', pseudos will be viewed automatically, and the user
\"thread score\" is.
This variable is local to the summary buffers."
- :group 'gnus-treading
+ :group 'gnus-threading
:group 'gnus-score-default
:type '(choice (const :tag "off" nil)
integer))
:group 'gnus-summary-visual
:type 'hook)
-(defcustom gnus-parse-headers-hook nil
+(defcustom gnus-parse-headers-hook '(gnus-set-summary-default-charset)
"*A hook called before parsing the headers."
:group 'gnus-various
:type 'hook)
The function is called with one parameter, the article header vector,
which it may alter in any way.")
-(defvar gnus-decode-encoded-word-function 'mail-decode-encoded-word-string
- "Variable that says which function should be used to decode a string with encoded words.")
-
(defcustom gnus-extra-headers nil
"*Extra headers to parse."
:group 'gnus-summary
: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)
+ ("^relcom\\>" koi8-r)
+ ("^\\(cz\\|hun\\|pl\\|sk\\|hr\\)\\>" iso-8859-2)
+ ("^israel\\>" iso-8859-1)
+ ("^han\\>" euc-kr)
+ ("^\\(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)
+ "List of charsets that should be ignored.
+When these charsets are used in the \"charset\" parameter, the
+default charset will be used instead."
+ :type '(repeat symbol)
+ :group 'gnus-charset)
+
;;; Internal variables
-(defvar gnus-article-mime-handles nil)
-(defvar gnus-article-decoded-p 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)
(?S ,(macroexpand '(mail-header-subject gnus-tmp-header)) ?s)
(?s gnus-tmp-subject-or-nil ?s)
(?n gnus-tmp-name ?s)
- (?A (car (cdr (funcall gnus-extract-address-components gnus-tmp-from)))
- ?s)
- (?a (or (car (funcall gnus-extract-address-components gnus-tmp-from))
+ (?A (std11-address-string
+ (car (mime-read-field 'From gnus-tmp-header))) ?s)
+ (?a (or (std11-full-name-string
+ (car (mime-read-field 'From gnus-tmp-header)))
gnus-tmp-from) ?s)
(?F gnus-tmp-from ?s)
(?x ,(macroexpand '(mail-header-xref gnus-tmp-header)) ?s)
(defvar gnus-have-all-headers nil)
(defvar gnus-last-article nil)
(defvar gnus-newsgroup-history nil)
+(defvar gnus-newsgroup-charset nil)
(defconst gnus-summary-local-variables
'(gnus-newsgroup-name
gnus-newsgroup-dependencies gnus-newsgroup-selected-overlay
gnus-newsgroup-scored gnus-newsgroup-kill-headers
gnus-thread-expunge-below
- gnus-score-alist gnus-current-score-file gnus-summary-expunge-below
+ gnus-score-alist gnus-current-score-file
+ (gnus-summary-expunge-below . global)
(gnus-summary-mark-below . global)
gnus-newsgroup-active gnus-scores-exclude-files
gnus-newsgroup-history gnus-newsgroup-ancient
(gnus-newsgroup-expunged-tally . 0)
gnus-cache-removable-articles gnus-newsgroup-cached
gnus-newsgroup-data gnus-newsgroup-data-reverse
- gnus-newsgroup-limit gnus-newsgroup-limits)
+ gnus-newsgroup-limit gnus-newsgroup-limits
+ gnus-newsgroup-charset)
"Variables that are buffer-local to the summary buffers.")
;; Byte-compiler warning.
(defvar gnus-article-mode-map)
-;; MIME stuff.
-
-(defvar gnus-decode-encoded-word-methods
- '(mail-decode-encoded-word-string)
- "List of methods used to decode encoded words.
-
-This variable is a list of FUNCTION or (REGEXP . FUNCTION). If item is
-FUNCTION, FUNCTION will be apply to all newsgroups. If item is a
-(REGEXP . FUNCTION), FUNCTION will be only apply to thes newsgroups
-whose names match REGEXP.
-
-For example:
-((\"chinese\" . gnus-decode-encoded-word-string-by-guess)
- mail-decode-encoded-word-string
- (\"chinese\" . rfc1843-decode-string))
-")
-
-(defvar gnus-decode-encoded-word-methods-cache nil)
-
-(defun gnus-multi-decode-encoded-word-string (string)
- "Apply the functions from `gnus-encoded-word-methods' that match."
- (unless (and gnus-decode-encoded-word-methods-cache
- (eq gnus-newsgroup-name
- (car gnus-decode-encoded-word-methods-cache)))
- (setq gnus-decode-encoded-word-methods-cache (list gnus-newsgroup-name))
- (mapc '(lambda (x)
- (if (symbolp x)
- (nconc gnus-decode-encoded-word-methods-cache (list x))
- (if (and gnus-newsgroup-name
- (string-match (car x) gnus-newsgroup-name))
- (nconc gnus-decode-encoded-word-methods-cache
- (list (cdr x))))))
- gnus-decode-encoded-word-methods))
- (let ((xlist gnus-decode-encoded-word-methods-cache))
- (pop xlist)
- (while xlist
- (setq string (funcall (pop xlist) string))))
- string)
-
;; Subject simplification.
(defun gnus-simplify-whitespace (str)
"\C-c\M-\C-s" gnus-summary-limit-include-expunged
"\C-c\C-s\C-n" gnus-summary-sort-by-number
"\C-c\C-s\C-l" gnus-summary-sort-by-lines
+ "\C-c\C-s\C-c" gnus-summary-sort-by-chars
"\C-c\C-s\C-a" gnus-summary-sort-by-author
"\C-c\C-s\C-s" gnus-summary-sort-by-subject
"\C-c\C-s\C-d" gnus-summary-sort-by-date
"\M-g" gnus-summary-rescan-group
"w" gnus-summary-stop-page-breaking
"\C-c\C-r" gnus-summary-caesar-message
+ "\M-t" gnus-summary-toggle-mime
"f" gnus-summary-followup
"F" gnus-summary-followup-with-original
"C" gnus-summary-cancel-article
"a" gnus-summary-post-news
"x" gnus-summary-limit-to-unread
"s" gnus-summary-isearch-article
- "t" gnus-article-hide-headers
+ "t" gnus-article-toggle-headers
"g" gnus-summary-show-article
"l" gnus-summary-goto-last-article
+ "v" gnus-summary-preview-mime-message
"\C-c\C-v\C-v" gnus-uu-decode-uu-view
"\C-d" gnus-summary-enter-digest-group
"\M-\C-d" gnus-summary-read-document
"\M-\C-e" gnus-summary-edit-parameters
+ "\M-\C-g" gnus-summary-customize-parameters
"\C-c\C-b" gnus-bug
"*" gnus-cache-enter-article
"\M-*" gnus-cache-remove-article
"L" gnus-summary-lower-score
"\M-i" gnus-symbolic-argument
"h" gnus-summary-select-article-buffer
- "b" gnus-article-view-part
-
+
"V" gnus-summary-score-map
"X" gnus-uu-extract-map
"S" gnus-summary-send-map)
"a" gnus-summary-limit-to-author
"u" gnus-summary-limit-to-unread
"m" gnus-summary-limit-to-marks
+ "M" gnus-summary-limit-exclude-marks
"v" gnus-summary-limit-to-score
"*" gnus-summary-limit-include-cached
"D" gnus-summary-limit-include-dormant
"e" gnus-summary-end-of-article
"^" gnus-summary-refer-parent-article
"r" gnus-summary-refer-parent-article
+ "D" gnus-summary-enter-digest-group
"R" gnus-summary-refer-references
"T" gnus-summary-refer-thread
"g" gnus-summary-show-article
"o" gnus-article-treat-overstrike
"e" gnus-article-emphasize
"w" gnus-article-fill-cited-article
+ "Q" gnus-article-fill-long-lines
+ "C" gnus-article-capitalize-sentences
"c" gnus-article-remove-cr
- "q" gnus-article-de-quoted-unreadable
"f" gnus-article-display-x-face
"l" gnus-summary-stop-page-breaking
"r" gnus-summary-caesar-message
- "t" gnus-article-hide-headers
+ "t" gnus-article-toggle-headers
"v" gnus-summary-verbose-headers
+ "m" gnus-summary-toggle-mime
"h" gnus-article-treat-html
+ "H" gnus-article-strip-headers-in-body
"d" gnus-article-treat-dumbquotes)
(gnus-define-keys (gnus-summary-wash-hide-map "W" gnus-summary-wash-map)
"a" gnus-article-hide
- "h" gnus-article-hide-headers
+ "h" gnus-article-toggle-headers
"b" gnus-article-hide-boring-headers
"s" gnus-article-hide-signature
"c" gnus-article-hide-citation
"C" gnus-article-hide-citation-in-followups
"p" gnus-article-hide-pgp
+ "B" gnus-article-strip-banner
"P" gnus-article-hide-pem
"\C-c" gnus-article-hide-citation-maybe)
"c" gnus-article-highlight-citation
"s" gnus-article-highlight-signature)
- (gnus-define-keys (gnus-summary-wash-mime-map "M" gnus-summary-wash-map)
- "w" gnus-article-decode-mime-words
- "c" gnus-article-decode-charset
- "v" gnus-mime-view-all-parts
- "b" gnus-article-view-part)
-
(gnus-define-keys (gnus-summary-wash-time-map "T" gnus-summary-wash-map)
"z" gnus-article-date-ut
"u" gnus-article-date-ut
"m" gnus-article-strip-multiple-blank-lines
"a" gnus-article-strip-blank-lines
"A" gnus-article-strip-all-blank-lines
- "s" gnus-article-strip-leading-space)
+ "s" gnus-article-strip-leading-space
+ "e" gnus-article-strip-trailing-space)
(gnus-define-keys (gnus-summary-help-map "H" gnus-summary-mode-map)
"v" gnus-version
"h" gnus-summary-save-article-folder
"v" gnus-summary-save-article-vm
"p" gnus-summary-pipe-output
- "s" gnus-soup-add-article))
+ "s" gnus-soup-add-article)
+
+ (gnus-define-keys (gnus-summary-mime-map "K" gnus-summary-mode-map)
+ "b" gnus-summary-display-buttonized
+ "m" gnus-summary-repair-multipart
+ "v" gnus-article-view-part
+ "o" gnus-article-save-part
+ "c" gnus-article-copy-part
+ "e" gnus-article-externalize-part
+ "i" gnus-article-inline-part
+ "|" gnus-article-pipe-part)
+ )
(defun gnus-summary-make-menu-bar ()
(gnus-turn-off-edit-menu 'summary)
(let ((innards
'(("Hide"
["All" gnus-article-hide t]
- ["Headers" gnus-article-hide-headers t]
+ ["Headers" gnus-article-toggle-headers t]
["Signature" gnus-article-hide-signature t]
["Citation" gnus-article-hide-citation t]
["PGP" gnus-article-hide-pgp t]
+ ["Banner" gnus-article-strip-banner t]
["Boring headers" gnus-article-hide-boring-headers t])
("Highlight"
["All" gnus-article-highlight t]
["Headers" gnus-article-highlight-headers t]
["Signature" gnus-article-highlight-signature t]
["Citation" gnus-article-highlight-citation t])
- ("MIME"
- ["Words" gnus-article-decode-mime-words t]
- ["Charset" gnus-article-decode-charset t]
- ["QP" gnus-article-de-quoted-unreadable t]
- ["View all" gnus-mime-view-all-parts t])
("Date"
["Local" gnus-article-date-local t]
["ISO8601" gnus-article-date-iso8601 t]
["Trailing" gnus-article-remove-trailing-blank-lines t]
["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])
+ ["Leading space" gnus-article-strip-leading-space t]
+ ["Trailing space" gnus-article-strip-trailing-space t])
["Overstrike" gnus-article-treat-overstrike t]
["Dumb quotes" gnus-article-treat-dumbquotes t]
["Emphasis" gnus-article-emphasize t]
["Word wrap" gnus-article-fill-cited-article t]
+ ["Fill long lines" gnus-article-fill-long-lines t]
+ ["Capitalize sentences" gnus-article-capitalize-sentences t]
["CR" gnus-article-remove-cr t]
["Show X-Face" gnus-article-display-x-face t]
- ["Quoted-Printable" gnus-article-de-quoted-unreadable t]
["UnHTMLize" gnus-article-treat-html t]
["Rot 13" gnus-summary-caesar-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]
+ ["Toggle MIME" gnus-summary-toggle-mime t]
["Verbose header" gnus-summary-verbose-headers t]
["Toggle header" gnus-summary-toggle-header t])
("Output"
["Wide reply and yank" gnus-summary-wide-reply-with-original t]
["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-mail-digest t]
+ ["Digest and post" gnus-summary-post-digest 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]
["Hide childless dormant"
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])
("Process Mark"
["Set mark" gnus-summary-mark-as-processable t]
["Sort by subject" gnus-summary-sort-by-subject t]
["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 lines" gnus-summary-sort-by-lines t]
+ ["Sort by characters" gnus-summary-sort-by-chars t])
("Help"
["Fetch group FAQ" gnus-summary-fetch-faq t]
["Describe group" gnus-summary-describe-group t]
["Edit local kill file" gnus-summary-edit-local-kill t]
["Edit main kill file" gnus-summary-edit-global-kill t]
["Edit group parameters" gnus-summary-edit-parameters t]
+ ["Customize group parameters" gnus-summary-customize-parameters t]
["Send a bug report" gnus-bug t]
("Exit"
["Catchup and exit" gnus-summary-catchup-and-exit t]
(make-local-variable 'gnus-summary-dummy-line-format)
(make-local-variable 'gnus-summary-dummy-line-format-spec)
(make-local-variable 'gnus-summary-mark-positions)
- (make-local-hook 'post-command-hook)
- (add-hook 'post-command-hook 'gnus-clear-inboxes-moved nil t)
(make-local-hook 'pre-command-hook)
(add-hook 'pre-command-hook 'gnus-set-global-variables nil t)
(gnus-run-hooks 'gnus-summary-mode-hook)
- (mm-enable-multibyte)
(gnus-update-format-specifications nil 'summary 'summary-mode 'summary-dummy)
(gnus-update-summary-mark-positions))
(defun gnus-summary-make-local-variables ()
"Make all the local summary buffer variables."
- (let ((locals gnus-summary-local-variables)
- global local)
- (while (setq local (pop locals))
+ (let (global)
+ (dolist (local gnus-summary-local-variables)
(if (consp local)
(progn
(if (eq (cdr local) 'global)
(setq global (symbol-value (car local)))
;; Use the value from the list.
(setq global (eval (cdr local))))
- (make-local-variable (car local))
- (set (car local) global))
+ (set (make-local-variable (car local)) global))
;; Simple nil-valued local variable.
- (make-local-variable local)
- (set local nil)))))
+ (set (make-local-variable local) nil)))))
(defun gnus-summary-clear-local-variables ()
(let ((locals gnus-summary-local-variables))
(original gnus-original-article-buffer)
(gac gnus-article-current)
(reffed gnus-reffed-article-number)
- (score-file gnus-current-score-file))
+ (score-file gnus-current-score-file)
+ (default-charset gnus-newsgroup-charset))
(save-excursion
(set-buffer gnus-group-buffer)
(setq gnus-newsgroup-name name
gnus-article-buffer article-buffer
gnus-original-article-buffer original
gnus-reffed-article-number reffed
- gnus-current-score-file score-file)
+ gnus-current-score-file score-file
+ gnus-newsgroup-charset default-charset)
;; The article buffer also has local variables.
(when (gnus-buffer-live-p gnus-article-buffer)
(set-buffer gnus-article-buffer)
(defun gnus-summary-last-article-p (&optional article)
"Return whether ARTICLE is the last article in the buffer."
(if (not (setq article (or article (gnus-summary-article-number))))
- t ; All non-existent numbers are the last article. :-)
+ ;; All non-existent numbers are the last article. :-)
+ t
(not (cdr (gnus-data-find-list article)))))
(defun gnus-make-thread-indent-array ()
(let ((gnus-summary-line-format-spec spec)
(gnus-newsgroup-downloadable '((0 . t))))
(gnus-summary-insert-line
- [0 "" "" "" "" "" 0 0 "" nil] 0 nil 128 t nil "" nil 1)
+ (make-full-mail-header 0 "" "" "" "" "" 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)
(- (point) 2)))))
(defun gnus-summary-from-or-to-or-newsgroups (header)
(let ((to (cdr (assq 'To (mail-header-extra header))))
- (newsgroups (cdr (assq 'Newsgroups (mail-header-extra header)))))
+ (newsgroups (cdr (assq 'Newsgroups (mail-header-extra header))))
+ (mail-parse-charset gnus-newsgroup-charset))
(cond
((and to
gnus-ignored-from-addresses
(if (or (null gnus-summary-default-score)
(<= (abs (- gnus-tmp-score gnus-summary-default-score))
gnus-summary-zcore-fuzz))
- ?
+ ? ;Whitespace
(if (< gnus-tmp-score gnus-summary-default-score)
gnus-score-below-mark gnus-score-over-mark)))
(gnus-tmp-replied
(setq gnus-tmp-name gnus-tmp-from))
(unless (numberp gnus-tmp-lines)
(setq gnus-tmp-lines 0))
- (gnus-put-text-property
+ (gnus-put-text-property-excluding-characters-with-faces
(point)
(progn (eval gnus-summary-line-format-spec) (point))
'gnus-number gnus-tmp-number)
(if (or (null gnus-summary-default-score)
(<= (abs (- score gnus-summary-default-score))
gnus-summary-zcore-fuzz))
- ?
+ ? ;Whitespace
(if (< score gnus-summary-default-score)
gnus-score-below-mark gnus-score-over-mark))
'score))
(setq heads nil)))))
gnus-newsgroup-dependencies)))
-(defmacro gnus-nov-read-integer ()
- '(prog1
- (if (eq (char-after) ?\t)
- 0
- (let ((num (ignore-errors (read buffer))))
- (if (numberp num) num 0)))
- (unless (eobp)
- (search-forward "\t" eol 'move))))
-
-(defmacro gnus-nov-skip-field ()
- '(search-forward "\t" eol 'move))
-
-(defmacro gnus-nov-field ()
- '(buffer-substring (point) (if (gnus-nov-skip-field) (1- (point)) eol)))
-
-(defmacro gnus-nov-parse-extra ()
- '(let (out string)
- (while (not (memq (char-after) '(?\n nil)))
- (setq string (gnus-nov-field))
- (when (string-match "^\\([^ :]+\\): " string)
- (push (cons (intern (match-string 1 string))
- (substring string (match-end 0)))
- out)))
- out))
-
;; This function has to be called with point after the article number
;; on the beginning of the line.
(defsubst gnus-nov-parse-line (number dependencies &optional force-new)
header)
;; overview: [num subject from date id refs chars lines misc]
- (unwind-protect
- (progn
- (narrow-to-region (point) eol)
- (unless (eobp)
- (forward-char))
-
- (setq header
- (make-full-mail-header
- number ; number
- (funcall gnus-decode-encoded-word-function
- (gnus-nov-field)) ; subject
- (funcall gnus-decode-encoded-word-function
- (gnus-nov-field)) ; from
- (gnus-nov-field) ; date
- (or (gnus-nov-field)
- (nnheader-generate-fake-message-id)) ; id
- (gnus-nov-field) ; refs
- (gnus-nov-read-integer) ; chars
- (gnus-nov-read-integer) ; lines
- (unless (eq (char-after) ?\n)
- (gnus-nov-field)) ; misc
- (gnus-nov-parse-extra)))) ; extra
-
- (widen))
+ (unless (eobp)
+ (forward-char))
+
+ (setq header
+ (make-full-mail-header
+ number ; number
+ (nnheader-nov-field) ; subject
+ (nnheader-nov-field) ; from
+ (nnheader-nov-field) ; date
+ (nnheader-nov-read-message-id) ; id
+ (nnheader-nov-field) ; refs
+ (nnheader-nov-read-integer) ; chars
+ (nnheader-nov-read-integer) ; lines
+ (unless (eobp)
+ (nnheader-nov-field)) ; misc
+ (nnheader-nov-parse-extra))) ; extra
(when gnus-alter-header-function
(funcall gnus-alter-header-function header))
(gnus-article-sort-by-lines
(gnus-thread-header h1) (gnus-thread-header h2)))
+(defsubst gnus-article-sort-by-chars (h1 h2)
+ "Sort articles by octet length."
+ (< (mail-header-chars h1)
+ (mail-header-chars h2)))
+
+(defun gnus-thread-sort-by-chars (h1 h2)
+ "Sort threads by root article octet length."
+ (gnus-article-sort-by-chars
+ (gnus-thread-header h1) (gnus-thread-header h2)))
+
(defsubst gnus-article-sort-by-author (h1 h2)
"Sort articles by root author."
(string-lessp
- (let ((extract (funcall
- gnus-extract-address-components
- (mail-header-from h1))))
- (or (car extract) (cadr extract) ""))
- (let ((extract (funcall
- gnus-extract-address-components
- (mail-header-from h2))))
- (or (car extract) (cadr extract) ""))))
+ (let ((addr (car (mime-read-field 'From h1))))
+ (or (std11-full-name-string addr)
+ (std11-address-string addr)
+ ""))
+ (let ((addr (car (mime-read-field 'From h2))))
+ (or (std11-full-name-string addr)
+ (std11-address-string addr)
+ ""))
+ ))
(defun gnus-thread-sort-by-author (h1 h2)
"Sort threads by root author."
(> (gnus-thread-total-score h1) (gnus-thread-total-score h2)))
(defun gnus-thread-total-score (thread)
- ;; This function find the total score of THREAD.
+ ;; This function find the total score of THREAD.
(cond ((null thread)
0)
((consp thread)
(if (or (null gnus-summary-default-score)
(<= (abs (- gnus-tmp-score gnus-summary-default-score))
gnus-summary-zcore-fuzz))
- ?
+ ? ;Whitespace
(if (< gnus-tmp-score gnus-summary-default-score)
gnus-score-below-mark gnus-score-over-mark))
gnus-tmp-replied
(setq gnus-newsgroup-name group)
(setq gnus-newsgroup-unselected nil)
(setq gnus-newsgroup-unreads (gnus-list-of-unread-articles group))
+ (gnus-summary-setup-default-charset)
;; Adjust and set lists of article marks.
(when info
(gnus-adjust-marked-articles info))
;; Kludge to avoid having cached articles nixed out in virtual groups.
- (when (gnus-virtual-group-p group)
- (setq cached gnus-newsgroup-cached))
+ (setq cached
+ (if (gnus-virtual-group-p group)
+ gnus-newsgroup-cached
+ (gnus-cache-articles-in-group group)))
(setq gnus-newsgroup-unreads
(gnus-set-difference
;; Retrieve the headers and read them in.
(gnus-message 5 "Fetching headers for %s..." gnus-newsgroup-name)
(setq gnus-newsgroup-headers
- (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" gnus-newsgroup-name)
- ;; Kludge to avoid having cached articles nixed out in virtual groups.
- (when cached
- (setq gnus-newsgroup-cached cached))
-
;; Suppress duplicates?
(when gnus-suppress-duplicates
(gnus-dup-suppress-articles))
;; Removed marked articles that do not exist.
(gnus-update-missing-marks
(gnus-sorted-complement fetched-articles articles))
+
+ ;; Kludge to avoid having cached articles nixed out in virtual groups.
+ (when cached
+ (setq gnus-newsgroup-cached cached))
+
;; We might want to build some more threads first.
(when (and gnus-fetch-old-headers
(eq gnus-headers-retrieved-by 'nov))
(condition-case ()
(cond
((and (or (<= scored marked) (= scored number))
- (numberp gnus-large-newsgroup)
+ (natnump gnus-large-newsgroup)
(> number gnus-large-newsgroup))
- (let ((input
- (read-string
- (format
- "How many articles from %s (default %d): "
- (gnus-limit-string gnus-newsgroup-name 35)
- number))))
- (if (string-match "^[ \t]*$" input) number input)))
+ (let* ((minibuffer-setup-hook (append
+ minibuffer-setup-hook
+ '(beginning-of-line)))
+ (input (read-string
+ (format
+ "How many articles from %s (max %d): "
+ (gnus-limit-string gnus-newsgroup-name 35)
+ number)
+ (number-to-string gnus-large-newsgroup))))
+ (if (string-match "^[ \t]*$" input)
+ number
+ input)))
((and (> scored marked) (< scored number)
(> (- scored number) 20))
(let ((input
out))
(defun gnus-adjust-marked-articles (info)
- "Set all article lists and remove all marks that are no longer legal."
+ "Set all article lists and remove all marks that are no longer valid."
(let* ((marked-lists (gnus-info-marks info))
(active (gnus-active (gnus-info-group info)))
(min (car active))
(uncompressed '(score bookmark killed))
type list newmarked symbol delta-marks)
(when info
- ;; Add all marks lists that are non-nil to the list of marks lists.
+ ;; Add all marks lists to the list of marks lists.
(while (setq type (pop types))
- (when (setq list (symbol-value
+ (setq list (symbol-value
(setq symbol
(intern (format "gnus-newsgroup-%s"
(car type))))))
+ (when list
;; Get rid of the entries of the articles that have the
;; default score.
(when (and (eq (cdr type) 'score)
(setcdr prev (cdr arts))
(setq prev arts))
(setq arts (cdr arts)))
- (setq list (cdr all))))
-
+ (setq list (cdr all)))))
+
+ (when (gnus-check-backend-function 'request-set-mark
+ gnus-newsgroup-name)
+ ;; uncompressed:s are not proper flags (they are cons cells)
+ ;; cache is a internal gnus flag
+ (unless (memq (cdr type) (cons 'cache uncompressed))
+ (let* ((old (cdr (assq (cdr type) (gnus-info-marks info))))
+ (list (gnus-compress-sequence (sort list '<)))
+ (del (gnus-remove-from-range old list))
+ (add (gnus-remove-from-range list old)))
+ (if add
+ (push (list add 'add (list (cdr type))) delta-marks))
+ (if del
+ (push (list del 'del (list (cdr type))) delta-marks)))))
+
+ (when list
(push (cons (cdr type)
(if (memq (cdr type) uncompressed) list
(gnus-compress-sequence
(set symbol (sort list '<)) t)))
newmarked)))
+
+ (when delta-marks
+ (unless (gnus-check-group gnus-newsgroup-name)
+ (error "Can't open server for %s" gnus-newsgroup-name))
+ (gnus-request-set-mark gnus-newsgroup-name delta-marks))
+
;; Enter these new marks into the info of the group.
(if (nthcdr 3 info)
(setcar (nthcdr 3 info) newmarked)
;; We might have to chop a bit of the string off...
(when (> (length mode-string) max-len)
(setq mode-string
- (concat (truncate-string-to-width mode-string (- max-len 3))
+ (concat (gnus-truncate-string mode-string (- max-len 3))
"...")))
;; Pad the mode string a bit.
(setq mode-string (format (format "%%-%ds" max-len) mode-string))))
(active (gnus-active group))
ninfo)
(when entry
- ;; First peel off all illegal article numbers.
+ ;; First peel off all invalid article numbers.
(when active
(let ((ids articles)
id first)
;; Update the group buffer.
(gnus-group-update-group group t)))))
-(defun gnus-methods-equal-p (m1 m2)
- (let ((m1 (or m1 gnus-select-method))
- (m2 (or m2 gnus-select-method)))
- (or (equal m1 m2)
- (and (eq (car m1) (car m2))
- (or (not (memq 'address (assoc (symbol-name (car m1))
- gnus-valid-select-methods)))
- (equal (nth 1 m1) (nth 1 m2)))))))
-
(defvar gnus-newsgroup-none-id 0)
(defun gnus-get-newsgroup-headers (&optional dependencies force-new)
(or dependencies
(save-excursion (set-buffer gnus-summary-buffer)
gnus-newsgroup-dependencies)))
- headers id end ref)
+ headers id end ref
+ (mail-parse-charset gnus-newsgroup-charset))
(save-excursion
(set-buffer nntp-server-buffer)
;; Translate all TAB characters into SPACE characters.
(subst-char-in-region (point-min) (point-max) ?\r ? t)
(gnus-run-hooks 'gnus-parse-headers-hook)
(let ((case-fold-search t)
- in-reply-to header p lines chars)
+ in-reply-to header p lines chars ctype)
(goto-char (point-min))
;; Search to the beginning of the next header. Error messages
;; do not begin with 2 or 3.
;; doesn't always go hand in hand.
(setq
header
- (vector
+ (make-full-mail-header
;; Number.
(prog1
(read cur)
(progn
(goto-char p)
(if (search-forward "\nsubject: " nil t)
- (funcall gnus-decode-encoded-word-function
- (nnheader-header-value))
+ (buffer-substring (match-end 0) (std11-field-end))
"(none)"))
;; From.
(progn
(goto-char p)
(if (search-forward "\nfrom: " nil t)
- (funcall gnus-decode-encoded-word-function
- (nnheader-header-value))
+ (buffer-substring (match-end 0) (std11-field-end))
"(nobody)"))
;; Date.
(progn
(goto-char p)
(if (search-forward "\ndate: " nil t)
- (nnheader-header-value) ""))
+ (buffer-substring (match-end 0) (std11-field-end))
+ ""))
;; Message-ID.
(progn
(goto-char p)
(progn
(setq end (point))
(prog1
- (nnheader-header-value)
+ (buffer-substring (match-end 0) (std11-field-end))
(setq ref
(buffer-substring
(progn
- (end-of-line)
+ ;; (end-of-line)
(search-backward ">" end t)
(1+ (point)))
(progn
;; were no references and the in-reply-to header looks
;; promising.
(if (and (search-forward "\nin-reply-to: " nil t)
- (setq in-reply-to (nnheader-header-value))
+ (setq in-reply-to
+ (buffer-substring (match-end 0)
+ (std11-field-end)))
(string-match "<[^>]+>" in-reply-to))
(let (ref2)
(setq ref (substring in-reply-to (match-beginning 0)
(progn
(goto-char p)
(and (search-forward "\nxref: " nil t)
- (nnheader-header-value)))
+ (buffer-substring (match-end 0) (std11-field-end))))
;; Extra.
(when gnus-extra-headers
(let ((extra gnus-extra-headers)
(goto-char p)
(when (search-forward
(concat "\n" (symbol-name (car extra)) ": ") nil t)
- (push (cons (car extra) (nnheader-header-value))
+ (push (cons (car extra)
+ (buffer-substring (match-end 0)
+ (std11-field-end)))
out))
(pop extra))
out))))
+ (goto-char p)
+ (if (and (search-forward "\ncontent-type: " nil t)
+ (setq ctype
+ (buffer-substring (match-end 0) (std11-field-end))))
+ (mime-entity-set-content-type-internal
+ header (mime-parse-Content-Type ctype)))
(when (equal id ref)
(setq ref nil))
;; Get the Xref when the users reads the articles since most/some
;; NNTP servers do not include Xrefs when using XOVER.
(setq gnus-article-internal-prepare-hook '(gnus-article-get-xrefs))
- (let ((cur nntp-server-buffer)
+ (let ((mail-parse-charset gnus-newsgroup-charset)
+ (cur nntp-server-buffer)
(dependencies (or dependencies gnus-newsgroup-dependencies))
number headers header)
(save-excursion
(let ((gnus-nov-is-evil t))
(nconc
(nreverse headers)
- (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.
(let ((max (max (point) (mark)))
articles article)
(save-excursion
- (goto-char (min (min (point) (mark))))
+ (goto-char (min (point) (mark)))
(while
(and
(push (setq article (gnus-summary-article-number)) articles)
(redraw-display))
(defun gnus-summary-reselect-current-group (&optional all rescan)
- "Exit and then reselect the current newsgroup.
+ "Rescan the current newsgroup, exit and then reselect it.
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))
(group gnus-newsgroup-name))
+ (save-excursion
+ (set-buffer gnus-group-buffer)
+ ;; We have to adjust the point of group mode buffer because
+ ;; point was moved to the next unread newsgroup by exiting.
+ (gnus-summary-jump-to-group group)
+ (when rescan
+ (save-excursion
+ (gnus-group-get-new-news-this-group 1))))
(setq gnus-newsgroup-begin nil)
(gnus-summary-exit)
- ;; We have to adjust the point of group mode buffer because
- ;; point was moved to the next unread newsgroup by exiting.
- (gnus-summary-jump-to-group group)
- (when rescan
- (save-excursion
- (gnus-group-get-new-news-this-group 1)))
- (gnus-group-read-group all t)
+ (gnus-group-read-group all t group)
(gnus-summary-goto-subject current-subject nil t)))
(defun gnus-summary-rescan-group (&optional all)
(mode major-mode)
(group-point nil)
(buf (current-buffer)))
+ (unless quit-config
+ ;; Do adaptive scoring, and possibly save score files.
+ (when gnus-newsgroup-adaptive
+ (gnus-score-adaptive))
+ (when gnus-use-scoring
+ (gnus-score-save)))
(gnus-run-hooks 'gnus-summary-prepare-exit-hook)
;; If we have several article buffers, we kill them at exit.
(unless gnus-single-article-buffer
;; Make all changes in this group permanent.
(unless quit-config
(gnus-run-hooks 'gnus-exit-group-hook)
- (gnus-summary-update-info)
- ;; Do adaptive scoring, and possibly save score files.
- (when gnus-newsgroup-adaptive
- (gnus-score-adaptive))
- (when gnus-use-scoring
- (gnus-score-save)))
+ (gnus-summary-update-info))
(gnus-close-group group)
;; Make sure where we were, and go to next newsgroup.
(set-buffer gnus-group-buffer)
(setq group-point (point))
(if temporary
nil ;Nothing to do.
- (when (gnus-buffer-live-p gnus-article-buffer)
- (save-excursion
- (set-buffer gnus-article-buffer)
- (mm-destroy-parts gnus-article-mime-handles)))
;; If we have several article buffers, we kill them at exit.
(unless gnus-single-article-buffer
(gnus-kill-buffer gnus-article-buffer)
gnus-expert-user
(gnus-y-or-n-p "Discard changes to this group and exit? "))
(gnus-async-halt-prefetch)
- (gnus-run-hooks (delq 'gnus-summary-expire-articles
- (copy-list gnus-summary-prepare-exit-hook)))
- (when (gnus-buffer-live-p gnus-article-buffer)
- (save-excursion
- (set-buffer gnus-article-buffer)
- (mm-destroy-parts gnus-article-mime-handles)))
+ (mapcar 'funcall
+ (delq 'gnus-summary-expire-articles
+ (copy-list gnus-summary-prepare-exit-hook)))
;; If we have several article buffers, we kill them at exit.
(unless gnus-single-article-buffer
(gnus-kill-buffer gnus-article-buffer)
(gnus-summary-recenter)
(gnus-summary-position-point))))
+(defun gnus-summary-preview-mime-message ()
+ "MIME decode and play this message."
+ (interactive)
+ (let ((gnus-break-pages nil)
+ (gnus-show-mime t))
+ (gnus-summary-select-article gnus-show-all-headers t))
+ (select-window (get-buffer-window gnus-article-buffer)))
+
;;; Dead summaries.
(defvar gnus-dead-summary-mode-map nil)
(defun gnus-summary-describe-briefly ()
"Describe summary mode commands briefly."
(interactive)
- (gnus-message 6
- (substitute-command-keys "\\<gnus-summary-mode-map>\\[gnus-summary-next-page]:Select \\[gnus-summary-next-unread-article]:Forward \\[gnus-summary-prev-unread-article]:Backward \\[gnus-summary-exit]:Exit \\[gnus-info-find-node]:Run Info \\[gnus-summary-describe-briefly]:This help")))
+ (gnus-message 6 (substitute-command-keys "\\<gnus-summary-mode-map>\\[gnus-summary-next-page]:Select \\[gnus-summary-next-unread-article]:Forward \\[gnus-summary-prev-unread-article]:Backward \\[gnus-summary-exit]:Exit \\[gnus-info-find-node]:Run Info \\[gnus-summary-describe-briefly]:This help")))
;; Walking around group mode buffer from summary mode.
;; The requested article is different from the current article.
(prog1
(gnus-summary-display-article article all-headers)
- (setq did article))
+ (setq did article)
+ (when (or all-headers gnus-show-all-headers)
+ (gnus-article-show-all-headers)))
(when (or all-headers gnus-show-all-headers)
(gnus-article-show-all-headers))
'old))
(interactive)
(gnus-group-edit-group gnus-newsgroup-name 'params))
+(defun gnus-summary-customize-parameters ()
+ "Customize the group parameters of the current group."
+ (interactive)
+ (gnus-group-customize gnus-newsgroup-name))
+
(defun gnus-summary-enter-digest-group (&optional force)
"Enter an nndoc group based on the current article.
If FORCE, force a digest interpretation. If not, try
(gnus-xmas-force-redisplay nil) ;Inhibit XEmacs redisplay.
(gnus-use-trees nil) ;Inhibit updating tree buffer.
(sum (current-buffer))
- (gnus-display-mime-function nil)
(found nil)
point)
(gnus-save-hidden-threads
If N is negative, print the N previous articles. If N is nil and articles
have been marked with the process mark, print these instead.
-If the optional second argument FILENAME is nil, send the image to the
+If the optional first argument FILENAME is nil, send the image to the
printer. If FILENAME is a string, save the PostScript image in a file with
that name. If FILENAME is a number, prompt the user for the name of the file
to save in."
(if (not arg)
;; Select the article the normal way.
(gnus-summary-select-article nil 'force)
+ ;; We have to require this here to make sure that the following
+ ;; dynamic binding isn't shadowed by autoloading.
+ (require 'gnus-async)
+ (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-display-mime-function
gnus-break-pages
+ gnus-show-mime
gnus-visual)
(gnus-summary-select-article nil 'force)))
(gnus-summary-goto-subject gnus-current-article)
(interactive "P")
(save-excursion
(set-buffer gnus-article-buffer)
- (let* ((buffer-read-only nil)
- (inhibit-point-motion-hooks t)
- (hidden (text-property-any
- (goto-char (point-min)) (search-forward "\n\n")
- 'invisible t))
- e)
- (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)
+ (save-restriction
+ (let* ((buffer-read-only nil)
+ (inhibit-point-motion-hooks t)
+ hidden e)
+ (save-restriction
+ (article-narrow-to-head)
+ (setq hidden (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))
- (setq e (1- (or (search-forward "\n\n" nil t) (point-max)))))
- (insert-buffer-substring gnus-original-article-buffer 1 e)
- (let ((article-inhibit-hiding t))
- (gnus-run-hooks 'gnus-article-display-hook))
- (when (or (not hidden) (and (numberp arg) (< arg 0)))
- (gnus-article-hide-headers)))))
+ (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 (or hidden
+ (and (numberp arg) (< arg 0)))
+ (let ((gnus-treat-hide-headers nil)
+ (gnus-treat-hide-boring-headers nil))
+ (gnus-treat-article 'head))
+ (gnus-treat-article 'head)))))))
(defun gnus-summary-show-all-headers ()
"Make all header lines visible."
(interactive)
(gnus-article-show-all-headers))
+(defun gnus-summary-toggle-mime (&optional arg)
+ "Toggle MIME processing.
+If ARG is a positive number, turn MIME processing on."
+ (interactive "P")
+ (setq gnus-show-mime
+ (if (null arg)
+ (not gnus-show-mime)
+ (> (prefix-numeric-value arg) 0)))
+ (gnus-summary-select-article t 'force))
+
(defun gnus-summary-caesar-message (&optional arg)
"Caesar rotate the current article by 13.
The numerical prefix specifies how many places to rotate each letter
(crosspost "Crosspost" "Crossposting")))
(copy-buf (save-excursion
(nnheader-set-temp-buffer " *copy article*")))
+ (default-marks gnus-article-mark-lists)
+ (no-expire-marks (delete '(expirable . expire)
+ (copy-sequence gnus-article-mark-lists)))
art-group to-method new-xref article to-groups)
(unless (assq action names)
(error "Unknown action %s" action))
gnus-newsgroup-name)) ; Server
(list 'gnus-request-accept-article
to-newsgroup (list 'quote select-method)
- (not articles)) ; Accept form
+ (not articles) t) ; Accept form
(not articles))) ; Only save nov last time
;; Copy the article.
((eq action 'copy)
(list (cdr art-group)))))
;; Copy any marks over to the new group.
- (let ((marks gnus-article-mark-lists)
+ (let ((marks (if (gnus-group-auto-expirable-p to-group)
+ default-marks
+ no-expire-marks))
(to-article (cdr art-group)))
;; See whether the article is to be put in the cache.
(save-excursion
(set-buffer (gnus-get-buffer-create " *import file*"))
(erase-buffer)
- (insert-file-contents file)
+ (nnheader-insert-file-contents file)
(goto-char (point-min))
(unless (nnheader-article-p)
;; This doesn't look like an article, so we fudge some headers.
;; There are expirable articles in this group, so we run them
;; through the expiry process.
(gnus-message 6 "Expiring articles...")
+ (unless (gnus-check-group gnus-newsgroup-name)
+ (error "Can't open server for %s" gnus-newsgroup-name))
;; The list of articles that weren't expired is returned.
(save-excursion
(if expiry-wait
If FORCE is non-nil, allow editing of articles even in read-only
groups."
(interactive "P")
- (save-excursion
- (set-buffer gnus-summary-buffer)
- (gnus-set-global-variables)
- (when (and (not force)
- (gnus-group-read-only-p))
- (error "The current newsgroup does not support article editing"))
- ;; Select article if needed.
- (unless (eq (gnus-summary-article-number)
- gnus-current-article)
- (gnus-summary-select-article t))
- (gnus-article-date-original)
- (gnus-article-edit-article
- `(lambda (no-highlight)
- (gnus-summary-edit-article-done
- ,(or (mail-header-references gnus-current-headers) "")
- ,(gnus-group-read-only-p) ,gnus-summary-buffer no-highlight)))))
+ (let ((mail-parse-charset gnus-newsgroup-charset))
+ (save-excursion
+ (set-buffer gnus-summary-buffer)
+ (gnus-set-global-variables)
+ (when (and (not force)
+ (gnus-group-read-only-p))
+ (error "The current newsgroup does not support article editing"))
+ (gnus-summary-show-article t)
+ (gnus-article-edit-article
+ 'ignore
+ `(lambda (no-highlight)
+ (let ((mail-parse-charset ',gnus-newsgroup-charset))
+ (gnus-summary-edit-article-done
+ ,(or (mail-header-references gnus-current-headers) "")
+ ,(gnus-group-read-only-p) ,gnus-summary-buffer no-highlight)))))))
(defalias 'gnus-summary-edit-article-postpone 'gnus-article-edit-exit)
;; Replace the article.
(let ((buf (current-buffer)))
(with-temp-buffer
- (insert-buffer buf)
+ (insert-buffer-substring buf)
(if (and (not read-only)
(not (gnus-request-replace-article
(cdr gnus-article-current) (car gnus-article-current)
- (current-buffer)
- (not gnus-article-decoded-p))))
+ (current-buffer) t)))
(error "Couldn't replace article")
;; Update the summary buffer.
(if (and references
(unless no-highlight
(save-excursion
(set-buffer gnus-article-buffer)
- (gnus-run-hooks 'gnus-article-display-hook)
+ ;;;!!! Fix this -- article should be rehighlighted.
+ ;;;(gnus-run-hooks 'gnus-article-display-hook)
(set-buffer gnus-original-article-buffer)
(gnus-request-article
(cdr gnus-article-current)
(setq mark (gnus-request-update-mark gnus-newsgroup-name article mark))
;; Check for auto-expiry.
(when (and gnus-newsgroup-auto-expire
- (or (= mark gnus-killed-mark) (= mark gnus-del-mark)
- (= mark gnus-catchup-mark) (= mark gnus-low-score-mark)
- (= mark gnus-ancient-mark)
- (= mark gnus-read-mark) (= mark gnus-souped-mark)
- (= mark gnus-duplicate-mark)))
+ (memq mark gnus-auto-expirable-marks))
(setq mark gnus-expirable-mark)
;; Let the backend know about the mark change.
(setq mark (gnus-request-update-mark gnus-newsgroup-name article mark))
"Mark ARTICLE with MARK. MARK can be any character.
Four MARK strings are reserved: `? ' (unread), `?!' (ticked),
`??' (dormant) and `?E' (expirable).
-If MARK is nil, then the default character `?D' is used.
+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."
;; The mark might be a string.
(when (stringp mark)
(setq mark (aref mark 0)))
;; If no mark is given, then we check auto-expiring.
- (and (not no-expire)
- gnus-newsgroup-auto-expire
- (or (not mark)
- (and (gnus-characterp mark)
- (or (= mark gnus-killed-mark) (= mark gnus-del-mark)
- (= mark gnus-catchup-mark) (= mark gnus-low-score-mark)
- (= mark gnus-read-mark) (= mark gnus-souped-mark)
- (= mark gnus-duplicate-mark))))
- (setq mark gnus-expirable-mark))
- (let* ((mark (or mark gnus-del-mark))
- (article (or article (gnus-summary-article-number)))
- (old-mark (gnus-summary-article-mark article)))
+ (when (null mark)
+ (setq mark gnus-del-mark))
+ (when (and (not no-expire)
+ gnus-newsgroup-auto-expire
+ (memq mark gnus-auto-expirable-marks))
+ (setq mark gnus-expirable-mark))
+ (let ((article (or article (gnus-summary-article-number)))
+ (old-mark (gnus-summary-article-mark article)))
;; Allow the backend to change the mark.
(setq mark (gnus-request-update-mark gnus-newsgroup-name article mark))
(if (eq mark old-mark)
The difference between N and the actual number of articles marked is
returned."
(interactive "p")
- (gnus-summary-mark-forward n gnus-del-mark t))
+ (gnus-summary-mark-forward n gnus-del-mark gnus-inhibit-user-auto-expire))
(defun gnus-summary-mark-as-read-backward (n)
"Mark the N articles as read backwards.
The difference between N and the actual number of articles marked is
returned."
(interactive "p")
- (gnus-summary-mark-forward (- n) gnus-del-mark t))
+ (gnus-summary-mark-forward
+ (- n) gnus-del-mark gnus-inhibit-user-auto-expire))
(defun gnus-summary-mark-as-read (&optional article mark)
"Mark current article as read.
(gnus-summary-article-header parent-article))))
(unless (and message-id (not (equal message-id "")))
(error "No message-id in desired parent"))
- ;; We don't want the article to be marked as read.
- (let (gnus-mark-article-hook)
- (gnus-summary-select-article t t nil current-article))
- (set-buffer gnus-original-article-buffer)
- (let ((buf (format "%s" (buffer-string))))
- (with-temp-buffer
- (insert buf)
- (goto-char (point-min))
- (if (re-search-forward "^References: " nil t)
- (progn
- (re-search-forward "^[^ \t]" nil t)
- (forward-line -1)
- (end-of-line)
- (insert " " message-id))
- (insert "References: " message-id "\n"))
- (unless (gnus-request-replace-article
- current-article (car gnus-article-current)
- (current-buffer))
- (error "Couldn't replace article"))))
+ (gnus-with-article current-article
+ (goto-char (point-min))
+ (if (re-search-forward "^References: " nil t)
+ (progn
+ (re-search-forward "^[^ \t]" nil t)
+ (forward-line -1)
+ (end-of-line)
+ (insert " " message-id))
+ (insert "References: " message-id "\n")))
(set-buffer gnus-summary-buffer)
(gnus-summary-unmark-all-processable)
(gnus-summary-update-article current-article)
(gnus-summary-sort 'score reverse))
(defun gnus-summary-sort-by-lines (&optional reverse)
- "Sort the summary buffer by article length.
+ "Sort the summary buffer by the number of lines.
Argument REVERSE means reverse order."
(interactive "P")
(gnus-summary-sort 'lines reverse))
+(defun gnus-summary-sort-by-chars (&optional reverse)
+ "Sort the summary buffer by article length.
+Argument REVERSE means reverse order."
+ (interactive "P")
+ (gnus-summary-sort 'chars reverse))
+
(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)))
(article (intern (format "gnus-article-sort-by-%s" predicate)))
(gnus-thread-sort-functions
- (list
- (if (not reverse)
- thread
- `(lambda (t1 t2)
- (,thread t2 t1)))))
+ (if (not reverse)
+ thread
+ `(lambda (t1 t2)
+ (,thread t2 t1))))
(gnus-article-sort-functions
- (list
- (if (not reverse)
- article
- `(lambda (t1 t2)
- (,article t2 t1)))))
+ (if (not reverse)
+ article
+ `(lambda (t1 t2)
+ (,article t2 t1))))
(buffer-read-only)
(gnus-summary-prepare-hook nil))
;; We do the sorting by regenerating the threads.
(save-buffer (save-excursion
(nnheader-set-temp-buffer " *Gnus Save*")))
(num (length articles))
- header article file)
- (while articles
- (setq header (gnus-summary-article-header
- (setq article (pop articles))))
+ header file)
+ (dolist (article articles)
+ (setq header (gnus-summary-article-header article))
(if (not (vectorp header))
;; This is a pseudo-article.
(if (assq 'name header)
If N is nil and any articles have been marked with the process mark,
save those articles instead."
(interactive "P")
- (let ((gnus-default-article-saver 'rmail-output-to-rmail-file))
+ (let ((gnus-default-article-saver 'gnus-summary-save-in-rmail))
(gnus-summary-save-article arg)))
(defun gnus-summary-save-article-file (&optional arg)
split-name))
((consp result)
(setq split-name (append result split-name)))))))))
- split-name))
+ (nreverse split-name)))
(defun gnus-valid-move-group-p (group)
(and (boundp group)
(lambda (f)
(if (equal f " ")
f
- (mm-quote-arg f)))
+ (gnus-quote-arg-for-sh-or-csh f)))
files " ")))))
(setq ps (cdr ps)))))
(if (and gnus-view-pseudos (not not-view))
(gnus-info-set-read ',info ',(gnus-info-read info))
(gnus-get-unread-articles-in-group ',info (gnus-active ,group))
(gnus-group-update-group ,group t))))
+ ;; Propagate the read marks to the backend.
+ (if (gnus-check-backend-function 'request-set-mark group)
+ (let ((del (gnus-remove-from-range (gnus-info-read info) read))
+ (add (gnus-remove-from-range read (gnus-info-read info))))
+ (when (or add del)
+ (unless (gnus-check-group group)
+ (error "Can't open server for %s" group))
+ (gnus-request-set-mark
+ group (delq nil (list (if add (list add 'add '(read)))
+ (if del (list del 'del '(read)))))))))
;; Enter this list into the group info.
(gnus-info-set-read info read)
;; Set the number of unread articles in gnus-newsrc-hashtb.
(gnus-summary-exit))
buffers)))))
+
+;;; @ for mime-partial
+;;;
+
+(defun gnus-request-partial-message ()
+ (save-excursion
+ (let ((number (gnus-summary-article-number))
+ (group gnus-newsgroup-name)
+ (mother gnus-article-buffer))
+ (set-buffer (get-buffer-create " *Partial Article*"))
+ (erase-buffer)
+ (setq mime-preview-buffer mother)
+ (gnus-request-article-this-buffer number group)
+ (mime-parse-buffer)
+ )))
+
+(autoload 'mime-combine-message/partial-pieces-automatically
+ "mime-partial"
+ "Internal method to combine message/partial messages automatically.")
+
+(mime-add-condition
+ 'action '((type . message)(subtype . partial)
+ (major-mode . gnus-original-article-mode)
+ (method . mime-combine-message/partial-pieces-automatically)
+ (summary-buffer-exp . gnus-summary-buffer)
+ (request-partial-message-method . gnus-request-partial-message)
+ ))
+
+
+;;; @ for message/rfc822
+;;;
+
+(defun gnus-mime-extract-message/rfc822 (entity situation)
+ (let (group article num cwin swin cur)
+ (with-current-buffer (mime-entity-buffer entity)
+ (save-restriction
+ (narrow-to-region (mime-entity-body-start entity)
+ (mime-entity-body-end entity))
+ (setq group (or (cdr (assq 'group situation))
+ (completing-read "Group: "
+ gnus-active-hashtb
+ nil
+ (gnus-read-active-file-p)
+ gnus-newsgroup-name))
+ article (gnus-request-accept-article group)
+ )
+ ))
+ (when (and (consp article)
+ (numberp (setq article (cdr article))))
+ (setq num (1+ (or (cdr (assq 'number situation)) 0))
+ cwin (get-buffer-window (current-buffer) t)
+ )
+ (save-window-excursion
+ (if (setq swin (get-buffer-window gnus-summary-buffer t))
+ (select-window swin)
+ (set-buffer gnus-summary-buffer)
+ )
+ (setq cur gnus-current-article)
+ (forward-line num)
+ (let (gnus-show-threads)
+ (gnus-summary-goto-subject article t)
+ )
+ (gnus-summary-clear-mark-forward 1)
+ (gnus-summary-goto-subject cur)
+ )
+ (when (and cwin (window-frame cwin))
+ (select-frame (window-frame cwin))
+ )
+ (when (boundp 'mime-acting-situation-to-override)
+ (set-alist 'mime-acting-situation-to-override
+ 'group
+ group)
+ (set-alist 'mime-acting-situation-to-override
+ 'after-method
+ `(progn
+ (save-current-buffer
+ (set-buffer gnus-group-buffer)
+ (gnus-activate-group ,group)
+ )
+ (gnus-summary-goto-article ,cur
+ gnus-show-all-headers)
+ ))
+ (set-alist 'mime-acting-situation-to-override
+ 'number num)
+ )
+ )))
+
+(mime-add-condition
+ 'action '((type . message)(subtype . rfc822)
+ (major-mode . gnus-original-article-mode)
+ (method . gnus-mime-extract-message/rfc822)
+ (mode . "extract")
+ ))
+
+(mime-add-condition
+ 'action '((type . message)(subtype . news)
+ (major-mode . gnus-original-article-mode)
+ (method . gnus-mime-extract-message/rfc822)
+ (mode . "extract")
+ ))
+
+(defun gnus-mime-extract-multipart (entity situation)
+ (let ((children (mime-entity-children entity))
+ mime-acting-situation-to-override
+ f)
+ (while children
+ (mime-play-entity (car children)
+ (cons (assq 'mode situation)
+ mime-acting-situation-to-override))
+ (setq children (cdr children)))
+ (if (setq f (cdr (assq 'after-method
+ mime-acting-situation-to-override)))
+ (eval f)
+ )))
+
+(mime-add-condition
+ 'action '((type . multipart)
+ (method . gnus-mime-extract-multipart)
+ (mode . "extract")
+ )
+ 'with-default)
+
+
+;;; @ end
+;;;
+
+(defun gnus-summary-setup-default-charset ()
+ "Setup newsgroup default charset."
+ (let ((name (and gnus-newsgroup-name
+ (gnus-group-real-name gnus-newsgroup-name))))
+ (setq gnus-newsgroup-charset
+ (or (and gnus-newsgroup-name
+ (or (gnus-group-find-parameter gnus-newsgroup-name
+ 'charset)
+ (let ((alist gnus-group-charset-alist)
+ elem (charset nil))
+ (while (setq elem (pop alist))
+ (when (and name
+ (string-match (car elem) name))
+ (setq alist nil
+ charset (cadr elem))))
+ charset)))
+ gnus-default-charset))))
+
+;;;
+;;; Mime Commands
+;;;
+
+(defun gnus-summary-display-buttonized (&optional show-all-parts)
+ "Display the current article buffer fully MIME-buttonized.
+If SHOW-ALL-PARTS (the prefix) is non-nil, all multipart/* parts are
+treated as multipart/mixed."
+ (interactive "P")
+ (require 'gnus-art)
+ (let ((gnus-unbuttonized-mime-types nil)
+ (gnus-mime-display-multipart-as-mixed show-all-parts))
+ (gnus-summary-show-article)))
+
+(defun gnus-summary-repair-multipart (article)
+ "Add a Content-Type header to a multipart article without one."
+ (interactive (list (gnus-summary-article-number)))
+ (gnus-with-article article
+ (message-narrow-to-head)
+ (goto-char (point-max))
+ (widen)
+ (when (search-forward "\n--" nil t)
+ (let ((separator (buffer-substring (point) (gnus-point-at-eol))))
+ (message-narrow-to-head)
+ (message-remove-header "Mime-Version")
+ (message-remove-header "Content-Type")
+ (goto-char (point-max))
+ (insert (format "Content-Type: multipart/mixed; boundary=\"%s\"\n"
+ separator))
+ (insert "Mime-Version: 1.0\n")
+ (widen))))
+ (let (gnus-mark-article-hook)
+ (gnus-summary-select-article t t nil article)))
+
+(defun gnus-summary-toggle-display-buttonized ()
+ "Toggle the buttonizing of the article buffer."
+ (interactive)
+ (require 'gnus-art)
+ (if (setq gnus-inhibit-mime-unbuttonizing
+ (not gnus-inhibit-mime-unbuttonizing))
+ (let ((gnus-unbuttonized-mime-types nil))
+ (gnus-summary-show-article))
+ (gnus-summary-show-article)))
+
+;;;
+;;; with article
+;;;
+
+(defmacro gnus-with-article (article &rest forms)
+ "Select ARTICLE and perform FORMS in the original article buffer.
+Then replace the article with the result."
+ `(progn
+ ;; We don't want the article to be marked as read.
+ (let (gnus-mark-article-hook)
+ (gnus-summary-select-article t t nil ,article))
+ (set-buffer gnus-original-article-buffer)
+ ,@forms
+ (if (not (gnus-check-backend-function
+ 'request-replace-article (car gnus-article-current)))
+ (gnus-message 5 "Read-only group; not replacing")
+ (unless (gnus-request-replace-article
+ ,article (car gnus-article-current)
+ (current-buffer) t)
+ (error "Couldn't replace article")))
+ ;; The cache and backlog have to be flushed somewhat.
+ (when gnus-keep-backlog
+ (gnus-backlog-remove-article
+ (car gnus-article-current) (cdr gnus-article-current)))
+ (when gnus-use-cache
+ (gnus-cache-update-article
+ (car gnus-article-current) (cdr gnus-article-current)))))
+
+(put 'gnus-with-article 'lisp-indent-function 1)
+(put 'gnus-with-article 'edebug-form-spec '(form body))
+
+;;;
+;;; Generic summary marking commands
+;;;
+
+(defvar gnus-summary-marking-alist
+ '((read gnus-del-mark "d")
+ (unread gnus-unread-mark "u")
+ (ticked gnus-ticked-mark "!")
+ (dormant gnus-dormant-mark "?")
+ (expirable gnus-expirable-mark "e"))
+ "An alist of names/marks/keystrokes.")
+
+(defvar gnus-summary-generic-mark-map (make-sparse-keymap))
+(defvar gnus-summary-mark-map)
+
+(defun gnus-summary-make-all-marking-commands ()
+ (define-key gnus-summary-mark-map "M" gnus-summary-generic-mark-map)
+ (dolist (elem gnus-summary-marking-alist)
+ (apply 'gnus-summary-make-marking-command elem)))
+
+(defun gnus-summary-make-marking-command (name mark keystroke)
+ (let ((map (make-sparse-keymap)))
+ (define-key gnus-summary-generic-mark-map keystroke map)
+ (dolist (lway `((next "next" next nil "n")
+ (next-unread "next unread" next t "N")
+ (prev "previous" prev nil "p")
+ (prev-unread "previous unread" prev t "P")
+ (nomove "" nil nil ,keystroke)))
+ (let ((func (gnus-summary-make-marking-command-1
+ mark (car lway) lway name)))
+ (setq func (eval func))
+ (define-key map (nth 4 lway) func)))))
+
+(defun gnus-summary-make-marking-command-1 (mark way lway name)
+ `(defun ,(intern
+ (format "gnus-summary-put-mark-as-%s%s"
+ name (if (eq way 'nomove)
+ ""
+ (concat "-" (symbol-name way)))))
+ (n)
+ ,(format
+ "Mark the current article as %s%s.
+If N, the prefix, then repeat N times.
+If N is negative, move in reverse order.
+The difference between N and the actual number of articles marked is
+returned."
+ name (cadr lway))
+ (interactive "p")
+ (gnus-summary-generic-mark n ,mark ',(nth 2 lway) ,(nth 3 lway))))
+
+(defun gnus-summary-generic-mark (n mark move unread)
+ "Mark N articles with MARK."
+ (unless (eq major-mode 'gnus-summary-mode)
+ (error "This command can only be used in the summary buffer"))
+ (gnus-summary-show-thread)
+ (let ((nummove
+ (cond
+ ((eq move 'next) 1)
+ ((eq move 'prev) -1)
+ (t 0))))
+ (if (zerop nummove)
+ (setq n 1)
+ (when (< n 0)
+ (setq n (abs n)
+ nummove (* -1 nummove))))
+ (while (and (> n 0)
+ (gnus-summary-mark-article nil mark)
+ (zerop (gnus-summary-next-subject nummove unread t)))
+ (setq n (1- n)))
+ (when (/= 0 n)
+ (gnus-message 7 "No more %sarticles" (if mark "" "unread ")))
+ (gnus-summary-recenter)
+ (gnus-summary-position-point)
+ (gnus-set-mode-line 'summary)
+ n))
+
+(gnus-summary-make-all-marking-commands)
+
(gnus-ems-redefine)
(provide 'gnus-sum)