;;; nnspool.el --- spool access for GNU Emacs
-;; Copyright (C) 1988,89,90,93,94,95,96 Free Software Foundation, Inc.
+;; Copyright (C) 198,998,89,90,93,94,95,96,97,98 Free Software Foundation, Inc.
;; Author: Masanobu UMEDA <umerin@flab.flab.fujitsu.junet>
-;; Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
+;; Lars Magne Ingebrigtsen <larsi@gnus.org>
;; Keywords: news
;; This file is part of GNU Emacs.
(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" "-S")
"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 "distribs.pat")
"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
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.")
+(defvoo nnspool-file-coding-system nnheader-file-coding-system
+ "Coding system for nnspool.")
+
\f
(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)
(default-directory nnspool-current-directory)
(do-message (and (numberp nnspool-large-newsgroup)
(> number nnspool-large-newsgroup)))
+ (nnheader-file-coding-system nnspool-file-coding-system)
file beg article ag)
(if (and (numberp (car articles))
(nnspool-retrieve-headers-with-nov articles fetch-old))
(if (stringp article)
;; This is a Message-ID.
(setq ag (nnspool-find-id article)
- file (and ag (nnspool-article-pathname
+ file (and ag (nnspool-article-pathname
(car ag) (cdr ag)))
article (cdr ag))
;; This is an article in the current group.
(setq beg (point))
(inline (nnheader-insert-head file))
(goto-char beg)
- (search-forward "\n\n" nil t)
- (forward-char -1)
- (insert ".\n")
+ (if (search-forward "\n\n" nil t)
+ (progn
+ (forward-char -1)
+ (insert ".\n"))
+ (goto-char (point-max))
+ (if (bolp)
+ (insert ".\n")
+ (insert "\n.\n")))
(delete-region (point) (point-max)))
-
+
(and do-message
(zerop (% (incf count) 20))
- (message "nnspool: Receiving headers... %d%%"
- (/ (* count 100) number))))
-
- (and do-message
- (message "nnspool: Receiving headers...done"))
-
+ (nnheader-message 5 "nnspool: Receiving headers... %d%%"
+ (/ (* count 100) number))))
+
+ (when do-message
+ (nnheader-message 5 "nnspool: Receiving headers...done"))
+
;; Fold continuation lines.
(nnheader-fold-continuation-lines)
'headers)))))
-(defun nnspool-open-server (server &optional defs)
- (nnheader-change-server 'nnspool server defs)
- (cond
+(deffoo nnspool-open-server (server &optional defs)
+ (nnoo-change-server 'nnspool server defs)
+ (cond
((not (file-exists-p nnspool-spool-directory))
(nnspool-close-server)
(nnheader-report 'nnspool "Spool directory doesn't exist: %s"
nnspool-spool-directory))
- ((not (file-directory-p (file-truename nnspool-spool-directory)))
+ ((not (file-directory-p
+ (directory-file-name
+ (file-truename nnspool-spool-directory))))
(nnspool-close-server)
(nnheader-report 'nnspool "Not a directory: %s" nnspool-spool-directory))
+ ((not (file-exists-p nnspool-active-file))
+ (nnheader-report 'nnspool "The active file doesn't exist: %s"
+ nnspool-active-file))
(t
(nnheader-report 'nnspool "Opened server %s using directory %s"
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))
file ag)
(if (stringp id)
- ;; This is a Message-ID.
+ ;; This is a Message-ID.
(when (setq ag (nnspool-find-id id))
(setq file (nnspool-article-pathname (car ag) (cdr ag))))
(setq file (nnspool-article-pathname nnspool-current-group id)))
(if (numberp id)
(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)))
(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)))
(set-buffer nntp-server-buffer)
(goto-char (point-min))
(when (search-forward "\n\n" nil t)
- (delete-region (1- (point)) (point-max)))))
+ (delete-region (1- (point)) (point-max)))
+ (nnheader-fold-continuation-lines)))
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)
(if (not (file-directory-p pathname))
- (nnheader-report
+ (nnheader-report
'nnspool "Invalid group name (no such directory): %s" group)
(setq nnspool-current-directory pathname)
(nnheader-report 'nnspool "Selected group %s" group)
;; Yes, completely empty spool directories *are* possible.
;; Fix by Sudish Joseph <joseph@cis.ohio-state.edu>
(when (setq dir (directory-files pathname nil "^[0-9]+$" t))
- (setq dir
+ (setq dir
(sort (mapcar (lambda (name) (string-to-int name)) dir) '<)))
(if dir
(nnheader-insert
(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)))
+ (or (nnspool-find-file nnspool-active-file)
+ (nnheader-report 'nnspool (nnheader-file-error nnspool-active-file)))))
-(defun nnspool-request-list-newsgroups (&optional server)
+(deffoo nnspool-request-list-newsgroups (&optional server)
"List newsgroups (defined in NNTP2)."
&nbs