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