* lpath.el: Fbind string-as-multibyte for XEmacs.
[gnus] / lisp / gnus-agent.el
index f8fb2cc..b6220c7 100644 (file)
@@ -1,6 +1,7 @@
 ;;; gnus-agent.el --- unplugged support for Gnus
-;; Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
-;;        Free Software Foundation, Inc.
+
+;; Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
+;;   2005, 2006 Free Software Foundation, Inc.
 
 ;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
 ;; This file is part of GNU Emacs.
@@ -17,8 +18,8 @@
 
 ;; You should have received a copy of the GNU General Public License
 ;; along with GNU Emacs; see the file COPYING.  If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
+;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
 
 ;;; Commentary:
 
@@ -117,6 +118,8 @@ If nil, only read articles will be expired."
 (defcustom gnus-agent-synchronize-flags nil
   "Indicate if flags are synchronized when you plug in.
 If this is `ask' the hook will query the user."
+  ;; If the default switches to something else than nil, then the function
+  ;; should be fixed not be exceedingly slow.  See 2005-09-20 ChangeLog entry.
   :version "21.1"
   :type '(choice (const :tag "Always" t)
                 (const :tag "Never" nil)
@@ -201,7 +204,7 @@ 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)))
+               (const :format "When unplugged" t)))
 
 (defcustom gnus-agent-prompt-send-queue nil
   "If non-nil, `gnus-group-send-queue' will prompt if called when
@@ -210,6 +213,18 @@ unplugged."
   :group 'gnus-agent
   :type 'boolean)
 
+(defcustom gnus-agent-article-alist-save-format 1
+  "Indicates whether to use compression(2), versus no
+compression(1), when writing agentview files.  The compressed
+files do save space but load times are 6-7 times higher.  A group
+must be opened then closed for the agentview to be updated using
+the new format."
+  ;; Wouldn't symbols instead numbers be nicer?  --rsteib
+  :version "22.1"
+  :group 'gnus-agent
+  :type '(radio (const :format "Compressed" 2)
+               (const :format "Uncompressed" 1)))
+
 ;;; Internal variables
 
 (defvar gnus-agent-history-buffers nil)
@@ -344,8 +359,8 @@ manipulated as follows:
               (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
+                      (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)
@@ -368,17 +383,17 @@ manipulated as follows:
 (gnus-agent-cat-defaccessor
  gnus-agent-cat-high-score                 agent-high-score)
 (gnus-agent-cat-defaccessor
- gnus-agent-cat-length-when-long           agent-length-when-long)
+ gnus-agent-cat-length-when-long           agent-long-article)
 (gnus-agent-cat-defaccessor
- gnus-agent-cat-length-when-short          agent-length-when-short)
+ gnus-agent-cat-length-when-short          agent-short-article)
 (gnus-agent-cat-defaccessor
  gnus-agent-cat-low-score                  agent-low-score)
 (gnus-agent-cat-defaccessor
  gnus-agent-cat-predicate                  agent-predicate)
 (gnus-agent-cat-defaccessor
- gnus-agent-cat-score-file                 agent-score-file)
+ gnus-agent-cat-score-file                 agent-score)
 (gnus-agent-cat-defaccessor
- gnus-agent-cat-enable-undownloaded-faces agent-enable-undownloaded-faces)
+ gnus-agent-cat-enable-undownloaded-faces  agent-enable-undownloaded-faces)
 
 
 ;; This form is equivalent to defsetf except that it calls make-symbol
