Annotation of 43BSD/contrib/mh/miscellany/mh-e/mh-e.ml, revision 1.1.1.1

1.1       root        1: ;;;  mh-e.el   (Version: 3.1a for GNU Emacs Version 17)
                      2: 
                      3: ;;;  Copyright (C) James Larus ([email protected], ucbvax!larus), 1985
                      4: ;;;    Please send suggestions and corrections to the above address.
                      5: ;;;
                      6: ;;;  This file contains mh-e, a GNU Emacs front end to the MH mail system.
                      7: 
                      8: 
                      9: ;; GNU Emacs is distributed in the hope that it will be useful,
                     10: ;; but without any warranty.  No author or distributor
                     11: ;; accepts responsibility to anyone for the consequences of using it
                     12: ;; or for whether it serves any particular purpose or works at all,
                     13: ;; unless he says so in writing.
                     14: 
                     15: ;; Everyone is granted permission to copy, modify and redistribute
                     16: ;; GNU Emacs, but only under the conditions described in the
                     17: ;; document "GNU Emacs copying permission notice".   An exact copy
                     18: ;; of the document is supposed to have been given to you along with
                     19: ;; GNU Emacs so that you can know how you may redistribute it all.
                     20: ;; It should be in a file named COPYING.  Among other things, the
                     21: ;; copyright notice and this notice must be preserved on all copies.
                     22: 
                     23: 
                     24: ;;;  Original version for Gosling emacs by Brian Reid, Stanford, 1982.
                     25: ;;;  Modified by James Larus, BBN, July 1984 and UCB, 1984 & 1985.
                     26: ;;;  Rewritten for GNU Emacs, James Larus 1985.
                     27: 
                     28: 
                     29: ;;;  NB MH must have been compiled with the MHE compiler flag or several
                     30: ;;;  features necessary to this program will be missing.
                     31: 
                     32: 
                     33: 
                     34: ;;; Constants:
                     35: 
                     36: ;;; Set for local environment:
                     37: ;;;* These are now in paths.el.
                     38: (defvar mh-progs "/usr/new/mh/"     "Directory containing MH commands")
                     39: (defvar mh-lib   "/usr/new/lib/mh/" "Directory of MH library")
                     40: 
                     41: 
                     42: ;;; Mode hooks:
                     43: 
                     44: (defvar mh-folder-mode-hook nil
                     45:   "*Invoked in mh-folder-mode on a new folder.")
                     46: (defvar mh-letter-mode-hook nil
                     47:   "*Invoked in mh-letter-mode on a new letter.")
                     48: (defvar mh-compose-letter-hook nil
                     49:   "*Invoked in mh-compose-and-send-mail on an outgoing letter.  It is passed
                     50: three arguments: TO recipients, SUBJECT, and CC recipients.")
                     51: 
                     52: 
                     53: ;;; Personal preferences:
                     54: 
                     55: (defvar mh-auto-fill-letters t
                     56:   "*Non-nil means invoke auto-fill-mode in draft messages.")
                     57: (defvar mh-clean-message-header nil
                     58:   "*Non-nil means remove invisible header lines in messages.")
                     59: (defvar mh-use-mhl nil
                     60:   "*Non-nil means use mhl to format messages.")
                     61: (defvar mh-lpr-command-format "lpr -p -J '%s'"
                     62:   "*Format for Unix command line to print a message. The format should be
                     63: a unix command line, with the string \"%s\" where the folder and message
                     64: number should appear.")
                     65: (defvar mh-summary-height 4
                     66:   "*Number of lines in summary window.")
                     67: (defvar mh-ins-buf-prefix ">> "
                     68:   "*String to put before each non-blank line of the the current message
                     69: as it is inserted in an outgoing letter.")
                     70: 
                     71: 
                     72: ;;; Real constants:
                     73: 
                     74: (defvar mh-cmd-note 4                 "Offset to insert notation")
                     75: (defvar mh-invisible-headers
                     76:   "^Received: \\|^Message-Id: \\|^Remailed-\\|^Via: \\|^Mail-from: \\|\^Return-Path: \\|^In-Reply-To: \\|^Resent-"
                     77:   "Regexp specifying headers that are not to be shown.")
                     78: 
                     79: 
                     80: ;;; Global variables:
                     81: 
                     82: (defvar mh-user-path  ""            "User's mail folder.")
                     83: (defvar mh-last-destination nil             "Destination of last "move" command.")
                     84: (defvar mh-folder-mode-map (make-sparse-keymap) "Keymap for MH folders.")
                     85: (defvar mh-letter-mode-map (make-sparse-keymap) "Keymap for composing mail.")
                     86: (defvar mh-pick-mode-map (make-sparse-keymap) "Keymap for searching folder.")
                     87: (defvar mh-folder-list nil          "List of folder names for completion.")
                     88: 
                     89: ;;; Macros:
                     90: 
                     91: (defmacro push (v l)
                     92:   (list 'setq l (list 'cons v l)))
                     93: 
                     94: (defmacro caar (l)
                     95:   (list 'car (list 'car l)))
                     96: 
                     97: (defmacro cadr (l)
                     98:   (list 'car (list 'cdr l)))
                     99: 
                    100: (defmacro cdar (l)
                    101:   (list 'cdr (list 'car l)))
                    102: 
                    103: (defmacro cddr (l)
                    104:   (list 'cdr (list 'cdr l)))
                    105: 
                    106: (defmacro when (pred &rest body)
                    107:   (list 'cond (cons pred body)))
                    108: 
                    109: 
                    110: 
                    111: ;;; Entry points:
                    112: 
                    113: (defun mh-rmail (&optional arg)
                    114:   "Inc(orporate) new mail if optional ARG omitted, or scan a MH mail box
                    115: if arg is present.  This front end uses the MH mail system, which uses
                    116: different conventions from the usual mail system."
                    117:   (interactive "P")
                    118:   (mh-find-path)
                    119:   (if (null mh-folder-list)
                    120:       (setq mh-folder-list (mh-make-folder-list)))
                    121:   (cond (arg
                    122:         (let ((folder (mh-get-folder-name "mh" "+inbox" t))
                    123:               (range (read-string "Range [all]? ")))
                    124:           (mh-scan-folder folder (if (equal range "") "all" range))
                    125:           (delete-other-windows)))
                    126:        (t
                    127:         (mh-inc-folder))))
                    128: 
                    129: 
                    130: (defun mh-smail ()
                    131:   "Send mail using the MH mail system."
                    132:   (interactive)
                    133:   (mh-find-path)
                    134:   (call-interactively 'mh-send))
                    135: 
                    136: 
                    137: 
                    138: ;;; User executable mh-e commands:
                    139: 
                    140: (defun mh-answer (&optional arg)
                    141:   "Answer a letter.  If given an argument, then include the current message
                    142: in the reply."
                    143:   (interactive "P")
                    144:   (let ((msg-filename (mh-msg-filename))
                    145:        (msg (mh-get-msg-num t))
                    146:        (minibuffer-help-form "from => Sender\n  to => Sender and primary recipients\n  cc => Sender and all recipients")
                    147:        (folder mh-current-folder))
                    148:     (let ((reply-to (completing-read "Reply to whom: "
                    149:                                     '(("from") ("to") ("cc"))
                    150:                                      nil t)))
                    151:     (message "Composing a reply...")
                    152:     (cond ((or (equal reply-to "from") (equal reply-to ""))
                    153:           (apply 'mh-exec-cmd
                    154:                  (nconc
                    155:                   (list "repl" "-build" mh-current-folder msg "-nocc" "all")
                    156:                   (if arg (list "-filter" "mhl.reply")))))
                    157:          ((equal reply-to "to")
                    158:           (apply 'mh-exec-cmd
                    159:                  (nconc
                    160:                   (list "repl" "-build" mh-current-folder msg "-cc" "to"
                    161:                         "-nocc" "me")
                    162:                   (if arg (list "-filter" "mhl.reply")))))
                    163:          ((equal reply-to "cc")
                    164:           (apply 'mh-exec-cmd
                    165:                  (nconc
                    166:                   (list "repl" "-build" mh-current-folder msg "-cc" "all")
                    167:                   (if arg (list "-filter" "mhl.reply"))))))
                    168: 
                    169:     (mh-read-draft)
                    170:     (delete-other-windows)
                    171:     (when (or (zerop (buffer-size))
                    172:              (not (y-or-n-p "The file 'draft' exists.  Use for reply? ")))
                    173:       (erase-buffer)
                    174:       (insert-file-contents (format "%sreply" mh-user-path))
                    175:       (delete-file (format "%sreply" mh-user-path)))
                    176:     (set-buffer-modified-p nil)
                    177: 
                    178:     (let ((to (mh-get-field "To:"))
                    179:          (subject (mh-get-field "Subject:"))
                    180:          (cc (mh-get-field "Cc:")))
                    181:       (goto-char (point-min))
                    182:       (re-search-forward "^$" (point-max) nil)
                    183:       (when (not arg)
                    184:        (switch-to-buffer-other-window "*message*")
                    185:        (erase-buffer)
                    186:        (if (file-exists-p msg-filename)
                    187:            (insert-file-contents msg-filename)
                    188:            (error "File %s does not exist" msg-filename))
                    189:        (set-buffer-modified-p nil)
                    190:        (goto-char (point-min))
                    191:        (re-search-forward "^$\\|^-*$")
                    192:        (recenter 0))
                    193:       (message "Composing a reply...done")
                    194:       (mh-compose-and-send-mail "" folder to subject cc "-" "Replied:")))))
                    195: 
                    196: 
                    197: (defun mh-copy-msg (&optional arg)
                    198:   "Copy specified message(s) to another folder without deleting them."
                    199:   (interactive "P")
                    200:   (let ((msgs (if arg
                    201:                  (mh-seq-to-msgs (mh-read-seq "Copy"))
                    202:                  (mh-get-msg-num t))))
                    203:     (mh-exec-cmd-no-wait "refile" msgs "-link" "-src"
                    204:                         mh-current-folder
                    205:                         (mh-get-folder-name "Copy to" "" t))
                    206:     (if arg
                    207:        (mh-notate-seq msgs ?C mh-cmd-note)
                    208:        (mh-notate ?C mh-cmd-note))))
                    209: 
                    210: 
                    211: (defun mh-delete-msg (&optional arg)
                    212:   "Marks the specified message(s) for later deletion."
                    213:   (interactive "P")
                    214:   (if arg
                    215:       (mh-apply-to-seq (mh-read-seq "Delete") 'mh-delete-one-msg)
                    216:       (mh-delete-one-msg))
                    217:   (mh-next-message))
                    218: 
                    219: 
                    220: (defun mh-execute-commands ()
                    221:   "Process outstanding delete and move commands."
                    222:   (interactive)
                    223:   (save-excursion
                    224:     (mh-process-commands mh-current-folder))
                    225:   (delete-other-windows)
                    226:   (setq mh-summarize t)
                    227:   (setq mode-name "Mh-Summary")
                    228:   (setq mode-line-format (mh-make-mode-line)))
                    229: 
                    230: 
                    231: (defun mh-forward (to cc subject)
                    232:   "Forward a letter."
                    233:   (interactive "sTo: \nsCc: \nsSubject: ")
                    234:   (let ((msg-filename (mh-msg-filename))
                    235:        (msg (mh-get-msg-num t))
                    236:        (folder mh-current-folder))
                    237:     (cond ((or (not (file-exists-p (format "%sdraft" mh-user-path)))
                    238:               (y-or-n-p "The file 'draft' exists.  Discard it? "))
                    239:           (mh-exec-cmd "forw" "-build" mh-current-folder msg)
                    240:           (mh-read-draft)
                    241:           (mh-insert-fields "To:" to "Subject:" subject "Cc:" cc))
                    242:          (t
                    243:           (mh-read-draft)))
                    244: 
                    245:     (goto-char (point-min))
                    246:     (delete-other-windows)
                    247:     (mh-compose-and-send-mail "" folder to subject cc "F" "Forwarded-To:")))
                    248: 
                    249: 
                    250: (defun mh-goto (number &optional no-error-if-no-message)
                    251:   "Position the cursor at message NUMBER.  Do not signal an error if optional
                    252: ARG is t.  Return non-nil if cursor is at message."
                    253:   (interactive "nMessage number? ")
                    254:   (let ((starting-place (point)))
                    255:     (goto-char (point-min))
                    256:     (cond ((not (re-search-forward (mh-msg-search-pat number) nil t))
                    257:           (goto-char starting-place)
                    258:           (if (not no-error-if-no-message) (error "No message %d " number))
                    259:           nil)
                    260:          (t
                    261:           (beginning-of-line)
                    262:           (mh-maybe-show)
                    263:           t))))
                    264: 
                    265: 
                    266: (defun mh-inc-folder ()
                    267:   "inc(orporate) new mail into inbox."
                    268:   (interactive)
                    269:   (switch-to-buffer-other-window "+inbox")
                    270:   (if (or (not (boundp 'mh-current-folder)) (null mh-current-folder))
                    271:       (mh-make-folder "+inbox"))
                    272:   (if (mh-get-new-mail)
                    273:       (mh-show)))
                    274: 
                    275: 
                    276: (defun mh-indicate-seq (&optional arg)
                    277:   "Add the specified message(s) to a sequence."
                    278:   (interactive "P")
                    279:   (let ((new-seq (mh-letter-to-seq last-input-char))
                    280:        (old-seq (if (looking-at "^[0-9a-z]")
                    281:                     (mh-letter-to-seq (char-after (point))))))
                    282:     (if old-seq
                    283:        (if arg
                    284:            (mh-remove-seq old-seq)
                    285:            (mh-remove-msg-from-seq (mh-get-msg-num t) old-seq)))
                    286:     (if (and (not arg)
                    287:             (or (not old-seq) (not (equal new-seq old-seq))))
                    288:        (mh-add-msg-to-seq (mh-get-msg-num t) new-seq)))
                    289:     (mh-next-message))
                    290: 
                    291: 
                    292: (defun mh-kill-folder ()
                    293:   "Removes the current folder."
                    294:   (interactive)
                    295:   (if (yes-or-no-p (format "Remove folder %s? " mh-current-folder))
                    296:       (let ((buffer mh-current-folder))
                    297:        (switch-to-buffer-other-window " *mh-temp*")
                    298:        (mh-exec-cmd "rmf" buffer)
                    299:        (mh-remove-folder-from-folder-list buffer)
                    300:        (message "Folder removed")
                    301:        (kill-buffer buffer))
                    302:       (message "Folder not removed")))
                    303: 
                    304: 
                    305: (defun mh-list-folders ()
                    306:   "List mail folders."
                    307:   (interactive)
                    308:   (message "listing folders...")
                    309:   (switch-to-buffer-other-window " *mh-temp*")
                    310:   (erase-buffer)
                    311:   (mh-exec-cmd-output "folders")
                    312:   (goto-char (point-min))
                    313:   (message "listing folders...done"))
                    314: 
                    315: 
                    316: (defun mh-move-msg (&optional arg)
                    317:   "Move specified message(s) to another folder."
                    318:   (interactive "P")
                    319:   (setq mh-last-destination (mh-get-folder-name "Destination" "" t))
                    320:   (if arg
                    321:       (mh-apply-to-seq (mh-read-seq "Move") 'mh-move-one-msg)
                    322:       (mh-move-one-msg))
                    323:   (mh-next-message))
                    324: 
                    325: 
                    326: (defun mh-next-line (&optional arg)
                    327:   "Move to next undeleted message in window and display body if summary
                    328: flag set."
                    329:   (interactive "p")
                    330:   (forward-line (if arg arg 1))
                    331:   (setq mh-next-direction 'forward)
                    332:   (cond ((re-search-forward "^....[^D^]" nil 0 arg)
                    333:         (beginning-of-line)
                    334:         (mh-maybe-show))
                    335:        (t
                    336:         (forward-line -1)
                    337:         (message "No more messages"))))
                    338: 
                    339: 
                    340: (defun mh-renumber-folder ()
                    341:   "Renumber messages in folder to be 1..N."
                    342:   (interactive)
                    343:   (message "packing buffer...")
                    344:   (mh-pack-folder)
                    345:   (mh-unmark-all-headers nil)
                    346:   (mh-position-to-current)
                    347:   (message "packing buffer...done"))
                    348: 
                    349: 
                    350: (defun mh-page-digest ()
                    351:   "Advance displayed message to next digested message."
                    352:   (interactive)
                    353:   (save-excursion
                    354:     (switch-to-buffer-other-window mh-show-buffer)
                    355:     (move-to-window-line nil)
                    356:     (let ((case-fold-search nil))
                    357:       (when (not (search-forward "\nFrom:" nil t))
                    358:        (other-window -1)
                    359:        (error "No more messages")))
                    360:     (recenter 0)
                    361:     (other-window -1)))
                    362: 
                    363: 
                    364: (defun mh-page-msg (&optional arg)
                    365:   (interactive "P")
                    366:   (scroll-other-window arg))
                    367: 
                    368: 
                    369: (defun mh-previous-line (&optional arg)
                    370:   "Move to previous message in window and display body if summary flag set."
                    371:   (interactive "p")
                    372:   (setq mh-next-direction 'backward)
                    373:   (if (not (re-search-backward "^....[^D^]" nil 0 arg))
                    374:       (message "Beginning of messages")
                    375:       (mh-maybe-show)))
                    376: 
                    377: 
                    378: (defun mh-previous-page ()
                    379:   "Page the displayed message backwards."
                    380:   (interactive)
                    381:   (save-excursion
                    382:     (switch-to-buffer-other-window mh-show-buffer)
                    383:     (scroll-down nil)
                    384:     (other-window -1)))
                    385: 
                    386: 
                    387: (defun mh-print-msg (&optional arg)
                    388:   "Print specified message(s) on a line printer."
                    389:   (interactive "P")
                    390:   (let ((msgs (if arg
                    391:                  (reverse (mh-seq-to-msgs (mh-read-seq "Print")))
                    392:                  (list (mh-get-msg-num t)))))
                    393:     (message "printing message...")
                    394:     (call-process "/bin/sh" nil 0 nil "-c"
                    395:                  (format "%smhl -nobell -clear %s | %s" mh-lib
                    396:                          (mh-msg-filenames msgs mh-folder-filename)
                    397:                          (format mh-lpr-command-format
                    398:                                  (if arg
                    399:                                      "Mail"
                    400:                                      (format "%s/%d" mh-current-folder
                    401:                                              (mh-get-msg-num t))))))
                    402:     (message "printing message...done")))
                    403: 
                    404: 
                    405: (defun mh-rescan-folder (&optional arg)
                    406:   "Optionally process commands in current folder and (re)scan it."
                    407:   (interactive "P")
                    408:   (if (and (or mh-delete-list mh-move-list)
                    409:           (y-or-n-p "Process commands? "))
                    410:       (mh-process-commands mh-current-folder))
                    411:   (setq mh-next-direction 'forward)
                    412:   (mh-scan-folder mh-current-folder
                    413:                  (if arg (read-string "Range [all]? ") "all")))
                    414: 
                    415: 
                    416: (defun mh-redistribute (to cc)
                    417:   "Redistribute a letter."
                    418:   (interactive "sTo: \nsCc: ")
                    419:   (let ((msg-filename (mh-msg-filename))
                    420:        (msg (mh-get-msg-num t))
                    421:        (folder mh-current-folder))
                    422:     (mh-read-draft)
                    423:     (delete-other-windows)
                    424:     (when (or (zerop (buffer-size))
                    425:              (not (y-or-n-p
                    426:                    "The file 'draft' exists.  Redistribute old version? ")))
                    427:       (erase-buffer)
                    428:       (insert-file-contents msg-filename)
                    429:       (goto-char (point-min))
                    430:       (insert "Resent-To: " to "\n")
                    431:       (if (not (equal cc ""))
                    432:          (insert "Resent-cc: " cc "\n")))
                    433:     (mh-compose-and-send-mail "-dist" folder to (mh-get-field "Subject:") cc
                    434:                              "F" "Distributed-to:")))
                    435: 
                    436: 
                    437: (defun mh-re-move ()
                    438:   "Move specified message to same folder as last move."
                    439:   (interactive)
                    440:   (if (null mh-last-destination)
                    441:       (error "No previous move"))
                    442:   (mh-move-one-msg)
                    443:   (mh-next-message))
                    444: 
                    445: 
                    446: (defun mh-save-message (file)
                    447:   "Append the current message to the end of a file."
                    448:   (interactive "FSave message in file: ")
                    449:   (let ((msg-filename (mh-msg-filename)))
                    450:     (call-process "/bin/csh" nil 0 nil "-c"
                    451:                  (format "cat %s >> %s " msg-filename file))))
                    452: 
                    453:     
                    454: (defun mh-search-folder ()
                    455:   "Search the current folder for messages matching a pattern."
                    456:   (interactive)
                    457:   (let ((folder mh-current-folder))
                    458:     (switch-to-buffer-other-window "pick-pattern")
                    459:     (if (or (zerop (buffer-size))
                    460:            (not (y-or-n-p "Reuse pattern? ")))
                    461:        (mh-make-pick-template)
                    462:        (message ""))
                    463:     (setq mh-searching-folder folder)))
                    464: 
                    465: 
                    466: (defun mh-send (to cc subject)
                    467:   "Compose and send a letter."
                    468:   (interactive "sTo: \nsCc: \nsSubject: ")
                    469:   (let ((folder (if (boundp 'mh-current-folder) mh-current-folder)))
                    470:     (message "Composing a message...")
                    471:     (mh-read-draft)
                    472:     (delete-other-windows)
                    473:     (when (or (zerop (buffer-size))
                    474:              (not (y-or-n-p "The file 'draft' exists.  Use it? ")))
                    475:       (erase-buffer)
                    476:       (if (file-exists-p (format "%scomponents" mh-user-path))
                    477:          (insert-file-contents (format "%scomponents" mh-user-path))
                    478:          (if (file-exists-p (format "%scomponents" mh-lib))
                    479:              (insert-file-contents (format "%scomponents" mh-lib))
                    480:              (error "Can't find components")))
                    481:       (mh-insert-fields "To:" to "Subject:" subject "Cc:" cc)
                    482:       (goto-char (point-max))
                    483:       (message "Composing a message...done"))
                    484:     (mh-compose-and-send-mail "" folder to subject cc)))
                    485: 
                    486: 
                    487: (defun mh-show ()
                    488:   "Show message indicated by cursor in scan buffer."
                    489:   (interactive)
                    490:   (setq mh-summarize nil)
                    491:   (setq mode-name "Mh-Show")
                    492:   (let ((msgn (mh-get-msg-num t))
                    493:        (msg-filename (mh-msg-filename))
                    494:        (folder mh-current-folder))
                    495:     (if (not (file-exists-p msg-filename))
                    496:        (error "Message %d does not exist." msgn))
                    497:     (switch-to-buffer mh-show-buffer)
                    498:     (erase-buffer)
                    499:     (if mh-use-mhl
                    500:        (mh-exec-lib-cmd-output "mhl" "-nobell" msg-filename)
                    501:        (insert-file-contents msg-filename))
                    502:     (setq buffer-file-name msg-filename)
                    503:     (goto-char (point-min))
                    504:     (cond (mh-clean-message-header
                    505:           (mh-clean-message-header (point-min))
                    506:           (goto-char (point-min)))
                    507:          (t
                    508:           (let ((case-fold-search t))
                    509:             (re-search-forward "^To:\\|^From:\\|^Subject:\\|^Date:" nil t)
                    510:             (beginning-of-line)
                    511:             (recenter 0))))
                    512:     (set-buffer-modified-p nil)
                    513:     (setq mode-line-format
                    514:          (concat "{%b} %[%p of " folder "/" msgn "%]   %M"))
                    515:     ;; These contortions are to force the summary line to be the top window.
                    516:     (switch-to-buffer-other-window folder)
                    517:     (delete-other-windows)
                    518:     (switch-to-buffer-other-window mh-show-buffer)
                    519:     (switch-to-buffer-other-window folder)
                    520:     (shrink-window (- (window-height) mh-summary-height))
                    521:     (recenter 1)
                    522:     ;; Remove from unseen seq.
                    523:     (mh-exec-cmd-no-wait "mark" mh-current-folder msgn "-seq" "unseen"
                    524:                         "-delete" "-nolist")))
                    525: 
                    526: 
                    527: (defun mh-sort-folder (&optional arg)
                    528:   "Sort the messages in the current folder by date."
                    529:   (interactive "P")
                    530:   (mh-process-commands mh-current-folder)
                    531:   (setq mh-next-direction 'forward)
                    532:   (message "sorting folder...")
                    533:   (mh-exec-cmd "sortm" mh-current-folder)
                    534:   (message "sorting folder...done")
                    535:   (mh-scan-folder mh-current-folder "all"))
                    536: 
                    537: 
                    538: (defun mh-summary ()
                    539:   "Show a summary of mh-e commands."
                    540:   (interactive)
                    541:   (message
                    542: "Next Prev Go Del ^ ! Copy Undo . Toggle Ans Forw Redist Send List Execute")
                    543:   (sit-for 5))
                    544: 
                    545: 
                    546: (defun mh-toggle-summarize ()
                    547:   "Turn the summary mode of displaying messages on or off."
                    548:   (interactive)
                    549:   (setq mh-summarize (not mh-summarize))
                    550:   (cond (mh-summarize
                    551:         (delete-other-windows)
                    552:         (setq mode-name "Mh-Summarize")
                    553:         (recenter))
                    554:        (t
                    555:         (setq mode-name "Mh-Show")
                    556:         (mh-show))))
                    557: 
                    558: 
                    559: (defun mh-undo (&optional arg)
                    560:   "Undo the deletion or move of the specified message(s)."
                    561:   (interactive "P")
                    562:   (cond ((looking-at "^....D")
                    563:         (let ((msgs (if arg (mh-read-seq "Undelete") (mh-get-msg-num t))))
                    564:           (setq mh-delete-list (delq msgs mh-delete-list))
                    565:           (if arg
                    566:               (mh-notate-seq msgs ?  mh-cmd-note)
                    567:               (mh-notate ?  mh-cmd-note))))
                    568: 
                    569:        ((looking-at "^....^")
                    570:         (let ((msgs (if arg (mh-read-seq "Unmove") (mh-get-msg-num t))))
                    571:           (mapcar
                    572:            (function (lambda (move) (setcdr move (delq msgs (cdr move)))))
                    573:            mh-move-list)
                    574:           (if arg
                    575:               (mh-notate-seq msgs ?  mh-cmd-note)
                    576:               (mh-notate ?  mh-cmd-note))))
                    577: 
                    578:        (t nil)))
                    579: 
                    580: 
                    581: (defun mh-visit-folder (&optional arg)
                    582:   "Visit a new folder."
                    583:   (interactive "p")
                    584:   (let ((folder (mh-get-folder-name "Visit" "" t))
                    585:        (range (if arg (read-string "Range [all]? ") "all")))
                    586:     (mh-scan-folder folder (if (equal range "") "all" range))
                    587:     (delete-other-windows)))
                    588: 
                    589: 
                    590: 
                    591: ;;; Support routines.
                    592: 
                    593: (defun mh-delete-one-msg ()
                    594:   "Delete the message pointed to by the cursor."
                    595:   (if (looking-at "....^")
                    596:       (error "Message %d already moved.  Undo move before deleting."
                    597:             (mh-get-msg-num t)))
                    598:   (push (mh-get-msg-num t) mh-delete-list)
                    599:   (mh-notate ?D mh-cmd-note))
                    600: 
                    601: 
                    602: (defun mh-move-one-msg ()
                    603:   "Move the message pointed to by the cursor."
                    604:   (if (looking-at "....D")
                    605:       (error "Message %d is already deleted.  Undo delete before moving."
                    606:             (mh-get-msg-num nil))
                    607:       (let ((others (assoc mh-last-destination mh-move-list))
                    608:            (msg (mh-get-msg-num t)))
                    609:        (if others
                    610:            (setcdr others (cons msg (cdr others)))
                    611:            (push (cons mh-last-destination (list msg)) mh-move-list))
                    612:        (mh-notate ?^ mh-cmd-note))))
                    613: 
                    614: 
                    615: (defun mh-clean-message-header (start)
                    616:   "Flush extraneous lines in a message header.  The variable
                    617: mh-invisible-headers contains a regular expression specifying these lines."
                    618:   (save-restriction
                    619:     (goto-char start)
                    620:     (search-forward "\n\n" nil t)
                    621:     (narrow-to-region start (point))
                    622:     (goto-char (point-min))
                    623:     (while (re-search-forward mh-invisible-headers nil t)
                    624:       (beginning-of-line)
                    625:       (kill-line 1)
                    626:       (while (looking-at "^[ \t]+")
                    627:        (beginning-of-line)
                    628:        (kill-line 1)))))
                    629: 
                    630: 
                    631: (defun mh-read-draft ()
                    632:   "Read draft file into buffer draft.  No errors if disk file has been
                    633: modified."
                    634:   (switch-to-buffer "draft")
                    635:   (set-buffer-modified-p nil)
                    636:   (kill-buffer "draft")
                    637:   (switch-to-buffer-other-window
                    638:    (find-file-noselect (format "%sdraft" mh-user-path))))
                    639: 
                    640: 
                    641: (defun mh-next-message ()
                    642:   "Move backward or forward to the next message in the buffer."
                    643:   (if (eq mh-next-direction 'forward)
                    644:       (mh-next-line 1)
                    645:       (mh-previous-line 1)))
                    646: 
                    647: 
                    648: (defun mh-maybe-show ()
                    649:   "If the scan listing is not summarized, show the message pointed to
                    650: by the cursor."
                    651:   (if (not mh-summarize) (mh-show)))
                    652: 
                    653: 
                    654: 
                    655: ;;; The folder data abstraction.
                    656: 
                    657: (defun mh-make-folder (name)
                    658:   "Create and initialize a new mail folder called NAME and make
                    659: it the current folder."
                    660:   (switch-to-buffer name)
                    661:   (kill-all-local-variables)
                    662:   (setq buffer-read-only nil)
                    663:   (erase-buffer)
                    664:   (make-local-variable 'mh-current-folder) ; Name of folder
                    665:   (setq mh-current-folder name)
                    666:   (make-local-variable 'mh-show-buffer) ; Buffer that displays messages
                    667:   (setq mh-show-buffer (format "show-%s" mh-current-folder))
                    668:   (make-local-variable 'mh-folder-filename) ; e.g. /usr/foobar/Mail/inbox/
                    669:   (setq mh-folder-filename (format "%s%s/" mh-user-path (substring name 1)))
                    670:   (make-local-variable 'mh-summarize)   ; Show scan list only?
                    671:   (setq mh-summarize t)
                    672:   (make-local-variable 'mh-next-seq-num)  ; Index of free sequence id
                    673:   (setq mh-next-seq-num 0)
                    674:   (make-local-variable 'mh-delete-list)         ; List of msgs nums to delete
                    675:   (setq mh-delete-list nil)
                    676:   (make-local-variable 'mh-move-list)   ; Alist of dest . msgs nums
                    677:   (setq mh-move-list nil)
                    678:   (make-local-variable 'mh-seq-list)    ; Alist of seq . msgs nums
                    679:   (setq mh-seq-list nil)
                    680:   (make-local-variable 'mh-next-direction) ; Direction to move to next message
                    681:   (setq mh-next-direction 'forward)
                    682:   (mh-folder-mode)
                    683:   (setq buffer-read-only t)
                    684:   (setq mode-name "Mh-Summarize"))
                    685: 
                    686: 
                    687: (defun mh-folder-mode ()
                    688:   "    \\[mh-next-line]: next message                  \\[mh-previous-line]: previous message
                    689:     \\[mh-delete-msg]: delete (mark for deletion)      \\[mh-move-msg]: put (mark for moving)
                    690:     \\[mh-undo]: undo last delete or mark              \\[mh-re-move]: repeat last ^ command
                    691:     \\[mh-copy-msg]: copy message to another folder
                    692:     \\[mh-show]: type message                  \\[mh-toggle-summarize]: toggle summarize mode
                    693:     \\[mh-page-msg] page message                       \\[mh-previous-page]: page message backwards
                    694:     \\[mh-print-msg]: print message                    \\[mh-goto]: goto a message
                    695:     \\[mh-execute-commands]: execute pending delete and move commands
                    696:     \\[mh-send]: send a message                        \\[mh-redistribute]: redistribute a message
                    697:     \\[mh-answer]: answer a message                    \\[mh-forward]: forward a message
                    698:     \\[mh-visit-folder]: visit folder                  \\[mh-inc-folder]: inc mail
                    699:     \\[mh-kill-folder]: kill folder                    \\[mh-list-folders]: list folders
                    700:     \\[mh-renumber-folder]: pack folder                        \\[mh-rescan-folder]: rescan folder
                    701:     \\[mh-search-folder]: search folder                        \\[mh-sort-folder]: sorts the letters in the folder
                    702: 
                    703:     0..9 Add a message to a numbered sequence
                    704: 
                    705: A prefix argument to delete, move, list, or undo applies to a sequence.
                    706: 
                    707: Edit the scan list, marking messages. Moving and deleting messages is
                    708: deferred until you type \\[mh-execute-commands]."
                    709:   (use-local-map mh-folder-mode-map)
                    710:   (setq major-mode 'mh-folder-mode)
                    711:   (setq mode-name "mh-folder")
                    712:   (if (and (boundp 'mh-folder-mode-hook) mh-folder-mode-hook)
                    713:       (funcall mh-folder-mode-hook)))
                    714: 
                    715: 
                    716: (defun mh-scan-folder (folder range)
                    717:   "Scan the folder FOLDER over the range RANGE.  Return in the folder."
                    718:   (if (null (get-buffer folder))
                    719:       (mh-make-folder folder)
                    720:       (switch-to-buffer-other-window folder))
                    721:   (mh-regenerate-headers range)
                    722:   (when (looking-at "scan: no messages ")
                    723:       (let ((buffer-read-only nil))
                    724:        (erase-buffer))
                    725:       (if (equal range "all")
                    726:          (message  "Folder %s is empty" folder)
                    727:          (message  "No messages in %s, range %s" folder range))
                    728:       (sit-for 5))
                    729:   (setq mode-line-format (mh-make-mode-line))
                    730:   (mh-unmark-all-headers nil)
                    731:   (mh-position-to-current))
                    732: 
                    733: 
                    734: (defun mh-regenerate-headers (range)
                    735:   "Replace buffer with scan of its contents over range RANGE."
                    736:   (let ((buffer-read-only nil))
                    737:     (message (format "scanning %s..." (buffer-name)))
                    738:     (delete-other-windows)
                    739:     (erase-buffer)
                    740:     (mh-exec-cmd-output "scan" (buffer-name) range)
                    741:     (goto-char (point-min))
                    742:     (message (format "scanning %s...done" (buffer-name)))
                    743:     ))
                    744: 
                    745: 
                    746: (defun mh-get-new-mail ()
                    747:   "Read new mail into the current buffer.  Return t if there was new mail,
                    748: nil otherwise.  Return in the current buffer."
                    749:   (let ((buffer-read-only nil))
                    750:     (message (format "inc %s..." (buffer-name)))
                    751:     (mh-unmark-all-headers nil)
                    752:     (setq mh-next-direction 'forward)
                    753:     (goto-char (point-max))
                    754:     (let ((start-of-inc (point)))
                    755:       (mh-exec-cmd-output "inc")
                    756:       (message (format "inc %s...done" (buffer-name)))
                    757:       (goto-char start-of-inc)
                    758:       (cond ((looking-at "inc: no mail")
                    759:             (kill-line 1)
                    760:             (setq mode-line-format (mh-make-mode-line))
                    761:             (previous-line 1)
                    762:             (message "No new mail")
                    763:             (sit-for 5)
                    764:             nil)
                    765:            (t
                    766:             (kill-line 2)
                    767:             (setq mode-line-format (mh-make-mode-line))
                    768:             t)))))
                    769: 
                    770: 
                    771: (defun mh-make-mode-line ()
                    772:   "Returns a string for mode-line-format."
                    773:   (save-excursion
                    774:     (let ((lines (count-lines (point-min) (point-max))))
                    775:       (goto-char (point-min))
                    776:       (let* ((first (mh-get-msg-num nil))
                    777:             (case-fold-search nil)
                    778:             (current (and (re-search-forward "....\\+" nil t)
                    779:                           (mh-get-msg-num nil))))
                    780:        (goto-char (point-max))
                    781:        (previous-line 1)
                    782:        (let ((last (mh-get-msg-num nil)))
                    783:          (concat "{%b} %[" lines " messages"
                    784:                  (if (> lines 0)
                    785:                      (format " (%d - %d)" first last)
                    786:                      "")
                    787:                  (if current
                    788:                      (format " cur = %d" current)
                    789:                      "")
                    790:                  "%]   (%p%% - %m)"))))))
                    791: 
                    792: 
                    793: (defun mh-unmark-all-headers (remove-all-flags)
                    794:   "This function removes all + flags from the headers, and if called
                    795:   with a non-nil argument, removes all D and ^ flags too."
                    796:   (let ((buffer-read-only nil)
                    797:        (case-fold-search nil))
                    798:     (goto-char (point-min))
                    799:     (while (if remove-all-flags
                    800:               (re-search-forward "^....\\D\\|^....\\^\\|^....\\+" nil t)
                    801:               (re-search-forward "^....\\+" nil t))
                    802:       (delete-backward-char 1)
                    803:       (insert " "))))
                    804: 
                    805: 
                    806: (defun mh-position-to-current ()
                    807:   "Position the cursor at the current message."
                    808:   (let ((curmsg (mh-get-cur-msg mh-folder-filename)))
                    809:     (cond ((or (zerop curmsg) (mh-goto curmsg t))
                    810:           (goto-char (point-max))
                    811:           (forward-line -1)
                    812:           (mh-maybe-show)
                    813:           (message "No current message"))
                    814:          (t
                    815:           (mh-notate ?+ 4)
                    816:           (recenter 0)))))
                    817: 
                    818: 
                    819: (defun mh-pack-folder ()
                    820:   "Closes and packs the current folder."
                    821:   (let ((buffer-read-only nil))
                    822:     (message "closing folder...")
                    823:     (mh-process-commands mh-current-folder)
                    824:     (message "packing folder...")
                    825:     (mh-exec-cmd-quiet "folder" mh-current-folder "-pack")
                    826:     (mh-regenerate-headers "all")
                    827:     (message "packing done"))
                    828:   (setq mode-line-format (mh-make-mode-line)))
                    829: 
                    830: 
                    831: (defun mh-apply-to-message-list (func list)
                    832:   "Apply function FUNC to each item in a message-list LIST,
                    833: passing the name and list of messages as arguments."
                    834:   (mapcar (function (lambda (l) (apply func (list (car l) (cdr l))))) list))
                    835: 
                    836: 
                    837: (defun mh-process-commands (buffer)
                    838:   "Process outstanding commands for the buffer BUFFER."
                    839:   (message "Processing deletes and moves...")
                    840:   (switch-to-buffer buffer)
                    841:   (let ((buffer-read-only nil))
                    842:     ;; Sequences must be first
                    843:     (mh-process-seq-commands mh-seq-list)
                    844: 
                    845:     ;; Then refile messages
                    846:     (mh-apply-to-message-list
                    847:      (function (lambda (dest msgs)
                    848:                 (apply 'mh-exec-cmd
                    849:                        (nconc (cons "refile" msgs)
                    850:                               (list "-src" (format "%s" buffer) dest)))))
                    851:      mh-move-list)
                    852: 
                    853:     ;; Now delete messages
                    854:     (if mh-delete-list
                    855:        (apply 'mh-exec-cmd
                    856:               (nconc (list "rmm" (format "%s" buffer)) mh-delete-list)))
                    857: 
                    858:     ;; Mark as cur message.
                    859:     (if (mh-get-msg-num nil)
                    860:        (mh-exec-cmd-no-wait "mark" mh-current-folder (mh-get-msg-num nil)
                    861:                             "-seq" "cur" "-add" "-zero" "-nolist")
                    862:        (mh-exec-cmd-no-wait "mark" mh-current-folder "-seq" "cur" "-delete"
                    863:                             "all" "-nolist"))
                    864: 
                    865:     (switch-to-buffer buffer)
                    866:     (goto-char (point-min))
                    867:     (flush-lines "^....D")
                    868:     (goto-char (point-min))
                    869:     (flush-lines "^....^")
                    870:     (setq mh-delete-list nil
                    871:          mh-move-list nil
                    872:          mh-seq-list nil))
                    873:   (message "Processing deletes and moves...done"))
                    874: 
                    875: 
                    876: 
                    877: ;;; A mode for composing and sending a message.
                    878: 
                    879: (defun mh-letter-mode ()
                    880:   "Mode for composing letters in mh-e.
                    881: Like text-mode, but with these additional commands:
                    882:     \\[mh-send-letter]: sends the message.
                    883:     \\[mh-insert-letter]: inserts a message into the current letter.
                    884:     \\[mh-to-to]: move to the To: field                \\[mh-to-subject]: move to the Subject: field
                    885:     \\[mh-to-cc]: move to the Cc: field                \\[mh-to-bcc]: move to the Bcc: field
                    886:     \\[mh-to-fcc]: move to the Fcc: field
                    887:     \\[mh-check-whom]: report who a message will go to
                    888:     \\[kill-buffer]: quit draft and delete it."
                    889:   (text-mode)
                    890:   (if mh-auto-fill-letters
                    891:       (auto-fill-mode 1))
                    892:   (make-local-variable 'paragraph-start)
                    893:   (setq paragraph-start (concat "^[ \t]*[-_][-_][-_]+$\\|" paragraph-start))
                    894:   (make-local-variable 'paragraph-separate)
                    895:   (setq paragraph-separate
                    896:        (concat "^[ \t]*[-_][-_][-_]+$\\|" paragraph-separate))
                    897:   (use-local-map mh-letter-mode-map)
                    898:   (setq major-mode 'mh-letter-mode)
                    899:   (setq mode-name "mh-letter")
                    900:   (if (and (boundp 'mh-letter-mode-hook) mh-letter-mode-hook)
                    901:       (funcall mh-letter-mode-hook)))
                    902: 
                    903: 
                    904: (defun mh-to-to ()
                    905:   "Move point to end of To: field."
                    906:   (interactive)
                    907:   (expand-abbrev)
                    908:   (mh-position-on-field "To:" t))
                    909: 
                    910: 
                    911: (defun mh-to-subject ()
                    912:   "Move point to end of Subject: field."
                    913:   (interactive)
                    914:   (expand-abbrev)
                    915:   (mh-position-on-field "Subject:" t))
                    916: 
                    917: 
                    918: (defun mh-to-cc ()
                    919:   "Move point to end of Cc: field.  Creates the field if necessary"
                    920:   (interactive)
                    921:   (expand-abbrev)
                    922:   (when (not (mh-position-on-field "Cc:" t))
                    923:     (mh-position-on-field "To:" nil)
                    924:     (insert-string "\nCc: ")))
                    925: 
                    926: 
                    927: (defun mh-to-bcc ()
                    928:   "Move point to end of Bcc: field.  Creates the field if necessary"
                    929:   (interactive)
                    930:   (expand-abbrev)
                    931:   (when (not (mh-position-on-field "Bcc:" t))
                    932:     (mh-position-on-field "To:" nil)
                    933:     (insert-string "\nBcc: ")))
                    934: 
                    935: 
                    936: (defun mh-to-fcc ()
                    937:   "Move point to end of Fcc: field.  Creates the field if necessary"
                    938:   (interactive)
                    939:   (expand-abbrev)
                    940:   (when (not (mh-position-on-field "Fcc:" t))
                    941:     (mh-position-on-field "To:" nil)
                    942:     (insert-string "\nFcc: ")))
                    943: 
                    944: 
                    945: (defun mh-check-whom ()
                    946:   "List recipients of the current message."
                    947:   (interactive)
                    948:   (let ((file-name (buffer-file-name)))
                    949:     (save-buffer)
                    950:     (message "Checking recipients...")
                    951:     (switch-to-buffer-other-window "*Mail Recipients*")
                    952:     (erase-buffer)
                    953:     (mh-exec-cmd-output "whom" file-name)
                    954:     (previous-window)))
                    955: 
                    956: 
                    957: 
                    958: ;;; Routines to make a search pattern and search for a message.
                    959: 
                    960: (defun mh-make-pick-template ()
                    961:   "Initialize a buffer with a template for a pick pattern."
                    962:   (erase-buffer)
                    963:   (kill-all-local-variables)
                    964:   (make-local-variable 'mh-searching-folder)
                    965:   (insert "From: \n"
                    966:          "To: \n"
                    967:          "Cc: \n"
                    968:          "Date: \n"
                    969:          "Subject: \n"
                    970:          "---------\n")
                    971:   (mh-letter-mode)
                    972:   (use-local-map mh-pick-mode-map)
                    973:   (setq mode-line-format "{%b}\tPick Pattern\t(^C^C to do search)")
                    974:   (goto-char (point-min))
                    975:   (end-of-line))
                    976: 
                    977: 
                    978: (defun mh-do-pick-search ()
                    979:   "Search for the messages in the current folder meeting the qualification
                    980: in the current buffer and make them into a sequence."
                    981:   (interactive)
                    982:   (let* ((pattern-buffer (buffer-name))
                    983:         (searching-buffer mh-searching-folder)
                    984:         (range "all")
                    985:         (seq (mh-new-seq mh-searching-folder))
                    986:         (pattern nil))
                    987:     (message "Searching...")
                    988:     (goto-char (point-min))
                    989:     (while (setq pattern (mh-next-pick-field pattern-buffer))
                    990:       (setq msgs
                    991:            (mh-seq-from-command searching-buffer
                    992:                                 seq
                    993:                                 (nconc (cons "pick" pattern)
                    994:                                        (list searching-buffer
                    995:                                              range
                    996:                                              "-sequence" seq "-list"))))
                    997:       (setq range seq))
                    998:     (message "Searching...done")
                    999:     (switch-to-buffer searching-buffer)
                   1000:     (mh-notate-seq seq (mh-seq-to-notation seq) 0)))
                   1001: 
                   1002: 
                   1003: (defun mh-next-pick-field (buffer)
                   1004:   "Return the next piece of a pick argument that can be extracted from the
                   1005: BUFFER.  Returns nil if no pieces remain."
                   1006:   (switch-to-buffer buffer)
                   1007:   (let ((case-fold-search t))
                   1008:     (cond ((eobp)
                   1009:           nil)
                   1010:          ((re-search-forward "^\\([a-z].*\\):[ \t]*\\([a-z0-9].*\\)$" nil t)
                   1011:           (let* ((component
                   1012:                   (format "-%s"
                   1013:                           (downcase (buffer-substring (match-beginning 1)
                   1014:                                                       (match-end 1)))))
                   1015:                  (pat (buffer-substring (match-beginning 2) (match-end 2))))
                   1016:               (forward-line 1)
                   1017:               (list component pat)))
                   1018:          ((re-search-forward "^-*$" nil t)
                   1019:           (forward-char 1)
                   1020:           (let ((body (buffer-substring (point) (point-max))))
                   1021:             (if (and (> (length body) 0) (not (equal body "\n")))
                   1022:                 (list "-search" body)
                   1023:                 nil)))
                   1024:          (t
                   1025:           nil))))
                   1026: 
                   1027: 
                   1028: 
                   1029: ;;; Routines compose and send a letter.
                   1030: 
                   1031: (defun mh-compose-and-send-mail (send-args sent-from-folder to subject cc
                   1032:                                           &optional annotate-char
                   1033:                                           annotate-field)
                   1034:   "Edit and compose a draft message and send or save it.
                   1035: SENT-FROM-FOLDER is buffer containing summary of current folder, if any.
                   1036: SEND-ARGS is an optional argument passed to the send command.
                   1037: The TO, SUBJECT, and CC fields are passed to the mh-compose-letter-hook.
                   1038: If ANNOTATE-CHAR is non-null, it is used to notate the scan listing of the
                   1039: current message.  In that case, the ANNOTATE-FIELD is used to build a string
                   1040: for mh-annotate-msg."
                   1041:   (let ((sent-from-msg))
                   1042:     (save-window-excursion
                   1043:       (when sent-from-folder
                   1044:        (switch-to-buffer sent-from-folder)
                   1045:        (setq sent-from-msg (mh-get-msg-num nil))))
                   1046:     (pop-to-buffer "draft")
                   1047:     (mh-letter-mode)
                   1048:     (make-local-variable 'mh-send-args)
                   1049:     (setq mh-send-args send-args)
                   1050:     (make-local-variable 'mh-sent-from-folder)
                   1051:     (setq mh-sent-from-folder sent-from-folder)
                   1052:     (make-local-variable 'mh-sent-from-msg)
                   1053:     (setq mh-sent-from-msg sent-from-msg)
                   1054:     (make-local-variable 'mh-annotate-field)
                   1055:     (setq mh-annotate-field annotate-field)
                   1056:     (make-local-variable 'mh-annotate-char)
                   1057:     (setq mh-annotate-char annotate-char)
                   1058:     (setq mode-line-format "{%b}  %[Mail/draft%] (%p - %m) (^C^C to send) %M")
                   1059:     (if (and (boundp 'mh-compose-letter-hook) mh-compose-letter-hook)
                   1060:        (funcall mh-compose-letter-hook to subject cc))))
                   1061: 
                   1062: 
                   1063: (defun mh-send-letter ()
                   1064:   "Send the letter in the current buffer."
                   1065:   (interactive)
                   1066:   (save-buffer)
                   1067:   (message "Sending...")
                   1068:   (if mh-send-args
                   1069:       (mh-exec-cmd-no-wait "send" "-push" "-unique" mh-send-args
                   1070:                           (buffer-file-name))
                   1071:       (mh-exec-cmd-no-wait "send" "-push" "-unique" (buffer-file-name)))
                   1072:   (if mh-annotate-char
                   1073:       (mh-annotate-msg mh-sent-from-msg mh-sent-from-folder
                   1074:                       mh-annotate-char
                   1075:                       "-component" mh-annotate-field
                   1076:                       "-text" (format "\"%s %s\"" (mh-get-field "To:")
                   1077:                                      (mh-get-field "Cc:"))))
                   1078:   (message "Sending...done")
                   1079:   (kill-buffer (buffer-name)))
                   1080: 
                   1081: 
                   1082: (defun mh-insert-letter (&optional arg)
                   1083:   "Insert a message in the current letter, asking for folder and number.
                   1084: Removes headers using mh-invisible-headers.
                   1085: Prefixes each non-blank line with mh-ins-buf-prefix (default \">> \").
                   1086: Just \\[universal-argument] means do not indent and do not delete any
                   1087: header fields.  Leaves point before the text and mark after it."
                   1088:   (interactive "p")
                   1089:   (let ((folder (mh-get-folder-name "Message from" mh-sent-from-folder nil))
                   1090:        (message (read-input (format "Message number%s: "
                   1091:                                     (if mh-sent-from-msg
                   1092:                                         (format " [%d]" mh-sent-from-msg)
                   1093:                                         ""))))
                   1094:        (start (point)))
                   1095:     (if (equal message "") (setq message (format "%d" mh-sent-from-msg)))
                   1096:     (mh-exec-lib-cmd-output "mhl" "-nobell"
                   1097:                            (format "%s%s/%s" mh-user-path
                   1098:                                    (substring folder 1) message))
                   1099:     (when (not (equal arg 4))
                   1100:       (mh-clean-message-header start)
                   1101:       (narrow-to-region start (mark))
                   1102:       (mh-insert-prefix-string mh-ins-buf-prefix)
                   1103:       (widen))
                   1104:     (exchange-point-and-mark)))
                   1105: 
                   1106: 
                   1107: (defun mh-insert-cur-message ()
                   1108:   "Inserts the currently visible message into the current buffer.
                   1109: Prefixes the string mh-ins-buf-prefix to each non-blank line
                   1110: of the inserted text.  If there is a region set in the
                   1111: currently visible message's buffer, only the region will be grabbed.
                   1112: Otherwise, the region from (point) to the end will be grabbed."
                   1113:   (interactive)
                   1114:   (let ((to-point (point))
                   1115:        (to-buffer (current-buffer)))
                   1116:     (set-buffer "*message*")
                   1117:     (let  ((mh-ins-str (if (mark)
                   1118:                           (buffer-substring (point) (mark))
                   1119:                           (buffer-substring (point) (point-max)))))
                   1120:       (set-buffer to-buffer)
                   1121:       (narrow-to-region to-point to-point)
                   1122:       (insert-string mh-ins-str)
                   1123:       (mh-insert-prefix-string mh-ins-buf-prefix)
                   1124:       (widen))))
                   1125: 
                   1126: 
                   1127: (defun mh-insert-prefix-string (ins-string)
                   1128: "Preface each line in the current buffer with STRING."
                   1129:   (goto-char (point-min))
                   1130:   (replace-regexp "^.." (concat ins-string "\\&") nil)
                   1131:   (goto-char (point-min)))
                   1132: 
                   1133: 
                   1134: 
                   1135: ;;; Commands to manipulate sequences.
                   1136: 
                   1137: (defmacro mh-seq-name (pair)
                   1138:   (list 'car pair))
                   1139: 
                   1140: (defmacro mh-seq-msgs (pair)
                   1141:   (list 'cdr pair))
                   1142: 
                   1143: 
                   1144: (defun mh-seq-to-msgs (seq)
                   1145:   "Returns the list of messages in sequence SEQ."
                   1146:   (mh-seq-msgs (assoc seq mh-seq-list)))
                   1147: 
                   1148: 
                   1149: (defun mh-read-seq (prompt)
                   1150:   "Prompt the user with PROMPT and read a sequence name."
                   1151:   (mh-letter-to-seq
                   1152:    (string-to-char (read-string (format "%s %s" prompt "sequence: ")))))
                   1153: 
                   1154: 
                   1155: (defun mh-seq-from-command (folder seq command)
                   1156:   "In FOLDER, make a sequence named SEQ by executing COMMAND."
                   1157:   (let ((msgs ())
                   1158:        (case-fold-search t))
                   1159:     (save-excursion
                   1160:       (save-window-excursion
                   1161:        (apply 'mh-exec-cmd-quiet command)
                   1162:        (switch-to-buffer " *mh-temp*")
                   1163:        (goto-char (point-min))
                   1164:        (while (re-search-forward "\\([0-9]+\\)" nil t)
                   1165:          (let ((num (string-to-int (buffer-substring (match-beginning 1)
                   1166:                                                      (match-end 1)))))
                   1167:            (if (not (zerop num))
                   1168:                (push num msgs)))))
                   1169:       (switch-to-buffer folder)
                   1170:       (push (cons seq msgs) mh-seq-list)
                   1171:       msgs)))
                   1172: 
                   1173: 
                   1174: (defun mh-remove-seq (seq)
                   1175:   "Delete the sequence SEQ."
                   1176:   (let ((entry (assoc seq mh-seq-list)))
                   1177:     (setq mh-seq-list (delq (car entry) mh-seq-list))
                   1178:     (mh-notate-seq (mh-seq-msgs (car entry)) ?  0)))
                   1179: 
                   1180: 
                   1181: (defun mh-remove-msg-from-seq (msg-num seq)
                   1182:   "Remove a message MSG-NUM from the sequence SEQ."
                   1183:   (let ((seq (assoc seq mh-seq-list)))
                   1184:     (if seq
                   1185:        (setcdr seq (delq msg-num (mh-seq-msgs seq)))))
                   1186:   (mh-notate ? 0))
                   1187: 
                   1188: 
                   1189: (defun mh-add-msg-to-seq (msg-num seq)
                   1190:   "Add a message MSG-NUM to a sequence SEQ."
                   1191:   (let ((seq-list (assoc seq mh-seq-list)))
                   1192:     (mh-notate (mh-seq-to-notation seq) 0)
                   1193:     (if (null seq-list)
                   1194:        (push (cons seq (list msg-num)) mh-seq-list)
                   1195:        (setcdr seq-list (cons msg-num (cdr seq-list))))))
                   1196: 
                   1197: 
                   1198: 
                   1199: (defun mh-new-seq (folder)
                   1200:   "Return a new sequence name for FOLDER."
                   1201:   (save-excursion
                   1202:     (switch-to-buffer folder)
                   1203:     (if (= mh-next-seq-num 10)
                   1204:        (error "No more sequences"))
                   1205:     (setq mh-next-seq-num (+ mh-next-seq-num 1))
                   1206:     (mh-letter-to-seq (+ (1- mh-next-seq-num) ?a))))
                   1207: 
                   1208: 
                   1209: (defun mh-letter-to-seq (letter)
                   1210:   "Given a LETTER, return a string that is a valid sequence name."
                   1211:   (cond ((and (>= letter ?0) (<= letter ?9))
                   1212:         (intern (format "mhe%c" letter)))
                   1213:        ((and (>= letter ?a) (<= letter ?z))
                   1214:         (intern (format "mhe%c" letter)))
                   1215:        (t
                   1216:         (error "A sequence is named 0...9"))))
                   1217: 
                   1218: 
                   1219: (defun mh-seq-to-notation (seq)
                   1220:   "Return the string used to indicate sequence SEQ in a scan listing."
                   1221:   (string-to-char (substring (symbol-name seq) 3 4)))
                   1222: 
                   1223: 
                   1224: (defun mh-notate-seq (seq notation offset)
                   1225:   "Mark all messages in the sequence SEQ with the NOTATION at character
                   1226: OFFSET."
                   1227:   (mh-apply-to-seq seq 'mh-notate notation offset))
                   1228: 
                   1229: 
                   1230: (defun mh-apply-to-seq (seq function &rest args)
                   1231:   "For each message in sequence SEQ, evaluate the FUNCTION with ARGS."
                   1232:   (mapcar (function (lambda (msg) (mh-goto msg) (apply function args)))
                   1233:          (mh-seq-to-msgs seq)))
                   1234: 
                   1235: 
                   1236: (defun mh-process-seq-commands (seq-list)
                   1237:   "Process outstanding sequence commands for the sequences in SEQ-LIST."
                   1238:   (mh-apply-to-message-list
                   1239:    (function (lambda (seq msgs)
                   1240:               (apply 'mh-exec-cmd-quiet
                   1241:                      (nconc (list "mark" "-zero" "-seq" (format "%s" seq)
                   1242:                                   "-add" "-nolist")
                   1243:                             msgs))))
                   1244:    seq-list))
                   1245: 
                   1246: 
                   1247: 
                   1248: ;;; Issue commands to mh.
                   1249: 
                   1250: (defun mh-exec-cmd (command &rest args)
                   1251:   "Execute MH command COMMAND with ARGS.  Any output is shown to the user."
                   1252:   (save-excursion
                   1253:     (switch-to-buffer-other-window " *mh-temp*")
                   1254:     (erase-buffer)
                   1255:     (apply 'call-process (nconc (list (format "%s%s" mh-progs command)
                   1256:                                      nil t nil)
                   1257:                                (mh-list-to-string args)))
                   1258:     (if (> (buffer-size) 0)
                   1259:        (sit-for 5))))
                   1260: 
                   1261: 
                   1262: (defun mh-exec-cmd-quiet (command &rest args)
                   1263:   "Execute MH command COMMAND with ARGS.  Output is collected, but not shown
                   1264:  to the user."
                   1265:   (save-excursion
                   1266:     (switch-to-buffer " *mh-temp*")
                   1267:     (erase-buffer)
                   1268:     (apply 'call-process (nconc (list (format "%s%s" mh-progs command)
                   1269:                                      nil t nil)
                   1270:                                (mh-list-to-string args)))))
                   1271: 
                   1272: 
                   1273: (defun mh-exec-cmd-output (command &rest args)
                   1274:   "Execute MH command COMMAND with ARGS putting the output into buffer after
                   1275: point.  Set mark after inserted text."
                   1276:   (set-mark (point))
                   1277:   (apply 'call-process (nconc (list (format "%s%s" mh-progs command) nil t nil)
                   1278:                              (mh-list-to-string args)))
                   1279:   (exchange-point-and-mark))
                   1280: 
                   1281: 
                   1282: (defun mh-exec-cmd-no-wait (command &rest args)
                   1283:   "Execute MH command COMMAND with ARGS and do not wait until it finishes."
                   1284:   (apply 'call-process (nconc (list (format "%s%s" mh-progs command) nil 0 nil)
                   1285:                              (mh-list-to-string args))))
                   1286: 
                   1287: 
                   1288: 
                   1289: (defun mh-exec-lib-cmd-output (command &rest args)
                   1290:   "Execute MH library command COMMAND with ARGS.  Put the output into
                   1291: buffer after point.  Set mark after inserted text."
                   1292:   (set-mark (point))
                   1293:   (apply 'call-process (nconc (list (format "%s%s" mh-lib command) nil t nil)
                   1294:                              (mh-list-to-string args)))
                   1295:   (exchange-point-and-mark))
                   1296: 
                   1297: 
                   1298: (defun mh-list-to-string (l)
                   1299:   "Flattens the list L and makes every element a string."
                   1300:   (let ((new-list nil))
                   1301:     (while l
                   1302:       (cond ((symbolp (car l)) (push (format "%s" (car l)) new-list))
                   1303:            ((numberp (car l)) (push (format "%d" (car l)) new-list))
                   1304:            ((equal (car l) ""))
                   1305:            ((stringp (car l)) (push (car l) new-list))
                   1306:            ((null (car l)))
                   1307:            ((listp (car l)) (setq new-list
                   1308:                                   (nconc (mh-list-to-string (car l))
                   1309:                                          new-list)))
                   1310:            (t (error "Bad argument %s" (car l))))
                   1311:       (setq l (cdr l)))
                   1312:     (nreverse new-list)))
                   1313: 
                   1314: 
                   1315: 
                   1316: ;;; Commands to annotate a message.
                   1317: 
                   1318: (defun mh-annotate-msg (msg buffer note &rest args)
                   1319:   "Mark the MESSAGE in BUFFER listing with the character NOTE and annotate
                   1320: the saved message with ARGS."
                   1321:   ;; Wait for annotation to finish, to avoid race condition with reading msg.
                   1322:   (apply 'mh-exec-cmd (cons "anno" (nconc (list buffer msg) args)))
                   1323:   (save-excursion
                   1324:     (switch-to-buffer buffer)
                   1325:     (if (mh-goto msg t)
                   1326:        (mh-notate note 5))))
                   1327: 
                   1328: 
                   1329: (defun mh-notate (notation offset)
                   1330:   "Marks the current message with the character NOTATION at position OFFSET."
                   1331:   (let ((buffer-read-only nil))
                   1332:     (beginning-of-line)
                   1333:     (goto-char (+ (point) offset))
                   1334:     (delete-char 1)
                   1335:     (insert notation)
                   1336:     (beginning-of-line)))
                   1337: 
                   1338: 
                   1339: 
                   1340: ;;; User prompting commands.
                   1341: 
                   1342: (defun mh-get-folder-name (prompt default can-create)
                   1343:   "Prompt for a folder name with PROMPT.  DEFAULT is used if the folder
                   1344: exists and the user types CR.  If the CAN-CREATE flag is t,
                   1345: then a non-existant folder is made."
                   1346:   (let* ((prompt (format "%s folder%s" prompt
                   1347:                         (if (equal "" default)
                   1348:                             "? "
                   1349:                             (format " [%s]? " default))))
                   1350:         name)
                   1351:     (while (and (setq name (completing-read prompt mh-folder-list
                   1352:                                            nil (not can-create)))
                   1353:                (equal name "")
                   1354:                (equal default "")))
                   1355:     (cond ((equal name "")
                   1356:           (setq name default))
                   1357:          ((not (equal (substring name 0 1) "+"))
                   1358:           (setq name (format "+%s" name))))
                   1359:     (let ((new-file-p
                   1360:           (not
                   1361:            (file-exists-p (format "%s%s" mh-user-path (substring name 1))))))
                   1362:       (cond ((and new-file-p
                   1363:                  (y-or-n-p
                   1364:                   (format "Folder %s does not exist. Create it? " name)))
                   1365:             (message "Creating %s" name)
                   1366:             (call-process "mkdir" nil nil nil
                   1367:                           (format "%s%s" mh-user-path (substring name 1)))
                   1368:             (message "Creating %s...done" name)
                   1369:             (push (list name) mh-folder-list)
                   1370:             (push (list (substring name 1 nil)) mh-folder-list))
                   1371:            (new-file-p
                   1372:             (error ""))
                   1373:            (t
                   1374:             (when (null (assoc name mh-folder-list))
                   1375:               (push (list name) mh-folder-list)
                   1376:               (push (list (substring name 1 nil)) mh-folder-list)))))
                   1377:     name))
                   1378: 
                   1379: 
                   1380: (defun mh-make-folder-list ()
                   1381:   "Returns a list of the user's folders in a form suitable for completing
                   1382: read."
                   1383:   (interactive)
                   1384:   (save-window-excursion
                   1385:     (mh-exec-cmd-quiet "folders" "-fast" "-norecurse")
                   1386:     (switch-to-buffer " *mh-temp*")
                   1387:     (goto-char (point-min))
                   1388:     (let ((list nil))
                   1389:       (while (not (eobp))
                   1390:        (let ((start (point)))
                   1391:          (search-forward "\n" nil t)
                   1392:          (let ((folder (buffer-substring start (- (point) 1))))
                   1393:            (push (list folder) list)
                   1394:            (push (list (format "+%s" folder)) list))))
                   1395:       list)))
                   1396: 
                   1397: 
                   1398: (defun mh-remove-folder-from-folder-list (folder)
                   1399:   "Remove FOLDER from the list of folders."
                   1400:   (setq mh-folder-list
                   1401:        (delq (assoc (substring folder 1 nil) mh-folder-list)
                   1402:              mh-folder-list)))
                   1403: 
                   1404: 
                   1405: 
                   1406: ;;; Misc. functions.
                   1407: 
                   1408: (defun mh-get-msg-num (error-if-no-message)
                   1409:   "Returns the message number of the current message.  If the argument
                   1410: ERROR-IF-NO-MESSAGE is t, then complain if the cursor is not pointing to a
                   1411: message."
                   1412:   (save-excursion
                   1413:     (beginning-of-line)
                   1414:     (cond ((looking-at "^[0-9a-z]?[ ]+\\([0-9]+\\)")
                   1415:           (string-to-int (buffer-substring (match-beginning 1)
                   1416:                                            (match-end 1))))
                   1417:          ((looking-at "^\\([0-9]+\\)")
                   1418:           (string-to-int (buffer-substring (match-beginning 1)
                   1419:                                            (match-end 1))))
                   1420:          (error-if-no-message
                   1421:           (error "Cursor not pointing to message"))
                   1422:          (t nil))))
                   1423: 
                   1424: 
                   1425: (defun mh-msg-search-pat (n)
                   1426:   "Returns a search pattern for message N in the scan listing."
                   1427:   (cond ((< n 10) (format "^...%d" n))
                   1428:        ((< n 100) (format "^..%d" n))
                   1429:        ((< n 1000) (format "^.%d" n))
                   1430:        (t (format "^%d" n))))
                   1431: 
                   1432: 
                   1433: (defun mh-msg-filename ()
                   1434:   "Returns a string containing the pathname for the file containing the
                   1435: current message."
                   1436:   (format "%s%d" mh-folder-filename (mh-get-msg-num t)))
                   1437: 
                   1438: 
                   1439: (defun mh-msg-filenames (msgs folder)
                   1440:   "Returns a string of filenames specifying MSGS in FOLDER."
                   1441:   (if msgs
                   1442:       (let ((args ""))
                   1443:        (while (cdr msgs)
                   1444:          (setq args (format "%s%s%d " args folder (car msgs)))
                   1445:          (setq msgs (cdr msgs)))
                   1446:        (format "%s%s%d" args folder (car msgs)))
                   1447:       ""))
                   1448: 
                   1449: 
                   1450: (defun mh-find-path ()
                   1451:   "Set mh_path from  ~/.mh_profile."
                   1452:   (save-window-excursion
                   1453:     (if (not (file-exists-p "~/.mh_profile"))
                   1454:        (error "Cannot find .mh_profile file."))
                   1455:     (switch-to-buffer " *mh_profile*")
                   1456:     (erase-buffer)
                   1457:     (insert-file-contents "~/.mh_profile")
                   1458:     (if (equal (setq mh-user-path (mh-get-field "Path:")) "")
                   1459:        (setq mh-user-path "Mail/")
                   1460:        (setq mh-user-path (format "%s/" mh-user-path)))
                   1461:     (if (not (equal (substring mh-user-path 0 1) "/"))
                   1462:        (setq mh-user-path (format "%s/%s" (getenv "HOME") mh-user-path)))))
                   1463: 
                   1464: 
                   1465: (defun mh-get-cur-msg (folder)
                   1466:   "Returns the number of the 'cur' message in FOLDER."
                   1467:   (save-excursion
                   1468:     (switch-to-buffer " *mh_temp*")
                   1469:     (erase-buffer)
                   1470:     (mh-exec-cmd-output "pick" folder "cur")
                   1471:     (string-to-int (buffer-substring (point-min) (point)))))
                   1472: 
                   1473: 
                   1474: (defun mh-get-field (field)
                   1475:   "Find and return the value of field FIELD in the current buffer.
                   1476: Returns the empty string if the field is not in the message."
                   1477:   (let ((case-fold-search t))
                   1478:     (goto-char (point-min))
                   1479:     (cond ((not (search-forward field nil t)) "")
                   1480:          ((looking-at "[\t ]*$") "")
                   1481:          (t
                   1482:           (re-search-forward "[\t ]*\\([a-zA-z0-9/].*\\)$" nil t)
                   1483:           (let ((field (buffer-substring (match-beginning 1)
                   1484:                                          (match-end 1)))
                   1485:                 (end-of-match (point)))
                   1486:             (forward-line)
                   1487:             (while (looking-at "[ \t]") (forward-line 1))
                   1488:             (backward-char 1)
                   1489:             (format "%s%s" field (buffer-substring end-of-match (point))))))))
                   1490: 
                   1491: 
                   1492: (defun mh-insert-fields (&rest name-values)
                   1493:   "Insert the NAME-VALUE pairs in the current buffer."
                   1494:   (let ((case-fold-search t))
                   1495:     (while name-values
                   1496:       (let ((field-name (car name-values))
                   1497:            (value (cadr name-values)))
                   1498:        (goto-char (point-min))
                   1499:        (cond ((not (re-search-forward (format "^%s" field-name) nil t))
                   1500:               (re-search-forward "^---\\|^$")
                   1501:               (beginning-of-line)
                   1502:               (insert field-name " " value "\n"))
                   1503:              (t
                   1504:               (end-of-line)
                   1505:               (insert " " value)))
                   1506:        (setq name-values (cddr name-values))))))
                   1507: 
                   1508: 
                   1509: (defun mh-position-on-field (field set-mark)
                   1510:   "Set point to the end of the line beginning with FIELD.  Sets the mark
                   1511: to the point, if SET-MARK is non-nil."
                   1512:   (if set-mark (set-mark (point)))
                   1513:   (goto-char (point-min))
                   1514:   (if (re-search-forward (format "^%s" field) nil t)
                   1515:       (progn (end-of-line) t)
                   1516:       nil))
                   1517: 
                   1518: 
                   1519: 
                   1520: ;;; Build the folder-mode keymap:
                   1521: 
                   1522: (define-key mh-folder-mode-map " " 'mh-page-msg)
                   1523: (define-key mh-folder-mode-map "!" 'mh-re-move)
                   1524: (define-key mh-folder-mode-map "." 'mh-show)
                   1525: (define-key mh-folder-mode-map "0" 'mh-indicate-seq)
                   1526: (define-key mh-folder-mode-map "1" 'mh-indicate-seq)
                   1527: (define-key mh-folder-mode-map "2" 'mh-indicate-seq)
                   1528: (define-key mh-folder-mode-map "3" 'mh-indicate-seq)
                   1529: (define-key mh-folder-mode-map "4" 'mh-indicate-seq)
                   1530: (define-key mh-folder-mode-map "5" 'mh-indicate-seq)
                   1531: (define-key mh-folder-mode-map "6" 'mh-indicate-seq)
                   1532: (define-key mh-folder-mode-map "7" 'mh-indicate-seq)
                   1533: (define-key mh-folder-mode-map "8" 'mh-indicate-seq)
                   1534: (define-key mh-folder-mode-map "9" 'mh-indicate-seq)
                   1535: (define-key mh-folder-mode-map ">" 'mh-save-message)
                   1536: (define-key mh-folder-mode-map "?" 'mh-summary)
                   1537: (define-key mh-folder-mode-map "\177" 'mh-previous-page)
                   1538: (define-key mh-folder-mode-map "\e " 'mh-page-digest)
                   1539: (define-key mh-folder-mode-map "\ef" 'mh-visit-folder)
                   1540: (define-key mh-folder-mode-map "\ei" 'mh-inc-folder)
                   1541: (define-key mh-folder-mode-map "\ek" 'mh-kill-folder)
                   1542: (define-key mh-folder-mode-map "\el" 'mh-list-folders)
                   1543: (define-key mh-folder-mode-map "\ep" 'mh-renumber-folder)
                   1544: (define-key mh-folder-mode-map "\er" 'mh-rescan-folder)
                   1545: (define-key mh-folder-mode-map "\es" 'mh-search-folder)
                   1546: (define-key mh-folder-mode-map "^" 'mh-move-msg)
                   1547: (define-key mh-folder-mode-map "a" 'mh-answer)
                   1548: (define-key mh-folder-mode-map "c" 'mh-copy-msg)
                   1549: (define-key mh-folder-mode-map "d" 'mh-delete-msg)
                   1550: (define-key mh-folder-mode-map "e" 'mh-execute-commands)
                   1551: (define-key mh-folder-mode-map "f" 'mh-forward)
                   1552: (define-key mh-folder-mode-map "g" 'mh-goto)
                   1553: (define-key mh-folder-mode-map "l" 'mh-print-msg)
                   1554: (define-key mh-folder-mode-map "n" 'mh-next-line)
                   1555: (define-key mh-folder-mode-map "p" 'mh-previous-line)
                   1556: (define-key mh-folder-mode-map "r" 'mh-redistribute)
                   1557: (define-key mh-folder-mode-map "s" 'mh-send)
                   1558: (define-key mh-folder-mode-map "t" 'mh-toggle-summarize)
                   1559: (define-key mh-folder-mode-map "u" 'mh-undo)
                   1560: (define-key mh-folder-mode-map "x" 'mh-execute-commands)
                   1561: 
                   1562: ;;; Build the letter-mode keymap:
                   1563: 
                   1564: (define-key mh-letter-mode-map "\^C\^C" 'mh-send-letter)
                   1565: (define-key mh-letter-mode-map "\^C\^Y" 'mh-insert-letter)
                   1566: (define-key mh-letter-mode-map "\^Cb" 'mh-to-bcc)
                   1567: (define-key mh-letter-mode-map "\^Cc" 'mh-to-cc)
                   1568: (define-key mh-letter-mode-map "\^Cf" 'mh-to-fcc)
                   1569: (define-key mh-letter-mode-map "\^Cq" 'kill-buffer)
                   1570: (define-key mh-letter-mode-map "\^Cs" 'mh-to-subject)
                   1571: (define-key mh-letter-mode-map "\^Ct" 'mh-to-to)
                   1572: (define-key mh-letter-mode-map "\^Cw" 'mh-check-whom)
                   1573: (define-key mh-letter-mode-map "\^Cy" 'mh-insert-cur-message)
                   1574: 
                   1575: ;;; Build the pick-mode keymap:
                   1576: 
                   1577: (define-key mh-pick-mode-map "\^C\^C" 'mh-do-pick-search)
                   1578: (define-key mh-pick-mode-map "\^Cb" 'mh-to-bcc)
                   1579: (define-key mh-pick-mode-map "\^Cc" 'mh-to-cc)
                   1580: (define-key mh-pick-mode-map "\^Cf" 'mh-to-fcc)
                   1581: (define-key mh-pick-mode-map "\^Cs" 'mh-to-subject)
                   1582: (define-key mh-pick-mode-map "\^Ct" 'mh-to-to)
                   1583: (define-key mh-pick-mode-map "\^Cw" 'mh-check-whom)
                   1584: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.