Update.
[elisp/wanderlust.git] / wl / wl-xmas.el
1 ;;; wl-xmas.el -- Wanderlust modules for XEmacsen.
2
3 ;; Copyright 1998,1999,2000 Yuuichi Teranishi <teranisi@gohome.org>
4
5 ;; Author: Yuuichi Teranishi <teranisi@gohome.org>
6 ;; Keywords: mail, net news
7 ;; Time-stamp: <00/03/24 14:44:00 teranisi>
8
9 ;; This file is part of Wanderlust (Yet Another Message Interface on Emacsen).
10
11 ;; This program is free software; you can redistribute it and/or modify
12 ;; it under the terms of the GNU General Public License as published by
13 ;; the Free Software Foundation; either version 2, or (at your option)
14 ;; any later version.
15 ;;
16 ;; This program is distributed in the hope that it will be useful,
17 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
18 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19 ;; GNU General Public License for more details.
20 ;;
21 ;; You should have received a copy of the GNU General Public License
22 ;; along with GNU Emacs; see the file COPYING.  If not, write to the
23 ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
24 ;; Boston, MA 02111-1307, USA.
25 ;;
26
27 ;;; Commentary:
28 ;; 
29
30 ;;; Code:
31 ;; 
32
33 (eval-when-compile
34   (require 'wl-folder)
35   (require 'wl-summary)
36   (require 'wl-draft)  
37   (require 'wl-message)
38   (require 'wl-highlight)
39   (defvar-maybe wl-draft-mode-map (make-sparse-keymap)))
40
41 (defun wl-xmas-setup-toolbar (bar)
42   (let ((dir wl-icon-dir)
43         icon up down disabled name)
44     (when dir
45       (while bar
46         (setq icon (aref (car bar) 0)
47               name (symbol-name icon)
48               bar (cdr bar))
49         (when (not (boundp icon))
50           (setq up (concat dir elmo-path-sep name "-up.xpm"))
51           (setq down (concat dir elmo-path-sep name "-down.xpm"))
52           (setq disabled (concat dir elmo-path-sep name "-disabled.xpm"))
53           (if (not (file-exists-p up))
54               (setq bar nil
55                     dir nil)
56             (set icon (toolbar-make-button-list
57                        up (and (file-exists-p down) down)
58                        (and (file-exists-p disabled) disabled)))))))
59     dir))
60
61 (defvar wl-use-toolbar (if (featurep 'toolbar) 'default-toolbar nil))
62 (defvar wl-plugged-glyph nil)
63 (defvar wl-unplugged-glyph nil)
64
65 (defvar wl-folder-toolbar
66   '([wl-folder-jump-to-current-entity
67      wl-folder-jump-to-current-entity t "Enter Current Folder"]
68     [wl-folder-next-entity
69      wl-folder-next-entity t "Next Folder"]
70     [wl-folder-prev-entity
71      wl-folder-prev-entity t "Previous Folder"]
72     [wl-folder-check-current-entity
73      wl-folder-check-current-entity t "Check Current Folder"]
74 ;    [wl-draft
75 ;     wl-draft t "Write a New Message"]
76     [wl-folder-sync-current-entity
77      wl-folder-sync-current-entity t "Sync Current Folder"]
78     [wl-draft
79      wl-draft t "Write a New Message"]
80     [wl-folder-empty-trash
81      wl-folder-empty-trash t "Empty Trash"]
82     [wl-exit
83      wl-exit t "Quit Wanderlust"]
84     )
85   "The Folder buffer toolbar.")
86
87 (defvar wl-summary-toolbar
88   '([wl-summary-read
89      wl-summary-read t "Read Messages"]
90     [wl-summary-next
91      wl-summary-next t "Next Message"]
92     [wl-summary-prev
93      wl-summary-prev t "Previous Message"]
94     [wl-summary-jump-to-current-message
95      wl-summary-jump-to-current-message t "Jump to Current Message"]
96     [wl-summary-sync-force-update
97      wl-summary-sync-force-update t "Sync Current Folder"]
98     [wl-summary-delete
99      wl-summary-delete t "Delete Current Message"]
100     [wl-summary-mark-as-important
101      wl-summary-mark-as-important t "Mark Current Message as Important"]
102     [wl-draft
103      wl-draft t "Write a New Message"]
104     [wl-summary-reply
105      wl-summary-reply t "Reply to Current Message" ]
106     [wl-summary-reply-with-citation
107      wl-summary-reply-with-citation t "Reply to Current Message with Citation"]
108     [wl-summary-forward
109      wl-summary-forward t "Forward Current Message"]
110     [wl-summary-exit
111      wl-summary-exit t "Exit Current Summary"]    
112     )
113   "The Summary buffer toolbar.")
114
115 (defvar wl-message-toolbar
116   '([wl-message-read
117      wl-message-read t "Read Contents"]
118     [wl-message-next-content
119      wl-message-next-content t "Next Content"]
120     [wl-message-prev-content
121      wl-message-prev-content t "Previous Content"]
122     [wl-message-quit
123      wl-message-quit t "Back to Summary"]
124     [wl-message-play-content
125      wl-message-play-content t "Play Content"]
126     [wl-message-extract-content
127      wl-message-extract-content t "Extract Content"]
128     )
129   "The Message buffer toolbar.")
130
131 (defalias 'wl-draft-insert-signature 'insert-signature) ;; for draft toolbar.
132
133 (defvar wl-draft-toolbar
134   '([wl-draft-send-from-toolbar
135      wl-draft-send-from-toolbar t "Send Current Draft"]
136     [wl-draft-yank-original
137      wl-draft-yank-original t "Yank Displaying Message"]
138     [wl-draft-insert-signature
139      wl-draft-insert-signature t "Insert Signature"]
140     [wl-draft-kill
141      wl-draft-kill t "Kill Current Draft"]
142     )
143   "The Draft buffer toolbar.")
144
145 (defun wl-xmas-setup-folder-toolbar ()
146   (and wl-use-toolbar
147        (wl-xmas-setup-toolbar wl-folder-toolbar)
148        (set-specifier (symbol-value wl-use-toolbar)
149                       (cons (current-buffer) wl-folder-toolbar))))
150
151 (defun wl-xmas-setup-summary-toolbar ()
152   (and wl-use-toolbar
153        (wl-xmas-setup-toolbar wl-summary-toolbar)
154        (set-specifier (symbol-value wl-use-toolbar)
155                       (cons (current-buffer) wl-summary-toolbar))))
156
157 (defun wl-xmas-setup-message-toolbar ()
158   (and wl-use-toolbar
159        (wl-xmas-setup-toolbar wl-message-toolbar)
160        (set-specifier (symbol-value wl-use-toolbar)
161                       (cons (current-buffer) wl-message-toolbar))))
162
163 (defun wl-xmas-setup-draft-toolbar ()
164   (and wl-use-toolbar
165        (wl-xmas-setup-toolbar wl-draft-toolbar)
166        (set-specifier (symbol-value wl-use-toolbar)
167                       (cons (current-buffer) wl-draft-toolbar))))
168
169 ;; XEmacs implementations.
170 (defun wl-highlight-folder-current-line (&optional numbers)
171   (interactive)
172   (save-excursion
173     (let ((highlights (list "opened" "closed"))
174           (inhibit-read-only t)
175           (fld-name (wl-folder-get-folder-name-by-id
176                      (get-text-property (point) 'wl-folder-entity-id)))
177           fregexp fsymbol bol eol matched type extent num type glyph)
178       (setq eol (progn (end-of-line) (point))
179             bol (progn (beginning-of-line) (point)))
180       (when (and fld-name (looking-at "[ \t]+\\([^ \t]+\\)"))
181         (if (and (setq extent (extent-at (match-beginning 1) nil nil nil 'at))
182                  (extent-begin-glyph extent))
183             (delete-extent extent))
184         (setq extent (make-extent (match-beginning 1) (match-beginning 1)))
185         (cond
186          ((string= fld-name wl-trash-folder) ;; set trash folder icon
187           (setq num (nth 2 numbers)) ;; number of messages
188           (set-extent-begin-glyph extent
189                                   (if (or (null num) 
190                                           (eq num 0))
191                                       wl-folder-trash-empty-glyph
192                                     wl-folder-trash-glyph)))
193          ((string= fld-name wl-draft-folder) ;; set draft folder icon
194           (set-extent-begin-glyph extent wl-folder-draft-glyph))
195          ((string= fld-name wl-queue-folder)
196           (set-extent-begin-glyph extent wl-folder-queue-glyph))
197          ((and (setq type (elmo-folder-get-type fld-name))
198                (or numbers ;; XXX dirty...!!
199                    (not (assoc fld-name wl-folder-group-alist))))
200           ;; not group folder.
201           (set-extent-begin-glyph extent 
202                                   (symbol-value
203                                    (intern (format "wl-folder-%s-glyph"
204                                                    type)))))))
205       (when (and numbers (nth 0 numbers) (nth 1 numbers))
206         (setq fsymbol 
207               (let ((unsync (nth 0 numbers))
208                     (unread (nth 1 numbers)))
209                 (cond ((and unsync (eq unsync 0))
210                        (if (and unread (> unread 0))
211                            'wl-highlight-folder-unread-face
212                          'wl-highlight-folder-zero-face))
213                       ((and unsync 
214                             (>= unsync wl-folder-many-unsync-threshold))
215                        'wl-highlight-folder-many-face)
216                       (t
217                        'wl-highlight-folder-few-face))))
218         (put-text-property bol eol 'face nil)
219         (put-text-property bol eol 'face fsymbol)
220         (setq matched t))
221       (while highlights
222         (setq fregexp (symbol-value 
223                        (intern (format "wl-highlight-folder-%s-regexp" 
224                                        (car highlights)))))
225         (if (not wl-highlight-group-folder-by-numbers)
226             (setq fsymbol (intern (format "wl-highlight-folder-%s-face"
227                                           (car highlights)))))
228         (when (looking-at fregexp)
229           (setq extent (make-extent (match-beginning 1) (match-end 1))
230                 glyph (intern (format "wl-folder-%s-glyph"
231                                       (car highlights))))
232           (if (null (symbol-value glyph))
233               (set glyph (wl-xmas-make-icon-glyph
234                           (extent-string extent)
235                           (symbol-value
236                            (cdr (assq glyph wl-folder-toggle-icon-list))))))
237           (setq glyph (symbol-value glyph))
238           (set-extent-property extent 'end-open t)
239           (set-extent-property extent 'start-closed t)
240           (set-extent-property extent 'invisible t)
241           (set-extent-end-glyph extent glyph)
242           (put-text-property bol eol 'face nil)
243           (put-text-property bol eol 'face fsymbol)
244           (setq matched t highlights nil))
245         (setq highlights (cdr highlights)))
246       (when (not matched)
247         (put-text-property bol eol 'face nil)
248         (if (looking-at (format "^[ ]*\\(%s\\|%s\\)"
249                                 wl-folder-unsubscribe-mark
250                                 wl-folder-removed-mark))
251             (put-text-property bol eol 'face
252                                'wl-highlight-folder-killed-face)
253           (put-text-property bol eol 'face
254                              'wl-highlight-folder-unknown-face)))
255       (if wl-use-highlight-mouse-line 
256           (wl-highlight-folder-mouse-line))
257       (if (and (featurep 'dragdrop) wl-use-dnd)
258           (wl-dnd-set-drop-target bol eol)))))
259
260 (defun wl-highlight-plugged-current-line ()
261   (interactive)
262   (save-excursion
263     (let ((inhibit-read-only t)
264           extent switch)
265       (beginning-of-line)
266       (when (looking-at "[ \t]*\\(\\[\\([^]]+\\)\\]\\)")
267         (setq switch (elmo-match-buffer 2))
268         (if (and (setq extent (extent-at (match-end 1) nil nil nil 'at))
269                  (extent-end-glyph extent))
270             (delete-extent extent))
271         (setq extent (make-extent (match-beginning 1) (match-end 1)))
272         (set-extent-property extent 'end-open t)
273         (set-extent-property extent 'start-closed t)
274         (set-extent-property extent 'invisible t)
275         (set-extent-end-glyph extent (if (string= switch wl-plugged-plug-on)
276                                          wl-plugged-glyph
277                                        wl-unplugged-glyph))))))
278
279 (defun wl-plugged-set-folder-icon (folder string)
280   (let ((string (copy-sequence string))
281         (len (length string))
282         type)
283     (if (string= folder wl-queue-folder)
284         (put-text-property 0 len 'begin-glyph wl-folder-queue-glyph string)
285       (if (setq type (elmo-folder-get-type folder))
286           (put-text-property 0 len
287                              'begin-glyph
288                              (symbol-value
289                               (intern (format "wl-folder-%s-glyph" type)))
290                              string)))
291     string))
292
293 (defvar wl-folder-internal-icon-list
294   ;; alist of (glyph . icon-file)
295   '((wl-folder-nntp-glyph         . wl-nntp-folder-icon)
296     (wl-folder-imap4-glyph        . wl-imap-folder-icon)
297     (wl-folder-pop3-glyph         . wl-pop-folder-icon)
298     (wl-folder-localdir-glyph     . wl-localdir-folder-icon)
299     (wl-folder-localnews-glyph    . wl-localnews-folder-icon)
300     (wl-folder-internal-glyph     . wl-internal-folder-icon)
301     (wl-folder-multi-glyph        . wl-multi-folder-icon)
302     (wl-folder-filter-glyph       . wl-filter-folder-icon)
303     (wl-folder-archive-glyph      . wl-archive-folder-icon)
304     (wl-folder-pipe-glyph         . wl-pipe-folder-icon)
305     (wl-folder-maildir-glyph      . wl-maildir-folder-icon)
306     (wl-folder-trash-empty-glyph  . wl-empty-trash-folder-icon)
307     (wl-folder-draft-glyph        . wl-draft-folder-icon)
308     (wl-folder-queue-glyph        . wl-queue-folder-icon)
309     (wl-folder-trash-glyph        . wl-trash-folder-icon)))
310
311 (defvar wl-folder-toggle-icon-list
312   '((wl-folder-opened-glyph       . wl-opened-group-folder-icon)
313     (wl-folder-closed-glyph       . wl-closed-group-folder-icon)))
314
315 (defun wl-xmas-make-icon-glyph (icon-string icon-file &optional locale tag-set)
316   (let ((glyph (make-glyph (vector 'string :data icon-string))))
317     (if wl-highlight-folder-with-icon
318         (set-glyph-image glyph
319                          (vector 'xpm :file (expand-file-name
320                                              icon-file wl-icon-dir))
321                          locale tag-set 'prepend))
322     glyph))
323
324 (defun wl-folder-init-icons ()  
325   (mapcar
326    (lambda (x)
327      (if (null (symbol-value (car x)))
328          (set (car x) (wl-xmas-make-icon-glyph "" (symbol-value (cdr x))))))
329    wl-folder-internal-icon-list))
330
331 (defun wl-plugged-init-icons ()
332   (if (null wl-plugged-glyph)
333       (setq wl-plugged-glyph
334             (wl-xmas-make-icon-glyph
335              (concat "[" wl-plugged-plug-on "]")
336              wl-plugged-icon)))
337   (if (null wl-unplugged-glyph)
338       (setq wl-unplugged-glyph
339             (wl-xmas-make-icon-glyph
340              (concat "[" wl-plugged-plug-off "]")
341              wl-unplugged-icon))))
342
343 (defun wl-make-modeline ()
344   "Make modeline for Wanderlust"
345   (wl-plugged-init-icons)
346   (let ((extent (make-extent nil nil))
347         (toggle-keymap (make-sparse-keymap)))
348     (define-key toggle-keymap 'button2 (make-modeline-command-wrapper
349                                         'wl-toggle-plugged))
350     (set-extent-keymap extent toggle-keymap)
351     (set-extent-property extent 'help-echo "button2 toggles plugged status")
352     (setq wl-plug-state-indicator-on (cons extent wl-plugged-glyph))
353     (setq wl-plug-state-indicator-off (cons extent wl-unplugged-glyph))
354     (setq wl-plug-state-indicator (if wl-plugged 
355                                       wl-plug-state-indicator-on
356                                     wl-plug-state-indicator-off)))
357   (wl-make-modeline-subr))
358
359 (defun wl-make-date-string ()
360   (let ((s (current-time-string)))
361     (string-match "\\`\\([A-Z][a-z][a-z]\\) +[A-Z][a-z][a-z] +[0-9][0-9]? *[0-9][0-9]?:[0-9][0-9]:[0-9][0-9] *[0-9]?[0-9]?[0-9][0-9]"
362                   s)
363     (concat (wl-match-string 1 s) ", "
364             (timezone-make-date-arpa-standard s (current-time-zone)))))
365
366
367 (defun wl-xmas-setup-folder ()
368   (and (featurep 'scrollbar)
369        (set-specifier scrollbar-height (cons (current-buffer) 0)))
370   (wl-xmas-setup-folder-toolbar))
371
372 (defun wl-xmas-setup-summary ()
373   (make-local-variable 'dragdrop-drop-functions)
374   (setq dragdrop-drop-functions '((wl-dnd-default-drop-message t t)))
375   (and (featurep 'scrollbar)
376        (set-specifier scrollbar-height (cons (current-buffer) 0)))
377   (wl-xmas-setup-summary-toolbar))
378
379 (defun wl-message-overload-functions ()
380   (wl-xmas-setup-message-toolbar)
381   (local-set-key "l" 'wl-message-toggle-disp-summary)
382   (local-set-key 'button2 'wl-message-refer-article-or-url)
383   (local-set-key 'button4 'wl-message-wheel-down)
384   (local-set-key 'button5 'wl-message-wheel-up)
385   (local-set-key [(shift button4)] 'wl-message-wheel-down)
386   (local-set-key [(shift button5)] 'wl-message-wheel-up))
387
388 (defun wl-message-wheel-up (event)
389   (interactive "e")
390   (let ((cur-buf (current-buffer))
391         proceed)
392     (save-selected-window
393       (select-window (event-window event))
394       (set-buffer cur-buf)
395       (setq proceed (wl-message-next-page)))
396     (if proceed
397         (if (memq 'shift (event-modifiers event))
398             (wl-summary-down t)
399           (wl-summary-next t)))))
400
401 (defun wl-message-wheel-down (event)
402   (interactive "e")
403   (let ((cur-buf (current-buffer))
404         proceed)
405     (save-selected-window
406       (select-window (event-window event))
407       (set-buffer cur-buf)
408       (setq proceed (wl-message-prev-page)))
409     (if proceed
410         (if (memq 'shift (event-modifiers event))
411             (wl-summary-up t)
412           (wl-summary-prev t)))))
413
414 (defun wl-draft-overload-menubar ()
415   (add-menu-item '("Mail") "Send, Keep Editing" 
416                  'wl-draft-send t "Send Mail")
417   (add-menu-item '("Mail") "Send Message" 
418                  'wl-draft-send-and-exit t "Send and Exit")
419   (delete-menu-item '("Mail" "Send Mail"))
420   (delete-menu-item '("Mail" "Send and Exit"))
421   )
422
423 (defun wl-draft-mode-setup ()
424   (require 'derived)
425   (define-derived-mode wl-draft-mode mail-mode "Draft"
426     "draft mode for Wanderlust derived from mail mode.
427 See info under Wanderlust for full documentation.
428
429 Special commands:
430 \\{wl-draft-mode-map}"))
431
432 (defun wl-draft-key-setup ()
433   (define-key wl-draft-mode-map "\C-c\C-y" 'wl-draft-yank-original)
434   (define-key wl-draft-mode-map "\C-c\C-s" 'wl-draft-send)
435   (define-key wl-draft-mode-map "\C-c\C-a" 'wl-draft-insert-x-face-field)
436   (define-key wl-draft-mode-map "\C-c\C-c" 'wl-draft-send-and-exit)
437   (define-key wl-draft-mode-map "\C-c\C-z" 'wl-draft-save-and-exit)
438   (define-key wl-draft-mode-map "\C-c\C-k" 'wl-draft-kill)
439   (define-key wl-draft-mode-map "\C-l" 'wl-draft-highlight-and-recenter)
440   (define-key wl-draft-mode-map "\C-i" 'wl-complete-field-body-or-tab)
441   (define-key wl-draft-mode-map "\C-c\C-r" 'wl-draft-caesar-region)
442   (define-key wl-draft-mode-map "\M-t" 'wl-toggle-plugged)
443   (define-key wl-draft-mode-map "\C-c\C-o" 'wl-jump-to-draft-buffer)
444   (define-key wl-draft-mode-map "\C-c\C-e" 'wl-draft-config-exec)
445   (define-key wl-draft-mode-map "\C-c\C-j" 'wl-template-select)
446   (define-key wl-draft-mode-map "\C-c\C-p" 'wl-draft-preview-message)
447   (define-key wl-draft-mode-map "\C-x\C-s" 'wl-draft-save)
448   (define-key wl-draft-mode-map "\C-xk"    'wl-draft-mimic-kill-buffer))
449
450 (defun wl-draft-overload-functions ()
451   (setq mode-line-buffer-identification
452         (format "Wanderlust: %s" (buffer-name)))
453   (local-set-key "\C-c\C-s" 'wl-draft-send) ; override
454   (wl-xmas-setup-draft-toolbar)
455   (wl-draft-overload-menubar)
456   (when wl-show-plug-status-on-modeline
457     (setq mode-line-format (wl-make-modeline))))
458
459 (defalias 'wl-defface 'defface)
460
461 (provide 'wl-xmas)
462
463 ;;; wl-xmas.el ends here