*** pub/sgnus/lisp/gnus.el	Sat Apr 13 08:07:56 1996
--- sgnus/lisp/gnus.el	Sun Apr 14 06:25:49 1996
***************
*** 1695,1701 ****
    "gnus-bug@ifi.uio.no (The Gnus Bugfixing Girls + Boys)"
    "The mail address of the Gnus maintainers.")
  
! (defconst gnus-version "September Gnus v0.70"
    "Version number for this version of Gnus.")
  
  (defvar gnus-info-nodes
--- 1695,1701 ----
    "gnus-bug@ifi.uio.no (The Gnus Bugfixing Girls + Boys)"
    "The mail address of the Gnus maintainers.")
  
! (defconst gnus-version "September Gnus v0.71"
    "Version number for this version of Gnus.")
  
  (defvar gnus-info-nodes
*** pub/sgnus/lisp/nndir.el	Sat Apr 13 08:07:58 1996
--- sgnus/lisp/nndir.el	Sun Apr 14 06:25:49 1996
***************
*** 94,100 ****
  
  (nnoo-import nndir
    (nnmh
-    nnmh-status-message
     nnmh-request-list
     nnmh-request-newgroups))
  
--- 94,99 ----
*** pub/sgnus/lisp/nnoo.el	Sat Apr 13 08:07:59 1996
--- sgnus/lisp/nnoo.el	Sun Apr 14 07:06:53 1996
***************
*** 161,186 ****
  	 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 (cdr bstate)))
  		      (nnoo-variables backend)))
        (while state
  	(set (caar state) (cdar state))
  	(pop state))
        (setcar bstate server)
!       (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)))))
  
  (defun nnoo-push-server (backend current)
    (let ((bstate (assq backend nnoo-state-alist))
--- 161,188 ----
  	 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))
*** pub/sgnus/lisp/nnvirtual.el	Sat Apr 13 08:07:59 1996
--- sgnus/lisp/nnvirtual.el	Sun Apr 14 08:32:06 1996
***************
*** 50,59 ****
  
  
  
! (defconst nnvirtual-version "nnvirtual 1.0"
!   "Version number of this version of nnvirtual.")
  
- (defvoo nnvirtual-group-alist nil)
  (defvoo nnvirtual-current-group nil)
  (defvoo nnvirtual-component-groups nil)
  (defvoo nnvirtual-mapping nil)
--- 50,57 ----
  
  
  
! (defconst nnvirtual-version "nnvirtual 1.0")
  
  (defvoo nnvirtual-current-group nil)
  (defvoo nnvirtual-component-groups nil)
  (defvoo nnvirtual-mapping nil)
***************
*** 69,77 ****
  
  (nnoo-define-basics nnvirtual)
  
! (deffoo nnvirtual-retrieve-headers (articles &optional newsgroup server fetch-old)
!   (when (nnvirtual-possibly-change-group newsgroup server)
      (save-excursion
        (if (stringp (car articles))
  	  'headers
  	(let ((vbuf (nnheader-set-temp-buffer 
--- 67,78 ----
  
  (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 
***************
*** 161,167 ****
  	    (kill-buffer vbuf)))))))
  
  (deffoo nnvirtual-request-article (article &optional group server buffer)
!   (when (and (nnvirtual-possibly-change-group group server)
  	     (numberp article))
      (let* ((amap (assq article nnvirtual-mapping))
  	   (cgroup (cadr amap)))
--- 162,168 ----
  	    (kill-buffer vbuf)))))))
  
  (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)))
