mh-show.el 36 KB

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