]> code.delx.au - gnu-emacs/blob - lisp/mh-e/mh-show.el
Update copyright notices for 2013.
[gnu-emacs] / lisp / mh-e / mh-show.el
1 ;;; mh-show.el --- MH-Show mode
2
3 ;; Copyright (C) 1993, 1995, 1997, 2000-2013 Free Software Foundation,
4 ;; Inc.
5
6 ;; Author: Bill Wohler <wohler@newt.com>
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
13 ;; GNU Emacs is free software: you can redistribute it and/or modify
14 ;; it under the terms of the GNU General Public License as published by
15 ;; the Free Software Foundation, either version 3 of the License, or
16 ;; (at your option) any later version.
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
24 ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
25
26 ;;; Commentary:
27
28 ;; Mode for showing messages.
29
30 ;;; Change Log:
31
32 ;;; Code:
33
34 (require 'mh-e)
35 (require 'mh-scan)
36
37 ;; Dynamically-created function not found in mh-loaddefs.el.
38 (autoload 'mh-tool-bar-init "mh-tool-bar")
39
40 (require 'font-lock)
41 (require 'gnus-cite)
42 (require 'gnus-util)
43 (require 'goto-addr)
44
45 (autoload 'mh-make-buffer-data "mh-mime") ;can't be automatically generated
46
47 \f
48
49 ;;; MH-Folder Commands
50
51 (defvar mh-showing-with-headers nil
52 "If non-nil, MH-Show buffer contains message with all header fields.
53 If nil, MH-Show buffer contains message processed normally.")
54
55 ;;;###mh-autoload
56 (defun mh-show (&optional message redisplay-flag)
57 "Display message\\<mh-folder-mode-map>.
58
59 If the message under the cursor is already displayed, this command
60 scrolls to the beginning of the message. MH-E normally hides a lot of
61 the superfluous header fields that mailers add to a message, but if
62 you wish to see all of them, use the command \\[mh-header-display].
63
64 Two hooks can be used to control how messages are displayed. The
65 first hook, `mh-show-mode-hook', is called early on in the
66 process of the message display. It is usually used to perform
67 some action on the message's content. The second hook,
68 `mh-show-hook', is the last thing called after messages are
69 displayed. It's used to affect the behavior of MH-E in general or
70 when `mh-show-mode-hook' is too early.
71
72 From a program, optional argument MESSAGE can be used to display an
73 alternative message. The optional argument REDISPLAY-FLAG forces the
74 redisplay of the message even if the show buffer was already
75 displaying the correct message.
76
77 See the \"mh-show\" customization group for a litany of options that
78 control what displayed messages look like."
79 (interactive (list nil t))
80 (when (or redisplay-flag
81 (and mh-showing-with-headers
82 (or mh-mhl-format-file mh-clean-message-header-flag)))
83 (mh-invalidate-show-buffer))
84 (mh-show-msg message))
85
86 ;;;###mh-autoload
87 (defun mh-header-display ()
88 "Display message with all header fields\\<mh-folder-mode-map>.
89
90 Use the command \\[mh-show] to show the message normally again."
91 (interactive)
92 (and (not mh-showing-with-headers)
93 (or mh-mhl-format-file mh-clean-message-header-flag)
94 (mh-invalidate-show-buffer))
95 (let ((mh-decode-mime-flag nil)
96 (mh-mhl-format-file nil)
97 (mh-clean-message-header-flag nil))
98 (mh-show-msg nil)
99 (mh-in-show-buffer (mh-show-buffer)
100 (goto-char (point-min))
101 (mh-recenter 0))
102 (setq mh-showing-with-headers t)))
103
104 ;;;###mh-autoload
105 (defun mh-show-preferred-alternative ()
106 "Display message with the default preferred alternative.
107 This is as if `mm-discouraged-alternatives' is set to nil.
108
109 Use the command \\[mh-show] to show the message normally again."
110 (interactive)
111 (let
112 ((mm-discouraged-alternatives))
113 (mh-show nil t)))
114
115 \f
116
117 ;;; Support Routines for MH-Folder Commands
118
119 ;;;###mh-autoload
120 (defun mh-maybe-show (&optional msg)
121 "Display message at cursor, but only if in show mode.
122 If optional arg MSG is non-nil, display that message instead."
123 (if mh-showing-mode (mh-show msg)))
124
125 (defun mh-show-msg (msg)
126 "Show MSG.
127
128 The hook `mh-show-hook' is called after the message has been
129 displayed."
130 (if (not msg)
131 (setq msg (mh-get-msg-num t)))
132 (mh-showing-mode t)
133 (setq mh-page-to-next-msg-flag nil)
134 (let ((folder mh-current-folder)
135 (folders (list mh-current-folder))
136 (clean-message-header mh-clean-message-header-flag)
137 (show-window (get-buffer-window mh-show-buffer))
138 (display-mime-buttons-flag mh-display-buttons-for-inline-parts-flag))
139 (if (not (eq (next-window (minibuffer-window)) (selected-window)))
140 (delete-other-windows)) ; force ourself to the top window
141 (mh-in-show-buffer (mh-show-buffer)
142 (setq mh-display-buttons-for-inline-parts-flag display-mime-buttons-flag)
143 (if (and show-window
144 (equal (mh-msg-filename msg folder) buffer-file-name))
145 (progn ;just back up to start
146 (goto-char (point-min))
147 (if (not clean-message-header)
148 (mh-start-of-uncleaned-message)))
149 (mh-display-msg msg folder)))
150 (unless (mh-window-full-height-p) ; not vertically split
151 (shrink-window (- (window-height) (or mh-summary-height
152 (mh-summary-height)))))
153 (mh-recenter nil)
154 ;; The following line is a nop which forces update of the scan line so
155 ;; that font-lock will update it (if needed)...
156 (mh-notate nil nil mh-cmd-note)
157 (if (not (memq msg mh-seen-list))
158 (setq mh-seen-list (cons msg mh-seen-list)))
159 (when mh-update-sequences-after-mh-show-flag
160 (mh-update-sequences)
161 (when mh-index-data
162 (setq folders
163 (append (mh-index-delete-from-sequence mh-unseen-seq (list msg))
164 folders)))
165 (when (mh-speed-flists-active-p)
166 (apply #'mh-speed-flists t folders)))
167 (run-hooks 'mh-show-hook)))
168
169 ;;;###mh-autoload
170 (defun mh-start-of-uncleaned-message ()
171 "Position uninteresting headers off the top of the window."
172 (let ((case-fold-search t))
173 (re-search-forward
174 "^To:\\|^Cc:\\|^From:\\|^Subject:\\|^Date:" nil t)
175 (beginning-of-line)
176 (mh-recenter 0)))
177
178 (defvar mh-show-buffer-mode-line-buffer-id " {show-%s} %d"
179 "Format string to produce `mode-line-buffer-identification' for show buffers.
180
181 First argument is folder name. Second is message number.")
182
183 ;;;###mh-autoload
184 (defun mh-display-msg (msg-num folder-name)
185 "Display MSG-NUM of FOLDER-NAME.
186 Sets the current buffer to the show buffer."
187 (let ((folder (mh-msg-folder folder-name)))
188 (set-buffer folder)
189 ;; When Gnus uses external displayers it has to keep handles longer. So
190 ;; we will delete these handles when mh-quit is called on the folder. It
191 ;; would be nicer if there are weak pointers in emacs lisp, then we could
192 ;; get the garbage collector to do this for us.
193 (unless (mh-buffer-data)
194 (setf (mh-buffer-data) (mh-make-buffer-data)))
195 ;; Bind variables in folder buffer in case they are local
196 (let ((formfile mh-mhl-format-file)
197 (clean-message-header mh-clean-message-header-flag)
198 (invisible-headers mh-invisible-header-fields-compiled)
199 (visible-headers nil)
200 (msg-filename (mh-msg-filename msg-num folder-name))
201 (show-buffer mh-show-buffer)
202 (mm-inline-media-tests mh-mm-inline-media-tests))
203 (if (not (file-exists-p msg-filename))
204 (error "Message %d does not exist" msg-num))
205 (if (and (> mh-show-maximum-size 0)
206 (> (elt (file-attributes msg-filename) 7)
207 mh-show-maximum-size)
208 (not (y-or-n-p
209 (format
210 "Message %d (%d bytes) exceeds %d bytes. Display it? "
211 msg-num (elt (file-attributes msg-filename) 7)
212 mh-show-maximum-size))))
213 (error "Message %d not displayed" msg-num))
214 (set-buffer show-buffer)
215 (cond ((not (equal msg-filename buffer-file-name))
216 (mh-unvisit-file)
217 (setq buffer-read-only nil)
218 ;; Cleanup old mime handles
219 (mh-mime-cleanup)
220 (erase-buffer)
221 ;; Changing contents, so this hook needs to be reinitialized.
222 ;; pgp.el uses this.
223 (if (boundp 'write-contents-hooks) ;Emacs 19
224 (kill-local-variable 'write-contents-hooks))
225 (if formfile
226 (mh-exec-lib-cmd-output "mhl" "-nobell" "-noclear"
227 (if (stringp formfile)
228 (list "-form" formfile))
229 msg-filename)
230 (insert-file-contents-literally msg-filename))
231 ;; Use mm to display buffer
232 (when (and mh-decode-mime-flag (not formfile))
233 (mh-add-missing-mime-version-header)
234 (setf (mh-buffer-data) (mh-make-buffer-data))
235 (mh-mime-display))
236 (mh-show-mode)
237 ;; Header cleanup
238 (goto-char (point-min))
239 (cond (clean-message-header
240 (mh-clean-msg-header (point-min)
241 invisible-headers
242 visible-headers)
243 (goto-char (point-min)))
244 (t
245 (mh-start-of-uncleaned-message)))
246 (mh-decode-message-header)
247 ;; the parts of visiting we want to do (no locking)
248 (or (eq buffer-undo-list t) ;don't save undo info for prev msgs
249 (setq buffer-undo-list nil))
250 (set-buffer-auto-saved)
251 ;; the parts of set-visited-file-name we want to do (no locking)
252 (setq buffer-file-name msg-filename)
253 (setq buffer-backed-up nil)
254 (auto-save-mode 1)
255 (set-mark nil)
256 (unwind-protect
257 (when (and mh-decode-mime-flag (not formfile))
258 (setq buffer-read-only nil)
259 (mh-display-smileys)
260 (mh-display-emphasis))
261 (setq buffer-read-only t))
262 (set-buffer-modified-p nil)
263 (setq mh-show-folder-buffer folder)
264 (setq mode-line-buffer-identification
265 (list (format mh-show-buffer-mode-line-buffer-id
266 folder-name msg-num)))
267 (mh-logo-display)
268 (set-buffer folder)
269 (setq mh-showing-with-headers nil))))))
270
271 (defun mh-msg-folder (folder-name)
272 "Return the name of the buffer for FOLDER-NAME."
273 folder-name)
274
275 ;;;###mh-autoload
276 (defun mh-clean-msg-header (start invisible-headers visible-headers)
277 "Flush extraneous lines in message header.
278
279 Header is cleaned from START to the end of the message header.
280 INVISIBLE-HEADERS contains a regular expression specifying lines
281 to delete from the header. VISIBLE-HEADERS contains a regular
282 expression specifying the lines to display. INVISIBLE-HEADERS is
283 ignored if VISIBLE-HEADERS is non-nil."
284 ;; XXX Note that MH-E no longer supports the `mh-visible-headers'
285 ;; variable, so this function could be trimmed of this feature too."
286 (let ((case-fold-search t)
287 (buffer-read-only nil))
288 (save-restriction
289 (goto-char start)
290 (if (search-forward "\n\n" nil 'move)
291 (backward-char 1))
292 (narrow-to-region start (point))
293 (goto-char (point-min))
294 (if visible-headers
295 (while (< (point) (point-max))
296 (cond ((looking-at visible-headers)
297 (forward-line 1)
298 (while (looking-at "[ \t]") (forward-line 1)))
299 (t
300 (mh-delete-line 1)
301 (while (looking-at "[ \t]")
302 (mh-delete-line 1)))))
303 (while (re-search-forward invisible-headers nil t)
304 (beginning-of-line)
305 (mh-delete-line 1)
306 (while (looking-at "[ \t]")
307 (mh-delete-line 1)))))
308 (let ((mh-compose-skipped-header-fields ()))
309 (mh-letter-hide-all-skipped-fields))
310 (unlock-buffer)))
311
312 ;;;###mh-autoload
313 (defun mh-invalidate-show-buffer ()
314 "Invalidate the show buffer so we must update it to use it."
315 (if (get-buffer mh-show-buffer)
316 (with-current-buffer mh-show-buffer
317 (mh-unvisit-file))))
318
319 (defun mh-unvisit-file ()
320 "Separate current buffer from the message file it was visiting."
321 (or (not (buffer-modified-p))
322 (null buffer-file-name) ;we've been here before
323 (yes-or-no-p (format "Message %s modified; discard changes? "
324 (file-name-nondirectory buffer-file-name)))
325 (error "Changes preserved"))
326 (clear-visited-file-modtime)
327 (unlock-buffer)
328 (setq buffer-file-name nil))
329
330 (defun mh-summary-height ()
331 "Return ideal value for the variable `mh-summary-height'.
332 The current frame height is taken into consideration."
333 (or (and (fboundp 'frame-height)
334 (> (frame-height) 24)
335 (min 10 (/ (frame-height) 6)))
336 4))
337
338 \f
339
340 ;; Infrastructure to generate show-buffer functions from folder functions
341 ;; XEmacs does not have deactivate-mark? What is the equivalent of
342 ;; transient-mark-mode for XEmacs? Should we be restoring the mark in the
343 ;; folder buffer after the operation has been carried out.
344 (defmacro mh-defun-show-buffer (function original-function
345 &optional dont-return)
346 "Define FUNCTION to run ORIGINAL-FUNCTION in folder buffer.
347 If the buffer we start in is still visible and DONT-RETURN is nil
348 then switch to it after that."
349 `(defun ,function ()
350 ,(format "Calls %s from the message's folder.\n%s\nSee `%s' for more info.\n"
351 original-function
352 (if dont-return ""
353 "When function completes, returns to the show buffer if it is
354 still visible.\n")
355 original-function)
356 (interactive)
357 (when (buffer-live-p (get-buffer mh-show-folder-buffer))
358 (let ((config (current-window-configuration))
359 (folder-buffer mh-show-folder-buffer)
360 (normal-exit nil)
361 ,@(if dont-return () '((cur-buffer-name (buffer-name)))))
362 (pop-to-buffer mh-show-folder-buffer nil)
363 (unless (equal (buffer-name
364 (window-buffer (frame-first-window (selected-frame))))
365 folder-buffer)
366 (delete-other-windows))
367 (mh-goto-cur-msg t)
368 (mh-funcall-if-exists deactivate-mark)
369 (unwind-protect
370 (prog1 (call-interactively (function ,original-function))
371 (setq normal-exit t))
372 (mh-funcall-if-exists deactivate-mark)
373 (when (eq major-mode 'mh-folder-mode)
374 (mh-funcall-if-exists hl-line-highlight))
375 (cond ((not normal-exit)
376 (set-window-configuration config))
377 ,(if dont-return
378 `(t (setq mh-previous-window-config config))
379 `((and (get-buffer cur-buffer-name)
380 (window-live-p (get-buffer-window
381 (get-buffer cur-buffer-name))))
382 (pop-to-buffer (get-buffer cur-buffer-name) nil)))))))))
383
384 ;; Generate interactive functions for the show buffer from the corresponding
385 ;; folder functions.
386 (mh-defun-show-buffer mh-show-previous-undeleted-msg
387 mh-previous-undeleted-msg)
388 (mh-defun-show-buffer mh-show-next-undeleted-msg
389 mh-next-undeleted-msg)
390 (mh-defun-show-buffer mh-show-quit mh-quit)
391 (mh-defun-show-buffer mh-show-delete-msg mh-delete-msg)
392 (mh-defun-show-buffer mh-show-refile-msg mh-refile-msg)
393 (mh-defun-show-buffer mh-show-undo mh-undo)
394 (mh-defun-show-buffer mh-show-execute-commands mh-execute-commands)
395 (mh-defun-show-buffer mh-show-reply mh-reply t)
396 (mh-defun-show-buffer mh-show-redistribute mh-redistribute)
397 (mh-defun-show-buffer mh-show-forward mh-forward t)
398 (mh-defun-show-buffer mh-show-header-display mh-header-display)
399 (mh-defun-show-buffer mh-show-refile-or-write-again
400 mh-refile-or-write-again)
401 (mh-defun-show-buffer mh-show-show mh-show)
402 (mh-defun-show-buffer mh-show-show-preferred-alternative mh-show-preferred-alternative)
403 (mh-defun-show-buffer mh-show-write-message-to-file
404 mh-write-msg-to-file)
405 (mh-defun-show-buffer mh-show-extract-rejected-mail
406 mh-extract-rejected-mail t)
407 (mh-defun-show-buffer mh-show-delete-msg-no-motion
408 mh-delete-msg-no-motion)
409 (mh-defun-show-buffer mh-show-first-msg mh-first-msg)
410 (mh-defun-show-buffer mh-show-last-msg mh-last-msg)
411 (mh-defun-show-buffer mh-show-copy-msg mh-copy-msg)
412 (mh-defun-show-buffer mh-show-edit-again mh-edit-again t)
413 (mh-defun-show-buffer mh-show-goto-msg mh-goto-msg)
414 (mh-defun-show-buffer mh-show-inc-folder mh-inc-folder)
415 (mh-defun-show-buffer mh-show-delete-subject-or-thread
416 mh-delete-subject-or-thread)
417 (mh-defun-show-buffer mh-show-delete-subject mh-delete-subject)
418 (mh-defun-show-buffer mh-show-print-msg mh-print-msg)
419 (mh-defun-show-buffer mh-show-send mh-send t)
420 (mh-defun-show-buffer mh-show-toggle-showing mh-toggle-showing t)
421 (mh-defun-show-buffer mh-show-pipe-msg mh-pipe-msg t)
422 (mh-defun-show-buffer mh-show-sort-folder mh-sort-folder)
423 (mh-defun-show-buffer mh-show-visit-folder mh-visit-folder t)
424 (mh-defun-show-buffer mh-show-rescan-folder mh-rescan-folder)
425 (mh-defun-show-buffer mh-show-pack-folder mh-pack-folder)
426 (mh-defun-show-buffer mh-show-kill-folder mh-kill-folder t)
427 (mh-defun-show-buffer mh-show-list-folders mh-list-folders t)
428 (mh-defun-show-buffer mh-show-undo-folder mh-undo-folder)
429 (mh-defun-show-buffer mh-show-delete-msg-from-seq
430 mh-delete-msg-from-seq)
431 (mh-defun-show-buffer mh-show-delete-seq mh-delete-seq)
432 (mh-defun-show-buffer mh-show-list-sequences mh-list-sequences)
433 (mh-defun-show-buffer mh-show-narrow-to-seq mh-narrow-to-seq)
434 (mh-defun-show-buffer mh-show-put-msg-in-seq mh-put-msg-in-seq)
435 (mh-defun-show-buffer mh-show-msg-is-in-seq mh-msg-is-in-seq)
436 (mh-defun-show-buffer mh-show-widen mh-widen)
437 (mh-defun-show-buffer mh-show-narrow-to-subject mh-narrow-to-subject)
438 (mh-defun-show-buffer mh-show-narrow-to-from mh-narrow-to-from)
439 (mh-defun-show-buffer mh-show-narrow-to-cc mh-narrow-to-cc)
440 (mh-defun-show-buffer mh-show-narrow-to-range mh-narrow-to-range)
441 (mh-defun-show-buffer mh-show-narrow-to-to mh-narrow-to-to)
442 (mh-defun-show-buffer mh-show-store-msg mh-store-msg)
443 (mh-defun-show-buffer mh-show-page-digest mh-page-digest)
444 (mh-defun-show-buffer mh-show-page-digest-backwards
445 mh-page-digest-backwards)
446 (mh-defun-show-buffer mh-show-burst-digest mh-burst-digest)
447 (mh-defun-show-buffer mh-show-page-msg mh-page-msg)
448 (mh-defun-show-buffer mh-show-previous-page mh-previous-page)
449 (mh-defun-show-buffer mh-show-modify mh-modify t)
450 (mh-defun-show-buffer mh-show-next-button mh-next-button)
451 (mh-defun-show-buffer mh-show-prev-button mh-prev-button)
452 (mh-defun-show-buffer mh-show-toggle-mime-part mh-folder-toggle-mime-part)
453 (mh-defun-show-buffer mh-show-save-mime-part mh-folder-save-mime-part)
454 (mh-defun-show-buffer mh-show-inline-mime-part mh-folder-inline-mime-part)
455 (mh-defun-show-buffer mh-show-toggle-threads mh-toggle-threads)
456 (mh-defun-show-buffer mh-show-thread-delete mh-thread-delete)
457 (mh-defun-show-buffer mh-show-thread-refile mh-thread-refile)
458 (mh-defun-show-buffer mh-show-update-sequences mh-update-sequences)
459 (mh-defun-show-buffer mh-show-next-unread-msg mh-next-unread-msg)
460 (mh-defun-show-buffer mh-show-previous-unread-msg mh-previous-unread-msg)
461 (mh-defun-show-buffer mh-show-thread-ancestor mh-thread-ancestor)
462 (mh-defun-show-buffer mh-show-thread-next-sibling mh-thread-next-sibling)
463 (mh-defun-show-buffer mh-show-thread-previous-sibling
464 mh-thread-previous-sibling)
465 (mh-defun-show-buffer mh-show-index-visit-folder mh-index-visit-folder t)
466 (mh-defun-show-buffer mh-show-toggle-tick mh-toggle-tick)
467 (mh-defun-show-buffer mh-show-narrow-to-tick mh-narrow-to-tick)
468 (mh-defun-show-buffer mh-show-junk-blacklist mh-junk-blacklist)
469 (mh-defun-show-buffer mh-show-junk-whitelist mh-junk-whitelist)
470 (mh-defun-show-buffer mh-show-index-new-messages mh-index-new-messages)
471 (mh-defun-show-buffer mh-show-index-ticked-messages mh-index-ticked-messages)
472 (mh-defun-show-buffer mh-show-index-sequenced-messages
473 mh-index-sequenced-messages)
474 (mh-defun-show-buffer mh-show-catchup mh-catchup)
475 (mh-defun-show-buffer mh-show-ps-print-toggle-color mh-ps-print-toggle-color)
476 (mh-defun-show-buffer mh-show-ps-print-toggle-faces mh-ps-print-toggle-faces)
477 (mh-defun-show-buffer mh-show-ps-print-msg-file mh-ps-print-msg-file)
478 (mh-defun-show-buffer mh-show-ps-print-msg mh-ps-print-msg)
479 (mh-defun-show-buffer mh-show-toggle-mime-buttons mh-toggle-mime-buttons)
480 (mh-defun-show-buffer mh-show-display-with-external-viewer
481 mh-display-with-external-viewer)
482
483 \f
484
485 ;;; Sequence Menu
486
487 (easy-menu-define
488 mh-show-sequence-menu mh-show-mode-map "Menu for MH-E folder-sequence."
489 '("Sequence"
490 ["Add Message to Sequence..." mh-show-put-msg-in-seq t]
491 ["List Sequences for Message" mh-show-msg-is-in-seq t]
492 ["Delete Message from Sequence..." mh-show-delete-msg-from-seq t]
493 ["List Sequences in Folder..." mh-show-list-sequences t]
494 ["Delete Sequence..." mh-show-delete-seq t]
495 ["Narrow to Sequence..." mh-show-narrow-to-seq t]
496 ["Widen from Sequence" mh-show-widen t]
497 "--"
498 ["Narrow to Subject Sequence" mh-show-narrow-to-subject t]
499 ["Narrow to Tick Sequence" mh-show-narrow-to-tick
500 (with-current-buffer mh-show-folder-buffer
501 (and mh-tick-seq (mh-seq-msgs (mh-find-seq mh-tick-seq))))]
502 ["Delete Rest of Same Subject" mh-show-delete-subject t]
503 ["Toggle Tick Mark" mh-show-toggle-tick t]
504 "--"
505 ["Push State Out to MH" mh-show-update-sequences t]))
506
507 ;;; Message Menu
508
509 (easy-menu-define
510 mh-show-message-menu mh-show-mode-map "Menu for MH-E folder-message."
511 '("Message"
512 ["Show Message" mh-show-show t]
513 ["Show Message with Header" mh-show-header-display t]
514 ["Show Message with Preferred Alternative"
515 mh-show-show-preferred-alternative t]
516 ["Next Message" mh-show-next-undeleted-msg t]
517 ["Previous Message" mh-show-previous-undeleted-msg t]
518 ["Go to First Message" mh-show-first-msg t]
519 ["Go to Last Message" mh-show-last-msg t]
520 ["Go to Message by Number..." mh-show-goto-msg t]
521 ["Modify Message" mh-show-modify t]
522 ["Delete Message" mh-show-delete-msg t]
523 ["Refile Message" mh-show-refile-msg t]
524 ["Undo Delete/Refile" mh-show-undo t]
525 ["Process Delete/Refile" mh-show-execute-commands t]
526 "--"
527 ["Compose a New Message" mh-send t]
528 ["Reply to Message..." mh-show-reply t]
529 ["Forward Message..." mh-show-forward t]
530 ["Redistribute Message..." mh-show-redistribute t]
531 ["Edit Message Again" mh-show-edit-again t]
532 ["Re-edit a Bounced Message" mh-show-extract-rejected-mail t]
533 "--"
534 ["Copy Message to Folder..." mh-show-copy-msg t]
535 ["Print Message" mh-show-print-msg t]
536 ["Write Message to File..." mh-show-write-msg-to-file t]
537 ["Pipe Message to Command..." mh-show-pipe-msg t]
538 ["Unpack Uuencoded Message..." mh-show-store-msg t]
539 ["Burst Digest Message" mh-show-burst-digest t]))
540
541 ;;; Folder Menu
542
543 (easy-menu-define
544 mh-show-folder-menu mh-show-mode-map "Menu for MH-E folder."
545 '("Folder"
546 ["Incorporate New Mail" mh-show-inc-folder t]
547 ["Toggle Show/Folder" mh-show-toggle-showing t]
548 ["Execute Delete/Refile" mh-show-execute-commands t]
549 ["Rescan Folder" mh-show-rescan-folder t]
550 ["Thread Folder" mh-show-toggle-threads t]
551 ["Pack Folder" mh-show-pack-folder t]
552 ["Sort Folder" mh-show-sort-folder t]
553 "--"
554 ["List Folders" mh-show-list-folders t]
555 ["Visit a Folder..." mh-show-visit-folder t]
556 ["View New Messages" mh-show-index-new-messages t]
557 ["Search..." mh-search t]
558 "--"
559 ["Quit MH-E" mh-quit t]))
560
561 \f
562
563 ;;; MH-Show Keys
564
565 (gnus-define-keys mh-show-mode-map
566 " " mh-show-page-msg
567 "!" mh-show-refile-or-write-again
568 "'" mh-show-toggle-tick
569 "," mh-show-header-display
570 "." mh-show-show
571 ":" mh-show-show-preferred-alternative
572 ">" mh-show-write-message-to-file
573 "?" mh-help
574 "E" mh-show-extract-rejected-mail
575 "M" mh-show-modify
576 "\177" mh-show-previous-page
577 "\C-d" mh-show-delete-msg-no-motion
578 "\t" mh-show-next-button
579 [backtab] mh-show-prev-button
580 "\M-\t" mh-show-prev-button
581 "\ed" mh-show-redistribute
582 "^" mh-show-refile-msg
583 "c" mh-show-copy-msg
584 "d" mh-show-delete-msg
585 "e" mh-show-edit-again
586 "f" mh-show-forward
587 "g" mh-show-goto-msg
588 "i" mh-show-inc-folder
589 "k" mh-show-delete-subject-or-thread
590 "m" mh-show-send
591 "n" mh-show-next-undeleted-msg
592 "\M-n" mh-show-next-unread-msg
593 "o" mh-show-refile-msg
594 "p" mh-show-previous-undeleted-msg
595 "\M-p" mh-show-previous-unread-msg
596 "q" mh-show-quit
597 "r" mh-show-reply
598 "s" mh-show-send
599 "t" mh-show-toggle-showing
600 "u" mh-show-undo
601 "x" mh-show-execute-commands
602 "v" mh-show-index-visit-folder
603 "|" mh-show-pipe-msg)
604
605 (gnus-define-keys (mh-show-folder-map "F" mh-show-mode-map)
606 "?" mh-prefix-help
607 "'" mh-index-ticked-messages
608 "S" mh-show-sort-folder
609 "c" mh-show-catchup
610 "f" mh-show-visit-folder
611 "k" mh-show-kill-folder
612 "l" mh-show-list-folders
613 "n" mh-index-new-messages
614 "o" mh-show-visit-folder
615 "q" mh-show-index-sequenced-messages
616 "r" mh-show-rescan-folder
617 "s" mh-search
618 "t" mh-show-toggle-threads
619 "u" mh-show-undo-folder
620 "v" mh-show-visit-folder)
621
622 (gnus-define-keys (mh-show-sequence-map "S" mh-show-mode-map)
623 "'" mh-show-narrow-to-tick
624 "?" mh-prefix-help
625 "d" mh-show-delete-msg-from-seq
626 "k" mh-show-delete-seq
627 "l" mh-show-list-sequences
628 "n" mh-show-narrow-to-seq
629 "p" mh-show-put-msg-in-seq
630 "s" mh-show-msg-is-in-seq
631 "w" mh-show-widen)
632
633 (define-key mh-show-mode-map "I" mh-inc-spool-map)
634
635 (gnus-define-keys (mh-show-junk-map "J" mh-show-mode-map)
636 "?" mh-prefix-help
637 "b" mh-show-junk-blacklist
638 "w" mh-show-junk-whitelist)
639
640 (gnus-define-keys (mh-show-ps-print-map "P" mh-show-mode-map)
641 "?" mh-prefix-help
642 "C" mh-show-ps-print-toggle-color
643 "F" mh-show-ps-print-toggle-faces
644 "f" mh-show-ps-print-msg-file
645 "l" mh-show-print-msg
646 "p" mh-show-ps-print-msg)
647
648 (gnus-define-keys (mh-show-thread-map "T" mh-show-mode-map)
649 "?" mh-prefix-help
650 "u" mh-show-thread-ancestor
651 "p" mh-show-thread-previous-sibling
652 "n" mh-show-thread-next-sibling
653 "t" mh-show-toggle-threads
654 "d" mh-show-thread-delete
655 "o" mh-show-thread-refile)
656
657 (gnus-define-keys (mh-show-limit-map "/" mh-show-mode-map)
658 "'" mh-show-narrow-to-tick
659 "?" mh-prefix-help
660 "c" mh-show-narrow-to-cc
661 "g" mh-show-narrow-to-range
662 "m" mh-show-narrow-to-from
663 "s" mh-show-narrow-to-subject
664 "t" mh-show-narrow-to-to
665 "w" mh-show-widen)
666
667 (gnus-define-keys (mh-show-extract-map "X" mh-show-mode-map)
668 "?" mh-prefix-help
669 "s" mh-show-store-msg
670 "u" mh-show-store-msg)
671
672 (gnus-define-keys (mh-show-digest-map "D" mh-show-mode-map)
673 "?" mh-prefix-help
674 " " mh-show-page-digest
675 "\177" mh-show-page-digest-backwards
676 "b" mh-show-burst-digest)
677
678 (gnus-define-keys (mh-show-mime-map "K" mh-show-mode-map)
679 "?" mh-prefix-help
680 "a" mh-mime-save-parts
681 "e" mh-show-display-with-external-viewer
682 "v" mh-show-toggle-mime-part
683 "o" mh-show-save-mime-part
684 "i" mh-show-inline-mime-part
685 "t" mh-show-toggle-mime-buttons
686 "\t" mh-show-next-button
687 [backtab] mh-show-prev-button
688 "\M-\t" mh-show-prev-button)
689
690 \f
691
692 ;;; MH-Show Font Lock
693
694 (defun mh-header-field-font-lock (field limit)
695 "Return the value of a header field FIELD to font-lock.
696 Argument LIMIT limits search."
697 (if (= (point) limit)
698 nil
699 (let* ((mail-header-end (mh-mail-header-end))
700 (lesser-limit (if (< mail-header-end limit) mail-header-end limit))
701 (case-fold-search t))
702 (when (and (< (point) mail-header-end) ;Only within header
703 (re-search-forward (format "^%s" field) lesser-limit t))
704 (let ((match-one-b (match-beginning 0))
705 (match-one-e (match-end 0)))
706 (mh-header-field-end)
707 (if (> (point) limit) ;Don't search for end beyond limit
708 (goto-char limit))
709 (set-match-data (list match-one-b match-one-e
710 (1+ match-one-e) (point)))
711 t)))))
712
713 (defun mh-header-to-font-lock (limit)
714 "Return the value of a header field To to font-lock.
715 Argument LIMIT limits search."
716 (mh-header-field-font-lock "To:" limit))
717
718 (defun mh-header-cc-font-lock (limit)
719 "Return the value of a header field cc to font-lock.
720 Argument LIMIT limits search."
721 (mh-header-field-font-lock "cc:" limit))
722
723 (defun mh-header-subject-font-lock (limit)
724 "Return the value of a header field Subject to font-lock.
725 Argument LIMIT limits search."
726 (mh-header-field-font-lock "Subject:" limit))
727
728 (defun mh-letter-header-font-lock (limit)
729 "Return the entire mail header to font-lock.
730 Argument LIMIT limits search."
731 (if (= (point) limit)
732 nil
733 (let* ((mail-header-end (save-match-data (mh-mail-header-end)))
734 (lesser-limit (if (< mail-header-end limit) mail-header-end limit)))
735 (when (mh-in-header-p)
736 (set-match-data (list 1 lesser-limit))
737 (goto-char lesser-limit)
738 t))))
739
740 (defun mh-show-font-lock-fontify-region (beg end loudly)
741 "Limit font-lock in `mh-show-mode' to the header.
742
743 Used when the option `mh-highlight-citation-style' is set to
744 \"Gnus\", leaving the body to be dealt with by Gnus highlighting.
745 The region between BEG and END is given over to be fontified and
746 LOUDLY controls if a user sees a message about the fontification
747 operation."
748 (let ((header-end (mh-mail-header-end)))
749 (cond
750 ((and (< beg header-end)(< end header-end))
751 (font-lock-default-fontify-region beg end loudly))
752 ((and (< beg header-end)(>= end header-end))
753 (font-lock-default-fontify-region beg header-end loudly))
754 (t
755 nil))))
756
757 (defvar mh-show-font-lock-keywords
758 '(("^\\(From:\\|Sender:\\)\\(.*\\)"
759 (1 'default)
760 (2 'mh-show-from))
761 (mh-header-to-font-lock
762 (0 'default)
763 (1 'mh-show-to))
764 (mh-header-cc-font-lock
765 (0 'default)
766 (1 'mh-show-cc))
767 ("^\\(Reply-To:\\|Return-Path:\\)\\(.*\\)$"
768 (1 'default)
769 (2 'mh-show-from))
770 (mh-header-subject-font-lock
771 (0 'default)
772 (1 'mh-show-subject))
773 ("^\\(Apparently-To:\\|Newsgroups:\\)\\(.*\\)"
774 (1 'default)
775 (2 'mh-show-cc))
776 ("^\\(In-reply-to\\|Date\\):\\(.*\\)$"
777 (1 'default)
778 (2 'mh-show-date))
779 (mh-letter-header-font-lock
780 (0 'mh-show-header append t)))
781 "Additional expressions to highlight in MH-Show buffers.")
782
783 ;;;###mh-autoload
784 (defun mh-show-font-lock-keywords ()
785 "Return variable `mh-show-font-lock-keywords'."
786 mh-show-font-lock-keywords)
787
788 (defvar mh-show-font-lock-keywords-with-cite
789 (let* ((cite-chars "[>|}]")
790 (cite-prefix "A-Za-z")
791 (cite-suffix (concat cite-prefix "0-9_.@-`'\"")))
792 (append
793 mh-show-font-lock-keywords
794 (list
795 ;; Use MATCH-ANCHORED to effectively anchor the regexp left side.
796 `(,cite-chars
797 (,(concat "\\=[ \t]*"
798 "\\(\\([" cite-prefix "]+[" cite-suffix "]*\\)?"
799 "\\(" cite-chars "[ \t]*\\)\\)+"
800 "\\(.*\\)")
801 (beginning-of-line) (end-of-line)
802 (2 font-lock-constant-face nil t)
803 (4 font-lock-comment-face nil t))))))
804 "Additional expressions to highlight in MH-Show buffers.")
805
806 ;;;###mh-autoload
807 (defun mh-show-font-lock-keywords-with-cite ()
808 "Return variable `mh-show-font-lock-keywords-with-cite'."
809 mh-show-font-lock-keywords-with-cite)
810
811 \f
812
813 ;;; MH-Show Mode
814
815 ;; Ensure new buffers won't get this mode if default major-mode is nil.
816 (put 'mh-show-mode 'mode-class 'special)
817
818 ;; Shush compiler.
819 (defvar font-lock-auto-fontify)
820
821 ;;;###mh-autoload
822 (define-derived-mode mh-show-mode text-mode "MH-Show"
823 "Major mode for showing messages in MH-E.\\<mh-show-mode-map>
824
825 Email addresses and URLs in the message are highlighted if the
826 option `goto-address-highlight-p' is on, which it is by default.
827 To view the web page for a highlighted URL or to send a message
828 using a highlighted email address, use the middle mouse button or
829 \\[goto-address-at-point]. See Info node `(mh-e)Sending Mail' to
830 see how to configure Emacs to send the message using MH-E.
831
832 The hook `mh-show-mode-hook' is called upon entry to this mode.
833
834 See also `mh-folder-mode'.
835
836 \\{mh-show-mode-map}"
837 (mh-do-in-gnu-emacs
838 (if (boundp 'tool-bar-map)
839 (set (make-local-variable 'tool-bar-map) mh-show-tool-bar-map)))
840 (mh-do-in-xemacs
841 (mh-tool-bar-init :show))
842 (set (make-local-variable 'mail-header-separator) mh-mail-header-separator)
843 (setq paragraph-start (default-value 'paragraph-start))
844 (mh-show-unquote-From)
845 (mh-show-xface)
846 (mh-show-addr)
847 (setq buffer-invisibility-spec '((vanish . t) t))
848 (set (make-local-variable 'line-move-ignore-invisible) t)
849 (make-local-variable 'font-lock-defaults)
850 ;;(set (make-local-variable 'font-lock-support-mode) nil)
851 (cond
852 ((equal mh-highlight-citation-style 'font-lock)
853 (setq font-lock-defaults '(mh-show-font-lock-keywords-with-cite t)))
854 ((equal mh-highlight-citation-style 'gnus)
855 (setq font-lock-defaults '((mh-show-font-lock-keywords)
856 t nil nil nil
857 (font-lock-fontify-region-function
858 . mh-show-font-lock-fontify-region)))
859 (mh-gnus-article-highlight-citation))
860 (t
861 (setq font-lock-defaults '(mh-show-font-lock-keywords t))))
862 (if (and (featurep 'xemacs)
863 font-lock-auto-fontify)
864 (turn-on-font-lock))
865 (when mh-decode-mime-flag
866 (mh-make-local-hook 'kill-buffer-hook)
867 (add-hook 'kill-buffer-hook 'mh-mime-cleanup nil t))
868 (easy-menu-add mh-show-sequence-menu)
869 (easy-menu-add mh-show-message-menu)
870 (easy-menu-add mh-show-folder-menu)
871 (make-local-variable 'mh-show-folder-buffer)
872 (buffer-disable-undo)
873 (setq buffer-read-only t)
874 (use-local-map mh-show-mode-map))
875
876 \f
877
878 ;;; Support Routines
879
880 (defun mh-show-unquote-From ()
881 "Decode >From at beginning of lines for `mh-show-mode'."
882 (save-excursion
883 (let ((modified (buffer-modified-p))
884 (case-fold-search nil)
885 (buffer-read-only nil))
886 (goto-char (mh-mail-header-end))
887 (while (re-search-forward "^>From" nil t)
888 (replace-match "From"))
889 (set-buffer-modified-p modified))))
890
891 ;;;###mh-autoload
892 (defun mh-show-addr ()
893 "Use `goto-address'."
894 (goto-address))
895
896 ;;;###mh-autoload
897 (defun mh-gnus-article-highlight-citation ()
898 "Highlight cited text in current buffer using Gnus."
899 (interactive)
900 ;; Don't allow Gnus to create buttons while highlighting, maybe this is bad
901 ;; style?
902 (flet ((gnus-article-add-button (&rest args) nil))
903 (let* ((modified (buffer-modified-p))
904 (gnus-article-buffer (buffer-name))
905 (gnus-cite-face-list `(,@(cdr gnus-cite-face-list)
906 ,(car gnus-cite-face-list))))
907 (gnus-article-highlight-citation t)
908 (set-buffer-modified-p modified))))
909
910 (provide 'mh-show)
911
912 ;; Local Variables:
913 ;; indent-tabs-mode: nil
914 ;; sentence-end-double-space: nil
915 ;; End:
916
917 ;;; mh-show.el ends here