From: yamaoka Date: Thu, 22 Jan 2004 06:47:52 +0000 (+0000) Subject: Synch to No Gnus 200401220636. X-Git-Tag: t-gnus-6_17_4-quimby-~1115 X-Git-Url: http://git.chise.org/gitweb/?a=commitdiff_plain;h=6d10b2a907addb9acc61dff650adff0e182fb6ad;p=elisp%2Fgnus.git- Synch to No Gnus 200401220636. --- diff --git a/lisp/ChangeLog b/lisp/ChangeLog index 947021f..2b35e2a 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog @@ -1,3 +1,83 @@ +2004-01-22 Jesper Harder + + * spam-stat.el (spam-stat-strip-xref): New function. + (spam-stat-process-directory): Use it. + + * gnus-util.el (gnus-fetch-field): Don't bind case-fold-search + here -- it's done in message-fetch-field. + +2004-01-21 Kevin Greiner + + * gnus-agent.el (gnus-agent-queue-mail, + gnus-agent-prompt-send-queue): New variables. + (gnus-agent-send-mail): Use gnus-agent-queue-mail. + * gnus-draft.el (gnus-group-send-queue): Pass the group name + "nndraft:queue" along to gnus-draft-send. Use + gnus-agent-prompt-send-queue. + (gnus-draft-send): Rebind gnus-agent-queue-mail to nil when group + is "nndraft:queue". Suggested by Gaute Strokkenes + + + * gnus-agent.el (agent-disable-undownloaded-faces): Removed + (agent-enable-undownloaded-faces): Added + (gnus-agent-cat-groups): Use eval-and-compile, not + eval-when-compile, to define gnus-agent-set-cat-groups as the setf + method of gnus-agent-cat-groups even when the buffer has been + evaled. + (gnus-agent-save-active,gnus-agent-save-active-1): Merged to + delete gnus-agent-save-active-1. + (gnus-agent-save-groups): Deleted. Identical to + gnus-agent-save-active. + (gnus-agent-write-active): No longer adjust agent's copy of active + file as agent's adjustments are now stored in their own + file. Removed optional parameter. + (gnus-agent-possibly-alter-active): Ignore groups of unagentized + servers. Add use of min/max range limits from server's local + file. + (gnus-agent-save-alist): Removed unused optional argument. + (gnus-agent-load-local,gnus-agent-read-and-cache-local), + (gnus-agent-read-local,gnus-agent-save-local,gnus-agent-get-local), + (gnus-agent-set-local): A per-server file that keeps min/max range + limits for articles known to the agent. Provides a fast mechanism + for altering many active ranges. + (gnus-agent-expire-group,gnus-agent-expire): No longer save the + active file (local makes it unnecessary). + (gnus-agent-regenerate-group): Fixed XEmacs compatibility. + + * gnus-cus.el (agent-disable-undownloaded-faces): Removed + (agent-enable-undownloaded-faces): Added + + * gnus-draft.el (gnus-draft-send): Bind gnus-agent-queue-mail to + disable it when sending to "nndraft:queue". + (gnus-group-send-queue): Add safety check to avoid sending queue + when unplugged. + + * gnus-group.el (gnus-group-catchup): Use new + gnus-sequence-of-unread-articles, not + gnus-list-of-unread-articles, to avoid exhausting memory with huge + numbers of articles. Use gnus-range-map to avoid having to + uncompress the unread list. + (gnus-group-archive-directory, + gnus-group-recent-archive-directory): Fixed invalid ange-ftp + reference. + + * gnus-range.el (gnus-range-map): Iterate over list or sequence. + (gnus-sorted-range-intersection): Intersection of two ranges + without requiring that they first be uncompressed. + + * gnus-start.el (gnus-activate-group): Unless blocked by the + caller, possibly expand the active range to include both cached + and agentized articles. + (gnus-convert-old-newsrc): Rewrote in anticipation of having + multiple version-dependent converters. + (gnus-groups-to-gnus-format): Replaced gnus-agent-save-groups with + gnus-agent-save-active. + (gnus-save-newsrc-file): Save dirty agent range limits. + + * gnus-sum.el (gnus-select-newgroup): Replaced inline code with + gnus-agent-possibly-alter-active. + (gnus-adjust-marked-articles): Faster handling of simple lists + 2004-01-21 Jesper Harder * spam-stat.el (spam-stat-test-directory): New optional argument diff --git a/lisp/gnus-agent.el b/lisp/gnus-agent.el index e0e952b..955e4c8 100644 --- a/lisp/gnus-agent.el +++ b/lisp/gnus-agent.el @@ -199,6 +199,21 @@ See Info node `(gnus)Server Buffer'." :type '(repeat symbol) :group 'gnus-agent) +(defcustom gnus-agent-queue-mail t + "Whether and when outgoing mail should be queued by the agent. When +`always', always queue outgoing mail. When `nil', never queue. +Otherwise, queue if and only if unplugged." + :group 'gnus-agent + :type '(radio (const :format "Always" always) + (const :format "Never" nil) + (const :format "When plugged" t))) + +(defcustom gnus-agent-prompt-send-queue nil + "If non-nil, `gnus-group-send-queue' will prompt if called when +unplugged." + :group 'gnus-agent + :type 'boolean) + ;;; Internal variables (defvar gnus-agent-history-buffers nil) @@ -354,11 +369,9 @@ manipulated as follows: (gnus-agent-cat-defaccessor gnus-agent-cat-score-file agent-score-file) (gnus-agent-cat-defaccessor - gnus-agent-cat-disable-undownloaded-faces agent-disable-undownloaded-faces) -(gnus-agent-cat-defaccessor gnus-agent-cat-enable-undownloaded-faces agent-enable-undownloaded-faces) -(eval-when-compile +(eval-and-compile (defsetf gnus-agent-cat-groups (category) (groups) (list 'gnus-agent-set-cat-groups category groups))) @@ -654,7 +667,8 @@ Optional arg GROUP-NAME allows to specify another group." 'gnus-dummy '((gnus-draft-mode))))) (defun gnus-agent-send-mail () - (if gnus-plugged + (if (or (not gnus-agent-queue-mail) + (and gnus-plugged (not (eq gnus-agent-queue-mail 'always)))) (funcall gnus-agent-send-mail-function) (goto-char (point-min)) (re-search-forward @@ -1086,10 +1100,6 @@ Optional arg ALL, if non-nil, means to fetch all articles." (setq gnus-newsgroup-downloadable (delq article gnus-newsgroup-downloadable)) - ;; The downloadable mark is implemented as a - ;; type of read mark. Therefore, marking the - ;; article as unread is sufficient to clear - ;; its downloadable flag. (gnus-summary-mark-article article gnus-unread-mark)) (was-marked-downloadable (gnus-summary-set-agent-mark article t))) @@ -1114,89 +1124,75 @@ This can be added to `gnus-select-article-hook' or ;;; Internal functions ;;; -;;; NOTES: -;;; The agent's active range is defined as follows: -;;; If the agent has no record of the group, use the actual active -;;; range. -;;; If the agent has a record, set the agent's active range to -;;; include the max limit of the actual active range. -;;; When expiring, update the min limit to match the smallest of the -;;; min article not expired or the min actual active range. - (defun gnus-agent-save-active (method) - (gnus-agent-save-active-1 method 'gnus-active-to-gnus-format)) - -(defun gnus-agent-save-active-1 (method function) (when (gnus-agent-method-p method) (let* ((gnus-command-method method) (new (gnus-make-hashtable (count-lines (point-min) (point-max)))) (file (gnus-agent-lib-file "active"))) - (funcall function nil new) + (gnus-active-to-gnus-format nil new) (gnus-agent-write-active file new) (erase-buffer) (nnheader-insert-file-contents file)))) -(defun gnus-agent-write-active (file new &optional literal-replacement) - (let ((old new)) - (when (and (not literal-replacement) - (file-exists-p file)) - (setq old (gnus-make-hashtable (count-lines (point-min) (point-max)))) - (with-temp-buffer - (nnheader-insert-file-contents file) - (gnus-active-to-gnus-format nil old)) - ;; Iterate over the current active groups, the current active - ;; range may expand, but NOT CONTRACT, the agent's active range. - (mapatoms - (lambda (nsym) - (let ((new-active (and nsym (boundp nsym) (symbol-value nsym)))) - (when new-active - (let* ((osym (intern (symbol-name nsym) old)) - (old-active (and (boundp osym) (symbol-value osym)))) - (if old-active - (let ((new-min (car new-active)) - (old-min (car old-active)) - (new-max (cdr new-active)) - (old-max (cdr old-active))) - (if (and (integerp new-min) - (< new-min old-min)) - (setcar old-active new-min)) - (if (and (integerp new-max) - (> new-max old-max)) - (setcdr old-active new-max))) - (set osym new-active)))))) - new)) +(defun gnus-agent-write-active (file new) (gnus-make-directory (file-name-directory file)) (let ((nnmail-active-file-coding-system gnus-agent-file-coding-system)) ;; The hashtable contains real names of groups. However, do NOT ;; add the foreign server prefix as gnus-active-to-gnus-format ;; will add it while reading the file. - (gnus-write-active-file file old nil)))) + (gnus-write-active-file file new nil))) -(defun gnus-agent-possibly-alter-active (group active) +(defun gnus-agent-possibly-alter-active (group active &optional info) "Possibly expand a group's active range to include articles downloaded into the agent." - -;; I can't use the agent's active file here as there is no practical -;; mechanism to update the active ranges in that file as the oldest -;; articles are removed from the agent. (let* ((gnus-command-method (or gnus-command-method - (gnus-find-method-for-group group))) - (alist (gnus-agent-load-alist group))) - - (let ((new-min (or (caar gnus-agent-article-alist) - (car active))) - (new-max (or (caar (last gnus-agent-article-alist)) - (cdr active)))) - - (when (< new-min (car active)) - (setcar active new-min)) - (when (> new-max (cdr active)) - (setcdr active new-max))))) - -(defun gnus-agent-save-groups (method) - (gnus-agent-save-active-1 method 'gnus-groups-to-gnus-format)) + (gnus-find-method-for-group group)))) + (when (gnus-agent-method-p gnus-command-method) + (let* ((local (gnus-agent-get-local group)) + (active-min (car active)) + (active-max (cdr active)) + (agent-min (or (car local) active-min)) + (agent-max (or (cdr local) active-max))) + + (when (< agent-min active-min) + (setcar active agent-min)) + + (when (> agent-max active-max) + (setcdr active agent-max)) + + (when (and info (< agent-max (- active-min 100))) + ;; I'm expanding the active range by such a large amount + ;; that there is a gap of more than 100 articles between the + ;; last article known to the agent and the first article + ;; currently available on the server. This gap contains + ;; articles that have been lost, mark them as read so that + ;; gnus doesn't waste resources trying to fetch them. + + ;; NOTE: I don't do this for smaller gaps (< 100) as I don't + ;; want to modify the local file everytime someone restarts + ;; gnus. The small gap will cause a tiny performance hit + ;; when gnus tries, and fails, to retrieve the articles. + ;; Still that should be smaller than opening a buffer, + ;; printing this list to the buffer, and then writing it to a + ;; file. + + (let ((read (gnus-info-read info))) + (gnus-info-set-read + info + (gnus-range-add + read + (list (cons (1+ agent-max) + (1- active-min)))))) + + ;; Lie about the agent's local range for this group to + ;; disable the set read each time this server is opened. + ;; NOTE: Opening this group will restore the valid local + ;; range but it will also expand the local range to + ;; incompass the new active range. + (gnus-agent-set-local group agent-min (1- active-min))))))) (defun gnus-agent-save-group-info (method group active) + "Update a single group's active range in the agent's copy of the server's active file." (when (gnus-agent-method-p method) (let* ((gnus-command-method method) (coding-system-for-write nnheader-file-coding-system) @@ -1798,7 +1794,7 @@ FILE and places the combined headers into `nntp-server-buffer'." (gnus-agent-save-alist gnus-agent-read-agentview))) alist)))) -(defun gnus-agent-save-alist (group &optional articles state dir) +(defun gnus-agent-save-alist (group &optional articles state) "Save the article-state alist for GROUP." (let* ((file-name-coding-system nnmail-pathname-coding-system) (prev (cons nil gnus-agent-article-alist)) @@ -1817,12 +1813,13 @@ FILE and places the combined headers into `nntp-server-buffer'." (setcdr (cadr prev) state))) (setq prev (cdr prev))) (setq gnus-agent-article-alist (cdr all)) - (if dir - (gnus-make-directory dir) - (gnus-make-directory (gnus-agent-article-name "" group))) - (with-temp-file (if dir - (expand-file-name ".agentview" dir) - (gnus-agent-article-name ".agentview" group)) + + (gnus-agent-set-local group + (caar gnus-agent-article-alist) + (caar (last gnus-agent-article-alist))) + + (gnus-make-directory (gnus-agent-article-name "" group)) + (with-temp-file (gnus-agent-article-name ".agentview" group) (cond ((eq gnus-agent-article-alist-save-format 1) (princ gnus-agent-article-alist (current-buffer))) ((eq gnus-agent-article-alist-save-format 2) @@ -1848,6 +1845,138 @@ FILE and places the combined headers into `nntp-server-buffer'." (princ gnus-agent-article-alist-save-format (current-buffer)) (insert "\n")))) +(defvar gnus-agent-article-local nil) +(defvar gnus-agent-file-loading-local nil) + +(defun gnus-agent-load-local (&optional method) + "Load the METHOD'S local file. The local file contains min/max +article counts for each of the method's subscribed groups." + (let ((gnus-command-method (or method gnus-command-method))) + (setq gnus-agent-article-local + (gnus-cache-file-contents + (gnus-agent-lib-file "local") + 'gnus-agent-file-loading-local + 'gnus-agent-read-and-cache-local)))) + +(defun gnus-agent-read-and-cache-local (file) + "Load and read FILE then bind its contents to +gnus-agent-article-local. If that variable had `dirty' (also known as +modified) original contents, they are first saved to their own file." + + (if (and gnus-agent-article-local + (symbol-value (intern "+dirty" gnus-agent-article-local))) + (gnus-agent-save-local)) + (gnus-agent-read-local file)) + +(defun gnus-agent-read-local (file) + "Load FILE and do a `read' there." + (let ((obarray (gnus-make-hashtable (count-lines (point-min) (point-max)))) + (line 1)) + (with-temp-buffer + (condition-case nil + (nnheader-insert-file-contents file) + (file-error)) + + (goto-char (point-min)) + ;; Skip any comments at the beginning of the file (the only place where they may appear) + (while (= (following-char) ?\;) + (forward-line 1) + (setq line (1+ line))) + + (while (not (eobp)) + (condition-case err + (let (group + min + max + (cur (current-buffer))) + (setq group (read cur) + min (read cur) + max (read cur)) + + (when (stringp group) + (setq group (intern group obarray))) + + ;; NOTE: The '+ 0' ensure that min and max are both numerics. + (set group (cons (+ 0 min) (+ 0 max)))) + (error + (gnus-message 3 "Warning - invalid agent local: %s on line %d: " file line (error-message-string err)))) + (forward-line 1) + (setq line (1+ line)))) + + (set (intern "+dirty" obarray) nil) + (set (intern "+method" obarray) gnus-command-method) + obarray)) + +(defun gnus-agent-save-local (&optional force) + "Save gnus-agent-article-local under it method's agent.lib directory." + (let ((obarray gnus-agent-article-local)) + (when (and obarray + (or force (symbol-value (intern "+dirty" obarray)))) + (let* ((gnus-command-method (symbol-value (intern "+method" obarray))) + ;; NOTE: gnus-command-method is used within gnus-agent-lib-file. + (dest (gnus-agent-lib-file "local"))) + (gnus-make-directory (gnus-agent-lib-file "")) + (with-temp-file dest + (let ((gnus-command-method (symbol-value (intern "+method" obarray))) + (file-name-coding-system nnmail-pathname-coding-system) + (coding-system-for-write + gnus-agent-file-coding-system) + print-level print-length item article + (standard-output (current-buffer))) + (mapatoms (lambda (symbol) + (cond ((not (boundp symbol)) + nil) + ((member (symbol-name symbol) '("+dirty" "+method")) + nil) + (t + (prin1 symbol) + (let ((range (symbol-value symbol))) + (princ " ") + (princ (car range)) + (princ " ") + (princ (cdr range)) + (princ "\n")))))))))))) + +(defun gnus-agent-get-local (group) + (let* ((gmane (gnus-group-real-name group)) + (gnus-command-method (gnus-find-method-for-group group)) + (local (gnus-agent-load-local)) + (symb (intern gmane local)) + (minmax (and (boundp symb) (symbol-value symb)))) + (unless minmax + ;; Bind these so that gnus-agent-load-alist doesn't change the + ;; current alist (i.e. gnus-agent-article-alist) + (let* ((gnus-agent-article-alist gnus-agent-article-alist) + (gnus-agent-file-loading-cache gnus-agent-file-loading-cache) + (alist (gnus-agent-load-alist group))) + (when alist + (setq minmax + (cons (caar alist) + (caar (last alist)))) + (gnus-agent-set-local group (car minmax) (cdr minmax) + gmane gnus-command-method local)))) + minmax)) + +(defun gnus-agent-set-local (group min max &optional gmane method local) + (let* ((gmane (or gmane (gnus-group-real-name group))) + (gnus-command-method (or method (gnus-find-method-for-group group))) + (local (or local (gnus-agent-load-local))) + (symb (intern gmane local)) + (minmax (and (boundp symb) (symbol-value symb)))) + + (if (cond ((and minmax + (or (not (eq min (car minmax))) + (not (eq max (cdr minmax))))) + (setcar minmax min) + (setcdr minmax max) + t) + (minmax + nil) + (t + (set symb (cons min max)) + t)) + (set (intern "+dirty" local) t)))) + (defun gnus-agent-article-name (article group) (expand-file-name article (file-name-as-directory @@ -2607,8 +2736,7 @@ FORCE is equivalent to setting the expiration predicates to true." (save-excursion (gnus-agent-expire-group-1 group overview (gnus-gethash-safe group orig) - articles force)) - (gnus-agent-write-active active-file orig t))) + articles force)))) (kill-buffer overview)))) (gnus-message 4 (gnus-agent-expire-done-message))))) @@ -2928,12 +3056,7 @@ expiration tests failed." group article-number) (let ((inhibit-quit t)) (unless (equal alist gnus-agent-article-alist) (setq gnus-agent-article-alist alist) - (gnus-agent-save-alist group) - - ;; The active list changed, set the agent's active range - ;; to match the beginning of the list. - (if alist - (setcar active (caar alist)))) + (gnus-agent-save-alist group)) (when (buffer-modified-p) (gnus-make-directory dir) @@ -2992,8 +3115,7 @@ articles in every agentized group.")) (when active (save-excursion (gnus-agent-expire-group-1 - expiring-group overview active articles force))))) - (gnus-agent-write-active active-file orig t)))) + expiring-group overview active articles force)))))))) (kill-buffer overview)) (gnus-agent-expire-unagentized-dirs) (gnus-message 4 (gnus-agent-expire-done-message)))))) @@ -3335,16 +3457,19 @@ If REREAD is not nil, downloaded articles are marked as unread." def select))) (catch 'mark - (while (let ((c (read-char-exclusive - "Mark as unread: (n)one / (a)ll / all (d)ownloaded articles? (n)" - ))) + (while (let (c + (cursor-in-echo-area t) + (echo-keystrokes 0)) + (message "Mark as unread: (n)one / (a)ll / all (d)ownloaded articles? (n) ") + (setq c (read-char-exclusive)) + (cond ((or (eq c ?\r) (eq c ?n) (eq c ?N)) (throw 'mark nil)) ((or (eq c ?a) (eq c ?A)) (throw 'mark t)) ((or (eq c ?d) (eq c ?D)) (throw 'mark 'some))) - (message "Ignoring unexpected input") + (gnus-message 3 "Ignoring unexpected input") (sit-for 1) t))))) @@ -3514,17 +3639,7 @@ If REREAD is not nil, downloaded articles are marked as unread." (let ((group (gnus-group-real-name group)) (group-active (gnus-active group))) - (when group-active - (let ((new-min (or (caar gnus-agent-article-alist) - (car group-active))) - (new-max (or (caar (last gnus-agent-article-alist)) - (cdr group-active)))) - - (when (< new-min (car group-active)) - (setcar group-active new-min)) - - (when (> new-max (cdr group-active)) - (setcdr group-active new-max)))))))) + (gnus-agent-possibly-alter-active group group-active))))) (when (and reread gnus-agent-article-alist) (gnus-make-ascending-articles-unread diff --git a/lisp/gnus-cus.el b/lisp/gnus-cus.el index 7ebcce2..6298d75 100644 --- a/lisp/gnus-cus.el +++ b/lisp/gnus-cus.el @@ -313,15 +313,15 @@ has been stored locally for at least this many days." (const :format "Disable " DISABLE)) "\nEnable, or disable, agent expiration in this group or topic." gnus-agent-cat-enable-expiration) - (agent-disable-undownloaded-faces - (boolean :tag "Disable Agent Faces") - "Have the summary buffer ignore the agent's undownloaded faces. -These faces, when used, act as a warning that an article has not been -fetched into either the agent nor the cache. This is of most use to -users who use the agent as a cache (i.e. they only operate on articles -that have been downloaded). Disable to display normal article faces -even when the article hasn't been downloaded." - gnus-agent-cat-disable-undownloaded-faces)) + (agent-enable-undownloaded-faces + (boolean :tag "Enable Agent Faces") + "Have the summary buffer use the agent's undownloaded faces. +These faces, when enabled, act as a warning that an article has not +been fetched into either the agent nor the cache. This is of most use +to users who use the agent as a cache (i.e. they only operate on +articles that have been downloaded). Leave disabled to display normal +article faces even when the article hasn't been downloaded." +gnus-agent-cat-enable-undownloaded-faces)) "Alist of group parameters that are not also topic parameters. Each entry has the form (NAME TYPE DOC ACCESSOR), where NAME is the @@ -898,7 +898,7 @@ articles in the thread. (defvar gnus-agent-cat-days-until-old) (defvar gnus-agent-cat-predicate) (defvar gnus-agent-cat-groups) - (defvar gnus-agent-cat-disable-undownloaded-faces) + (defvar gnus-agent-cat-enable-undownloaded-faces) ) (defun gnus-trim-whitespace (s) @@ -1048,7 +1048,7 @@ articles in the thread. (widget-insert "\nVisual Settings ") - (gnus-agent-cat-prepare-category-field agent-disable-undownloaded-faces) + (gnus-agent-cat-prepare-category-field agent-enable-undownloaded-faces) (use-local-map widget-keymap) (widget-setup) diff --git a/lisp/gnus-draft.el b/lisp/gnus-draft.el index 1d87290..c941bb3 100644 --- a/lisp/gnus-draft.el +++ b/lisp/gnus-draft.el @@ -133,17 +133,20 @@ (defun gnus-draft-send (article &optional group interactive) "Send message ARTICLE." - (let ((message-syntax-checks (if interactive message-syntax-checks - 'dont-check-for-anything-just-trust-me)) - (message-hidden-headers nil) - (message-inhibit-body-encoding (or (not group) - (equal group "nndraft:queue") - message-inhibit-body-encoding)) - (message-send-hook (and group (not (equal group "nndraft:queue")) - message-send-hook)) - (message-setup-hook (and group (not (equal group "nndraft:queue")) - message-setup-hook)) - type method move-to) + (let* ((is-queue (or (not group) + (equal group "nndraft:queue"))) + (message-syntax-checks (if interactive message-syntax-checks + 'dont-check-for-anything-just-trust-me)) + (message-hidden-headers nil) + (message-inhibit-body-encoding (or is-queue + message-inhibit-body-encoding)) + (message-send-hook (and (not is-queue) + message-send-hook)) + (message-setup-hook (and (not is-queue) + message-setup-hook)) + (gnus-agent-queue-mail (and (not is-queue) + gnus-agent-queue-mail)) + type method move-to) (gnus-draft-setup article (or group "nndraft:queue")) ;; We read the meta-information that says how and where ;; this message is to be sent. @@ -197,22 +200,25 @@ (defun gnus-group-send-queue () "Send all sendable articles from the queue group." (interactive) - (gnus-activate-group "nndraft:queue") - (save-excursion - (let* ((articles (nndraft-articles)) - (unsendable (gnus-uncompress-range - (cdr (assq 'unsend - (gnus-info-marks - (gnus-get-info "nndraft:queue")))))) - (gnus-posting-styles nil) - (total (length articles)) - article) - (while (setq article (pop articles)) - (unless (memq article unsendable) - (let ((message-sending-message - (format "Sending message %d of %d..." - (- total (length articles)) total))) - (gnus-draft-send article))))))) + (when (or gnus-plugged + (not gnus-agent-prompt-send-queue) + (gnus-y-or-n-p "Gnus is unplugged; really send queue? ")) + (gnus-activate-group "nndraft:queue") + (save-excursion + (let* ((articles (nndraft-articles)) + (unsendable (gnus-uncompress-range + (cdr (assq 'unsend + (gnus-info-marks + (gnus-get-info "nndraft:queue")))))) + (gnus-posting-styles nil) + (total (length articles)) + article) + (while (setq article (pop articles)) + (unless (memq article unsendable) + (let ((message-sending-message + (format "Sending message %d of %d..." + (- total (length articles)) total))) + (gnus-draft-send article)))))))) ;;;###autoload (defun gnus-draft-reminder () diff --git a/lisp/gnus-group.el b/lisp/gnus-group.el index 4c5e6a1..5597079 100644 --- a/lisp/gnus-group.el +++ b/lisp/gnus-group.el @@ -44,13 +44,13 @@ (eval-when-compile (require 'mm-url)) (defcustom gnus-group-archive-directory - "*ftp@ftp.hpc.uh.edu:/pub/emacs/ding-list/" + "/ftp@ftp.hpc.uh.edu:/pub/emacs/ding-list/" "*The address of the (ding) archives." :group 'gnus-group-foreign :type 'directory) (defcustom gnus-group-recent-archive-directory - "*ftp@ftp.hpc.uh.edu:/pub/emacs/ding-list-recent/" + "/ftp@ftp.hpc.uh.edu:/pub/emacs/ding-list-recent/" "*The address of the most recent (ding) articles." :group 'gnus-group-foreign :type 'directory) @@ -3169,7 +3169,7 @@ or nil if no action could be taken." (let* ((entry (gnus-group-entry group)) (num (car entry)) (marks (gnus-info-marks (nth 2 entry))) - (unread (gnus-list-of-unread-articles group))) + (unread (gnus-sequence-of-unread-articles group))) ;; Remove entries for this group. (nnmail-purge-split-history (gnus-group-real-name group)) ;; Do the updating only if the newsgroup isn't killed. @@ -3182,16 +3182,17 @@ or nil if no action could be taken." 'del '(tick)) (list (cdr (assq 'dormant marks)) 'del '(dormant)))) - (setq unread (gnus-uncompress-range - (gnus-range-add (gnus-range-add - unread (cdr (assq 'dormant marks))) - (cdr (assq 'tick marks))))) + (setq unread (gnus-range-add (gnus-range-add + unread (cdr (assq 'dormant marks))) + (cdr (assq 'tick marks)))) (gnus-add-marked-articles group 'tick nil nil 'force) (gnus-add-marked-articles group 'dormant nil nil 'force)) ;; Do auto-expirable marks if that's required. (when (gnus-group-auto-expirable-p group) - (gnus-add-marked-articles group 'expire unread) - (gnus-request-set-mark group (list (list unread 'add '(expire))))) + (gnus-range-map (lambda (article) + (gnus-add-marked-articles group 'expire (list article)) + (gnus-request-set-mark group (list (list (list article) 'add '(expire))))) + unread)) (let ((gnus-newsgroup-name group)) (gnus-run-hooks 'gnus-group-catchup-group-hook)) num))) diff --git a/lisp/gnus-range.el b/lisp/gnus-range.el index fc151a2..ffe47c1 100644 --- a/lisp/gnus-range.el +++ b/lisp/gnus-range.el @@ -184,6 +184,43 @@ LIST1 and LIST2 have to be sorted over <." (nreverse out))) ;;;###autoload +(defun gnus-sorted-range-intersection (range1 range2) + "Return intersection of RANGE1 and RANGE2. +RANGE1 and RANGE2 have to be sorted over <." + (let* (out + (min1 (car range1)) + (max1 (if (numberp min1) min1 (prog1 (cdr min1) (setq min1 (car min1))))) + (min2 (car range2)) + (max2 (if (numberp min2) min2 (prog1 (cdr min2) (setq min2 (car min2)))))) + (setq range1 (cdr range1) + range2 (cdr range2)) + (while (and min1 min2) + (cond ((< max1 min2) ; range1 preceeds range2 + (setq range1 (cdr range1) + min1 nil)) + ((< max2 min1) ; range2 preceeds range1 + (setq range2 (cdr range2) + min2 nil)) + (t ; some sort of overlap is occurring + (let ((min (max min1 min2)) + (max (min max1 max2))) + (setq out (if (= min max) + (cons min out) + (cons (cons min max) out)))) + (if (< max1 max2) ; range1 ends before range2 + (setq min1 nil) ; incr range1 + (setq min2 nil)))) ; incr range2 + (unless min1 + (setq min1 (car range1) + max1 (if (numberp min1) min1 (prog1 (cdr min1) (setq min1 (car min1)))) + range1 (cdr range1))) + (unless min2 + (setq min2 (car range2) + max2 (if (numberp min2) min2 (prog1 (cdr min2) (setq min2 (car min2)))) + range2 (cdr range2)))) + (nreverse out))) + +;;;###autoload (defalias 'gnus-set-sorted-intersection 'gnus-sorted-nintersection) ;;;###autoload @@ -589,6 +626,18 @@ LIST is a sorted list." (setcdr prev (cons num list))) (cdr top))) +(defun gnus-range-map (func range) + "Apply FUNC to each value contained by RANGE." + (while range + (let ((span (pop range))) + (if (numberp span) + (funcall func span) + (let ((first (car span)) + (last (cdr span))) + (while (<= first last) + (funcall func first) + (setq first (1+ first)))))))) + (provide 'gnus-range) ;;; gnus-range.el ends here diff --git a/lisp/gnus-start.el b/lisp/gnus-start.el index 3542e31..dfb11dd 100644 --- a/lisp/gnus-start.el +++ b/lisp/gnus-start.el @@ -37,7 +37,12 @@ (require 'gnus-util) (autoload 'message-make-date "message") (autoload 'gnus-agent-read-servers-validate "gnus-agent") +(autoload 'gnus-agent-save-local "gnus-agent") (autoload 'gnus-agent-possibly-alter-active "gnus-agent") +(eval-when-compile + (defvar gnus-agent-covered-methods nil) + (defvar gnus-agent-file-loading-local nil) + (defvar gnus-agent-file-loading-cache nil)) (defcustom gnus-startup-file (nnheader-concat gnus-home-directory ".newsrc") "Your `.newsrc' file. @@ -681,6 +686,8 @@ the first newsgroup." (setq gnus-list-of-killed-groups nil gnus-have-read-active-file nil gnus-agent-covered-methods nil + gnus-agent-file-loading-local nil + gnus-agent-file-loading-cache nil gnus-server-method-cache nil gnus-newsrc-alist nil gnus-newsrc-hashtb nil @@ -1530,6 +1537,15 @@ newsgroup." (gnus-active group)) (gnus-active group) + ;; If a cache is present, we may have to alter the active info. + (when gnus-use-cache + (inline (gnus-cache-possibly-alter-active + group active))) + + ;; If the agent is enabled, we may have to alter the active info. + (when gnus-agent + (gnus-agent-possibly-alter-active group active)) + (gnus-set-active group active) ;; Return the new active info. active))))) @@ -1545,6 +1561,10 @@ newsgroup." (let* ((range (gnus-info-read info)) (num 0)) + + ;; These checks are present in gnus-activate-group but skipped + ;; due to setting dont-check in the preceeding call. + ;; If a cache is present, we may have to alter the active info. (when (and gnus-use-cache info) (inline (gnus-cache-possibly-alter-active @@ -1552,8 +1572,7 @@ newsgroup." ;; If the agent is enabled, we may have to alter the active info. (when (and gnus-agent info) - (gnus-agent-possibly-alter-active - (gnus-info-group info) active)) + (gnus-agent-possibly-alter-active (gnus-info-group info) active info)) ;; Modify the list of read articles according to what articles ;; are available; then tally the unread articles and add the @@ -2145,7 +2164,7 @@ newsgroup." (gnus-online method) (gnus-agent-method-p method)) (progn - (gnus-agent-save-groups method) + (gnus-agent-save-active method) (gnus-active-to-gnus-format method hashtb nil real-active)) (goto-char (point-min)) @@ -2214,6 +2233,85 @@ If FORCE is non-nil, the .newsrc file is read." (kill-buffer (current-buffer)) (gnus-message 5 "Reading %s...done" newsrc-file)))))) +(quote (;; T-gnus doesn't provide those functions. +(defun gnus-convert-old-newsrc () + "Convert old newsrc formats into the current format, if needed." + (let ((fcv (and gnus-newsrc-file-version + (gnus-continuum-version gnus-newsrc-file-version)))) + (when fcv + ;; A .newsrc.eld file was loaded. + (let ((converters + (sort + (mapcar (lambda (date-func) + (cons (gnus-continuum-version (car date-func)) + date-func)) + ;; This is a list of converters that must be run + ;; to bring the newsrc file up to the current + ;; version. If you create an incompatibility + ;; with older versions, you should create an + ;; entry here. The entry should consist of the + ;; current gnus version (hardcoded so that it + ;; doesn't change with each release) and the + ;; function that must be applied to convert the + ;; previous version into the current version. + '(("September Gnus v0.1" nil gnus-convert-old-ticks))) + #'car-less-than-car))) + ;; Skip converters older than the file version + (while (and converters (>= fcv (caar converters))) + (pop converters)) + + ;; Perform converters to bring older version up to date. + (when (and converters + (< fcv (caar converters))) + (while (let (c + (cursor-in-echo-area t) + (echo-keystrokes 0)) + (message "Convert newsrc from version '%s' to '%s'? (n/y/?)" + gnus-newsrc-file-version gnus-version) + (setq c (read-char-exclusive)) + + (cond ((or (eq c ?n) (eq c ?N)) + (error "Can not start gnus using old (unconverted) newsrc")) + ((or (eq c ?y) (eq c ?Y)) + nil) + ((eq c ?\?) + (message "This conversion is irreversible. \ + You should backup your files before proceeding.") + (sit-for 5) + t) + (t + (gnus-message 3 "Ignoring unexpected input") + (sit-for 3) + t)))) + (while (and converters (< fcv (caar converters))) + (let* ((converter (pop converters)) + (convert-to (nth 1 converter)) + (load-from (nth 2 converter)) + (func (nth 3 converter))) + (when (and load-from + (not (fboundp func))) + (load load-from t)) + (funcall func convert-to))) + (gnus-dribble-enter + (format ";Converted newsrc from version '%s' to '%s'? (n/y/?)" + gnus-newsrc-file-version gnus-version))))))) + +(defun gnus-convert-old-ticks (converting-to) + (let ((newsrc (cdr gnus-newsrc-alist)) + marks info dormant ticked) + (while (setq info (pop newsrc)) + (when (setq marks (gnus-info-marks info)) + (setq dormant (cdr (assq 'dormant marks)) + ticked (cdr (assq 'tick marks))) + (when (or dormant ticked) + (gnus-info-set-read + info + (gnus-add-to-range + (gnus-info-read info) + (nconc (gnus-uncompress-range dormant) + (gnus-uncompress-range ticked))))))))) +)) + (defun gnus-load (file &optional coding-system) "Load FILE, but in such a way that read errors can be reported." (with-temp-buffer @@ -2656,6 +2754,10 @@ If FORCE is non-nil, the .newsrc file is read." ;; from the variable gnus-newsrc-alist. (when (and (or gnus-newsrc-alist gnus-killed-list) gnus-current-startup-file) + ;; Save agent range limits for the currently active method. + (when gnus-agent + (gnus-agent-save-local force)) + (save-excursion (if (and (or gnus-use-dribble-file gnus-slave) (not force) @@ -2673,6 +2775,7 @@ If FORCE is non-nil, the .newsrc file is read." (gnus-message 8 "Saving %s..." gnus-current-startup-file) (gnus-gnus-to-newsrc-format) (gnus-message 8 "Saving %s...done" gnus-current-startup-file)) + ;; Save .newsrc.eld. (set-buffer (gnus-get-buffer-create " *Gnus-newsrc*")) (make-local-variable 'version-control) diff --git a/lisp/gnus-sum.el b/lisp/gnus-sum.el index 759f509..576e55a 100644 --- a/lisp/gnus-sum.el +++ b/lisp/gnus-sum.el @@ -5030,17 +5030,8 @@ If SELECT-ARTICLES, only select those articles from GROUP." group (gnus-status-message group))) (when gnus-agent - ;; The agent may be storing articles that are no longer in the - ;; server's active range. If that is the case, the active range - ;; needs to be expanded such that the agent's articles can be - ;; included in the summary. - (let* ((gnus-command-method (gnus-find-method-for-group group)) - (alist (gnus-agent-load-alist group)) - (active (gnus-active group))) - (if (and (car alist) - (< (caar alist) (car active))) - (gnus-set-active group (cons (caar alist) (cdr active))))) - + (gnus-agent-possibly-alter-active group (gnus-active group) info) + (setq gnus-summary-use-undownloaded-faces (gnus-agent-find-parameter group @@ -5369,7 +5360,8 @@ If SELECT-ARTICLES, only select those articles from GROUP." (min (car active)) (max (cdr active)) (types gnus-article-mark-lists) - marks var articles article mark mark-type) + marks var articles article mark mark-type + bgn end) (dolist (marks marked-lists) (setq mark (car marks) @@ -5379,13 +5371,34 @@ If SELECT-ARTICLES, only select those articles from GROUP." ;; We set the variable according to the type of the marks list, ;; and then adjust the marks to a subset of the active articles. (cond - ;; Adjust "simple" lists. + ;; Adjust "simple" lists - compressed yet unsorted ((eq mark-type 'list) - (set var (setq articles (gnus-uncompress-range (cdr marks)))) - (when (memq mark '(tick dormant expire reply save)) - (while articles - (when (or (< (setq article (pop articles)) min) (> article max)) - (set var (delq article (symbol-value var))))))) + ;; Simultaneously uncompress and clip to active range + (setq articles (cdr marks)) + (while (setq article (car articles)) + (when (cond ((consp article) + (setq bgn (max (car article) min) + end (min (cdr article) max)) + (if (> bgn end) + t ; range excluded - splice out of marks + (setcar articles bgn) ; First value replaces range. + (setq bgn (1+ bgn)) + (while (<= bgn end) + (setq articles (setcdr articles (cons bgn (cdr articles))) + bgn (1+ bgn))) + (setq articles (cdr articles)) + nil)) + ((or (< article min) + (> article max)) + t ; value excluded - splice out of marks + ) + (t + (setq articles (cdr articles)) + nil)) + ; perform slice to remove article + (setcar articles (cadr articles)) + (setcdr articles (cddr articles)))) + (set var (cdr marks))) ;; Adjust assocs. ((eq mark-type 'tuple) (set var (setq articles (cdr marks))) @@ -6314,15 +6327,15 @@ displayed, no centering will be performed." (while read (when first (while (< first nlast) - (push first unread) - (setq first (1+ first)))) + (setq unread (cons first unread) + first (1+ first)))) (setq first (1+ (if (atom (car read)) (car read) (cdar read)))) (setq nlast (if (atom (cadr read)) (cadr read) (caadr read))) (setq read (cdr read))))) ;; And add the last unread articles. (while (<= first last) - (push first unread) - (setq first (1+ first))) + (setq unread (cons first unread) + first (1+ first))) ;; Return the list of unread articles. (delq 0 (nreverse unread)))) @@ -6340,6 +6353,44 @@ displayed, no centering will be performed." (cdr (assq 'dormant marked))) (cdr (assq 'tick marked)))))) +;; This function returns a sequence of article numbers based on the +;; difference between the ranges of read articles in this group and +;; the range of active articles. +(defun gnus-sequence-of-unread-articles (group) + (let* ((read (gnus-info-read (gnus-get-info group))) + (active (or (gnus-active group) (gnus-activate-group group))) + (last (cdr active)) + first nlast unread) + ;; If none are read, then all are unread. + (if (not read) + (setq first (car active)) + ;; If the range of read articles is a single range, then the + ;; first unread article is the article after the last read + ;; article. Sounds logical, doesn't it? + (if (and (not (listp (cdr read))) + (or (< (car read) (car active)) + (progn (setq read (list read)) + nil))) + (setq first (max (car active) (1+ (cdr read)))) + ;; `read' is a list of ranges. + (when (/= (setq nlast (or (and (numberp (car read)) (car read)) + (caar read))) + 1) + (setq first (car active))) + (while read + (when first + (push (cons first nlast) unread)) + (setq first (1+ (if (atom (car read)) (car read) (cdar read)))) + (setq nlast (if (atom (cadr read)) (cadr read) (caadr read))) + (setq read (cdr read))))) + ;; And add the last unread articles. + (cond ((< first last) + (push (cons first last) unread)) + ((= first last) + (push first unread))) + ;; Return the sequence of unread articles. + (delq 0 (nreverse unread)))) + ;; Various summary commands (defun gnus-summary-select-article-buffer () diff --git a/lisp/gnus-util.el b/lisp/gnus-util.el index 60fff97..6021b19 100644 --- a/lisp/gnus-util.el +++ b/lisp/gnus-util.el @@ -195,8 +195,7 @@ is slower." "Return the value of the header FIELD of current article." (save-excursion (save-restriction - (let ((case-fold-search t) - (inhibit-point-motion-hooks t)) + (let ((inhibit-point-motion-hooks t)) (nnheader-narrow-to-headers) (message-fetch-field field))))) diff --git a/lisp/spam-stat.el b/lisp/spam-stat.el index 3602a69..b7b7cd2 100644 --- a/lisp/spam-stat.el +++ b/lisp/spam-stat.el @@ -122,6 +122,7 @@ ;;; Code: +(require 'mail-parse) (defgroup spam-stat nil "Statistical spam detection for Emacs. @@ -471,6 +472,13 @@ check the variable `spam-stat-score-data'." ;; Testing +(defun spam-stat-strip-xref () + "Strip the the Xref header." + (save-restriction + (mail-narrow-to-head) + (when (re-search-forward "^Xref:.*\n" nil t) + (delete-region (match-beginning 0) (match-end 0))))) + (defun spam-stat-process-directory (dir func) "Process all the regular files in directory DIR using function FUNC." (let* ((files (directory-files dir t "^[^.]")) @@ -484,6 +492,7 @@ check the variable `spam-stat-score-data'." (setq count (1+ count)) (message "Reading %s: %.2f%%" dir (/ count max)) (insert-file-contents f) + (spam-stat-strip-xref) (funcall func) (erase-buffer)))))) diff --git a/texi/ChangeLog b/texi/ChangeLog index 48b3632..6af5a10 100644 --- a/texi/ChangeLog +++ b/texi/ChangeLog @@ -1,3 +1,12 @@ +2004-01-21 Kevin Greiner + + * gnus.texi (Outgoing Messages, Agent Variables): Add + gnus-agent-queue-mail and gnus-agent-prompt-send-queue. + Suggested by Gaute Strokkenes + + * gnus.texi (agent-disable-undownloaded-faces): Replaced with + agent-enable-undownloaded-faces + 2004-01-17 Jesper Harder * sieve.texi (Manage Sieve API): nil -> @code{nil}. diff --git a/texi/gnus-ja.texi b/texi/gnus-ja.texi index 9dd50f7..0065a5c 100644 --- a/texi/gnus-ja.texi +++ b/texi/gnus-ja.texi @@ -16867,54 +16867,48 @@ Commands}) $B$+!"$^$?$O%(!<%8%'%s%H$K07$C$FM_$7$/$J$$$N$K<+F0E*$KDI2C$5$l(B @cindex Agent Parameters @table @code -@item gnus-agent-cat-name +@item agent-cat-name $BJ,N`$NL>A0!#(B -@item gnus-agent-cat-groups +@item agent-groups $B$3$NJ,N`$K$"$k%0%k!<%W$N%j%9%H!#(B -@item gnus-agent-cat-predicate +@item agent-predicate ($BDL>o(B) $B$I$N5-;v$r%@%&%s%m!<%I$9$k$N$,E,Ev$+$H$$$&Bg$^$+$JNX3T$rM?$($k=R(B $B8l!#$=$7$F(B -@item gnus-agent-cat-score-file +@item agent-score-file ($BDL>o(B) $B$I$N5-;v$r%@%&%s%m!<%I$9$k$+$r7h$a$k$H$-$N$h$j$-$a$N:Y$+$$%9%3%"(B $B5,B'!#(B($B$3$N%@%&%s%m!<%I%9%3%"(B (@dfn{download score}) $B$ODL>o$N%9%3%"$H$O(B $BI,$:$7$b4X78$,L5$$$3$H$KCm0U$7$F$/$@$5$$!#(B) -@item gnus-agent-cat-enable-expiration +@item agent-enable-expiration $B$3$N%0%k!<%W$N8E$$5-;v$r%(!<%8%'%s%H$,4|8B@Z$l>C5n$9$Y$-$+$I$&$+$r<($9(B $B%V!<%kJQ?t!#BgDq$N%0%k!<%W$O%G%#%9%/6u4V$rO2Hq$7$J$$$?$a$K4|8B@Z$l>C5n$5(B $B$l$k$Y$-$G$9!#$$$d!"C5n$5$l$k$Y$-$G$O$J(B $B$$%0%k!<%W$@$1$r4^$s$G$$$k$H8@$C$F$b!"$?$V$s:9$7;Y$($"$j$^$;$s!#(B -@item gnus-agent-cat-days-until-old +@item agent-days-until-old $B4{FI$N5-;v$r4|8B@Z$l>C5n$7$F$b:9$7;Y$($J$$$3$H$rH=CG$9$kA0$K!"%(!<%8%'%s(B $B%H$,BT$C$F$$$k$Y$-F|?t$r<($9@0?t!#(B -@item gnus-agent-cat-low-score +@item agent-low-score @code{gnus-agent-low-score} $B$r>e=q$-$9$k@0?t!#(B -@item gnus-agent-cat-high-score +@item agent-high-score @code{gnus-agent-high-score} $B$r>e=q$-$9$k@0?t!#(B -@item gnus-agent-cat-length-when-short +@item agent-length-when-short @code{gnus-agent-short-article} $B$r>e=q$-$9$k@0?t!#(B -@item gnus-agent-cat-length-when-long +@item agent-length-when-long @code{gnus-agent-long-article} $B$r>e=q$-$9$k@0?t!#(B -@c @item gnus-agent-cat-disable-undownloaded-faces -@c $B%@%&%s%m!<%I$5$l$F$$$J$$5-;v$r(B gnus-summary-*-undownloaded-face $B$r;H$C$F(B -@c $B35N,%P%C%U%!$KI=<($9$Y$-(B @emph{$B$G$O$J$$(B} $B$3$H$r<($9%7%s%\%k!#CM(B -@c $B$,(B @code{nil} $B$@$H!"B>$N%7%s%\%k$,$=$l$i$rM^@)$7$F$$$F$b!"%@%&%s%m!<%I$5(B -@c $B$l$F$$$J$$5-;vMQ$N%U%'!<%9$r;H$($k$h$&$K$J$j$^$9!#(B - -@item gnus-agent-cat-enable-undownloaded-faces +@item agent-enable-undownloaded-faces $B%@%&%s%m!<%I$5$l$F$$$J$$5-;v$r(B gnus-summary-*-undownloaded-face $B$r;H$C$F(B -$B35N,%P%C%U%!$KI=<($9$Y$-$G$"$k$3$H$r<($9%7%s%\%k!#CM$,(B @code{nil} $B$@$H!"(B -$BB>$N%7%s%\%k$,$=$l$i$rM-8z$K$7$F$$$F$b!"%@%&%s%m!<%I$5$l$F$$$J$$5-;vMQ$N(B -$B%U%'!<%9$r;H$o$J$$$h$&$K$J$j$^$9!#(B +$B35N,%P%C%U%!$KI=<($9$Y$-$+$I$&$+$r<($9%7%s%\%k!#(B@code{nil} $B0J30$J$i$I$s(B +$B$J%7%s%\%k$G$b!"%@%&%s%m!<%I$5$l$F$$$J$$5-;vMQ$N%U%'!<%9$r;H$&$h$&$K$J$j(B +$B$^$9!#(B @end table $B$$$C$?$sJ,N`$,:n$i$l$?$i!"J,N`$NL>A0$rJQ$($k$3$H$O$G$-$^$;$s!#(B @@ -17466,22 +17460,20 @@ parameters at one time (@code{gnus-category-customize-category}). $B;~4V$r:G>.$K$9$k$?$a$K(B) $B%(!<%8%'%s%H$r%-%c%C%7%e$H$7$F;H$&>l9g$O!"%@%&%s(B $B%m!<%I$5$l$F$$$J$$5-;v$N%U%'!<%9$O$*$=$i$/NI$$9M$($N$h$&$K;W$($k$G$7$g$&!#(B $B%@%&%s%m!<%I$5$l$?5-;v$KBP$7$F$9$Y$F$N;E;v(B ($B0u$rIU$1$k!"FI$`!":o=|$9(B -$B$k(B) $B$r9T$J$($P!"$$$D$bDL>o$N%U%'!<%9$,8=$l$k$+$i$G$9!#(B - -$B$H$-$?$^%(!<%8%'%s%H$r;H$&%f!<%6$K$H$C$F$O!"%@%&%s%m!<%I$5$l$F$$$J$$5-;v(B -$B$N%U%'!<%9$O!"$I$&$7$h$&$b$J$/$R$I$$9M$($G$"$k$h$&$K;W$($k$+$b$7$l$^$;$s!#(B -$BO@E@$O!"H`$i$NBgDq$N5-;v$O%(!<%8%'%s%H$Ko$N%U%'!<%9$,!"%@%&%s%m!<%I$5$l$F$$$J$$5-;v$N%U%'!<%9$N1"$K2b$s$G$7$^$&(B -$B$3$H$G$9!#$3$l$,$"$J$?$N6-6x$J$i$P!"$"$J$?$K$OFs$D$NA*Br;h$,$"$j$^$9!#Bh(B -$B0l$K!"(B@code{gnus-summary-*-undownloaded-face} $B$N%U%'!<%972$K4X$o$k;0$D$N(B -$B%3%s%9%;%k$r>C5n$9$k$?$a$K(B @code{gnus-summary-highlight} $B$r%+%9%?%^%$%:(B -$B$9$k$3$H$K$h$C$F!"%@%&%s%m!<%I$5$l$F$$$J$$5-;v$N%U%'!<%9$r40A4$KM^@)$9$k(B -$B$3$H$,$G$-$^$9!#BhFs$K!"$b$C$H@vN}$5$l$?%"%W%m!<%A$,9%$_$J$i$P!"(B -@code{agent-disable-undownloaded-faces} $B%0%k!<%W%Q%i%a!<%?$r(B t $B$K@_Dj$7(B -$B$F$bNI$$$G$7$g$&!#$3$N%Q%i%a!<%?$OB>$N$9$Y$F$N%(!<%8%'%s%H%Q%i%a!<%?$HF1(B -$BMM$K!"%(!<%8%'%s%HJ,N`(B (@pxref{Agent Categories})$B!"%0%k!<%W%H%T%C(B -$B%/(B (@pxref{Topic Parameters})$B!"$"$k$$$O8D!9$N%0%k!<%W(B (@pxref{Group -Parameters}) $B$KBP$7$F@_Dj$9$k$3$H$,$G$-$^$9!#(B +$B$k(B) $B$r9T$J$($P!"$$$D$bDL>o$N%U%'!<%9$,8=$l$k$+$i$G$9!#(B@acronym{NOV} $B$r(B +$B%-%c%C%7%e$9$k$3$H$K$h$C$F%*%s%i%$%s@-G=$r2~A1$9$k$?$a$K%(!<%8%'%s%H$r;H$C(B +$B$F$$$k%f!<%6$K$H$C$F!"%@%&%s%m!<%I$5$l$F$$$J$$5-;v$N%U%'!<%9$,8+$($k$+$b(B +$B$7$l$J$$$3$H$O!"$^$C$?$/$>$C$H$9$k$[$I$$$d$J$3$H$G$7$g$&!#$=$l$i$N$I$N5-(B +$B;v$b%(!<%8%'%s%H$Kl9g$O!"(B +@code{agent-enable-undownloaded-faces} $B%0%k!<%W%Q%i%a!<%?$r(B @code{t} $B$K(B +$B@_Dj$7$F!"%@%&%s%m!<%I$5$l$F$$$J$$5-;v$N%U%'!<%9$rM-8z$K$7$J$1$l$P$J$j$^(B +$B$;$s!#$3$N%Q%i%a!<%?$OB>$N$9$Y$F$N%(!<%8%'%s%H%Q%i%a!<%?$HF1MM$K!"%(!<%8%'(B +$B%s%HJ,N`(B (@pxref{Agent Categories})$B!"%0%k!<%W%H%T%C%/(B (@pxref{Topic +Parameters})$B!"$"$k$$$O8D!9$N%0%k!<%W(B (@pxref{Group Parameters}) $B$KBP$7$F(B +$B@_Dj$9$k$3$H$,$G$-$^$9!#(B @node Agent as Cache @subsection $B%-%c%C%7%e$H$7$F$N%(!<%8%'%s%H(B @@ -17633,13 +17625,25 @@ gnus $B$O%(!<%8%'%s%H$N85$G(B nnimap $B%0%k!<%W$rFI$`$H$-!"%U%i%0$NJQ2=$K@d$( @node Outgoing Messages @subsection $B:9=PMQ%a%C%;!<%8(B -Gnus $B$,@Z$jN%$5$l$F$$$k$H$-!"A4$F$N:9=PMQ%a%C%;!<%8(B ($B%a!<%k$H%K%e!<%9$N(B -$BN>J}(B) $B$O2<=q$-%0%k!<%W(B ``queue'' (@pxref{Drafts}) $B$K3JG<$5$l$^$9!#Ej9F$7(B -$B$?8e$G$b!"$3$3$G$=$N%a%C%;!<%8$r8+$?$jJT=8$9$k$N$O0U$N$^$^$G$9!#(B +$B%G%#%U%)%k%H$G!"(BGnus $B$,@Z$jN%$5$l$F$$$k$H$-!"A4$F$N:9=PMQ%a%C%;!<%8(B ($B%a!<(B +$B%k$H%K%e!<%9$NN>J}(B) $B$O2<=q$-%0%k!<%W(B ``queue'' (@pxref{Drafts}) $B$K3JG<$5(B +$B$l$^$9!#Ej9F$7$?8e$G$b!"$3$3$G$=$N%a%C%;!<%8$r8+$?$jJT=8$9$k$N$O0U$N$^$^(B +$B$G$9!#(B -Gnus $B$,:F$S:9$79~$^$l$?$H$-!"%a%C%;!<%8$rAw?.$9$k$?$a$K!"FCJL$JL?Na$r;H$C(B -$B$F2<=q$-%0%k!<%W$+$iAw$k$3$H$b!"%0%k!<%W%P%C%U%!Fb$G(B @kbd{J S} $B$r;H$C$F!"(B -$B2<=q$-%0%k!<%WFb$NA4$F$NAw?.2DG=%a%C%;!<%8Aw?.$9$k$3$H$b$G$-$^$9!#(B +$BAw=P$9$k%a!<%k$,(B queue $B$5$l$k(B ($B=gHVBT$A$K$J$k(B) $B>u67$r@)8f$9$k$3$H$O2DG=(B +$B$G$9(B (@code{gnus-agent-queue-mail}, @pxref{Agent Variables} $B;2>H(B)$B!#(B +Gnus $B$,@Z$jN%$5$l$F$$$k>l9g!"%K%e!<%9$O>o$K(B queue $B$5$l$k$@$1$G$9!#(B + +$B%a%C%;!<%8$rAw?.$9$k$?$a$K!"2<=q$-%0%k!<%W$+$i!"$=$3$G;H$($kFCJL$JL?Na$r(B +$B;H$C$FAw$k$3$H$b!"%0%k!<%W%P%C%U%!Fb$G(B @kbd{J S} $B$r;H$C$F!"2<=q$-%0%k!<(B +$B%WFb$N$9$Y$F$NAw?.2DG=$J%a%C%;!<%8Aw?.$9$k$3$H$b$G$-$^$9!#%K%e!<%9$NEj9F(B +$B$O(B Gnus $B$,:9$79~$^$l$F$$$k$H$-$@$1$G$-$^$9$,!"%a!<%k$O$$$D$G$bAw?.$9$k$3(B +$B$H$,$G$-$^$9!#(B + +$B@Z$jN%$5$l$F$$$k$H$-$K%a!<%k$NAw?.$,$G$-$:!"$+$D@Z$jN%$5$l$F$$$k$H$-$K$&$C(B +$B$+$j(B @kbd{J S} $B$rC!$$$F$7$^$&$3$H$,?4G[$J$i$P!"(BGnus $B$K$"$J$?$N9TF0$r3NG'(B +$B$5$;$k$3$H$,$G$-$^$9(B (@code{gnus-agent-prompt-send-queue}, @pxref{Agent +Variables} $B;2>H(B)$B!#(B @node Agent Variables @subsection $B%(!<%8%'%s%HJQ?t(B @@ -17737,6 +17741,31 @@ gnus $B$,%5!<%P!<$K@\B3$G$-$J$H$-$K2?$,5/$-$?$+$rJ*8l$j$^$9!#%(!<%8%'%s%H(B $B5-;v$r>o$KL5;k$9$k$3$H(B)$B!"(B@code{unfetched} ($BA`:n$O%X%C%@!<$,o$K(B queue ($B=gHVBT$A(B) $B$KF~$l$^$9!#(B +@code{t} $B$@$C$?$i(B Gnus $B$O@Z$jN%$5$l$F$$$k$H$-$@$1%a!<%k$r(B queue $B$KF~$l$^(B +$B$9!#(B@code{nil} $B$@$C$?$i(B queue $B$KF~$l$^$;$s!#%G%#%U%)%k%H$O(B @code{t} $B$G$9!#(B + +@item gnus-agent-prompt-send-queue +@vindex gnus-agent-prompt-send-queue +@code{gnus-agent-prompt-send-queue} $B$,Hs(B-@code{nil} $B$@$C$?$i!"@Z$jN%$5$l(B +$B$F$$$k$N$K$b$+$+$o$i$:(B @kbd{J S} $B$rC!$$$?>l9g$K!"(BGnus $B$OK\Ev$K$=$l$r9T$J$C(B +$B$F$bNI$$$+$I$&$+$r3NG'$7$^$9!#%G%#%U%)%k%H$O(B @code{nil} $B$G$9!#(B + +@item gnus-agent-auto-agentize-methods +@vindex gnus-agent-auto-agentize-methods +$B$"$J$?$,0JA0$K%(!<%8%'%s%H$r;H$C$?$3$H$,L5$$(B ($B$b$C$H5;=QE*$K$O!"(B +@file{~/News/agent/lib/servers} $B$,L5$$>l9g(B)$B!"(BGnus $B$O$[$s$N>/?t$N%5!<%P!<(B +$B$r<+F0E*$K%(!<%8%'%s%H2=$7$^$9!#$3$NJQ?t$O$I$N%P%C%/%(%s%I$r<+F0$G%(!<%8%'(B +$B%s%H2=$9$Y$-$+$r@)8f$7$^$9!#0lHL$K!"%(!<%8%'%s%H2=$O1s3V%P%C%/%(%s%I$@$1(B +$B$KM-MQ$G$9!#<+F0$N%(!<%8%'%s%H2=$O!"%5!<%P!<$KBP$7$F(B @kbd{J a} $B$r