X-Git-Url: https://cgit.sxemacs.org/?a=blobdiff_plain;f=lisp%2Fgnus-sum.el;h=82d9d65e1a554cca6db85af6a1aafc2a14d7717b;hb=b44eabaf077673e60b8dfbfadaad18c402588241;hp=227fb58ece6432f291098c37de8d6db81cc5e175;hpb=2e33d39729730bd9b58520e013ce3e53250eeb15;p=gnus diff --git a/lisp/gnus-sum.el b/lisp/gnus-sum.el index 227fb58ec..82d9d65e1 100644 --- a/lisp/gnus-sum.el +++ b/lisp/gnus-sum.el @@ -1,5 +1,5 @@ ;;; gnus-sum.el --- summary mode commands for Gnus -;; Copyright (C) 1996,97,98 Free Software Foundation, Inc. +;; Copyright (C) 1996,97,98,99 Free Software Foundation, Inc. ;; Author: Lars Magne Ingebrigtsen ;; Keywords: news @@ -256,8 +256,8 @@ If this variable is `best', select the highest-scored unread article 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 @@ -310,6 +310,7 @@ and non-`vertical', do both horizontal and vertical recentering." :group 'gnus-summary-maneuvering :type '(choice (const :tag "none" nil) (const vertical) + (integer :tag "height") (sexp :menu-tag "both" t))) (defcustom gnus-show-all-headers nil @@ -344,7 +345,7 @@ 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) @@ -459,7 +460,7 @@ It uses the same syntax as the `gnus-split-methods' variable." :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) @@ -474,6 +475,19 @@ It uses the same syntax as the `gnus-split-methods' variable." :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 @@ -772,12 +786,35 @@ 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 + :type '(repeat symbol)) + +(defcustom gnus-ignored-from-addresses + (and user-mail-address (regexp-quote user-mail-address)) + "*Regexp of From headers that may be suppressed in favor of To headers." + :group 'gnus-summary + :type 'regexp) + +(defcustom gnus-group-charset-alist + '(("^hk\\>\\|^tw\\>\\|\\" cn-big5) + ("^cn\\>\\|\\" cn-gb-2312) + ("^fj\\>\\|^japan\\>" iso-2022-jp-2) + ("^relcom\\>" koi8-r) + (".*" iso-8859-1)) + "Alist of regexps (to match group names) and default charsets to be used." + :type '(repeat (list (regexp :tag "Group") + (symbol :tag "Charset"))) + :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) @@ -832,6 +869,7 @@ which it may alter in any way.") (?l (bbb-grouplens-score gnus-tmp-header) ?s) (?V (gnus-thread-total-score (and (boundp 'thread) (car thread))) ?d) (?U gnus-tmp-unread ?c) + (?f (gnus-summary-from-or-to-or-newsgroups gnus-tmp-header) ?s) (?t (gnus-summary-number-of-articles-in-thread (and (boundp 'thread) (car thread)) gnus-tmp-level) ?d) @@ -958,6 +996,7 @@ variable (string, integer, character, etc).") (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 @@ -989,7 +1028,8 @@ variable (string, integer, character, etc).") (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. @@ -997,22 +1037,42 @@ variable (string, integer, character, etc).") ;; MIME stuff. -(defvar gnus-encoded-word-method-alist - '(("chinese" mail-decode-encoded-word-string rfc1843-decode-string) - (".*" mail-decode-encoded-word-string)) - "Alist of regexps (to match group names) and lists of functions to be applied.") +(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-method-alist' that match." - (let ((alist gnus-encoded-word-method-alist) - elem) - (while (setq elem (pop alist)) - (when (string-match (car elem) gnus-newsgroup-name) - (pop elem) - (while elem - (setq string (funcall (pop elem) string))) - (setq alist nil))) - 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. @@ -1241,6 +1301,7 @@ increase the score of each group you read." "\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 @@ -1250,8 +1311,10 @@ increase the score of each group you read." "L" gnus-summary-lower-score "\M-i" gnus-symbolic-argument "h" gnus-summary-select-article-buffer + "b" gnus-article-view-part - + "\M-t" gnus-summary-toggle-display-buttonized + "V" gnus-summary-score-map "X" gnus-uu-extract-map "S" gnus-summary-send-map) @@ -1381,6 +1444,7 @@ increase the score of each group you read." "o" gnus-article-treat-overstrike "e" gnus-article-emphasize "w" gnus-article-fill-cited-article + "Q" gnus-article-fill-long-lines "c" gnus-article-remove-cr "q" gnus-article-de-quoted-unreadable "f" gnus-article-display-x-face @@ -1429,7 +1493,8 @@ increase the score of each group you read." "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 @@ -1463,7 +1528,17 @@ increase the score of each group you read." "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 + "|" gnus-article-pipe-part) + ) (defun gnus-summary-make-menu-bar () (gnus-turn-off-edit-menu 'summary) @@ -1532,11 +1607,13 @@ increase the score of each group you read." ["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] ["CR" gnus-article-remove-cr t] ["Show X-Face" gnus-article-display-x-face t] ["Quoted-Printable" gnus-article-de-quoted-unreadable t] @@ -1760,6 +1837,7 @@ increase the score of each group you read." ["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] @@ -1790,6 +1868,7 @@ increase the score of each group you read." ("article body" "body" string) ("article head" "head" string) ("xref" "xref" string) + ("extra header" "extra" string) ("lines" "lines" number) ("followups to author" "followup" string))) (types '((number ("less than" <) @@ -1904,8 +1983,6 @@ The following commands are available: (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) @@ -2325,7 +2402,8 @@ marks of articles." (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 @@ -2338,7 +2416,8 @@ marks of articles." 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) @@ -2357,7 +2436,8 @@ marks of articles." (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 () @@ -2387,7 +2467,7 @@ marks of articles." (let ((gnus-summary-line-format-spec spec) (gnus-newsgroup-downloadable '((0 . t)))) (gnus-summary-insert-line - [0 "" "" "" "" "" 0 0 ""] 0 nil 128 t nil "" nil 1) + [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))))) @@ -2411,6 +2491,30 @@ marks of articles." (point) (progn (eval gnus-summary-dummy-line-format-spec) (point)) (list 'gnus-number gnus-tmp-number 'gnus-intangible gnus-tmp-number))) +(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)))) + (mail-parse-charset gnus-newsgroup-charset)) + (cond + ((and to + gnus-ignored-from-addresses + (string-match gnus-ignored-from-addresses + (mail-header-from header))) + (concat "-> " + (or (car (funcall gnus-extract-address-components + (funcall + gnus-decode-encoded-word-function to))) + (funcall gnus-decode-encoded-word-function to)))) + ((and newsgroups + gnus-ignored-from-addresses + (string-match gnus-ignored-from-addresses + (mail-header-from header))) + (concat "=> " newsgroups)) + (t + (or (car (funcall gnus-extract-address-components + (mail-header-from header))) + (mail-header-from header)))))) + (defun gnus-summary-insert-line (gnus-tmp-header gnus-tmp-level gnus-tmp-current gnus-tmp-unread gnus-tmp-replied @@ -2424,7 +2528,7 @@ marks of articles." (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 @@ -2489,7 +2593,7 @@ marks of articles." (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)) @@ -2558,7 +2662,7 @@ If NO-DISPLAY, don't generate a summary buffer." kill-buffer no-display select-articles) (setq show-all nil - select-articles nil))))) + select-articles nil))))) (eq gnus-auto-select-next 'quietly)) (set-buffer gnus-group-buffer) ;; The entry function called above goes to the next @@ -3057,9 +3161,6 @@ Returns HEADER if it was entered in the DEPENDENCIES. Returns nil otherwise." (setq heads nil))))) gnus-newsgroup-dependencies))) -;; The following macros and functions were written by Felix Lee -;; . - (defmacro gnus-nov-read-integer () '(prog1 (if (eq (char-after) ?\t) @@ -3075,6 +3176,16 @@ Returns HEADER if it was entered in the DEPENDENCIES. Returns nil otherwise." (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) @@ -3103,7 +3214,8 @@ Returns HEADER if it was entered in the DEPENDENCIES. Returns nil otherwise." (gnus-nov-read-integer) ; chars (gnus-nov-read-integer) ; lines (unless (eq (char-after) ?\n) - (gnus-nov-field))))) ; misc + (gnus-nov-field)) ; misc + (gnus-nov-parse-extra)))) ; extra (widen)) @@ -3548,7 +3660,7 @@ Unscored articles will be counted as having a score of zero." (> (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) @@ -3579,6 +3691,12 @@ Unscored articles will be counted as having a score of zero." (defvar gnus-tmp-root-expunged nil) (defvar gnus-tmp-dummy-line nil) +(defvar gnus-tmp-header) +(defun gnus-extra-header (type &optional header) + "Return the extra header of TYPE." + (or (cdr (assq type (mail-header-extra (or header gnus-tmp-header)))) + "")) + (defun gnus-summary-prepare-threads (threads) "Prepare summary buffer from THREADS and indentation LEVEL. THREADS is either a list of `(PARENT [(CHILD1 [(GRANDCHILD ...]...) ...])' @@ -3776,7 +3894,7 @@ or a straight list of headers." (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 @@ -3895,6 +4013,7 @@ If SELECT-ARTICLES, only select those articles from GROUP." (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 @@ -4082,7 +4201,7 @@ If SELECT-ARTICLES, only select those articles from GROUP." 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)) @@ -4140,7 +4259,7 @@ If SELECT-ARTICLES, only select those articles from GROUP." (let ((types gnus-article-mark-lists) (info (gnus-get-info gnus-newsgroup-name)) (uncompressed '(score bookmark killed)) - type list newmarked symbol delta-marks) + type list newmarked symbol delta-marks) (when info ;; Add all marks lists that are non-nil to the list of marks lists. (while (setq type (pop types)) @@ -4165,12 +4284,28 @@ If SELECT-ARTICLES, only select those articles from GROUP." (setq arts (cdr arts))) (setq list (cdr all)))) + (when (gnus-check-backend-function 'request-set-mark + gnus-newsgroup-name) + ;; score & bookmark are not proper flags (they are cons cells) + ;; cache is a internal gnus flag + (unless (memq (cdr type) '(cache score bookmark)) + (let* ((old (cdr (assq (cdr type) (gnus-info-marks info)))) + (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))))) + (push (cons (cdr type) (if (memq (cdr type) uncompressed) list (gnus-compress-sequence (set symbol (sort list '<)) t))) newmarked))) + (if delta-marks + (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) @@ -4189,7 +4324,9 @@ If SELECT-ARTICLES, only select those articles from GROUP." "This function sets the mode line of the article or summary buffers. If WHERE is `summary', the summary mode line format will be used." ;; Is this mode line one we keep updated? - (when (memq where gnus-updated-mode-lines) + (when (and (memq where gnus-updated-mode-lines) + (symbol-value + (intern (format "gnus-%s-mode-line-format-spec" where)))) (let (mode-string) (save-excursion ;; We evaluate this in the summary buffer since these @@ -4239,7 +4376,7 @@ If WHERE is `summary', the summary mode line format will be used." ;; We might have to chop a bit of the string off... (when (> (length mode-string) max-len) (setq mode-string - (concat (truncate-string mode-string (- max-len 3)) + (concat (truncate-string-to-width mode-string (- max-len 3)) "..."))) ;; Pad the mode string a bit. (setq mode-string (format (format "%%-%ds" max-len) mode-string)))) @@ -4317,7 +4454,7 @@ The resulting hash table is returned, or nil if no Xrefs were found." (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) @@ -4403,11 +4540,13 @@ The resulting hash table is returned, or nil if no Xrefs were found." (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) ?\t ? t) + (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) @@ -4517,7 +4656,19 @@ The resulting hash table is returned, or nil if no Xrefs were found." (progn (goto-char p) (and (search-forward "\nxref: " nil t) - (nnheader-header-value))))) + (nnheader-header-value))) + ;; Extra. + (when gnus-extra-headers + (let ((extra gnus-extra-headers) + out) + (while extra + (goto-char p) + (when (search-forward + (concat "\n" (symbol-name (car extra)) ": ") nil t) + (push (cons (car extra) (nnheader-header-value)) + out)) + (pop extra)) + out)))) (when (equal id ref) (setq ref nil)) @@ -4543,11 +4694,13 @@ list of headers that match SEQUENCE (see `nntp-retrieve-headers')." ;; 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 (set-buffer nntp-server-buffer) + (subst-char-in-region (point-min) (point-max) ?\r ? t) ;; Allow the user to mangle the headers before parsing them. (gnus-run-hooks 'gnus-parse-headers-hook) (goto-char (point-min)) @@ -4616,14 +4769,14 @@ the subject line on." (let* ((line (and (numberp old-header) old-header)) (old-header (and (vectorp old-header) old-header)) (header (cond ((and old-header use-old-header) - old-header) - ((and (numberp id) - (gnus-number-to-header id)) - (gnus-number-to-header id)) - (t - (gnus-read-header id)))) - (number (and (numberp id) id)) - d) + old-header) + ((and (numberp id) + (gnus-number-to-header id)) + (gnus-number-to-header id)) + (t + (gnus-read-header id)))) + (number (and (numberp id) id)) + d) (when header ;; Rebuild the thread that this article is part of and go to the ;; article we have fetched. @@ -4865,7 +5018,9 @@ displayed, no centering will be performed." ;; Recenter only when requested. Suggested by popovich@park.cs.columbia.edu. (let* ((top (cond ((< (window-height) 4) 0) ((< (window-height) 7) 1) - (t 2))) + (t (if (numberp gnus-auto-center-summary) + gnus-auto-center-summary + 2)))) (height (1- (window-height))) (bottom (save-excursion (goto-char (point-max)) (forward-line (- height)) @@ -5077,6 +5232,10 @@ If FORCE (the prefix), also save the .newsrc file(s)." gnus-exit-group-hook is called with no arguments if that value is non-nil." (interactive) (gnus-set-global-variables) + (when (gnus-buffer-live-p gnus-article-buffer) + (save-excursion + (set-buffer gnus-article-buffer) + (mm-destroy-parts gnus-article-mime-handles))) (gnus-kill-save-kill-buffer) (gnus-async-halt-prefetch) (let* ((group gnus-newsgroup-name) @@ -5084,6 +5243,12 @@ gnus-exit-group-hook is called with no arguments if that value is non-nil." (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 @@ -5102,12 +5267,7 @@ gnus-exit-group-hook is called with no arguments if that value is non-nil." ;; 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) @@ -5122,10 +5282,6 @@ gnus-exit-group-hook is called with no arguments if that value is non-nil." (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) @@ -5169,8 +5325,9 @@ gnus-exit-group-hook is called with no arguments if that value is non-nil." 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))) + (mapcar 'funcall + (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) @@ -5343,8 +5500,7 @@ in." (defun gnus-summary-describe-briefly () "Describe summary mode commands briefly." (interactive) - (gnus-message 6 - (substitute-command-keys "\\\\[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-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. @@ -5564,7 +5720,9 @@ be displayed." ;; 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)) @@ -5858,9 +6016,9 @@ Return nil if there are no articles." (interactive) (prog1 (when (gnus-summary-first-subject) - (gnus-summary-show-thread) - (gnus-summary-first-subject) - (gnus-summary-display-article (gnus-summary-article-number))) + (gnus-summary-show-thread) + (gnus-summary-first-subject) + (gnus-summary-display-article (gnus-summary-article-number))) (gnus-summary-position-point))) (defun gnus-summary-best-unread-article () @@ -6500,6 +6658,11 @@ or `gnus-select-method', no matter what backend the article comes from." (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 @@ -6644,15 +6807,16 @@ Optional argument BACKWARD means do search for backward. ;; 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) (let ((gnus-select-article-hook nil) ;Disable hook. - (gnus-article-display-hook nil) (gnus-mark-article-hook nil) ;Inhibit marking as read. (gnus-use-article-prefetch nil) (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-display-mime-function) + point) (gnus-save-hidden-threads (gnus-summary-select-article) (set-buffer gnus-article-buffer) @@ -6821,14 +6985,22 @@ article massaging functions being run." (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-visual) + ;; Destroy any MIME parts. + (when (gnus-buffer-live-p gnus-article-buffer) + (save-excursion + (set-buffer gnus-article-buffer) + (mm-destroy-parts gnus-article-mime-handles))) (gnus-summary-select-article nil 'force))) (gnus-summary-goto-subject gnus-current-article) (gnus-summary-position-point)) @@ -6868,10 +7040,12 @@ If ARG is a negative number, hide the unwanted header lines." (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))))) + (narrow-to-region (point-min) (point)) + (if (or (not 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." @@ -6981,7 +7155,7 @@ and `request-accept' functions." 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) @@ -7358,7 +7532,7 @@ groups." ;; 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) @@ -7401,7 +7575,8 @@ groups." (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) @@ -7646,6 +7821,7 @@ If N is negative, mark backwards instead. Mark with MARK, ?r by default. The difference between N and the actual number of articles marked is returned." (interactive "p") + (gnus-summary-show-thread) (let ((backward (< n 0)) (gnus-summary-goto-unread (and gnus-summary-goto-unread @@ -7683,11 +7859,7 @@ returned." (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)) @@ -7738,25 +7910,21 @@ returned." "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) @@ -7808,19 +7976,19 @@ marked." (let ((forward (cdr (assq type gnus-summary-mark-positions))) (buffer-read-only nil)) (re-search-backward "[\n\r]" (gnus-point-at-bol) 'move-to-limit) - (when (looking-at "\r") - (incf forward)) - (when (and forward - (<= (+ forward (point)) (point-max))) - ;; Go to the right position on the line. - (goto-char (+ forward (point))) - ;; Replace the old mark with the new mark. - (subst-char-in-region (point) (1+ (point)) (char-after) mark) - ;; Optionally update the marks by some user rule. - (when (eq type 'unread) - (gnus-data-set-mark - (gnus-data-find (gnus-summary-article-number)) mark) - (gnus-summary-update-line (eq mark gnus-unread-mark)))))) + (when forward + (when (looking-at "\r") + (incf forward)) + (when (<= (+ forward (point)) (point-max)) + ;; Go to the right position on the line. + (goto-char (+ forward (point))) + ;; Replace the old mark with the new mark. + (subst-char-in-region (point) (1+ (point)) (char-after) mark) + ;; Optionally update the marks by some user rule. + (when (eq type 'unread) + (gnus-data-set-mark + (gnus-data-find (gnus-summary-article-number)) mark) + (gnus-summary-update-line (eq mark gnus-unread-mark))))))) (defun gnus-mark-article-as-read (article &optional mark) "Enter ARTICLE in the pertinent lists and remove it from others." @@ -7901,14 +8069,15 @@ If N is negative, mark backwards instead. 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. @@ -8191,25 +8360,15 @@ is non-nil or the Subject: of both articles are the same." (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) @@ -8453,17 +8612,15 @@ Argument 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. @@ -8624,6 +8781,7 @@ save those articles instead." (defun gnus-valid-move-group-p (group) (and (boundp group) (symbol-name group) + (symbol-value group) (memq 'respool (assoc (symbol-name (car (gnus-find-method-for-group @@ -8960,7 +9118,7 @@ save those articles instead." (push (cons prev (cdr active)) read)) (setq read (if (> (length read) 1) (nreverse read) read)) (if compute - read + read (save-excursion (set-buffer gnus-group-buffer) (gnus-undo-register @@ -8969,8 +9127,16 @@ save those articles instead." (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) + (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) + (gnus-info-set-read info read) ;; Set the number of unread articles in gnus-newsrc-hashtb. (gnus-get-unread-articles-in-group info (gnus-active group)) t)))) @@ -9003,6 +9169,67 @@ save those articles instead." (gnus-summary-exit)) buffers))))) +(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))) + (gnus-ems-redefine) (provide 'gnus-sum)