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