-;;; gnus-agent.el --- unplugged support for Gnus
-;; Copyright (C) 1997, 1998, 1999, 2000 Free Software Foundation, Inc.
+;;; gnus-agent.el --- unplugged support for Semi-gnus
+;; Copyright (C) 1997, 1998, 1999, 2000, 2001
+;; Free Software Foundation, Inc.
;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
+;; Tatsuya Ichikawa <t-ichi@po.shiojiri.ne.jp>
;; This file is part of GNU Emacs.
;; GNU Emacs is free software; you can redistribute it and/or modify
;;; Code:
+(eval-when-compile (require 'cl))
+(eval-when-compile (require 'gnus-clfns))
+
(require 'gnus)
(require 'gnus-cache)
(require 'nnvirtual)
(if (featurep 'xemacs)
(require 'itimer)
(require 'timer))
- (require 'cl))
+ (require 'gnus-group))
+
+(eval-and-compile
+ (autoload 'gnus-server-update-server "gnus-srvr"))
(defcustom gnus-agent-directory (nnheader-concat gnus-directory "agent/")
"Where the Gnus agent will store its files."
:group 'gnus-agent
:type 'hook)
+;; Extracted from gnus-xmas-redefine in order to preserve user settings
+(when (featurep 'xemacs)
+ (add-hook 'gnus-agent-group-mode-hook 'gnus-xmas-agent-group-menu-add))
+
(defcustom gnus-agent-summary-mode-hook nil
"Hook run in Agent summary minor modes."
:group 'gnus-agent
:type 'hook)
+;; Extracted from gnus-xmas-redefine in order to preserve user settings
+(when (featurep 'xemacs)
+ (add-hook 'gnus-agent-summary-mode-hook 'gnus-xmas-agent-summary-menu-add))
+
(defcustom gnus-agent-server-mode-hook nil
"Hook run in Agent summary minor modes."
:group 'gnus-agent
:type 'hook)
+;; Extracted from gnus-xmas-redefine in order to preserve user settings
+(when (featurep 'xemacs)
+ (add-hook 'gnus-agent-server-mode-hook 'gnus-xmas-agent-server-menu-add))
+
(defcustom gnus-agent-confirmation-function 'y-or-n-p
"Function to confirm when error happens."
+ :version "21.1"
:group 'gnus-agent
:type 'function)
+(defcustom gnus-agent-large-newsgroup nil
+ "*The number of articles which indicates a large newsgroup.
+If the number of unread articles exceeds it, The number of articles to be
+fetched will be limited to it. If not a positive integer, never consider it."
+ :group 'gnus-agent
+ :type '(choice (const nil)
+ (integer :tag "Number")))
+
(defcustom gnus-agent-synchronize-flags 'ask
"Indicate if flags are synchronized when you plug in.
If this is `ask' the hook will query the user."
+ :version "21.1"
:type '(choice (const :tag "Always" t)
(const :tag "Never" nil)
(const :tag "Ask" ask))
(setq gnus-agent-overview-buffer
(gnus-get-buffer-create " *Gnus agent overview*"))
(with-current-buffer gnus-agent-overview-buffer
- (mm-enable-multibyte))
+ (set-buffer-multibyte t))
nil))
(gnus-add-shutdown 'gnus-close-agent 'gnus)
(setq gnus-plugged plugged)
(gnus-run-hooks 'gnus-agent-unplugged-hook)
(setcar (cdr gnus-agent-mode-status) " Unplugged"))
- (set-buffer-modified-p t))
+ (force-mode-line-update))
(defun gnus-agent-close-connections ()
"Close all methods covered by the Gnus agent."
\(gnus-agentize)
-This will modify the `gnus-before-startup-hook', `gnus-post-method',
-and `message-send-mail-function' variables, and install the Gnus
-agent minor mode in all Gnus buffers."
+This will modify the `gnus-setup-news-hook', and
+`message-send-mail-real-function' variables, and install the Gnus agent
+minor mode in all Gnus buffers."
(interactive)
(gnus-open-agent)
(add-hook 'gnus-setup-news-hook 'gnus-agent-queue-setup)
(unless gnus-agent-send-mail-function
- (setq gnus-agent-send-mail-function message-send-mail-function
- message-send-mail-function 'gnus-agent-send-mail))
+ (setq gnus-agent-send-mail-function (or
+ message-send-mail-real-function
+ message-send-mail-function)
+ message-send-mail-real-function 'gnus-agent-send-mail))
(unless gnus-agent-covered-methods
(setq gnus-agent-covered-methods (list gnus-select-method))))
(save-restriction
(message-narrow-to-headers)
(let* ((gcc (mail-fetch-field "gcc" nil t))
- (methods (and gcc
+ (methods (and gcc
(mapcar 'gnus-inews-group-method
(message-unquote-tokens
- (message-tokenize-header
+ (message-tokenize-header
gcc " ,")))))
covered)
(while (and (not covered) methods)
(when (or (and gnus-agent-synchronize-flags
(not (eq gnus-agent-synchronize-flags 'ask)))
(and (eq gnus-agent-synchronize-flags 'ask)
- (gnus-y-or-n-p (format "Synchronize flags on server `%s'? "
+ (gnus-y-or-n-p (format "Synchronize flags on server `%s'? "
(cadr method)))))
(gnus-agent-synchronize-flags-server method)))
(when (member method gnus-agent-covered-methods)
(error "Server already in the agent program"))
(push method gnus-agent-covered-methods)
+ (gnus-server-update-server server)
(gnus-agent-write-servers)
(message "Entered %s into the Agent" server)))
(error "Server not in the agent program"))
(setq gnus-agent-covered-methods
(delete method gnus-agent-covered-methods))
+ (gnus-server-update-server server)
(gnus-agent-write-servers)
(message "Removed %s from the agent" server)))
"Write the alist of covered servers."
(gnus-make-directory (nnheader-concat gnus-agent-directory "lib"))
(let ((coding-system-for-write nnheader-file-coding-system)
- (file-name-coding-system nnmail-pathname-coding-system))
+ (output-coding-system nnheader-file-coding-system)
+ (file-name-coding-system nnmail-pathname-coding-system)
+ (pathname-coding-system nnmail-pathname-coding-system))
(with-temp-file (nnheader-concat gnus-agent-directory "lib/servers")
(prin1 gnus-agent-covered-methods (current-buffer)))))
(gnus-agent-method-p gnus-command-method))
(gnus-agent-load-alist gnus-newsgroup-name)
;; First mark all undownloaded articles as undownloaded.
- (let ((articles (append gnus-newsgroup-unreads
- gnus-newsgroup-marked
- gnus-newsgroup-dormant))
- article)
- (while (setq article (pop articles))
- (unless (or (cdr (assq article gnus-agent-article-alist))
- (memq article gnus-newsgroup-downloadable)
- (memq article gnus-newsgroup-cached))
- (push article gnus-newsgroup-undownloaded))))
+ (dolist (article (mapcar (lambda (header) (mail-header-number header))
+ gnus-newsgroup-headers))
+ (unless (or (cdr (assq article gnus-agent-article-alist))
+ (memq article gnus-newsgroup-downloadable)
+ (memq article gnus-newsgroup-cached))
+ (push article gnus-newsgroup-undownloaded)))
;; Then mark downloaded downloadable as not-downloadable,
;; if you get my drift.
- (let ((articles gnus-newsgroup-downloadable)
- article)
- (while (setq article (pop articles))
- (when (cdr (assq article gnus-agent-article-alist))
- (setq gnus-newsgroup-downloadable
- (delq article gnus-newsgroup-downloadable))))))))
+ (dolist (article gnus-newsgroup-downloadable)
+ (when (cdr (assq article gnus-agent-article-alist))
+ (setq gnus-newsgroup-downloadable
+ (delq article gnus-newsgroup-downloadable)))))))
(defun gnus-agent-catchup ()
"Mark all undownloaded articles as read."
(funcall function nil new)
(gnus-agent-write-active file new)
(erase-buffer)
- (nnheader-insert-file-contents file))))
+ (insert-file-contents-as-coding-system gnus-agent-file-coding-system
+ file))))
(defun gnus-agent-write-active (file new)
(let ((orig (gnus-make-hashtable (count-lines (point-min) (point-max))))
elem osym)
(when (file-exists-p file)
(with-temp-buffer
- (nnheader-insert-file-contents file)
+ (insert-file-contents-as-coding-system gnus-agent-file-coding-system
+ file)
(gnus-active-to-gnus-format nil orig))
(mapatoms
(lambda (sym)
(set (intern (symbol-name sym) orig) (symbol-value sym)))))
new))
(gnus-make-directory (file-name-directory file))
- (let ((coding-system-for-write gnus-agent-file-coding-system))
- ;; The hashtable contains real names of groups, no more prefix
- ;; removing, so set `full' to `t'.
- (gnus-write-active-file file orig t))))
+ ;; The hashtable contains real names of groups, no more prefix
+ ;; removing, so set `full' to `t'.
+ (gnus-write-active-file file orig t)))
(defun gnus-agent-save-groups (method)
(gnus-agent-save-active-1 method 'gnus-groups-to-gnus-format))
(when (gnus-agent-method-p method)
(let* ((gnus-command-method method)
(coding-system-for-write nnheader-file-coding-system)
+ (output-coding-system nnheader-file-coding-system)
(file-name-coding-system nnmail-pathname-coding-system)
+ (pathname-coding-system nnmail-pathname-coding-system)
(file (gnus-agent-lib-file "active"))
oactive)
(gnus-make-directory (file-name-directory file))
(with-temp-file file
- ;; Emacs got problem to match non-ASCII group in multibyte buffer.
- (mm-disable-multibyte)
(when (file-exists-p file)
(nnheader-insert-file-contents file))
(goto-char (point-min))
(nnheader-translate-file-chars
(nnheader-replace-chars-in-string
(nnheader-replace-duplicate-chars-in-string
- (nnheader-replace-chars-in-string
+ (nnheader-replace-chars-in-string
(gnus-group-real-name group)
?/ ?_)
?. ?_)
(format " *Gnus agent %s history*"
(gnus-agent-method)))))
gnus-agent-history-buffers)
- (mm-disable-multibyte) ;; everything is binary
(erase-buffer)
(insert "\n")
(let ((file (gnus-agent-lib-file "history")))
(save-excursion
(set-buffer gnus-agent-current-history)
(gnus-make-directory (file-name-directory gnus-agent-file-name))
- (let ((coding-system-for-write gnus-agent-file-coding-system))
- (write-region (1+ (point-min)) (point-max)
- gnus-agent-file-name nil 'silent))))
+ (write-region-as-coding-system
+ gnus-agent-file-coding-system
+ (1+ (point-min)) (point-max) gnus-agent-file-name nil 'silent)))
(defun gnus-agent-close-history ()
(when (gnus-buffer-live-p gnus-agent-current-history)
(with-temp-buffer
(let (article)
(while (setq article (pop articles))
- (when (or
- (gnus-backlog-request-article group article
+ (when (or
+ (gnus-backlog-request-article group article
nntp-server-buffer)
(gnus-request-article article group))
(goto-char (point-max))
(if (not (re-search-forward "^Message-ID: *<\\([^>\n]+\\)>" nil t))
(setq id "No-Message-ID-in-article")
(setq id (buffer-substring (match-beginning 1) (match-end 1))))
- (let ((coding-system-for-write
- gnus-agent-file-coding-system))
- (write-region (point-min) (point-max)
- (concat dir (number-to-string (caar pos)))
- nil 'silent))
+ (write-region-as-coding-system
+ gnus-agent-file-coding-system
+ (point-min) (point-max)
+ (concat dir (number-to-string (caar pos))) nil 'silent)
(when (setq elem (assq (caar pos) gnus-agent-article-alist))
(setcdr elem t))
(gnus-agent-enter-history
(save-excursion
(while gnus-agent-buffer-alist
(set-buffer (cdar gnus-agent-buffer-alist))
- (let ((coding-system-for-write
- gnus-agent-file-coding-system))
- (write-region (point-min) (point-max)
- (gnus-agent-article-name ".overview"
- (caar gnus-agent-buffer-alist))
- nil 'silent))
+ (write-region-as-coding-system
+ gnus-agent-file-coding-system
+ (point-min) (point-max)
+ (gnus-agent-article-name ".overview"
+ (caar gnus-agent-buffer-alist))
+ nil 'silent)
(pop gnus-agent-buffer-alist))
(while gnus-agent-group-alist
(with-temp-file (caar gnus-agent-group-alist)
(pop gnus-agent-group-alist))))
(defun gnus-agent-fetch-headers (group &optional force)
- (let ((articles (gnus-list-of-unread-articles group))
- (gnus-decode-encoded-word-function 'identity)
- (file (gnus-agent-article-name ".overview" group)))
- ;; Add article with marks to list of article headers we want to fetch.
+ (let* ((articles (gnus-list-of-unread-articles group))
+ (len (length articles))
+ (gnus-decode-encoded-word-function 'identity)
+ (file (gnus-agent-article-name ".overview" group))
+ i)
+ ;; Check the number of articles is not too large.
+ (when (and (integerp gnus-agent-large-newsgroup)
+ (< 0 gnus-agent-large-newsgroup))
+ (and (< 0 (setq i (- len gnus-agent-large-newsgroup)))
+ (setq articles (nthcdr i articles))))
+ ;; add article with marks to list of article headers we want to fetch.
(dolist (arts (gnus-info-marks (gnus-get-info group)))
(setq articles (gnus-union (gnus-uncompress-sequence (cdr arts))
- articles)))
+ articles)))
(setq articles (sort articles '<))
;; Remove known articles.
(when (gnus-agent-load-alist group)
(when articles
(gnus-message 7 "Fetching headers for %s..." group)
(save-excursion
- (set-buffer nntp-server-buffer)
- (unless (eq 'nov (gnus-retrieve-headers articles group))
- (nnvirtual-convert-headers))
- ;; Save these headers for later processing.
- (copy-to-buffer gnus-agent-overview-buffer (point-min) (point-max))
+ (set-buffer nntp-server-buffer)
+ (unless (eq 'nov (gnus-retrieve-headers articles group))
+ (nnvirtual-convert-headers))
+ ;; Save these headers for later processing.
+ (copy-to-buffer gnus-agent-overview-buffer (point-min) (point-max))
(when (file-exists-p file)
(gnus-agent-braid-nov group articles file))
- (let ((coding-system-for-write
- gnus-agent-file-coding-system))
- (write-region (point-min) (point-max) file nil 'silent))
+ (write-region-as-coding-system
+ gnus-agent-file-coding-system
+ (point-min) (point-max) file nil 'silent)
(gnus-agent-save-alist group articles nil)
(gnus-agent-enter-history
"last-header-fetched-for-session"
(defun gnus-agent-save-alist (group &optional articles state dir)
"Save the article-state alist for GROUP."
- (let ((file-name-coding-system nnmail-pathname-coding-system))
- (with-temp-file (if dir
- (expand-file-name ".agentview" dir)
- (gnus-agent-article-name ".agentview" group))
- (princ (setq gnus-agent-article-alist
- (nconc gnus-agent-article-alist
- (mapcar (lambda (article) (cons article state))
- articles)))
- (current-buffer))
- (insert "\n"))))
+ (let ((file-name-coding-system nnmail-pathname-coding-system)
+ (pathname-coding-system nnmail-pathname-coding-system)
+ print-level print-length)
+ (with-temp-file (if dir
+ (expand-file-name ".agentview" dir)
+ (gnus-agent-article-name ".agentview" group))
+ (princ (setq gnus-agent-article-alist
+ (nconc gnus-agent-article-alist
+ (mapcar (lambda (article) (cons article state))
+ articles)))
+ (current-buffer))
+ (insert "\n"))))
(defun gnus-agent-article-name (article group)
(expand-file-name (if (stringp article) article (string-to-number article))
(expand-file-name (gnus-agent-group-path group)
(gnus-agent-directory)))))
-(defun gnus-agent-batch-confirmation (msg)
- "Show error message and return t."
- (gnus-message 1 msg)
- t)
-
;;;###autoload
(defun gnus-agent-batch-fetch ()
"Start Gnus and fetch session."
(while (setq group (pop groups))
(when (<= (gnus-group-level group) gnus-agent-handle-level)
(gnus-agent-fetch-group-1 group gnus-command-method))))))
- (error
+ (error
(unless (funcall gnus-agent-confirmation-function
(format "Error (%s). Continue? " err))
- (error "Cannot fetch articles into the Gnus agent.")))
- (quit
+ (error "Cannot fetch articles into the Gnus agent")))
+ (quit
(unless (funcall gnus-agent-confirmation-function
- (format "Quit (%s). Continue? " err))
- (signal 'quit "Cannot fetch articles into the Gnus agent."))))
+ (format "Quit fetching session (%s). Continue? "
+ err))
+ (signal 'quit "Cannot fetch articles into the Gnus agent"))))
(pop methods))
(gnus-message 6 "Finished fetching articles into the Gnus agent"))))
(setq gnus-newsgroup-dependencies
(make-vector (length articles) 0))
(setq gnus-newsgroup-headers
- (gnus-get-newsgroup-headers-xover articles nil nil
+ (gnus-get-newsgroup-headers-xover articles nil nil
group))
;; `gnus-agent-overview-buffer' may be killed for
;; timeout reason. If so, recreate it.
(caddr info)
(format "Editing the score expression for category %s" category)
`(lambda (groups)
- (setcar (cddr (assq ',category gnus-category-alist)) groups)
+ (setcar (nthcdr 2 (assq ',category gnus-category-alist)) groups)
(gnus-category-write)
(gnus-category-list)))))
(while (setq gnus-command-method (pop methods))
(when (file-exists-p (gnus-agent-lib-file "active"))
(with-temp-buffer
- (nnheader-insert-file-contents (gnus-agent-lib-file "active"))
- (gnus-active-to-gnus-format
+ (insert-file-contents-as-coding-system
+ gnus-agent-file-coding-system (gnus-agent-lib-file "active"))
+ (gnus-active-to-gnus-format
gnus-command-method
(setq orig (gnus-make-hashtable
(count-lines (point-min) (point-max))))))
(if (numberp fetch-date)
(> fetch-date day)
;; History file is corrupted.
- (gnus-message
- 5
+ (gnus-message
+ 5
(format "File %s is corrupted!"
(gnus-agent-lib-file "history")))
(sit-for 1)
(gnus-uncompress-range
(cdr (assq 'tick (gnus-info-marks info))))
(gnus-uncompress-range
- (cdr (assq 'dormant
- (gnus-info-marks info)))))
+ (cdr (assq 'dormant (gnus-info-marks info))))
+ (gnus-uncompress-range
+ (cdr (assq 'save (gnus-info-marks info))))
+ (gnus-uncompress-range
+ (cdr (assq 'reply (gnus-info-marks info)))))
nov-file (gnus-agent-article-name ".overview" group)
lowest nil
highest nil)
(or (not (numberp
(setq art (read (current-buffer)))))
(< art article)))
- (if (and (numberp art)
+ (if (and (numberp art)
(file-exists-p
(gnus-agent-article-name
(number-to-string art) group)))
;; Schedule the history line for nuking.
(push (cdr elem) histories)))
(gnus-make-directory (file-name-directory nov-file))
- (let ((coding-system-for-write
- gnus-agent-file-coding-system))
- (write-region (point-min) (point-max) nov-file nil 'silent))
+ (write-region-as-coding-system
+ gnus-agent-file-coding-system
+ (point-min) (point-max) nov-file nil 'silent)
;; Delete the unwanted entries in the alist.
(setq gnus-agent-article-alist
(sort gnus-agent-article-alist 'car-less-than-car))
(gnus-delete-line))
(gnus-agent-save-history)
(gnus-agent-close-history)
- (gnus-write-active-file
- (gnus-agent-lib-file "active") orig))
+ (gnus-write-active-file (gnus-agent-lib-file "active") orig))
(gnus-message 4 "Expiry...done")))))))
;;;###autoload