*** 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 + + * nnvirtual.el (nnvirtual-open-server): Would return nil. + Sat Apr 13 05:37:10 1996 Lars Magne Ingebrigtsen + + * 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 + + * 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 * gnus.texi (Message): New chapter.