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