***************
*** 184,228 ****
    (unless (assq 'nnvirtual-component-regexp defs)
      (push `(nnvirtual-component-regexp ,server)
  	  defs))
!   (nnoo-change-server 'nnvirtual server defs))
  
  (deffoo nnvirtual-request-group (group &optional server dont-check)
    (cond
!    ((null (nnvirtual-possibly-change-group
! 	   group server 
! 	   (if nnvirtual-always-rescan nil (not dont-check))))
      (setq nnvirtual-current-group nil)
      (nnheader-report 'nnvirtual "No component groups in %s" group))
     (t
      (let ((len (length nnvirtual-mapping)))
        (nnheader-insert "211 %d 1 %d %s\n" len len group)))))
  
  (deffoo 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)))))))
  
  (deffoo 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))))
    mark)
      
  (deffoo nnvirtual-close-group (group &optional server)
!   (when (nnvirtual-possibly-change-group group 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))
--- 185,241 ----
    (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-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)))))
  
  (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)
      
  (deffoo nnvirtual-close-group (group &optional server)
!   (when (nnvirtual-possibly-change-server server)
      ;; Copy (un)read articles.
      (nnvirtual-update-reads)
      ;; We copy the marks from this group to the component
      ;; groups here.
      (nnvirtual-update-marked))
***************
*** 238,244 ****
    (nnheader-report 'nnvirtual "LIST NEWSGROUPS is not implemented."))
  
  (deffoo nnvirtual-request-update-info (group info &optional server)
!   (when (nnvirtual-possibly-change-group group server)
      (let ((map nnvirtual-mapping)
  	  (marks (mapcar (lambda (m) (list (cdr m))) gnus-article-mark-lists))
  	  reads mr m op)
--- 251,257 ----
    (nnheader-report 'nnvirtual "LIST NEWSGROUPS is not implemented."))
  
  (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)
***************
*** 274,280 ****
        t)))
  
  (deffoo nnvirtual-catchup-group (group &optional server all)
!   (nnvirtual-possibly-change-group group server)
    (let ((gnus-group-marked nnvirtual-component-groups)
  	(gnus-expert-user t))
      ;; Make sure all groups are activated.
--- 287,293 ----
        t)))
  
  (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.
***************
*** 289,295 ****
  
  (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)))))
--- 302,307 ----
***************
*** 318,379 ****
  		    (concat "Xref: " (mail-header-xref header) "\t")
  		  "") "\n")))))
  
! (defun nnvirtual-possibly-change-group (group server &optional check)
!   (let ((inf t))
!     (when (or (not (equal group nnvirtual-current-group))
! 	      (not (nnoo-current-server-p 'nnvirtual server))
! 	      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) nnvirtual-component-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 nnvirtual-component-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-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))))
  	type list mart cgroups)
      (while (setq type (cdr (pop mark-lists)))
        (setq list (gnus-uncompress-range (cdr (assq type marks))))
--- 330,344 ----
  		    (concat "Xref: " (mail-header-xref header) "\t")
  		  "") "\n")))))
  
! (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 (nnvirtual-current-group))))
  	type list mart cgroups)
      (while (setq type (cdr (pop mark-lists)))
        (setq list (gnus-uncompress-range (cdr (assq type marks))))
***************
*** 392,398 ****
    "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)))
  	m)
      (while articles
        (setq m (assq (pop articles) nnvirtual-mapping))
--- 357,363 ----
    "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
! 		   (nnvirtual-current-group)))
  	m)
      (while articles
        (setq m (assq (pop articles) nnvirtual-mapping))
***************
*** 400,405 ****
--- 365,374 ----
      (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)
***************
*** 434,440 ****
  				     g n (and (memq n unreads) t)
  				     (inline (nnvirtual-marks n marks))))
  			     (gnus-uncompress-range active))))
! 		 nnvirtual-component-groups))
  	       (lambda (m1 m2)
  		 (< (car m1) (car m2)))))
      (i 0))
--- 403,411 ----
  				     g n (and (memq n unreads) t)
  				     (inline (nnvirtual-marks n marks))))
  			     (gnus-uncompress-range active))))
! 		 (setq nnvirtual-component-groups
! 		       (delete (nnvirtual-current-group)
! 			       nnvirtual-component-groups))))
  	       (lambda (m1 m2)
  		 (< (car m1) (car m2)))))
      (i 0))
*** pub/sgnus/lisp/ChangeLog	Sat Apr 13 08:08:06 1996
--- sgnus/lisp/ChangeLog	Sun Apr 14 08:32:08 1996
***************
*** 1,4 ****
--- 1,10 ----
+ Sun Apr 14 06:27:19 1996  Lars Magne Ingebrigtsen  <larsi@aegir.ifi.uio.no>
+ 
+ 	* 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.
  
*** pub/sgnus/texi/gnus.texi	Sat Apr 13 08:08:08 1996
--- sgnus/texi/gnus.texi	Sun Apr 14 06:25:53 1996
***************
*** 12708,12713 ****
--- 12708,12714 ----
  @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
  
  
***************
*** 12797,12803 ****
  @item (nnchoke-close-server &optional SERVER)
  
  Close connection to @var{server} and free all resources connected
! to it. 
  
  There should be no data returned.
  
--- 12798,12805 ----
  @item (nnchoke-close-server &optional SERVER)
  
  Close connection to @var{server} and free all resources connected
! to it.  Return @code{nil} if the server couldn't be closed for some
! reason.
  
  There should be no data returned.
  
***************
*** 12806,12822 ****
  
  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.)
  
  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. 
  
  There should be no data returned.
  
--- 12808,12825 ----
  
  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.)  This
! function is generally only called when Gnus is shutting down.
  
  There should be no data returned. 
  
  
  @item (nnchoke-server-opened &optional SERVER)
  
! 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.
  
***************
*** 12841,12846 ****
--- 12844,12856 ----
  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)
  
***************
*** 12922,12942 ****
  
  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
  
  
--- 12932,12937 ----
***************
*** 13096,13101 ****
--- 13091,13099 ----
  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. 
  
  
***************
*** 13105,13110 ****
--- 13103,13111 ----
  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.
  
  
***************
*** 13133,13138 ****
--- 13134,13326 ----
  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)
+ 
+ 
+ 
+ (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")
+ 
+ 
+ 
+ ;;; 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
*** pub/sgnus/texi/ChangeLog	Sat Apr 13 08:08:07 1996
--- sgnus/texi/ChangeLog	Sun Apr 14 06:25:50 1996
***************
*** 1,3 ****
--- 1,10 ----
+ 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.
