Follow Glenn's lead and update format of Copyright.
[bpt/emacs.git] / lisp / mh-e / mh-tool-bar.el
CommitLineData
dda00b2c
BW
1;;; mh-tool-bar.el --- MH-E tool bar support
2
dcf71371
BW
3;; Copyright (C) 2002, 2003, 2005, 2006, 2007, 2008, 2009
4;; Free Software Foundation, Inc.
dda00b2c
BW
5
6;; Author: Satyaki Das <satyaki@theforce.stanford.edu>
7;; Maintainer: Bill Wohler <wohler@newt.com>
8;; Keywords: mail
9;; See: mh-e.el
10
11;; This file is part of GNU Emacs.
12
5e809f55 13;; GNU Emacs is free software: you can redistribute it and/or modify
dda00b2c 14;; it under the terms of the GNU General Public License as published by
5e809f55
GM
15;; the Free Software Foundation, either version 3 of the License, or
16;; (at your option) any later version.
dda00b2c
BW
17
18;; GNU Emacs is distributed in the hope that it will be useful,
19;; but WITHOUT ANY WARRANTY; without even the implied warranty of
20;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21;; GNU General Public License for more details.
22
23;; You should have received a copy of the GNU General Public License
5e809f55 24;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
dda00b2c
BW
25
26;;; Commentary:
27
28;;; Change Log:
29
30;;; Code:
31
32(require 'mh-e)
f169fdd3
MB
33(mh-do-in-gnu-emacs
34 (require 'tool-bar))
35(mh-do-in-xemacs
36 (require 'toolbar))
dda00b2c
BW
37
38;;; Tool Bar Commands
39
40(defun mh-tool-bar-search (&optional arg)
41 "Interactively call `mh-tool-bar-search-function'.
42Optional argument ARG is not used."
43 (interactive "P")
44 (call-interactively mh-tool-bar-search-function))
45
46(defun mh-tool-bar-customize ()
47 "Call `mh-customize' from the tool bar."
48 (interactive)
49 (mh-customize t))
50
51(defun mh-tool-bar-folder-help ()
52 "Visit \"(mh-e)Top\"."
53 (interactive)
54 (info "(mh-e)Top")
55 (delete-other-windows))
56
57(defun mh-tool-bar-letter-help ()
58 "Visit \"(mh-e)Editing Drafts\"."
59 (interactive)
60 (info "(mh-e)Editing Drafts")
61 (delete-other-windows))
62
63(defmacro mh-tool-bar-reply-generator (function recipient folder-buffer-flag)
64 "Generate FUNCTION that replies to RECIPIENT.
65If FOLDER-BUFFER-FLAG is nil then the function generated...
66When INCLUDE-FLAG is non-nil, include message body being replied to."
67 `(defun ,function (&optional arg)
68 ,(format "Reply to \"%s\".\nWhen ARG is non-nil include message in reply."
69 recipient)
70 (interactive "P")
71 ,(if folder-buffer-flag nil '(set-buffer mh-show-folder-buffer))
72 (mh-reply (mh-get-msg-num nil) ,recipient arg)))
73
74(mh-tool-bar-reply-generator mh-tool-bar-reply-from "from" t)
75(mh-tool-bar-reply-generator mh-show-tool-bar-reply-from "from" nil)
76(mh-tool-bar-reply-generator mh-tool-bar-reply-to "to" t)
77(mh-tool-bar-reply-generator mh-show-tool-bar-reply-to "to" nil)
78(mh-tool-bar-reply-generator mh-tool-bar-reply-all "all" t)
79(mh-tool-bar-reply-generator mh-show-tool-bar-reply-all "all" nil)
80
81\f
82
83;;; Tool Bar Creation
84
d2464a9f
BW
85;; Shush compiler.
86(defvar image-load-path)
87
dda00b2c
BW
88(defmacro mh-tool-bar-define (defaults &rest buttons)
89 "Define a tool bar for MH-E.
90DEFAULTS is the list of buttons that are present by default. It
91is a list of lists where the sublists are of the following form:
92
93 (:KEYWORD FUNC1 FUNC2 FUNC3 ...)
94
95Here :KEYWORD is one of :folder or :letter. If it is :folder then
96the default buttons in the folder and show mode buffers are being
97specified. If it is :letter then the default buttons in the
98letter mode are listed. FUNC1, FUNC2, FUNC3, ... are the names of
99the functions that the buttons would execute.
100
101Each element of BUTTONS is a list consisting of four mandatory
102items and one optional item as follows:
103
104 (FUNCTION MODES ICON DOC &optional ENABLE-EXPR)
105
106where,
107
108 FUNCTION is the name of the function that will be executed when
109 the button is clicked.
110
111 MODES is a list of symbols. List elements must be from \"folder\",
112 \"letter\" and \"sequence\". If \"folder\" is present then the button is
113 available in the folder and show buffer. If the name of FUNCTION is
114 of the form \"mh-foo\", where foo is some arbitrary string, then we
115 check if the function `mh-show-foo' exists. If it exists then that
116 function is used in the show buffer. Otherwise the original function
117 `mh-foo' is used in the show buffer as well. Presence of \"sequence\"
118 is handled similar to the above. The only difference is that the
119 button is shown only when the folder is narrowed to a sequence. If
120 \"letter\" is present in MODES, then the button is available during
121 draft editing and runs FUNCTION when clicked.
122
123 ICON is the icon that is drawn in the button.
124
125 DOC is the documentation for the button. It is used in tool-tips and
126 in providing other help to the user. GNU Emacs uses only the first
127 line of the string. So the DOC should be formatted such that the
128 first line is useful and complete without the rest of the string.
129
130 Optional item ENABLE-EXPR is an arbitrary lisp expression. If it
131 evaluates to nil, then the button is deactivated, otherwise it is
132 active. If it isn't present then the button is always active."
133 ;; The following variable names have been carefully chosen to make code
134 ;; generation easier. Modifying the names should be done carefully.
135 (let (folder-buttons folder-docs folder-button-setter sequence-button-setter
136 show-buttons show-button-setter show-seq-button-setter
137 letter-buttons letter-docs letter-button-setter
138 folder-defaults letter-defaults
139 folder-vectors show-vectors letter-vectors)
140 (dolist (x defaults)
141 (cond ((eq (car x) :folder) (setq folder-defaults (cdr x)))
142 ((eq (car x) :letter) (setq letter-defaults (cdr x)))))
143 (dolist (button buttons)
144 (unless (and (listp button)
145 (or (equal (length button) 4) (equal (length button) 5)))
146 (error "Incorrect MH-E tool-bar button specification: %s" button))
147 (let* ((name (nth 0 button))
148 (name-str (symbol-name name))
149 (icon (nth 2 button))
150 (xemacs-icon (mh-do-in-xemacs
fbe4aef8 151 `(cdr (assoc (quote ,(intern icon)) mh-xemacs-icon-map))))
dda00b2c
BW
152 (full-doc (nth 3 button))
153 (doc (if (string-match "\\(.*\\)\n" full-doc)
154 (match-string 1 full-doc)
155 full-doc))
d36069f0 156 (enable-expr (if (eql (length button) 4) t (nth 4 button)))
dda00b2c
BW
157 (modes (nth 1 button))
158 functions show-sym)
159 (when (memq 'letter modes) (setq functions `(:letter ,name)))
160 (when (or (memq 'folder modes) (memq 'sequence modes))
161 (setq functions
162 (append `(,(if (memq 'folder modes) :folder :sequence) ,name)
163 functions))
164 (setq show-sym
165 (if (string-match "^mh-\\(.*\\)$" name-str)
166 (intern (concat "mh-show-" (match-string 1 name-str)))
167 name))
168 (setq functions
169 (append `(,(if (memq 'folder modes) :show :show-seq)
170 ,(if (fboundp show-sym) show-sym name))
171 functions)))
172 (do ((functions functions (cddr functions)))
173 ((null functions))
174 (let* ((type (car functions))
175 (function (cadr functions))
176 (type1 (substring (symbol-name type) 1))
177 (vector-list (cond ((eq type :show) 'show-vectors)
178 ((eq type :show-seq) 'show-vectors)
179 ((eq type :letter) 'letter-vectors)
180 (t 'folder-vectors)))
181 (list (cond ((eq type :letter) 'mh-tool-bar-letter-buttons)
182 (t 'mh-tool-bar-folder-buttons)))
d2464a9f 183 (key (intern (concat "mh-" type1 "-tool-bar-" name-str)))
dda00b2c
BW
184 (setter (intern (concat type1 "-button-setter")))
185 (mbuttons (cond ((eq type :letter) 'letter-buttons)
186 ((eq type :show) 'show-buttons)
187 ((eq type :show-seq) 'show-buttons)
188 (t 'folder-buttons)))
189 (docs (cond ((eq mbuttons 'letter-buttons) 'letter-docs)
190 ((eq mbuttons 'folder-buttons) 'folder-docs))))
fbe4aef8 191 (add-to-list vector-list `(vector ,xemacs-icon ',function t ,full-doc))
dda00b2c
BW
192 (add-to-list
193 setter `(when (member ',name ,list)
194 (mh-funcall-if-exists
195 tool-bar-add-item ,icon ',function ',key
196 :help ,doc :enable ',enable-expr)))
197 (add-to-list mbuttons name)
198 (if docs (add-to-list docs doc))))))
199 (setq folder-buttons (nreverse folder-buttons)
200 letter-buttons (nreverse letter-buttons)
201 show-buttons (nreverse show-buttons)
202 letter-docs (nreverse letter-docs)
203 folder-docs (nreverse folder-docs)
204 folder-vectors (nreverse folder-vectors)
205 show-vectors (nreverse show-vectors)
206 letter-vectors (nreverse letter-vectors))
207 (dolist (x folder-defaults)
208 (unless (memq x folder-buttons)
efc27af6 209 (error "Folder defaults contains unknown button %s" x)))
dda00b2c
BW
210 (dolist (x letter-defaults)
211 (unless (memq x letter-buttons)
efc27af6 212 (error "Letter defaults contains unknown button %s" x)))
dda00b2c 213 `(eval-when (compile load eval)
dda00b2c
BW
214 ;; GNU Emacs tool bar specific code
215 (mh-do-in-gnu-emacs
d2464a9f
BW
216 (defun mh-buffer-exists-p (mode)
217 "Test whether a buffer with major mode MODE is present."
218 (loop for buf in (buffer-list)
219 when (with-current-buffer buf
220 (eq major-mode mode))
221 return t))
dda00b2c
BW
222 ;; Tool bar initialization functions
223 (defun mh-tool-bar-folder-buttons-init ()
224 (when (mh-buffer-exists-p 'mh-folder-mode)
d2464a9f
BW
225 (let* ((load-path (mh-image-load-path-for-library "mh-e"
226 "mh-logo.xpm"))
227 (image-load-path (cons (car load-path)
228 (when (boundp 'image-load-path)
229 image-load-path))))
230 (setq mh-folder-tool-bar-map
231 (let ((tool-bar-map (make-sparse-keymap)))
232 ,@(nreverse folder-button-setter)
233 tool-bar-map))
234 (setq mh-folder-seq-tool-bar-map
235 (let ((tool-bar-map (copy-keymap mh-folder-tool-bar-map)))
236 ,@(nreverse sequence-button-setter)
237 tool-bar-map))
238 (setq mh-show-tool-bar-map
239 (let ((tool-bar-map (make-sparse-keymap)))
240 ,@(nreverse show-button-setter)
241 tool-bar-map))
242 (setq mh-show-seq-tool-bar-map
243 (let ((tool-bar-map (copy-keymap mh-show-tool-bar-map)))
244 ,@(nreverse show-seq-button-setter)
245 tool-bar-map)))))
dda00b2c
BW
246 (defun mh-tool-bar-letter-buttons-init ()
247 (when (mh-buffer-exists-p 'mh-letter-mode)
d2464a9f
BW
248 (let* ((load-path (mh-image-load-path-for-library "mh-e"
249 "mh-logo.xpm"))
250 (image-load-path (cons (car load-path)
251 (when (boundp 'image-load-path)
252 image-load-path))))
253 (setq mh-letter-tool-bar-map
254 (let ((tool-bar-map (make-sparse-keymap)))
255 ,@(nreverse letter-button-setter)
256 tool-bar-map)))))
dda00b2c 257 ;; Custom setter functions
d2464a9f
BW
258 (defun mh-tool-bar-update (mode default-map sequence-map)
259 "Update `tool-bar-map' in all buffers of MODE.
260Use SEQUENCE-MAP if display is limited; DEFAULT-MAP otherwise."
261 (loop for buf in (buffer-list)
262 do (with-current-buffer buf
263 (if (eq mode major-mode)
264 (let ((map (if mh-folder-view-stack
265 sequence-map
266 default-map)))
267 ;; Yes, make-local-variable is necessary since we
268 ;; get here during initialization when loading
269 ;; mh-e.el, after the +inbox buffer has been
270 ;; created, but before mh-folder-mode has run and
271 ;; created the local map.
272 (set (make-local-variable 'tool-bar-map) map))))))
dda00b2c
BW
273 (defun mh-tool-bar-folder-buttons-set (symbol value)
274 "Construct tool bar for `mh-folder-mode' and `mh-show-mode'."
275 (set-default symbol value)
d2464a9f
BW
276 (mh-tool-bar-folder-buttons-init)
277 (mh-tool-bar-update 'mh-folder-mode mh-folder-tool-bar-map
278 mh-folder-seq-tool-bar-map)
279 (mh-tool-bar-update 'mh-show-mode mh-show-tool-bar-map
280 mh-show-seq-tool-bar-map))
dda00b2c
BW
281 (defun mh-tool-bar-letter-buttons-set (symbol value)
282 "Construct tool bar for `mh-letter-mode'."
283 (set-default symbol value)
d2464a9f
BW
284 (mh-tool-bar-letter-buttons-init)
285 (mh-tool-bar-update 'mh-letter-mode mh-letter-tool-bar-map
286 mh-letter-tool-bar-map)))
dda00b2c
BW
287 ;; XEmacs specific code
288 (mh-do-in-xemacs
289 (defvar mh-tool-bar-folder-vector-map
fbe4aef8
BW
290 (list ,@(loop for button in folder-buttons
291 for vector in folder-vectors
292 collect `(cons ',button ,vector))))
dda00b2c 293 (defvar mh-tool-bar-show-vector-map
fbe4aef8
BW
294 (list ,@(loop for button in show-buttons
295 for vector in show-vectors
296 collect `(cons ',button ,vector))))
dda00b2c 297 (defvar mh-tool-bar-letter-vector-map
fbe4aef8
BW
298 (list ,@(loop for button in letter-buttons
299 for vector in letter-vectors
300 collect `(cons ',button ,vector))))
301 (defvar mh-tool-bar-folder-buttons)
302 (defvar mh-tool-bar-show-buttons)
303 (defvar mh-tool-bar-letter-buttons)
dda00b2c
BW
304 ;; Custom setter functions
305 (defun mh-tool-bar-letter-buttons-set (symbol value)
306 (set-default symbol value)
307 (when mh-xemacs-has-tool-bar-flag
308 (setq mh-tool-bar-letter-buttons
309 (loop for b in value
fbe4aef8
BW
310 collect (cdr
311 (assoc b mh-tool-bar-letter-vector-map))))))
dda00b2c
BW
312 (defun mh-tool-bar-folder-buttons-set (symbol value)
313 (set-default symbol value)
314 (when mh-xemacs-has-tool-bar-flag
315 (setq mh-tool-bar-folder-buttons
316 (loop for b in value
317 collect (cdr (assoc b mh-tool-bar-folder-vector-map))))
318 (setq mh-tool-bar-show-buttons
319 (loop for b in value
320 collect (cdr (assoc b mh-tool-bar-show-vector-map))))))
321 (defun mh-tool-bar-init (mode)
322 "Install tool bar in MODE."
fbe4aef8
BW
323 (when mh-xemacs-use-tool-bar-flag
324 (let ((tool-bar (cond ((eq mode :folder)
325 mh-tool-bar-folder-buttons)
326 ((eq mode :letter)
327 mh-tool-bar-letter-buttons)
328 ((eq mode :show)
329 mh-tool-bar-show-buttons)))
330 (height 37)
331 (width 40)
332 (buffer (current-buffer)))
dda00b2c
BW
333 (cond
334 ((eq mh-xemacs-tool-bar-position 'top)
335 (set-specifier top-toolbar tool-bar buffer)
336 (set-specifier top-toolbar-visible-p t)
337 (set-specifier top-toolbar-height height))
338 ((eq mh-xemacs-tool-bar-position 'bottom)
339 (set-specifier bottom-toolbar tool-bar buffer)
340 (set-specifier bottom-toolbar-visible-p t)
341 (set-specifier bottom-toolbar-height height))
342 ((eq mh-xemacs-tool-bar-position 'left)
343 (set-specifier left-toolbar tool-bar buffer)
344 (set-specifier left-toolbar-visible-p t)
345 (set-specifier left-toolbar-width width))
346 ((eq mh-xemacs-tool-bar-position 'right)
347 (set-specifier right-toolbar tool-bar buffer)
348 (set-specifier right-toolbar-visible-p t)
349 (set-specifier right-toolbar-width width))
350 (t (set-specifier default-toolbar tool-bar buffer)))))))
351 ;; Declare customizable tool bars
352 (custom-declare-variable
353 'mh-tool-bar-folder-buttons
354 '(list ,@(mapcar (lambda (x) `(quote ,x)) folder-defaults))
355 "List of buttons to include in MH-Folder tool bar."
d36069f0
BW
356 :group 'mh-tool-bar
357 :set 'mh-tool-bar-folder-buttons-set
dda00b2c
BW
358 :type '(set ,@(loop for x in folder-buttons
359 for y in folder-docs
23347d76
BW
360 collect `(const :tag ,y ,x)))
361 ;;:package-version '(MH-E "7.1")
362 )
dda00b2c
BW
363 (custom-declare-variable
364 'mh-tool-bar-letter-buttons
365 '(list ,@(mapcar (lambda (x) `(quote ,x)) letter-defaults))
366 "List of buttons to include in MH-Letter tool bar."
d36069f0
BW
367 :group 'mh-tool-bar
368 :set 'mh-tool-bar-letter-buttons-set
dda00b2c
BW
369 :type '(set ,@(loop for x in letter-buttons
370 for y in letter-docs
23347d76
BW
371 collect `(const :tag ,y ,x)))
372 ;;:package-version '(MH-E "7.1")
fbe4aef8 373 ))))
dda00b2c 374
fbe4aef8 375;; The icon names are duplicated in the Makefile and mh-xemacs.el.
dda00b2c 376(mh-tool-bar-define
84b57004
BW
377 ((:folder mh-inc-folder mh-mime-save-parts
378 mh-previous-undeleted-msg mh-page-msg
379 mh-next-undeleted-msg mh-delete-msg mh-refile-msg
efc27af6
BW
380 mh-undo mh-execute-commands mh-toggle-tick mh-reply
381 mh-alias-grab-from-field mh-send mh-rescan-folder
382 mh-tool-bar-search mh-visit-folder
84b57004
BW
383 mh-tool-bar-customize mh-tool-bar-folder-help
384 mh-widen)
385 (:letter mh-send-letter save-buffer mh-fully-kill-draft
386 mh-compose-insertion ispell-message undo
387 clipboard-kill-region clipboard-kill-ring-save
388 clipboard-yank mh-tool-bar-customize
389 mh-tool-bar-letter-help))
efc27af6 390 ;; Folder/Show buffer buttons
84b57004 391 (mh-inc-folder (folder) "mail/inbox" "Incorporate new mail in Inbox
dda00b2c 392This button runs `mh-inc-folder' which drags any
efc27af6
BW
393new mail into your Inbox folder")
394 (mh-mime-save-parts (folder) "attach" "Save MIME parts from this message
dda00b2c 395This button runs `mh-mime-save-parts' which saves a message's
efc27af6
BW
396different parts into separate files")
397 (mh-previous-undeleted-msg (folder) "left-arrow"
398 "Go to the previous undeleted message
dda00b2c 399This button runs `mh-previous-undeleted-msg'")
84b57004 400 (mh-page-msg (folder) "next-page" "Page the current message forwards
efc27af6
BW
401This button runs `mh-page-msg'")
402 (mh-next-undeleted-msg (folder) "right-arrow" "Go to the next undeleted message
403The button runs `mh-next-undeleted-msg'")
84b57004 404 (mh-delete-msg (folder) "delete" "Mark this message for deletion
efc27af6 405This button runs `mh-delete-msg'")
84b57004 406 (mh-refile-msg (folder) "mail/move" "Refile this message
efc27af6
BW
407This button runs `mh-refile-msg'")
408 (mh-undo (folder) "undo" "Undo last operation
409This button runs `undo'"
410 (mh-outstanding-commands-p))
84b57004 411 (mh-execute-commands (folder) "data-save" "Perform moves and deletes
efc27af6
BW
412This button runs `mh-execute-commands'"
413 (mh-outstanding-commands-p))
84b57004 414 (mh-toggle-tick (folder) "mail/flag-for-followup" "Toggle tick mark
efc27af6
BW
415This button runs `mh-toggle-tick'")
416 (mh-toggle-showing (folder) "show" "Toggle showing message
417This button runs `mh-toggle-showing'")
84b57004
BW
418 (mh-reply (folder) "mail/reply" "Reply to this message
419This button runs `mh-reply'")
efc27af6
BW
420 (mh-tool-bar-reply-from (folder) "mail/reply-from" "Reply to \"from\"")
421 (mh-tool-bar-reply-to (folder) "mail/reply-to" "Reply to \"to\"")
422 (mh-tool-bar-reply-all (folder) "mail/reply-all" "Reply to \"all\"")
84b57004 423 (mh-alias-grab-from-field (folder) "contact" "Create alias for sender
efc27af6
BW
424This button runs `mh-alias-grab-from-field'"
425 (and (mh-extract-from-header-value)
426 (not (mh-alias-for-from-p))))
427 (mh-send (folder) "mail/compose" "Compose new message
428This button runs `mh-send'")
429 (mh-rescan-folder (folder) "refresh" "Rescan this folder
430This button runs `mh-rescan-folder'")
431 (mh-pack-folder (folder) "mail/repack" "Repack this folder
432This button runs `mh-pack-folder'")
433 (mh-tool-bar-search (folder) "search" "Search
434This button runs `mh-tool-bar-search-function'")
84b57004 435 (mh-visit-folder (folder) "open" "Visit other folder
efc27af6
BW
436This button runs `mh-visit-folder'")
437 ;; Letter buffer buttons
438 (mh-send-letter (letter) "mail/send" "Send this letter")
efc27af6
BW
439 (save-buffer (letter) "save" "Save current buffer to its file"
440 (buffer-modified-p))
84b57004
BW
441 (mh-fully-kill-draft (letter) "delete" "Kill this draft")
442 (mh-compose-insertion (letter) "attach" "Insert attachment")
443 (ispell-message (letter) "spell" "Check spelling")
efc27af6 444 (undo (letter) "undo" "Undo last operation")
84b57004
BW
445 (clipboard-kill-region (letter) "cut"
446 "Cut (kill) text in region")
447 (clipboard-kill-ring-save (letter) "copy"
448 "Copy text in region")
449 (clipboard-yank (letter) "paste"
450 "Paste (yank) text cut or copied earlier")
efc27af6
BW
451 ;; Common buttons
452 (mh-tool-bar-customize (folder letter) "preferences" "MH-E Preferences")
453 (mh-tool-bar-folder-help (folder) "help" "Help! (general help)
454This button runs `info'")
455 (mh-tool-bar-letter-help (letter) "help" "Help! (general help)
456This button runs `info'")
457 ;; Folder narrowed to sequence buttons
84b57004 458 (mh-widen (sequence) "zoom-out" "Widen from the sequence
efc27af6 459This button runs `mh-widen'"))
dda00b2c
BW
460
461(provide 'mh-tool-bar)
462
463;; Local Variables:
464;; indent-tabs-mode: nil
465;; sentence-end-double-space: nil
466;; End:
467
a1ab640d 468;; arch-tag: 28c2436d-bb8d-486a-a8d7-5a4d9cae3513
dda00b2c 469;;; mh-tool-bar.el ends here