117c5363ea92583780b7829ef43009f993540499
[elisp/gnus.git-] / lisp / gnus-offline.el
1 ;;; gnus-offline.el --- To process mail & news at offline environment.
2 ;;; $Id: gnus-offline.el,v 1.1.2.5.2.36.4.8 1999-10-24 10:26:31 czkmt Exp $
3
4 ;;; Copyright (C) 1998 Tatsuya Ichikawa
5 ;;;                    Yukihiro Ito
6 ;;; Author: Tatsuya Ichikawa <t-ichi@po.shiojiri.ne.jp>
7 ;;;         Yukihiro Ito <ito@rs.civil.tohoku.ac.jp>
8 ;;;         Hidekazu Nakamura <u90121@uis-inf.co.jp>
9 ;;;         Tsukamoto Tetsuo <czkmt@remus.dti.ne.jp>
10
11 ;;; Version: 2.20
12 ;;; Keywords: news , mail , offline , gnus
13 ;;;
14 ;;; SPECIAL THANKS
15 ;;;    Keiichi Suzuki <kei-suzu@mail.wbs.or.jp>
16 ;;;    KORIYAMA Naohiro <kory@ba2.so-net.or.jp>
17 ;;;    Katsumi Yamaoka <yamaoka@jpl.org>
18
19 ;;; This file is part of Semi-gnus.
20 ;;;
21 ;;; GNU Emacs is free software; you can redistribute it and/or modify
22 ;;; it under the terms of the GNU General Public License as published by
23 ;;; the Free Software Foundation; either version 2, or (at your option)
24 ;;; any later version.
25
26 ;;; GNU Emacs is distributed in the hope that it will be useful,
27 ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
28 ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
29 ;;; GNU General Public License for more details.
30
31 ;;; You should have received a copy of the GNU General Public License
32 ;;; along with GNU Emacs; see the file COPYING.  If not, write to the
33 ;;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
34 ;;; Boston, MA 02111-1307, USA.
35 ;;;
36 ;;;; Commentary:
37 ;;; Note.
38 ;;;   This file works only with after version of Emacs 19.30.
39 ;;;   This file needs miee.el and SEMI.
40 ;;;   If you set gnus-offline-drafts-queue-type to 'agent , you don't need 
41 ;;;   miee.el
42 ;;;   You must use T-gnus 6.12.0 or later.
43 ;;;
44 ;;; How to use.
45 ;;;
46 ;;; Add following code at the end in your .emacs
47 ;;;
48 ;;;    (load "gnus-ofsetup")
49 ;;;    (gnus-setup-for-offline)
50 ;;;
51 ;;; If you use gnus-agent as souper , put gnus-agent setup code in you .gnus.el
52 ;;;
53 ;;; If you use nnspool as souper , put following code in your .emacs before
54 ;;; gnus-offline setting.
55 ;;;
56 ;;; Then , put hang.exe in exec-path directory.
57 ;;;
58 ;;; In Gnus group buffer , type g to get all news and mail.
59 ;;; Then send mail and news in spool directory.
60 ;;;
61 ;;; Variables.
62 ;;;  gnus-offline-dialup-program-arguments
63 ;;;                                   ... List of dialup program arguments.
64 ;;;  gnus-offline-hangup-program-arguments
65 ;;;                                   ... List of hangup program arguments.
66 ;;;  gnus-offline-mail-treat-environ  ... toggle sending mail online/offline.
67 ;;;  gnus-offline-articles-to-fetch   ... toggle fetch articles.
68 ;;;                                        both->mail->news->both...
69 ;;;  gnus-offline-load-hook           ... hook before gnus-offline load.
70 ;;;  gnus-offline-before-online-hook  ... hook before all online jobs.
71 ;;;  gnus-offline-after-online-hook   ... hook after all online jobs.
72 ;;;  gnus-offline-interval-time       ... Interval time to do all online jobs.
73 ;;;                                        (minutes)
74 ;;;  gnus-offline-dialup-function     ... Function to diualup.
75 ;;;  gnus-offline-hangup-function     ... Function to hangup.
76
77 ;;; Code:
78
79 (eval '(run-hooks 'gnus-offline-load-hook))
80
81 (require 'cl)
82 (require 'custom)
83 (require 'easymenu)
84 (provide 'gnus-offline)
85
86 (eval-after-load "eword-decode"
87   '(mime-set-field-decoder 'X-Gnus-Offline-Backend nil nil))
88
89 (defgroup gnus-offline nil
90   "Offline backend utility for Gnus."
91   :prefix "gnus-offline-"
92   :group 'gnus
93   :group 'mail
94   :group 'news)
95
96 (defconst gnus-offline-version-number "2.20")
97 (defconst gnus-offline-codename
98 ;;  "Beta5"                     ; Beta
99 ;;  "This is the time"          ; 2.00
100 ;;  "A matter of trust"
101 ;;  "Modern Woman"
102 ;;  "Ahhhhhhh!!"                ; 2.10b1
103   "Cup of life"                 ; 2.20
104 ;;  "Code of silence"
105   )
106
107 (defconst gnus-offline-version (format "Gnus offline backend utiliy v%s"
108                                        gnus-offline-version-number))
109
110 (eval-when-compile
111   (mapc
112    (lambda (symbol)
113      (unless (boundp symbol)
114        (make-local-variable symbol)
115        (eval (list 'setq symbol nil))))
116    '(nnagent-version
117      nnspool-version
118      msspool-news-server
119      msspool-news-service
120      miee-popup-menu
121      gnus-group-toolbar)))
122
123 (put 'gnus-offline-set-unplugged-state 'menu-enable 'gnus-offline-connected)
124 (if (eq system-type 'windows-nt)
125     (define-process-argument-editing "/hang\\.exe\\'"
126       (lambda (x)
127         (general-process-argument-editing-function
128          x nil t t nil t t))))
129
130 (defcustom gnus-offline-auto-hangup t
131   "*Whether dialup-network automatically hang up when all online jobs has done."
132   :group 'gnus-offline
133   :type 'boolean)
134
135 (defcustom gnus-offline-load-hook nil
136   "*Hook to be run after the gnus-offline package has been loaded."
137   :group 'gnus-offline
138   :type 'hook)
139
140 (defcustom gnus-offline-before-online-hook nil
141   "*Hook to be run before all online jobs."
142   :group 'gnus-offline
143   :type 'hook)
144
145 (defcustom gnus-offline-after-online-hook nil
146   "*Hook to be run after all online jobs."
147   :group 'gnus-offline
148   :type 'hook)
149
150 (defcustom gnus-offline-mail-treat-environ 'offline
151   "*If online , gnus-offline send all mail under online environ.
152 If offline , gnus-offline send all mail temporary to spool dir."
153   :group 'gnus-offline
154   :type '(choice (const offline)
155                  (const online)))
156
157 (defcustom gnus-offline-articles-to-fetch 'both
158   "*If both , gnus-offline fetch mail and news articles.
159 If mail , gnus-offline only fetch mail articles.
160  If news , gnus-offline only fetch news articles."
161   :group 'gnus-offline
162   :type '(choice (const both)
163                  (const mail)
164                  (const news)))
165
166 (defcustom gnus-offline-mail-group-level 1
167   "*Group level for mail group."
168   :group 'gnus-offline
169   :type 'integer)
170
171 (defcustom gnus-offline-after-empting-spool-hook nil
172   "*Hook to be run before empting spool."
173   :group 'gnus-offline
174   :type 'hook)
175
176 (defcustom gnus-offline-before-empting-spool-hook nil
177   "*Hook to be run after empting spool."
178   :group 'gnus-offline
179   :type 'hook)
180
181 (defcustom gnus-offline-dialup-function 'gnus-offline-connect-server
182   "*Function to dialup."
183   :group 'gnus-offline
184   :type 'function)
185
186 (defcustom gnus-offline-hangup-function 'gnus-offline-hangup-line
187   "*Function to hangup."
188   :group 'gnus-offline
189   :type 'function)
190
191 (defcustom gnus-offline-agent-automatic-expire t
192   "*Non-nil means expire articles on every session."
193   :group 'gnus-offline
194   :type 'boolean)
195
196 ;; These variables should be customized using `gnus-offline-customize',
197 ;; not by `customize'.
198
199 (defvar gnus-offline-dialup-program nil
200   "*Program name for dialup.")
201
202 (defvar gnus-offline-hangup-program nil
203   "*Program name for hangup.")
204
205 (defvar gnus-offline-dialup-program-arguments nil
206   "*Program arguments of gnus-offline-dialup-program.")
207
208 (defvar gnus-offline-hangup-program-arguments nil
209   "*Program arguments of gnus-offline-hangup-program.")
210
211 (defvar gnus-offline-interval-time 0
212   "*Interval time(minutes) to do online jobs.
213 If set to 0 , timer call is disabled.")
214
215 (defvar gnus-offline-drafts-queue-type 'agent
216   "*Queuing function used for draft messages.")
217
218 (defvar gnus-offline-MTA-type 'smtp
219   "*Type of MTA, sendmail or smtp.el.")
220
221 ;;; Internal variables.
222 (defvar gnus-offline-connected nil
223   "*If value is t , dialup line is connected status.
224 If value is nil , dialup line is disconnected status.")
225
226 (defvar gnus-offline-news-fetch-method nil
227   "*Method to fetch news articles.")
228
229 (defvar gnus-offline-mail-fetch-method nil
230   "*Method to fetch mail articles.")
231
232 (defvar gnus-offline-header-string
233   (format "%s - \"%s\""
234           gnus-offline-version
235           gnus-offline-codename)
236   "*Header string for gnus-offline.")
237
238 (defvar gnus-offline-stored-group-level nil
239   "*Mail Group level before changing.")
240
241 (defvar gnus-offline-mail-source nil
242   "*mail-sources save variable.")
243
244 (defvar gnus-offline-lang)
245
246 (defvar gnus-offline-resource-en
247   '((error-check-1
248      . "WARNING!!: gnus-agent.el or nnagent.el is not loaded.
249 Please check your .emacs or .gnus.el to work gnus-agent fine.")
250     (error-check-2 ."WARNING!!: nnspool.el is not loaded.
251 Please check your .emacs or .gnus.el to work nnspool fine.")
252     (connect-server-1 . "Dialing ...")
253     (connect-server-2 . "Dialing ... done.")
254     (get-new-news-function-1 . "Set to online status.")
255     (hangup-line-1 . "Hang up line ... ")
256     (hangup-line-2 . "Hang up line ... done.")
257     (after-jobs-done-1 . "All online jobs has done.")
258     (toggle-auto-hangup-1 . "Auto hang up logic")
259     (toggle-auto-hangup-2 . "disabled.")
260     (toggle-auto-hangup-3 . "enabled.")
261     (toggle-on/off-send-mail-1 . "Sending mail immidiately.")
262     (toggle-on/off-send-mail-2 . "Sending mail temporary to spool directory.")
263     (toggle-articles-to-fetch-1 . "Articles fetch from server.")
264     (toggle-articles-to-fetch-2 . "Only Mail")
265     (toggle-articles-to-fetch-3 . "Only News")
266     (toggle-articles-to-fetch-4 . "Mail/News both")
267     (empting-spool-1 . "Sending mails in spool ...")
268     (empting-spool-2 . "Sending mails in spool ... done.")
269     (empting-spool-3 . "Posting news in spool ...")
270     (empting-spool-4 . "Posting news in spool ... done.")
271     (empting-spool-5 . "Sending messages in spool ...")
272     (empting-spool-6 . "Sending messages in spool ... done.")
273     (interval-time-1 . "Interval time (now %d minutes) : ")
274     (interval-time-2 . "Retrieving message logic by timer is disabled.")
275     (interval-time-3 . "Interval time set to %d minutes")
276     (menu-miee-1 . "Post news in spool")
277     (menu-miee-2 . "Send mails in spool")
278     (menu-miee-3 . "Message Offline")
279     (menu-miee-4 . "Message Online")
280     (menu-1 . "Toggle articles to fetch")
281     (menu-2 . "Toggle online/offline send mail")
282     (menu-3 . "Toggle auto hangup")
283     (menu-4 . "Expire articles")
284     (menu-5 . "Set interval time")
285     (menu-6 . "Hang up Line.")
286     (menu-7 . "Customize options...")))
287
288 (defvar gnus-offline-resource-ja
289   '((error-check-1
290      . "\e$B7Y9p\e(B!!: gnus-agent.el \e$B$^$?$O\e(B nnagent.el \e$B$,%m!<%I$5$l$F$$$^$;$s!#\e(B
291 .emacs \e$B$^$?$O\e(B .gnus.el \e$B$N\e(B gnus-agent \e$B$N@_Dj$r@5$7$/$7$F$/$@$5$$!#\e(B")
292     (error-check-2 ."\e$B7Y9p\e(B!!: nnspool.el \e$B$,%m!<%I$5$l$F$$$^$;$s!#\e(B
293 .emacs \e$B$^$?$O\e(B .gnus.el \e$B$N\e(B nnspool \e$B$N@_Dj$r@5$7$/$7$F$/$@$5$$!#\e(B")
294     (connect-server-1 . "\e$B%@%$%d%k$7$F$$$^$9\e(B...")
295     (connect-server-2 . "\e$B%@%$%d%k$7$F$$$^$9\e(B...\e$B40N;!#\e(B")
296     (get-new-news-function-1 . "\e$B%*%s%i%$%s>uBV$G$9!#\e(B")
297     (hangup-line-1 . "\e$B@ZCG$7$F$$$^$9\e(B...")
298     (hangup-line-2 . "\e$B@ZCG$7$F$$$^$9\e(B...\e$B40N;!#\e(B")
299     (after-jobs-done-1 . "\e$BA4$F$N%*%s%i%$%s=hM}$r40N;$7$^$7$?!#\e(B")
300     (toggle-auto-hangup-1 . "\e$B<+F0@ZCG5!G=$r\e(B ")
301     (toggle-auto-hangup-2 . "\e$B%*%U\e(B \e$B$K$7$^$7$?!#\e(B")
302     (toggle-auto-hangup-3 . "\e$B%*%s\e(B \e$B$K$7$^$7$?!#\e(B")
303     (toggle-on/off-send-mail-1 . "\e$B%a!<%k$rD>@\Aw?.$7$^$9!#\e(B")
304     (toggle-on/off-send-mail-2 . "\e$B%a!<%k$O%-%e!<$KAw$i$l$^$9!#\e(B")
305     (toggle-articles-to-fetch-1 . "\e$B<u?.$9$k%a%C%;!<%8$O\e(B... ")
306     (toggle-articles-to-fetch-2 . "\e$B%a!<%k$N$_$G$9!#\e(B")
307     (toggle-articles-to-fetch-3 . "\e$B%K%e!<%9$N$_$G$9!#\e(B")
308     (toggle-articles-to-fetch-4 . "\e$B%a!<%k$H%K%e!<%9$NN>J}$G$9!#\e(B")
309     (empting-spool-1 . "\e$B%-%e!<$N%a!<%k$rAw?.Cf\e(B...")
310     (empting-spool-2 . "\e$B%-%e!<$N%a!<%k$rAw?.Cf\e(B... \e$B40N;!#\e(B")
311     (empting-spool-3 . "\e$B%-%e!<$N%K%e!<%95-;v$rAw?.Cf\e(B...")
312     (empting-spool-4 . "\e$B%-%e!<$N%K%e!<%95-;v$rAw?.Cf\e(B... \e$B40N;!#\e(B")
313     (empting-spool-5 . "\e$B%-%e!<$N%a%C%;!<%8$rAw?.Cf\e(B...")
314     (empting-spool-6 . "\e$B%-%e!<$N%a%C%;!<%8$rAw?.Cf\e(B... \e$B40N;!#\e(B")
315     (interval-time-1 . "\e$BAw<u?.%8%g%V$N4V3V\e(B (\e$B8=:_$N@_Dj$O\e(B %d \e$BJ,$G$9\e(B) : ")
316     (interval-time-2 . "\e$B<+F0Aw<u?.5!G=$r\e(B \e$B%*%U\e(B \e$B$K$7$^$7$?!#\e(B")
317     (interval-time-3 . "\e$B<+F0Aw<u?.$N4V3V$r\e(B %d \e$BJ,$K@_Dj$7$^$7$?!#\e(B")))
318
319 (defvar gnus-offline-resource-ja_complete
320   (append
321    gnus-offline-resource-ja
322    '((menu-miee-1 . "Spool \e$B$K$"$k5-;v$NAw?.\e(B")
323      (menu-miee-2 . "Spool \e$B$K$"$k\e(B Mail \e$B$NAw?.\e(B")
324      (menu-miee-3 . "Offline \e$B>uBV$X\e(B")
325      (menu-miee-4 . "Online \e$B>uBV$X\e(B")
326      (menu-1 . "\e$B<hF@5-;v<oN`$NJQ99\e(B")
327      (menu-2 . "Mail \e$BAw?.J}K!\e(B(On/Off)\e$B$N@ZBX$(\e(B")
328      (menu-3 . "\e$B<+F0@ZCG$N@ZBX$(\e(B")
329      (menu-4 . "\e$B<hF@:Q5-;v$r>C$9\e(B")
330      (menu-5 . "\e$B5-;v<hF@4V3V;~4V$N@_Dj\e(B")
331      (menu-6 . "\e$B2s@~$N@ZCG\e(B")
332      (menu-7 . "\e$B%W%m%Q%F%#\e(B..."))))
333
334 ;;; Functions
335
336 (defun gnus-offline-get-message (symbol &optional lang)
337   (setq lang (or lang gnus-offline-lang))
338   (or
339    (cdr (assq symbol (symbol-value
340                       (intern (format "gnus-offline-resource-%s" lang)))))
341    (cdr (assq symbol gnus-offline-resource-en))))
342
343 ;;
344 ;; Setting up...
345 ;;
346 (defun gnus-offline-setup ()
347   "*Initialize gnus-offline function"
348
349   ;; Menu and keymap
350   (gnus-offline-define-menu-and-key)
351   
352   ;; To transfer Mail/News function.
353   (cond ((eq gnus-offline-mail-treat-environ 'offline)
354          ;; send mail under offline environ.
355          (gnus-offline-set-offline-sendmail-function))
356         ((eq gnus-offline-mail-treat-environ 'online)
357          ;; send mail under offline environ.
358          (gnus-offline-set-online-sendmail-function))))
359
360 ;;
361 ;; Setting Error check.
362 (defun gnus-offline-error-check ()
363   ;; Check gnus-agent and nnspool setting.
364   (let ((buffer " *Offline Error*"))
365     (cond ((eq gnus-offline-news-fetch-method 'nnagent)
366            ;; nnagent and gnus-agent loaded ??
367            (unless (and (featurep 'gnus-agent)
368                         (featurep 'nnagent))
369              (set-buffer (gnus-get-buffer-create buffer))
370              (erase-buffer)
371              (insert (gnus-offline-get-message 'error-check-1))
372              (pop-to-buffer buffer)))
373         
374           ((eq gnus-offline-news-fetch-method 'nnspool)
375            (unless (featurep 'nnspool)
376              (set-buffer (gnus-get-buffer-create buffer))
377              (erase-buffer)
378              (insert (gnus-offline-get-message 'error-check-2))
379              (pop-to-buffer buffer)))
380           (t
381            nil))))
382 ;;
383 ;;
384 (defun gnus-offline-set-offline-sendmail-function ()
385   "*Initialize sendmail-function when unplugged status."
386   (cond ((eq gnus-offline-drafts-queue-type 'miee)
387          (if (eq gnus-offline-news-fetch-method 'nnagent)
388              (setq gnus-agent-send-mail-function
389                    'sendmail-to-spool-in-gnspool-format))
390          (setq message-send-mail-function 'sendmail-to-spool-in-gnspool-format))
391         (t
392          (setq gnus-agent-send-mail-function
393                (gnus-offline-set-online-sendmail-function)
394                message-send-mail-function 'gnus-agent-send-mail))))
395 ;;
396 (defun gnus-offline-set-online-sendmail-function ()
397   "*Initialize sendmail-function when plugged status."
398   (if (eq gnus-offline-MTA-type 'smtp)
399       (setq message-send-mail-function 'message-send-mail-with-smtp)
400     (setq message-send-mail-function 'message-send-mail-with-sendmail)))
401 ;;
402 (defun gnus-offline-set-offline-post-news-function ()
403   "*Initialize sendnews-function when unplugged status."
404   (if (eq gnus-offline-drafts-queue-type 'miee)
405       (setq message-send-news-function 'gnspool-request-post)))
406 ;;
407 (defun gnus-offline-set-online-post-news-function ()
408   "*Initialize sendnews-function when plugged status."
409   (setq message-send-news-function 'message-send-news-with-gnus))
410 ;;
411 ;; Get new news jobs. (gnus-agent and nnspool)
412 ;;
413 (defun gnus-offline-gnus-get-new-news (&optional arg)
414   "*Override function \"gnus-group-get-new-news\"."
415   (interactive "P")
416   (run-hooks 'gnus-offline-before-online-hook)
417   (if (functionp gnus-offline-dialup-function)
418       (funcall gnus-offline-dialup-function))
419   (gnus-offline-get-new-news-function)
420   (gnus-group-get-new-news arg))
421
422 ;;
423 ;; dialup...
424 ;;
425 (defun gnus-offline-connect-server ()
426   "*Dialup function."
427   ;; Dialup if gnus-offline-dialup-program is specified
428   (if (stringp gnus-offline-dialup-program)
429       (progn
430         (message (gnus-offline-get-message 'connect-server-1))
431         (apply 'call-process gnus-offline-dialup-program nil nil nil
432                gnus-offline-dialup-program-arguments)
433         (sleep-for 1)
434         (message (gnus-offline-get-message 'connect-server-2)))))
435
436 ;;
437 ;; Jobs before get new news , send mail and post news.
438 ;;
439 (defun gnus-offline-get-new-news-function ()
440   "*Prepare to get new news/mail."
441   ;; Set mail group level
442   (if (eq gnus-offline-articles-to-fetch 'mail)
443       (gnus-offline-set-mail-group-level gnus-offline-mail-group-level))
444
445   ;; Set to online environ.
446   (setq gnus-offline-connected t)
447
448   ;; Set send mail/news functions to online functions.
449   (gnus-offline-set-online-sendmail-function)
450   (gnus-offline-set-online-post-news-function)
451   (message (gnus-offline-get-message 'get-new-news-function-1))
452
453   ;; fetch only news
454   (if (eq gnus-offline-articles-to-fetch 'news)
455       (gnus-offline-disable-fetch-mail))
456
457   ;; fetch both mail and news. or Only mail.
458   (gnus-offline-enable-fetch-news)
459   (if (memq gnus-offline-articles-to-fetch '(both mail))
460       (gnus-offline-enable-fetch-mail))
461
462   ;; fetch only mail for gnus-agent
463   (if (and (eq gnus-offline-news-fetch-method 'nnagent)
464            (eq gnus-offline-articles-to-fetch 'mail))
465           (setq gnus-agent-handle-level gnus-offline-mail-group-level)))
466
467 ;;
468 ;; Change mail group level to handle only mail.
469 ;;
470 (defun gnus-offline-set-mail-group-level (level)
471   "*Set nnm* group level."
472   (switch-to-buffer gnus-group-buffer)
473   (goto-char (point-min))
474   
475   ;; Save current level
476   (if (not gnus-offline-stored-group-level)
477       (while (re-search-forward " nnm" nil t)
478         (setq gnus-offline-stored-group-level
479               (append gnus-offline-stored-group-level
480                       (list (gnus-group-group-level)))))
481     (forward-line 1)
482     (beginning-of-line))
483   ;;
484   (goto-char (point-min))
485   (while (re-search-forward " nnm" nil t)
486     (gnus-group-set-current-level 1 level)
487     (forward-line 1)
488     (beginning-of-line))
489   t)
490 ;;
491 ;; Restore mail group level
492 ;;
493 (defun gnus-offline-restore-mail-group-level ()
494   "*Restore nnm* group level."
495   (switch-to-buffer gnus-group-buffer)
496   (goto-char (point-min))
497   (let ((num 0))
498     (while (re-search-forward " nnm" nil t)
499       (gnus-group-set-current-level 1 (nth num gnus-offline-stored-group-level))
500       (forward-line 1)
501       (setq num (+ num 1))
502       (beginning-of-line))))
503 ;;
504 ;; Jobs after getting new news.
505 ;;
506 (defun gnus-offline-after-get-new-news ()
507   "*After getting news and mail jobs."
508   (if (memq gnus-offline-articles-to-fetch '(both mail))
509       (progn
510         ;; Mail/both
511         ;; send mail/news in spool
512         (gnus-offline-empting-spool)
513         (if (eq gnus-offline-articles-to-fetch 'mail)
514             (progn
515               ;; Send only mail and hang up...
516               (if (and gnus-offline-connected
517                        gnus-offline-auto-hangup)
518                   (gnus-offline-set-unplugged-state))
519               ;; Disable fetch mail.
520               (gnus-offline-disable-fetch-mail)
521               (gnus-offline-after-jobs-done)))))
522   
523   ;; News/Both
524   (if (memq gnus-offline-articles-to-fetch '(both news))
525       (progn
526         (if gnus-offline-connected
527             (cond ((eq gnus-offline-news-fetch-method 'nnagent)
528                    ;; Get New News (gnus-agent)
529                    (gnus-agent-toggle-plugged t)
530                   
531                    ;; fetch articles
532                    (gnus-agent-fetch-session)
533                   
534                    ;; Hang Up line. then set to offline status.
535                    (if (and gnus-offline-connected
536                             gnus-offline-auto-hangup)
537                        (gnus-offline-set-unplugged-state))
538                    
539                    ;; All online jobs has done.
540                    (gnus-offline-after-jobs-done))
541                   (t
542                    (if (eq gnus-offline-news-fetch-method 'nnspool)
543                        ;; Get New News (nnspool)
544                        (gnspool-get-news))))))))
545 ;;
546 ;; Disable fetch mail
547 ;;
548 (defun gnus-offline-disable-fetch-mail ()
549   "*Set do not fetch mail."
550   (setq mail-sources nil
551         nnmail-spool-file nil))
552 ;;
553 ;; Enable fetch mail
554 ;;
555 (defun gnus-offline-enable-fetch-mail ()
556   "*Set to fetch mail."
557   (setq gnus-offline-mail-fetch-method 'nnmail)
558   (setq mail-sources gnus-offline-mail-source))
559 ;;
560 ;; Enable fetch news
561 ;;
562 (defun gnus-offline-enable-fetch-news ()
563   "*Set to fetch news."
564   (if (eq gnus-offline-news-fetch-method 'nnagent)
565       (progn
566         (setq gnus-agent-handle-level gnus-level-subscribed)
567         (gnus-agent-toggle-plugged t))))
568 \f
569 ;;
570 ;; Add your custom header.
571 ;;
572 (defun gnus-offline-add-custom-header (header string)
573   "*Add X-Gnus-Offline-Backend header to Mail/News message."
574   (let ((delimline
575          (progn (goto-char (point-min))
576                 (re-search-forward
577                  (concat "^" (regexp-quote mail-header-separator) "\n"))
578                 (point-marker)))
579         hdr str)
580     (goto-char (point-min))
581     (unless (re-search-forward (concat "^" header) delimline t)
582       (goto-char delimline)
583       (forward-line -1)
584       (beginning-of-line)
585       (setq hdr (concat header " "))
586       (setq str (concat hdr string))
587       (setq hdr (concat str "\n"))
588       (insert-string hdr))))
589 ;;
590 ;; Add X-Offline-Backend header.
591 ;;
592 (defun gnus-offline-message-add-header ()
593   "*Add X-Gnus-Offline-Backend header to Mail/News message."
594   (when (eq gnus-offline-mail-treat-environ 'offline)
595     (let* ((ver (if (eq gnus-offline-news-fetch-method 'nnagent)
596                     nnagent-version
597                   nnspool-version))
598            (str (format "\n                        with %s" ver)))
599     (gnus-offline-add-custom-header
600      "X-Gnus-Offline-Backend:" (concat gnus-offline-header-string str)))))
601
602 \f
603 ;;
604 ;; Toggle plugged/unplugged
605 ;;
606 (defun gnus-offline-toggle-plugged (plugged)
607   "*Override function \"Jj\" - gnus-agent-toggle-plugged."
608   (interactive (list (not gnus-offline-connected)))
609   (if plugged
610       (progn
611         (setq gnus-offline-connected plugged)
612         (gnus-agent-toggle-plugged plugged)
613         ;; Set send mail/news function to offline functions.
614         (gnus-offline-set-online-sendmail-function)
615         (gnus-offline-set-online-post-news-function))
616     ;; Set to offline status
617     (gnus-offline-set-unplugged-state)))
618 ;;
619 ;; Function of hang up line.
620 ;;
621 (defun gnus-offline-set-unplugged-state ()
622   "*Set to unplugged state."
623   (interactive)
624   ;; Hang Up Line.
625   (if (functionp gnus-offline-hangup-function)
626       (funcall gnus-offline-hangup-function))
627   (setq gnus-offline-connected nil)
628   (if (eq gnus-offline-news-fetch-method 'nnagent)
629       (gnus-agent-toggle-plugged nil))
630
631   ;; Set send mail/news function to offline functions.
632   (gnus-offline-set-offline-sendmail-function)
633   (gnus-offline-set-offline-post-news-function)
634   ;;
635   (setenv "MAILHOST" nil))
636 ;;
637 ;; Hangup line function 
638 ;;
639 (defun gnus-offline-hangup-line ()
640   "*Hangup line function."
641   (message (gnus-offline-get-message 'hangup-line-1))
642   (if (stringp gnus-offline-hangup-program)
643       (apply 'start-process "hup" nil gnus-offline-hangup-program
644              gnus-offline-hangup-program-arguments))
645   (message (gnus-offline-get-message 'hangup-line-2)))
646 ;;
647 ;; Hang Up line routine whe using nnspool
648 ;;
649 (defun gnus-offline-nnspool-hangup-line ()
650   (if (and gnus-offline-connected
651            gnus-offline-auto-hangup)
652       (gnus-offline-set-unplugged-state))
653   (gnus-offline-after-jobs-done))
654 ;;
655 ;; Function of all jobs has done.
656 ;;
657 (defun gnus-offline-after-jobs-done ()
658   "*Jobs after all online jobs."
659   (run-hooks 'gnus-offline-after-online-hook)
660   (if (eq gnus-offline-articles-to-fetch 'mail)
661       (gnus-offline-restore-mail-group-level))
662   (if (eq gnus-offline-news-fetch-method 'nnagent)
663       (gnus-offline-agent-expire))
664   (if (and (featurep 'xemacs)
665            (fboundp 'play-sound-file))
666       (ding nil 'drum)
667     (ding))
668   (gnus-group-save-newsrc)
669   (message (gnus-offline-get-message 'after-jobs-done-1)))
670
671 \f
672 ;;
673 ;; Toggle auto hang up
674 ;;
675 (defun gnus-offline-toggle-auto-hangup ()
676   "*Toggle auto hangup flag."
677   (interactive)
678   (let ((string (gnus-offline-get-message 'toggle-auto-hangup-1)) str)
679     (if gnus-offline-auto-hangup
680         (progn
681           (setq gnus-offline-auto-hangup nil
682                 str (gnus-offline-get-message 'toggle-auto-hangup-2)))
683       (setq gnus-offline-auto-hangup t
684             str (gnus-offline-get-message 'toggle-auto-hangup-3)))
685     (message (format "%s %s" string str))))
686 ;;
687 ;; Toggle offline/online to send mail.
688 ;;
689 (defun gnus-offline-toggle-on/off-send-mail ()
690   "*Toggel online/offline sendmail."
691   (interactive)
692   (if (eq gnus-offline-mail-treat-environ 'offline)
693       (progn
694         ;; Sending mail under online environ.
695         (gnus-offline-set-online-sendmail-function)
696         (setq gnus-offline-mail-treat-environ 'online)
697         (message (gnus-offline-get-message 'toggle-on/off-send-mail-1)))
698     ;; Sending mail under offline environ.
699     (gnus-offline-set-offline-sendmail-function)
700     (setq gnus-offline-mail-treat-environ 'offline)
701     (message (gnus-offline-get-message 'toggle-on/off-send-mail-2))))
702 ;;
703 ;; Toggle articles to fetch ... both -> mail -> news -> both
704 ;;
705 (defun gnus-offline-toggle-articles-to-fetch ()
706   "*Set articles to fetch... both(Mail/News) -> mail only -> News only -> both"
707   (interactive)
708   (let ((string (gnus-offline-get-message 'toggle-articles-to-fetch-1))
709         str)
710     (cond ((eq gnus-offline-articles-to-fetch 'both)
711            (setq gnus-offline-articles-to-fetch 'mail
712                  str (gnus-offline-get-message 'toggle-articles-to-fetch-2)))
713           ((eq gnus-offline-articles-to-fetch 'mail)
714            (setq gnus-offline-articles-to-fetch 'news
715                  str (gnus-offline-get-message 'toggle-articles-to-fetch-3)))
716           (t
717            (setq gnus-offline-articles-to-fetch 'both
718                  str (gnus-offline-get-message 'toggle-articles-to-fetch-4))))
719     (message (format "%s %s" string str))))
720 ;;
721 ;; Send mail and Post news using Miee or gnus-agent.
722 ;;
723 (defun gnus-offline-empting-spool ()
724   "*Send all drafts on queue."
725   (run-hooks 'gnus-offline-before-empting-spool-hook)
726   (if (eq gnus-offline-drafts-queue-type 'miee)
727       ;; Send queued message by miee.el.
728       (progn
729         (if (eq gnus-offline-mail-treat-environ 'offline)
730             (progn
731               (message (gnus-offline-get-message 'empting-spool-1))
732               ;; Using miee to send mail.
733               (mail-spool-send)
734               (message (gnus-offline-get-message 'empting-spool-2))))
735         (message (gnus-offline-get-message 'empting-spool-3))
736         ;; Using miee to post news.
737         (if (and (not (stringp msspool-news-server))
738                  (not msspool-news-service))
739             (progn
740               (setq msspool-news-server (nth 1 gnus-select-method))
741               (setq msspool-news-service 119)))
742         (news-spool-post)
743         (message (gnus-offline-get-message 'empting-spool-4)))
744     ;; Send queued message by gnus-agent
745     (message (gnus-offline-get-message 'empting-spool-5))
746     (gnus-group-send-drafts)
747     (message (gnus-offline-get-message 'empting-spool-6)))
748   ;;
749   (run-hooks 'gnus-offline-after-empting-spool-hook))
750 ;;
751 ;; Set interval time
752 ;;
753 (defun gnus-offline-set-interval-time ()
754   "*Set interval time for gnus-daemon."
755   (interactive)
756   (setq gnus-offline-interval-time
757         (string-to-int (read-from-minibuffer
758                         (format (gnus-offline-get-message 'interval-time-1)
759                                 gnus-offline-interval-time)
760                         nil)))
761   (if (< gnus-offline-interval-time 2)
762       (progn
763         (message (gnus-offline-get-message 'interval-time-2))
764         (setq gnus-offline-interval-time 0))
765     (message
766      (format (gnus-offline-get-message 'interval-time-3)
767              gnus-offline-interval-time)))
768   (gnus-offline-processed-by-timer))
769 ;;
770 ;; Expire articles using gnus-agent.
771 ;;
772 (defun gnus-offline-agent-expire ()
773   "*Expire expirable article on News group."
774   (interactive)
775   (and gnus-offline-agent-automatic-expire
776        (if (eq 0 gnus-agent-expire-days)
777            (let (gnus-agent-expire-all)
778              (gnus-agent-expire))
779          (gnus-agent-expire))))
780 ;;
781 ;; Menu.
782 ;;
783 (defun gnus-offline-define-menu-and-key ()
784   "*Set key and menu."
785   (if (eq gnus-offline-drafts-queue-type 'miee)
786       (if (featurep 'xemacs)
787           (add-hook 'gnus-group-mode-hook 'gnus-offline-define-menu-on-miee)
788         (gnus-offline-define-menu-on-miee))
789     (add-hook 'gnus-group-mode-hook 'gnus-offline-define-menu-on-agent))
790   (add-hook 'gnus-group-mode-hook
791             '(lambda ()
792                (local-set-key "\C-coh" 'gnus-offline-set-unplugged-state)
793                (local-set-key "\C-cof" 'gnus-offline-toggle-articles-to-fetch)
794                (local-set-key "\C-coo" 'gnus-offline-toggle-on/off-send-mail)
795                (local-set-key "\C-cox" 'gnus-offline-toggle-auto-hangup)
796                (local-set-key "\C-cos" 'gnus-offline-set-interval-time)
797                (substitute-key-definition
798                 'gnus-group-get-new-news 'gnus-offline-gnus-get-new-news
799                 gnus-group-mode-map)
800                (if (eq gnus-offline-news-fetch-method 'nnagent)
801                    (progn
802                      (substitute-key-definition
803                       'gnus-agent-toggle-plugged 'gnus-offline-toggle-plugged
804                       gnus-agent-group-mode-map)
805                      (local-set-key "\C-coe" 'gnus-offline-agent-expire)))
806                (or (featurep 'xemacs)
807                    (define-key gnus-group-mode-map 
808                      (if (eq system-type 'windows-nt) [S-mouse-2] [mouse-3])
809                      'gnus-offline-popup-menu))))
810   (if (eq gnus-offline-news-fetch-method 'nnagent)
811       (add-hook 'gnus-summary-mode-hook
812                 '(lambda ()
813                    (substitute-key-definition
814                     'gnus-agent-toggle-plugged 'gnus-offline-toggle-plugged
815                     gnus-agent-summary-mode-map))))
816   (if (featurep 'xemacs)
817       ;; Overwrite the toolbar spec for gnus-group-mode.
818       (add-hook 'gnus-startup-hook
819                 #'(lambda ()
820                     (catch 'tag
821                       (mapc (lambda (but)
822                               (when (eq 'gnus-group-get-new-news (aref but 1))
823                                 (aset but 1 'gnus-offline-gnus-get-new-news)
824                                 (throw 'tag nil)))
825                             gnus-group-toolbar))))))
826 ;;
827 ;;
828 (defun gnus-offline-get-menu-items (list)
829   (mapcar
830    #'(lambda (el)
831        (if (listp el)
832            (apply 'vector
833                   (cons (gnus-offline-get-message (car el)) (cdr el)))
834          el))
835    list))
836
837 (defvar gnus-offline-menu
838   (gnus-offline-get-menu-items
839    '((menu-1 gnus-offline-toggle-articles-to-fetch t)
840      (menu-2 gnus-offline-toggle-on/off-send-mail t)
841      (menu-3 gnus-offline-toggle-auto-hangup t)
842      "----"
843      (menu-4 gnus-offline-agent-expire
844              (eq gnus-offline-news-fetch-method 'nnagent))
845      (menu-5 gnus-offline-set-interval-time t)
846      "----"
847      (menu-6 gnus-offline-set-unplugged-state gnus-offline-connected)
848      "----"
849      (menu-7 gnus-ofsetup-customize t))))
850
851 (defun gnus-offline-define-menu-on-miee ()
852   "*Set and change menu bar on MIEE menu."
853   (let ((miee-menu
854          (gnus-offline-get-menu-items
855           '((menu-miee-1 news-spool-post t)
856             (menu-miee-2 mail-spool-send t)
857             "----"
858             (menu-miee-3 message-offline-state (not message-offline-state))
859             (menu-miee-4 message-online-state message-offline-state)
860             "----")))
861         menu)
862     (setq menu
863           (easy-menu-change
864            nil "Miee"
865            (append miee-menu
866                    (list (cons "Gnus Offline" gnus-offline-menu)))))
867     (and (featurep 'xemacs)
868          (easy-menu-add menu))))
869 ;;
870 ;; define menu without miee.
871 ;;
872 (defun gnus-offline-define-menu-on-agent ()
873   "*Set menu bar on OFFLINE menu."
874   (easy-menu-define
875    gnus-offline-menu-on-agent gnus-group-mode-map "Gnus offline Menu"
876    (cons "Offline" gnus-offline-menu))
877   (and (featurep 'xemacs)
878        (easy-menu-add gnus-offline-menu-on-agent)))
879 ;;
880 ;; Popup menu within the group buffer (under Emacs).
881 ;;
882 (defvar gnus-offline-popup-menu nil)
883 (defun gnus-offline-popup-menu (event)
884   "Popup menu for Gnus Offline."
885   (interactive "e")
886   (unless gnus-offline-popup-menu
887     (setq gnus-offline-popup-menu
888           (let ((menu
889                  (if (boundp 'miee-popup-menu)
890                      (or (assq 'keymap
891                                 (assq 'Miee (assq 'menu-bar global-map)))
892                          miee-popup-menu)
893                    (symbol-value 'gnus-offline-menu-on-agent))))
894             (if (string< emacs-version "20")
895                 (append (list 'keymap
896                               (if (boundp 'miee-popup-menu)
897                                   '(nil "Miee")
898                                 '(nil "Offline"))
899                               '(nil "")
900                               '(nil ""))
901                         (cdr menu))
902               menu))))
903   (let* ((pop (x-popup-menu t gnus-offline-popup-menu))
904          (func (and pop (lookup-key gnus-offline-popup-menu
905                                     (apply 'vector pop)))))
906     (and pop func (funcall func))))
907 \f
908 ;;
909 ;; Timer Function
910 (defun gnus-offline-processed-by-timer ()
911   "*Set timer interval."
912   (if (and (> gnus-offline-interval-time 0)
913            (not gnus-offline-connected))
914       ;; Timer call
915       (gnus-demon-add-handler 'gnus-offline-gnus-get-new-news
916                               gnus-offline-interval-time
917                               gnus-offline-interval-time))
918   (if (= gnus-offline-interval-time 0)
919       (gnus-demon-remove-handler 'gnus-offline-gnus-get-new-news t)))
920 ;;
921 ;;
922 ;;; gnus-offline.el ends here