* gnus-registry.el: Silence XEmacs byte compiler.
[gnus] / lisp / gnus-agent.el
index 04bdb3b..1d0f346 100644 (file)
@@ -1,7 +1,6 @@
 ;;; gnus-agent.el --- unplugged support for Gnus
 
-;; Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
-;;   2006, 2007, 2008, 2009, 2010  Free Software Foundation, Inc.
+;; Copyright (C) 1997-2013 Free Software Foundation, Inc.
 
 ;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
 ;; This file is part of GNU Emacs.
@@ -187,7 +186,7 @@ When found, offer to remove them."
 (defcustom gnus-agent-auto-agentize-methods nil
   "Initially, all servers from these methods are agentized.
 The user may remove or add servers using the Server buffer.
-See Info node `(gnus)Server Buffer'."
+See Info nodes `(gnus)Server Buffer', `(gnus)Agent Variables'."
   :version "22.1"
   :type '(repeat symbol)
   :group 'gnus-agent)
@@ -203,8 +202,7 @@ queue.  Otherwise, queue if and only if unplugged."
                (const :format "When unplugged" t)))
 
 (defcustom gnus-agent-prompt-send-queue nil
-  "If non-nil, `gnus-group-send-queue' will prompt if called when
-unplugged."
+  "If non-nil, `gnus-group-send-queue' will prompt if called when unplugged."
   :version "22.1"
   :group 'gnus-agent
   :type 'boolean)
@@ -244,7 +242,6 @@ NOTES:
 (defvar gnus-category-group-cache nil)
 (defvar gnus-agent-spam-hashtb nil)
 (defvar gnus-agent-file-name nil)
-(defvar gnus-agent-send-mail-function nil)
 (defvar gnus-agent-file-coding-system 'raw-text)
 (defvar gnus-agent-file-loading-cache nil)
 (defvar gnus-agent-total-fetched-hashtb nil)
@@ -357,23 +354,11 @@ manipulated as follows:
   (func LIST): Returns VALUE1
   (setf (func LIST) NEW_VALUE1): Replaces VALUE1 with NEW_VALUE1."
     `(progn (defmacro ,name (category)
-              (list (quote cdr) (list (quote assq)
-                                      (quote (quote ,prop-name)) category)))
-
-            (define-setf-method ,name (category)
-              (let* ((--category--temp-- (make-symbol "--category--"))
-                     (--value--temp-- (make-symbol "--value--")))
-                (list (list --category--temp--) ; temporary-variables
-                      (list category)          ; value-forms
-                      (list --value--temp--)   ; store-variables
-                      (let* ((category --category--temp--) ; store-form
-                             (value --value--temp--))
-                        (list (quote gnus-agent-cat-set-property)
-                              category
-                              (quote (quote ,prop-name))
-                              value))
-                      (list (quote ,name) --category--temp--) ; access-form
-                      )))))
+              (list 'cdr (list 'assq '',prop-name category)))
+
+            (defsetf ,name (category) (value)
+              (list 'gnus-agent-cat-set-property
+                    category '',prop-name value))))
   )
 
 (defmacro gnus-agent-cat-name (category)
@@ -401,22 +386,10 @@ manipulated as follows:
  gnus-agent-cat-enable-undownloaded-faces  agent-enable-undownloaded-faces)
 
 
-;; This form is equivalent to defsetf except that it calls make-symbol
-;; whereas defsetf calls gensym (Using gensym creates a run-time
-;; dependency on the CL library).
-
-(eval-and-compile
-  (define-setf-method gnus-agent-cat-groups (category)
-    (let* ((--category--temp-- (make-symbol "--category--"))
-          (--groups--temp-- (make-symbol "--groups--")))
-      (list (list --category--temp--)
-           (list category)
-           (list --groups--temp--)
-           (let* ((category --category--temp--)
-                  (groups --groups--temp--))
-             (list (quote gnus-agent-set-cat-groups) category groups))
-           (list (quote gnus-agent-cat-groups) --category--temp--))))
-  )
+;; This form may expand to code that uses CL functions at run-time,
+;; but that's OK since those functions will only ever be called from
+;; something like `setf', so only when CL is loaded anyway.
+(defsetf gnus-agent-cat-groups gnus-agent-set-cat-groups)
 
 (defun gnus-agent-set-cat-groups (category groups)
   (unless (eq groups 'ignore)
@@ -443,7 +416,7 @@ manipulated as follows:
                      (setf (gnus-agent-cat-groups old-category)
                            (delete group (gnus-agent-cat-groups
                                           old-category))))))
-               ;; Purge cache as preceeding loop invalidated it.
+               ;; Purge cache as preceding loop invalidated it.
                (setq gnus-category-group-cache nil))
 
              (setcdr (or (assq 'agent-groups category)
@@ -513,8 +486,8 @@ manipulated as follows:
     ;; Set up the menu.
     (when (gnus-visual-p 'agent-menu 'menu)
       (funcall (intern (format "gnus-agent-%s-make-menu-bar" buffer))))
-    (unless (assq 'gnus-agent-mode minor-mode-alist)
-      (push gnus-agent-mode-status minor-mode-alist))
+    (unless (assq mode minor-mode-alist)
+      (push (cons mode (cdr gnus-agent-mode-status)) minor-mode-alist))
     (unless (assq mode minor-mode-map-alist)
       (push (cons mode (symbol-value (intern (format "gnus-agent-%s-mode-map"
                                                     buffer))))
@@ -604,7 +577,7 @@ manipulated as follows:
                  (make-mode-line-mouse-map mouse-button mouse-func)
                  'mouse-face
                  (if (and (featurep 'xemacs)
-                          ;; XEmacs' `facep' only checks for a face
+                          ;; XEmacs's `facep' only checks for a face
                           ;; object, not for a face name, so it's useless
                           ;; to check with `facep'.
                           (find-face 'modeline))
@@ -685,17 +658,14 @@ This will modify the `gnus-setup-news-hook', and
 minor mode in all Gnus buffers."
   (interactive)
   (gnus-open-agent)
-  (add-hook 'gnus-setup-news-hook 'gnus-agent-queue-setup)
-  (unless gnus-agent-send-mail-function
-    (setq gnus-agent-send-mail-function
-         (or message-send-mail-real-function
-             (function (lambda () (funcall message-send-mail-function))))
-         message-send-mail-real-function 'gnus-agent-send-mail))
+  (setq message-send-mail-real-function 'gnus-agent-send-mail)
 
   ;; If the servers file doesn't exist, auto-agentize some servers and
   ;; save the servers file so this auto-agentizing isn't invoked
   ;; again.
-  (unless (file-exists-p (nnheader-concat gnus-agent-directory "lib/servers"))
+  (when (and (not (file-exists-p (nnheader-concat
+                                 gnus-agent-directory "lib/servers")))
+            gnus-agent-auto-agentize-methods)
     (gnus-message 3 "First time agent user, agentizing remote groups...")
     (mapc
      (lambda (server-or-method)
@@ -724,13 +694,14 @@ Optional arg GROUP-NAME allows to specify another group."
 (defun gnus-agent-send-mail ()
   (if (or (not gnus-agent-queue-mail)
          (and gnus-plugged (not (eq gnus-agent-queue-mail 'always))))
-      (funcall gnus-agent-send-mail-function)
+      (message-multi-smtp-send-mail)
     (goto-char (point-min))
     (re-search-forward
      (concat "^" (regexp-quote mail-header-separator) "\n"))
     (replace-match "\n")
     (gnus-agent-insert-meta-information 'mail)
-    (gnus-request-accept-article "nndraft:queue" nil t t)))
+    (gnus-request-accept-article "nndraft:queue" nil t t)
+    (gnus-group-refresh-group "nndraft:queue")))
 
 (defun gnus-agent-insert-meta-information (type &optional method)
   "Insert meta-information into the message that says how it's to be posted.
@@ -801,12 +772,13 @@ be a select method."
   (setq group (or group gnus-newsgroup-name))
   (unless group
     (error "No group on the current line"))
-
-  (gnus-agent-while-plugged
-    (let ((gnus-command-method (gnus-find-method-for-group group)))
-      (gnus-agent-with-fetch
-        (gnus-agent-fetch-group-1 group gnus-command-method)
-        (gnus-message 5 "Fetching %s...done" group)))))
+  (if (not (gnus-agent-group-covered-p group))
+      (message "%s isn't covered by the agent" group)
+    (gnus-agent-while-plugged
+      (let ((gnus-command-method (gnus-find-method-for-group group)))
+       (gnus-agent-with-fetch
+         (gnus-agent-fetch-group-1 group gnus-command-method)
+         (gnus-message 5 "Fetching %s...done" group))))))
 
 (defun gnus-agent-add-group (category arg)
   "Add the current group to an agent category."
@@ -1129,7 +1101,7 @@ article's mark is toggled."
                   (setq alist (cdr alist)))
                  ((> a h)
                    ;; Headers that are not in the alist should be
-                   ;; fictious (see nnagent-retrieve-headers); they
+                   ;; fictitious (see nnagent-retrieve-headers); they
                    ;; imply that this article isn't in the agent.
                   (gnus-agent-append-to-list tail-undownloaded h)
                   (gnus-agent-append-to-list tail-unfetched    h)
@@ -1180,6 +1152,7 @@ downloadable."
     (gnus-summary-position-point)))
 
 (defun gnus-agent-summary-fetch-series ()
+  "Fetch the process-marked articles into the Agent."
   (interactive)
   (when gnus-newsgroup-processable
     (setq gnus-newsgroup-downloadable
@@ -1194,7 +1167,7 @@ downloadable."
            (mapc #'gnus-summary-remove-process-mark
                  (gnus-sorted-ndifference gnus-newsgroup-processable gnus-newsgroup-undownloaded))
 
-            ;; The preceeding call to (gnus-agent-summary-fetch-group)
+            ;; The preceding call to (gnus-agent-summary-fetch-group)
             ;; updated the temporary gnus-newsgroup-downloadable to
             ;; remove each article successfully fetched.  Now, I
             ;; update the real gnus-newsgroup-downloadable to only
@@ -1227,8 +1200,9 @@ Optional arg ALL, if non-nil, means to fetch all articles."
             (cond (gnus-agent-mark-unread-after-downloaded
                    (setq gnus-newsgroup-downloadable
                          (delq article gnus-newsgroup-downloadable))
-
-                   (gnus-summary-mark-article article gnus-unread-mark))
+                  (when (and (not (member article gnus-newsgroup-dormant))
+                             (not (member article gnus-newsgroup-marked)))
+                    (gnus-summary-mark-article article gnus-unread-mark)))
                   (was-marked-downloadable
                    (gnus-summary-set-agent-mark article t)))
             (when (gnus-summary-goto-subject article nil t)
@@ -1301,12 +1275,18 @@ This can be added to `gnus-select-article-hook' or
             (gnus-group-update-group group t)))
     nil))
 
-(defun gnus-agent-save-active (method)
+(defun gnus-agent-save-active (method &optional groups-p)
+  "Sync the agent's active file with the current buffer.
+Pass non-nil for GROUPS-P if the buffer starts out in groups format.
+Regardless, both the file and the buffer end up in active format
+if METHOD is agentized; otherwise the function is a no-op."
   (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")))
-      (gnus-active-to-gnus-format nil new)
+      (if groups-p
+         (gnus-groups-to-gnus-format nil new)
+       (gnus-active-to-gnus-format nil new))
       (gnus-agent-write-active file new)
       (erase-buffer)
       (let ((nnheader-file-coding-system gnus-agent-file-coding-system))
@@ -1367,7 +1347,7 @@ downloaded into the agent."
           ;; 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.
+          ;; encompass the new active range.
           (gnus-agent-set-local group agent-min (1- active-min)))))))
 
 (defun gnus-agent-save-group-info (method group active)
@@ -1509,9 +1489,10 @@ downloaded into the agent."
 
 (defun gnus-agent-fetch-articles (group articles)
   "Fetch ARTICLES from GROUP and put them into the Agent."
-  (when articles
+  (when (and articles
+            (gnus-online (gnus-group-method group)))
     (gnus-agent-load-alist group)
-    (let* ((alist   gnus-agent-article-alist)
+    (let* ((alist gnus-agent-article-alist)
            (headers (if (< (length articles) 2) nil gnus-newsgroup-headers))
            (selected-sets (list nil))
            (current-set-size 0)
@@ -1519,14 +1500,14 @@ downloaded into the agent."
            header-number)
       ;; Check each article
       (while (setq article (pop articles))
-        ;; Skip alist entries preceeding this article
+        ;; Skip alist entries preceding this article
         (while (> article (or (caar alist) (1+ article)))
           (setq alist (cdr alist)))
 
         ;; Prune off articles that we have already fetched.
         (unless (and (eq article (caar alist))
                      (cdar alist))
-          ;; Skip headers preceeding this article
+          ;; Skip headers preceding this article
           (while (> article
                     (setq header-number
                           (let* ((header (car headers)))
@@ -1553,9 +1534,9 @@ downloaded into the agent."
                                       ;; 65 char/line.  If the line count
                                       ;; is missing, arbitrarily assume a
                                       ;; size of 1000 characters.
-                                    (max (* 65 (mail-header-lines
-                                                (car headers)))
-                                         1000)
+                                     (max (* 65 (mail-header-lines
+                                                 (car headers)))
+                                          1000)
                                     char-size))
                              0))))
             (setcar selected-sets (nreverse (car selected-sets)))
@@ -1924,14 +1905,15 @@ article numbers will be returned."
             (setq articles (gnus-list-range-intersection
                             articles (list (cons low high)))))))
 
-      (gnus-message
-       10 "gnus-agent-fetch-headers: undownloaded articles are '%s'"
-       (gnus-compress-sequence articles t))
+      (when articles
+       (gnus-message
+        10 "gnus-agent-fetch-headers: undownloaded articles are '%s'"
+        (gnus-compress-sequence articles t)))
 
       (with-current-buffer nntp-server-buffer
         (if articles
             (progn
-             (gnus-message 7 "Fetching headers for %s..."
+             (gnus-message 8 "Fetching headers for %s..."
                            (gnus-agent-decoded-group-name group))
 
               ;; Fetch them.
@@ -2227,7 +2209,10 @@ doesn't exist, to valid the overview buffer."
 article counts for each of the method's subscribed groups."
   (let ((gnus-command-method (or method gnus-command-method)))
     (when (or (null gnus-agent-article-local-times)
-             (zerop gnus-agent-article-local-times))
+             (zerop gnus-agent-article-local-times)
+             (not (gnus-methods-equal-p
+                   gnus-command-method
+                   (symbol-value (intern "+method" gnus-agent-article-local)))))
       (setq gnus-agent-article-local
            (gnus-cache-file-contents
             (gnus-agent-lib-file "local")
@@