*** empty log message ***
authorLars Magne Ingebrigtsen <larsi@gnus.org>
Tue, 4 Mar 1997 08:57:04 +0000 (08:57 +0000)
committerLars Magne Ingebrigtsen <larsi@gnus.org>
Tue, 4 Mar 1997 08:57:04 +0000 (08:57 +0000)
25 files changed:
lisp/ChangeLog
lisp/custom.el
lisp/gnus-score.el
lisp/gnus-setup.el
lisp/gnus-vis.el
lisp/gnus.el
lisp/message.el
lisp/nnbabyl.el
lisp/nndir.el
lisp/nndoc.el
lisp/nndraft.el
lisp/nneething.el
lisp/nnfolder.el
lisp/nnheader.el
lisp/nnkiboze.el
lisp/nnmbox.el
lisp/nnmh.el
lisp/nnml.el
lisp/nnoo.el [new file with mode: 0644]
lisp/nnsoup.el
lisp/nnspool.el
lisp/nntp.el
lisp/nnvirtual.el
texi/ChangeLog
texi/gnus.texi

index aaa0c29..ba1c451 100644 (file)
@@ -1,5 +1,85 @@
+Sun Apr 14 08:54:37 1996  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+
+       * message.el (message-mode): Mail-hist isn't defined in XEmacs
+       19.13. 
+
+       * nnoo.el (defvoo): Didn't work under XEmacs.
+
+Sun Apr 14 06:27:19 1996  Lars Magne Ingebrigtsen  <larsi@aegir.ifi.uio.no>
+
+       * gnus.el: September Gnus v0.71 is released.
+
+       * nnvirtual.el (nnvirtual-open-server): Would return nil.
+
+Sat Apr 13 05:37:10 1996  Lars Magne Ingebrigtsen  <larsi@aegir.ifi.uio.no>
+
+       * gnus.el: September Gnus v0.70 is released.
+
+       * nnvirtual.el (nnvirtual-component-regexp): New variable.
+
+Fri Apr 12 18:59:45 1996  Lars Magne Ingebrigtsen  <lars@eyesore.no>
+
+       * nnoo.el: New file.  All backends now use it.
+
+Wed Apr 10 11:39:15 1996  Jan Vroonhof  <vroonhof@math.ethz.ch>
+
+       * gnus-vis.el (gnus-summary-make-menu-bar): Entry for "Eddit
+         current score file" used nonexistant function.
+
+Fri Apr 12 04:57:03 1996  Lars Magne Ingebrigtsen  <lars@eyesore.no>
+
+       * gnus.el (gnus-group-get-new-news-this-group): Would jump around
+       too much.
+
+       * message.el (message-make-fqdm): Better `user-mail-address'.
+
+Thu Apr 11 00:32:33 1996  Steven L Baur  <steve@miranova.com>
+
+       * gnus-setup.el (gnus-use-mailcrypt): Attach mailcrypt
+       initialization to message-mode-hook.
+
+Fri Apr 12 03:30:38 1996  Lars Magne Ingebrigtsen  <lars@eyesore.no>
+
+       * message.el (message-insert-to): Insert ", " if needed.
+       (message-bounce): Insert an undo boundary.
+
+       * gnus.el (gnus-summary-local-variables): Make
+       gnus-thread-expunge-below a local variable. 
+
+       * message.el (message-setup): Insert default headers before
+       generating. 
+
+       * gnus-vis.el (gnus-button-url-regexp): Allow all word-constituent
+       characters.
+
+Thu Apr 11 04:27:19 1996  Lars Magne Ingebrigtsen  <lars@eyesore.no>
+
+       * gnus-score.el (gnus-score-body): Would bug out when there were
+       no articles.
+
+       * gnus-vis.el (gnus-summary-make-menu-bar): Wrong function
+       called. 
+
+Wed Apr 10 12:48:59 1996  Lars Magne Ingebrigtsen  <lars@eyesore.no>
+
+       * message.el (message-make-organization): Remove all newlines from
+       Organization files.
+       (message-setup): Use mailabbrev.
+       (message-send): Use mail-hist.
+
+Tue Apr  9 14:52:55 1996  Per Abrahamsen  <abraham@dina.kvl.dk>
+
+       * custom.el ((fboundp 'event-point)): Was `event-closest-point'. 
+
+Wed Apr 10 12:28:41 1996  Lars Magne Ingebrigtsen  <lars@eyesore.no>
+
+       * message.el (message-mode-map): Moved Followup-to and Fcc.
+       (message-resend): Would bug out.
+
 Wed Apr 10 00:25:17 1996  Lars Magne Ingebrigtsen  <larsi@aegir.ifi.uio.no>
 
+       * gnus.el: September Gnus v0.69 is released.
+
        * nnvirtual.el (nnvirtual-close-group): Nix out variables.
 
        * gnus-cache.el (gnus-cache-possibly-remove-article): Didn't work
index 8ba1a90..b1421ac 100644 (file)
@@ -170,7 +170,7 @@ It is provided only to ease porting of broken FSF Emacs programs."
     (fset 'custom-set-text-properties 'gnus-xmas-set-text-properties)
   (fset 'custom-set-text-properties 'set-text-properties))
 
