mh-e.el 113 KB
Newer Older
Richard M. Stallman's avatar
Richard M. Stallman committed
1 2
;;; mh-e.el --- GNU Emacs interface to the MH mail system

Bill Wohler's avatar
Bill Wohler committed
3 4
;; Copyright (C) 1985, 1986, 1987, 1988,
;;  1990, 1992, 1993, 1994, 1995, 1997, 1999,
5
;;  2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
Richard M. Stallman's avatar
Richard M. Stallman committed
6

Bill Wohler's avatar
Bill Wohler committed
7
;; Author: Bill Wohler <wohler@newt.com>
Gerd Moellmann's avatar
Gerd Moellmann committed
8
;; Maintainer: Bill Wohler <wohler@newt.com>
9
;; Version: 7.85+cvs
Richard M. Stallman's avatar
Richard M. Stallman committed
10 11
;; Keywords: mail

12
;; This file is part of GNU Emacs.
Karl Heuer's avatar
Karl Heuer committed
13 14

;; GNU Emacs is free software; you can redistribute it and/or modify
Richard M. Stallman's avatar
Richard M. Stallman committed
15 16 17 18
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation; either version 2, or (at your option)
;; any later version.

Karl Heuer's avatar
Karl Heuer committed
19
;; GNU Emacs is distributed in the hope that it will be useful,
Richard M. Stallman's avatar
Richard M. Stallman committed
20 21 22 23 24
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;; GNU General Public License for more details.

;; You should have received a copy of the GNU General Public License
Erik Naggum's avatar
Erik Naggum committed
25
;; along with GNU Emacs; see the file COPYING.  If not, write to the
Lute Kamstra's avatar
Lute Kamstra committed
26 27
;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
;; Boston, MA 02110-1301, USA.
Richard M. Stallman's avatar
Richard M. Stallman committed
28 29 30

;;; Commentary:

Bill Wohler's avatar
Bill Wohler committed
31 32 33 34
;; How to Use:
;;   M-x mh-rmail to read mail.  Type C-h m there for a list of commands.
;;   C-u M-x mh-rmail to visit any folder.
;;   M-x mh-smail to send mail.  From within the mail reader, "m" works, too.
Erik Naggum's avatar
Erik Naggum committed
35

