See ChangeLog for the log entries
[gnus] / lisp / nnfolder.el
index fcc0ae5..783d8d0 100644 (file)
@@ -1,10 +1,10 @@
 ;;; nnfolder.el --- mail folder access for Gnus
-;; Copyright (C) 1995,96 Free Software Foundation, Inc.
+;; Copyright (C) 1995,96,97,98,99 Free Software Foundation, Inc.
 
 ;; Author: Scott Byer <byer@mv.us.adobe.com>
-;;     Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
+;;     Lars Magne Ingebrigtsen <larsi@gnus.org>
 ;;     Masanobu UMEDA <umerin@flab.flab.fujitsu.junet>
-;; Keywords: news, mail
+;; Keywords: mail
 
 ;; This file is part of GNU Emacs.
 
 
 ;;; Commentary:
 
-;; For an overview of what the interface functions do, please see the
-;; Gnus sources.  
-
-;; Various enhancements by byer@mv.us.adobe.com (Scott Byer).
-
 ;;; Code:
 
 (require 'nnheader)
 (require 'nnmail)
 (require 'nnoo)
 (eval-when-compile (require 'cl))
+(require 'gnus-util)
 
 (nnoo-declare nnfolder)
 
 (defvoo nnfolder-directory (expand-file-name message-directory)
   "The name of the nnfolder directory.")
 
-(defvoo nnfolder-active-file 
+(defvoo nnfolder-active-file
   (nnheader-concat nnfolder-directory "active")
   "The name of the active file.")
 
 ;; style. -SLB
 
 (defvoo nnfolder-ignore-active-file nil
-  "If non-nil, causes nnfolder to do some extra work in order to determine the true active ranges of an mbox file.  
-Note that the active file is still saved, but it's values are not
-used.  This costs some extra time when scanning an mbox when opening
-it.")
-
-(defvoo nnfolder-newsgroups-file 
+  "If non-nil, causes nnfolder to do some extra work in order to determine
+the true active ranges of an mbox file.  Note that the active file is still
+saved, but it's values are not used.  This costs some extra time when
+scanning an mbox when opening it.")
+
+(defvoo nnfolder-distrust-mbox nil
+  "If non-nil, causes nnfolder to not trust the user with respect to
+inserting unaccounted for mail in the middle of an mbox file.  This can greatly
+slow down scans, which now must scan the entire file for unmarked messages.
+When nil, scans occur forward from the last marked message, a huge
+time saver for large mailboxes.")
+
+(defvoo nnfolder-newsgroups-file
   (concat (file-name-as-directory nnfolder-directory) "newsgroups")
   "Mail newsgroups description file.")
 
@@ -66,6 +69,9 @@ it.")
 (defvoo nnfolder-prepare-save-mail-hook nil
   "Hook run narrowed to an article before saving.")
 
+(defvoo nnfolder-save-buffer-hook nil
+  "Hook run before saving the nnfolder mbox buffer.")
+
 (defvoo nnfolder-inhibit-expiry nil
   "If non-nil, inhibit expiry.")
 
@@ -82,7 +88,15 @@ it.")
 (defvoo nnfolder-status-string "")
 (defvoo nnfolder-group-alist nil)
 (defvoo nnfolder-buffer-alist nil)
+(defvoo nnfolder-scantime-alist nil)
 (defvoo nnfolder-active-timestamp nil)
+(defvoo nnfolder-active-file-coding-system mm-text-coding-system)
+(defvoo nnfolder-active-file-coding-system-for-write 
+    nnmail-active-file-coding-system)
+(defvoo nnfolder-file-coding-system mm-text-coding-system)
+(defvoo nnfolder-file-coding-system-for-write nnheader-file-coding-system
+  "Coding system for save nnfolder file.
+If NIL, NNFOLDER-FILE-CODING-SYSTEM is used.")
 
 \f
 
@@ -94,46 +108,35 @@ it.")
   (save-excursion
     (set-buffer nntp-server-buffer)
     (erase-buffer)
-    (let ((delim-string (concat "^" message-unix-mail-delimiter))
-         article art-string start stop)
+    (let (article start stop)
       (nnfolder-possibly-change-group group server)
-      (set-buffer nnfolder-current-buffer)
-      (goto-char (point-min))
-      (if (stringp (car articles))
-         'headers
-       (while articles
-         (setq article (car articles))
-         (setq art-string (nnfolder-article-string article))
-         (set-buffer nnfolder-current-buffer)
-         (if (or (search-forward art-string nil t)
-                 ;; Don't search the whole file twice!  Also, articles
-                 ;; probably have some locality by number, so searching
-                 ;; backwards will be faster.  Especially if we're at the
-                 ;; beginning of the buffer :-). -SLB
-                 (search-backward art-string nil t))
-             (progn
-               (setq start (or (re-search-backward delim-string nil t)
-                               (point)))
-               (search-forward "\n\n" nil t)
-               (setq stop (1- (point)))
-               (set-buffer nntp-server-buffer)
-               (insert (format "221 %d Article retrieved.\n" article))
-               (insert-buffer-substring nnfolder-current-buffer start stop)
-               (goto-char (point-max))
-               (insert ".\n")))
-         (setq articles (cdr articles)))
-
-       (set-buffer nntp-server-buffer)
-       (nnheader-fold-continuation-lines)
-       'headers))))
+      (when nnfolder-current-buffer
+       (set-buffer nnfolder-current-buffer)
+       (goto-char (point-min))
+       (if (stringp (car articles))
+           'headers
+         (while (setq article (pop articles))
+           (set-buffer nnfolder-current-buffer)
+           (when (nnfolder-goto-article article)
+             (setq start (point))
+             (setq stop (if (search-forward "\n\n" nil t)
+                            (1- (point))
+                          (point-max)))
+             (set-buffer nntp-server-buffer)
+             (insert (format "221 %d Article retrieved.\n" article))
+             (insert-buffer-substring nnfolder-current-buffer start stop)
+             (goto-char (point-max))
+             (insert ".\n")))
+
+         (set-buffer nntp-server-buffer)
+         (nnheader-fold-continuation-lines)
+         'headers)))))
 
 (deffoo nnfolder-open-server (server &optional defs)
   (nnoo-change-server 'nnfolder server defs)
-  (when (not (file-exists-p nnfolder-directory))
-    (condition-case ()
-       (make-directory nnfolder-directory t)
-      (error t)))
-  (cond 
+  (nnmail-activate 'nnfolder t)
+  (gnus-make-directory nnfolder-directory)
+  (cond
    ((not (file-exists-p nnfolder-directory))
     (nnfolder-close-server)
     (nnheader-report 'nnfolder "Couldn't create directory: %s"
@@ -142,6 +145,7 @@ it.")
     (nnfolder-close-server)
     (nnheader-report 'nnfolder "Not a directory: %s" nnfolder-directory))
    (t
+    (nnmail-activate 'nnfolder)
     (nnheader-report 'nnfolder "Opened server %s using directory %s"
                     server nnfolder-directory)
     t)))
@@ -160,73 +164,74 @@ it.")
   (save-excursion
     (set-buffer nnfolder-current-buffer)
     (goto-char (point-min))
-    (if (search-forward (nnfolder-article-string article) nil t)
-       (let (start stop)
-         (re-search-backward (concat "^" message-unix-mail-delimiter) nil t)
-         (setq start (point))
-         (forward-line 1)
-         (or (and (re-search-forward 
-                   (concat "^" message-unix-mail-delimiter) nil t)
-                  (forward-line -1))
-             (goto-char (point-max)))
-         (setq stop (point))
-         (let ((nntp-server-buffer (or buffer nntp-server-buffer)))
-           (set-buffer nntp-server-buffer)
-           (erase-buffer)
-           (insert-buffer-substring nnfolder-current-buffer start stop)
+    (when (nnfolder-goto-article article)
+      (let (start stop)
+       (setq start (point))
+       (forward-line 1)
+       (unless (and (nnmail-search-unix-mail-delim)
+                    (forward-line -1))
+         (goto-char (point-max)))
+       (setq stop (point))
+       (let ((nntp-server-buffer (or buffer nntp-server-buffer)))
+         (set-buffer nntp-server-buffer)
+         (erase-buffer)
+         (insert-buffer-substring nnfolder-current-buffer start stop)
+         (goto-char (point-min))
+         (while (looking-at "From ")
+           (delete-char 5)
+           (insert "X-From-Line: ")
+           (forward-line 1))
+         (if (numberp article)
+             (cons nnfolder-current-group article)
            (goto-char (point-min))
-           (while (looking-at "From ")
-             (delete-char 5)
-             (insert "X-From-Line: ")
-             (forward-line 1))
-           (if (numberp article) 
-               (cons nnfolder-current-group article)
-             (goto-char (point-min))
-             (search-forward (concat "\n" nnfolder-article-marker))
-             (cons nnfolder-current-group
-                   (string-to-int 
-                    (buffer-substring 
-                     (point) (progn (end-of-line) (point)))))))))))
+           (search-forward (concat "\n" nnfolder-article-marker))
+           (cons nnfolder-current-group
+                 (string-to-int
+                  (buffer-substring
+                   (point) (progn (end-of-line) (point)))))))))))
 
 (deffoo nnfolder-request-group (group &optional server dont-check)
+  (nnfolder-possibly-change-group group server t)
   (save-excursion
-    (nnmail-activate 'nnfolder)
     (if (not (assoc group nnfolder-group-alist))
        (nnheader-report 'nnfolder "No such group: %s" group)
-      (nnfolder-possibly-change-group group server)
       (if dont-check
-         (progn 
+         (progn
            (nnheader-report 'nnfolder "Selected group %s" group)
            t)
        (let* ((active (assoc group nnfolder-group-alist))
               (group (car active))
               (range (cadr active)))
-         (cond 
+         (cond
           ((null active)
            (nnheader-report 'nnfolder "No such group: %s" group))
+          ((null nnfolder-current-group)
+           (nnheader-report 'nnfolder "Empty group: %s" group))
           (t
            (nnheader-report 'nnfolder "Selected group %s" group)
-           (nnheader-insert "211 %d %d %d %s\n" 
+           (nnheader-insert "211 %d %d %d %s\n"
                             (1+ (- (cdr range) (car range)))
                             (car range) (cdr range) group))))))))
 
 (deffoo nnfolder-request-scan (&optional group server)
-  (nnfolder-possibly-change-group group server)
-  (nnmail-get-new-mail
-   'nnfolder 
-   (lambda ()
-     (let ((bufs nnfolder-buffer-alist))
-       (save-excursion
-        (while bufs
-          (if (not (buffer-name (nth 1 (car bufs))))
-              (setq nnfolder-buffer-alist 
-                    (delq (car bufs) nnfolder-buffer-alist))
-            (set-buffer (nth 1 (car bufs)))
-            (and (buffer-modified-p) (save-buffer))
-            (kill-buffer (current-buffer)))
-          (setq bufs (cdr bufs))))))
-   nnfolder-directory
-   group))
+  (nnfolder-possibly-change-group nil server)
+  (when nnfolder-get-new-mail
+    (nnfolder-possibly-change-group group server)
+    (nnmail-get-new-mail
+     'nnfolder
+     (lambda ()
+       (let ((bufs nnfolder-buffer-alist))
+        (save-excursion
+          (while bufs
+            (if (not (gnus-buffer-live-p (nth 1 (car bufs))))
+                (setq nnfolder-buffer-alist
+                      (delq (car bufs) nnfolder-buffer-alist))
+              (set-buffer (nth 1 (car bufs)))
+              (nnfolder-save-buffer)
+              (kill-buffer (current-buffer)))
+            (setq bufs (cdr bufs))))))
+     nnfolder-directory
+     group)))
 
 ;; Don't close the buffer if we're not shutting down the server.  This way,
 ;; we can keep the buffer in the group buffer cache, and not have to grovel
@@ -237,12 +242,22 @@ it.")
   ;; Make sure we _had_ the group open.
   (when (or (assoc group nnfolder-buffer-alist)
            (equal