-(or (fboundp 'event-closest-point)
+(or (fboundp 'event-point)
     ;; Missing in Emacs 19.29.
     (defun event-point (event)
       "Return the character position of the given mouse-motion, button-press,
index cefd231..cca2c3b 100644 (file)
@@ -1309,89 +1309,90 @@ SCORE is the score to add."
                                  'gnus-request-body)
                                 (t 'gnus-request-article)))
             entries alist ofunc article last)
-       (while (cdr articles)
-         (setq articles (cdr articles)))
-       (setq last (mail-header-number (caar articles)))
-       (setq articles gnus-scores-articles)
-       ;; Not all backends support partial fetching.  In that case,
-       ;; we just fetch the entire article.
-       (or (gnus-check-backend-function 
-            (and (string-match "^gnus-" (symbol-name request-func))
-                 (intern (substring (symbol-name request-func)
-                                    (match-end 0))))
-            gnus-newsgroup-name)
-           (progn
-             (setq ofunc request-func)
-             (setq request-func 'gnus-request-article)))
-       (while articles
-         (setq article (mail-header-number (caar articles)))
-         (gnus-message 7 "Scoring on article %s of %s..." article last)
-         (when (funcall request-func article gnus-newsgroup-name)
-           (widen)
-           (goto-char (point-min))
-           ;; If just parts of the article is to be searched, but the
-           ;; backend didn't support partial fetching, we just narrow
-           ;; to the relevant parts.
-           (if ofunc
-               (if (eq ofunc 'gnus-request-head)
+       (when articles
+         (while (cdr articles)
+           (setq articles (cdr articles)))
+         (setq last (mail-header-number (caar articles)))
+         (setq articles gnus-scores-articles)
+         ;; Not all backends support partial fetching.  In that case,
+         ;; we just fetch the entire article.
+         (or (gnus-check-backend-function 
+              (and (string-match "^gnus-" (symbol-name request-func))
+                   (intern (substring (symbol-name request-func)
+                                      (match-end 0))))
+              gnus-newsgroup-name)
+             (progn
+               (setq ofunc request-func)
+               (setq request-func 'gnus-request-article)))
+         (while articles
+           (setq article (mail-header-number (caar articles)))
+           (gnus-message 7 "Scoring on article %s of %s..." article last)
+           (when (funcall request-func article gnus-newsgroup-name)
+             (widen)
+             (goto-char (point-min))
+             ;; If just parts of the article is to be searched, but the
+             ;; backend didn't support partial fetching, we just narrow
+             ;; to the relevant parts.
+             (if ofunc
+                 (if (eq ofunc 'gnus-request-head)
+                     (narrow-to-region
+                      (point)
+                      (or (search-forward "\n\n" nil t) (point-max)))
                    (narrow-to-region
-                    (point)
-                    (or (search-forward "\n\n" nil t) (point-max)))
-                 (narrow-to-region
-                  (or (search-forward "\n\n" nil t) (point))
-                  (point-max))))
-           (setq scores all-scores)
-           ;; Find matches.
-           (while scores
-             (setq alist (car scores)
-                   scores (cdr scores)
-                   entries (assoc header alist))
-             (while (cdr entries)      ;First entry is the header index.
-               (let* ((rest (cdr entries))             
-                      (kill (car rest))
-                      (match (nth 0 kill))
-                      (type (or (nth 3 kill) 's))
-                      (score (or (nth 1 kill) 
-                                 gnus-score-interactive-default-score))
-                      (date (nth 2 kill))
-                      (found nil)
-                      (case-fold-search 
-                       (not (or (eq type 'R) (eq type 'S)
-                                (eq type 'Regexp) (eq type 'String))))
-                      (search-func 
-                       (cond ((or (eq type 'r) (eq type 'R)
-                                  (eq type 'regexp) (eq type 'Regexp))
-                              're-search-forward)
-                             ((or (eq type 's) (eq type 'S)
-                                  (eq type 'string) (eq type 'String))
-                              'search-forward)
-                             (t
-                              (error "Illegal match type: %s" type)))))
-                 (goto-char (point-min))
-                 (if (funcall search-func match nil t)
-                     ;; Found a match, update scores.
-                     (progn
-                       (setcdr (car articles) (+ score (cdar articles)))
-                       (setq found t)
-                       (and trace (setq gnus-score-trace 
-                                        (cons
-                                         (cons
-                                          (car-safe
-                                           (rassq alist gnus-score-cache))
-                                          kill)
-                                         gnus-score-trace)))))
-                 ;; Update expire date
-                 (cond
-                  ((null date))        ;Permanent entry.
-                  ((and found gnus-update-score-entry-dates) ;Match, update date.
-                   (gnus-score-set 'touched '(t) alist)
-                   (setcar (nthcdr 2 kill) now))
-                  ((and expire (< date expire)) ;Old entry, remove.
-                   (gnus-score-set 'touched '(t) alist)
-                   (setcdr entries (cdr rest))
-                   (setq rest entries)))
-                 (setq entries rest)))))
-         (setq articles (cdr articles))))))
+                    (or (search-forward "\n\n" nil t) (point))
+                    (point-max))))
+             (setq scores all-scores)
+             ;; Find matches.
+             (while scores
+               (setq alist (car scores)
+                     scores (cdr scores)
+                     entries (assoc header alist))
+               (while (cdr entries)    ;First entry is the header index.
+                 (let* ((rest (cdr entries))           
+                        (kill (car rest))
+                        (match (nth 0 kill))
+                        (type (or (nth 3 kill) 's))
+                        (score (or (nth 1 kill) 
+                                   gnus-score-interactive-default-score))
+                        (date (nth 2 kill))
+                        (found nil)
+                        (case-fold-search 
+                         (not (or (eq type 'R) (eq type 'S)
+                                  (eq type 'Regexp) (eq type 'String))))
+                        (search-func 
+                         (cond ((or (eq type 'r) (eq type 'R)
+                                    (eq type 'regexp) (eq type 'Regexp))
+                                're-search-forward)
+                               ((or (eq type 's) (eq type 'S)
+                                    (eq type 'string) (eq type 'String))
+                                'search-forward)
+                               (t
+                                (error "Illegal match type: %s" type)))))
+                   (goto-char (point-min))
+                   (if (funcall search-func match nil t)
+                       ;; Found a match, update scores.
+                       (progn
+                         (setcdr (car articles) (+ score (cdar articles)))
+                         (setq found t)
+                         (and trace (setq gnus-score-trace 
+                                          (cons
+                                           (cons
+                                            (car-safe
+                                             (rassq alist gnus-score-cache))
+                                            kill)
+                                           gnus-score-trace)))))
+                   ;; Update expire date
+                   (cond
+                    ((null date))      ;Permanent entry.
+                    ((and found gnus-update-score-entry-dates) ;Match, update date.
+                     (gnus-score-set 'touched '(t) alist)
+                     (setcar (nthcdr 2 kill) now))
+                    ((and expire (< date expire)) ;Old entry, remove.
+                     (gnus-score-set 'touched '(t) alist)
+                     (setcdr entries (cdr rest))
+                     (setq rest entries)))
+                   (setq entries rest)))))
+           (setq articles (cdr articles)))))))
   nil)
 
 (defun gnus-score-followup (scores header now expire &optional trace thread)
index 2478624..2d349a8 100644 (file)
          (setq load-path (cons gnus-mailcrypt-lisp-directory load-path)))
       (autoload 'mc-install-write-mode "mailcrypt" nil t)
       (autoload 'mc-install-read-mode "mailcrypt" nil t)
-      (add-hook 'mail-mode-hook 'mc-install-write-mode)
-      (add-hook 'news-mode-hook 'mc-install-write-mode)
-      (add-hook 'news-reply-mode-hook 'mc-install-write-mode)
+      (add-hook 'message-mode-hook 'mc-install-write-mode)
       (add-hook 'gnus-summary-mode-hook 'mc-install-read-mode)
       (if gnus-use-mhe
          (progn
index 0fcf2fc..f0dcfc5 100644 (file)
 ;(defvar gnus-signature-face 'italic
 ;  "Face used for signature.")
 
-(defvar gnus-button-url-regexp "\\b\\(s?https?\\|ftp\\|file\\|gopher\\|news\\|telnet\\|wais\\|mailto\\):\\(//[-a-zA-Z0-9_.]+:[0-9]*\\)?[-a-zA-Z0-9_=?#$@~`%&*+|\\/.,]*[-a-zA-Z0-9_=#$@~`%&*+|\\/]"
+(defvar gnus-button-url-regexp "\\b\\(s?https?\\|ftp\\|file\\|gopher\\|news\\|telnet\\|wais\\|mailto\\):\\(//[-a-zA-Z0-9_.]+:[0-9]*\\)?[\\w-a-zA-Z0-9_=?#$@~`%&*+|\\/.,]*[\\w-a-zA-Z0-9_=#$@~`%&*+|\\/]"
   "*Regular expression that matches URLs.")
 
 (defvar gnus-button-alist 
@@ -579,7 +579,7 @@ ticked: The number of ticked articles in the group.
         ["Switch current score file" gnus-score-change-score-file t]
         ["Set mark below" gnus-score-set-mark-below t]
         ["Set expunge below" gnus-score-set-expunge-below t]
-        ["Edit current score file" gnus-score-edit-alist t]
+        ["Edit current score file" gnus-score-edit-current-scores t]
         ["Edit score file" gnus-score-edit-file t]
         ["Trace score" gnus-score-find-trace t]
         ["Rescore buffer" gnus-summary-rescore t]
index a4cc567..6cff2e2 100644 (file)
@@ -1695,7 +1695,7 @@ variable (string, integer, character, etc).")
   "gnus-bug@ifi.uio.no (The Gnus Bugfixing Girls + Boys)"
   "The mail address of the Gnus maintainers.")
 
-(defconst gnus-version "September Gnus v0.69"
+(defconst gnus-version "September Gnus v0.73"
   "Version number for this version of Gnus.")
 
 (defvar gnus-info-nodes
@@ -1901,7 +1901,7 @@ gnus-newsrc-hashtb should be kept so that both hold the same information.")
     gnus-last-article gnus-article-internal-prepare-hook
     gnus-newsgroup-dependencies gnus-newsgroup-selected-overlay
     gnus-newsgroup-scored gnus-newsgroup-kill-headers
-    gnus-newsgroup-async 
+    gnus-newsgroup-async gnus-thread-expunge-below
     gnus-score-alist gnus-current-score-file gnus-summary-expunge-below
     gnus-summary-mark-below gnus-newsgroup-active gnus-scores-exclude-files
     gnus-newsgroup-history gnus-newsgroup-ancient
@@ -6353,19 +6353,20 @@ If N is negative, this group and the N-1 previous groups will be checked."
   (interactive "P")
   (let* ((groups (gnus-group-process-prefix n))
         (ret (if (numberp n) (- n (length groups)) 0))
+        (beg (unless n (point)))
         group)
-    (while groups
-      (setq group (car groups)
-           groups (cdr groups))
+    (while (setq group (pop groups))
       (gnus-group-remove-mark group)
-      (if (and group (gnus-activate-group group 'scan))
+      (if (gnus-activate-group group 'scan)
          (progn
            (gnus-get-unread-articles-in-group
             (gnus-get-info group) (gnus-active group) t)
-           (gnus-close-group group)
+           (unless (gnus-virtual-group-p group)
+             (gnus-close-group group))
            (gnus-group-update-group group))
        (ding)
        (gnus-message 3 "%s error: %s" group (gnus-status-message group))))
+    (when beg (goto-char beg))
     (when gnus-goto-next-group-when-activating
       (gnus-group-next-unread-group 1 t))
     (gnus-summary-position-point)
index 7159c0a..50c26bc 100644 (file)
@@ -117,7 +117,7 @@ any confusion.")
 
 ;;;###autoload
 (defvar message-signature-separator "^-- *$"
-  "Regexp matching signature separator.")
+  "Regexp matching the signature separator.")
 
 ;;;###autoload
 (defvar message-interactive nil 
@@ -220,20 +220,6 @@ the value.")
 (defvar message-header-separator "--text follows this line--" 
   "*Line used to separate headers from text in messages being composed.")
 
-;;;###autoload
-(defvar message-alias-file nil
-  "*If non-nil, the name of a file to use instead of `/usr/lib/aliases'.
-This file defines aliases to be expanded by the mailer; this is a different
-feature from that of defining aliases in `.mailrc' to be expanded in Emacs.
-This variable has no effect unless your system uses sendmail as its mailer.")
-
-;;;###autoload
-(defvar message-personal-alias-file "~/.mailrc"
-  "*If non-nil, the name of the user's personal mail alias file.
-This file typically should be in same format as the `.mailrc' file used by
-the `Mail' or `mailx' program.
-This file need not actually exist.")
-
 (defvar message-setup-hook nil
   "Normal hook, run each time a new outgoing message is initialized.
 The function `message-setup' runs this hook.")
@@ -245,17 +231,6 @@ The function `message-setup' runs this hook.")
 (defvar message-citation-line-function 'message-insert-citation-line
   "*Function called to insert the \"Whomever writes:\" line.")
 
-(defvar message-aliases t
-  "Alist of mail address aliases.
-If t, initialized from your mail aliases file.
-\(The file's name is normally `~/.mailrc', but your MAILRC environment
-variable can override that name.)
-The alias definitions in the file have this form:
-    alias ALIAS MEANING")
-
-(defvar message-alias-modtime nil
-  "The modification time of your mail alias file when it was last examined.")
-
 ;;;###autoload
 (defvar message-yank-prefix "> "
   "*Prefix inserted on the lines of yanked messages.
@@ -278,23 +253,16 @@ point and mark around the citation text as modified.")
 
 (defvar message-abbrevs-loaded nil)
 
-(autoload 'expand-mail-aliases "mailalias"
-  "Expand all mail aliases in suitable header fields found between BEG and END.
-Suitable header fields are `To', `Cc' and `Bcc' and their `Resent-' variants.
-Optional second arg EXCLUDE may be a regular expression defining text to be
-removed from alias expansions."
-  nil)
-
 ;;;###autoload
 (defvar message-signature t
-  "*String to be inserted at the and the the message buffer.
+  "*String to be inserted at the end of the message buffer.
 If t, the `message-signature-file' file will be inserted instead.
 If a function, the result from the function will be used instead.
 If a form, the result from the form will be used instead.")
 
 ;;;###autoload
 (defvar message-signature-file "~/.signature"
-  "*File containing the text inserted at end of mail buffer.")
+  "*File containing the text inserted at end of message. buffer.")
 
 (defvar message-distribution-function nil
   "*Function called to return a Distribution header.")
@@ -391,6 +359,8 @@ The cdr of ech entry is a function for applying the face to a region.")
 (defvar message-sent-hook nil
   "Hook run after sending messages.")
 
+;;; Internal variables.
+
 (defvar message-header-format-alist 
   `((Newsgroups)
     (To . message-fill-header) 
@@ -567,13 +537,13 @@ Return the number of headers removed."
 
   (define-key message-mode-map "\C-c\C-f\C-t" 'message-goto-to)
   (define-key message-mode-map "\C-c\C-f\C-b" 'message-goto-bcc)
-  (define-key message-mode-map "\C-c\C-f\C-f" 'message-goto-fcc)
+  (define-key message-mode-map "\C-c\C-f\C-w" 'message-goto-fcc)
   (define-key message-mode-map "\C-c\C-f\C-c" 'message-goto-cc)
   (define-key message-mode-map "\C-c\C-f\C-s" 'message-goto-subject)
   (define-key message-mode-map "\C-c\C-f\C-r" 'message-goto-reply-to)
   (define-key message-mode-map "\C-c\C-f\C-n" 'message-goto-newsgroups)
   (define-key message-mode-map "\C-c\C-f\C-d" 'message-goto-distribution)
-  (define-key message-mode-map "\C-c\C-f\C-o" 'message-goto-followup-to)
+  (define-key message-mode-map "\C-c\C-f\C-f" 'message-goto-followup-to)
   (define-key message-mode-map "\C-c\C-f\C-k" 'message-goto-keywords)
   (define-key message-mode-map "\C-c\C-f\C-u" 'message-goto-summary)
   (define-key message-mode-map "\C-c\C-b" 'message-goto-body)
@@ -657,6 +627,8 @@ C-c C-r  message-ceasar-buffer-body (rot13 the message body)."
   (setq message-sent-message-via nil)
   (make-local-variable 'message-checksum)
   (setq message-checksum nil)
+  (when (fboundp 'mail-hist-define-keys)
+    (mail-hist-define-keys))
   (run-hooks 'text-mode-hook 'message-mode-hook))
 
 \f
@@ -740,14 +712,16 @@ C-c C-r  message-ceasar-buffer-body (rot13 the message body)."
 (defun message-insert-to ()
   "Insert a To header that points to the author of the article being replied to."
   (interactive)
-  (message-position-on-field "To")
+  (when (message-position-on-field "To")
+    (insert ", "))
   (insert (or (message-fetch-reply-field "reply-to")
              (message-fetch-reply-field "from") "")))
 
 (defun message-insert-newsgroups ()
   "Insert the Newsgroups header from the article being replied to."
   (interactive)
-  (message-position-on-field "Newsgroups")
+  (when (message-position-on-field "Newsgroups")
+    (insert ","))
   (insert (or (message-fetch-reply-field "newsgroups") "")))
 
 \f
@@ -1030,6 +1004,8 @@ the user from the mailer."
                             "Already sent message via mail; resend? "))
                        (funcall message-send-mail-function arg))))
       (message-do-fcc)
+      (when (fboundp 'mail-hist-put-headers-into-history)
+       (mail-hist-put-headers-into-history))
       (run-hooks 'message-sent-hook)
       (message "Sending...done")
       ;; If buffer has no file, mark it as unmodified and delete autosave.
@@ -1108,8 +1084,6 @@ the user from the mailer."
                           ;; Always specify who from,
                           ;; since some systems have broken sendmails.
                           (list "-f" (user-login-name))
-                          (and message-alias-file
-                               (list (concat "-oA" message-alias-file)))
                           ;; These mean "report errors by mail"
                           ;; and "deliver in background".
                           (if (null message-interactive) '("-oem" "-odb"))
@@ -1524,7 +1498,7 @@ the user from the mailer."
                  (file-exists-p message-user-organization-file))
             (insert-file-contents message-user-organization-file)))
       (goto-char (point-min))
-      (when (re-search-forward "[ \t\n]*" nil t)
+      (while (re-search-forward "[\t\n]+" nil t)
        (replace-match "" t t))
       (unless (zerop (buffer-size))
        (buffer-string)))))
@@ -1662,7 +1636,7 @@ give as trustworthy answer as possible."
       ;; `system-name' returned the right result.
       system-name)
      ;; We try `user-mail-address' as a backup.
-     ((string-match "@\\([^\\s-]+\\)\\(\\'\\|\\W\\)" user-mail-address)
+     ((string-match "@\\(.*\\)\\'" (message-user-mail-address))
       (match-string 1 user-mail-address))
      ;; Try `mail-host-address'.
      ((and (boundp 'mail-host-address)
@@ -1843,12 +1817,6 @@ Headers already prepared in the buffer are not modified."
        (replace-match " " t t))
       (goto-char (point-max)))))
 
-(defun sendmail-synch-aliases ()
-  (let ((modtime (nth 5 (file-attributes message-personal-alias-file))))
-    (or (equal message-alias-modtime modtime)
-       (setq message-alias-modtime modtime
-             message-aliases t))))
-
 (defun message-position-point ()
   "Move point to where the user probably wants to find it."
   (message-narrow-to-headers)
@@ -1902,21 +1870,25 @@ Headers already prepared in the buffer are not modified."
     (insert message-default-headers))
   (insert mail-header-separator "\n")
   (forward-line -1)
-  (when (and (message-news-p)
-            message-default-news-headers)
+  (when (message-news-p)
+    (when message-default-news-headers
+      (insert message-default-news-headers))
     (when message-generate-headers-first
-      (message-generate-headers message-required-news-headers))
-    (insert message-default-news-headers))
-  (when (and (message-mail-p)
-            message-default-mail-headers)
+      (message-generate-headers message-required-news-headers)))
+  (when (message-mail-p)
+    (when message-default-mail-headers
+      (insert message-default-mail-headers))
     (when message-generate-headers-first
-      (message-generate-headers message-required-mail-headers))
-    (insert message-default-mail-headers))
+      (message-generate-headers message-required-mail-headers)))
   (message-insert-signature)
   (message-set-auto-save-file-name)
   (save-restriction
     (message-narrow-to-headers)
     (run-hooks 'message-header-setup-hook))
+  ;; Allow mail alias things.
+  (if (fboundp 'mail-abbrevs-setup)
+      (mail-abbrevs-setup)
+    (mail-aliases-setup))
   (set-buffer-modified-p nil)
   (run-hooks 'message-setup-hook)
   (message-position-point)
@@ -2273,12 +2245,13 @@ Optional NEWS will use news to forward instead of mail."
     (let ((cur (current-buffer))
          beg)
       ;; We first set up a normal mail buffer.
-      (message-set-work-buffer)
+      (set-buffer (get-buffer-create " *message resend*"))
+      (buffer-disable-undo (current-buffer))
+      (erase-buffer)
       (message-setup `((To . ,address)))
       ;; Insert our usual headers.
-      (message-narrow-to-headers)
       (message-generate-headers '(From Date To))
-      (goto-char (point-min))
+      (message-narrow-to-headers)
       ;; Rename them all to "Resent-*".
       (while (re-search-forward "^[A-Za-z]" nil t)
        (forward-char -1)
@@ -2302,7 +2275,8 @@ Optional NEWS will use news to forward instead of mail."
        (beginning-of-line)
        (insert "Also-"))
       ;; Send it.
-      (funcall message-send-mail-function))))
+      (funcall message-send-mail-function)
+      (kill-buffer (current-buffer)))))
 
 ;;;###autoload
 (defun message-bounce ()
@@ -2314,6 +2288,7 @@ you."
   (let ((cur (current-buffer)))
     (message-pop-to-buffer "*mail message*")
     (insert-buffer-substring cur)
+    (undo-boundary)
     (goto-char (point-min))
     (or (and (re-search-forward mail-unsent-separator nil t)
             (forward-line 1))
index 3a0508b..b6567f9 100644 (file)
 (require 'nnheader)
 (require 'rmail)
 (require 'nnmail)
+(require 'nnoo)
 (eval-when-compile (require 'cl))
 
-(defvar nnbabyl-mbox-file (expand-file-name "~/RMAIL")
+(nnoo-declare nnbabyl)
+
+(defvoo nnbabyl-mbox-file (expand-file-name "~/RMAIL")
   "The name of the rmail box file in the users home directory.")
 
-(defvar nnbabyl-active-file (expand-file-name "~/.rmail-active")
+(defvoo nnbabyl-active-file (expand-file-name "~/.rmail-active")
   "The name of the active file for the rmail box.")
 
-(defvar nnbabyl-get-new-mail t
+(defvoo nnbabyl-get-new-mail t
   "If non-nil, nnbabyl will check the incoming mail file and split the mail.")
 
-(defvar nnbabyl-prepare-save-mail-hook nil
+(defvoo nnbabyl-prepare-save-mail-hook nil
   "Hook run narrowed to an article before saving.")
 
 \f
 (defconst nnbabyl-version "nnbabyl 1.0"
   "nnbabyl version.")
 
-(defvar nnbabyl-mbox-buffer nil)
-(defvar nnbabyl-current-group nil)
-(defvar nnbabyl-status-string "")
-(defvar nnbabyl-group-alist nil)
-(defvar nnbabyl-active-timestamp nil)
+(defvoo nnbabyl-mbox-buffer nil)
+(defvoo nnbabyl-current-group nil)
+(defvoo nnbabyl-status-string "")
+(defvoo nnbabyl-group-alist nil)
+(defvoo nnbabyl-active-timestamp nil)
 
-(defvar nnbabyl-previous-buffer-mode nil)
+(defvoo nnbabyl-previous-buffer-mode nil)
 
 (eval-and-compile
   (autoload 'gnus-set-text-properties "gnus-ems"))
 
 \f
 
-(defvar nnbabyl-current-server nil)
-(defvar nnbabyl-server-alist nil)
-(defvar nnbabyl-server-variables 
-  `((nnbabyl-mbox-file ,nnbabyl-mbox-file)
-    (nnbabyl-active-file ,nnbabyl-active-file)
-    (nnbabyl-get-new-mail ,nnbabyl-get-new-mail)
-    (nnbabyl-current-group nil)
-    (nnbabyl-status-string "")
-    (nnbabyl-previous-buffer-mode nil)
-    (nnbabyl-group-alist nil)))
-
-\f
-
 ;;; Interface functions
 
-(defun nnbabyl-retrieve-headers (sequence &optional newsgroup server fetch-old)
+(nnoo-define-basics nnbabyl)
+
+(deffoo nnbabyl-retrieve-headers (sequence &optional newsgroup server fetch-old)
   (save-excursion
     (set-buffer nntp-server-buffer)
     (erase-buffer)
       (nnheader-fold-continuation-lines)
       'headers)))
 
-(defun nnbabyl-open-server (server &optional defs)
-  (nnheader-change-server 'nnbabyl server defs)
+(deffoo nnbabyl-open-server (server &optional defs)
+  (nnoo-change-server 'nnbabyl server defs)
   (cond 
    ((not (file-exists-p nnbabyl-mbox-file))
     (nnbabyl-close-server)
                     nnbabyl-mbox-file)
     t)))
 
-(defun nnbabyl-close-server (&optional server)
+(deffoo nnbabyl-close-server (&optional server)
   ;; Restore buffer mode.
   (when (and (nnbabyl-server-opened)
             nnbabyl-previous-buffer-mode)
        (caar nnbabyl-previous-buffer-mode)
        (cdar nnbabyl-previous-buffer-mode))
       (funcall (cdr nnbabyl-previous-buffer-mode))))
-  (setq nnbabyl-current-server nil
-       nnbabyl-mbox-buffer nil)
+  (nnoo-close-server 'nnbabyl server)
+  (setq nnbabyl-mbox-buffer nil)
   t)
 
-(defun nnbabyl-server-opened (&optional server)
-  (and (equal server nnbabyl-current-server)
+(deffoo nnbabyl-server-opened (&optional server)
+  (and (nnoo-current-server-p 'nnbabyl server)
        nnbabyl-mbox-buffer
        (buffer-name nnbabyl-mbox-buffer)
        nntp-server-buffer
        (buffer-name nntp-server-buffer)))
 
-(defun nnbabyl-status-message (&optional server)
-  nnbabyl-status-string)
-
-(defun nnbabyl-request-article (article &optional newsgroup server buffer)
+(deffoo nnbabyl-request-article (article &optional newsgroup server buffer)
   (nnbabyl-possibly-change-newsgroup newsgroup server)
   (save-excursion
     (set-buffer nnbabyl-mbox-buffer)
                (cons nnbabyl-current-group article)
              (nnbabyl-article-group-number)))))))
 
-(defun nnbabyl-request-group (group &optional server dont-check)
+(deffoo nnbabyl-request-group (group &optional server dont-check)
   (let ((active (cadr (assoc group nnbabyl-group-alist))))
     (save-excursion
       (cond 
                         (car active) (cdr active) group)
        t)))))
 
-(defun nnbabyl-request-scan (&optional group server)
+(deffoo nnbabyl-request-scan (&optional group server)
   (nnbabyl-read-mbox)
   (nnmail-get-new-mail 
    'nnbabyl 
         (goto-char (match-end 0))
         (insert-buffer-substring in-buf))))))
 
-(defun nnbabyl-close-group (group &optional server)
+(deffoo nnbabyl-close-group (group &optional server)
   t)
 
-(defun nnbabyl-request-create-group (group &optional server) 
+(deffoo nnbabyl-request-create-group (group &optional server) 
   (nnmail-activate 'nnbabyl)
   (unless (assoc group nnbabyl-group-alist)
     (setq nnbabyl-group-alist (cons (list group (cons 1 0))
     (nnmail-save-active nnbabyl-group-alist nnbabyl-active-file))
   t)
 
-(defun nnbabyl-request-list (&optional server)
+(deffoo nnbabyl-request-list (&optional server)
   (save-excursion
     (or (nnmail-find-file nnbabyl-active-file)
        (progn
          (nnmail-save-active nnbabyl-group-alist nnbabyl-active-file)
          (nnmail-find-file nnbabyl-active-file)))))
 
-(defun nnbabyl-request-newgroups (date &optional server)
+(deffoo nnbabyl-request-newgroups (date &optional server)
   (nnbabyl-request-list server))
 
-(defun nnbabyl-request-list-newsgroups (&optional server)
+(deffoo nnbabyl-request-list-newsgroups (&optional server)
   (nnheader-report 'nnbabyl "nnbabyl: LIST NEWSGROUPS is not implemented."))
 
-(defun nnbabyl-request-expire-articles
+(deffoo nnbabyl-request-expire-articles
   (articles newsgroup &optional server force)
   (nnbabyl-possibly-change-newsgroup newsgroup server)
   (let* ((is-old t)
       (nnmail-save-active nnbabyl-group-alist nnbabyl-active-file)
       (nconc rest articles))))
 
-(defun nnbabyl-request-move-article 
+(deffoo nnbabyl-request-move-article 
   (article group server accept-form &optional last)
   (nnbabyl-possibly-change-newsgroup group server)
   (let ((buf (get-buffer-create " *nnbabyl move*"))
        (and last (save-buffer))))
     result))
 
-(defun nnbabyl-request-accept-article (group &optional server last)
+(deffoo nnbabyl-request-accept-article (group &optional server last)
   (nnbabyl-possibly-change-newsgroup group server)
   (let ((buf (current-buffer))
        result beg)
                    nnbabyl-group-alist nnbabyl-active-file)))
        result))))
 
-(defun nnbabyl-request-replace-article (article group buffer)
+(deffoo nnbabyl-request-replace-article (article group buffer)
   (nnbabyl-possibly-change-newsgroup group)
   (save-excursion
     (set-buffer nnbabyl-mbox-buffer)
       (save-buffer)
       t)))
 
-(defun nnbabyl-request-delete-group (group &optional force server)
+(deffoo nnbabyl-request-delete-group (group &optional force server)
   (nnbabyl-possibly-change-newsgroup group server)
   ;; Delete all articles in GROUP.
   (if (not force)
   (nnmail-save-active nnbabyl-group-alist nnbabyl-active-file)
   t)
 
-(defun nnbabyl-request-rename-group (group new-name &optional server)
+(deffoo nnbabyl-request-rename-group (group new-name &optional server)
   (nnbabyl-possibly-change-newsgroup group server)
   (save-excursion
     (set-buffer nnbabyl-mbox-buffer)
index 3326844..4553109 100644 (file)
@@ -2,7 +2,6 @@
 ;; Copyright (C) 1995,96 Free Software Foundation, Inc.
 
 ;; Author: Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
-;;     Masanobu UMEDA <umerin@flab.flab.fujitsu.junet>
 ;; Keywords: news
 
 ;; This file is part of GNU Emacs.
 (require 'nnheader)
 (require 'nnmh)
 (require 'nnml)
+(require 'nnoo)
 (eval-when-compile (require 'cl))
 
-(defvar nndir-directory nil
-  "Where nndir will look for groups.")
+(nnoo-declare nndir
+  nnml nnmh)
 
-(defvar nndir-nov-is-evil nil
-  "*Non-nil means that nndir will never retrieve NOV headers.")
+(defvoo nndir-directory nil
+  "Where nndir will look for groups."
+  nnml-current-directory nnmh-current-directory)
 
-\f
-
-(defconst nndir-version "nndir 1.0")
-
-(defvar nndir-status-string "")
-
-(defvar nndir-group "blououUOUOuuubhbh")
+(defvoo nndir-nov-is-evil nil
+  "*Non-nil means that nndir will never retrieve NOV headers."
+  nnml-nov-is-evil)
 
 \f
 
-(defvar nndir-current-server nil)
-(defvar nndir-server-alist nil)
-(defvar nndir-server-variables 
-  `((nndir-directory nil)
-    (nndir-status-string "")
-    (nndir-nov-is-evil ,nndir-nov-is-evil)
-    (nndir-group-alist nil)))
+(defvoo nndir-current-group "" nil nnml-current-group nnmh-current-group)
+(defvoo nndir-top-directory nil nil nnml-directory nnmh-directory)
+(defvoo nndir-get-new-mail nil nil nnml-get-new-mail nnmh-get-new-mail)
+
+(defvoo nndir-status-string "" nil nnmh-status-string)
+(defconst nndir-version "nndir 1.0")
 
 \f
 
 ;;; Interface functions.
 
+(nnoo-define-basics nndir)
 
-(defun nndir-retrieve-headers (sequence &optional 
-                                       nndir-group server fetch-old)
-  (nndir-execute-nnml-command
-   `(nnml-retrieve-headers ',sequence nndir-group ,server ,fetch-old)))
-
-(defun nndir-open-server (server &optional defs)
-  (nnheader-change-server 'nndir server defs)
+(deffoo nndir-open-server (server &optional defs)
+  (setq nndir-directory
+       (or (cadr (assq 'nndir-directory defs))
+           server))
   (unless (assq 'nndir-directory defs)
-    (setq nndir-directory server))
+    (push `(nndir-directory ,server) defs))
+  (push `(nndir-current-group
+         ,(file-name-nondirectory (directory-file-name nndir-directory)))
+       defs)
+  (push `(nndir-top-directory
+         ,(file-name-directory (directory-file-name nndir-directory)))
+       defs)
+  (nnoo-change-server 'nndir server defs)
   (let (err)
     (cond 
      ((not (condition-case arg
                       server nndir-directory)
       t))))
 
-(defun nndir-close-server (&optional server)
-  (setq nndir-current-server nil)
-  t)
-
-(defun nndir-server-opened (&optional server)
-  (and nntp-server-buffer
-       (get-buffer nntp-server-buffer)
-       nndir-current-server
-       (equal nndir-current-server server)))
-
-(defun nndir-status-message (&optional server)
-  nndir-status-string)
-
-(defun nndir-request-article (id &optional nndir-group server buffer)
-  (nndir-execute-nnmh-command
-   `(nnmh-request-article ,id nndir-group ,server ,buffer)))
-
-(defun nndir-request-group (nndir-group &optional server dont-check)
-  (nndir-execute-nnmh-command
-   `(nnmh-request-group nndir-group "" ,dont-check)))
-
-(defun nndir-request-list (&optional server dir)
-  (let ((nndir-directory (concat (file-name-as-directory
-                                 nndir-directory) "dummy")))
-    (nndir-execute-nnmh-command
-     `(nnmh-request-list ,(concat "nndir+" (or server "")) ,dir))))
-
-(defun nndir-request-newgroups (date &optional server)
-  (nndir-execute-nnmh-command
-   `(nnmh-request-newgroups ,date ,server)))
-
-(defun nndir-request-expire-articles 
-  (articles nndir-group &optional server force)
-  (nndir-execute-nnmh-command
-   `(nnmh-request-expire-articles ',articles nndir-group ,server ,force)))
-
-(defun nndir-request-accept-article (nndir-group &optional server last)
-  (nndir-execute-nnmh-command
-   `(nnmh-request-accept-article nndir-group ,server ,last)))
-
-(defun nndir-close-group (nndir-group &optional server)
-  t)
-
-(defun nndir-request-create-group (group &optional server)
-  (if (file-exists-p nndir-directory)
-      (if (file-directory-p nndir-directory)
-         t
-       nil)
-    (condition-case ()
-       (progn
-         (make-directory nndir-directory t)
-         t)
-      (file-error nil))))
+(nnoo-map-functions nndir
+  (nnml-retrieve-headers 0 nndir-current-group 0 0)
+  (nnmh-request-article 0 nndir-current-group 0 0)
+  (nnmh-request-group nndir-current-group 0 0)
+  (nnmh-close-group nndir-current-group 0))
 
-\f
-;;; Low-Level Interface
-
-(defun nndir-execute-nnmh-command (command)
-  (unless (nnmh-server-opened nndir-current-server)
-    (nnmh-open-server nndir-current-server 
-              `((nnmh-directory ,nnml-directory)
-                (nnmh-get-new-mail nil))))
-  (let ((dir (file-name-as-directory (expand-file-name nndir-directory))))
-    (if (and (not (file-directory-p nndir-group))
-            (or (file-directory-p (concat dir nndir-group))
-                (file-directory-p
-                 (concat dir (nnheader-replace-chars-in-string 
-                              nndir-group ?. ?/)))))
-       (let ((nnmh-directory nndir-directory)
-             (nnmh-get-new-mail nil))
-         (eval command))
-      (let ((dir (directory-file-name (expand-file-name nndir-directory))))
-       (string-match "/[^/]+$" dir)
-       (let ((nndir-group (substring dir (1+ (match-beginning 0))))
-             (nnmh-directory (substring dir 0 (1+ (match-beginning 0))))
-             (nnmh-get-new-mail nil))
-         (eval command))))))
-
-(defun nndir-execute-nnml-command (command)
-  (unless (nnml-server-opened nndir-current-server)
-    (nnml-open-server nndir-current-server 
-              `((nnml-directory ,nnml-directory)
-                (nnml-nov-is-evil ,nnml-nov-is-evil)
-                (nnml-get-new-mail nil))))
-  (let ((dir (file-name-as-directory (expand-file-name nndir-directory))))
-    (if (and (not (file-directory-p nndir-group))
-            (or (file-directory-p (concat dir nndir-group))
-                (file-directory-p
-                 (concat dir (nnheader-replace-chars-in-string 
-                              nndir-group ?. ?/)))))
-       (let ((nnml-directory nndir-directory)
-             (nnml-nov-is-evil nndir-nov-is-evil)
-             (nnml-get-new-mail nil))
-         (eval command))
-      (let ((dir (directory-file-name (expand-file-name nndir-directory))))
-       (string-match "/[^/]+$" dir)
-       (let* ((nndir-group (substring dir (1+ (match-beginning 0))))
-              (nnml-directory (substring dir 0 (1+ (match-beginning 0))))
-              (nnml-nov-is-evil nndir-nov-is-evil)
-              (nnml-get-new-mail nil))
-         (eval command))))))
+(nnoo-import nndir
+  (nnmh
+   nnmh-request-list
+   nnmh-request-newgroups))
 
 (provide 'nndir)
 
index d2bab2d..0623038 100644 (file)
 (require 'nnheader)
 (require 'rmail)
 (require 'nnmail)
+(require 'nnoo)
 (eval-when-compile (require 'cl))
 
-(defvar nndoc-article-type 'guess
+(nnoo-declare nndoc)
+
+(defvoo nndoc-article-type 'guess
   "*Type of the file.
 One of `mbox', `babyl', `digest', `news', `rnews', `mmdf', `forward',
 `mime-digest', `standard-digest', `slack-digest', `clari-briefs' or
 `guess'.")
 
-(defvar nndoc-post-type 'mail
+(defvoo nndoc-post-type 'mail
   "*Whether the nndoc group is `mail' or `post'.")
 
 (defvar nndoc-type-alist 
@@ -100,56 +103,27 @@ One of `mbox', `babyl', `digest', `news', `rnews', `mmdf', `forward',
 
 \f
 
-(defvar nndoc-file-begin nil)
-(defvar nndoc-first-article nil)
-(defvar nndoc-article-end nil)
-(defvar nndoc-article-begin nil)
-(defvar nndoc-head-begin nil)
-(defvar nndoc-head-end nil)
-(defvar nndoc-file-end nil)
-(defvar nndoc-body-begin nil)
-(defvar nndoc-body-end-function nil)
-(defvar nndoc-body-begin-function nil)
-(defvar nndoc-body-end nil)
-(defvar nndoc-dissection-alist nil)
-(defvar nndoc-prepare-body nil)
-(defvar nndoc-generate-head nil)
-(defvar nndoc-article-transform nil)
-
-(defvar nndoc-status-string "")
-(defvar nndoc-group-alist nil)
-(defvar nndoc-current-buffer nil
+(defvoo nndoc-file-begin nil)
+(defvoo nndoc-first-article nil)
+(defvoo nndoc-article-end nil)
+(defvoo nndoc-article-begin nil)
+(defvoo nndoc-head-begin nil)
+(defvoo nndoc-head-end nil)
+(defvoo nndoc-file-end nil)
+(defvoo nndoc-body-begin nil)
+(defvoo nndoc-body-end-function nil)
+(defvoo nndoc-body-begin-function nil)
+(defvoo nndoc-body-end nil)
+(defvoo nndoc-dissection-alist nil)
+(defvoo nndoc-prepare-body nil)
+(defvoo nndoc-generate-head nil)
+(defvoo nndoc-article-transform nil)
+
+(defvoo nndoc-status-string "")
+(defvoo nndoc-group-alist nil)
+(defvoo nndoc-current-buffer nil
   "Current nndoc news buffer.")
-(defvar nndoc-address nil)
-
-\f
-
-(defvar nndoc-current-server nil)
-(defvar nndoc-server-alist nil)
-(defvar nndoc-server-variables
-  `((nndoc-article-type ,nndoc-article-type)
-    (nndoc-article-begin nil)
-    (nndoc-article-end nil)
-    (nndoc-head-begin nil)
-    (nndoc-head-end nil)
-    (nndoc-first-article nil)
-    (nndoc-current-buffer nil)
-    (nndoc-group-alist nil)
-    (nndoc-end-of-file nil)
-    (nndoc-body-begin nil)
-    (nndoc-dissection-alist nil)
-    (nndoc-generate-head nil)
-    (nndoc-article-transform nil)
-    (nndoc-body-end-function nil)
-    (nndoc-prepare-body nil)
-    (nndoc-body-begin-function nil)
-    (nndoc-status-string ,nndoc-status-string)
-    (nndoc-body-end ,nndoc-body-end)
-    (nndoc-file-end ,nndoc-file-end)
-    (nndoc-file-begin ,nndoc-file-begin)
-    (nndoc-type-alist ,nndoc-type-alist)
-    (nndoc-post-type ,nndoc-post-type)
-    (nndoc-address nil)))
+(defvoo nndoc-address nil)
 
 (defconst nndoc-version "nndoc 1.0"
   "nndoc version.")
@@ -158,7 +132,9 @@ One of `mbox', `babyl', `digest', `news', `rnews', `mmdf', `forward',
 
 ;;; Interface functions
 
-(defun nndoc-retrieve-headers (articles &optional newsgroup server fetch-old)
+(nnoo-define-basics nndoc)
+
+(deffoo nndoc-retrieve-headers (articles &optional newsgroup server fetch-old)
   (when (nndoc-possibly-change-buffer newsgroup server)
     (save-excursion
       (set-buffer nntp-server-buffer)
@@ -182,22 +158,7 @@ One of `mbox', `babyl', `digest', `news', `rnews', `mmdf', `forward',
          (nnheader-fold-continuation-lines)
          'headers)))))
 
-(defun nndoc-open-server (server &optional defs)
-  (nnheader-change-server 'nndoc server defs))
-
-(defun nndoc-close-server (&optional server)
-  (setq nndoc-current-server nil)
-  t)
-
-(defun nndoc-server-opened (&optional server)
-  (and (equal server nndoc-current-server)
-       nntp-server-buffer
-       (buffer-name nntp-server-buffer)))
-
-(defun nndoc-status-message (&optional server)
-  nndoc-status-string)
-
-(defun nndoc-request-article (article &optional newsgroup server buffer)
+(deffoo nndoc-request-article (article &optional newsgroup server buffer)
   (nndoc-possibly-change-buffer newsgroup server)
   (save-excursion
     (let ((buffer (or buffer nntp-server-buffer))
@@ -220,7 +181,7 @@ One of `mbox', `babyl', `digest', `news', `rnews', `mmdf', `forward',
          (funcall nndoc-article-transform article))
        t))))
 
-(defun nndoc-request-group (group &optional server dont-check)
+(deffoo nndoc-request-group (group &optional server dont-check)
   "Select news GROUP."
   (let (number)
     (cond 
@@ -236,12 +197,12 @@ One of `mbox', `babyl', `digest', `news', `rnews', `mmdf', `forward',
      (t
       (nnheader-insert "211 %d %d %d %s\n" number 1 number group)))))
 
-(defun nndoc-request-type (group &optional article)
+(deffoo nndoc-request-type (group &optional article)
   (cond ((not article) 'unknown)
         (nndoc-post-type nndoc-post-type)
         (t 'unknown)))
 
-(defun nndoc-close-group (group &optional server)
+(deffoo nndoc-close-group (group &optional server)
   (nndoc-possibly-change-buffer group server)
   (and nndoc-current-buffer
        (buffer-name nndoc-current-buffer)
@@ -249,21 +210,19 @@ One of `mbox', `babyl', `digest', `news', `rnews', `mmdf', `forward',
   (setq nndoc-group-alist (delq (assoc group nndoc-group-alist)
                                nndoc-group-alist))
   (setq nndoc-current-buffer nil)
-  (setq nndoc-current-server nil)
+  (nnoo-close-server 'nndoc server)
   (setq nndoc-dissection-alist nil)
   t)
 
-(defun nndoc-request-list (&optional server)
+(deffoo nndoc-request-list (&optional server)
   nil)
 
-(defun nndoc-request-newgroups (date &optional server)
+(deffoo nndoc-request-newgroups (date &optional server)
   nil)
 
-(defun nndoc-request-list-newsgroups (&optional server)
+(deffoo nndoc-request-list-newsgroups (&optional server)
   nil)
 
-(defalias 'nndoc-request-post 'nnmail-request-post)
-
 \f
 ;;; Internal functions.
 
index 344fc4c..8026a55 100644 (file)
 
 (require 'nnheader)
 (require 'nnmh)
+(require 'nnoo)
 (eval-and-compile (require 'cl))
 
+(nnoo-declare nndraft)
+
 (eval-and-compile
   (autoload 'mail-send-and-exit "sendmail"))
 
-(defvar nndraft-directory nil
+(defvoo nndraft-directory nil
   "Where nndraft will store its directory.")
 
 \f
 
 (defconst nndraft-version "nndraft 1.0")
-(defvar nndraft-status-string "")
-
-\f
-
-(defvar nndraft-current-server nil)
-(defvar nndraft-server-alist nil)
-(defvar nndraft-server-variables 
-  `((nndraft-directory nil)
-    (nndraft-status-string "")
-    (nndraft-group-alist)))
+(defvoo nndraft-status-string "")
 
 \f
 
 ;;; Interface functions.
 
+(nnoo-define-basics nndraft)
 
-(defun nndraft-retrieve-headers (articles &optional group server fetch-old)
+(deffoo nndraft-retrieve-headers (articles &optional group server fetch-old)
   (save-excursion
     (set-buffer nntp-server-buffer)
     (erase-buffer)
@@ -84,8 +79,8 @@
        (nnheader-fold-continuation-lines)
        'headers))))
 
-(defun nndraft-open-server (server &optional defs)
-  (nnheader-change-server 'nndraft server defs)
+(deffoo nndraft-open-server (server &optional defs)
+  (nnoo-change-server 'nndraft server defs)
   (unless (assq 'nndraft-directory defs)
     (setq nndraft-directory server))
   (cond 
                     server nndraft-directory)
     t)))
 
-(defun nndraft-close-server (&optional server)
-  (setq nndraft-current-server nil)
-  t)
-
-(defun nndraft-server-opened (&optional server)
-  (and nntp-server-buffer
-       (get-buffer nntp-server-buffer)
-       nndraft-current-server
-       (equal nndraft-current-server server)))
-
-(defun nndraft-status-message (&optional server)
-  nndraft-status-string)
-
-(defun nndraft-request-article (id &optional group server buffer)
+(deffoo nndraft-request-article (id &optional group server buffer)
   (when (numberp id)
     ;; We get the newest file of the auto-saved file and the 
     ;; "real" file.
            (replace-match "" t t)))
        t))))
 
-(defun nndraft-request-restore-buffer (article &optional group server)
+(deffoo nndraft-request-restore-buffer (article &optional group server)
   "Request a new buffer that is restored to the state of ARTICLE."
   (let ((file (nndraft-article-filename article ".state"))
        nndraft-point nndraft-mode nndraft-buffer-name)
        (goto-char nndraft-point))
       nndraft-buffer-name)))
 
-(defun nndraft-request-update-info (group info &optional server)
+(deffoo nndraft-request-update-info (group info &optional server)
   (setcar (cddr info) nil)
   (when (nth 3 info)
     (setcar (nthcdr 3 info) nil))
   t)
 
-(defun nndraft-request-associate-buffer (group)
+(deffoo nndraft-request-associate-buffer (group)
   "Associate the current buffer with some article in the draft group."
   (let* ((gnus-verbose-backends nil)
         (article (cdr (nndraft-request-accept-article
-                       group nndraft-current-server t 'noinsert)))
+                       group (nnoo-current-server 'nndraft) t 'noinsert)))
         (file (nndraft-article-filename article)))
     (setq buffer-file-name file)
     (setq buffer-auto-save-file-name (make-auto-save-file-name))
     (clear-visited-file-modtime)
     article))
 
-(defun nndraft-request-group (group &optional server dont-check)
+(deffoo nndraft-request-group (group &optional server dont-check)
   (prog1
       (nndraft-execute-nnmh-command
        `(nnmh-request-group group "" ,dont-check))
     (nnheader-report 'nndraft nnmh-status-string)))
 
-(defun nndraft-request-list (&optional server dir)
+(deffoo nndraft-request-list (&optional server dir)
   (nndraft-execute-nnmh-command
    `(nnmh-request-list nil ,dir)))
 
-(defun nndraft-request-newgroups (date &optional server)
+(deffoo nndraft-request-newgroups (date &optional server)
   (nndraft-execute-nnmh-command
    `(nnmh-request-newgroups ,date ,server)))
 
-(defun nndraft-request-expire-articles 
+(deffoo nndraft-request-expire-articles 
   (articles group &optional server force)
   (let ((res (nndraft-execute-nnmh-command
              `(nnmh-request-expire-articles
            (funcall nnmail-delete-file-function auto)))))
     res))
 
-(defun nndraft-request-accept-article (group &optional server last noinsert)
+(deffoo nndraft-request-accept-article (group &optional server last noinsert)
   (let* ((point (point))
         (mode major-mode)
         (name (buffer-name))
       (kill-buffer (current-buffer)))
     gart))
 
-(defun nndraft-close-group (group &optional server)
+(deffoo nndraft-close-group (group &optional server)
   t)
 
-(defun nndraft-request-create-group (group &optional server)
+(deffoo nndraft-request-create-group (group &optional server)
   (if (file-exists-p nndraft-directory)
       (if (file-directory-p nndraft-directory)
          t
index c70d747..691c84f 100644 (file)
 
 (require 'nnheader)
 (require 'nnmail)
+(require 'nnoo)
 (eval-when-compile (require 'cl))
 
-(defvar nneething-map-file-directory "~/.nneething/"
+(nnoo-declare nneething)
+
+(defvoo nneething-map-file-directory "~/.nneething/"
   "*Where nneething stores the map files.")
 
-(defvar nneething-map-file ".nneething"
+(defvoo nneething-map-file ".nneething"
   "*Name of the map files.")
 
-(defvar nneething-exclude-files nil
+(defvoo nneething-exclude-files nil
   "*Regexp saying what files to exclude from the group.
 If this variable is nil, no files will be excluded.")
 
@@ -51,45 +54,28 @@ If this variable is nil, no files will be excluded.")
 (defconst nneething-version "nneething 1.0"
   "nneething version.")
 
-(defvar nneething-current-directory nil
+(defvoo nneething-current-directory nil
   "Current news group directory.")
 
-(defvar nneething-status-string "")
-(defvar nneething-group-alist nil)
-
-(defvar nneething-message-id-number 0)
-(defvar nneething-work-buffer " *nneething work*")
-
-(defvar nneething-directory nil)
-(defvar nneething-group nil)
-(defvar nneething-map nil)
-(defvar nneething-read-only nil)
-(defvar nneething-active nil)
+(defvoo nneething-status-string "")
+(defvoo nneething-group-alist nil)
 
-\f
+(defvoo nneething-message-id-number 0)
+(defvoo nneething-work-buffer " *nneething work*")
 
-(defvar nneething-current-server nil)
-(defvar nneething-server-alist)
-(defvar nneething-server-variables 
-  `((nneething-directory ,nneething-directory)
-    (nneething-current-directory nil)
-    (nneething-status-string "")
-    (nneething-active nil)
-    (nneething-read-only nil)
-    (nneething-map nil)
-    (nneething-group nil)
-    (nneething-work-buffer ,nneething-work-buffer)
-    (nneething-message-id-number ,nneething-message-id-number)
-    (nneething-exclude-files nil)
-    (nneething-map-file ,nneething-map-file)
-    (nneething-map-file-directory ,nneething-map-file-directory)
-    (nneething-group-alist nil)))
+(defvoo nneething-directory nil)
+(defvoo nneething-group nil)
+(defvoo nneething-map nil)
+(defvoo nneething-read-only nil)
+(defvoo nneething-active nil)
 
 \f
 
 ;;; Interface functions.
 
-(defun nneething-retrieve-headers (articles &optional group server fetch-old)
+(nnoo-define-basics nneething)
+
+(deffoo nneething-retrieve-headers (articles &optional group server fetch-old)
   (nneething-possibly-change-directory group)
 
   (save-excursion
@@ -127,21 +113,7 @@ If this variable is nil, no files will be excluded.")
        (nnheader-fold-continuation-lines)
        'headers))))
 
-(defun nneething-open-server (server &optional defs)
-  (nnheader-report 'nneething "")
-  (nnheader-init-server-buffer))
-
-(defun nneething-close-server (&optional server)
-  (setq nneething-current-directory nil)
-  t)
-
-(defun nneething-server-opened (&optional server)
-  nneething-current-directory)
-
-(defun nneething-status-message (&optional server)
-  nneething-status-string)
-
-(defun nneething-request-article (id &optional group server buffer)
+(deffoo nneething-request-article (id &optional group server buffer)
   (nneething-possibly-change-directory group)
   (let ((file (unless (stringp id) (nneething-file-name id)))
        (nntp-server-buffer (or buffer nntp-server-buffer)))
@@ -157,7 +129,7 @@ If this variable is nil, no files will be excluded.")
                 (insert "\n")))
           t))))
 
-(defun nneething-request-group (group &optional dir dont-check)
+(deffoo nneething-request-group (group &optional dir dont-check)
   (nneething-possibly-change-directory group dir)
   (unless dont-check
     (nneething-create-mapping)
@@ -170,16 +142,16 @@ If this variable is nil, no files will be excluded.")
        group)))
   t)
 
-(defun nneething-request-list (&optional server dir)
+(deffoo nneething-request-list (&optional server dir)
   (nnheader-report 'nneething "LIST is not implemented."))
 
-(defun nneething-request-newgroups (date &optional server)
+(deffoo nneething-request-newgroups (date &optional server)
   (nnheader-report 'nneething "NEWSGROUPS is not implemented."))
 
-(defun nneething-request-type (group &optional article)
+(deffoo nneething-request-type (group &optional article)
   'unknown)
 
-(defun nneething-close-group (group &optional server)
+(deffoo nneething-close-group (group &optional server)
   (setq nneething-current-directory nil)
   t)
 
index 258b02c..da44d31 100644 (file)
 (require 'nnheader)
 (require 'rmail)
 (require 'nnmail)
+(require 'nnoo)
 (eval-when-compile (require 'cl))
 
-(defvar nnfolder-directory (expand-file-name "~/Mail/")
+(nnoo-declare nnfolder)
+
+(defvoo nnfolder-directory (expand-file-name "~/Mail/")
   "The name of the nnfolder directory.")
 
-(defvar nnfolder-active-file 
+(defvoo nnfolder-active-file 
   (concat (file-name-as-directory nnfolder-directory) "active")
   "The name of the active file.")
 
 ;; I renamed this variable to something more in keeping with the general GNU
 ;; style. -SLB
 
-(defvar nnfolder-ignore-active-file nil
+(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.")
 
-(defvar nnfolder-newsgroups-file 
+(defvoo nnfolder-newsgroups-file 
   (concat (file-name-as-directory nnfolder-directory) "newsgroups")
   "Mail newsgroups description file.")
 
-(defvar nnfolder-get-new-mail t
+(defvoo nnfolder-get-new-mail t
   "If non-nil, nnfolder will check the incoming mail file and split the mail.")
 
-(defvar nnfolder-prepare-save-mail-hook nil
+(defvoo nnfolder-prepare-save-mail-hook nil
   "Hook run narrowed to an article before saving.")
 
-(defvar nnfolder-inhibit-expiry nil
+(defvoo nnfolder-inhibit-expiry nil
   "If non-nil, inhibit expiry.")
 
 \f
@@ -74,37 +77,20 @@ it.")
 (defconst nnfolder-article-marker "X-Gnus-Article-Number: "
   "String used to demarcate what the article number for a message is.")
 
-(defvar nnfolder-current-group nil)
-(defvar nnfolder-current-buffer nil)
-(defvar nnfolder-status-string "")
-(defvar nnfolder-group-alist nil)
-(defvar nnfolder-buffer-alist nil)
-(defvar nnfolder-active-timestamp nil)
-
-\f
-
-(defvar nnfolder-current-server nil)
-(defvar nnfolder-server-alist nil)
-(defvar nnfolder-server-variables 
-  `((nnfolder-directory ,nnfolder-directory)
-    (nnfolder-active-file ,nnfolder-active-file)
-    (nnfolder-newsgroups-file ,nnfolder-newsgroups-file)
-    (nnfolder-get-new-mail ,nnfolder-get-new-mail)
-    (nnfolder-inhibit-expiry ,nnfolder-inhibit-expiry) 
-    (nnfolder-current-group nil)
-    (nnfolder-prepare-save-mail-hook nil)
-    (nnfolder-ignore-active-file ,nnfolder-ignore-active-file)
-    (nnfolder-current-buffer nil)
-    (nnfolder-status-string "")
-    (nnfolder-group-alist nil)
-    (nnfolder-buffer-alist nil)
-    (nnfolder-active-timestamp nil)))
+(defvoo nnfolder-current-group nil)
+(defvoo nnfolder-current-buffer nil)
+(defvoo nnfolder-status-string "")
+(defvoo nnfolder-group-alist nil)
+(defvoo nnfolder-buffer-alist nil)
+(defvoo nnfolder-active-timestamp nil)
 
 \f
 
 ;;; Interface functions
 
-(defun nnfolder-retrieve-headers (articles &optional group server fetch-old)
+(nnoo-define-basics nnfolder)
+
+(deffoo nnfolder-retrieve-headers (articles &optional group server fetch-old)
   (save-excursion
     (set-buffer nntp-server-buffer)
     (erase-buffer)
@@ -141,8 +127,8 @@ it.")
        (nnheader-fold-continuation-lines)
        'headers))))
 
-(defun nnfolder-open-server (server &optional defs)
-  (nnheader-change-server 'nnfolder server defs)
+(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)
@@ -160,31 +146,16 @@ it.")
                     server nnfolder-directory)
     t)))
 
-(defun nnfolder-close-server (&optional server)
-  (setq nnfolder-current-server nil
-       nnfolder-group-alist nil)
-  t)
-
-(defun nnfolder-server-opened (&optional server)
-  (and (equal server nnfolder-current-server)
-       nntp-server-buffer
-       (buffer-name nntp-server-buffer)))
-
-(defun nnfolder-request-close ()
+(deffoo nnfolder-request-close ()
   (let ((alist nnfolder-buffer-alist))
     (while alist
       (nnfolder-close-group (caar alist) nil t)
       (setq alist (cdr alist))))
+  (nnoo-close-server 'nnfolder)
   (setq nnfolder-buffer-alist nil
-       nnfolder-server-alist nil
-       nnfolder-current-server nil
        nnfolder-group-alist nil))
 
-(defun nnfolder-status-message (&optional server)
-  (nnfolder-possibly-change-group nil server)
-  nnfolder-status-string)
-
-(defun nnfolder-request-article (article &optional group server buffer)
+(deffoo nnfolder-request-article (article &optional group server buffer)
   (nnfolder-possibly-change-group group server)
   (save-excursion
     (set-buffer nnfolder-current-buffer)
@@ -217,7 +188,7 @@ it.")
                     (buffer-substring 
                      (point) (progn (end-of-line) (point)))))))))))
 
-(defun nnfolder-request-group (group &optional server dont-check)
+(deffoo nnfolder-request-group (group &optional server dont-check)
   (save-excursion
     (nnmail-activate 'nnfolder)
     (if (not (assoc group nnfolder-group-alist))
@@ -239,7 +210,7 @@ it.")
                             (1+ (- (cdr range) (car range)))
                             (car range) (cdr range) group))))))))
 
-(defun nnfolder-request-scan (&optional group server)
+(deffoo nnfolder-request-scan (&optional group server)
   (nnfolder-possibly-change-group group server)
   (nnmail-get-new-mail
    'nnfolder 
@@ -262,7 +233,7 @@ it.")
 ;; over the buffer again unless we add new mail to it or modify it in some
 ;; way.
 
-(defun nnfolder-close-group (group &optional server force)
+(deffoo nnfolder-close-group (group &optional server force)
   ;; Make sure we _had_ the group open.
   (when (or (assoc group nnfolder-buffer-alist)
            (equal group nnfolder-current-group))
@@ -282,7 +253,7 @@ it.")
        nnfolder-current-buffer nil)
   t)
 
-(defun nnfolder-request-create-group (group &optional server) 
+(deffoo nnfolder-request-create-group (group &optional server) 
   (nnfolder-possibly-change-group nil server)
   (nnmail-activate 'nnfolder)
   (when group 
@@ -291,22 +262,22 @@ it.")
       (nnmail-save-active nnfolder-group-alist nnfolder-active-file)))
   t)
 
-(defun nnfolder-request-list (&optional server)
+(deffoo nnfolder-request-list (&optional server)
   (nnfolder-possibly-change-group nil server)
   (save-excursion
     (nnmail-find-file nnfolder-active-file)
     (setq nnfolder-group-alist (nnmail-get-active))))
 
-(defun nnfolder-request-newgroups (date &optional server)
+(deffoo nnfolder-request-newgroups (date &optional server)
   (nnfolder-possibly-change-group nil server)
   (nnfolder-request-list server))
 
-(defun nnfolder-request-list-newsgroups (&optional server)
+(deffoo nnfolder-request-list-newsgroups (&optional server)
   (nnfolder-possibly-change-group nil server)
   (save-excursion
     (nnmail-find-file nnfolder-newsgroups-file)))
 
-(defun nnfolder-request-expire-articles 
+(deffoo nnfolder-request-expire-articles 
   (articles newsgroup &optional server force)
   (nnfolder-possibly-change-group newsgroup server)
   (let* ((is-old t)
@@ -347,7 +318,7 @@ it.")
       (nnmail-save-active nnfolder-group-alist nnfolder-active-file)
       (nconc rest articles))))
 
-(defun nnfolder-request-move-article
+(deffoo nnfolder-request-move-article
   (article group server accept-form &optional last)
   (nnfolder-possibly-change-group group server)
   (let ((buf (get-buffer-create " *nnfolder move*"))
@@ -379,7 +350,7 @@ it.")
            (save-buffer))))
     result))
 
-(defun nnfolder-request-accept-article (group &optional server last)
+(deffoo nnfolder-request-accept-article (group &optional server last)
   (nnfolder-possibly-change-group group server)
   (and (stringp group) (nnfolder-possibly-change-group group))
   (let ((buf (current-buffer))
@@ -405,7 +376,7 @@ it.")
       (nnheader-report 'nnfolder "Couldn't store article"))
     result))
 
-(defun nnfolder-request-replace-article (article group buffer)
+(deffoo nnfolder-request-replace-article (article group buffer)
   (nnfolder-possibly-change-group group)
   (save-excursion
     (set-buffer nnfolder-current-buffer)
@@ -417,7 +388,7 @@ it.")
       (and (buffer-modified-p) (save-buffer))
       t)))
 
-(defun nnfolder-request-delete-group (group &optional force server)
+(deffoo nnfolder-request-delete-group (group &optional force server)
   (nnfolder-close-group group server t)
   ;; Delete all articles in GROUP.
   (if (not force)
@@ -435,7 +406,7 @@ it.")
   (nnmail-save-active nnfolder-group-alist nnfolder-active-file)
   t)
 
-(defun nnfolder-request-rename-group (group new-name &optional server)
+(deffoo nnfolder-request-rename-group (group new-name &optional server)
   (nnfolder-possibly-change-group group server)
   (save-excursion
     (set-buffer nnfolder-current-buffer)
index c3dcb7b..4b35929 100644 (file)
@@ -192,7 +192,7 @@ on your system, you could say something like:
     (set (caar state) (nth 1 (car state)))
     (setq state (cdr state))))
 
-(defun nnheader-change-server (backend server defs)
+(defun nnheader-change-server-old (backend server defs)
   (nnheader-init-server-buffer)
   (let ((current-server (intern (format "%s-current-server" backend)))
        (alist (intern (format "%s-server-alist" backend)))
@@ -461,7 +461,7 @@ without formatting."
       (and (listp form) (eq (car form) 'lambda))))
 
 (fset 'nnheader-find-file-noselect 'find-file-noselect)
-  
+
 (provide 'nnheader)
 
 ;;; nnheader.el ends here
index 5025c79..cb7023a 100644 (file)
 (require 'nnheader)
 (require 'gnus)
 (require 'gnus-score)
+(require 'nnoo)
 (eval-when-compile (require 'cl))
 
-(defvar nnkiboze-directory 
+(nnoo-declare nnkiboze)
+
+(defvoo nnkiboze-directory 
   (expand-file-name (or gnus-article-save-directory "~/News/"))
   "nnkiboze will put its files in this directory.")
 
-(defvar nnkiboze-level 9
+(defvoo nnkiboze-level 9
   "*The maximum level to be searched for articles.")
 
-(defvar nnkiboze-remove-read-articles t
+(defvoo nnkiboze-remove-read-articles t
   "*If non-nil, nnkiboze will remove read articles from the kiboze group.")
 
 \f
 (defconst nnkiboze-version "nnkiboze 1.0"
   "Version numbers of this version of nnkiboze.")
 
-(defvar nnkiboze-current-group nil)
-(defvar nnkiboze-current-score-group "")
-(defvar nnkiboze-status-string "")
+(defvoo nnkiboze-current-group nil)
+(defvoo nnkiboze-current-score-group "")
+(defvoo nnkiboze-status-string "")
 
 \f
 
 ;;; Interface functions.
 
-(defun nnkiboze-retrieve-headers (articles &optional group server fetch-old)
+(nnoo-define-basics nnkiboze)
+
+(deffoo nnkiboze-retrieve-headers (articles &optional group server fetch-old)
   (nnkiboze-possibly-change-newsgroups group)
   (if gnus-nov-is-evil
       nil
              (if (not (eobp)) (delete-region (point) (point-max)))
              'nov))))))
 
-(defun nnkiboze-open-server (newsgroups &optional something)
-  "Open a virtual newsgroup that contains NEWSGROUPS."
+(deffoo nnkiboze-open-server (newsgroups &optional something)
   (gnus-make-directory nnkiboze-directory)
   (nnheader-init-server-buffer))
 
-(defun nnkiboze-close-server (&rest dum)
-  "Close news server."
-  t)
-
-(defalias 'nnkiboze-request-quit (symbol-function 'nnkiboze-close-server))
-
-(defun nnkiboze-server-opened (&optional server)
-  "Return server process status, T or NIL.
-If the stream is opened, return T, otherwise return NIL."
+(deffoo nnkiboze-server-opened (&optional server)
   (and nntp-server-buffer
        (get-buffer nntp-server-buffer)))
 
-(defun nnkiboze-status-message (&optional server)
-  "Return server status response as string."
-  nnkiboze-status-string)
-
-(defun nnkiboze-request-article (article &optional newsgroup server buffer)
-  "Select article by message number."
+(deffoo nnkiboze-request-article (article &optional newsgroup server buffer)
   (nnkiboze-possibly-change-newsgroups newsgroup)
   (if (not (numberp article))
       ;; This is a real kludge. It might not work at times, but it
@@ -125,7 +116,7 @@ If the stream is opened, return T, otherwise return NIL."
       (and (gnus-request-group igroup t)
           (gnus-request-article iarticle igroup buffer)))))
 
-(defun nnkiboze-request-group (group &optional server dont-check)
+(deffoo nnkiboze-request-group (group &optional server dont-check)
   "Make GROUP the current newsgroup."
   (nnkiboze-possibly-change-newsgroups group)
   (if dont-check
@@ -150,7 +141,7 @@ If the stream is opened, return T, otherwise return NIL."
            (insert (format "211 %d %d %d %s\n" total beg end group)))))))
   t)
 
-(defun nnkiboze-close-group (group &optional server)
+(deffoo nnkiboze-close-group (group &optional server)
   (nnkiboze-possibly-change-newsgroups group)
   ;; Remove NOV lines of articles that are marked as read.
   (when (and (file-exists-p (nnkiboze-nov-file-name))
@@ -177,17 +168,17 @@ If the stream is opened, return T, otherwise return NIL."
          (kill-buffer (current-buffer)))))
     (setq nnkiboze-current-group nil)))
 
-(defun nnkiboze-request-list (&optional server) 
+(deffoo nnkiboze-request-list (&optional server) 
   (nnheader-report 'nnkiboze "LIST is not implemented."))
 
-(defun nnkiboze-request-newgroups (date &optional server)
+(deffoo nnkiboze-request-newgroups (date &optional server)
   "List new groups."
   (nnheader-report 'nnkiboze "NEWGROUPS is not supported."))
 
-(defun nnkiboze-request-list-newsgroups (&optional server)
+(deffoo nnkiboze-request-list-newsgroups (&optional server)
   (nnheader-report 'nnkiboze "LIST NEWSGROUPS is not implemented."))
 
-(defun nnkiboze-request-delete-group (group &optional force server)
+(deffoo nnkiboze-request-delete-group (group &optional force server)
   (nnkiboze-possibly-change-newsgroups group)
   (when force
      (let ((files (list (nnkiboze-nov-file-name)
index 21d4446..80556f6 100644 (file)
 (require 'nnheader)
 (require 'rmail)
 (require 'nnmail)
+(require 'nnoo)
 (eval-when-compile (require 'cl))
 
-(defvar nnmbox-mbox-file (expand-file-name "~/mbox")
+(nnoo-declare nnmbox)
+
+(defvoo nnmbox-mbox-file (expand-file-name "~/mbox")
   "The name of the mail box file in the user's home directory.")
 
-(defvar nnmbox-active-file (expand-file-name "~/.mbox-active")
+(defvoo nnmbox-active-file (expand-file-name "~/.mbox-active")
   "The name of the active file for the mail box.")
 
-(defvar nnmbox-get-new-mail t
+(defvoo nnmbox-get-new-mail t
   "If non-nil, nnmbox will check the incoming mail file and split the mail.")
 
-(defvar nnmbox-prepare-save-mail-hook nil
+(defvoo nnmbox-prepare-save-mail-hook nil
   "Hook run narrowed to an article before saving.")
 
 \f
 (defconst nnmbox-version "nnmbox 1.0"
   "nnmbox version.")
 
-(defvar nnmbox-current-group nil
+(defvoo nnmbox-current-group nil
   "Current nnmbox news group directory.")
 
 (defconst nnmbox-mbox-buffer nil)
 
-(defvar nnmbox-status-string "")
-
-(defvar nnmbox-group-alist nil)
-(defvar nnmbox-active-timestamp nil)
-
-\f
+(defvoo nnmbox-status-string "")
 
-(defvar nnmbox-current-server nil)
-(defvar nnmbox-server-alist nil)
-(defvar nnmbox-server-variables 
-  `((nnmbox-mbox-file ,nnmbox-mbox-file)
-    (nnmbox-active-file ,nnmbox-active-file)
-    (nnmbox-get-new-mail ,nnmbox-get-new-mail)
-    (nnmbox-current-group nil)
-    (nnmbox-active-timestamp nil)
-    (nnmbox-prepare-save-mail-hook nil)
-    (nnmbox-status-string "")
-    (nnmbox-group-alist nil)))
+(defvoo nnmbox-group-alist nil)
+(defvoo nnmbox-active-timestamp nil)
 
 \f
 
 ;;; Interface functions
 
-(defun nnmbox-retrieve-headers (sequence &optional newsgroup server fetch-old)
+(nnoo-define-basics nnmbox)
+
+(deffoo nnmbox-retrieve-headers (sequence &optional newsgroup server fetch-old)
   (save-excursion
     (set-buffer nntp-server-buffer)
     (erase-buffer)
       (nnheader-fold-continuation-lines)
       'headers)))
 
-(defun nnmbox-open-server (server &optional defs)
-  (nnheader-change-server 'nnmbox server defs)
+(deffoo nnmbox-open-server (server &optional defs)
+  (nnoo-change-server 'nnmbox server defs)
   (cond 
    ((not (file-exists-p nnmbox-mbox-file))
     (nnmbox-close-server)
                     nnmbox-mbox-file)
     t)))
 
-(defun nnmbox-close-server (&optional server)
+(deffoo nnmbox-close-server (&optional server)
   (when (and nnmbox-mbox-buffer
             (buffer-name nnmbox-mbox-buffer))
     (kill-buffer nnmbox-mbox-buffer))
-  (setq nnmbox-current-server nil)
+  (nnoo-close-server 'nnmbox server)
   t)
 
-(defun nnmbox-server-opened (&optional server)
-  (and (equal server nnmbox-current-server)
+(deffoo nnmbox-server-opened (&optional server)
+  (and (nnoo-current-server-p 'nnmbox server)
        nnmbox-mbox-buffer
        (buffer-name nnmbox-mbox-buffer)
        nntp-server-buffer
        (buffer-name nntp-server-buffer)))
 
-(defun nnmbox-status-message (&optional server)
-  nnmbox-status-string)
-
-(defun nnmbox-request-article (article &optional newsgroup server buffer)
+(deffoo nnmbox-request-article (article &optional newsgroup server buffer)
   (nnmbox-possibly-change-newsgroup newsgroup server)
   (save-excursion
     (set-buffer nnmbox-mbox-buffer)
                (cons nnmbox-current-group article)
              (nnmbox-article-group-number)))))))
 
-(defun nnmbox-request-group (group &optional server dont-check)
+(deffoo nnmbox-request-group (group &optional server dont-check)
   (let ((active (cadr (assoc group nnmbox-group-alist))))
     (cond 
      ((null active)
                       (car active) (cdr active) group)
       t))))
 
-(defun nnmbox-request-scan (&optional group server)
+(deffoo nnmbox-request-scan (&optional group server)
   (nnmbox-read-mbox)
   (nnmail-get-new-mail 
    'nnmbox 
         (goto-char (point-max))
         (insert-buffer-substring in-buf))))))
 
-(defun nnmbox-close-group (group &optional server)
+(deffoo nnmbox-close-group (group &optional server)
   t)
 
-(defun nnmbox-request-list (&optional server)
+(deffoo nnmbox-request-list (&optional server)
   (save-excursion
     (or (nnmail-find-file nnmbox-active-file)
        (progn
          (nnmail-save-active nnmbox-group-alist nnmbox-active-file)
          (nnmail-find-file nnmbox-active-file)))))
 
-(defun nnmbox-request-newgroups (date &optional server)
+(deffoo nnmbox-request-newgroups (date &optional server)
   (nnmbox-request-list server))
 
-(defun nnmbox-request-list-newsgroups (&optional server)
+(deffoo nnmbox-request-list-newsgroups (&optional server)
   (nnheader-report 'nnmbox "LIST NEWSGROUPS is not implemented."))
 
-(defun nnmbox-request-expire-articles 
+(deffoo nnmbox-request-expire-articles 
   (articles newsgroup &optional server force)
   (nnmbox-possibly-change-newsgroup newsgroup server)
   (let* ((is-old t)
       (nnmail-save-active nnmbox-group-alist nnmbox-active-file)
       (nconc rest articles))))
 
-(defun nnmbox-request-move-article
+(deffoo nnmbox-request-move-article
   (article group server accept-form &optional last)
   (nnmbox-possibly-change-newsgroup group server)
   (let ((buf (get-buffer-create " *nnmbox move*"))
        (and last (save-buffer))))
     result))
 
-(defun nnmbox-request-accept-article (group &optional server last)
+(deffoo nnmbox-request-accept-article (group &optional server last)
   (nnmbox-possibly-change-newsgroup group server)
   (let ((buf (current-buffer))
        result)
      (nnmail-save-active nnmbox-group-alist nnmbox-active-file))
     (car result)))
 
-(defun nnmbox-request-replace-article (article group buffer)
+(deffoo nnmbox-request-replace-article (article group buffer)
   (nnmbox-possibly-change-newsgroup group)
   (save-excursion
     (set-buffer nnmbox-mbox-buffer)
       (save-buffer)
       t)))
 
-(defun nnmbox-request-delete-group (group &optional force server)
+(deffoo nnmbox-request-delete-group (group &optional force server)
   (nnmbox-possibly-change-newsgroup group server)
   ;; Delete all articles in GROUP.
   (if (not force)
   (nnmail-save-active nnmbox-group-alist nnmbox-active-file)
   t)
 
-(defun nnmbox-request-rename-group (group new-name &optional server)
+(deffoo nnmbox-request-rename-group (group new-name &optional server)
   (nnmbox-possibly-change-newsgroup group server)
   (save-excursion
     (set-buffer nnmbox-mbox-buffer)
index c3617ec..eb4cea3 100644 (file)
 (require 'rmail)
 (require 'nnmail)
 (require 'gnus)
+(require 'nnoo)
 (eval-and-compile (require 'cl))
 
-(defvar nnmh-directory "~/Mail/"
+(nnoo-declare nnmh)
+
+(defvoo nnmh-directory "~/Mail/"
   "*Mail spool directory.")
 
-(defvar nnmh-get-new-mail t
+(defvoo nnmh-get-new-mail t
   "*If non-nil, nnmh will check the incoming mail file and split the mail.")
 
-(defvar nnmh-prepare-save-mail-hook nil
+(defvoo nnmh-prepare-save-mail-hook nil
   "*Hook run narrowed to an article before saving.")
 
-(defvar nnmh-be-safe nil
+(defvoo nnmh-be-safe nil
   "*If non-nil, nnmh will check all articles to make sure whether they are new or not.")
 
 \f
 (defconst nnmh-version "nnmh 1.0"
   "nnmh version.")
 
-(defvar nnmh-current-directory nil
+(defvoo nnmh-current-directory nil
   "Current news group directory.")
 
-(defvar nnmh-status-string "")
-(defvar nnmh-group-alist nil)
-
-\f
-
-(defvar nnmh-current-server nil)
-(defvar nnmh-server-alist nil)
-(defvar nnmh-server-variables 
-  `((nnmh-directory ,nnmh-directory)
-    (nnmh-get-new-mail ,nnmh-get-new-mail)
-    (nnmh-be-safe nil)
-    (nnmh-prepare-save-mail-hook nil)
-    (nnmh-current-directory nil)
-    (nnmh-status-string "")
-    (nnmh-group-alist)))
+(defvoo nnmh-status-string "")
+(defvoo nnmh-group-alist nil)
 
 \f
 
 ;;; Interface functions.
 
-(defun nnmh-retrieve-headers (articles &optional newsgroup server fetch-old)
+(nnoo-define-basics nnmh)
+
+(deffoo nnmh-retrieve-headers (articles &optional newsgroup server fetch-old)
   (save-excursion
     (set-buffer nntp-server-buffer)
     (erase-buffer)
        (nnheader-fold-continuation-lines)
        'headers))))
 
-(defun nnmh-open-server (server &optional defs)
-  (nnheader-change-server 'nnmh server defs)
+(deffoo nnmh-open-server (server &optional defs)
+  (nnoo-change-server 'nnmh server defs)
   (when (not (file-exists-p nnmh-directory))
     (condition-case ()
        (make-directory nnmh-directory t)
                     server nnmh-directory)
     t)))
 
-(defun nnmh-close-server (&optional server)
-  (setq nnmh-current-server nil
-       nnmh-group-alist nil)
-  t)
-
-(defun nnmh-server-opened (&optional server)
-  (and (equal server nnmh-current-server)
-       nntp-server-buffer
-       (buffer-name nntp-server-buffer)))
-
-(defun nnmh-status-message (&optional server)
-  nnmh-status-string)
-
-(defun nnmh-request-article (id &optional newsgroup server buffer)
+(deffoo nnmh-request-article (id &optional newsgroup server buffer)
   (nnmh-possibly-change-directory newsgroup server)
   (let ((file (if (stringp id)
                  nil
         (save-excursion (nnmail-find-file file))
         (string-to-int (file-name-nondirectory file)))))
 
-(defun nnmh-request-group (group &optional server dont-check)
+(deffoo nnmh-request-group (group &optional server dont-check)
   (let ((pathname (nnmail-group-pathname group nnmh-directory))
        dir)
     (cond 
            (nnheader-report 'nnmh "Empty group %s" group)
            (nnheader-insert (format "211 0 1 0 %s\n" group))))))))))
 
-(defun nnmh-request-scan (&optional group server)
+(deffoo nnmh-request-scan (&optional group server)
   (nnmail-get-new-mail 'nnmh nil nnmh-directory group))      
 
-(defun nnmh-request-list (&optional server dir)
+(deffoo nnmh-request-list (&optional server dir)
   (unless dir
     (nnheader-insert "")
     (setq dir (file-truename (file-name-as-directory nnmh-directory))))
   (setq nnmh-group-alist (nnmail-get-active))
   t)
 
-(defun nnmh-request-newgroups (date &optional server)
+(deffoo nnmh-request-newgroups (date &optional server)
   (nnmh-request-list server))
 
-(defun nnmh-request-expire-articles (articles newsgroup &optional server force)
+(deffoo nnmh-request-expire-articles (articles newsgroup &optional server force)
   (nnmh-possibly-change-directory newsgroup server)
   (let* ((active-articles 
          (mapcar
     (message "")
     (nconc rest articles)))
 
-(defun nnmh-close-group (group &optional server)
+(deffoo nnmh-close-group (group &optional server)
   t)
 
-(defun nnmh-request-move-article 
+(deffoo nnmh-request-move-article 
   (article group server accept-form &optional last)
   (let ((buf (get-buffer-create " *nnmh move*"))
        result)
        (file-error nil)))
     result))
 
-(defun nnmh-request-accept-article (group &optional server last noinsert)
+(deffoo nnmh-request-accept-article (group &optional server last noinsert)
   (nnmh-possibly-change-directory group server)
   (if (stringp group)
       (and 
      (nnmail-activate 'nnmh)
      (car (nnmh-save-mail noinsert)))))
 
-(defun nnmh-request-replace-article (article group buffer)
+(deffoo nnmh-request-replace-article (article group buffer)
   (nnmh-possibly-change-directory group)
   (save-excursion
     (set-buffer buffer)
          t)
       (error nil))))
 
-(defun nnmh-request-create-group (group &optional server) 
+(deffoo nnmh-request-create-group (group &optional server) 
   (nnmail-activate 'nnmh)
   (or (assoc group nnmh-group-alist)
       (let (active)
                 (setcdr active (apply 'max articles)))))))
   t)
 
-(defun nnmh-request-delete-group (group &optional force server)
+(deffoo nnmh-request-delete-group (group &optional force server)
   (nnmh-possibly-change-directory group server)
   ;; Delete all articles in GROUP.
   (if (not force)
        nnmh-current-directory nil)
   t)
 
-(defun nnmh-request-rename-group (group new-name &optional server)
+(deffoo nnmh-request-rename-group (group new-name &optional server)
   (nnmh-possibly-change-directory group server)
   ;; Rename directory.
   (and (file-writable-p nnmh-current-directory)
index e8f0c6e..f151bca 100644 (file)
 
 (require 'nnheader)
 (require 'nnmail)
+(require 'nnoo)
 (eval-when-compile (require 'cl))
 
-(defvar nnml-directory "~/Mail/"
+(nnoo-declare nnml)
+
+(defvoo nnml-directory "~/Mail/"
   "Mail spool directory.")
 
-(defvar nnml-active-file 
+(defvoo nnml-active-file 
   (concat (file-name-as-directory nnml-directory) "active")
   "Mail active file.")
 
-(defvar nnml-newsgroups-file 
+(defvoo nnml-newsgroups-file 
   (concat (file-name-as-directory nnml-directory) "newsgroups")
   "Mail newsgroups description file.")
 
-(defvar nnml-get-new-mail t
+(defvoo nnml-get-new-mail t
   "If non-nil, nnml will check the incoming mail file and split the mail.")
 
-(defvar nnml-nov-is-evil nil
+(defvoo nnml-nov-is-evil nil
   "If non-nil, Gnus will never generate and use nov databases for mail groups.
 Using nov databases will speed up header fetching considerably.
 This variable shouldn't be flipped much. If you have, for some reason,
@@ -57,10 +60,10 @@ the `nnml-generate-nov-databases' command. The function will go
 through all nnml directories and generate nov databases for them
 all. This may very well take some time.")
 
-(defvar nnml-prepare-save-mail-hook nil
+(defvoo nnml-prepare-save-mail-hook nil
   "Hook run narrowed to an article before saving.")
 
-(defvar nnml-inhibit-expiry nil
+(defvoo nnml-inhibit-expiry nil
   "If non-nil, inhibit expiry.")
 
 
@@ -69,47 +72,25 @@ all. This may very well take some time.")
 (defconst nnml-version "nnml 1.0"
   "nnml version.")
 
-(defvar nnml-nov-file-name ".overview")
-
-(defvar nnml-current-directory nil)
-(defvar nnml-current-group nil)
-(defvar nnml-status-string "")
-(defvar nnml-nov-buffer-alist nil)
-(defvar nnml-group-alist nil)
-(defvar nnml-active-timestamp nil)
-(defvar nnml-article-file-alist nil)
-
-(defvar nnml-generate-active-function 'nnml-generate-active-info)
+(defvoo nnml-nov-file-name ".overview")
 
-\f
+(defvoo nnml-current-directory nil)
+(defvoo nnml-current-group nil)
+(defvoo nnml-status-string "")
+(defvoo nnml-nov-buffer-alist nil)
+(defvoo nnml-group-alist nil)
+(defvoo nnml-active-timestamp nil)
+(defvoo nnml-article-file-alist nil)
 
-;; Server variables.
-
-(defvar nnml-current-server nil)
-(defvar nnml-server-alist nil)
-(defvar nnml-server-variables 
-  `((nnml-directory ,nnml-directory)
-    (nnml-active-file ,nnml-active-file)
-    (nnml-newsgroups-file ,nnml-newsgroups-file)
-    (nnml-get-new-mail ,nnml-get-new-mail)
-    (nnml-nov-is-evil ,nnml-nov-is-evil)
-    (nnml-nov-file-name ,nnml-nov-file-name)
-    (nnml-current-directory nil)
-    (nnml-generate-active-function ,nnml-generate-active-function)
-    (nnml-article-file-alist nil)
-    (nnml-prepare-save-mail-hook ,nnml-prepare-save-mail-hook)
-    (nnml-current-group nil)
-    (nnml-inhibit-expiry ,nnml-inhibit-expiry)
-    (nnml-status-string "")
-    (nnml-nov-buffer-alist nil)
-    (nnml-group-alist nil)
-    (nnml-active-timestamp nil)))
+(defvoo nnml-generate-active-function 'nnml-generate-active-info)
 
 \f
 
 ;;; Interface functions.
 
-(defun nnml-retrieve-headers (sequence &optional newsgroup server fetch-old)
+(nnoo-define-basics nnml)
+
+(deffoo nnml-retrieve-headers (sequence &optional newsgroup server fetch-old)
   (save-excursion
     (set-buffer nntp-server-buffer)
     (erase-buffer)
@@ -159,8 +140,8 @@ all. This may very well take some time.")
          (nnheader-fold-continuation-lines)
          'headers)))))
 
-(defun nnml-open-server (server &optional defs)
-  (nnheader-change-server 'nnml server defs)
+(deffoo nnml-open-server (server &optional defs)
+  (nnoo-change-server 'nnml server defs)
   (when (not (file-exists-p nnml-directory))
     (condition-case ()
        (make-directory nnml-directory t)
@@ -177,20 +158,7 @@ all. This may very well take some time.")
                     server nnml-directory)
     t)))
 
-(defun nnml-close-server (&optional server)
-  (setq nnml-current-server nil
-       nnml-group-alist nil)
-  t)
-
-(defun nnml-server-opened (&optional server)
-  (and (equal server nnml-current-server)
-       nntp-server-buffer
-       (buffer-name nntp-server-buffer)))
-
-(defun nnml-status-message (&optional server)
-  nnml-status-string)
-
-(defun nnml-request-article (id &optional newsgroup server buffer)
+(deffoo nnml-request-article (id &optional newsgroup server buffer)
   (nnml-possibly-change-directory newsgroup server)
   (let* ((nntp-server-buffer (or buffer nntp-server-buffer))
         file path gpath group-num)
@@ -223,7 +191,7 @@ all. This may very well take some time.")
       ;; We return the article number.
       (cons newsgroup (string-to-int (file-name-nondirectory path)))))))
 
-(defun nnml-request-group (group &optional server dont-check)
+(deffoo nnml-request-group (group &optional server dont-check)
   (cond 
    ((not (nnml-possibly-change-directory group server))
     (nnheader-report 'nnml "Invalid group (no such directory)"))
@@ -240,21 +208,15 @@ all. This may very well take some time.")
                         (max (1+ (- (cdr active) (car active))) 0)
                         (car active) (cdr active) group))))))
 
-(defun nnml-request-scan (&optional group server)
+(deffoo nnml-request-scan (&optional group server)
   (setq nnml-article-file-alist nil)
   (nnmail-get-new-mail 'nnml 'nnml-save-nov nnml-directory group))
 
-(defun nnml-close-group (group &optional server)
+(deffoo nnml-close-group (group &optional server)
   (setq nnml-article-file-alist nil)
   t)
 
-(defun nnml-request-close ()
-  (setq nnml-current-server nil
-       nnml-article-file-alist nil
-       nnml-server-alist nil)
-  t)
-
-(defun nnml-request-create-group (group &optional server) 
+(deffoo nnml-request-create-group (group &optional server) 
   (nnmail-activate 'nnml)
   (or (assoc group nnml-group-alist)
       (let (active)
@@ -271,19 +233,19 @@ all. This may very well take some time.")
        (nnmail-save-active nnml-group-alist nnml-active-file)))
   t)
 
-(defun nnml-request-list (&optional server)
+(deffoo nnml-request-list (&optional server)
   (save-excursion
     (nnmail-find-file nnml-active-file)
     (setq nnml-group-alist (nnmail-get-active))))
 
-(defun nnml-request-newgroups (date &optional server)
+(deffoo nnml-request-newgroups (date &optional server)
   (nnml-request-list server))
 
-(defun nnml-request-list-newsgroups (&optional server)
+(deffoo nnml-request-list-newsgroups (&optional server)
   (save-excursion
     (nnmail-find-file nnml-newsgroups-file)))
 
-(defun nnml-request-expire-articles (articles newsgroup &optional server force)
+(deffoo nnml-request-expire-articles (articles newsgroup &optional server force)
   (nnml-possibly-change-directory newsgroup server)
   (let* ((active-articles 
          (nnheader-directory-articles nnml-current-directory))
@@ -324,7 +286,7 @@ all. This may very well take some time.")
     (message "")
     (nconc rest articles)))
 
-(defun nnml-request-move-article 
+(deffoo nnml-request-move-article 
   (article group server accept-form &optional last)
   (let ((buf (get-buffer-create " *nnml move*"))
        result)
@@ -351,7 +313,7 @@ all. This may very well take some time.")
        (and last (nnml-save-nov))))
     result))
 
-(defun nnml-request-accept-article (group &optional server last)
+(deffoo nnml-request-accept-article (group &optional server last)
   (nnml-possibly-change-directory group server)
   (let (result)
     (if (stringp group)
@@ -372,7 +334,7 @@ all. This may very well take some time.")
         (and last (nnml-save-nov)))))
     result))
 
-(defun nnml-request-replace-article (article group buffer)
+(deffoo nnml-request-replace-article (article group buffer)
   (nnml-possibly-change-directory group)
   (save-excursion
     (set-buffer buffer)
@@ -413,7 +375,7 @@ all. This may very well take some time.")
          (nnml-save-nov)
          t)))))
 
-(defun nnml-request-delete-group (group &optional force server)
+(deffoo nnml-request-delete-group (group &optional force server)
   (nnml-possibly-change-directory group server)
   (when force
     ;; Delete all articles in GROUP.
@@ -441,7 +403,7 @@ all. This may very well take some time.")
   (nnmail-save-active nnml-group-alist nnml-active-file)
   t)
 
-(defun nnml-request-rename-group (group new-name &optional server)
+(deffoo nnml-request-rename-group (group new-name &optional server)
   (nnml-possibly-change-directory group server)
   ;; Rename directory.
   (and (file-writable-p nnml-current-directory)
@@ -725,7 +687,7 @@ all. This may very well take some time.")
   ;; Read the active file to make sure we don't re-use articles 
   ;; numbers in empty groups.
   (nnmail-activate 'nnml)
-  (nnml-open-server (or nnml-current-server ""))
+  (nnml-open-server (or (nnoo-current-server 'nnml) ""))
   (setq nnml-directory (expand-file-name nnml-directory))
   ;; Recurse down the directories.
   (nnml-generate-nov-databases-1 nnml-directory)
@@ -753,6 +715,7 @@ all. This may very well take some time.")
       ;; Generate the nov file.
       (nnml-generate-nov-file dir files))))
 
+(defvar files)
 (defun nnml-generate-active-info (dir)
   ;; Update the active info for this group.
   (let ((group (nnheader-file-to-group 
diff --git a/lisp/nnoo.el b/lisp/nnoo.el
new file mode 100644 (file)
index 0000000..cddba4a
--- /dev/null
@@ -0,0 +1,251 @@
+;;; nnoo.el --- OO Gnus Backends
+;; Copyright (C) 1996 Free Software Foundation, Inc.
+
+;; Author: Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
+;; Keywords: news
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; 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.
+
+;;; Commentary:
+
+;;; Code:
+
+(eval-when-compile (require 'cl))
+
+(defvar nnoo-definition-alist nil)
+(defvar nnoo-state-alist nil)
+
+(defmacro defvoo (var init &optional doc &rest map)
+  "The same as `defvar', only takes list of variables to MAP to."
+  `(prog1
+       ,(if doc
+           `(defvar ,var ,init ,doc)
+         `(defvar ,var ,init))
+     (nnoo-define ',var ',map)))
+(put 'defvoo 'lisp-indent-function 2)
+(put 'defvoo 'lisp-indent-hook 2)
+(put 'defvoo 'edebug-form-spec '(var init &optional doc &rest map))
+
+(defmacro deffoo (func args &rest forms)
+  "The same as `defun', only register FUNC."
+  `(prog1
+       (defun ,func ,args ,@forms)
+     (nnoo-register-function ',func)))
+(put 'deffoo 'lisp-indent-function 2)
+(put 'deffoo 'lisp-indent-hook 2)
+(put 'deffoo 'edebug-form-spec '(&define name lambda-list def-body))
+
+(defun nnoo-register-function (func)
+  (let ((funcs (nthcdr 3 (assoc (nnoo-backend func) 
+                               nnoo-definition-alist))))
+    (unless funcs
+      (error "%s belongs to a backend that hasn't been declared" func))
+    (setcar funcs (cons func (car funcs)))))
+
+(defmacro nnoo-declare (backend &rest parents)
+  `(eval-and-compile
+     (push (list ',backend 
+                (mapcar (lambda (p) (list p)) ',parents)
+                nil nil)
+          nnoo-definition-alist)))
+(put 'nnoo-declare 'lisp-indent-function 1)
+(put 'nnoo-declare 'lisp-indent-hook 1)
+
+(defun nnoo-parents (backend)
+  (nth 1 (assoc backend nnoo-definition-alist)))
+
+(defun nnoo-variables (backend)
+  (nth 2 (assoc backend nnoo-definition-alist)))
+
+(defun nnoo-functions (backend)
+  (nth 3 (assoc backend nnoo-definition-alist)))
+
+(defmacro nnoo-import (backend &rest imports)
+  `(nnoo-import-1 ',backend ',imports))
+(put 'nnoo-import 'lisp-indent-function 1)
+(put 'nnoo-import 'lisp-indent-hook 1)
+
+(defun nnoo-import-1 (backend imports)
+  (let ((call-function
+        (if (symbolp (car imports)) (pop imports) 'nnoo-parent-function))
+       imp functions function)
+    (while (setq imp (pop imports))
+      (setq functions
+           (or (cdr imp)
+               (nnoo-functions (car imp))))
+      (while functions
+       (unless (fboundp (setq function
+                              (nnoo-symbol backend (nnoo-rest-symbol
+                                                        (car functions)))))
+         (eval `(deffoo ,function (&rest args)
+                  (,call-function ',backend ',(car functions) args))))
+       (pop functions)))))
+
+(defun nnoo-parent-function (backend function args)
+  (let* ((pbackend (nnoo-backend function)))
+    (nnoo-change-server pbackend (nnoo-current-server backend)
+                       (cdr (assq pbackend (nnoo-parents backend))))
+    (apply function args)))
+
+(defun nnoo-execute (backend function &rest args)
+  "Execute FUNCTION on behalf of BACKEND."
+  (let* ((pbackend (nnoo-backend function)))
+    (nnoo-change-server pbackend (nnoo-current-server backend)
+                       (cdr (assq pbackend (nnoo-parents backend))))
+    (apply function args)))
+
+(defmacro nnoo-map-functions (backend &rest maps)
+  `(nnoo-map-functions-1 ',backend ',maps))
+(put 'nnoo-map-functions 'lisp-indent-function 1)
+(put 'nnoo-map-functions 'lisp-indent-hook 1)
+
+(defun nnoo-map-functions-1 (backend maps)
+  (let (m margs i)
+    (while (setq m (pop maps))
+      (setq i 0
+           margs nil)
+      (while (< i (length (cdr m)))
+       (if (numberp (nth i (cdr m)))
+           (push `(nth ,i args) margs)
+         (push (nth i (cdr m)) margs))
+       (incf i))
+      (eval `(deffoo ,(nnoo-symbol backend (nnoo-rest-symbol (car m)))
+                (&rest args)
+              (nnoo-parent-function ',backend ',(car m) 
+                                    ,(cons 'list (nreverse margs))))))))
+  
+(defun nnoo-backend (symbol)
+  (string-match "^[^-]+-" (symbol-name symbol))
+  (intern (substring (symbol-name symbol) 0 (1- (match-end 0)))))
+
+(defun nnoo-rest-symbol (symbol)
+  (string-match "^[^-]+-" (symbol-name symbol))
+  (intern (substring (symbol-name symbol) (match-end 0))))
+
+(defun nnoo-symbol (backend symbol)
+  (intern (format "%s-%s" backend symbol)))
+
+(defun nnoo-define (var map)
+  (let* ((backend (nnoo-backend var))
+        (def (assq backend nnoo-definition-alist))
+        (parents (nth 1 def)))
+    (unless def
+      (error "%s belongs to a backend that hasn't been declared." var))
+    (setcar (nthcdr 2 def) 
+           (delq (assq var (nth 2 def)) (nth 2 def)))
+    (setcar (nthcdr 2 def)
+           (cons (cons var (symbol-value var))
+                 (nth 2 def)))
+    (while map
+      (nconc (assq (nnoo-backend (car map)) parents)
+            (list (list (pop map) var))))))
+
+(defun nnoo-change-server (backend server defs)
+  (let* ((bstate (cdr (assq backend nnoo-state-alist)))
+        (sdefs (assq backend nnoo-definition-alist))
+        (current (car bstate))
+        (parents (nnoo-parents backend))
+        state)
+    (unless bstate
+      (push (setq bstate (list backend nil))
+           nnoo-state-alist)
+      (pop bstate))
+    (if (equal server current)
+       t
+      (nnoo-push-server backend current)
+      (setq state (or (cdr (assoc server (cddr bstate)))
+                     (nnoo-variables backend)))
+      (while state
+       (set (caar state) (cdar state))
+       (pop state))
+      (setcar bstate server)
+      (unless (cdr (assoc server (cddr bstate)))
+       (while defs
+         (set (caar defs) (cadar defs))
+         (pop defs)))
+      (while parents
+       (nnoo-change-server 
+        (caar parents) server 
+        (mapcar (lambda (def) (list (car def) (symbol-value (cadr def))))
+                (cdar parents)))
+       (pop parents))))
+  t)
+
+(defun nnoo-push-server (backend current)
+  (let ((bstate (assq backend nnoo-state-alist))
+       (defs (nnoo-variables backend)))
+    ;; Remove the old definition.
+    (setcdr (cdr bstate) (delq (assoc current (cddr bstate)) (cddr bstate)))
+    (let (state)
+      (while defs
+       (push (cons (caar defs) (symbol-value (caar defs)))
+             state)
+       (pop defs))
+      (nconc bstate (list (cons current state))))))
+
+(defun nnoo-current-server-p (backend server)
+  (equal (nnoo-current-server backend) server))
+
+(defun nnoo-current-server (backend)
+  (nth 1 (assq backend nnoo-state-alist)))
+
+(defun nnoo-close-server (backend &optional server)
+  (unless server
+    (setq server (nnoo-current-server backend)))
+  (when server
+    (let* ((bstate (cdr (assq backend nnoo-state-alist)))
+          (defs (assoc server (cdr bstate))))
+      (when bstate
+       (setcar bstate nil)
+       (setcdr bstate (delq defs (cdr bstate)))
+       (pop defs)
+       (while defs
+         (set (car (pop defs)) nil)))))
+  t)
+
+(defun nnoo-close (backend)
+  (setq nnoo-state-alist
+       (delq (assq backend nnoo-state-alist)
+             nnoo-state-alist))
+  t)
+
+(defun nnoo-status-message (backend server)
+  (nnheader-get-report backend))
+
+(defun nnoo-server-opened (backend server)
+  (and (nnoo-current-server-p backend server)
+       nntp-server-buffer
+       (buffer-name nntp-server-buffer)))
+
+(defmacro nnoo-define-basics (backend)
+  `(eval-and-compile
+     (nnoo-define-basics-1 ',backend)))
+
+(defun nnoo-define-basics-1 (backend)
+  (let ((functions '(close-server server-opened status-message)))
+    (while functions
+      (eval `(deffoo ,(nnoo-symbol backend (car functions)) 
+                (&optional server)
+              (,(nnoo-symbol 'nnoo (pop functions)) ',backend server)))))
+  (eval `(deffoo ,(nnoo-symbol backend 'open-server)
+            (server &optional defs)
+          (nnoo-change-server ',backend server defs))))
+
+(provide 'nnoo)
+
+;;; nnoo.el ends here.
index e40adb7..c9ae095 100644 (file)
 (require 'nnmail)
 (require 'gnus-soup)
 (require 'gnus-msg)
+(require 'nnoo)
 (eval-when-compile (require 'cl))
 
-(defvar nnsoup-directory "~/SOUP/"
+(nnoo-declare nnsoup)
+
+(defvoo nnsoup-directory "~/SOUP/"
   "*SOUP packet directory.")
 
-(defvar nnsoup-tmp-directory "/tmp/"
+(defvoo nnsoup-tmp-directory "/tmp/"
   "*Where nnsoup will store temporary files.")
 
-(defvar nnsoup-replies-directory (concat nnsoup-directory "replies/")
+(defvoo nnsoup-replies-directory (concat nnsoup-directory "replies/")
   "*Directory where outgoing packets will be composed.")
 
-(defvar nnsoup-replies-format-type ?n
+(defvoo nnsoup-replies-format-type ?n
   "*Format of the replies packages.")
 
-(defvar nnsoup-replies-index-type ?n
+(defvoo nnsoup-replies-index-type ?n
   "*Index type of the replies packages.")
 
-(defvar nnsoup-active-file (concat nnsoup-directory "active")
+(defvoo nnsoup-active-file (concat nnsoup-directory "active")
   "Active file.")
 
-(defvar nnsoup-packer "tar cf - %s | gzip > $HOME/Soupin%d.tgz"
+(defvoo nnsoup-packer "tar cf - %s | gzip > $HOME/Soupin%d.tgz"
   "Format string command for packing a SOUP packet.
 The SOUP files will be inserted where the %s is in the string.
 This string MUST contain both %s and %d. The file number will be
 inserted where %d appears.")
 
-(defvar nnsoup-unpacker "gunzip -c %s | tar xvf -"
+(defvoo nnsoup-unpacker "gunzip -c %s | tar xvf -"
   "*Format string command for unpacking a SOUP packet.
 The SOUP packet file name will be inserted at the %s.")
 
-(defvar nnsoup-packet-directory "~/"
+(defvoo nnsoup-packet-directory "~/"
   "*Where nnsoup will look for incoming packets.")
 
-(defvar nnsoup-packet-regexp "Soupout"
+(defvoo nnsoup-packet-regexp "Soupout"
   "*Regular expression matching SOUP packets in `nnsoup-packet-directory'.")
 
 \f
@@ -71,44 +74,21 @@ The SOUP packet file name will be inserted at the %s.")
 (defconst nnsoup-version "nnsoup 0.0"
   "nnsoup version.")
 
-(defvar nnsoup-status-string "")
-(defvar nnsoup-group-alist nil)
-(defvar nnsoup-current-prefix 0)
-(defvar nnsoup-replies-list nil)
-(defvar nnsoup-buffers nil)
-(defvar nnsoup-current-group nil)
-(defvar nnsoup-group-alist-touched nil)
-
-\f
-
-;; Server variables.
-
-(defvar nnsoup-current-server nil)
-(defvar nnsoup-server-alist nil)
-(defvar nnsoup-server-variables 
-  `((nnsoup-directory ,nnsoup-directory)
-    (nnsoup-active-file ,nnsoup-active-file)
-    (nnsoup-status-string "")
-    (nnsoup-current-prefix 0)
-    (nnsoup-current-group nil)
-    (nnsoup-buffers nil)
-    (nnsoup-replies-list nil)
-    (nnsoup-packet-regexp ,nnsoup-packet-regexp)
-    (nnsoup-packet-directory ,nnsoup-packet-directory)
-    (nnsoup-unpacker ,nnsoup-unpacker)
-    (nnsoup-packer ,nnsoup-packer)
-    (nnsoup-group-alist-touched nil)
-    (nnsoup-replies-index-type ,nnsoup-replies-index-type)
-    (nnsoup-replies-format-type ,nnsoup-replies-format-type)
-    (nnsoup-replies-directory ,nnsoup-replies-directory)
-    (nnsoup-tmp-directory ,nnsoup-tmp-directory)
-    (nnsoup-group-alist nil)))
+(defvoo nnsoup-status-string "")
+(defvoo nnsoup-group-alist nil)
+(defvoo nnsoup-current-prefix 0)
+(defvoo nnsoup-replies-list nil)
+(defvoo nnsoup-buffers nil)
+(defvoo nnsoup-current-group nil)
+(defvoo nnsoup-group-alist-touched nil)
 
 \f
 
 ;;; Interface functions.
 
-(defun nnsoup-retrieve-headers (sequence &optional group server fetch-old)
+(nnoo-define-basics nnsoup)
+
+(deffoo nnsoup-retrieve-headers (sequence &optional group server fetch-old)
   (nnsoup-possibly-change-group group)
   (save-excursion
     (set-buffer nntp-server-buffer)
@@ -194,8 +174,8 @@ The SOUP packet file name will be inserted at the %s.")
          (nnheader-fold-continuation-lines)
          'headers)))))
 
-(defun nnsoup-open-server (server &optional defs)
-  (nnheader-change-server 'nnsoup server defs)
+(deffoo nnsoup-open-server (server &optional defs)
+  (nnoo-change-server 'nnsoup server defs)
   (when (not (file-exists-p nnsoup-directory))
     (condition-case ()
        (make-directory nnsoup-directory t)
@@ -213,13 +193,7 @@ The SOUP packet file name will be inserted at the %s.")
                     server nnsoup-directory)
     t)))
 
-(defun nnsoup-close-server (&optional server)
-  (setq nnsoup-current-server nil
-       nnsoup-group-alist-touched nil
-       nnsoup-group-alist nil)
-  t)
-
-(defun nnsoup-request-close ()
+(deffoo nnsoup-request-close ()
   (nnsoup-write-active-file)
   (nnsoup-write-replies)
   (gnus-soup-save-areas)
@@ -233,20 +207,11 @@ The SOUP packet file name will be inserted at the %s.")
   (setq nnsoup-group-alist nil
        nnsoup-group-alist-touched nil
        nnsoup-current-group nil
-       nnsoup-current-server nil
-       nnsoup-server-alist nil
        nnsoup-replies-list nil)
+  (nnoo-close-server 'nnoo)
   t)
 
-(defun nnsoup-server-opened (&optional server)
-  (and (equal server nnsoup-current-server)
-       nntp-server-buffer
-       (buffer-name nntp-server-buffer)))
-
-(defun nnsoup-status-message (&optional server)
-  nnsoup-status-string)
-
-(defun nnsoup-request-article (id &optional newsgroup server buffer)
+(deffoo nnsoup-request-article (id &optional newsgroup server buffer)
   (nnsoup-possibly-change-group newsgroup)
   (let (buf)
     (save-excursion
@@ -257,7 +222,7 @@ The SOUP packet file name will be inserted at the %s.")
        (insert-buffer-substring buf)
        t))))
 
-(defun nnsoup-request-group (group &optional server dont-check)
+(deffoo nnsoup-request-group (group &optional server dont-check)
   (nnsoup-possibly-change-group group)
   (if dont-check 
       t
@@ -269,7 +234,7 @@ The SOUP packet file name will be inserted at the %s.")
         (max (1+ (- (cdr active) (car active))) 0) 
         (car active) (cdr active) group)))))
 
-(defun nnsoup-request-type (group &optional article)
+(deffoo nnsoup-request-type (group &optional article)
   (nnsoup-possibly-change-group group)
   (if (not article)
       'unknown
@@ -281,7 +246,7 @@ The SOUP packet file name will be inserted at the %s.")
            ((= kind ?n) 'news)
            (t 'unknown)))))
 
-(defun nnsoup-close-group (group &optional server)
+(deffoo nnsoup-close-group (group &optional server)
   ;; Kill all nnsoup buffers.
   (let ((buffers nnsoup-buffers)
        elem)
@@ -292,7 +257,7 @@ The SOUP packet file name will be inserted at the %s.")
             (kill-buffer (cdr elem))))))
   t)
 
-(defun nnsoup-request-list (&optional server)
+(deffoo nnsoup-request-list (&optional server)
   (save-excursion
     (set-buffer nntp-server-buffer)
     (erase-buffer)
@@ -307,24 +272,24 @@ The SOUP packet file name will be inserted at the %s.")
        (insert " y\n"))
       t)))
 
-(defun nnsoup-request-scan (group &optional server)
+(deffoo nnsoup-request-scan (group &optional server)
   (nnsoup-unpack-packets))
 
-(defun nnsoup-request-newgroups (date &optional server)
+(deffoo nnsoup-request-newgroups (date &optional server)
   (nnsoup-request-list))
 
-(defun nnsoup-request-list-newsgroups (&optional server)
+(deffoo nnsoup-request-list-newsgroups (&optional server)
   nil)
 
-(defun nnsoup-request-post (&optional server)
+(deffoo nnsoup-request-post (&optional server)
   (nnsoup-store-reply "news")
   t)
 
-(defun nnsoup-request-mail (&optional server)
+(deffoo nnsoup-request-mail (&optional server)
   (nnsoup-store-reply "mail")
   t)
 
-(defun nnsoup-request-expire-articles (articles group &optional server force)
+(deffoo nnsoup-request-expire-articles (articles group &optional server force)
   (nnsoup-possibly-change-group group)
   (let* ((total-infolist (assoc group nnsoup-group-alist))
         (active (cadr total-infolist))
index 7a68fc2..5a9fc86 100644 (file)
 (require 'nnheader)
 (require 'nntp)
 (require 'timezone)
+(require 'nnoo)
 (eval-when-compile (require 'cl))
 
-(defvar nnspool-inews-program news-inews-program
+(nnoo-declare nnspool)
+
+(defvoo nnspool-inews-program news-inews-program
   "Program to post news.
 This is most commonly `inews' or `injnews'.")
 
-(defvar nnspool-inews-switches '("-h")
+(defvoo nnspool-inews-switches '("-h")
   "Switches for nnspool-request-post to pass to `inews' for posting news.
 If you are using Cnews, you probably should set this variable to nil.")
 
-(defvar nnspool-spool-directory (file-name-as-directory news-path)
+(defvoo nnspool-spool-directory (file-name-as-directory news-path)
   "Local news spool directory.")
 
-(defvar nnspool-nov-directory (concat nnspool-spool-directory "over.view/")
+(defvoo nnspool-nov-directory (concat nnspool-spool-directory "over.view/")
   "Local news nov directory.")
 
-(defvar nnspool-lib-dir "/usr/lib/news/"
+(defvoo nnspool-lib-dir "/usr/lib/news/"
   "Where the local news library files are stored.")
 
-(defvar nnspool-active-file (concat nnspool-lib-dir "active")
+(defvoo nnspool-active-file (concat nnspool-lib-dir "active")
   "Local news active file.")
 
-(defvar nnspool-newsgroups-file (concat nnspool-lib-dir "newsgroups")
+(defvoo nnspool-newsgroups-file (concat nnspool-lib-dir "newsgroups")
   "Local news newsgroups file.")
 
-(defvar nnspool-distributions-file (concat nnspool-lib-dir "distributions")
+(defvoo nnspool-distributions-file (concat nnspool-lib-dir "distributions")
   "Local news distributions file.")
 
-(defvar nnspool-history-file (concat nnspool-lib-dir "history")
+(defvoo nnspool-history-file (concat nnspool-lib-dir "history")
   "Local news history file.")
 
-(defvar nnspool-active-times-file (concat nnspool-lib-dir "active.times")
+(defvoo nnspool-active-times-file (concat nnspool-lib-dir "active.times")
   "Local news active date file.")
 
-(defvar nnspool-large-newsgroup 50
+(defvoo nnspool-large-newsgroup 50
   "The number of the articles which indicates a large newsgroup.
 If the number of the articles is greater than the value, verbose
 messages will be shown to indicate the current status.")
 
-(defvar nnspool-nov-is-evil nil
+(defvoo nnspool-nov-is-evil nil
   "Non-nil means that nnspool will never return NOV lines instead of headers.")
 
 (defconst nnspool-sift-nov-with-sed nil
@@ -76,7 +79,7 @@ messages will be shown to indicate the current status.")
 If nil, nnspool will load the entire file into a buffer and process it
 there.")
 
-(defvar nnspool-rejected-article-hook nil
+(defvoo nnspool-rejected-article-hook nil
   "*A hook that will be run when an article has been rejected by the server.")
 
 \f
@@ -84,39 +87,18 @@ there.")
 (defconst nnspool-version "nnspool 2.0"
   "Version numbers of this version of NNSPOOL.")
 
-(defvar nnspool-current-directory nil
+(defvoo nnspool-current-directory nil
   "Current news group directory.")
 
-(defvar nnspool-current-group nil)
-(defvar nnspool-status-string "")
-
-\f
-
-(defvar nnspool-current-server nil)
-(defvar nnspool-server-alist nil)
-(defvar nnspool-server-variables 
-  `((nnspool-inews-program ,nnspool-inews-program)
-    (nnspool-inews-switches ,nnspool-inews-switches)
-    (nnspool-spool-directory ,nnspool-spool-directory)
-    (nnspool-nov-directory ,nnspool-nov-directory)
-    (nnspool-lib-dir ,nnspool-lib-dir)
-    (nnspool-active-file ,nnspool-active-file)
-    (nnspool-newsgroups-file ,nnspool-newsgroups-file)
-    (nnspool-distributions-file ,nnspool-distributions-file)
-    (nnspool-rejected-article-hook nil)
-    (nnspool-history-file ,nnspool-history-file)
-    (nnspool-active-times-file ,nnspool-active-times-file)
-    (nnspool-large-newsgroup ,nnspool-large-newsgroup)
-    (nnspool-nov-is-evil ,nnspool-nov-is-evil)
-    (nnspool-sift-nov-with-sed ,nnspool-sift-nov-with-sed)
-    (nnspool-current-directory nil)
-    (nnspool-current-group nil)
-    (nnspool-status-string "")))
+(defvoo nnspool-current-group nil)
+(defvoo nnspool-status-string "")
 
 \f
 ;;; Interface functions.
 
-(defun nnspool-retrieve-headers (articles &optional group server fetch-old)
+(nnoo-define-basics nnspool)
+
+(deffoo nnspool-retrieve-headers (articles &optional group server fetch-old)
   "Retrieve the headers of ARTICLES."
   (save-excursion
     (set-buffer nntp-server-buffer)
@@ -168,8 +150,8 @@ there.")
          (nnheader-fold-continuation-lines)
          'headers)))))
 
-(defun nnspool-open-server (server &optional defs)
-  (nnheader-change-server 'nnspool server defs)
+(deffoo nnspool-open-server (server &optional defs)
+  (nnoo-change-server 'nnspool server defs)
   (cond 
    ((not (file-exists-p nnspool-spool-directory))
     (nnspool-close-server)
@@ -183,20 +165,7 @@ there.")
                     server nnspool-spool-directory)
     t)))
 
-(defun nnspool-close-server (&optional server)
-  (setq nnspool-current-server nil)
-  t)
-
-(defun nnspool-server-opened (&optional server)
-  (and (equal server nnspool-current-server)
-       nntp-server-buffer
-       (buffer-name nntp-server-buffer)))
-
-(defun nnspool-status-message (&optional server)
-  "Return server status response as string."
-  nnspool-status-string)
-
-(defun nnspool-request-article (id &optional group server buffer)
+(deffoo nnspool-request-article (id &optional group server buffer)
   "Select article by message ID (or number)."
   (nnspool-possibly-change-directory group)
   (let ((nntp-server-buffer (or buffer nntp-server-buffer))
@@ -215,7 +184,7 @@ there.")
             (cons nnspool-current-group id)
           ag))))
            
-(defun nnspool-request-body (id &optional group server)
+(deffoo nnspool-request-body (id &optional group server)
   "Select article body by message ID (or number)."
   (nnspool-possibly-change-directory group)
   (let ((res (nnspool-request-article id)))
@@ -227,7 +196,7 @@ there.")
          (delete-region (point-min) (point)))
        res))))
 
-(defun nnspool-request-head (id &optional group server)
+(deffoo nnspool-request-head (id &optional group server)
   "Select article head by message ID (or number)."
   (nnspool-possibly-change-directory group)
   (let ((res (nnspool-request-article id)))
@@ -239,7 +208,7 @@ there.")
          (delete-region (1- (point)) (point-max)))))
     res))
 
-(defun nnspool-request-group (group &optional server dont-check)
+(deffoo nnspool-request-group (group &optional server dont-check)
   "Select news GROUP."
   (let ((pathname (nnspool-article-pathname group))
        dir)
@@ -265,29 +234,29 @@ there.")
          (nnheader-report 'nnspool "Empty group %s" group)
          (nnheader-insert "211 0 0 0 %s\n" group))))))
 
-(defun nnspool-request-type (group &optional article)
+(deffoo nnspool-request-type (group &optional article)
   'news)
 
-(defun nnspool-close-group (group &optional server)
+(deffoo nnspool-close-group (group &optional server)
   t)
 
-(defun nnspool-request-list (&optional server)
+(deffoo nnspool-request-list (&optional server)
   "List active newsgroups."
   (save-excursion
     (nnspool-find-file nnspool-active-file)))
 
-(defun nnspool-request-list-newsgroups (&optional server)
+(deffoo nnspool-request-list-newsgroups (&optional server)
   "List newsgroups (defined in NNTP2)."
   (save-excursion
     (nnspool-find-file nnspool-newsgroups-file)))
 
-(defun nnspool-request-list-distributions (&optional server)
+(deffoo nnspool-request-list-distributions (&optional server)
   "List distributions (defined in NNTP2)."
   (save-excursion
     (nnspool-find-file nnspool-distributions-file)))
 
 ;; Suggested by Hallvard B Furuseth <h.b.furuseth@usit.uio.no>.
-(defun nnspool-request-newgroups (date &optional server)
+(deffoo nnspool-request-newgroups (date &optional server)
   "List groups created after DATE."
   (if (nnspool-find-file nnspool-active-times-file)
       (save-excursion
@@ -321,7 +290,7 @@ there.")
        t)
     nil))
 
-(defun nnspool-request-post (&optional server)
+(deffoo nnspool-request-post (&optional server)
   "Post a new news in current buffer."
   (save-excursion
     (let* ((process-connection-type nil) ; t bugs out on Solaris
@@ -345,6 +314,10 @@ there.")
          (error nil))
        t))))
 
+
+\f
+;;; Internal functions.
+
 (defun nnspool-inews-sentinel (proc status)
   (save-excursion
     (set-buffer (process-buffer proc))
@@ -360,9 +333,6 @@ there.")
       (ding)
       (run-hooks 'nnspool-rejected-article-hook))))
 
-\f
-;;; Internal functions.
-
 (defun nnspool-retrieve-headers-with-nov (articles &optional fetch-old)
   (if (or gnus-nov-is-evil nnspool-nov-is-evil)
       nil
index cf6b135..c3a0c5e 100644 (file)
 (require 'rnews)
 (require 'sendmail)
 (require 'nnheader)
+(require 'nnoo)
 (eval-when-compile (require 'cl))
 
+(nnoo-declare nntp)
+
 (eval-and-compile
   (unless (fboundp 'open-network-stream)
     (require 'tcp)))
@@ -45,7 +48,7 @@
   (autoload 'telnet-send-input "telnet" nil t)
   (autoload 'timezone-parse-date "timezone"))
 
-(defvar nntp-server-hook nil
+(defvoo nntp-server-hook nil
   "*Hooks for the NNTP server.
 If the kanji code of the NNTP server is different from the local kanji
 code, the correct kanji code of the buffer associated with the NNTP
@@ -61,7 +64,7 @@ server must be specified as follows:
 If you'd like to change something depending on the server in this
 hook, use the variable `nntp-address'.")
 
-(defvar nntp-server-opened-hook nil
+(defvoo nntp-server-opened-hook nil
   "*Hook used for sending commands to the server at startup.  
 The default value is `nntp-send-mode-reader', which makes an innd
 server spawn an nnrpd server.  Another useful function to put in this
@@ -70,7 +73,7 @@ to allow posting from the server.  Note that this is only necessary to
 do on servers that use strict access control.")  
 (add-hook 'nntp-server-opened-hook 'nntp-send-mode-reader)
 
-(defvar nntp-server-action-alist 
+(defvoo nntp-server-action-alist 
   '(("nntpd 1\\.5\\.11t" 
      (remove-hook 'nntp-server-opened-hook 'nntp-send-mode-reader)))
   "Alist of regexps to match on server types and actions to be taken.
@@ -82,7 +85,7 @@ to innd, you could say something like:
 
 You probably don't want to do that, though.")
 
-(defvar nntp-open-server-function 'nntp-open-network-stream
+(defvoo nntp-open-server-function 'nntp-open-network-stream
   "*Function used for connecting to a remote system.
 It will be called with the address of the remote system.
 
@@ -92,75 +95,75 @@ system (see nntp-port-number).  The other is `nntp-open-rlogin', which
 does an rlogin on the remote system, and then does a telnet to the
 NNTP server available there (see nntp-rlogin-parameters).")
 
-(defvar nntp-rlogin-parameters '("telnet" "${NNTPSERVER:=localhost}" "nntp")
+(defvoo nntp-rlogin-parameters '("telnet" "${NNTPSERVER:=localhost}" "nntp")
   "*Parameters to `nntp-open-login'.
 That function may be used as `nntp-open-server-function'.  In that
 case, this list will be used as the parameter list given to rsh.")
 
-(defvar nntp-rlogin-user-name nil
+(defvoo nntp-rlogin-user-name nil
   "*User name on remote system when using the rlogin connect method.")
 
-(defvar nntp-address nil
+(defvoo nntp-address nil
   "*The name of the NNTP server.")
 
-(defvar nntp-port-number "nntp"
+(defvoo nntp-port-number "nntp"
   "*Port number to connect to.")
 
-(defvar nntp-end-of-line "\r\n"
+(defvoo nntp-end-of-line "\r\n"
   "String to use on the end of lines when talking to the NNTP server.
 This is \"\\r\\n\" by default, but should be \"\\n\" when
 using rlogin to communicate with the server.")
 
-(defvar nntp-large-newsgroup 50
+(defvoo nntp-large-newsgroup 50
   "*The number of the articles which indicates a large newsgroup.
 If the number of the articles is greater than the value, verbose
 messages will be shown to indicate the current status.")
 
-(defvar nntp-buggy-select (memq system-type '(fujitsu-uts))
+(defvoo nntp-buggy-select (memq system-type '(fujitsu-uts))
   "*t if your select routine is buggy.
 If the select routine signals error or fall into infinite loop while
 waiting for the server response, the variable must be set to t.  In
 case of Fujitsu UTS, it is set to T since `accept-process-output'
 doesn't work properly.")
 
-(defvar nntp-maximum-request 400
+(defvoo nntp-maximum-request 400
   "*The maximum number of the requests sent to the NNTP server at one time.
 If Emacs hangs up while retrieving headers, set the variable to a
 lower value.")
 
-(defvar nntp-debug-read 10000
+(defvoo nntp-debug-read 10000
   "*Display '...' every 10Kbytes of a message being received if it is non-nil.
 If it is a number, dots are displayed per the number.")
 
-(defvar nntp-nov-is-evil nil
+(defvoo nntp-nov-is-evil nil
   "*If non-nil, nntp will never attempt to use XOVER when talking to the server.")
 
-(defvar nntp-xover-commands '("XOVER" "XOVERVIEW")
+(defvoo nntp-xover-commands '("XOVER" "XOVERVIEW")
   "*List of strings that are used as commands to fetch NOV lines from a server.
 The strings are tried in turn until a positive response is gotten. If
 none of the commands are successful, nntp will just grab headers one
 by one.")
 
-(defvar nntp-nov-gap 20
+(defvoo nntp-nov-gap 20
   "*Maximum allowed gap between two articles.
 If the gap between two consecutive articles is bigger than this
 variable, split the XOVER request into two requests.")
 
-(defvar nntp-connection-timeout nil
+(defvoo nntp-connection-timeout nil
   "*Number of seconds to wait before an nntp connection times out.
 If this variable is nil, which is the default, no timers are set.")
 
-(defvar nntp-command-timeout nil
+(defvoo nntp-command-timeout nil
   "*Number of seconds to wait for a response when sending a command.
 If this variable is nil, which is the default, no timers are set.")
 
-(defvar nntp-retry-on-break nil
+(defvoo nntp-retry-on-break nil
   "*If non-nil, re-send the command when the user types `C-g'.")
 
-(defvar nntp-news-default-headers nil
+(defvoo nntp-news-default-headers nil
   "*If non-nil, override `mail-default-headers' when posting news.")
 
-(defvar nntp-prepare-server-hook nil
+(defvoo nntp-prepare-server-hook nil
   "*Hook run before a server is opened.
 If can be used to set up a server remotely, for instance.  Say you
 have an account at the machine \"other.machine\".  This machine has
@@ -168,10 +171,10 @@ access to an NNTP server that you can't access locally.  You could
 then use this hook to rsh to the remote machine and start a proxy NNTP
 server there that you can connect to.")
 
-(defvar nntp-async-number 5
+(defvoo nntp-async-number 5
   "*How many articles should be prefetched when in asynchronous mode.")
 
-(defvar nntp-warn-about-losing-connection t
+(defvoo nntp-warn-about-losing-connection t
   "*If non-nil, beep when a server closes connection.")
 
 \f
@@ -182,73 +185,34 @@ server there that you can connect to.")
 (defvar nntp-server-buffer nil
   "Buffer associated with the NNTP server process.")
 
-(defvar nntp-server-process nil
+(defvoo nntp-server-process nil
   "The NNTP server process.
 You'd better not use this variable in NNTP front-end program, but
 instead use `nntp-server-buffer'.")
 
-(defvar nntp-status-string nil
-  "Save the server response message.
-You'd better not use this variable in NNTP front-end program but
-instead call function `nntp-status-message' to get status message.")
+(defvoo nntp-status-string nil
+  "Save the server response message.")
 
 (defvar nntp-opened-connections nil
   "All (possibly) opened connections.")
 
-(defvar nntp-server-xover 'try)
-(defvar nntp-server-list-active-group 'try)
-(defvar nntp-current-group "")
-(defvar nntp-server-type nil)
-
-(defvar nntp-async-process nil)
-(defvar nntp-async-buffer nil)
-(defvar nntp-async-articles nil)
-(defvar nntp-async-fetched nil)
-(defvar nntp-async-group-alist nil)
-
-\f
+(defvoo nntp-server-xover 'try)
+(defvoo nntp-server-list-active-group 'try)
+(defvoo nntp-current-group "")
+(defvoo nntp-server-type nil)
 
-(defvar nntp-current-server nil)
-(defvar nntp-server-alist nil)
-(defvar nntp-server-variables 
-  `((nntp-server-hook ,nntp-server-hook)
-    (nntp-server-opened-hook ,nntp-server-opened-hook)
-    (nntp-port-number ,nntp-port-number)
-    (nntp-address ,nntp-address)
-    (nntp-large-newsgroup ,nntp-large-newsgroup)
-    (nntp-buggy-select ,nntp-buggy-select)
-    (nntp-maximum-request ,nntp-maximum-request)
-    (nntp-debug-read ,nntp-debug-read)
-    (nntp-nov-is-evil ,nntp-nov-is-evil)
-    (nntp-xover-commands ,nntp-xover-commands)
-    (nntp-connection-timeout ,nntp-connection-timeout)
-    (nntp-news-default-headers ,nntp-news-default-headers)
-    (nntp-prepare-server-hook ,nntp-prepare-server-hook) 
-    (nntp-async-number ,nntp-async-number)
-    (nntp-open-server-function ,nntp-open-server-function)
-    (nntp-warn-about-losing-connection ,nntp-warn-about-losing-connection)
-    (nntp-retry-on-break nil)
-    (nntp-command-timeout nil)
-    (nntp-nov-gap ,nntp-nov-gap)
-    (nntp-rlogin-parameters ,nntp-rlogin-parameters)
-    (nntp-rlogin-user-name ,nntp-rlogin-user-name)
-    (nntp-end-of-line ,nntp-end-of-line)
-    (nntp-server-type nil)
-    (nntp-async-process nil)
-    (nntp-async-buffer nil)
-    (nntp-async-articles nil)
-    (nntp-async-fetched nil)
-    (nntp-async-group-alist nil)
-    (nntp-server-process nil)
-    (nntp-status-string nil)
-    (nntp-server-xover try)
-    (nntp-server-list-active-group try)
-    (nntp-current-group "")))
+(defvoo nntp-async-process nil)
+(defvoo nntp-async-buffer nil)
+(defvoo nntp-async-articles nil)
+(defvoo nntp-async-fetched nil)
+(defvoo nntp-async-group-alist nil)
 
 \f
 ;;; Interface functions.
 
-(defun nntp-retrieve-headers (articles &optional group server fetch-old)
+(nnoo-define-basics nntp)
+
+(deffoo nntp-retrieve-headers (articles &optional group server fetch-old)
   "Retrieve the headers of ARTICLES."
   (nntp-possibly-change-server group server)
   (save-excursion
@@ -317,7 +281,7 @@ instead call function `nntp-status-message' to get status message.")
        'headers))))
 
 
-(defun nntp-retrieve-groups (groups &optional server)
+(deffoo nntp-retrieve-groups (groups &optional server)
   "Retrieve group info on GROUPS."
   (nntp-possibly-change-server nil server)
   (save-excursion
@@ -375,11 +339,11 @@ instead call function `nntp-status-message' to get status message.")
                         (progn (forward-line 1) (point))))
        'active))))
 
-(defun nntp-open-server (server &optional defs connectionless)
+(deffoo nntp-open-server (server &optional defs connectionless)
   "Open the virtual server SERVER.
 If CONNECTIONLESS is non-nil, don't attempt to connect to any physical
 servers."
-  (nnheader-init-server-buffer)
+  (nnoo-change-server 'nntp server defs)
   (if (nntp-server-opened server)
       t
     (if (or (stringp (car defs))
@@ -387,19 +351,6 @@ servers."
        (setq defs (cons (list 'nntp-port-number (car defs)) (cdr defs))))
     (or (assq 'nntp-address defs)
        (setq defs (append defs (list (list 'nntp-address server)))))
-    (if (and nntp-current-server
-            (not (equal server nntp-current-server)))
-       (setq nntp-server-alist 
-             (cons (list nntp-current-server
-                         (nnheader-save-variables nntp-server-variables))
-                   nntp-server-alist)))
-           (let ((state (assoc server nntp-server-alist)))
-      (if state 
-         (progn
-           (nnheader-restore-variables (nth 1 state))
-           (setq nntp-server-alist (delq state nntp-server-alist)))
-       (nnheader-set-init-variables nntp-server-variables defs)))
-    (setq nntp-current-server server)
     (or (nntp-server-opened server)
        connectionless
        (prog2
@@ -407,7 +358,7 @@ servers."
            (nntp-open-server-semi-internal nntp-address nntp-port-number)
          (nnheader-insert "")))))
 
-(defun nntp-close-server (&optional server)
+(deffoo nntp-close-server (&optional server)
   "Close connection to SERVER."
   (nntp-possibly-change-server nil server t)
   (unwind-protect
@@ -422,35 +373,35 @@ servers."
          (nntp-send-command nil "QUIT")))
     (nntp-close-server-internal server)))
 
-(defun nntp-request-close ()
+(deffoo nntp-request-close ()
   "Close all server connections."
   (let (proc entry)
-     (while nntp-opened-connections
-       (when (setq proc (pop nntp-opened-connections))
-        (condition-case ()
-            (process-send-string proc (concat "QUIT" nntp-end-of-line))
-          (error nil))
-        (delete-process proc)))
-     (and nntp-async-buffer
-         (get-buffer nntp-async-buffer)
-         (kill-buffer nntp-async-buffer))
-    (while (setq entry (pop nntp-server-alist))
-      (and (setq proc (nth 1 (assq 'nntp-async-buffer entry)))
-          (buffer-name proc)
-          (kill-buffer proc)))
-    (setq nntp-current-server nil
-         nntp-async-group-alist nil)))
-
-(defun nntp-server-opened (&optional server)
+    (while nntp-opened-connections
+      (when (setq proc (pop nntp-opened-connections))
+       (condition-case ()
+           (process-send-string proc (concat "QUIT" nntp-end-of-line))
+         (error nil))
+       (delete-process proc)))
+    (and nntp-async-buffer
+        (get-buffer nntp-async-buffer)
+        (kill-buffer nntp-async-buffer))
+    (let ((alist (cddr (assq 'nntp nnoo-state-alist))))
+      (while (setq entry (pop alist))
+       (and (setq proc (nth 1 (assq 'nntp-async-buffer entry)))
+            (buffer-name proc)
+            (kill-buffer proc))))
+    (nnoo-close-server 'nntp)
+    (setq nntp-async-group-alist nil)))
+
+(deffoo nntp-server-opened (&optional server)
   "Say whether a connection to SERVER has been opened."
-  (and (or (not server)
-          (equal server nntp-current-server))
+  (and (nnoo-current-server-p 'nntp server)
        nntp-server-buffer
        (buffer-name nntp-server-buffer)
        nntp-server-process
        (memq (process-status nntp-server-process) '(open run))))
 
-(defun nntp-status-message (&optional server)
+(deffoo nntp-status-message (&optional server)
   "Return server status as a string."
   (if (and nntp-status-string
           ;; NNN MESSAGE
@@ -460,7 +411,7 @@ servers."
     ;; Empty message if nothing.
     (or nntp-status-string "")))
 
-(defun nntp-request-article (id &optional group server buffer)
+(deffoo nntp-request-article (id &optional group server buffer)
   "Request article ID (Message-ID or number)."
   (nntp-possibly-change-server group server)
 
@@ -515,7 +466,7 @@ servers."
        (when buffer 
          (set-process-buffer nntp-server-process nntp-server-buffer))))))
 
-(defun nntp-request-body (id &optional group server)
+(deffoo nntp-request-body (id &optional group server)
   "Request body of article ID (Message-ID or number)."
   (nntp-possibly-change-server group server)
   (prog1
@@ -524,7 +475,7 @@ servers."
        "^\\.\r?\n" "BODY" (or (and (numberp id) (int-to-string id)) id))
     (nntp-decode-text)))
 
-(defun nntp-request-head (id &optional group server)
+(deffoo nntp-request-head (id &optional group server)
   "Request head of article ID (Message-ID or number)."
   (nntp-possibly-change-server group server)
   (prog1
@@ -535,23 +486,23 @@ servers."
          (nntp-find-group-and-number)))
     (nntp-decode-text)))
 
-(defun nntp-request-stat (id &optional group server)
+(deffoo nntp-request-stat (id &optional group server)
   "Request STAT of article ID (Message-ID or number)."
   (nntp-possibly-change-server group server)
   (nntp-send-command 
    "^[23].*\r?\n" "STAT" (or (and (numberp id) (int-to-string id)) id)))
 
-(defun nntp-request-type (group &optional article)
+(deffoo nntp-request-type (group &optional article)
   'news)
 
-(defun nntp-request-group (group &optional server dont-check)
+(deffoo nntp-request-group (group &optional server dont-check)
   "Select GROUP."
   (nntp-possibly-change-server nil server)
   (setq nntp-current-group
        (when (nntp-send-command "^2.*\r?\n" "GROUP" group)
          group)))
 
-(defun nntp-request-asynchronous (group &optional server articles)
+(deffoo nntp-request-asynchronous (group &optional server articles)
   "Enable pre-fetch in GROUP."
   (when nntp-async-articles
     (nntp-async-request-group group))
@@ -575,38 +526,38 @@ servers."
       (nntp-async-send-strings "GROUP" group)
       t)))
 
-(defun nntp-list-active-group (group &optional server)
+(deffoo nntp-list-active-group (group &optional server)
   "Return the active info on GROUP (which can be a regexp."
   (nntp-possibly-change-server group server)
   (nntp-send-command "^.*\r?\n" "LIST ACTIVE" group))
 
-(defun nntp-request-group-description (group &optional server)
+(deffoo nntp-request-group-description (group &optional server)
   "Get the description of GROUP."
   (nntp-possibly-change-server nil server)
   (prog1
       (nntp-send-command "^.*\r?\n" "XGTITLE" group)
     (nntp-decode-text)))
 
-(defun nntp-close-group (group &optional server)
+(deffoo nntp-close-group (group &optional server)
   "Close GROUP."
   (setq nntp-current-group nil)
   t)
 
-(defun nntp-request-list (&optional server)
+(deffoo nntp-request-list (&optional server)
   "List all active groups."
   (nntp-possibly-change-server nil server)
   (prog1
       (nntp-send-command "^\\.\r?\n" "LIST")
     (nntp-decode-text)))
 
-(defun nntp-request-list-newsgroups (&optional server)
+(deffoo nntp-request-list-newsgroups (&optional server)
   "Get descriptions on all groups on SERVER."
   (nntp-possibly-change-server nil server)
   (prog1
       (nntp-send-command "^\\.\r?\n" "LIST NEWSGROUPS")
     (nntp-decode-text)))
 
-(defun nntp-request-newgroups (date &optional server)
+(deffoo nntp-request-newgroups (date &optional server)
   "List groups that have arrived since DATE."
   (nntp-possibly-change-server nil server)
   (let* ((date (timezone-parse-date date))
@@ -620,24 +571,24 @@ servers."
        (nntp-send-command "^\\.\r?\n" "NEWGROUPS" time-string)
       (nntp-decode-text))))
 
-(defun nntp-request-list-distributions (&optional server)
+(deffoo nntp-request-list-distributions (&optional server)
   "List distributions."
   (nntp-possibly-change-server nil server)
   (prog1
       (nntp-send-command "^\\.\r?\n" "LIST DISTRIBUTIONS")
     (nntp-decode-text)))
 
-(defun nntp-request-last (&optional group server)
+(deffoo nntp-request-last (&optional group server)
   "Decrease the current article pointer."
   (nntp-possibly-change-server group server)
   (nntp-send-command "^[23].*\r?\n" "LAST"))
 
-(defun nntp-request-next (&optional group server)
+(deffoo nntp-request-next (&optional group server)
   "Advance the current article pointer."
   (nntp-possibly-change-server group server)
   (nntp-send-command "^[23].*\r?\n" "NEXT"))
 
-(defun nntp-request-post (&optional server)
+(deffoo nntp-request-post (&optional server)
   "Post the current buffer."
   (nntp-possibly-change-server nil server)
   (when (nntp-send-command "^[23].*\r?\n" "POST")
@@ -693,7 +644,7 @@ It will prompt for a password."
 
 (defun nntp-default-sentinel (proc status)
   "Default sentinel function for NNTP server process."
-  (let ((servers nntp-server-alist)
+  (let ((servers (cddr (assq 'nntp nnoo-state-alist)))
        server)
     ;; Go through the alist of server names and find the name of the
     ;; server that the process that sent the signal is connected to.
@@ -713,7 +664,8 @@ It will prompt for a password."
 (defun nntp-kill-connection (server)
   "Choke the connection to SERVER."
   (let ((proc (nth 1 (assq 'nntp-server-process 
-                          (assoc server nntp-server-alist)))))
+                          (assoc server (cddr 
+                                         (assq 'nntp nnoo-state-alist)))))))
     (when proc 
       (delete-process (process-name proc)))
     (nntp-close-server server)
@@ -780,13 +732,15 @@ It will prompt for a password."
              (cond
               ((fboundp 'run-at-time)
                (run-at-time nntp-command-timeout
-                            nil 'nntp-kill-command nntp-current-server))
+                            nil 'nntp-kill-command 
+                            (nnoo-current-server 'nntp)))
               ((fboundp 'start-itimer)
                ;; Not sure if this will work or not, only one way to
                ;; find out
                (eval '(start-itimer "nntp-timeout"
                                     (lambda ()
-                                      (nntp-kill-command nntp-current-server))
+                                      (nntp-kill-command 
+                                       (nnoo-current-server 'nntp)))
                                     nntp-command-timeout nil))))))
        (nntp-retry-command t)
        result)
@@ -818,8 +772,9 @@ It will prompt for a password."
 
 (defun nntp-kill-command (server)
   "Kill and restart the connection to SERVER."
-  (let ((proc (nth 1 (assq 'nntp-server-process 
-                          (assoc server nntp-server-alist)))))
+  (let ((proc (nth 1 (assq 
+                     'nntp-server-process 
+                     (assoc server (cddr (assq 'nntp nnoo-state-alist)))))))
     (when proc 
       (delete-process (process-name proc)))
     (nntp-close-server server)
@@ -1080,8 +1035,8 @@ It will prompt for a password."
   "Send STRINGS to the server."
   (let ((cmd (concat (mapconcat 'identity strings " ") nntp-end-of-line)))
     ;; We open the nntp server if it is down.
-    (or (nntp-server-opened nntp-current-server)
-       (nntp-open-server nntp-current-server)
+    (or (nntp-server-opened (nnoo-current-server 'nntp))
+       (nntp-open-server (nnoo-current-server 'nntp))
        (error (nntp-status-message)))
     ;; Send the strings.
     (process-send-string nntp-server-process cmd)
@@ -1156,9 +1111,9 @@ If SERVICE, this this as the port number."
              'nntp (buffer-substring (point-min) (point-max)))))
       (and timer (cancel-timer timer))
       (message "")
-      (or status
-         (setq nntp-current-server nil
-               nntp-async-number nil))
+      (unless status
+       (nnoo-close-server 'nntp server)
+       (setq nntp-async-number nil))
       status)))
 
 (defvar nntp-default-directories '("~" "/tmp" "/")
index ca68057..acd4088 100644 (file)
 (require 'nntp)
 (require 'nnheader)
 (require 'gnus)
+(require 'nnoo)
 (eval-when-compile (require 'cl))
 
-(defvar nnvirtual-always-rescan nil
+(nnoo-declare nnvirtual)
+
+(defvoo nnvirtual-always-rescan nil
   "*If non-nil, always scan groups for unread articles when entering a group.
 If this variable is nil (which is the default) and you read articles
 in a component group after the virtual group has been activated, the
 read articles from the component group will show up when you enter the
 virtual group.")
 
+(defvoo nnvirtual-component-regexp nil
+  "*Regexp to match component groups.")
+
 \f
 
-(defconst nnvirtual-version "nnvirtual 1.0"
-  "Version number of this version of nnvirtual.")
+(defconst nnvirtual-version "nnvirtual 1.0")
 
-(defvar nnvirtual-group-alist nil)
-(defvar nnvirtual-current-group nil)
-(defvar nnvirtual-component-groups nil)
-(defvar nnvirtual-mapping nil)
+(defvoo nnvirtual-current-group nil)
+(defvoo nnvirtual-component-groups nil)
+(defvoo nnvirtual-mapping nil)
 
-(defvar nnvirtual-status-string "")
+(defvoo nnvirtual-status-string "")
 
 (eval-and-compile
   (autoload 'gnus-cache-articles-in-group "gnus-cache"))
@@ -61,9 +65,14 @@ virtual group.")
 
 ;;; Interface functions.
 
-(defun nnvirtual-retrieve-headers (articles &optional newsgroup server fetch-old)
-  (when (nnvirtual-possibly-change-group newsgroup server)
+(nnoo-define-basics nnvirtual)
+
+(deffoo nnvirtual-retrieve-headers (articles &optional newsgroup
+                                            server fetch-old)
+  (when (nnvirtual-possibly-change-server server)
     (save-excursion
+      (set-buffer nntp-server-buffer)
+      (erase-buffer)
       (if (stringp (car articles))
          'headers
        (let ((vbuf (nnheader-set-temp-buffer 
@@ -152,28 +161,8 @@ virtual group.")
                'nov)
            (kill-buffer vbuf)))))))
 
-(defun nnvirtual-open-server (server &optional something)
-  (nnheader-init-server-buffer))
-
-(defun nnvirtual-close-server (&rest dum)
-  t)
-
-(defun nnvirtual-request-close ()
-  (setq nnvirtual-current-group nil
-       nnvirtual-component-groups nil
-       nnvirtual-mapping nil
-       nnvirtual-group-alist nil)
-  t)
-
-(defun nnvirtual-server-opened (&optional server)
-  (and nntp-server-buffer
-       (get-buffer nntp-server-buffer)))
-
-(defun nnvirtual-status-message (&optional server)
-  nnvirtual-status-string)
-
-(defun nnvirtual-request-article (article &optional group server buffer)
-  (when (and (nnvirtual-possibly-change-group group server)
+(deffoo nnvirtual-request-article (article &optional group server buffer)
+  (when (and (nnvirtual-possibly-change-server server)
             (numberp article))
     (let* ((amap (assq article nnvirtual-mapping))
           (cgroup (cadr amap)))
@@ -192,59 +181,77 @@ virtual group.")
              (gnus-request-article-this-buffer (caddr amap) cgroup))
          (gnus-request-article (caddr amap) cgroup)))))))
 
-(defun nnvirtual-request-group (group &optional server dont-check)
+(deffoo nnvirtual-open-server (server &optional defs)
+  (unless (assq 'nnvirtual-component-regexp defs)
+    (push `(nnvirtual-component-regexp ,server)
+         defs))
+  (nnoo-change-server 'nnvirtual server defs)
+  (if nnvirtual-component-groups
+      t
+    (setq nnvirtual-mapping nil)
+    ;; Go through the newsrc alist and find all component groups.
+    (let ((newsrc (cdr gnus-newsrc-alist))
+         group)
+      (while (setq group (car (pop newsrc)))
+       (and (string-match nnvirtual-component-regexp group) ; Match
+            ;; Add this group to the list of component groups.
+            (setq nnvirtual-component-groups
+                  (cons group 
+                        (delete group nnvirtual-component-groups))))))
+    (if (not nnvirtual-component-groups)
+       (nnheader-report 'nnvirtual "No component groups: %s" server)
+      t)))
+
+(deffoo nnvirtual-request-group (group &optional server dont-check)
+  (nnvirtual-possibly-change-server server)
   (cond
-   ((null (nnvirtual-possibly-change-group
-          group server 
-          (if nnvirtual-always-rescan nil (not dont-check))))
+   ((null nnvirtual-component-groups)
     (setq nnvirtual-current-group nil)
     (nnheader-report 'nnvirtual "No component groups in %s" group))
    (t
+    (unless dont-check
+      (nnvirtual-create-mapping))
+    (setq nnvirtual-current-group group)
     (let ((len (length nnvirtual-mapping)))
       (nnheader-insert "211 %d 1 %d %s\n" len len group)))))
 
-(defun nnvirtual-request-type (group &optional article)
-  (when (nnvirtual-possibly-change-group group nil)
-    (if (not article)
-       'unknown
-      (let ((mart (assq article nnvirtual-mapping)))
-       (when mart
-         (gnus-request-type (cadr mart) (car mart)))))))
-
-(defun nnvirtual-request-update-mark (group article mark)
-  (when (nnvirtual-possibly-change-group group nil)
-    (let* ((nart (assq article nnvirtual-mapping))
-          (cgroup (cadr nart))
-          ;; The component group might be a virtual group.
-          (nmark (gnus-request-update-mark cgroup (caddr nart) mark)))
-      (when (and (= mark nmark)
-                (gnus-group-auto-expirable-p cgroup))
-       (setq mark gnus-expirable-mark))))
+(deffoo nnvirtual-request-type (group &optional article)
+  (if (not article)
+      'unknown
+    (let ((mart (assq article nnvirtual-mapping)))
+      (when mart
+       (gnus-request-type (cadr mart) (car mart))))))
+
+(deffoo nnvirtual-request-update-mark (group article mark)
+  (let* ((nart (assq article nnvirtual-mapping))
+        (cgroup (cadr nart))
+        ;; The component group might be a virtual group.
+        (nmark (gnus-request-update-mark cgroup (caddr nart) mark)))
+    (when (and (= mark nmark)
+              (gnus-group-auto-expirable-p cgroup))
+      (setq mark gnus-expirable-mark)))
   mark)
     
-(defun nnvirtual-close-group (group &optional server)
-  (when (nnvirtual-possibly-change-group group server)
+(deffoo nnvirtual-close-group (group &optional server)
+  (when (nnvirtual-possibly-change-server server)
     ;; Copy (un)read articles.
     (nnvirtual-update-reads)
-    (setq nnvirtual-mapping nil
-         nnvirtual-current-group nil
-         nnvirtual-component-groups nil)
     ;; We copy the marks from this group to the component
     ;; groups here.
     (nnvirtual-update-marked))
   t)
     
-(defun nnvirtual-request-list (&optional server) 
+(deffoo nnvirtual-request-list (&optional server) 
   (nnheader-report 'nnvirtual "LIST is not implemented."))
 
-(defun nnvirtual-request-newgroups (date &optional server)
+(deffoo nnvirtual-request-newgroups (date &optional server)
   (nnheader-report 'nnvirtual "NEWGROUPS is not supported."))
 
-(defun nnvirtual-request-list-newsgroups (&optional server)
+(deffoo nnvirtual-request-list-newsgroups (&optional server)
   (nnheader-report 'nnvirtual "LIST NEWSGROUPS is not implemented."))
 
-(defun nnvirtual-request-update-info (group info &optional server)
-  (when (nnvirtual-possibly-change-group group server)
+(deffoo nnvirtual-request-update-info (group info &optional server)
+  (when (nnvirtual-possibly-change-server server)
     (let ((map nnvirtual-mapping)
          (marks (mapcar (lambda (m) (list (cdr m))) gnus-article-mark-lists))
          reads mr m op)
@@ -279,8 +286,8 @@ virtual group.")
          (setcdr (nthcdr 2 info) (list marks))))
       t)))
 
-(defun nnvirtual-catchup-group (group &optional server all)
-  (nnvirtual-possibly-change-group group server)
+(deffoo nnvirtual-catchup-group (group &optional server all)
+  (nnvirtual-possibly-change-server server)
   (let ((gnus-group-marked nnvirtual-component-groups)
        (gnus-expert-user t))
     ;; Make sure all groups are activated.
@@ -293,9 +300,8 @@ virtual group.")
       (set-buffer gnus-group-buffer)
       (gnus-group-catchup-current nil all))))
 
-(defun nnvirtual-find-group-art (group article)
+(deffoo nnvirtual-find-group-art (group article)
   "Return the real group and article for virtual GROUP and ARTICLE."
-  (nnvirtual-possibly-change-group group nil)
   (let ((mart (assq article nnvirtual-mapping)))
     (when mart
       (cons (cadr mart) (caddr mart)))))
@@ -324,61 +330,15 @@ virtual group.")
                    (concat "Xref: " (mail-header-xref header) "\t")
                  "") "\n")))))
 
-(defun nnvirtual-possibly-change-group (group regexp &optional check)
-  (let ((inf t))
-    (when (or (not (equal group nnvirtual-current-group))
-             check)
-      (setq inf (assoc group nnvirtual-group-alist))
-      (when nnvirtual-current-group
-       ;; Push the old group variables onto the alist.
-       (setq nnvirtual-group-alist
-             (cons (list nnvirtual-current-group
-                         nnvirtual-component-groups
-                         nnvirtual-mapping)
-                   (delq inf nnvirtual-group-alist))))
-      (if check
-         ;; We nix out the variables.
-         (setq nnvirtual-current-group nil
-               nnvirtual-component-groups nil
-               nnvirtual-mapping nil
-               nnvirtual-group-alist
-               (delq (assoc group nnvirtual-group-alist)
-                     nnvirtual-group-alist))
-       (setq nnvirtual-current-group nil
-             nnvirtual-component-groups nil
-             nnvirtual-mapping nil)
-       ;; Try to find the variables in the assoc.
-       (when (and inf (equal (nth 3 inf) regexp))
-         (setq nnvirtual-current-group (car inf)
-               nnvirtual-component-groups (nth 1 inf)
-               nnvirtual-mapping (nth 2 inf))))
-      
-      (unless nnvirtual-component-groups
-       (setq nnvirtual-mapping nil)
-       (setq nnvirtual-current-group group)
-       ;; Go through the newsrc alist and find all component groups.
-       (let ((newsrc (cdr gnus-newsrc-alist))
-             (virt-group (gnus-group-prefixed-name 
-                          nnvirtual-current-group '(nnvirtual ""))))
-         (while (setq group (car (pop newsrc)))
-           (and (string-match regexp group) ; Match
-                ;; Virtual groups shouldn't include itself.
-                (not (string= group virt-group))
-                ;; Add this group to the list of component groups.
-                (setq nnvirtual-component-groups
-                      (cons group 
-                            (delete group nnvirtual-component-groups))))))
-       (if (not nnvirtual-component-groups)
-           (nnheader-report 'nnvirtual "No component groups: %s" group)
-         (nnvirtual-create-mapping)))))
-  nnvirtual-component-groups)
+(defun nnvirtual-possibly-change-server (server)
+  (or (not server)
+      (nnoo-current-server-p 'nnvirtual server)
+      (nnvirtual-open-server server)))
 
 (defun nnvirtual-update-marked ()
   "Copy marks from the virtual group to the component groups."
   (let ((mark-lists gnus-article-mark-lists)
-       (marks (gnus-info-marks (gnus-get-info 
-                                (concat "nnvirtual:"
-                                        nnvirtual-current-group))))
+       (marks (gnus-info-marks (gnus-get-info (nnvirtual-current-group))))
        type list mart cgroups)
     (while (setq type (cdr (pop mark-lists)))
       (setq list (gnus-uncompress-range (cdr (assq type marks))))
@@ -397,7 +357,7 @@ virtual group.")
   "Copy (un)reads from the current group to the component groups."
   (let ((groups (mapcar (lambda (g) (list g)) nnvirtual-component-groups))
        (articles (gnus-list-of-unread-articles
-                  (concat "nnvirtual:" nnvirtual-current-group)))
+                  (nnvirtual-current-group)))
        m)
     (while articles
       (setq m (assq (pop articles) nnvirtual-mapping))
@@ -405,6 +365,10 @@ virtual group.")
     (while groups
       (gnus-update-read-articles (caar groups) (cdr (pop groups))))))
 
+(defun nnvirtual-current-group ()
+  "Return the prefixed name of the current nnvirtual group."
+  (concat "nnvirtual:" nnvirtual-current-group))
+
 (defsubst nnvirtual-marks (article marks)
   "Return a list of mark types for ARTICLE."
   (let (out)
@@ -439,7 +403,9 @@ virtual group.")
                                     g n (and (memq n unreads) t)
                                     (inline (nnvirtual-marks n marks))))
                             (gnus-uncompress-range active))))
-                nnvirtual-component-groups))
+                (setq nnvirtual-component-groups
+                      (delete (nnvirtual-current-group)
+                              nnvirtual-component-groups))))
               (lambda (m1 m2)
                 (< (car m1) (car m2)))))
     (i 0))
index 8272862..9f36aed 100644 (file)
@@ -1,3 +1,14 @@
+Sat Apr 13 13:53:34 1996  Lars Magne Ingebrigtsen  <lars@eyesore.no>
+
+       * gnus.texi (Writing New Backends): New node.
+       (Declaring Backends): New node.
+       (An Example Backend): New node.
+       (Optional Backend Functions): Fix return values.
+
+Wed Apr 10 08:36:20 1996  Lars Magne Ingebrigtsen  <lars@eyesore.no>
+
+       * gnus.texi (Message): New chapter.
+
 Tue Apr  9 23:41:15 1996  Lars Magne Ingebrigtsen  <larsi@aegir.ifi.uio.no>
 
        * gnus.texi (GroupLens): Moved.
index fe5bd55..aa3d88b 100644 (file)
@@ -300,6 +300,7 @@ the program.
 * The Group Buffer::      Selecting, subscribing and killing groups.
 * The Summary Buffer::    Reading, saving and posting articles.
 * The Article Buffer::    Displaying and handling articles.
+* Message::               Message sending interface.
 * Composing Messages::    Information on sending mail and news.
 * Select Methods::        Gnus reads all messages from various select methods.
 * Scoring::               Assigning values to articles.
@@ -6382,57 +6383,85 @@ This is the delimiter mentioned above.  By default, it is @samp{^L}
 @end table
 
 
-@node Composing Messages
-@chapter Composing Messages
+@node Message
+@chapter Message
 @cindex reply
 @cindex followup
 @cindex post
 
-@kindex C-c C-c (Post)
-All commands for posting and mailing will put you in a post or mail
-buffer where you can edit the article all you like, before you send the
-article by pressing @kbd{C-c C-c}.  If you are in a foreign news group,
-and you wish to post the article using the foreign server, you can give
-a prefix to @kbd{C-c C-c} to make Gnus try to post using the foreign
-server.
+All message composition (both mail and news) takes place in
+@code{message} mode buffers.  
 
-@menu 
-* Mail::                 Mailing and replying.
-* Post::                 Posting and following up.
-* Posting Server::       What server should you post via?
-* Mail and Post::        Mailing and posting at the same time.
-* Archived Messages::    Where Gnus stores the messages you've sent.
-* Posting Styles::       An easier way to configure some key elements.
-* Drafts::               Postponing messages and rejected messages.
-* Rejected Articles::    What happens if the server doesn't like your article?
+@menu
+* Message Interface::         Setting up message buffers.
+* Message Commands::          Commands you can execute in message mode buffers.
+* Message Variables::         Customizing the message buffers.
 @end menu
 
-Also see @pxref{Canceling and Superseding} for information on how to
-remove articles you shouldn't have posted.
 
+@node Message Interface
+@section Message Interface
 
-@node Mail
-@section Mail
+When a program (or a person) wants to respond to a message -- reply,
+follow up, forward, cancel -- the program (or person) should just put
+point in the buffer where the message is and call the required command.
+@code{Message} will then pop up a new @code{message} mode buffer with
+appropriate headers filled out, and the user can edit the message before
+sending it.
 
-Variables for customizing outgoing mail:
+@menu
+* New Mail Message::
+* New News Message::
+* Reply::
+* Wide Reply::
+* Followup::
+* Canceling News::
+* Superseding::
+* Forwarding::
+* Resending::
+* Bouncing::
+@end menu
+
+
+@node New Mail Message
+@subsection New Mail Message
+
+The @code{message-mail} command pops up a new message buffer.  
+
+Two optional parameters are accepted: The first will be used as the
+@code{To} header and the second as the @code{Subject} header.  If these
+aren't present, those two headers will be empty.
 
-@table @code
-@item gnus-reply-to-function
-@vindex gnus-reply-to-function
-Gnus uses the normal methods to determine where replies are to go, but
-you can change the behavior to suit your needs by fiddling with this
-variable.
+
+@node New News Message
+@subsection New News Message
+
+The @code{message-news} command pops up a new message buffer.  
+
+This function accepts two optional parameters.  The first will be used
+as the @code{Newsgroups} header and the second as the @code{Subject}
+header.  If these aren't present, those two headers will be empty.
+
+
+@node Reply
+@subsection Reply
+
+The @code{message-reply} function pops up a message buffer that's a
+reply to the message in the current buffer.
+
+Message uses the normal methods to determine where replies are to go,
+but you can change the behavior to suit your needs by fiddling with the
+@code{message-reply-to-function} variable.
 
 If you want the replies to go to the @code{Sender} instead of the
-@code{From} in the group @samp{mail.stupid-list}, you could do something
-like this:
+@code{From}, you could do something like this:
 
 @lisp
-(setq gnus-reply-to-function
-      (lambda (group)
-       (cond ((string= group "mail.stupid-list")
-               (mail-fetch-field "sender"))
-             (t
+(setq message-reply-to-function
+      (lambda ()
+       (cond ((equal (mail-fetch-field "from") "somebody")
+               (mail-fetch-field "sender"))     
+             (t 
               nil))))
 @end lisp
 
@@ -6450,167 +6479,406 @@ should be a cons, where the car should be the name of an header
 (eg. @samp{larsi@@ifi.uio.no}).  All these headers will be inserted into
 the head of the outgoing mail. 
 
-@item gnus-mail-send-method
-@vindex gnus-mail-send-method
-@vindex send-mail-function
-@findex sendmail-send-it
-This variable says how a mail should be mailed.  It uses the function in
-the @code{send-mail-function} variable as the default, which usually is
-@code{sendmail-send-it}.
 
-@item gnus-uu-digest-headers
-@vindex gnus-uu-digest-headers
-List of regexps to match headers included in digested messages.  The
-headers will be included in the sequence they are matched.
+@node Wide Reply
+@subsection Wide Reply
+
+The @code{message-wide-reply} pops up a message buffer that's a wide
+reply to the message in the current buffer.
+
+Message uses the normal methods to determine where wide replies are to go,
+but you can change the behavior to suit your needs by fiddling with the
+@code{message-wide-reply-to-function}.  It is used in the same way as
+@code{message-reply-to-function} (@pxref{Reply}). 
+
+
+@node Followup
+@subsection Followup
+
+The @code{message-followup} command pops up a message buffer that's a
+followup to the message in the current buffer.
+
+Message uses the normal methods to determine where followups are to go,
+but you can change the behavior to suit your needs by fiddling with the
+@code{message-followup-to-function}.  It is used in the same way as
+@code{message-reply-to-function} (@pxref{Reply}).
+
+The @code{message-use-followup-to} variable says what to do about
+@code{Followup-To} headers.  If it is @code{use}, always use the value.
+If it is @code{ask} (which is the default), ask whether to use the
+value.  If it is @code{t}, use the value unless it is @samp{poster}.  If
+it is @code{nil}, don't use the value.
+
+
+@node Canceling News
+@subsection Canceling News
+
+The @code{message-cancel-news} command cancels the article in the
+current buffer.
+
+
+@node Superseding
+@subsection Superseding
+
+The @code{message-supersede} command pops up a message buffer that will
+supersede the message in the current buffer.
 
-@item gnus-mail-hook
-@vindex gnus-mail-hook
-Hook called as the last thing after setting up a mail buffer.
-
-@item gnus-required-mail-headers
-@vindex gnus-required-mail-headers
-@cindex sendmail
-Gnus will generate headers in all outgoing mail instead of letting
-@code{sendmail} do it for us.  This makes it possible to do more neat
-stuff, like putting mail without sending it, do hairy @code{Fcc}
-handling, and much more.  This variable controls what headers Gnus will
-generate, and is of the exact same form as @code{gnus-required-headers},
-which does the same for news articles (@pxref{Post}). 
-
-@cindex X-Mailer
-The @code{Newsgroups} header is illegal in this list, while @code{To} is
-required, and @code{X-Mailer} can be added if you so should want.
-
-@vindex gnus-forward-start-separator
-@item gnus-forward-start-separator
-Delimiter inserted before forwarded messages.
-
-@vindex gnus-forward-end-separator
-@item gnus-forward-end-separator
-Delimiter inserted after forwarded messages.
-
-@vindex gnus-signature-before-forwarded-message
-@item gnus-signature-before-forwarded-message
+Headers matching the @code{message-ignored-supersedes-headers} are
+removed before popping up the new message buffer.  The default is
+@samp{^Path:\\|^Date\\|^NNTP-Posting-Host:\\|^Xref:\\|^Lines:\\|^Received:\\|^X-From-Line:\\|Return-Path:}.
+
+
+
+@node Forwarding
+@subsection Forwarding
+
+The @code{message-forward} command pops up a message buffer to forward
+the message in the current buffer.  If given a prefix, forward using
+news.
+
+@table @code
+@item message-forward-start-separator
+Delimiter inserted before forwarded messages.  The default is
+@samp{------- Start of forwarded message -------\n}. 
+
+@vindex message-forward-end-separator
+@item message-forward-end-separator
+Delimiter inserted after forwarded messages.  The default is
+@samp{------- End of forwarded message -------\n}. 
+
+@item message-signature-before-forwarded-message
 If this variable is @code{t}, which it is by default, your personal
 signature will be inserted before the forwarded message.  If not, the
 forwarded message will be inserted first in the new mail.
 
-@item gnus-forward-included-headers
-@vindex gnus-forward-included-headers
-Regexp matching header lines to be included in forwarded messages.  It
-uses the same regexp as @code{gnus-visible-headers} by default.
-
-@end table
-
-@kindex C-c M-C-c (Mail)
-@kindex C-c M-C-p (Mail)
-@findex gnus-put-message
-You normally send a mail message by pressing @kbd{C-c C-c}.  However,
-you may wish to just put the mail message you have just written in your
-own local mail group instead of sending it.  Sounds quite unlikely, but
-I found that useful, so you can now also press @kbd{C-c M-C-p} to
-@dfn{put} the article in the current mail group, or, if there is no such
-thing, you will be prompted for a mail group, and then the article will
-be put there.  This means that the article is @dfn{not} mailed.  
-
-@findex gnus-kill-message-buffer
-@cindex kill mail buffer
-@kindex C-x k (Mail)
-@kindex C-x k (Post)
-If enter a mail (or post) buffer and then decide not to compose a
-message after all, you'd normally just kill the buffer with @kbd{C-x k}.
-However, since the mail and post buffers are associated with articles in
-the draft group, this will leave lots of rubbish articles in the draft
-group.  To avoid that problem, kill mail and post buffer with @kbd{C-c
-C-k} (@code{gnus-kill-message-buffer}) instead.  This will make sure
-that everything is properly cleaned up before the buffer is killed.
-
-@vindex gnus-mail-method
-There are three ``methods'' for handling all mail.  The default is
-@code{sendmail}.  Some people like what @code{mh} does better, and some
-people prefer @code{vm}.  Set @code{gnus-mail-method} to the one you
-think is way koolest.
-
-Three variables for customizing what to use when:
+@item message-forward-included-headers
+Regexp matching header lines to be included in forwarded messages.  
+
+@end table
+
+
+@node Resending
+@subsection Resending
+
+The @code{message-resend} command will prompt the user for an address
+and resend the message in the current buffer to that address.
+
+Headers the match the @code{message-ignored-resent-headers} regexp will
+be removed before sending the message.  The default is
+@samp{^Return-receipt}. 
+
+
+@node Bouncing
+@subsection Bouncing
+
+@findex message-bounce
+The @code{message-bounce} command will, if the current buffer contains a
+bounced mail message, pop up a message buffer stripped of the bounce
+information.
+
+@vindex message-ignored-bounced-headers
+Headers that match the @code{message-ignored-bounced-headers} regexp
+will be removed before popping up the buffer.  The default is
+@samp{^Received:}. 
+
+
+@node Message Commands
+@section Message Commands
+
+@menu
+* Message Header Commands::     Commands for moving to headers.
+* Message Movement::            Moving around in message buffers.
+* Message Insertion::           Inserting things into message buffers.
+* Various Message::             Various things.
+* Sending Messages::            Actually sending the message.
+@end menu
+
+
+@node Message Header Commands
+@subsection Message Header Commands
+
+All these commands move to the header in question.  If it doesn't exist,
+it will be inserted.
+
+@table @kbd
+
+@item C-c ?
+Describe the message mode.
+
+@item C-c C-f C-t
+Go to the @code{To} header (@code{message-goto-to}).
+
+@item C-c C-f C-b
+Go to the @code{Bcc} header (@code{message-goto-bcc}).
+
+@item C-c C-f C-f
+Go to the @code{Fcc} header (@code{message-goto-fcc}).
+
+@item C-c C-f C-c
+Go to the @code{Cc} header (@code{message-goto-cc}).
+
+@item C-c C-f C-s
+Go to the @code{Subject} header (@code{message-goto-subject}).
+
+@item C-c C-f C-r
+Go to the @code{Reply-To} header (@code{message-goto-reply-to}).
+
+@item C-c C-f C-n
+Go to the @code{Newsgroups} header (@code{message-goto-newsgroups}).
+
+@item C-c C-f C-d
+Go to the @code{Distribution} header (@code{message-goto-distribution}).
+
+@item C-c C-f C-o
+Go to the @code{Followup-To} header (@code{message-goto-followup-to}).
+
+@item C-c C-f C-k
+Go to the @code{Keywords} header (@code{message-goto-keywords}).
+
+@item C-c C-f C-u
+Go to the @code{Summary} header (@code{message-goto-summary}).
+
+@end table
+
+
+@node Message Movement
+@subsection Message Movement
+
+@table @kbd
+@item C-c C-b
+Move to the beginning of the body of the message
+(@code{message-goto-body}). 
+
+@item C-c C-i
+Move to the signature of the message (@code{message-goto-signature}).
+
+@end table
+
+
+@node Message Insertion
+@subsection Message Insertion
+
+@table @kbd
+
+@item C-c C-y
+Yank the message that's being replied to into the message buffer
+(@code{message-yank-original}). 
+
+@item C-c C-q
+Fill the yanked message (@code{message-fill-yanked-message}). 
+
+@item C-c C-w
+Insert a signature at the end of the buffer
+(@code{message-insert-signature}).  
+
+@end table
 
 @table @code
+@item message-ignored-cited-headers
+All headers that match this regexp will be removed from yanked
+messages.  The default is @samp{.}, which means that all headers will be
+removed.
 
-@vindex gnus-mail-reply-method
-@item gnus-mail-reply-method
-This function is used to compose replies.  The three functions available
-are:
+@item message-citation-line-function
+Function called to insert the citation line.  The default is
+@code{message-insert-citation-line}. 
 
-@findex gnus-mail-reply-using-vm
-@findex gnus-mail-reply-using-mhe
-@findex gnus-mail-reply-using-mail
-@itemize @bullet
-@item 
-@code{gnus-mail-reply-using-mail} (sendmail)
-@item 
-@code{gnus-mail-reply-using-mhe} (mh)
-@item
-@code{gnus-mail-reply-using-vm} (vm)
-@end itemize
+@item message-yank-prefix
+@cindex yanking
+@cindex quoting
+When you are replying to or following up an article, you normally want
+to quote the person you are answering.  Inserting quoted text is done by
+@dfn{yanking}, and each quoted line you yank will have
+@code{message-yank-prefix} prepended to it.  The default is @samp{> }.
+If it is @code{nil}, just indent the message.
 
-@vindex gnus-mail-forward-method
-@item gnus-mail-forward-method
-This function is used to forward messages.  The three functions available
-are:
+@item message-indentation-spaces
+Number of spaces to indent yanked messages.
 
-@findex gnus-mail-forward-using-vm
-@findex gnus-mail-forward-using-mhe
-@findex gnus-mail-forward-using-mail
-@itemize @bullet
-@item 
-@code{gnus-mail-forward-using-mail} (sendmail)
-@item 
-@code{gnus-mail-forward-using-mhe} (mh)
-@item
-@code{gnus-mail-forward-using-vm} (vm)
-@end itemize
+@item message-cite-function
+Function for citing an original message.  The default is
+@code{message-cite-original}. 
 
-@vindex gnus-mail-other-window-method
-@item gnus-mail-other-window-method
-This function is used to send mails.  The three functions available are:
+@item message-indent-citation-function
+Function for modifying a citation just inserted in the mail buffer.
+This can also be a list of functions.  Each function can find the
+citation between @code{(point)} and @code{(mark t)}.  And each function
+should leave point and mark around the citation text as modified.
 
-@findex gnus-mail-other-window-using-vm
-@findex gnus-mail-other-window-using-mhe
-@findex gnus-mail-other-window-using-mail
-@itemize @bullet
-@item 
-@code{gnus-mail-other-window-using-mail} (sendmail)
-@item 
-@code{gnus-mail-other-window-using-mhe} (mh)
-@item
-@code{gnus-mail-other-window-using-vm} (vm)
-@end itemize
+@item message-signature
+String to be inserted at the end of the message buffer.  If @code{t}
+(which is the default), the @code{message-signature-file} file will be
+inserted instead.  If a function, the result from the function will be
+used instead.  If a form, the result from the form will be used instead.
+
+@item message-signature-file
+File containing the signature to be inserted at the end of the buffer.
+The default is @samp{~/.signature}.
 
 @end table
 
+Note that RFC1036 says that a signature should be preceded by the three
+characters @samp{-- } on a line by themselves.  This is to make it
+easier for the recipient to automatically recognize and process the
+signature.  So don't remove those characters, even though you might feel
+that they ruin you beautiful design, like, totally.
 
-@node Post
-@section Post
+Also note that no signature should be more than four lines long.
+Including ASCII graphics is an efficient way to get everybody to believe
+that you are silly and have nothing important to say.
 
-Variables for composing news articles:
 
-@vindex gnus-required-headers
-@code{gnus-required-headers} a list of header symbols.  These headers
-will either be automatically generated, or, if that's impossible, they
-will be prompted for.  The following symbols are legal:
+
+@node Various Message
+@subsection Various Message
+
+@table @kbd
+
+@item C-c C-r
+Caesar rotate (aka. rot13) the current message
+(@code{message-caesar-buffer-body}).  If narrowing is in effect, just
+rotate the visible portion of the buffer.  A numerical prefix says how
+many places to rotate the text.  The default is 13.
+
+@item C-c C-t
+Insert a @code{To} header that contains the @code{Reply-To} or
+@code{From} header of the message you're following up
+(@code{message-insert-to}). 
+
+@item C-c C-n
+Insert a @code{Newsgroups} header that reflects the @code{Followup-To}
+or @code{Newsgroups} header of the article you're replying to.
+
+@end table
+
+
+@node Sending Messages
+@subsection Sending Messages
+
+@table @kbd
+@item C-c C-c
+Send the message and bury the current buffer
+(@code{message-send-and-exit}). 
+
+@item C-c C-s
+Send the message (@code{message-send}). 
+
+@end table
+
+
+@node Message Variables
+@section Message Variables
+
+@menu
+* Message Headers::
+* Mail Headers::
+* Mail Variables::
+* News Headers::
+* News Variables::
+* Various Message Variables::
+* Sending Variables::
+@end menu
+
+
+@node Message Headers
+@subsection Message Headers
+
+Message is a quite aggressive on the message generation front.  It has
+to be -- it's a combined news and mail agent.  To be able to send
+combined messages, it has to generate all headers itself to ensure that
+mail and news copies of messages look sufficiently similar.
+
+@table @code
+
+@item message-generate-headers-first
+If non-@code{nil}, generate all headers before starting to compose the
+message.  
+
+@item message-from-style
+Specifies how @code{From} headers should look.  There are four legal
+values:
+
+@table @code
+@item nil
+Just the address -- @samp{king@@grassland.com}.
+
+@item parens
+@samp{king@@grassland.com (Elvis Parsley)}.
+
+@item angles
+@samp{Elvis Parsley <king@@grassland.com>}.
+
+@item default
+Look like @code{angles} if that doesn't require quoting, and
+@code{parens} if it does.  If even @code{parens} requires quoting, use
+@code{angles} anyway.
+
+@end table
+
+@item message-deletable-headers
+Headers in this list that were previously generated by Gnus will be
+deleted before posting.  Let's say you post an article.  Then you decide
+to post it again to some other group, you naughty boy, so you jump back
+to the @code{*post-buf*} buffer, edit the @code{Newsgroups} line, and
+ship it off again.  By default, this variable makes sure that the old
+generated @code{Message-ID} is deleted, and a new one generated.  If
+this isn't done, the entire empire would probably crumble, anarchy would
+prevail, and cats would start walking on two legs and rule the world.
+Allegedly.  
+
+@item message-default-headers
+This string is inserted at the end of the headers in all message
+buffers.
+
+@end table
+
+
+@node Mail Headers
+@subsection Mail Headers
+
+@table @code
+@item message-required-mail-headers
+See @pxref{News Headers} for the syntax of this variable.  It is
+@code{(From Date Subject (optional . In-Reply-To) Message-ID Lines
+(optional . X-Mailer))} by default.
+
+@item message-ignored-mail-headers
+Regexp of headers to be removed before mailing.  The default is
+@samp{^Gcc:\\|^Fcc:}. 
+
+@item message-default-mail-headers
+This string is inserted at the end of the headers in all message
+buffers that are initialized as mail.
+
+@end table
+
+
+@node Mail Variables
+@subsection Mail Variables 
+
+@table @code
+@item message-send-mail-function
+Function used to send the current buffer as mail.  The default is
+@code{message-send-mail}. 
+
+@end table
+
+
+@node News Headers
+@subsection News Headers
+
+@code{message-required-news-headers} a list of header symbols.  These
+headers will either be automatically generated, or, if that's
+impossible, they will be prompted for.  The following symbols are legal:
 
 @table @code
 
 @item From
 @cindex From
-@findex gnus-inews-user-name
-@vindex gnus-user-from-line
-@vindex gnus-user-login-name
-@vindex gnus-local-domain
-@vindex user-mail-address
 This required header will be filled out with the result of the
-@code{gnus-inews-user-name} function, which depends on the
-@code{gnus-user-from-line}, @code{gnus-user-login-name},
-@code{gnus-local-domain} and @code{user-mail-address} variables.
+@code{message-make-from} function, which depends on the
+@code{message-from-style}, @code{user-full-name},
+@code{user-mail-address} variables.
 
 @item Subject
 @cindex Subject
@@ -6623,11 +6891,10 @@ to.  If it isn't present already, it will be prompted for.
 
 @item Organization
 @cindex organization
-@vindex gnus-local-organization
-@vindex gnus-organization-file
 This optional header will be filled out depending on the
-@code{gnus-local-organization} variable.  @code{gnus-organization-file}
-will be used if that variable is nil.
+@code{message-user-organization} variable.
+@code{message-user-organization-file} will be used if that variable is
+@code{t}.
 
 @item Lines
 @cindex Lines
@@ -6640,28 +6907,35 @@ created based on date, time, user name and system name.
 
 @item X-Newsreader
 @cindex X-Newsreader
-This optional header will be filled out with the Gnus version numbers. 
+This optional header will be filled out according to the
+@code{message-newsreader} local variable.
+
+@item X-Mailer
+This optional header will be filled out according to the
+@code{message-mailer} local variable, unless there already is an
+@code{X-Newsreader} header present.
+
+@item In-Reply-To
+This optional header is filled out using the @code{Date} and @code{From}
+header of the article being replied.
 
 @item Expires
-@vindex gnus-article-expires
 @cindex Expires
 This extremely optional header will be inserted according to the
-@code{gnus-article-expires} variable.  It is highly deprecated and
-shouldn't be used unless you know what you're doing.
+@code{message-expires} variable.  It is highly deprecated and shouldn't
+be used unless you know what you're doing.
 
 @item Distribution
 @cindex Distribution
-@findex gnus-distribution-function
 This optional header is filled out according to the
-@code{gnus-distribution-function} variable.  It is a deprecated and much
-misunderstood header.
+@code{message-distribution-function} variable.  It is a deprecated and
+much misunderstood header.
 
 @item Path
 @cindex path
-@vindex gnus-use-generic-path
 This extremely optional header should probably not ever be used.
 However, some @emph{very} old servers require that this header is
-present.  @code{gnus-use-generic-path} further controls how this
+present.  @code{message-user-path} further controls how this
 @code{Path} header is to look.  If is is @code{nil}, the the server name
 as the leaf node.  If is is a string, use the string.  If it is neither
 a string nor @code{nil}, use the user name only.  However, it is highly
@@ -6680,145 +6954,16 @@ into the list.  If you want to insert a funny quote, you could enter
 something like @code{(X-Yow . yow)} into the list.  The function
 @code{yow} will then be called without any arguments.
 
-The list contains a cons where the car of the cons is @code{optional},
-the cdr of this cons will only be inserted if it is non-@code{nil}.
+If the list contains a cons where the car of the cons is
+@code{optional}, the cdr of this cons will only be inserted if it is
+non-@code{nil}.
 
-Other variables for customizing outgoing articles:
+Other variables for customizing outgoing news articles:
 
 @table @code
-@item nntp-news-default-headers
-@vindex nntp-news-default-headers
-If non-@code{nil}, this variable will override
-@code{mail-default-headers} when posting.  This variable should then be
-a string.  This string will be inserted, as is, in the head of all
-outgoing articles.
-
-@item gnus-use-followup-to
-@vindex gnus-use-followup-to
-If @code{nil}, always ignore the Followup-To header.  If it is @code{t},
-use its value, but ignore the special value @samp{poster}, which will
-send the followup as a reply mail to the person you are responding to.
-If it is the symbol @code{ask}, query the user before posting.
-If it is the symbol @code{use}, always use the value.
-
-@item gnus-followup-to-function
-@vindex gnus-followup-to-function
-This variable is most useful in mail groups, where ``following up''
-really means sending a mail to a list address.  Gnus uses the normal
-methods to determine where follow-ups are to go, but you can change the
-behavior to suit your needs by fiddling with this variable.
-
-If you want the followups to go to the @code{Sender} instead of the
-@code{From} in the group @samp{mail.stupid-list}, you could do something
-like this:
-
-@lisp
-(setq gnus-followup-to-function
-      (lambda (group)
-       (cond ((string= group "mail.stupid-list")
-               (mail-fetch-field "sender"))
-             (t
-              nil))))
-@end lisp
-
-This function will be called narrowed to header of the article that is
-being followed up.
-
-@item gnus-removable-headers
-@vindex gnus-removable-headers
-@cindex NNTP-Posting-Host
-Some headers that are generated are toxic to the @sc{nntp} server.
-These include the @code{NNTP-Posting-Host}, @code{Bcc} and @code{Xref},
-so these headers are deleted if they are present in this list of
-symbols.
-
-@item gnus-deletable-headers
-@vindex gnus-deletable-headers
-Headers in this list that were previously generated by Gnus will be
-deleted before posting.  Let's say you post an article.  Then you decide
-to post it again to some other group, you naughty boy, so you jump back
-to the @code{*post-buf*} buffer, edit the @code{Newsgroups} line, and
-ship it off again.  By default, this variable makes sure that the old
-generated @code{Message-ID} is deleted, and a new one generated.  If
-this isn't done, the entire empire would probably crumble, anarchy would
-prevail, and cats would start walking on two legs and rule the world.
-Allegedly. 
-
-@item gnus-signature-function
-@vindex gnus-signature-function
-If non-@code{nil}, this variable should be a function that returns a
-signature file name.  The function will be called with the name of the
-group being posted to.  If the function returns a string that doesn't
-correspond to a file, the string itself is inserted.  If the function
-returns @code{nil}, the @code{gnus-signature-file} variable will be used
-instead.
-
-@item gnus-post-prepare-function
-@vindex gnus-post-prepare-function
-This function is called with the name of the current group after the
-post buffer has been initialized, and can be used for inserting a
-signature.  Nice if you use different signatures in different groups.
-
-@item gnus-post-prepare-hook
-@vindex gnus-post-prepare-hook
-@findex gnus-inews-insert-signature
-This hook is called after a post buffer has been prepared.  If you want
-to insert a signature at this point, you could put
-@code{gnus-inews-insert-signature} into this hook.
-
-@item news-reply-header-hook
-@vindex news-reply-header-hook
-A related variable when following up and replying is this variable,
-which inserts the @dfn{quote line}.  The default value is:
-
-@lisp
-(defvar news-reply-header-hook
-  (lambda ()
-    (insert "In article " news-reply-yank-message-id
-            " " news-reply-yank-from " writes:\n\n")))
-@end lisp
-
-This will create lines like:
-
-@example
-In article <zngay8jrql@@eyesore.no> Lars Mars <lars@@eyesore.no> writes:
-@end example
-
-Having the @code{Message-ID} in this line is probably overkill, so I
-would suggest this hook instead:
 
-@lisp
-(setq news-reply-header-hook
-  (lambda () (insert news-reply-yank-from " writes:\n\n")))
-@end lisp
-
-@item gnus-prepare-article-hook
-@vindex gnus-prepare-article-hook
-This hook is called before the headers have been prepared.  
-
-@item gnus-inews-article-function
-@vindex gnus-inews-article-function
-This function is used to do the actual article processing and header
-checking/generation.  
-
-@item gnus-inews-article-hook
-@vindex gnus-inews-article-hook
-This hook is called right before the article is posted.  By default it
-handles FCC processing (i.e., saving the article to a file.)  You can
-also have this hook add a score to all followups to the article you've
-written (@pxref{Followups To Yourself}). 
-
-@item gnus-inews-article-header-hook
-@vindex gnus-inews-article-header-hook
-@cindex *post-news*
-This hook is called after inserting the required headers in an article
-to be posted.  The hook is called from the @code{*post-news*} buffer,
-narrowed to the head, and is intended for people who would like to
-insert additional headers, or just change headers in some way or other.
-
-@item gnus-check-before-posting
-@vindex gnus-check-before-posting
-If non-@code{nil}, Gnus will attempt to check the legality of the
+@item message-syntax-checks
+If non-@code{nil}, message will attempt to check the legality of the
 headers, as well as some other stuff, before posting.  You can control
 the granularity of the check by adding or removing elements from this
 list.  Legal elements are:
@@ -6861,6 +7006,134 @@ Check whether any of the headers are empty.
 
 All these conditions are checked by default.
 
+@item message-ignored-news-headers
+Regexp of headers to be removed before posting.  The default is
+@samp{^NNTP-Posting-Host:\\|^Xref:\\|^Bcc:\\|^Gcc:\\|^Fcc:}. 
+
+@item message-default-news-headers
+This string is inserted at the end of the headers in all message
+buffers that are initialized as news.
+
+@end table
+
+
+@node News Variables
+@subsection News Variables
+
+@table @code
+@item message-send-news-function
+Function used to send the current buffer as news.  The default is
+@code{message-send-news}. 
+
+@item message-post-method
+Method used for posting a prepared news message.
+
+@end table
+
+
+@node Various Message Variables
+@subsection Various Message Variables
+
+@table @code
+@item message-signature-separator
+Regexp matching the signature separator.  It is @samp{^-- *$} by
+default. 
+
+@item mail-header-separator
+String used to separate the headers from the body.  It is @samp{--text
+follows this line--} by default.
+
+@item message-autosave-directory
+Directory where message buffers will be autosaved to.
+
+@item message-setup-hook
+Hook run when the message buffer has been initialized.
+
+@item message-header-setup-hook
+Hook called narrowed to the headers after initializing the headers. 
+
+@item message-send-hook
+Hook run before sending messages.
+
+@item message-sent-hook
+Hook run after sending messages.
+
+@item message-mode-syntax-table
+Syntax table used in message mode buffers.
+
+@end table
+
+
+
+@node Sending Variables
+@subsection Sending Variables
+
+@table @code
+
+@item message-fcc-handler-function 
+A function called to save outgoing articles.  This function will be
+called with the name of the file to store the article in. The default
+function is @code{rmail-output} which saves in Unix mailbox format.
+
+@item message-courtesy-message
+When sending combined messages, this string is inserted at the start of
+the mailed copy.  If this variable is @code{nil}, no such courtesy
+message will be added.
+
+@end table
+
+
+
+
+
+@node Composing Messages
+@chapter Composing Messages
+@cindex reply
+@cindex followup
+@cindex post
+
+@kindex C-c C-c (Post)
+All commands for posting and mailing will put you in a message buffer
+where you can edit the article all you like, before you send the article
+by pressing @kbd{C-c C-c}.  If you are in a foreign news group, and you
+wish to post the article using the foreign server, you can give a prefix
+to @kbd{C-c C-c} to make Gnus try to post using the foreign server.
+
+@menu 
+* Mail::                 Mailing and replying.
+* Post::                 Posting and following up.
+* Posting Server::       What server should you post via?
+* Mail and Post::        Mailing and posting at the same time.
+* Archived Messages::    Where Gnus stores the messages you've sent.
+* Posting Styles::       An easier way to configure some key elements.
+* Drafts::               Postponing messages and rejected messages.
+* Rejected Articles::    What happens if the server doesn't like your article?
+@end menu
+
+Also see @pxref{Canceling and Superseding} for information on how to
+remove articles you shouldn't have posted.
+
+
+@node Mail
+@section Mail
+
+Variables for customizing outgoing mail:
+
+@table @code
+@item gnus-uu-digest-headers
+@vindex gnus-uu-digest-headers
+List of regexps to match headers included in digested messages.  The
+headers will be included in the sequence they are matched.
+
+@end table
+
+
+@node Post
+@section Post
+
+Variables for composing news articles:
+
+@table @code
 @item gnus-sent-message-ids-file
 @vindex gnus-sent-message-ids-file
 Gnus will keep a @code{Message-ID} history file of all the mails it has
@@ -6920,109 +7193,6 @@ Here's a list of variables that are relevant to both mailing and
 posting:
 
 @table @code
-@item gnus-signature-file
-@itemx mail-signature
-@vindex mail-signature
-@vindex gnus-signature-file
-@cindex double signature
-@cindex signature
-If @code{gnus-signature-file} is non-@code{nil}, it should be the name
-of a file containing a signature (@file{~/.signature} by default).  This
-signature will be appended to all outgoing post.  Most people find it
-more convenient to use @code{mail-signature}, which (sort of) does the
-same, but inserts the signature into the buffer before you start editing
-the post (or mail).  So---if you have both of these variables set, you
-will get two signatures.  Note that @code{mail-signature} does not work
-the same way as @code{gnus-signature-file}, which is a bit confusing.
-If @code{mail-signature} is @code{t}, it will insert
-@file{~/.signature}.  If it is a string, this string will be inserted. 
-
-Note that RFC1036 says that a signature should be preceded by the three
-characters @samp{-- } on a line by themselves.  This is to make it
-easier for the recipient to automatically recognize and process the
-signature.  So don't remove those characters, even though you might feel
-that they ruin you beautiful design, like, totally.
-
-Also note that no signature should be more than four lines long.
-Including ASCII graphics is an efficient way to get everybody to believe
-that you are silly and have nothing important to say.
-
-@item mail-yank-prefix
-@vindex mail-yank-prefix
-@cindex yanking
-@cindex quoting
-When you are replying to or following up an article, you normally want
-to quote the person you are answering.  Inserting quoted text is done by
-@dfn{yanking}, and each quoted line you yank will have
-@code{mail-yank-prefix} prepended to it.  This is @code{nil} by default,
-which isn't very pretty---the prefix will just be some spaces.  Most
-everybody prefers that lines are prepended with @samp{> }, so
-@code{(setq mail-yank-prefix "> ")} in your @file{.emacs} file.
-
-@item mail-yank-ignored-headers
-@vindex mail-yank-ignored-headers
-When you yank a message, you do not want to quote any headers, so
-@code{(setq mail-yank-ignored-headers "^")}.
-
-@item user-mail-address
-@vindex user-mail-address
-@vindex gnus-user-login-name
-@vindex gnus-use-generic-from
-@vindex gnus-local-domain
-If all of @code{gnus-user-login-name}, @code{gnus-use-generic-from} and
-@code{gnus-local-domain} are @code{nil}, Gnus will use
-@code{user-mail-address} as the address part of the @code{From} header.
-
-@item gnus-local-domain
-@vindex gnus-local-domain
-@cindex domain
-The local domain name excluding the host name.  If your host is called
-@samp{narfi.ifi.uio.no}, then this variable should be
-@samp{ifi.uio.no}. 
-
-@item gnus-local-domain
-@vindex gnus-local-domain
-@cindex domain
-The local domain name excluding the host name.  If your host is called
-@samp{narfi.ifi.uio.no}, then this variable should be
-@samp{ifi.uio.no}. 
-
-@item gnus-user-from-line
-@vindex gnus-user-from-line
-Your full, complete e-mail address with name.  This variable overrides
-the other Gnus variables if it is non-@code{nil}.
-
-Here are two example values of this variable: @samp{larsi@@ifi.uio.no
-(Lars Magne Ingebrigtsen)} and @samp{Lars Magne Ingebrigtsen
-<larsi@@ifi.uio.no>}.  The latter version is recommended in news (and is
-probably illegal in mail), but the name has to be quoted if it contains
-non-alpha-numerical characters---@samp{\"Lars M. Ingebrigtsen\"
-<larsi@@ifi.uio.no>}.
-
-@item mail-default-headers
-@vindex mail-default-headers
-This is a string that will be inserted into the header of all outgoing
-mail messages and news articles.  Convenient to use to insert standard
-headers.  If @code{nntp-news-default-headers} is non-@code{nil}, that
-variable will override this one when posting articles.
-
-@item gnus-auto-mail-to-author
-@vindex gnus-auto-mail-to-author
-If @code{ask}, you will be prompted for whether you want to send a mail
-copy to the author of the article you are following up.  If
-non-@code{nil} and not @code{ask}, Gnus will send a mail with a copy of
-all follow-ups to the authors of the articles you follow up.  It's nice
-in one way---you make sure that the person you are responding to gets
-your response.  Other people loathe this method and will hate you dearly
-for it, because it means that they will first get a mail, and then have
-to read the same article later when they read the news.  It is
-@code{nil} by default.
-
-@item gnus-mail-courtesy-message
-@vindex gnus-mail-courtesy-message
-This is a string that will be prepended to all mails that are the result
-of using the variable described above.  
-
 @item gnus-mailing-list-groups
 @findex gnus-mailing-list-groups
 @cindex mailing lists
@@ -7037,24 +7207,6 @@ really are mailing lists.  Then, at least, followups to the mailing
 lists will work most of the time.  Posting to these groups (@kbd{a}) is
 still a pain, though.
 
-@item mail-citation-hook
-@vindex mail-citation-hook
-This hook is run after yanking a message, both in mail and post
-buffers.  Point will be at the beginning of the yanked message and mark
-will be at the end.  If this hook is non-@code{nil} the yanked text
-won't be indented automatically---you have to do that explicitly. 
-
-For instance, if you want to remove signatures automatically, you could
-say something like:
-
-@lisp
-(add-hook 'mail-citation-hook 'gnus-inews-remove-signature)
-@end lisp
-
-This function indents the cited message and then removes the
-signature.  If you decide you want to include the signature after all,
-you can just press the @code{undo} key.
-
 @end table
 
 You may want to do spell-checking on messages that you send out.  Or, if
@@ -7065,15 +7217,9 @@ spell-checking via the @code{ispell} package:
 @cindex ispell
 @findex ispell-message
 @lisp
-(add-hook 'news-inews-hook 'ispell-message)        ;For news posts
-(add-hook 'mail-send-hook 'ispell-message)        ;for mail posts via sendmail
+(add-hook 'message-send-hook 'ispell-message) 
 @end lisp
 
-@findex gnus-inews-insert-mime-headers
-If you want to insert some @sc{mime} headers into the articles you post,
-without doing any actual encoding, you could add
-@code{gnus-inews-insert-mime-headers} to @code{gnus-inews-article-hook}.
-
 
 @node Archived Messages
 @section Archived Messages
@@ -7996,7 +8142,7 @@ course.
 @menu
 * Getting Started Reading Mail:: A simple cookbook example.
 * Splitting Mail::               How to create mail groups.
-* Mail Variables::               Variables for customizing mail handling.
+* Mail Backend Variables::       Variables for customizing mail handling.
 * Fancy Mail Splitting::         Gnus can do hairy splitting of incoming mail.
 * Mail and Procmail::            Reading mail groups that procmail create.
 * Incorporating Old Mail::       What about the old mail you have?
@@ -8115,8 +8261,8 @@ you really should be out collecting empty bottles to save up for next
 month's rent money.
 
 
-@node Mail Variables
-@subsection Mail Variables
+@node Mail Backend Variables
+@subsection Mail Backend Variables
 
 These variables are (for the most part) pertinent to all the various
 mail backends.
@@ -11929,8 +12075,8 @@ wrong show.
 The writer of the original @sc{gnus}.
 
 @item Per Abrahamsen
-Scoring, highlighting and @sc{soup} code (as well as numerous other
-things).
+Custom, scoring, highlighting and @sc{soup} code (as well as numerous
+other things).
 
 @item Luis Fernandes
 Design and graphics.
@@ -12562,6 +12708,7 @@ In the examples and definitions I will refer to the imaginary backend
 @menu
 * Required Backend Functions::        Functions that must be implemented.
 * Optional Backend Functions::        Functions that need not be implemented.
+* Writing New Backends::              Extending old backends.
 @end menu
 
 
@@ -12651,7 +12798,8 @@ non-@code{nil} value.  There should be no data returned.
 @item (nnchoke-close-server &optional SERVER)
 
 Close connection to @var{server} and free all resources connected
-to it. 
+to it.  Return @code{nil} if the server couldn't be closed for some
+reason.
 
 There should be no data returned.
 
@@ -12660,17 +12808,18 @@ There should be no data returned.
 
 Close connection to all servers and free all resources that the backend
 have reserved.  All buffers that have been created by that backend
-should be killed.  (Not the @code{nntp-server-buffer}, though.)
+should be killed.  (Not the @code{nntp-server-buffer}, though.)  This
+function is generally only called when Gnus is shutting down.
 
 There should be no data returned. 
 
 
 @item (nnchoke-server-opened &optional SERVER)
 
-This function should return whether @var{server} is opened, and that the
-connection to it is still alive.  This function should under no
-circumstances attempt to reconnect to a server that is has lost
-connection to. 
+If @var{server} is the current virtual server, and the connection to the
+physical server is alive, then this function should return a
+non-@code{nil} vlue.  This function should under no circumstances
+attempt to reconnect to a server that is has lost connection to.
 
 There should be no data returned.
 
@@ -12695,6 +12844,13 @@ possible to avoid copying large amounts of data from one buffer to
 another, and Gnus mainly request articles to be inserted directly into
 its article buffer.
 
+If it is at all possible, this function should return a cons cell where
+the car is the group name the article was fetched from, and the cdr is
+the article number.  This will enable Gnus to find out what the real
+group and article numbers are when fetching articles by
+@code{Message-ID}.  If this isn't possible, @code{t} should be returned
+on successful article retrievement.
+
 
 @item (nnchoke-open-group GROUP &optional SERVER)
 
@@ -12776,21 +12932,6 @@ clear if the posting could not be completed.
 
 There should be no result data from this function. 
 
-
-@item (nnchoke-request-post-buffer POST GROUP SUBJECT HEADER ARTICLE-BUFFER INFO FOLLOW-TO RESPECT-POSTER)
-
-This function should return a buffer suitable for composing an article
-to be posted by @code{nnchoke-request-post}.  If @var{post} is
-non-@code{nil}, this is not a followup, but a totally new article.
-@var{group} is the name of the group to be posted to.  @var{subject} is
-the subject of the message.  @var{article-buffer} is the buffer being
-followed up, if that is the case.  @var{info} is the group info.
-@var{follow-to} is the group that one is supposed to re-direct the
-article ot.  If @var{respect-poster} is non-@code{nil}, the special
-@samp{poster} value of a @code{Followup-To} header is to be respected.
-
-There should be no result data returned.
-
 @end table
 
 
@@ -12911,7 +13052,7 @@ created after @samp{date}, which is in normal human-readable date
 format.  The data should be in the active buffer format.
 
 
-@item (nnchoke-request-create-groups GROUP &optional SERVER)
+@item (nnchoke-request-create-group GROUP &optional SERVER)
 
 This function should create an empty group with name @var{group}.  
 
@@ -12950,15 +13091,21 @@ If @var{last} is @code{nil}, that means that there is a high likelihood
 that there will be more requests issued shortly, so that allows some
 optimizations. 
 
+The function should return a cons where the car is the group name and
+the cdr is the article number that the article was entered as.
+
 There should be no data returned. 
 
 
-@item (nnchoke-request-accept-article GROUP &optional LAST)
+@item (nnchoke-request-accept-article GROUP &optional SERVER LAST)
 
 This function takes the current buffer and inserts it into @var{group}.
 If @var{last} in @code{nil}, that means that there will be more calls to
 this function in short order.
 
+The function should return a cons where the car is the group name and
+the cdr is the article number that the article was entered as.
+
 There should be no data returned.
 
 
@@ -12989,6 +13136,193 @@ There should be no data returned.
 @end table
 
 
+@node Writing New Backends
+@subsection Writing New Backends
+
+The various backends share many similarities.  @code{nnml} is just like
+@code{nnspool}, but it allows you to edit the articles on the server.
+@code{nnmh} is just like @code{nnml}, but it doesn't use an active file,
+and it doesn't maintain overview databases.  @code{nndir} is just like
+@code{nnml}, but it has no concept of ``groups'', and it doesn't allow
+editing articles.
+
+It would make sense if it were possible to ``inherit'' functions from
+backends when writing new backends.  And, indeed, you can do that if you
+want to.  (You don't have to if you don't want to, of course.)  
+
+All the backends declare their public variables and functions by using a
+package called @code{nnoo}.  
+
+@menu
+* Declaring Backends::     An overview of the @code{nnoo} mechanisms.
+* An Example Backend::     A complete backend.
+@end menu
+
+
+@node Declaring Backends
+@subsubsection Declaring Backends
+
+To inherit functions from other backends (and allow other backends to
+inherit functions from the current backend), you should use the
+following macros:
+following. 
+
+@table @code
+
+@item nnoo-declare
+This macro declares the first parameter to be a child of the subsequent
+parameters.  For instance:
+
+@lisp
+(nnoo-declare nndir
+  nnml nnmh)
+@end lisp
+
+@code{nndir} has here declared that it intends to inherit functions from
+both @code{nnml} and @code{nnmh}.
+
+@item defvoo
+This macro is equivalent to @code{defvar}, but registers the variable as
+a public server variable.  Most state-oriented variables should be
+declared with @code{defvoo} instead of @code{defvar}.  
+
+In addition to the normal @code{defvar} parameters, it takes a list of
+variables in the parent backends to map the variable to when executing
+a function in those backends.
+
+@lisp
+(defvoo nndir-directory nil
+  "Where nndir will look for groups."
+  nnml-current-directory nnmh-current-directory)
+@end lisp
+
+This means that @code{nnml-current-directory} will be set to
+@code{nndir-directory} when an @code{nnml} function is called on behalf
+of @code{nndir}.  (The same with @code{nnmh}.)  
+
+@item nnoo-define-basics
+This macro defines some common functions that almost all backends should
+have.
+
+@example
+(nnoo-define-basics nndir)
+@end example
+
+@item deffoo
+This macro is just like @code{defun} and takes the same parameters.  In
+addition to doing the normal @code{defun} things, it registers the
+function as being public so that other backends can inherit it.
+
+@item nnoo-map-functions
+This macro allows mapping of functions from the current backend to
+functions from the parent backends.
+
+@example
+(nnoo-map-functions nndir
+  (nnml-retrieve-headers 0 nndir-current-group 0 0)
+  (nnmh-request-article 0 nndir-current-group 0 0))
+@end example
+
+This means that when @code{nndir-retrieve-headers} is called, the first,
+third, and fourth parameters will be passed on to
+@code{nnml-retrieve-headers}, while the second parameter is set to the
+value of @code{nndir-current-group}.
+
+@item nnoo-import
+This macro allows importing functions from backends.  It should be the
+last thing in the source file, since it will only define functions that
+haven't already been defined.
+
+@example
+(nnoo-import nndir
+  (nnmh
+   nnmh-request-list
+   nnmh-request-newgroups)
+  (nnml))
+@end example
+
+This means that calls to @code{nndir-request-list} should just be passed
+on to @code{nnmh-request-list}, while all public functions from
+@code{nnml} that haven't been defined in @code{nndir} yet should be
+defined now.
+
+@end table
+
+
+@node An Example Backend
+@subsubsection An Example Backend
+
+Below is a slightly shortened version of the @code{nndir} backend.
+
+@lisp
+;;; nndir.el --- single directory newsgroup access for Gnus
+;; Copyright (C) 1995,96 Free Software Foundation, Inc.
+
+;;; Code:
+
+(require 'nnheader)
+(require 'nnmh)
+(require 'nnml)
+(require 'nnoo)
+(eval-when-compile (require 'cl))
+
+(nnoo-declare nndir
+  nnml nnmh)
+
+(defvoo nndir-directory nil
+  "Where nndir will look for groups."
+  nnml-current-directory nnmh-current-directory)
+
+(defvoo nndir-nov-is-evil nil
+  "*Non-nil means that nndir will never retrieve NOV headers."
+  nnml-nov-is-evil)
+
+\f
+
+(defvoo nndir-current-group "" nil nnml-current-group nnmh-current-group)
+(defvoo nndir-top-directory nil nil nnml-directory nnmh-directory)
+(defvoo nndir-get-new-mail nil nil nnml-get-new-mail nnmh-get-new-mail)
+
+(defvoo nndir-status-string "" nil nnmh-status-string)
+(defconst nndir-version "nndir 1.0")
+
+\f
+
+;;; Interface functions.
+
+(nnoo-define-basics nndir)
+
+(deffoo nndir-open-server (server &optional defs)
+  (setq nndir-directory
+       (or (cadr (assq 'nndir-directory defs))
+           server))
+  (unless (assq 'nndir-directory defs)
+    (push `(nndir-directory ,server) defs))
+  (push `(nndir-current-group
+         ,(file-name-nondirectory (directory-file-name nndir-directory)))
+       defs)
+  (push `(nndir-top-directory
+         ,(file-name-directory (directory-file-name nndir-directory)))
+       defs)
+  (nnoo-change-server 'nndir server defs))
+
+(nnoo-map-functions nndir
+  (nnml-retrieve-headers 0 nndir-current-group 0 0)
+  (nnmh-request-article 0 nndir-current-group 0 0)
+  (nnmh-request-group nndir-current-group 0 0)
+  (nnmh-close-group nndir-current-group 0))
+
+(nnoo-import nndir
+  (nnmh
+   nnmh-status-message
+   nnmh-request-list
+   nnmh-request-newgroups))
+
+(provide 'nndir)
+@end lisp
+
+
+
 @node Score File Syntax
 @subsection Score File Syntax