Annotation of 43BSD/contrib/mh/miscellany/mh-e/mh-e.ml, revision 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.