@@ -575,7 +590,8 @@ manipulated as follows:
   (if (and (fboundp 'propertize)
           (fboundp 'make-mode-line-mouse-map))
       (propertize string 'local-map
-                 (make-mode-line-mouse-map mouse-button mouse-func))
+                 (make-mode-line-mouse-map mouse-button mouse-func)
+                 'mouse-face 'mode-line-highlight)
     string))
 
 (defun gnus-agent-toggle-plugged (set-to)
@@ -823,7 +839,7 @@ be a select method."
   (save-excursion
     (dolist (gnus-command-method (gnus-agent-covered-methods))
       (when (and (file-exists-p (gnus-agent-lib-file "flags"))
-                (not (eq (gnus-server-status gnus-command-method) 'offline)))
+                (eq (gnus-server-status gnus-command-method) 'ok))
        (gnus-agent-possibly-synchronize-flags-server gnus-command-method)))))
 
 (defun gnus-agent-synchronize-flags-server (method)
@@ -868,9 +884,11 @@ be a select method."
 
 ;;;###autoload
 (defun gnus-agent-rename-group (old-group new-group)
-  "Rename fully-qualified OLD-GROUP as NEW-GROUP.  Always updates the agent, even when
-disabled, as the old agent files would corrupt gnus when the agent was
-next enabled. Depends upon the caller to determine whether group renaming is supported."
+  "Rename fully-qualified OLD-GROUP as NEW-GROUP.
+Always updates the agent, even when disabled, as the old agent
+files would corrupt gnus when the agent was next enabled.
+Depends upon the caller to determine whether group renaming is
+supported."
   (let* ((old-command-method (gnus-find-method-for-group old-group))
         (old-path           (directory-file-name
                              (let (gnus-command-method old-command-method)
@@ -898,9 +916,11 @@ next enabled. Depends upon the caller to determine whether group renaming is sup
 
 ;;;###autoload
 (defun gnus-agent-delete-group (group)
-  "Delete fully-qualified GROUP.  Always updates the agent, even when
-disabled, as the old agent files would corrupt gnus when the agent was
-next enabled. Depends upon the caller to determine whether group deletion is supported."
+  "Delete fully-qualified GROUP.
+Always updates the agent, even when disabled, as the old agent
+files would corrupt gnus when the agent was next enabled.
+Depends upon the caller to determine whether group deletion is
+supported."
   (let* ((command-method (gnus-find-method-for-group group))
         (path           (directory-file-name
                          (let (gnus-command-method command-method)
@@ -1144,20 +1164,22 @@ downloadable."
   (when gnus-newsgroup-processable
     (setq gnus-newsgroup-downloadable
           (let* ((dl gnus-newsgroup-downloadable)
-                 (gnus-newsgroup-downloadable
-                 (sort (gnus-copy-sequence gnus-newsgroup-processable) '<))
-                 (fetched-articles (gnus-agent-summary-fetch-group)))
-            ;; The preceeding call to (gnus-agent-summary-fetch-group)
-            ;; updated gnus-newsgroup-downloadable to remove each
-            ;; article successfully fetched.
+                (processable (sort (gnus-copy-sequence gnus-newsgroup-processable) '<))
+                 (gnus-newsgroup-downloadable processable))
+           (gnus-agent-summary-fetch-group)
+
+            ;; For each article that I processed that is no longer
+            ;; undownloaded, remove its processable mark.
 
-            ;; For each article that I processed, remove its
-            ;; processable mark IF the article is no longer
-            ;; downloadable (i.e. it's already downloaded)
-            (dolist (article gnus-newsgroup-processable)
-              (unless (memq article gnus-newsgroup-downloadable)
-                (gnus-summary-remove-process-mark article)))
-            (gnus-sorted-ndifference dl fetched-articles)))))
+           (mapc #'gnus-summary-remove-process-mark 
+                 (gnus-sorted-ndifference gnus-newsgroup-processable gnus-newsgroup-undownloaded))
+
+            ;; The preceeding 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
+            ;; include undownloaded articles.
+           (gnus-sorted-ndifference dl (gnus-sorted-ndifference processable gnus-newsgroup-undownloaded))))))
 
 (defun gnus-agent-summary-fetch-group (&optional all)
   "Fetch the downloadable articles in the group.
@@ -1250,7 +1272,13 @@ This can be added to `gnus-select-article-hook' or
                                  'gnus-range-add
                                'gnus-remove-from-range)
                              (cdr info-marks)
-                             range)))))))))
+                             range))))))))
+
+      ;;Marks can be synchronized at any time by simply toggling from
+      ;;unplugged to plugged.  If that is what is happening right now, make
+      ;;sure that the group buffer is up to date.
+          (when (gnus-buffer-live-p gnus-group-buffer)
+            (gnus-group-update-group group t)))
     nil))
 
 (defun gnus-agent-save-active (method)
@@ -1553,7 +1581,7 @@ downloaded into the agent."
                           (while (looking-at "\\([^: \n]+\\):\\([0-9]+\\) *")
                             (push (cons (buffer-substring (match-beginning 1)
                                                           (match-end 1))
-                                        (string-to-int
+                                        (string-to-number
                                         (buffer-substring (match-beginning 2)
                                                           (match-end 2))))
                                   crosses)
@@ -1843,7 +1871,7 @@ article numbers will be returned."
 (defsubst gnus-agent-read-article-number ()
   "Reads the article number at point.  Returns nil when a valid article number can not be read."
 
-  ;; It is unfortunite but the read function quietly overflows
+  ;; It is unfortunate but the read function quietly overflows
   ;; integer.  As a result, I have to use string operations to test
   ;; for overflow BEFORE calling read.
   (when (looking-at "[0-9]+\t")
@@ -1902,21 +1930,21 @@ doesn't exist, to valid the overview buffer."
       (gnus-agent-copy-nov-line (pop articles))
 
       (ignore-errors
-       (while articles
-        (while (let ((art (read (current-buffer))))
-                 (cond ((< art (car articles))
-                        (forward-line 1)
-                        t)
-                       ((= art (car articles))
-                        (beginning-of-line)
-                        (delete-region
-                         (point) (progn (forward-line 1) (point)))
-                        nil)
-                       (t
-                        (beginning-of-line)
-                        nil))))
-
-        (gnus-agent-copy-nov-line (pop articles)))))
+       (while articles
+         (while (let ((art (read (current-buffer))))
+                  (cond ((< art (car articles))
+                         (forward-line 1)
+                         t)
+                        ((= art (car articles))
+                         (beginning-of-line)
+                         (delete-region
+                          (point) (progn (forward-line 1) (point)))
+                         nil)
+                        (t
+                         (beginning-of-line)
+                         nil))))
+
+         (gnus-agent-copy-nov-line (pop articles)))))
 
     (goto-char (point-max))
 
@@ -1932,23 +1960,39 @@ doesn't exist, to valid the overview buffer."
        (goto-char p))
 
       (setq last (or last -134217728))
-      (let (sort art)
-       (while (not (eobp))
-         (setq art (gnus-agent-read-article-number))
-         (cond ((not art)
-                ;; Bad art num - delete this line
-                (beginning-of-line)
-                (delete-region (point) (progn (forward-line 1) (point))))
-               ((< art last)
-                ;; Art num out of order - enable sort
-                (setq sort t)
-                (forward-line 1))
-               (t
-                ;; Good art num
-                (setq last art)
-                (forward-line 1))))
-       (when sort
-         (sort-numeric-fields 1 (point-min) (point-max)))))))
+      (while (catch 'problems
+              (let (sort art)
+                (while (not (eobp))
+                  (setq art (gnus-agent-read-article-number))
+                  (cond ((not art)
+                         ;; Bad art num - delete this line
+                         (beginning-of-line)
+                         (delete-region (point) (progn (forward-line 1) (point))))
+                        ((< art last)
+                         ;; Art num out of order - enable sort
+                         (setq sort t)
+                         (forward-line 1))
+                        ((= art last)
+                         ;; Bad repeat of art number - delete this line
+                         (beginning-of-line)
+                         (delete-region (point) (progn (forward-line 1) (point))))
+                        (t
+                         ;; Good art num
+                         (setq last art)
+                         (forward-line 1))))
+                (when sort
+                  ;; something is seriously wrong as we simply shouldn't see out-of-order data.
+                  ;; First, we'll fix the sort.
+                  (sort-numeric-fields 1 (point-min) (point-max))
+
+                  ;; but now we have to consider that we may have duplicate rows...      
+                  ;; so reset to beginning of file
+                  (goto-char (point-min))
+                  (setq last -134217728)
+         
+                  ;; and throw a code that restarts this scan
+                  (throw 'problems t))
+                nil))))))
 
 ;; Keeps the compiler from warning about the free variable in
 ;; gnus-agent-read-agentview.
@@ -1965,61 +2009,55 @@ doesn't exist, to valid the overview buffer."
            'gnus-agent-file-loading-cache
            'gnus-agent-read-agentview))))
 
-;; Save format may be either 1 or 2.  Two is the new, compressed
-;; format that is still being tested.  Format 1 is uncompressed but
-;; known to be reliable.
-(defconst gnus-agent-article-alist-save-format 2)
-
 (defun gnus-agent-read-agentview (file)
   "Load FILE and do a `read' there."
   (with-temp-buffer
     (condition-case nil
-      (progn
-        (nnheader-insert-file-contents file)
-        (goto-char (point-min))
-        (let ((alist (read (current-buffer)))
-              (version (condition-case nil (read (current-buffer))
-                         (end-of-file 0)))
-              changed-version)
-
-          (cond
-           ((< version 2)
-            (error "gnus-agent-read-agentview no longer supports version %d.  Stop gnus, manually evaluate gnus-agent-convert-to-compressed-agentview, then restart gnus." version))
-           ((= version 0)
-            (let ((inhibit-quit t)
-                  entry)
-              (gnus-agent-open-history)
-              (set-buffer (gnus-agent-history-buffer))
-              (goto-char (point-min))
-              (while (not (eobp))
-                (if (and (looking-at
-                          "[^\t\n]+\t\\([0-9]+\\)\t\\([^ \n]+\\) \\([0-9]+\\)")
-                         (string= (match-string 2)
-                                  gnus-agent-read-agentview)
-                         (setq entry (assoc (string-to-number (match-string 3)) alist)))
-                    (setcdr entry (string-to-number (match-string 1))))
-                (forward-line 1))
-              (gnus-agent-close-history)
-              (setq changed-version t)))
-           ((= version 1)
-            (setq changed-version (not (= 1 gnus-agent-article-alist-save-format))))
-           ((= version 2)
-            (let (uncomp)
-              (mapcar
-               (lambda (comp-list)
-                 (let ((state (car comp-list))
-                       (sequence (inline
-                                  (gnus-uncompress-range
-                                   (cdr comp-list)))))
-                   (mapcar (lambda (article-id)
-                             (setq uncomp (cons (cons article-id state) uncomp)))
-                           sequence)))
-               alist)
-              (setq alist (sort uncomp 'car-less-than-car)))))
-          (when changed-version
-            (let ((gnus-agent-article-alist alist))
-              (gnus-agent-save-alist gnus-agent-read-agentview)))
-          alist))
+       (progn
+         (nnheader-insert-file-contents file)
+         (goto-char (point-min))
+         (let ((alist (read (current-buffer)))
+               (version (condition-case nil (read (current-buffer))
+                          (end-of-file 0)))
+               changed-version)
+
+           (cond
+            ((= version 0)
+             (let ((inhibit-quit t)
+                   entry)
+               (gnus-agent-open-history)
+               (set-buffer (gnus-agent-history-buffer))
+               (goto-char (point-min))
+               (while (not (eobp))
+                 (if (and (looking-at
+                           "[^\t\n]+\t\\([0-9]+\\)\t\\([^ \n]+\\) \\([0-9]+\\)")
+                          (string= (match-string 2)
+                                   gnus-agent-read-agentview)
+                          (setq entry (assoc (string-to-number (match-string 3)) alist)))
+                     (setcdr entry (string-to-number (match-string 1))))
+                 (forward-line 1))
+               (gnus-agent-close-history)
+               (setq changed-version t)))
+            ((= version 1)
+             (setq changed-version (not (= 1 gnus-agent-article-alist-save-format))))
+            ((= version 2)
+             (let (uncomp)
+               (mapcar
+                (lambda (comp-list)
+                  (let ((state (car comp-list))
+                        (sequence (inline
+                                    (gnus-uncompress-range
+                                     (cdr comp-list)))))
+                    (mapcar (lambda (article-id)
+                              (setq uncomp (cons (cons article-id state) uncomp)))
+                            sequence)))
+                alist)
+               (setq alist (sort uncomp 'car-less-than-car)))
+             (setq changed-version (not (= 2 gnus-agent-article-alist-save-format)))))
+           (when changed-version
+             (let ((gnus-agent-article-alist alist))
+               (gnus-agent-save-alist gnus-agent-read-agentview)))
+           alist))
       (file-error nil))))
 
 (defun gnus-agent-save-alist (group &optional articles state)
@@ -2131,7 +2169,7 @@ modified) original contents, they are first saved to their own file."
               ;; 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: "
+           (gnus-message 3 "Warning - invalid agent local: %s on line %d: %s"
                          file line (error-message-string err))))
         (forward-line 1)
         (setq line (1+ line))))
@@ -2162,13 +2200,14 @@ modified) original contents, they are first saved to their own file."
                                ((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")))))
+                                  (when range
+                                    (prin1 symbol)
+                                    (princ " ")
+                                    (princ (car range))
+                                    (princ " ")
+                                    (princ (cdr range))
+                                    (princ "\n"))))))
                        my-obarray))))))))
 
 (defun gnus-agent-get-local (group &optional gmane method)
@@ -2423,9 +2462,11 @@ modified) original contents, they are first saved to their own file."
                         (dolist (article marked-articles)
                           (gnus-summary-set-agent-mark article t))
                         (dolist (article fetched-articles)
-                          (if gnus-agent-mark-unread-after-downloaded
-                              (gnus-summary-mark-article
-                              article gnus-unread-mark))
+                          (when gnus-agent-mark-unread-after-downloaded
+                           (setq gnus-newsgroup-downloadable
+                                 (delq article gnus-newsgroup-downloadable))
+                           (gnus-summary-mark-article
+                            article gnus-unread-mark))
                           (when (gnus-summary-goto-subject article nil t)
                             (gnus-summary-update-download-mark article)))
                         (dolist (article unfetched-articles)
@@ -2576,7 +2617,7 @@ The following commands are available:
   (buffer-disable-undo)
   (setq truncate-lines t)
   (setq buffer-read-only t)
-  (gnus-run-hooks 'gnus-category-mode-hook))
+  (gnus-run-mode-hooks 'gnus-category-mode-hook))
 
 (defalias 'gnus-category-position-point 'gnus-goto-colon)
 
@@ -2957,7 +2998,7 @@ FORCE is equivalent to setting the expiration predicates to true."
       (if (or (not (eq articles t))
               (yes-or-no-p
                (concat "Are you sure that you want to "
-                       "expire all articles in " group ".")))
+                       "expire all articles in " group "")))
           (let ((gnus-command-method (gnus-find-method-for-group group))
                 (overview (gnus-get-buffer-create " *expire overview*"))
                 orig)
@@ -3074,7 +3115,7 @@ FORCE is equivalent to setting the expiration predicates to true."
         ;; information with this list.  For example, a flag indicating
         ;; that a particular article MUST BE KEPT.  To do this, I'm
         ;; going to transform the elements to look like (article#
-        ;; fetch_date keep_flag NOV_entry_marker) Later, I'll reverse
+        ;; fetch_date keep_flag NOV_entry_position) Later, I'll reverse
         ;; the process to generate the expired article alist.
 
         ;; Convert the alist elements to (article# fetch_date nil
@@ -3106,15 +3147,15 @@ FORCE is equivalent to setting the expiration predicates to true."
           (gnus-message 7 "gnus-agent-expire: Loading overview...")
           (nnheader-insert-file-contents nov-file)
           (goto-char (point-min))
-
+       
           (let (p)
             (while (< (setq p (point)) (point-max))
               (condition-case nil
                   ;; If I successfully read an integer (the plus zero
-                  ;; ensures a numeric type), prepend a marker entry
+                  ;; ensures a numeric type), append the position
                   ;; to the list
                   (push (list (+ 0 (read (current-buffer))) nil nil
-                              (set-marker (make-marker) p))
+                              p)
                         dlist)
                 (error
                  (gnus-message 1 "gnus-agent-expire: read error \
@@ -3166,15 +3207,39 @@ line." (point) nov-file)))
                   (setq first (cdr first)
                         secnd (cdr secnd))
                   (setcar first (or (car first)
-                                    (car secnd))) ; NOV_entry_marker
+                                    (car secnd))) ; NOV_entry_position
 
                   (setcdr dlist (cddr dlist)))
               (setq dlist (cdr dlist)))))
+
+        ;; Check the order of the entry positions.  They should be in
+        ;; ascending order.  If they aren't, the positions must be
+        ;; converted to markers.
+        (when (let ((dlist dlist)
+                    (prev-pos -1)
+                    pos)
+                (while dlist
+                  (if (setq pos (nth 3 (pop dlist)))
+                      (if (< pos prev-pos)
+                          (throw 'sort-results 'unsorted)
+                        (setq prev-pos pos)))))
+          (gnus-message 7 "gnus-agent-expire: Unsorted overview; inserting markers to compensate.")
+          (mapcar (lambda (entry)
+                    (let ((pos (nth 3 entry)))
+                      (if pos
+                          (setf (nth 3 entry)
+                                (set-marker (make-marker)
+                                            pos)))))
+                  dlist))
+
         (gnus-message 7 "gnus-agent-expire: Merging entries... Done")
 
         (let* ((len (float (length dlist)))
                (alist (list nil))
-               (tail-alist alist))
+               (tail-alist alist)
+               (position-offset 0)
+               )
+
           (while dlist
             (let ((new-completed (truncate (* 100.0
                                               (/ (setq cnt (1+ cnt))
@@ -3251,13 +3316,18 @@ missing NOV entry.  Run gnus-agent-regenerate-group to restore it.")))
 
                   (when marker
                     (push "NOV entry removed" actions)
-                    (goto-char marker)
+
+                    (goto-char (if (markerp marker)
+                                   marker
+                                 (- marker position-offset)))
 
                     (incf nov-entries-deleted)
 
-                    (let ((from (point-at-bol))
-                          (to (progn (forward-line 1) (point))))
-                      (incf bytes-freed (- to from))
+                    (let* ((from (point-at-bol))
+                           (to (progn (forward-line 1) (point)))
+                           (freed (- to from)))
+                      (incf bytes-freed freed)
+                      (incf position-offset freed)
                       (delete-region from to)))
 
                   ;; If considering all articles is set, I can only
@@ -3284,9 +3354,9 @@ expiration tests failed." group article-number)
                  tail-alist (cons article-number fetch-date)))
                )
 
-              ;; Clean up markers as I want to recycle this buffer
-              ;; over several groups.
-              (when marker
+              ;; Remove markers as I intend to reuse this buffer again.
+              (when (and marker
+                         (markerp marker))
                 (set-marker marker nil))
 
               (setq dlist (cdr dlist))))
@@ -3337,7 +3407,7 @@ FORCE is equivalent to setting the expiration predicates to true."
       (gnus-agent-expire-group group articles force)
     (if (or (not (eq articles t))
             (yes-or-no-p "Are you sure that you want to expire all \
-articles in every agentized group."))
+articles in every agentized group"))
         (let ((methods (gnus-agent-covered-methods))
               ;; Bind gnus-agent-expire-current-dirs to enable tracking
               ;; of agent directories.
@@ -3735,7 +3805,7 @@ If REREAD is not nil, downloaded articles are marked as unread."
           (dir (file-name-directory file))
           point
           (downloaded (if (file-exists-p dir)
-                          (sort (mapcar (lambda (name) (string-to-int name))
+                          (sort (mapcar (lambda (name) (string-to-number name))
                                         (directory-files dir nil "^[0-9]+$" t))
                                 '>)
                         (progn (gnus-make-directory dir) nil)))
@@ -3767,7 +3837,7 @@ If REREAD is not nil, downloaded articles are marked as unread."
                              (gnus-delete-line)
                              (setq nov-arts (cdr nov-arts))
                              (gnus-message 4 "gnus-agent-regenerate-group: NOV\
-entry of article %s deleted." l1))
+ entry of article %s deleted." l1))
                             ((not l2)
                              nil)
                             ((< l1 l2)
@@ -3900,16 +3970,19 @@ entry of article %s deleted." l1))
              (gnus-agent-possibly-alter-active group group-active)))))
 
       (when (and reread gnus-agent-article-alist)
-       (gnus-make-ascending-articles-unread
-        group
-        (if (listp reread)
-            reread
-          (delq nil (mapcar (function (lambda (c)
-                                        (cond ((eq reread t)
-                                               (car c))
-                                              ((cdr c)
-                                               (car c)))))
-                            gnus-agent-article-alist))))
+       (gnus-agent-synchronize-group-flags 
+        group 
+        (list (list
+               (if (listp reread)
+                   reread
+                 (delq nil (mapcar (function (lambda (c)
+                                               (cond ((eq reread t)
+                                                      (car c))
+                                                     ((cdr c)
+                                                      (car c)))))
+                                   gnus-agent-article-alist)))
+               'del '(read)))
+        gnus-command-method)
 
        (when regenerated
          (gnus-agent-update-files-total-fetched-for group nil)))
@@ -3995,7 +4068,7 @@ agent has fetched."
                                                   (number-to-string file)
                                                 file)))) 0))))
               (setq delta sum))
-          (let ((sum 0.0)
+          (let ((sum (- (nth 2 entry)))
                 (info (directory-files-and-attributes path nil "^-?[0-9]+$" t))
                 file)
             (while (setq file (pop info))