Bill Wohler's avatar
Bill Wohler committed
36 37 38 39
;; Your .emacs might benefit from these bindings:
;;   (global-set-key "\C-cr" 'mh-rmail)
;;   (global-set-key "\C-xm" 'mh-smail)
;;   (global-set-key "\C-x4m" 'mh-smail-other-window)
Erik Naggum's avatar
Erik Naggum committed
40

Bill Wohler's avatar
Bill Wohler committed
41
;; MH (Message Handler) is a powerful mail reader.
Erik Naggum's avatar
Erik Naggum committed
42

Bill Wohler's avatar
Bill Wohler committed
43 44
;; The MH newsgroup is comp.mail.mh; the mailing list is mh-users@ics.uci.edu
;; (send to mh-users-request to be added). See the monthly Frequently Asked
Bill Wohler's avatar
Bill Wohler committed
45
;; Questions posting there for information on getting MH and MH-E:
Bill Wohler's avatar
Bill Wohler committed
46
;;   http://www.faqs.org/faqs/mail/mh-faq/part1/preamble.html
Erik Naggum's avatar
Erik Naggum committed
47

Bill Wohler's avatar
Bill Wohler committed
48
;; N.B. MH must have been compiled with the MHE compiler flag or several
Bill Wohler's avatar
Bill Wohler committed
49
;; features necessary for MH-E will be missing from MH commands, specifically
Erik Naggum's avatar
Erik Naggum committed
50 51
;; the -build switch to repl and forw.

Bill Wohler's avatar
Bill Wohler committed
52
;; MH-E is an Emacs interface to the MH mail system.
Bill Wohler's avatar
Bill Wohler committed
53

54 55 56
;; MH-E is supported in GNU Emacs 21 and 22 as well as XEmacs 21
;; (except for versions 21.5.9-21.5.16), with MH 6.8.4 on, nmh 1.0.4
;; on, and GNU mailutils 0.4 on.
Bill Wohler's avatar
Bill Wohler committed
57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75

;; Mailing Lists:
;;   mh-e-users@lists.sourceforge.net
;;   mh-e-announce@lists.sourceforge.net
;;   mh-e-devel@lists.sourceforge.net
;;
;;   Subscribe by sending a "subscribe" message to
;;   <list>-request@lists.sourceforge.net, or by using the web interface at
;;   https://sourceforge.net/mail/?group_id=13357

;; Bug Reports:
;;   https://sourceforge.net/tracker/?group_id=13357&atid=113357
;;   Include the output of M-x mh-version in any bug report.

;; Feature Requests:
;;   https://sourceforge.net/tracker/?atid=363357&group_id=13357&func=browse

;; Support:
;;   https://sourceforge.net/tracker/?group_id=13357&atid=213357
Erik Naggum's avatar
Erik Naggum committed
76

Erik Naggum's avatar
Erik Naggum committed
77
;;; Change Log:
Erik Naggum's avatar
Erik Naggum committed
78 79 80

;; Original version for Gosling emacs by Brian Reid, Stanford, 1982.
;; Modified by James Larus, BBN, July 1984 and UCB, 1984 & 1985.
Bill Wohler's avatar
Bill Wohler committed
81 82 83 84
;; Rewritten for GNU Emacs, James Larus, 1985.
;; Modified by Stephen Gildea, 1988.
;; Maintenance picked up by Bill Wohler and the
;; SourceForge Crew <http://mh-e.sourceforge.net/>, 2001.
Bill Wohler's avatar
Bill Wohler committed
85

Richard M. Stallman's avatar
Richard M. Stallman committed
86 87
;;; Code:

88
;;(message "> mh-e")
Bill Wohler's avatar
Bill Wohler committed
89
(provide 'mh-e)
Bill Wohler's avatar
Bill Wohler committed
90

Bill Wohler's avatar
Bill Wohler committed
91 92
(eval-when-compile (require 'mh-acros))
(mh-require-cl)
Bill Wohler's avatar
Bill Wohler committed
93

94 95
(require 'easymenu)
(require 'gnus-util)
96
(require 'mh-buffers)
97 98
(require 'mh-seq)
(require 'mh-utils)
99
;;(message "< mh-e")
Bill Wohler's avatar
Bill Wohler committed
100

101
(defconst mh-version "7.85+cvs" "Version number of MH-E.")
Richard M. Stallman's avatar
Richard M. Stallman committed
102 103 104

(defvar mh-partial-folder-mode-line-annotation "select"
  "Annotation when displaying part of a folder.
105 106
The string is displayed after the folder's name. nil for no
annotation.")
Bill Wohler's avatar
Bill Wohler committed
107

Bill Wohler's avatar
Bill Wohler committed
108

Bill Wohler's avatar
Bill Wohler committed
109

Bill Wohler's avatar
Bill Wohler committed
110 111
;;; Scan Line Formats

Bill Wohler's avatar
Bill Wohler committed
112 113 114
;; Parameterize MH-E to work with different scan formats.  The defaults work
;; with the standard MH scan listings, in which the first 4 characters on
;; the line are the message number, followed by two places for notations.
Bill Wohler's avatar
Bill Wohler committed
115

Bill Wohler's avatar
Bill Wohler committed
116 117 118
;; The following scan formats are passed to the scan program if the setting of
;; `mh-scan-format-file' is t. They are identical except the later one makes
;; use of the nmh `decode' function to decode RFC 2047 encodings. If you just
119
;; want to change the column of the notations, use the `mh-set-cmd-note'
Bill Wohler's avatar
Bill Wohler committed
120
;; function.
Bill Wohler's avatar
Bill Wohler committed
121 122 123 124 125 126 127 128 129 130 131 132 133 134 135

(defvar mh-scan-format-mh
  (concat
   "%4(msg)"
   "%<(cur)+%| %>"
   "%<{replied}-"
   "%?(nonnull(comp{to}))%<(mymbox{to})t%>"
   "%?(nonnull(comp{cc}))%<(mymbox{cc})c%>"
   "%?(nonnull(comp{bcc}))%<(mymbox{bcc})b%>"
   "%?(nonnull(comp{newsgroups}))n%>"
   "%<(zero) %>"
   "%02(mon{date})/%02(mday{date})%<{date} %|*%>"
   "%<(mymbox{from})%<{to}To:%14(friendly{to})%>%>"
   "%<(zero)%17(friendly{from})%>  "
   "%{subject}%<{body}<<%{body}%>")
136
  "*Scan format string for MH.
137 138 139 140
This string is passed to the scan program via the -format
argument. This format is identical to the default except that
additional hints for fontification have been added to the fifth
column (remember that in Emacs, the first column is 0).
Bill Wohler's avatar
Bill Wohler committed
141

142
The values of the fifth column, in priority order, are: \"-\" if
143
the message has been replied to, t if an address on the To: line
144 145
matches one of the mailboxes of the current user, \"c\" if the Cc:
line matches, \"b\" if the Bcc: line matches, and \"n\" if a
146
non-empty Newsgroups: header is present.")
Bill Wohler's avatar
Bill Wohler committed
147 148 149 150 151 152 153 154 155 156 157 158 159 160 161

(defvar mh-scan-format-nmh
  (concat
   "%4(msg)"
   "%<(cur)+%| %>"
   "%<{replied}-"
   "%?(nonnull(comp{to}))%<(mymbox{to})t%>"
   "%?(nonnull(comp{cc}))%<(mymbox{cc})c%>"
   "%?(nonnull(comp{bcc}))%<(mymbox{bcc})b%>"
   "%?(nonnull(comp{newsgroups}))n%>"
   "%<(zero) %>"
   "%02(mon{date})/%02(mday{date})%<{date} %|*%>"
   "%<(mymbox{from})%<{to}To:%14(decode(friendly{to}))%>%>"
   "%<(zero)%17(decode(friendly{from}))%>  "
   "%(decode{subject})%<{body}<<%{body}%>")
Bill Wohler's avatar
Bill Wohler committed
162 163
  "*Scan format string for nmh.
This string is passed to the scan program via the -format arg.
164 165 166
This format is identical to the default except that additional
hints for fontification have been added to the fifth
column (remember that in Emacs, the first column is 0).
Bill Wohler's avatar
Bill Wohler committed
167

168
The values of the fifth column, in priority order, are: \"-\" if
169
the message has been replied to, t if an address on the To: field
170 171
matches one of the mailboxes of the current user, \"c\" if the Cc:
field matches, \"b\" if the Bcc: field matches, and \"n\" if a
172
non-empty Newsgroups: field is present.")
Bill Wohler's avatar
Bill Wohler committed
173 174

(defvar mh-note-deleted ?D
175
  "Messages that have been deleted are marked by this character.
Bill Wohler's avatar
Bill Wohler committed
176 177 178
See also `mh-scan-deleted-msg-regexp'.")

(defvar mh-note-refiled ?^
179
  "Messages that have been refiled are marked by this character.
Bill Wohler's avatar
Bill Wohler committed
180 181 182
See also `mh-scan-refiled-msg-regexp'.")

(defvar mh-note-cur ?+
183
  "The current message (in MH, not in MH-E) is marked by this character.
Bill Wohler's avatar
Bill Wohler committed
184
See also `mh-scan-cur-msg-number-regexp'.")
Bill Wohler's avatar
Bill Wohler committed
185

Bill Wohler's avatar
Bill Wohler committed
186
(defvar mh-scan-good-msg-regexp  "^\\( *[0-9]+\\)[^D^0-9]"
187
  "This regular expression matches \"good\" messages.
188 189 190 191 192 193 194 195 196

It must match from the beginning of the line. Note that the
default setting of `mh-folder-font-lock-keywords' expects this
expression to contain at least one parenthesized expression which
matches the message number as in the default of

  \"^\\\\( *[0-9]+\\\\)[^D^0-9]\".

This expression includes the leading space within the parenthesis
197 198
since it looks better to highlight it as well. The highlighting
is done with the face `mh-folder-msg-number'. This regular
199
expression should be correct as it is needed by non-fontification
200
functions.")
Bill Wohler's avatar
Bill Wohler committed
201

Bill Wohler's avatar
Bill Wohler committed
202
(defvar mh-scan-deleted-msg-regexp "^\\( *[0-9]+\\)D"
203
  "This regular expression matches deleted messages.
204 205 206 207 208 209 210 211 212

It must match from the beginning of the line. Note that the
default setting of `mh-folder-font-lock-keywords' expects this
expression to contain at least one parenthesized expression which
matches the message number as in the default of

  \"^\\\\( *[0-9]+\\\\)D\".

This expression includes the leading space within the parenthesis
213 214
since it looks better to highlight it as well. The highlighting
is done with the face `mh-folder-deleted'. This regular
215 216
expression should be correct as it is needed by non-fontification
functions. See also `mh-note-deleted'.")
Bill Wohler's avatar
Bill Wohler committed
217

Bill Wohler's avatar
Bill Wohler committed
218
(defvar mh-scan-refiled-msg-regexp  "^\\( *[0-9]+\\)\\^"
219
  "This regular expression matches refiled messages.
220 221 222 223 224 225 226 227 228

It must match from the beginning of the line. Note that the
default setting of `mh-folder-font-lock-keywords' expects this
expression to contain at least one parenthesized expression which
matches the message number as in the default of

  \"^\\\\( *[0-9]+\\\\)\\\\^\".

This expression includes the leading space within the parenthesis
229 230
since it looks better to highlight it as well. The highlighting
is done with the face `mh-folder-refiled'. This regular
231
expression should be correct as it is needed by non-fontification
232
functions. See also `mh-note-refiled'.")
Bill Wohler's avatar
Bill Wohler committed
233 234

(defvar mh-scan-valid-regexp "^ *[0-9]"
235
  "This regular expression describes a valid scan line.
236 237 238

This is used to eliminate error messages that are occasionally
produced by \"inc\".")
Bill Wohler's avatar
Bill Wohler committed
239

Bill Wohler's avatar
Bill Wohler committed
240
(defvar mh-scan-cur-msg-number-regexp "^\\( *[0-9]+\\+\\).*"
241
  "This regular expression matches the current message.
242 243 244 245 246 247 248 249 250 251

It must match from the beginning of the line. Note that the
default setting of `mh-folder-font-lock-keywords' expects this
expression to contain at least one parenthesized expression which
matches the message number as in the default of

  \"^\\\\( *[0-9]+\\\\+\\\\).*\".

This expression includes the leading space and current message
marker \"+\" within the parenthesis since it looks better to
252 253 254 255
highlight these items as well. The highlighting is done with the
face `mh-folder-cur-msg-number'. This regular expression should
be correct as it is needed by non-fontification functions. See
also `mh-note-cur'.")
Bill Wohler's avatar
Bill Wohler committed
256 257

(defvar mh-scan-date-regexp "\\([0-9][0-9]/[0-9][0-9]\\)"
258
  "This regular expression matches a valid date.
259 260 261 262 263 264

It must not be anchored to the beginning or the end of the line.
Note that the default setting of `mh-folder-font-lock-keywords'
expects this expression to contain only one parenthesized
expression which matches the date field as in the default of
\"\\\\([0-9][0-9]/[0-9][0-9]\\\\)\"}. If this regular expression
265 266
is not correct, the date will not be highlighted with the face
`mh-folder-date'.")
Bill Wohler's avatar
Bill Wohler committed
267 268

(defvar mh-scan-rcpt-regexp  "\\(To:\\)\\(..............\\)"
269
  "This regular expression specifies the recipient in messages you sent.
270

Bill Wohler's avatar
Bill Wohler committed
271
Note that the default setting of `mh-folder-font-lock-keywords'
272
expects this expression to contain two parenthesized expressions.
273
The first is expected to match the \"To:\" that the default scan
274 275 276
format file generates. The second is expected to match the
recipient's name as in the default of
\"\\\\(To:\\\\)\\\\(..............\\\\)\". If this regular
277 278 279
expression is not correct, the \"To:\" string will not be
highlighted with the face `mh-folder-to' and the recipient will
not be highlighted with the face `mh-folder-address'")
Bill Wohler's avatar
Bill Wohler committed
280 281

(defvar mh-scan-body-regexp "\\(<<\\([^\n]+\\)?\\)"
282
  "This regular expression matches the message body fragment.
283 284 285 286 287

Note that the default setting of `mh-folder-font-lock-keywords'
expects this expression to contain at least one parenthesized
expression which matches the body text as in the default of
\"\\\\(<<\\\\([^\\n]+\\\\)?\\\\)\". If this regular expression is
288 289
not correct, the body fragment will not be highlighted with the
face `mh-folder-body'.")
Bill Wohler's avatar
Bill Wohler committed
290 291

(defvar mh-scan-subject-regexp
Bill Wohler's avatar
Bill Wohler committed
292
  "^ *[0-9]+........[ ]*...................\\([Rr][Ee]\\(\\[[0-9]+\\]\\)?:\\s-*\\)*\\([^<\n]*\\)"
293
  "This regular expression matches the subject.
294 295 296 297

It must match from the beginning of the line. Note that the
default setting of `mh-folder-font-lock-keywords' expects this
expression to contain at least three parenthesized expressions.
298 299 300 301 302 303 304
The first is expected to match the \"Re:\" string, if any, and is
highlighted with the face `mh-folder-followup'. The second
matches an optional bracketed number after \"Re:\", such as in
\"Re[2]:\" (and is thus a sub-expression of the first expression)
and the third is expected to match the subject line itself which
is highlighted with the face `mh-folder-subject'. For example,
the default (broken on multiple lines for readability) is
305

306 307 308
  ^ *[0-9]+........[ ]*...................
  \\\\([Rr][Ee]\\\\(\\\\\\=[[0-9]+\\\\]\\\\)?:\\\\s-*\\\\)*
  \\\\([^<\\n]*\\\\)
309 310 311

This regular expression should be correct as it is needed by
non-fontification functions.")
Bill Wohler's avatar
Bill Wohler committed
312

313 314 315
(defvar mh-scan-sent-to-me-sender-regexp
  "^ *[0-9]+.\\([bct]\\).....[ ]*\\(..................\\)"
  "This regular expression matches messages sent to us.
316 317

Note that the default setting of `mh-folder-font-lock-keywords'
318
expects this expression to contain at least two parenthesized
319
expressions. The first should match the fontification hint (see
320
`mh-scan-format-nmh') and the second should match the user name
321 322
as in the default of

323
  ^ *[0-9]+.\\\\([bct]\\\\).....[ ]*\\\\(..................\\\\)
324

325 326 327 328
If this regular expression is not correct, the notation hints
will not be highlighted with the face
`mh-mh-folder-sent-to-me-hint' and the sender will not be
highlighted with the face `mh-folder-sent-to-me-sender'.")
Bill Wohler's avatar
Bill Wohler committed
329

Bill Wohler's avatar
Bill Wohler committed
330 331


Bill Wohler's avatar
Bill Wohler committed
332 333
(defvar mh-folder-font-lock-keywords
  (list
Bill Wohler's avatar
Bill Wohler committed
334 335
   ;; Folders when displaying index buffer
   (list "^\\+.*"
336
         '(0 'mh-search-folder))
Bill Wohler's avatar
Bill Wohler committed
337 338
   ;; Marked for deletion
   (list (concat mh-scan-deleted-msg-regexp ".*")
339
         '(0 'mh-folder-deleted))
Bill Wohler's avatar
Bill Wohler committed
340 341
   ;; Marked for refile
   (list (concat mh-scan-refiled-msg-regexp ".*")
342 343 344 345 346
         '(0 'mh-folder-refiled))
   ;; After subject
   (list mh-scan-body-regexp
         '(1 'mh-folder-body nil t))
   ;; Subject
Bill Wohler's avatar
Bill Wohler committed
347
   '(mh-folder-font-lock-subject
348 349 350
     (1 'mh-folder-followup append t)
     (2 'mh-folder-subject append t))
   ;; Current message number
Bill Wohler's avatar
Bill Wohler committed
351
   (list mh-scan-cur-msg-number-regexp
352 353
         '(1 'mh-folder-cur-msg-number))
   ;; Message number
Bill Wohler's avatar
Bill Wohler committed
354
   (list mh-scan-good-msg-regexp
355 356 357 358 359
         '(1 'mh-folder-msg-number))
   ;; Date
   (list mh-scan-date-regexp
         '(1 'mh-folder-date))
   ;; Messages from me (To:)
Bill Wohler's avatar
Bill Wohler committed
360
   (list mh-scan-rcpt-regexp
361 362 363 364 365 366
         '(1 'mh-folder-to)
         '(2 'mh-folder-address))
   ;; Messages to me
   (list mh-scan-sent-to-me-sender-regexp
         '(1 'mh-folder-sent-to-me-hint)
         '(2 'mh-folder-sent-to-me-sender)))
367
  "Keywords (regular expressions) used to fontify the MH-Folder buffer.")
Bill Wohler's avatar
Bill Wohler committed
368 369 370

(defvar mh-scan-cmd-note-width 1
  "Number of columns consumed by the cmd-note field in `mh-scan-format'.
371

372 373
This column will have one of the values: \" \", \"D\", \"^\", \"+\" and
where \" \" is the default value,
374

375 376 377
  \"D\" is the `mh-note-deleted' character,
  \"^\" is the `mh-note-refiled' character, and
  \"+\" is the `mh-note-cur' character.")
Bill Wohler's avatar
Bill Wohler committed
378 379 380

(defvar mh-scan-destination-width 1
  "Number of columns consumed by the destination field in `mh-scan-format'.
381

382
This column will have one of \" \", \"%\", \"-\", \"t\", \"c\", \"b\", or \"n\"
383 384
in it.

385 386 387 388 389 390 391
  \" \" blank space is the default character.
  \"%\" indicates that the message in in a named MH sequence.
  \"-\" indicates that the message has been annotated with a replied field.
  \"t\" indicates that the message contains mymbox in the To: field.
  \"c\" indicates that the message contains mymbox in the Cc: field.
  \"b\" indicates that the message contains mymbox in the Bcc: field.
  \"n\" indicates that the message contains a Newsgroups: field.")
Bill Wohler's avatar
Bill Wohler committed
392 393 394 395 396 397 398

(defvar mh-scan-date-width 5
  "Number of columns consumed by the date field in `mh-scan-format'.
This column will typically be of the form mm/dd.")

(defvar mh-scan-date-flag-width 1
  "Number of columns consumed to flag (in)valid dates in `mh-scan-format'.
399
This column will have \" \" for valid and \"*\" for invalid or
400
missing dates.")
Bill Wohler's avatar
Bill Wohler committed
401 402 403 404 405 406 407 408 409 410

(defvar mh-scan-from-mbox-width 17
  "Number of columns consumed with the \"From:\" line in `mh-scan-format'.
This column will have a friendly name or e-mail address of the
originator, or a \"To: address\" for outgoing e-mail messages.")

(defvar mh-scan-from-mbox-sep-width 2
  "Number of columns consumed by whitespace after from-mbox in `mh-scan-format'.
This column will only ever have spaces in it.")

411 412 413 414
(defvar mh-scan-field-destination-offset
  (+ mh-scan-cmd-note-width)
  "The offset from the `mh-cmd-note' for the destination column.")

Bill Wohler's avatar
Bill Wohler committed
415
(defvar mh-scan-field-from-start-offset
Bill Wohler's avatar
Bill Wohler committed
416 417 418 419 420
  (+ mh-scan-cmd-note-width
     mh-scan-destination-width
     mh-scan-date-width
     mh-scan-date-flag-width)
  "The offset from the `mh-cmd-note' to find the start of \"From:\" address.")
Bill Wohler's avatar
Bill Wohler committed
421 422

(defvar mh-scan-field-from-end-offset
Bill Wohler's avatar
Bill Wohler committed
423 424
  (+ mh-scan-field-from-start-offset mh-scan-from-mbox-width)
  "The offset from the `mh-cmd-note' to find the end of \"From:\" address.")
Bill Wohler's avatar
Bill Wohler committed
425 426 427 428 429 430 431 432 433

(defvar mh-scan-field-subject-start-offset
  (+ mh-scan-cmd-note-width
     mh-scan-destination-width
     mh-scan-date-width
     mh-scan-date-flag-width
     mh-scan-from-mbox-width
     mh-scan-from-mbox-sep-width)
  "The offset from the `mh-cmd-note' to find the start of the subject.")
Bill Wohler's avatar
Bill Wohler committed
434 435

(defun mh-folder-font-lock-subject (limit)
Bill Wohler's avatar
Bill Wohler committed
436
  "Return MH-E scan subject strings to font-lock between point and LIMIT."
Bill Wohler's avatar
Bill Wohler committed
437 438 439
  (if (not (re-search-forward mh-scan-subject-regexp limit t))
      nil
    (if (match-beginning 1)
Bill Wohler's avatar
Bill Wohler committed
440 441 442 443
        (set-match-data (list (match-beginning 1) (match-end 3)
                              (match-beginning 1) (match-end 3) nil nil))
      (set-match-data (list (match-beginning 3) (match-end 3)
                            nil nil (match-beginning 3) (match-end 3))))
Bill Wohler's avatar
Bill Wohler committed
444 445
    t))

Bill Wohler's avatar
Bill Wohler committed
446 447 448 449


;; Fontifify unseen mesages in bold.

Bill Wohler's avatar
Bill Wohler committed
450 451
(defmacro mh-generate-sequence-font-lock (seq prefix face)
  "Generate the appropriate code to fontify messages in SEQ.
452 453 454
PREFIX is used to generate unique names for the variables and
functions defined by the macro. So a different prefix should be
provided for every invocation.
Bill Wohler's avatar
Bill Wohler committed
455 456 457 458 459 460
FACE is the font-lock face used to display the matching scan lines."
  (let ((cache (intern (format "mh-folder-%s-seq-cache" prefix)))
        (func (intern (format "mh-folder-font-lock-%s" prefix))))
    `(progn
       (defvar ,cache nil
         "Internal cache variable used for font-lock in MH-E.
461 462
Should only be non-nil through font-lock stepping, and nil once
font-lock is done highlighting.")
Bill Wohler's avatar
Bill Wohler committed
463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503
       (make-variable-buffer-local ',cache)

       (defun ,func (limit)
         "Return unseen message lines to font-lock between point and LIMIT."
         (if (not ,cache) (setq ,cache (mh-seq-msgs (mh-find-seq ,seq))))
         (let ((cur-msg (mh-get-msg-num nil)))
           (cond ((not ,cache)
                  nil)
                 ((>= (point) limit)              ;Presumably at end of buffer
                  (setq ,cache nil)
                  nil)
                 ((member cur-msg ,cache)
                  (let ((bpoint (progn (beginning-of-line)(point)))
                        (epoint (progn (forward-line 1)(point))))
                    (if (<= limit (point)) (setq  ,cache nil))
                    (set-match-data (list bpoint epoint bpoint epoint))
                    t))
                 (t
                  ;; move forward one line at a time, checking each message
                  (while (and (= 0 (forward-line 1))
                              (> limit (point))
                              (not (member (mh-get-msg-num nil) ,cache))))
                  ;; Examine how we must have exited the loop...
                  (let ((cur-msg (mh-get-msg-num nil)))
                    (cond ((or (<= limit (point))
                               (not (member cur-msg ,cache)))
                           (setq ,cache nil)
                           nil)
                          ((member cur-msg ,cache)
                           (let ((bpoint (progn (beginning-of-line) (point)))
                                 (epoint (progn (forward-line 1) (point))))
                             (if (<= limit (point)) (setq ,cache nil))
                             (set-match-data
                              (list bpoint epoint bpoint epoint))
                             t))))))))

       (setq mh-folder-font-lock-keywords
             (append mh-folder-font-lock-keywords
                     (list (list ',func (list 1 '',face 'prepend t))))))))

(mh-generate-sequence-font-lock mh-unseen-seq unseen bold)
504
(mh-generate-sequence-font-lock mh-tick-seq tick mh-folder-tick)
Bill Wohler's avatar
Bill Wohler committed
505 506


Richard M. Stallman's avatar
Richard M. Stallman committed
507 508 509

;;; Internal variables:

510 511 512 513 514 515 516 517
(defvar mh-last-destination nil
  "Destination of last refile or write command.")

(defvar mh-last-destination-folder nil
  "Destination of last refile command.")

(defvar mh-last-destination-write nil
  "Destination of last write command.")
Richard M. Stallman's avatar
Richard M. Stallman committed
518 519 520 521

(defvar mh-folder-mode-map (make-keymap)
  "Keymap for MH folders.")

522 523 524 525 526
(defvar mh-arrow-marker nil
  "Marker for arrow display in fringe.")

(defvar mh-delete-list nil
  "List of message numbers to delete.
527 528
This variable can be used by
`mh-before-commands-processed-hook'.")
Bill Wohler's avatar
Bill Wohler committed
529

530 531
(defvar mh-refile-list nil
  "List of folder names in `mh-seq-list'.
532 533
This variable can be used by
`mh-before-commands-processed-hook'.")
Richard M. Stallman's avatar
Richard M. Stallman committed
534

535 536
(defvar mh-folders-changed nil
  "Lists which folders were affected by deletes and refiles.
537 538
This list will always include the current folder
`mh-current-folder'. This variable can be used by
539
`mh-after-commands-processed-hook'.")
Richard M. Stallman's avatar
Richard M. Stallman committed
540

541 542
(defvar mh-next-direction 'forward
  "Direction to move to next message.")
543

544 545 546
(defvar mh-view-ops ()
  "Stack of operations that change the folder view.
These operations include narrowing or threading.")
Richard M. Stallman's avatar
Richard M. Stallman committed
547

548 549 550 551 552
(defvar mh-folder-view-stack ()
  "Stack of previous folder views.")

(defvar mh-index-data nil
  "Info about index search results.")
Richard M. Stallman's avatar
Richard M. Stallman committed
553

Bill Wohler's avatar
Bill Wohler committed
554 555 556
(defvar mh-index-previous-search nil)
(defvar mh-index-msg-checksum-map nil)
(defvar mh-index-checksum-origin-map nil)
Bill Wohler's avatar
Bill Wohler committed
557
(defvar mh-index-sequence-search-flag nil)
Bill Wohler's avatar
Bill Wohler committed
558

559 560
(defvar mh-first-msg-num nil
  "Number of first message in buffer.")
Richard M. Stallman's avatar
Richard M. Stallman committed
561

562 563
(defvar mh-last-msg-num nil
  "Number of last msg in buffer.")
Richard M. Stallman's avatar
Richard M. Stallman committed
564

565 566
(defvar mh-mode-line-annotation nil
  "Message range displayed in buffer.")
Richard M. Stallman's avatar
Richard M. Stallman committed
567

568 569
(defvar mh-sequence-notation-history nil
  "Remember original notation that is overwritten by `mh-note-seq'.")
Bill Wohler's avatar
Bill Wohler committed
570

571 572
(defvar mh-colors-available-flag nil
  "Non-nil means colors are available.")
Bill Wohler's avatar
Bill Wohler committed
573

Bill Wohler's avatar
Bill Wohler committed
574 575


Richard M. Stallman's avatar
Richard M. Stallman committed
576 577
;;; Macros and generic functions:

Bill Wohler's avatar
Bill Wohler committed
578 579
(defun mh-mapc (function list)
  "Apply FUNCTION to each element of LIST for side effects only."
Richard M. Stallman's avatar
Richard M. Stallman committed
580
  (while list
Bill Wohler's avatar
Bill Wohler committed
581
    (funcall function (car list))
Richard M. Stallman's avatar
Richard M. Stallman committed
582 583
    (setq list (cdr list))))

Bill Wohler's avatar
Bill Wohler committed
584
(defun mh-scan-format ()
Bill Wohler's avatar
Bill Wohler committed
585
  "Return the output format argument for the scan program."
Bill Wohler's avatar
Bill Wohler committed
586
  (if (equal mh-scan-format-file t)
Bill Wohler's avatar
Bill Wohler committed
587
      (list "-format" (if (mh-variant-p 'nmh 'mu-mh)
Bill Wohler's avatar
Bill Wohler committed
588 589 590 591
                          (list (mh-update-scan-format
                                 mh-scan-format-nmh mh-cmd-note))
                        (list (mh-update-scan-format
                               mh-scan-format-mh mh-cmd-note))))
Bill Wohler's avatar
Bill Wohler committed
592
    (if (not (equal mh-scan-format-file nil))
Bill Wohler's avatar
Bill Wohler committed
593
        (list "-form" mh-scan-format-file))))
Bill Wohler's avatar
Bill Wohler committed
594

Richard M. Stallman's avatar
Richard M. Stallman committed
595 596 597 598 599 600


;;; Entry points:

;;;###autoload
(defun mh-rmail (&optional arg)
601 602 603 604 605
  "Incorporate new mail with MH.
Scan an MH folder if ARG is non-nil.

This function is an entry point to MH-E, the Emacs interface to
the MH mail system."
Richard M. Stallman's avatar
Richard M. Stallman committed
606 607 608 609
  (interactive "P")
  (mh-find-path)
  (if arg
      (call-interactively 'mh-visit-folder)
Bill Wohler's avatar
Bill Wohler committed
610 611
    (unless (get-buffer mh-inbox)
      (mh-visit-folder mh-inbox (symbol-name mh-unseen-seq)))
Bill Wohler's avatar
Bill Wohler committed
612
    (mh-inc-folder)))
Richard M. Stallman's avatar
Richard M. Stallman committed
613

Bill Wohler's avatar
Bill Wohler committed
614 615 616
;;;###autoload
(defun mh-nmail (&optional arg)
  "Check for new mail in inbox folder.
617 618 619 620
Scan an MH folder if ARG is non-nil.

This function is an entry point to MH-E, the Emacs interface to
the MH mail system."
Bill Wohler's avatar
Bill Wohler committed
621
  (interactive "P")
Bill Wohler's avatar
Bill Wohler committed
622
  (mh-find-path)                        ; init mh-inbox
Bill Wohler's avatar
Bill Wohler committed
623 624 625
  (if arg
      (call-interactively 'mh-visit-folder)
    (mh-visit-folder mh-inbox)))
Richard M. Stallman's avatar
Richard M. Stallman committed
626 627 628



Bill Wohler's avatar
Bill Wohler committed
629
;;; User executable MH-E commands:
Richard M. Stallman's avatar
Richard M. Stallman committed
630

Bill Wohler's avatar
Bill Wohler committed
631
(defun mh-delete-msg (range)
632
  "Delete RANGE\\<mh-folder-mode-map>.
633

634 635 636 637 638 639 640 641 642 643 644 645 646 647 648
To mark a message for deletion, use this command. A \"D\" is
placed by the message in the scan window, and the next undeleted
message is displayed. If the previous command had been
\\[mh-previous-undeleted-msg], then the next message displayed is
the first undeleted message previous to the message just deleted.
Use \\[mh-next-undeleted-msg] to force subsequent
\\[mh-delete-msg] commands to move forward to the next undeleted
message after deleting the message under the cursor.

The hook `mh-delete-msg-hook' is called after you mark a message
for deletion. For example, a past maintainer of MH-E used this
once when he kept statistics on his mail usage.

Check the documentation of `mh-interactive-range' to see how
RANGE is read in interactive use."
Bill Wohler's avatar
Bill Wohler committed
649 650
  (interactive (list (mh-interactive-range "Delete")))
  (mh-delete-msg-no-motion range)
651 652
  (if (looking-at mh-scan-deleted-msg-regexp)
      (mh-next-msg)))
Bill Wohler's avatar
Bill Wohler committed
653 654

(defun mh-delete-msg-no-motion (range)
655
  "Delete RANGE, don't move to next message.
656

657 658 659
This command marks the RANGE for deletion but leaves the cursor
at the current message in case you wish to perform other
operations on the message.
Bill Wohler's avatar
Bill Wohler committed
660

661 662
Check the documentation of `mh-interactive-range' to see how
RANGE is read in interactive use."
Bill Wohler's avatar
Bill Wohler committed
663 664
  (interactive (list (mh-interactive-range "Delete")))
  (mh-iterate-on-range () range
Bill Wohler's avatar
Bill Wohler committed
665
    (mh-delete-a-msg nil)))
Richard M. Stallman's avatar
Richard M. Stallman committed
666 667

(defun mh-execute-commands ()
668 669
  "Process outstanding delete and refile requests\\<mh-folder-mode-map>.

670 671 672 673 674 675
If you've marked messages to be deleted or refiled and you want
to go ahead and delete or refile the messages, use this command.
Many MH-E commands that may affect the numbering of the
messages (such as \\[mh-rescan-folder] or \\[mh-pack-folder])
will ask if you want to process refiles or deletes first and then
either run this command for you or undo the pending refiles and
676 677
deletes, which are lost.

678 679 680
This function runs `mh-before-commands-processed-hook' before the
commands are processed and `mh-after-commands-processed-hook'
after the commands are processed."
Richard M. Stallman's avatar
Richard M. Stallman committed
681
  (interactive)
Bill Wohler's avatar
Bill Wohler committed
682
  (if mh-folder-view-stack (mh-widen t))
Richard M. Stallman's avatar
Richard M. Stallman committed
683 684
  (mh-process-commands mh-current-folder)
  (mh-set-scan-mode)
Bill Wohler's avatar
Bill Wohler committed
685
  (mh-goto-cur-msg)                    ; after mh-set-scan-mode for efficiency
Richard M. Stallman's avatar
Richard M. Stallman committed
686
  (mh-make-folder-mode-line)
Bill Wohler's avatar
Bill Wohler committed
687
  t)                                    ; return t for write-file-functions
Richard M. Stallman's avatar
Richard M. Stallman committed
688 689

(defun mh-first-msg ()
690
  "Display first message."
Richard M. Stallman's avatar
Richard M. Stallman committed
691
  (interactive)
Karl Heuer's avatar
Karl Heuer committed
692
  (goto-char (point-min))
Bill Wohler's avatar
Bill Wohler committed
693
  (while (and (not (eobp)) (not (looking-at mh-scan-valid-regexp)))
Karl Heuer's avatar
Karl Heuer committed
694
    (forward-line 1)))
Richard M. Stallman's avatar
Richard M. Stallman committed
695 696

(defun mh-header-display ()
697 698 699
  "Display message with all header fields\\<mh-folder-mode-map>.

Use the command \\[mh-show] to show the message normally again."
Richard M. Stallman's avatar
Richard M. Stallman committed
700 701
  (interactive)
  (and (not mh-showing-with-headers)
702
       (or mh-mhl-format-file mh-clean-message-header-flag)
Richard M. Stallman's avatar
Richard M. Stallman committed
703
       (mh-invalidate-show-buffer))
Bill Wohler's avatar
Bill Wohler committed
704
  (let ((mh-decode-mime-flag nil)
705
        (mh-mhl-format-file nil)
Bill Wohler's avatar
Bill Wohler committed
706
        (mh-clean-message-header-flag nil))
Richard M. Stallman's avatar
Richard M. Stallman committed
707 708 709 710 711 712
    (mh-show-msg nil)
    (mh-in-show-buffer (mh-show-buffer)
      (goto-char (point-min))
      (mh-recenter 0))
    (setq mh-showing-with-headers t)))

713
(defun mh-inc-folder (&optional file folder)
714 715 716
  "Incorporate new mail into a folder.

You can incorporate mail from any file into the current folder by
717
specifying a prefix argument; you'll be prompted for the name of
718
the FILE to use as well as the destination FOLDER
719

720
The hook `mh-inc-folder-hook' is run after incorporating new
721
mail.
722

723 724
Do not call this function from outside MH-E; use \\[mh-rmail]
instead."
Richard M. Stallman's avatar
Richard M. Stallman committed
725
  (interactive (list (if current-prefix-arg
Bill Wohler's avatar
Bill Wohler committed
726 727
                         (expand-file-name
                          (read-file-name "inc mail from file: "
Bill Wohler's avatar
Bill Wohler committed
728 729 730 731 732
                                          mh-user-path)))
                     (if current-prefix-arg
                         (mh-prompt-for-folder "inc mail into" mh-inbox t))))
  (if (not folder)
      (setq folder mh-inbox))
Bill Wohler's avatar
Bill Wohler committed
733 734
  (let ((threading-needed-flag nil))
    (let ((config (current-window-configuration)))
Bill Wohler's avatar
Bill Wohler committed
735 736
      (when (and mh-show-buffer (get-buffer mh-show-buffer))
        (delete-windows-on mh-show-buffer))
Bill Wohler's avatar
Bill Wohler committed
737 738 739 740 741 742 743
      (cond ((not (get-buffer folder))
             (mh-make-folder folder)
             (setq threading-needed-flag mh-show-threads-flag)
             (setq mh-previous-window-config config))
            ((not (eq (current-buffer) (get-buffer folder)))
             (switch-to-buffer folder)
             (setq mh-previous-window-config config))))
744
    (mh-get-new-mail file)
Bill Wohler's avatar
Bill Wohler committed
745 746 747 748
    (when (and threading-needed-flag
               (save-excursion
                 (goto-char (point-min))
                 (or (null mh-large-folder)
Bill Wohler's avatar
Bill Wohler committed
749
                     (not (equal (forward-line (1+ mh-large-folder)) 0))
Bill Wohler's avatar
Bill Wohler committed
750 751 752
                     (and (message "Not threading since the number of messages exceeds `mh-large-folder'")
                          nil))))
      (mh-toggle-threads))
Bill Wohler's avatar
Bill Wohler committed
753 754
    (beginning-of-line)
    (if (and mh-showing-mode (looking-at mh-scan-valid-regexp)) (mh-show))
Bill Wohler's avatar
Bill Wohler committed
755
    (run-hooks 'mh-inc-folder-hook)))
Richard M. Stallman's avatar
Richard M. Stallman committed
756 757

(defun mh-last-msg ()
758
  "Display last message."
Richard M. Stallman's avatar
Richard M. Stallman committed
759 760
  (interactive)
  (goto-char (point-max))
Bill Wohler's avatar
Bill Wohler committed
761
  (while (and (not (bobp)) (not (looking-at mh-scan-valid-regexp)))
Bill Wohler's avatar
Bill Wohler committed
762 763
    (forward-line -1))
  (mh-recenter nil))
Richard M. Stallman's avatar
Richard M. Stallman committed
764

765 766 767
(defun mh-next-undeleted-msg (&optional count wait-after-complaining-flag)
  "Display next message.

768 769
This command can be given a prefix argument COUNT to specify how
many unread messages to skip.
770

771 772 773
In a program, pause for a second after printing message if we are
at the last undeleted message and optional argument
WAIT-AFTER-COMPLAINING-FLAG is non-nil."
Karl Heuer's avatar
Karl Heuer committed
774
  (interactive "p")
Richard M. Stallman's avatar
Richard M. Stallman committed
775
  (setq mh-next-direction 'forward)
Karl Heuer's avatar
Karl Heuer committed
776
  (forward-line 1)
777
  (cond ((re-search-forward mh-scan-good-msg-regexp nil t count)
Bill Wohler's avatar
Bill Wohler committed
778 779 780
         (beginning-of-line)
         (mh-maybe-show))
        (t (forward-line -1)
Bill Wohler's avatar
Bill Wohler committed
781 782
           (message "No more undeleted messages")
           (if wait-after-complaining-flag (sit-for 1)))))
Richard M. Stallman's avatar
Richard M. Stallman committed
783

Bill Wohler's avatar
Bill Wohler committed
784
(defun mh-folder-from-address ()
Bill Wohler's avatar
Bill Wohler committed
785 786 787
  "Derive folder name from sender.

The name of the folder is derived as follows:
Bill Wohler's avatar
Bill Wohler committed
788

789 790
  a) The folder name associated with the first address found in
     the list `mh-default-folder-list' is used. Each element in
791
     this list contains a \"Check Recipient\" item. If this item is
792 793
     turned on, then the address is checked against the recipient
     instead of the sender. This is useful for mailing lists.
Bill Wohler's avatar
Bill Wohler committed
794

795 796 797
  b) An alias prefixed by `mh-default-folder-prefix'
     corresponding to the address is used. The prefix is used to
     prevent clutter in your mail directory.
Bill Wohler's avatar
Bill Wohler committed
798

Bill Wohler's avatar
Bill Wohler committed
799
Return nil if a folder name was not derived, or if the variable
800 801
`mh-default-folder-must-exist-flag' is t and the folder does not
exist."
Bill Wohler's avatar
Bill Wohler committed
802
  ;; Loop for all entries in mh-default-folder-list
Bill Wohler's avatar
Bill Wohler committed
803 804
  (save-restriction
    (goto-char (point-min))
Bill Wohler's avatar
Bill Wohler committed
805
    (re-search-forward "\n\n" nil 'limit)
Bill Wohler's avatar
Bill Wohler committed
806 807 808 809 810 811 812 813 814 815
    (narrow-to-region (point-min) (point))
    (let ((to/cc (concat (or (message-fetch-field "to") "") ", "
                         (or (message-fetch-field "cc") "")))
          (from (or (message-fetch-field "from") ""))
          folder-name)
      (setq folder-name
            (loop for list in mh-default-folder-list
                  when (string-match (nth 0 list) (if (nth 2 list) to/cc from))
                  return (nth 1 list)
                  finally return nil))
Bill Wohler's avatar
Bill Wohler committed
816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837

      ;; Make sure a result from `mh-default-folder-list' begins with "+"
      ;; since 'mh-expand-file-name below depends on it
      (when (and folder-name (not (eq (aref folder-name 0) ?+)))
        (setq folder-name (concat "+" folder-name)))

      ;; If not, is there an alias for the address?
      (when (not folder-name)
        (let* ((from-header (mh-extract-from-header-value))
               (address (and from-header
                             (nth 1 (mail-extract-address-components
                                     from-header))))
               (alias (and address (mh-alias-address-to-alias address))))
          (when alias
            (setq folder-name
                  (and alias (concat "+" mh-default-folder-prefix alias))))))

      ;; If mh-default-folder-must-exist-flag set, check that folder exists.
      (if (and folder-name
               (or (not mh-default-folder-must-exist-flag)
                   (file-exists-p (mh-expand-file-name folder-name))))
          folder-name))))
Bill Wohler's avatar
Bill Wohler committed
838 839 840 841 842

(defun mh-prompt-for-refile-folder ()
  "Prompt the user for a folder in which the message should be filed.
The folder is returned as a string.

Bill Wohler's avatar
Bill Wohler committed
843 844 845
The default folder name is generated by the option
`mh-default-folder-for-message-function' if it is non-nil or
`mh-folder-from-address'."
Bill Wohler's avatar
Bill Wohler committed
846 847
  (mh-prompt-for-folder
   "Destination"
Bill Wohler's avatar
Bill Wohler committed
848 849 850 851 852 853 854 855 856 857 858 859 860
   (let ((refile-file (ignore-errors (mh-msg-filename (mh-get-msg-num t)))))
     (if (null refile-file) ""
       (save-excursion
         (set-buffer (get-buffer-create mh-temp-buffer))
         (erase-buffer)
         (insert-file-contents refile-file)
         (or (and mh-default-folder-for-message-function
                  (let ((buffer-file-name refile-file))
                    (funcall mh-default-folder-for-message-function)))
             (mh-folder-from-address)
             (and (eq 'refile (car mh-last-destination-folder))
                  (symbol-name (cdr mh-last-destination-folder)))
             ""))))
Bill Wohler's avatar
Bill Wohler committed
861 862
   t))

Bill Wohler's avatar
Bill Wohler committed
863
(defun mh-refile-msg (range folder &optional dont-update-last-destination-flag)
864 865
  "Refile (output) RANGE into FOLDER.

866 867 868
You are prompted for the folder name. Note that this command can also
be used to create folders. If you specify a folder that does not
exist, you will be prompted to create it.
869

870 871
The hook `mh-refile-msg-hook' is called after a message is marked to
be refiled.
Bill Wohler's avatar
Bill Wohler committed
872

873 874
Check the documentation of `mh-interactive-range' to see how RANGE is
read in interactive use.
Bill Wohler's avatar
Bill Wohler committed
875

876 877 878
In a program, the variables `mh-last-destination' and
`mh-last-destination-folder' are not updated if
DONT-UPDATE-LAST-DESTINATION-FLAG is non-nil."
Bill Wohler's avatar
Bill Wohler committed
879
  (interactive (list (mh-interactive-range "Refile")
Bill Wohler's avatar
Bill Wohler committed
880 881 882 883
                     (intern (mh-prompt-for-refile-folder))))
  (unless dont-update-last-destination-flag
    (setq mh-last-destination (cons 'refile folder)
          mh-last-destination-folder mh-last-destination))
Bill Wohler's avatar
Bill Wohler committed
884
  (mh-iterate-on-range () range
Bill Wohler's avatar
Bill Wohler committed
885
    (mh-refile-a-msg nil folder))
Bill Wohler's avatar
Bill Wohler committed
886
  (when (looking-at mh-scan-refiled-msg-regexp) (mh-next-msg)))
Richard M. Stallman's avatar
Richard M. Stallman committed
887

Bill Wohler's avatar
Bill Wohler committed
888
(defun mh-refile-or-write-again (range &optional interactive-flag)
889 890
  "Repeat last output command.

891 892 893 894
If you are refiling several messages into the same folder, you
can use this command to repeat the last
refile (\\[mh-refile-msg]) or write (\\[mh-write-msg-to-file]).
You can use a range.
895

896 897
Check the documentation of `mh-interactive-range' to see how RANGE is
read in interactive use.
898

899 900
In a program, a non-nil INTERACTIVE-FLAG means that the function was
called interactively."
Bill Wohler's avatar
Bill Wohler committed
901
  (interactive (list (mh-interactive-range "Redo") t))
Richard M. Stallman's avatar
Richard M. Stallman committed
902 903
  (if (null mh-last-destination)
      (error "No previous refile or write"))
904 905
  (cond ((eq (car mh-last-destination) 'refile)
         (mh-refile-msg range (cdr mh-last-destination))
906
         (message "Destination folder: %s" (cdr mh-last-destination)))
907 908 909 910
        (t
         (mh-iterate-on-range msg range
           (apply 'mh-write-msg-to-file msg (cdr mh-last-destination)))
         (mh-next-msg interactive-flag))))
Richard M. Stallman's avatar
Richard M. Stallman committed
911 912

(defun mh-quit ()
Bill Wohler's avatar
Bill Wohler committed
913
  "Quit the current MH-E folder.
914

915 916 917 918 919 920 921 922 923 924 925 926 927 928
When you want to quit using MH-E and go back to editing, you can use
this command. This buries the buffers of the current MH-E folder and
restores the buffers that were present when you first ran
\\[mh-rmail]. It also removes any MH-E working buffers whose name
begins with \" *mh-\" or \"*MH-E \". You can later restore your MH-E
session by selecting the \"+inbox\" buffer or by running \\[mh-rmail]
again.

The two hooks `mh-before-quit-hook' and `mh-quit-hook' are called by
this function. The former one is called before the quit occurs, so you
might use it to perform any MH-E operations; you could perform some
query and abort the quit or call `mh-execute-commands', for example.
The latter is not run in an MH-E context, so you might use it to
modify the window setup."
Richard M. Stallman's avatar
Richard M. Stallman committed
929
  (interactive)
Bill Wohler's avatar
Bill Wohler committed
930
  (run-hooks 'mh-before-quit-hook)
Bill Wohler's avatar
Bill Wohler committed
931 932 933
  (let ((show-buffer (get-buffer mh-show-buffer)))
    (when show-buffer
      (kill-buffer show-buffer)))
Karl Heuer's avatar
Karl Heuer committed
934
  (mh-update-sequences)
Bill Wohler's avatar
Bill Wohler committed
935
  (mh-destroy-postponed-handles)