+2003-05-13 Katsumi Yamaoka <yamaoka@jpl.org>
+
+ * dgnushack.el (assq-delete-all): New compiler macro for Emacs 20.
+
+2003-05-12 Katsumi Yamaoka <yamaoka@jpl.org>
+
+ * lpath.el: Fbind find-coding-system.
+
+ * dgnushack.el (dgnushack-make-load): Remove redundant format call
+ in message. Suggested by Yoichi NAKAYAMA <yoichi@geiin.org>.
+ * pop3.el (pop3-movemail): Ditto.
+
+2003-05-12 Colin Marquardt <c.marquardt@alcatel.de> (tiny change)
+
+ * gnus.el (gnus-agent): Docstring fix.
+
+2003-05-12 Teodor Zlatanov <tzz@lifelogs.com>
+
+ * gnus-registry.el (gnus-registry-install): new variable
+ (gnus-registry-fetch-extra, gnus-registry-fetch-extra-entry)
+ (gnus-registry-store-extra-entry, gnus-registry-delete-group)
+ (gnus-registry-add-group): add a modification timestamp to each entry
+ (gnus-registry-install-hooks): new function
+
+2003-05-12 Kevin Greiner <kgreiner@xpediantsolutions.com>
+
+ * gnus-agent.el (gnus-agent-cat-name): Eval macro while compiling.
+ (gnus-agent-cat-disable-undownloaded-faces): New function.
+ Accessor for new agent property
+ 'agent-disable-undownloaded-faces'.
+ gnus-cus.el (gnus-agent-parameters): Added
+ agent-disable-undownloaded-faces and corrected documentation.
+ (gnus-agent-cat-prepare-category-field,
+ gnus-agent-customize-category): Changed to avoid creating free
+ references to each field's symbol.
+ gnus-sum.el (gnus-summary-use-undownloaded-faces): New local variable.
+ (gnus-select-newgroup): Initialize it.
+ (gnus-summary-highlight-line): Use it.
+
+2003-05-12 Dave Love <fx@gnu.org>
+
+ * rfc2047.el (rfc2047-point-at-bol, rfc2047-point-at-bol): Eval
+ and compile.
+ (rfc2047-syntax-table): Fix building table to work in Emacs 22.
+ (rfc2047-unfold-region): Delete unused var `leading'.
+
2003-05-12 Simon Josefsson <jas@extundo.com>
* pgg.el (pgg-temp-buffer-show-function): Reuse existing visible
(batch-update-autoloads))))
(defun dgnushack-make-load ()
- (message (format "Generating %s..." dgnushack-gnus-load-file))
+ (message "Generating %s..." dgnushack-gnus-load-file)
(with-temp-file dgnushack-gnus-load-file
(if (file-exists-p dgnushack-cus-load-file)
(progn
(search-forward "\n;;; Code:" nil t)
(forward-line 1)
(insert "\n(autoload 'custom-add-loads \"cus-load\")\n"))))
- (message (format "Compiling %s..." dgnushack-gnus-load-file))
+ (message "Compiling %s..." dgnushack-gnus-load-file)
(byte-compile-file dgnushack-gnus-load-file))
\f
value))
(list (quote ,name) --category--temp--) ; access-form
)))))
-
- (defmacro gnus-agent-cat-name (category)
- `(car ,category))
)
+(defmacro gnus-agent-cat-name (category)
+ `(car ,category))
+
+(gnus-agent-cat-defaccessor
+ gnus-agent-cat-days-until-old agent-days-until-old)
(gnus-agent-cat-defaccessor
- gnus-agent-cat-days-until-old agent-days-until-old)
+ gnus-agent-cat-enable-expiration agent-enable-expiration)
(gnus-agent-cat-defaccessor
- gnus-agent-cat-enable-expiration agent-enable-expiration)
+ gnus-agent-cat-groups agent-groups)
(gnus-agent-cat-defaccessor
- gnus-agent-cat-groups agent-groups)
+ gnus-agent-cat-high-score agent-high-score)
(gnus-agent-cat-defaccessor
- gnus-agent-cat-high-score agent-high-score)
+ gnus-agent-cat-length-when-long agent-length-when-long)
(gnus-agent-cat-defaccessor
- gnus-agent-cat-length-when-long agent-length-when-long)
+ gnus-agent-cat-length-when-short agent-length-when-short)
(gnus-agent-cat-defaccessor
- gnus-agent-cat-length-when-short agent-length-when-short)
+ gnus-agent-cat-low-score agent-low-score)
(gnus-agent-cat-defaccessor
- gnus-agent-cat-low-score agent-low-score)
+ gnus-agent-cat-predicate agent-predicate)
(gnus-agent-cat-defaccessor
- gnus-agent-cat-predicate agent-predicate)
+ gnus-agent-cat-score-file agent-score-file)
(gnus-agent-cat-defaccessor
- gnus-agent-cat-score-file agent-score-file)
+ gnus-agent-cat-disable-undownloaded-faces agent-disable-undownloaded-faces)
(eval-when-compile
(defsetf gnus-agent-cat-groups (category) (groups)
(symbol-value
(cdr
(assq symbol
- '((agent-short-article . gnus-agent-short-article)
- (agent-long-article . gnus-agent-long-article)
- (agent-low-score . gnus-agent-low-score)
- (agent-high-score . gnus-agent-high-score)
- (agent-days-until-old . gnus-agent-expire-days)
- (agent-enable-expiration
- . gnus-agent-enable-expiration)
- (agent-predicate . gnus-agent-predicate)))))))
+ '((agent-short-article . gnus-agent-short-article)
+ (agent-long-article . gnus-agent-long-article)
+ (agent-low-score . gnus-agent-low-score)
+ (agent-high-score . gnus-agent-high-score)
+ (agent-days-until-old . gnus-agent-expire-days)
+ (agent-enable-expiration
+ . gnus-agent-enable-expiration)
+ (agent-predicate . gnus-agent-predicate)))))))
(defun gnus-agent-fetch-headers (group &optional force)
"Fetch interesting headers into the agent. The group's overview
(eval-when-compile (require 'cl))
(require 'pym)
+ (define-compiler-macro assq-delete-all (&whole form key alist)
+ (if (>= emacs-major-version 21)
+ form
+ `(let* ((key ,key)
+ (alist ,alist)
+ (tail alist))
+ (while tail
+ (if (and (consp (car tail)) (eq (car (car tail)) key))
+ (setq alist (delq (car tail) alist)))
+ (setq tail (cdr tail)))
+ alist)))
+
(define-compiler-macro butlast (&whole form x &optional n)
(if (>= emacs-major-version 21)
form
gnus-agent-cat-days-until-old)
(agent-enable-expiration
(radio :tag "Expire in this Group or Topic" :value nil
-; (const :format "Inherit " nil)
(const :format "Enable " ENABLE)
(const :format "Disable " DISABLE))
"\nEnable, or disable, agent expiration in this group or topic."
- gnus-agent-cat-enable-expiration) )
+ 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))
"Alist of group parameters that are not also topic parameters.
-Each entry has the form (NAME TYPE DOC), where NAME is the parameter
-itself (a symbol), TYPE is the parameters type (a sexp widget), and
-DOC is a documentation string for the parameter."))
+Each entry has the form (NAME TYPE DOC ACCESSOR), where NAME is the
+parameter itself (a symbol), TYPE is the parameters type (a sexp
+widget), DOC is a documentation string for the parameter, and ACCESSOR
+is a function (symbol) that extracts the current value from the
+category."))
(defvar gnus-custom-params)
(defvar gnus-custom-method)
(eval-when-compile
(defvar category-fields nil)
- (defvar gnus-agent-cat-predicate nil)
- (defvar gnus-agent-cat-score-file nil)
- (defvar gnus-agent-cat-length-when-short nil)
- (defvar gnus-agent-cat-length-when-long nil)
- (defvar gnus-agent-cat-low-score nil)
- (defvar gnus-agent-cat-high-score nil)
- (defvar gnus-agent-cat-groups nil)
- (defvar gnus-agent-cat-enable-expiration nil)
- (defvar gnus-agent-cat-days-until-old nil)
- (defvar gnus-agent-cat-name nil)
)
(defun gnus-trim-whitespace (s)
(val (,field info))
(deflt (if (,field defaults)
(concat " [" (gnus-trim-whitespace
- (pp-to-string (,field defaults))) "]"))))
+ (pp-to-string (,field defaults))) "]")))
+ symb)
(if (eq (car type) 'radio)
(let* ((rtype (nreverse type))
(widget-insert "\n")
- (set (make-local-variable ',field)
- (if val
- (widget-create type :value val)
- (widget-create type)))
- (widget-put ,field :default val)
- (widget-put ,field :accessor ',field)
- (push ,field category-fields))))
+ (setq val (if val
+ (widget-create type :value val)
+ (widget-create type))
+ symb (set (make-local-variable ',field) val))
+
+ (widget-put symb :default val)
+ (widget-put symb :accessor ',field)
+ (push symb category-fields))))
(defun gnus-agent-customize-category (category)
"Edit the CATEGORY."
;; gnus-agent-cat-prepare-category-field as I don't want the
;; group list to appear when customizing a topic.
(widget-insert "\n")
- (set (make-local-variable 'gnus-agent-cat-groups)
- (widget-create
- `(choice
- :format "%[Select Member Groups%]\n%v" :value ignore
- (const :menu-tag "do not change" :tag "" :value ignore)
- (checklist :entry-format "%b %v"
- :menu-tag "display group selectors"
- :greedy t
- :value ,(delq nil
- (mapcar
- (lambda (newsrc)
- (car (member
- (gnus-info-group newsrc)
- (gnus-agent-cat-groups info))))
- (cdr gnus-newsrc-alist)))
- ,@(mapcar (lambda (newsrc)
- `(const ,(gnus-info-group newsrc)))
- (cdr gnus-newsrc-alist))))))
-
- (widget-put gnus-agent-cat-groups :default (gnus-agent-cat-groups info))
- (widget-put gnus-agent-cat-groups :accessor 'gnus-agent-cat-groups)
- (push gnus-agent-cat-groups category-fields)
+
+ (let ((symb
+ (set
+ (make-local-variable 'gnus-agent-cat-groups)
+ (widget-create
+ `(choice
+ :format "%[Select Member Groups%]\n%v" :value ignore
+ (const :menu-tag "do not change" :tag "" :value ignore)
+ (checklist :entry-format "%b %v"
+ :menu-tag "display group selectors"
+ :greedy t
+ :value
+ ,(delq nil
+ (mapcar
+ (lambda (newsrc)
+ (car (member
+ (gnus-info-group newsrc)
+ (gnus-agent-cat-groups info))))
+ (cdr gnus-newsrc-alist)))
+ ,@(mapcar (lambda (newsrc)
+ `(const ,(gnus-info-group newsrc)))
+ (cdr gnus-newsrc-alist))))))))
+
+ (widget-put symb :default (gnus-agent-cat-groups info))
+ (widget-put symb :accessor 'gnus-agent-cat-groups)
+ (push symb category-fields))
(widget-insert "\nExpiration Settings ")
:group 'gnus-registry
:type '(repeat string))
+(defcustom gnus-registry-install nil
+ "Whether the registry should be installed."
+ :group 'gnus-registry
+ :type 'boolean)
+
(defcustom gnus-registry-cache-file "~/.gnus.registry.eld"
"File where the Gnus registry will be stored."
:group 'gnus-registry
(string-match x word))
list)))))
-(defun gnus-registry-fetch-extra (id)
+(defun gnus-registry-fetch-extra (id &optional entry)
"Get the extra data of a message, based on the message ID.
Returns the first place where the trail finds a nonstring."
(let ((trail (gethash id gnus-registry-hashtb)))
(dolist (crumb trail)
(unless (stringp crumb)
- (return crumb)))))
+ (return (gnus-registry-fetch-extra-entry crumb entry))))))
+
+(defun gnus-registry-fetch-extra-entry (alist &optional entry)
+ "Get the extra data of a message, or a specific entry in it."
+ (if entry
+ (assq entry alist)
+ alist))
(defun gnus-registry-store-extra (id extra)
"Store the extra data of a message, based on the message ID.
(puthash id (cons extra (delete old-extra trail))
gnus-registry-hashtb))))
+(defun gnus-registry-store-extra-entry (id key value)
+ "Put a specific entry in the extras field of the registry entry for id."
+ (let* ((extra (gnus-registry-fetch-extra id))
+ (alist (cons (cons key value)
+ (assq-delete-all key (gnus-registry-fetch-extra id)))))
+ (gnus-registry-store-extra id alist)))
+
(defun gnus-registry-fetch-group (id)
"Get the group of a message, based on the message ID.
Returns the first place where the trail finds a group name."
gnus-registry-hashtb))
;; now, clear the entry if there are no more groups
(unless (gnus-registry-group-count id)
- (remhash id gnus-registry-hashtb)))))
+ (remhash id gnus-registry-hashtb))
+ (gnus-registry-store-extra-entry id 'mtime (current-time)))))
(defun gnus-registry-add-group (id group &rest extra)
"Add a group for a message, based on the message ID."
(cons group trail)
(list group))
gnus-registry-hashtb)
- (when extra (gnus-registry-store-extra id extra)))))))
+ (when extra (gnus-registry-store-extra id extra))
+ (gnus-registry-store-extra-entry id 'mtime (current-time)))))))
(defun gnus-registry-clear ()
"Clear the Gnus registry."
(setq gnus-registry-alist nil)
(setq gnus-registry-hashtb (alist-to-hashtable gnus-registry-alist)))
-; also does copy, respool, and crosspost
-(add-hook 'gnus-summary-article-move-hook 'gnus-register-action)
-(add-hook 'gnus-summary-article-delete-hook 'gnus-register-action)
-(add-hook 'gnus-summary-article-expire-hook 'gnus-register-action)
-(add-hook 'nnmail-spool-hook 'gnus-register-spool-action)
-
-(add-hook 'gnus-save-newsrc-hook 'gnus-registry-save)
-(add-hook 'gnus-read-newsrc-el-hook 'gnus-registry-read)
-
-(add-hook 'gnus-summary-prepare-hook 'gnus-registry-register-message-ids)
+(defun gnus-registry-install-hooks ()
+ "Install the registry hooks."
+ (interactive)
+ (add-hook 'gnus-summary-article-move-hook 'gnus-register-action)
+ (add-hook 'gnus-summary-article-delete-hook 'gnus-register-action)
+ (add-hook 'gnus-summary-article-expire-hook 'gnus-register-action)
+ (add-hook 'nnmail-spool-hook 'gnus-register-spool-action)
+
+ (add-hook 'gnus-save-newsrc-hook 'gnus-registry-save)
+ (add-hook 'gnus-read-newsrc-el-hook 'gnus-registry-read)
+
+ (add-hook 'gnus-summary-prepare-hook 'gnus-registry-register-message-ids))
+
+(when gnus-registry-install
+ (gnus-registry-install-hooks))
;; TODO: a lot of things
(defvar gnus-newsgroup-data-reverse nil)
(defvar gnus-newsgroup-limit nil)
(defvar gnus-newsgroup-limits nil)
+(defvar gnus-summary-use-undownloaded-faces nil)
(defvar gnus-newsgroup-unreads nil
"Sorted list of unread articles in the current newsgroup.")
gnus-newsgroup-data gnus-newsgroup-data-reverse
gnus-newsgroup-limit gnus-newsgroup-limits
gnus-newsgroup-charset gnus-newsgroup-display
+ gnus-summary-use-undownloaded-faces
gnus-newsgroup-incorporated)
"Variables that are buffer-local to the summary buffers.")
(active (gnus-active group)))
(if (and (car alist)
(< (caar alist) (car active)))
- (gnus-set-active group (cons (caar alist) (cdr active))))))
+ (gnus-set-active group (cons (caar alist) (cdr active)))))
+
+ (setq gnus-summary-use-undownloaded-faces
+ (not (gnus-agent-find-parameter
+ group
+ 'agent-disable-undownloaded-faces))))
(setq gnus-newsgroup-name group
gnus-newsgroup-unselected nil
(default gnus-summary-default-score)
(default-high gnus-summary-default-high-score)
(default-low gnus-summary-default-low-score)
- (uncached (memq article gnus-newsgroup-undownloaded))
- (downloaded (not uncached)))
+ (uncached (and gnus-summary-use-undownloaded-faces
+ (memq article gnus-newsgroup-undownloaded))))
(let ((face (funcall (gnus-summary-highlight-line-0))))
(unless (eq face (get-text-property beg 'face))
(gnus-put-text-property-excluding-characters-with-faces
(defcustom gnus-agent t
"Whether we want to use the Gnus agent or not.
-Putting (gnus-agentize) in ~/.gnus is obsolete by (setq gnus-agent t)."
+Putting (gnus-agentize) in ~/.gnus is obsoleted by (setq gnus-agent t)."
:version "21.3"
:group 'gnus-agent
:type 'boolean)
(maybe-fbind '(Info-directory
Info-menu bbdb-create-internal bbdb-records create-image
- display-graphic-p display-time-event-handler find-image
- image-size image-type-available-p insert-image
+ display-graphic-p display-time-event-handler find-coding-system
+ find-image image-size image-type-available-p insert-image
make-mode-line-mouse-map make-temp-file open-ssl-stream
propertize put-image replace-regexp-in-string
rmail-msg-is-pruned rmail-msg-restore-non-pruned-header
(require 'base64)
(autoload 'mm-body-7-or-8 "mm-bodies")
-;; Avoid gnus-util for mm- code.
-(defalias 'rfc2047-point-at-bol
- (if (fboundp 'point-at-bol)
- 'point-at-bol
- 'line-beginning-position))
+(eval-and-compile
+ ;; Avoid gnus-util for mm- code.
+ (defalias 'rfc2047-point-at-bol
+ (if (fboundp 'point-at-bol)
+ 'point-at-bol
+ 'line-beginning-position))
-(defalias 'rfc2047-point-at-eol
- (if (fboundp 'point-at-eol)
- 'point-at-eol
- 'line-end-position))
+ (defalias 'rfc2047-point-at-eol
+ (if (fboundp 'point-at-eol)
+ 'point-at-eol
+ 'line-end-position)))
(defvar rfc2047-header-encoding-alist
'(("Newsgroups" . nil)
;; skip to the end of regions appropriately. Nb. ietf-drums does
;; things differently.
(defconst rfc2047-syntax-table
- ;; This is what we should do, but XEmacs doesn't support the optional
- ;; arg of `make-syntax-table':
-;; (let ((table (make-char-table 'syntax-table '(2))))
+ ;; (make-char-table 'syntax-table '(2)) only works in Emacs.
(let ((table (make-syntax-table)))
- ;; N.b. this currently doesn't work in Emacs 22.
- (map-char-table (lambda (k v) (modify-syntax-entry k "w" table)) table)
+ ;; The following is done to work for setting all elements of the table
+ ;; in Emacs 21 and 22 and XEmacs; it appears to be the cleanest way.
+ ;; Play safe and don't assume the form of the word syntax entry --
+ ;; copy it from ?a.
+ (if (fboundp 'set-char-table-range) ; Emacs
+ (set-char-table-range table t (aref (standard-syntax-table) ?a))
+ (if (fboundp 'put-char-table)
+ (if (fboundp 'get-char-table) ; warning avoidance
+ (put-char-table t (get-char-table ?a (standard-syntax-table))
+ table))))
(modify-syntax-entry ?\\ "\\" table)
(modify-syntax-entry ?\" "\"" table)
(modify-syntax-entry ?\( "." table)
;; token, either immediately or separated by space.
last-encoded)
(goto-char (point-min))
- (condition-case nil ; in case of unbalanced quotes
+ (condition-case nil ; in case of unbalanced quotes
;; Look for rfc2822-style: sequences of atoms, quoted
;; strings, specials, whitespace. (Specials mustn't be
;; encoded.)
(let ((bol (save-restriction
(widen)
(rfc2047-point-at-bol)))
- (eol (rfc2047-point-at-eol))
- leading)
+ (eol (rfc2047-point-at-eol)))
(forward-line 1)
(while (not (eobp))
(if (and (looking-at "[ \t]")
+2003-05-12 Kevin Greiner <kgreiner@xpediantsolutions.com>
+
+ * gnus.texi (Agent Visuals): Add.
+
2003-05-09 Simon Josefsson <jas@extundo.com>
* pgg.texi (Default user identity): Add.
* Agent Basics:: \e$B$3$l$i$O$I$&F0$/$N$+\e(B
* Agent Categories:: \e$B2?$r%@%&%s%m!<%I$9$k$+$r\e(B gnus \e$B%(!<%8%'%s%H$K65$($kJ}K!\e(B
* Agent Commands:: \e$B3F%P%C%U%!!<$G$N?7$7$$L?Na\e(B
+* Agent Visuals:: \e$B%(!<%8%'%s%H$,35N,%P%C%U%!$KJQ2=$r$b$?$i$9$+$b$7$l$J$$J}K!\e(B
* Agent as Cache:: \e$B%(!<%8%'%s%H$OBg$-$J%-%c%C%7%e$G$b$"$k\e(B
* Agent Expiry:: \e$B8E$$5-;v$r>C$9J}K!\e(B
* Agent Regeneration:: \e$BDL?.@ZCG$dB>$N;v8N$+$i2sI|$9$kJ}K!\e(B
* Agent Basics:: \e$B$3$l$i$O$I$&F0$/$N$+\e(B
* Agent Categories:: \e$B2?$r%@%&%s%m!<%I$9$k$+$r\e(B gnus \e$B%(!<%8%'%s%H$K65$($kJ}K!\e(B
* Agent Commands:: \e$B3F%P%C%U%!!<$G$N?7$7$$L?Na\e(B
+* Agent Visuals:: \e$B%(!<%8%'%s%H$,35N,%P%C%U%!$KJQ2=$r$b$?$i$9$+$b$7$l$J$$J}K!\e(B
* Agent as Cache:: \e$B%(!<%8%'%s%H$OBg$-$J%-%c%C%7%e$G$b$"$k\e(B
* Agent Expiry:: \e$B8E$$5-;v$r>C$9J}K!\e(B
* Agent Regeneration:: \e$BDL?.@ZCG$dB>$N;v8N$+$i2sI|$9$kJ}K!\e(B
\e$B$k\e(B (@code{gnus-agent-remove-server})\e$B!#\e(B
@end table
+@c TRANSLATEME
+@node Agent Visuals
+@subsection Agent Visuals
+
+If you open a summary while unplugged and, Gnus knows from the group's
+active range that there are more articles than the headers currently
+stored in the Agent, you may see some articles whose subject looks
+something like @samp{[Undownloaded article #####]}. These are
+placeholders for the missing headers. Aside from setting a mark,
+there is not much that can be done with one of these placeholders.
+When Gnus finally gets a chance to fetch the group's headers, the
+placeholders will automatically be replaced by the actual headers.
+You can configure the summary buffer's maneuvering to skip over the
+placeholders if you care (See @code{gnus-auto-goto-ignores}).
+
+While it may be obvious to all, the only headers and articles
+available while unplugged are those headers and articles that were
+fetched into the Agent while previously plugged. To put it another
+way, "If you forget to fetch something while plugged, you might have a
+less than satisfying unplugged session". For this reason, the Agent
+adds two visual effects to your summary buffer. These effects display
+the download status of each article so that you always know which
+articles will be available when unplugged.
+
+The first visual effect is the @samp{%O} spec. If you customize
+gnus-summary-line-format to include this specifier, you will add a
+single character field that indicates an article's download status.
+Articles that have been fetched into either the Agent or the Cache,
+will display @code{gnus-downloaded-mark} (defaults to @samp{+}). All
+other articles will display @code{gnus-undownloaded-mark} (defaults to
+@samp{-}). If you open a group that has not been agentized, a space
+(@samp{ }) will be displayed.
+
+The second visual effect are the undownloaded faces. The faces, there
+are three indicating the article's score (low, normal, high), seem to
+result in a love/hate response from many Gnus users. The problem is
+that the face selection is controlled by a list of condition tests and
+face names (See @code{gnus-summary-highlight}). Each condition is
+tested in the order in which it appears in the list so early
+conditions have precedence over later conditions. All of this means
+that, if you tick an undownloaded article, the article will continue
+to be displayed in the undownloaded face rather than the ticked face.
+
+If you use the Agent as a cache (to avoid downloading the same article
+each time you visit it or to minimize your connection time), the
+undownloaded face will probably seem like a good idea. The reason
+being that you do all of our work (marking, reading, deleting) with
+downloaded articles so the normal faces always appear.
+
+For occasional Agent users, the undownloaded faces may appear to be an
+absolutely horrible idea. The issue being that, since most of their
+articles have not been fetched into the Agent, most of the normal
+faces will be obscured by the undownloaded faces. If this is your
+situation, you have two choices available. First, you can completely
+disable the undownload faces by customizing
+@code{gnus-summary-highlight} to delete the three cons-cells that
+refer to the gnus-summary*-undownloaded-face faces. Second, if you
+prefer to take a more fine-grained approach, you may set the
+@code{agent-disable-undownloaded-faces} group parameter to t. This
+parameter, like all other agent parameters, may be set on an Agent
+Category (@pxref{Agent Categories}), a Group Topic (@pxref{Topic
+Parameters}), or an individual group (@pxref{Group Parameters}).
+
@node Agent as Cache
@subsection \e$B%-%c%C%7%e$H$7$F$N%(!<%8%'%s%H\e(B
* Agent Basics:: How it all is supposed to work.
* Agent Categories:: How to tell the Gnus Agent what to download.
* Agent Commands:: New commands for all the buffers.
+* Agent Visuals:: Ways that the agent may effect your summary buffer.
* Agent as Cache:: The Agent is a big cache too.
* Agent Expiry:: How to make old articles go away.
* Agent Regeneration:: How to recover from lost connections and other accidents.
* Agent Basics:: How it all is supposed to work.
* Agent Categories:: How to tell the Gnus Agent what to download.
* Agent Commands:: New commands for all the buffers.
+* Agent Visuals:: Ways that the agent may effect your summary buffer.
* Agent as Cache:: The Agent is a big cache too.
* Agent Expiry:: How to make old articles go away.
* Agent Regeneration:: How to recover from lost connections and other accidents.
@end table
+@node Agent Visuals
+@subsection Agent Visuals
+
+If you open a summary while unplugged and, Gnus knows from the group's
+active range that there are more articles than the headers currently
+stored in the Agent, you may see some articles whose subject looks
+something like @samp{[Undownloaded article #####]}. These are
+placeholders for the missing headers. Aside from setting a mark,
+there is not much that can be done with one of these placeholders.
+When Gnus finally gets a chance to fetch the group's headers, the
+placeholders will automatically be replaced by the actual headers.
+You can configure the summary buffer's maneuvering to skip over the
+placeholders if you care (See @code{gnus-auto-goto-ignores}).
+
+While it may be obvious to all, the only headers and articles
+available while unplugged are those headers and articles that were
+fetched into the Agent while previously plugged. To put it another
+way, "If you forget to fetch something while plugged, you might have a
+less than satisfying unplugged session". For this reason, the Agent
+adds two visual effects to your summary buffer. These effects display
+the download status of each article so that you always know which
+articles will be available when unplugged.
+
+The first visual effect is the @samp{%O} spec. If you customize
+gnus-summary-line-format to include this specifier, you will add a
+single character field that indicates an article's download status.
+Articles that have been fetched into either the Agent or the Cache,
+will display @code{gnus-downloaded-mark} (defaults to @samp{+}). All
+other articles will display @code{gnus-undownloaded-mark} (defaults to
+@samp{-}). If you open a group that has not been agentized, a space
+(@samp{ }) will be displayed.
+
+The second visual effect are the undownloaded faces. The faces, there
+are three indicating the article's score (low, normal, high), seem to
+result in a love/hate response from many Gnus users. The problem is
+that the face selection is controlled by a list of condition tests and
+face names (See @code{gnus-summary-highlight}). Each condition is
+tested in the order in which it appears in the list so early
+conditions have precedence over later conditions. All of this means
+that, if you tick an undownloaded article, the article will continue
+to be displayed in the undownloaded face rather than the ticked face.
+
+If you use the Agent as a cache (to avoid downloading the same article
+each time you visit it or to minimize your connection time), the
+undownloaded face will probably seem like a good idea. The reason
+being that you do all of our work (marking, reading, deleting) with
+downloaded articles so the normal faces always appear.
+
+For occasional Agent users, the undownloaded faces may appear to be an
+absolutely horrible idea. The issue being that, since most of their
+articles have not been fetched into the Agent, most of the normal
+faces will be obscured by the undownloaded faces. If this is your
+situation, you have two choices available. First, you can completely
+disable the undownload faces by customizing
+@code{gnus-summary-highlight} to delete the three cons-cells that
+refer to the gnus-summary*-undownloaded-face faces. Second, if you
+prefer to take a more fine-grained approach, you may set the
+@code{agent-disable-undownloaded-faces} group parameter to t. This
+parameter, like all other agent parameters, may be set on an Agent
+Category (@pxref{Agent Categories}), a Group Topic (@pxref{Topic
+Parameters}), or an individual group (@pxref{Group Parameters}).
+
@node Agent as Cache
@subsection Agent as Cache