aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKarl Heuer1995-04-09 22:29:08 +0000
committerKarl Heuer1995-04-09 22:29:08 +0000
commitb6d4ab054bc16fb43ccb01e8a9663c71749e5b28 (patch)
treef216ab997282559d2a759ee132144e323e878e76
parent85e36d2b62818790cc609cfe8a981ed2c50c8354 (diff)
downloademacs-b6d4ab054bc16fb43ccb01e8a9663c71749e5b28.tar.gz
emacs-b6d4ab054bc16fb43ccb01e8a9663c71749e5b28.zip
New version from author
-rw-r--r--lisp/mail/mh-utils.el313
1 files changed, 190 insertions, 123 deletions
diff --git a/lisp/mail/mh-utils.el b/lisp/mail/mh-utils.el
index 57137260f75..df922317671 100644
--- a/lisp/mail/mh-utils.el
+++ b/lisp/mail/mh-utils.el
@@ -1,7 +1,7 @@
1;;; mh-utils.el --- mh-e code needed for both sending and reading 1;;; mh-utils.el --- mh-e code needed for both sending and reading
2;; Time-stamp: <94/04/11 20:56:35 gildea> 2;; Time-stamp: <95/02/10 14:20:14 gildea>
3 3
4;; Copyright 1993 Free Software Foundation, Inc. 4;; Copyright (C) 1993, 1995 Free Software Foundation, Inc.
5 5
6;; This file is part of mh-e. 6;; This file is part of mh-e.
7 7
@@ -23,6 +23,10 @@
23 23
24;; Internal support for mh-e package. 24;; Internal support for mh-e package.
25 25
26;;; Change Log:
27
28;; $Id: mh-utils.el,v 1.8 95/03/02 04:54:00 gildea Exp $
29
26;;; Code: 30;;; Code:
27 31
28;;; Set for local environment: 32;;; Set for local environment:
@@ -39,6 +43,11 @@
39This directory contains, among other things, 43This directory contains, among other things,
40the mhl program and the components file.") 44the mhl program and the components file.")
41 45
46;;;###autoload
47(put 'mh-progs 'risky-local-variable t)
48;;;###autoload
49(put 'mh-lib 'risky-local-variable t)
50
42;;; User preferences: 51;;; User preferences:
43 52
44(defvar mh-auto-folder-collect t 53(defvar mh-auto-folder-collect t
@@ -60,7 +69,7 @@ Only used if `mh-clean-message-header' is non-nil. Setting this variable
60overrides `mh-invisible-headers'.") 69overrides `mh-invisible-headers'.")
61 70
62(defvar mh-invisible-headers 71(defvar mh-invisible-headers
63 "^Received: \\|^Message-Id: \\|^Remailed-\\|^Via: \\|^Mail-from: \\|^Return-Path: \\|^In-Reply-To: \\|^Resent-" 72 "^Received: \\|^Message-Id: \\|^Remailed-\\|^Via: \\|^Mail-from: \\|^Return-Path: \\|^Delivery-Date: \\|^In-Reply-To: \\|^Resent-"
64 "Regexp matching lines in a message header that are not to be shown. 73 "Regexp matching lines in a message header that are not to be shown.
65If `mh-visible-headers' is non-nil, it is used instead to specify what 74If `mh-visible-headers' is non-nil, it is used instead to specify what
66to keep.") 75to keep.")
@@ -87,57 +96,84 @@ with the default format file, to format messages when printing them.
87The format used should specify a non-zero value for overflowoffset so 96The format used should specify a non-zero value for overflowoffset so
88the message continues to conform to RFC 822 and mh-e can parse the headers.") 97the message continues to conform to RFC 822 and mh-e can parse the headers.")
89 98
90(defvar mh-msg-folder-hook nil 99(defvar mh-default-folder-for-message-function nil
91 "Select a default folder for refiling or Fcc. 100 "Function to select a default folder for refiling or Fcc.
92Called by `\\[mh-refile-msg]' and `\\[mh-to-fcc]' to get a default 101If set to a function, that function is called with no arguments by
93when prompting the user for a folder. Called from within a save-excursion, 102`\\[mh-refile-msg]' and `\\[mh-to-fcc]' to get a default when
94with point at the start of the message. Should return the folder to offer 103prompting the user for a folder. The function is called from within a
95as the refile or Fcc folder, as a string with a leading `+' sign.") 104save-excursion, with point at the start of the message. It should
105return the folder to offer as the refile or Fcc folder, as a string
106with a leading `+' sign. It can also return an empty string to use no
107default, or NIL to calculate the default the usual way.
108NOTE: This variable is not an ordinary hook;
109It may not be a list of functions.")
110
111(defvar mh-find-path-hook nil
112 "Invoked by mh-find-path while reading the user's MH profile.")
96 113
114(defvar mh-folder-list-change-hook nil
115 "Invoked whenever the cached folder list `mh-folder-list' is changed.")
116
117(defvar mh-show-buffer-mode-line-buffer-id "{show-%s} %d"
118 "Format string to produce `mode-line-buffer-identification' for show buffers.
119First argument is folder name. Second is message number.")
97 120
98(defvar mh-cmd-note 4 121(defvar mh-cmd-note 4
99 "Offset to insert notation.") 122 "Offset to insert notation.")
100 123
101(defvar mh-folder-list nil 124(defvar mh-note-seq "%"
102 "List of folder names for completion.") 125 "String whose first character is used to notate messages in a sequence.")
126
127;;; Internal bookkeeping variables:
128
129;; The value of `mh-folder-list-change-hook' is called whenever
130;; mh-folder-list variable is set.
131(defvar mh-folder-list nil) ;List of folder names for completion.
132
133;; Cached value of the `Path:' component in the user's MH profile.
134(defvar mh-user-path nil) ;User's mail folder directory.
103 135
104(defvar mh-user-path nil 136;; An mh-draft-folder of NIL means do not use a draft folder.
105 "User's mail folder directory.") 137;; Cached value of the `Draft-Folder:' component in the user's MH profile.
138(defvar mh-draft-folder nil) ;Name of folder containing draft messages.
106 139
107(defvar mh-draft-folder nil 140;; Cached value of the `Unseen-Sequence:' component in the user's MH profile.
108 "Name of folder containing draft messages. 141(defvar mh-unseen-seq nil) ;Name of the Unseen sequence.
109NIL means do not use draft folder.")
110 142
111(defvar mh-previous-window-config nil 143;; Cached value of the `Previous-Sequence:' component in the user's MH profile.
112 "Window configuration before mh-e command.") 144(defvar mh-previous-seq nil) ;Name of the Previous sequence.
113 145
114(defvar mh-current-folder nil 146;; Cached value of the `Inbox:' component in the user's MH profile,
115 "Name of current folder, a string.") 147;; or "+inbox" if no such component.
148(defvar mh-inbox nil) ;Name of the Inbox folder.
116 149
117(defvar mh-folder-filename nil 150(defconst mh-temp-buffer " *mh-temp*") ;Name of mh-e scratch buffer.
118 "Full path of directory for this folder.")
119 151
120(defvar mh-show-buffer nil 152(defvar mh-previous-window-config nil) ;Window configuration before mh-e command.
121 "Buffer that displays mesage for this folder.")
122 153
123(defvar mh-unseen-seq nil 154;;; Internal variables local to a folder.
124 "Name of the Unseen sequence.")
125 155
126(defvar mh-previous-seq nil 156(defvar mh-current-folder nil) ;Name of current folder, a string.
127 "Name of the Previous sequence.")
128 157
129(defvar mh-seen-list nil 158(defvar mh-show-buffer nil) ;Buffer that displays message for this folder.
130 "List of displayed messages.")
131 159
132(defvar mh-seq-list nil 160(defvar mh-folder-filename nil) ;Full path of directory for this folder.
133 "Alist of (seq . msgs) numbers.")
134 161
135(defvar mh-showing nil 162(defvar mh-showing nil) ;If non-nil, show the message in a separate window.
136 "If non-nil, show the message in a separate window.")
137 163
138(defvar mh-showing-with-headers nil 164;;; This holds a documentation string used by describe-mode.
139 "If non-nil, show buffer contains message with all headers. 165(defun mh-showing ()
140If nil, show buffer contains message processed normally.") 166 "When moving to a new message in the Folder window,
167also show it in a separate Show window."
168 nil)
169
170(defvar mh-seq-list nil) ;The sequences of this folder. An alist of (seq . msgs).
171
172(defvar mh-seen-list nil) ;List of displayed messages to be removed from the Unseen sequence.
173
174;; If non-nil, show buffer contains message with all headers.
175;; If nil, show buffer contains message processed normally.
176(defvar mh-showing-with-headers nil) ;Showing message with headers or normally.
141 177
142 178
143;;; mh-e macros 179;;; mh-e macros
@@ -163,7 +199,7 @@ If nil, show buffer contains message processed normally.")
163(put 'with-mh-folder-updating 'lisp-indent-hook 1) 199(put 'with-mh-folder-updating 'lisp-indent-hook 1)
164 200
165(defmacro mh-in-show-buffer (show-buffer &rest body) 201(defmacro mh-in-show-buffer (show-buffer &rest body)
166 ;; Format is (mh-in-show-buffer (show-buffer) &body BODY). 202 ;; Format is (mh-in-show-buffer (SHOW-BUFFER) &body BODY).
167 ;; Display buffer SHOW-BUFFER in other window and execute BODY in it. 203 ;; Display buffer SHOW-BUFFER in other window and execute BODY in it.
168 ;; Stronger than save-excursion, weaker than save-window-excursion. 204 ;; Stronger than save-excursion, weaker than save-window-excursion.
169 (setq show-buffer (car show-buffer)) ; CL style 205 (setq show-buffer (car show-buffer)) ; CL style
@@ -177,6 +213,8 @@ If nil, show buffer contains message processed normally.")
177 213
178(put 'mh-in-show-buffer 'lisp-indent-hook 1) 214(put 'mh-in-show-buffer 'lisp-indent-hook 1)
179 215
216(defmacro mh-make-seq (name msgs) (list 'cons name msgs))
217
180(defmacro mh-seq-name (pair) (list 'car pair)) 218(defmacro mh-seq-name (pair) (list 'car pair))
181 219
182(defmacro mh-seq-msgs (pair) (list 'cdr pair)) 220(defmacro mh-seq-msgs (pair) (list 'cdr pair))
@@ -198,7 +236,7 @@ The value of mh-show-mode-hook is called when a new message is displayed."
198 ;; If in showing mode, then display the message pointed to by the cursor. 236 ;; If in showing mode, then display the message pointed to by the cursor.
199 (if mh-showing (mh-show msg))) 237 (if mh-showing (mh-show msg)))
200 238
201(defun mh-show (&optional msg) 239(defun mh-show (&optional message)
202 "Show MESSAGE (default: message at cursor). 240 "Show MESSAGE (default: message at cursor).
203Force a two-window display with the folder window on top (size 241Force a two-window display with the folder window on top (size
204mh-summary-height) and the show buffer below it. 242mh-summary-height) and the show buffer below it.
@@ -212,7 +250,7 @@ Type \"\\[mh-header-display]\" to see the message with all its headers."
212 (and mh-showing-with-headers 250 (and mh-showing-with-headers
213 (or mhl-formfile mh-clean-message-header) 251 (or mhl-formfile mh-clean-message-header)
214 (mh-invalidate-show-buffer)) 252 (mh-invalidate-show-buffer))
215 (mh-show-msg msg)) 253 (mh-show-msg message))
216 254
217 255
218(defun mh-show-msg (msg) 256(defun mh-show-msg (msg)
@@ -254,11 +292,12 @@ Type \"\\[mh-header-display]\" to see the message with all its headers."
254 (error "Message %d does not exist" msg-num)) 292 (error "Message %d does not exist" msg-num))
255 (set-buffer show-buffer) 293 (set-buffer show-buffer)
256 (cond ((not (equal msg-filename buffer-file-name)) 294 (cond ((not (equal msg-filename buffer-file-name))
257 ;; Buffer does not yet contain message. 295 (mh-unvisit-file)
258 (clear-visited-file-modtime)
259 (unlock-buffer)
260 (setq buffer-file-name nil) ; no locking during setup
261 (erase-buffer) 296 (erase-buffer)
297 ;; Changing contents, so this hook needs to be reinitialized.
298 ;; pgp.el uses this.
299 (if (boundp 'write-contents-hooks) ;Emacs 19
300 (setq write-contents-hooks nil))
262 (if formfile 301 (if formfile
263 (mh-exec-lib-cmd-output "mhl" "-nobell" "-noclear" 302 (mh-exec-lib-cmd-output "mhl" "-nobell" "-noclear"
264 (if (stringp formfile) 303 (if (stringp formfile)
@@ -273,10 +312,15 @@ Type \"\\[mh-header-display]\" to see the message with all its headers."
273 (goto-char (point-min))) 312 (goto-char (point-min)))
274 (t 313 (t
275 (mh-start-of-uncleaned-message))) 314 (mh-start-of-uncleaned-message)))
276 (set-buffer-modified-p nil) 315 ;; the parts of visiting we want to do (no locking)
277 (or (eq buffer-undo-list t) ;don't save undo info for prev msgs 316 (or (eq buffer-undo-list t) ;don't save undo info for prev msgs
278 (setq buffer-undo-list nil)) 317 (setq buffer-undo-list nil))
318 (set-buffer-modified-p nil)
319 (set-buffer-auto-saved)
320 ;; the parts of set-visited-file-name we want to do (no locking)
279 (setq buffer-file-name msg-filename) 321 (setq buffer-file-name msg-filename)
322 (setq buffer-backed-up nil)
323 (auto-save-mode 1)
280 (set-mark nil) 324 (set-mark nil)
281 (mh-show-mode) 325 (mh-show-mode)
282 (setq mode-line-buffer-identification 326 (setq mode-line-buffer-identification
@@ -289,7 +333,7 @@ Type \"\\[mh-header-display]\" to see the message with all its headers."
289 ;; position uninteresting headers off the top of the window 333 ;; position uninteresting headers off the top of the window
290 (let ((case-fold-search t)) 334 (let ((case-fold-search t))
291 (re-search-forward 335 (re-search-forward
292 "^To:\\|^From:\\|^Subject:\\|^Date:" nil t) 336 "^To:\\|^Cc:\\|^From:\\|^Subject:\\|^Date:" nil t)
293 (beginning-of-line) 337 (beginning-of-line)
294 (mh-recenter 0))) 338 (mh-recenter 0)))
295 339
@@ -299,9 +343,21 @@ Type \"\\[mh-header-display]\" to see the message with all its headers."
299 (if (get-buffer mh-show-buffer) 343 (if (get-buffer mh-show-buffer)
300 (save-excursion 344 (save-excursion
301 (set-buffer mh-show-buffer) 345 (set-buffer mh-show-buffer)
302 (setq buffer-file-name nil)))) 346 (mh-unvisit-file))))
347
303 348
349(defun mh-unvisit-file ()
350 ;; Separate current buffer from the message file it was visiting.
351 (or (not (buffer-modified-p))
352 (null buffer-file-name) ;we've been here before
353 (yes-or-no-p (format "Message %s modified; flush changes? "
354 (file-name-nondirectory buffer-file-name)))
355 (error "Flushing changes not confirmed"))
356 (clear-visited-file-modtime)
357 (unlock-buffer)
358 (setq buffer-file-name nil))
304 359
360
305(defun mh-get-msg-num (error-if-no-message) 361(defun mh-get-msg-num (error-if-no-message)
306 ;; Return the message number of the displayed message. If the argument 362 ;; Return the message number of the displayed message. If the argument
307 ;; ERROR-IF-NO-MESSAGE is non-nil, then complain if the cursor is not 363 ;; ERROR-IF-NO-MESSAGE is non-nil, then complain if the cursor is not
@@ -368,22 +424,6 @@ Type \"\\[mh-header-display]\" to see the message with all its headers."
368 (delete-region (point) (save-excursion (forward-line lines) (point)))) 424 (delete-region (point) (save-excursion (forward-line lines) (point))))
369 425
370 426
371(defun mh-get-field (field)
372 ;; Find and return the value of field FIELD in the current buffer.
373 ;; Returns the empty string if the field is not in the message.
374 (let ((case-fold-search t))
375 (goto-char (point-min))
376 (cond ((not (re-search-forward (format "^%s" field) nil t)) "")
377 ((looking-at "[\t ]*$") "")
378 (t
379 (re-search-forward "[\t ]*\\([^\t \n].*\\)$" nil t)
380 (let ((start (match-beginning 1)))
381 (forward-line 1)
382 (while (looking-at "[ \t]")
383 (forward-line 1))
384 (buffer-substring start (1- (point))))))))
385
386
387(defun mh-notate (msg notation offset) 427(defun mh-notate (msg notation offset)
388 ;; Marks MESSAGE with the character NOTATION at position OFFSET. 428 ;; Marks MESSAGE with the character NOTATION at position OFFSET.
389 ;; Null MESSAGE means the message that the cursor points to. 429 ;; Null MESSAGE means the message that the cursor points to.
@@ -399,10 +439,11 @@ Type \"\\[mh-header-display]\" to see the message with all its headers."
399 439
400(defun mh-goto-msg (number &optional no-error-if-no-message dont-show) 440(defun mh-goto-msg (number &optional no-error-if-no-message dont-show)
401 "Position the cursor at message NUMBER. 441 "Position the cursor at message NUMBER.
402Non-nil second argument means do not signal an error if message does not exist. 442Optional non-nil second argument means return nil instead of
403Non-nil third argument means not to show the message. 443signaling an error if message does not exist.
404Return non-nil if cursor is at message." 444Non-nil third argument means not to show the message."
405 (interactive "NJump to message: ") 445 (interactive "NGo to message: ")
446 (setq number (prefix-numeric-value number)) ;Emacs 19
406 (let ((cur-msg (mh-get-msg-num nil)) 447 (let ((cur-msg (mh-get-msg-num nil))
407 (starting-place (point)) 448 (starting-place (point))
408 (msg-pattern (mh-msg-search-pat number))) 449 (msg-pattern (mh-msg-search-pat number)))
@@ -430,45 +471,63 @@ Return non-nil if cursor is at message."
430 (format mh-msg-search-regexp n)) 471 (format mh-msg-search-regexp n))
431 472
432 473
474(defun mh-get-profile-field (field)
475 ;; Find and return the value of FIELD in the current buffer.
476 ;; Returns NIL if the field is not in the buffer.
477 (let ((case-fold-search t))
478 (goto-char (point-min))
479 (cond ((not (re-search-forward (format "^%s" field) nil t)) nil)
480 ((looking-at "[\t ]*$") nil)
481 (t
482 (re-search-forward "[\t ]*\\([^\t \n].*\\)$" nil t)
483 (let ((start (match-beginning 1)))
484 (end-of-line)
485 (buffer-substring start (point)))))))
486
487
433(defun mh-find-path () 488(defun mh-find-path ()
434 ;; Set mh-progs and mh-lib. 489 ;; Set mh-progs and mh-lib.
435 ;; (This step is necessary if MH was installed after this Emacs was dumped.) 490 ;; (This step is necessary if MH was installed after this Emacs was dumped.)
436 ;; Set mh-user-path, mh-draft-folder, 491 ;; From profile file, set mh-user-path, mh-draft-folder,
437 ;; mh-unseen-seq, and mh-previous-seq from profile file. 492 ;; mh-unseen-seq, mh-previous-seq, mh-inbox.
438 (mh-find-progs) 493 (mh-find-progs)
439 (save-excursion 494 (save-excursion
440 ;; Be sure profile is fully expanded before switching buffers 495 ;; Be sure profile is fully expanded before switching buffers
441 (let ((profile (expand-file-name (or (getenv "MH") "~/.mh_profile")))) 496 (let ((profile (expand-file-name (or (getenv "MH") "~/.mh_profile"))))
442 (set-buffer (get-buffer-create " *mh-temp*")) 497 (set-buffer (get-buffer-create mh-temp-buffer))
443 (setq buffer-offer-save nil) ;for people who set default to t 498 (setq buffer-offer-save nil) ;for people who set default to t
444 (erase-buffer) 499 (erase-buffer)
445 (condition-case err 500 (condition-case err
446 (insert-file-contents profile) 501 (insert-file-contents profile)
447 (file-error 502 (file-error
448 (mh-install profile err))) 503 (mh-install profile err)))
449 (setq mh-draft-folder (mh-get-field "Draft-Folder:")) 504 (setq mh-user-path (mh-get-profile-field "Path:"))
450 (cond ((equal mh-draft-folder "") 505 (if (not mh-user-path)
451 (setq mh-draft-folder nil))
452 ((not (mh-folder-name-p mh-draft-folder))
453 (setq mh-draft-folder (format "+%s" mh-draft-folder))))
454 (setq mh-user-path (mh-get-field "Path:"))
455 (if (equal mh-user-path "")
456 (setq mh-user-path "Mail")) 506 (setq mh-user-path "Mail"))
457 (setq mh-user-path 507 (setq mh-user-path
458 (file-name-as-directory 508 (file-name-as-directory
459 (expand-file-name mh-user-path (expand-file-name "~")))) 509 (expand-file-name mh-user-path (expand-file-name "~"))))
460 (if (and mh-draft-folder 510 (setq mh-draft-folder (mh-get-profile-field "Draft-Folder:"))
461 (not (file-exists-p (mh-expand-file-name mh-draft-folder)))) 511 (if mh-draft-folder
462 (error "Draft folder \"%s\" not found. Create it and try again." 512 (progn
463 (mh-expand-file-name mh-draft-folder))) 513 (if (not (mh-folder-name-p mh-draft-folder))
464 (setq mh-unseen-seq (mh-get-field "Unseen-Sequence:")) 514 (setq mh-draft-folder (format "+%s" mh-draft-folder)))
465 (if (equal mh-unseen-seq "") 515 (if (not (file-exists-p (mh-expand-file-name mh-draft-folder)))
466 (setq mh-unseen-seq 'unseen) ;old MH default? 516 (error "Draft folder \"%s\" not found. Create it and try again."
467 (setq mh-unseen-seq (intern mh-unseen-seq))) 517 (mh-expand-file-name mh-draft-folder)))))
468 (setq mh-previous-seq (mh-get-field "Previous-Sequence:")) 518 (setq mh-inbox (mh-get-profile-field "Inbox:"))
469 (if (equal mh-previous-seq "") 519 (cond ((not mh-inbox)
470 (setq mh-previous-seq nil) 520 (setq mh-inbox "+inbox"))
471 (setq mh-previous-seq (intern mh-previous-seq)))))) 521 ((not (mh-folder-name-p mh-inbox))
522 (setq mh-inbox (format "+%s" mh-inbox))))
523 (setq mh-unseen-seq (mh-get-profile-field "Unseen-Sequence:"))
524 (if mh-unseen-seq
525 (setq mh-unseen-seq (intern mh-unseen-seq))
526 (setq mh-unseen-seq 'unseen)) ;old MH default?
527 (setq mh-previous-seq (mh-get-profile-field "Previous-Sequence:"))
528 (if mh-previous-seq
529 (setq mh-previous-seq (intern mh-previous-seq)))
530 (run-hooks 'mh-find-path-hook))))
472 531
473(defun mh-find-progs () 532(defun mh-find-progs ()
474 (or (file-exists-p (expand-file-name "inc" mh-progs)) 533 (or (file-exists-p (expand-file-name "inc" mh-progs))
@@ -478,20 +537,25 @@ Return non-nil if cursor is at message."
478 "/usr/local/mh/" 537 "/usr/local/mh/"
479 "/usr/bin/mh/" ;Ultrix 4.2 538 "/usr/bin/mh/" ;Ultrix 4.2
480 "/usr/new/mh/" ;Ultrix <4.2 539 "/usr/new/mh/" ;Ultrix <4.2
481 "/usr/contrib/mh/bin" ;BSDI 540 "/usr/contrib/mh/bin/" ;BSDI
541 "/usr/local/bin/"
482 ) 542 )
483 "inc") 543 "inc")
544 mh-progs
484 "/usr/local/bin/"))) 545 "/usr/local/bin/")))
485 (or (file-exists-p (expand-file-name "mhl" mh-lib)) 546 (or (file-exists-p (expand-file-name "mhl" mh-lib))
486 (setq mh-lib 547 (setq mh-lib
487 (or (mh-path-search '("/usr/local/lib/mh/" 548 (or (mh-path-search '("/usr/local/lib/mh/"
549 "/usr/local/mh/lib/"
550 "/usr/local/bin/mh/"
488 "/usr/lib/mh/" ;Ultrix 4.2 551 "/usr/lib/mh/" ;Ultrix 4.2
489 "/usr/new/lib/mh/" ;Ultrix <4.2 552 "/usr/new/lib/mh/" ;Ultrix <4.2
490 "/usr/contrib/mh/lib" ;BSDI 553 "/usr/contrib/mh/lib/" ;BSDI
491 ) 554 )
492 "mhl") 555 "mhl")
493 (mh-path-search exec-path "mhl") ;unlikely 556 (mh-path-search exec-path "mhl") ;unlikely
494 "/usr/local/bin/mh/")))) 557 mh-lib
558 "/usr/local/lib/mh/"))))
495 559
496(defun mh-path-search (path file) 560(defun mh-path-search (path file)
497 ;; Search PATH, a list of directory names, for FILE. 561 ;; Search PATH, a list of directory names, for FILE.
@@ -510,6 +574,8 @@ Return non-nil if cursor is at message."
510 profile (car (cdr (cdr error-val))))) 574 profile (car (cdr (cdr error-val)))))
511 ;; The "install-mh" command will output a short note which 575 ;; The "install-mh" command will output a short note which
512 ;; mh-exec-cmd will display to the user. 576 ;; mh-exec-cmd will display to the user.
577 ;; The MH 5 version of install-mh might try prompt the user
578 ;; for information, which would fail here.
513 (mh-exec-cmd (expand-file-name "install-mh" mh-lib) "-auto") 579 (mh-exec-cmd (expand-file-name "install-mh" mh-lib) "-auto")
514 ;; now try again to read the profile file 580 ;; now try again to read the profile file
515 (erase-buffer) 581 (erase-buffer)
@@ -521,16 +587,14 @@ Return non-nil if cursor is at message."
521 587
522 588
523(defun mh-set-folder-modified-p (flag) 589(defun mh-set-folder-modified-p (flag)
524 "Mark current folder as modified or unmodified according to FLAG." 590 ;; Mark current folder as modified or unmodified according to FLAG.
525 (set-buffer-modified-p flag)) 591 (set-buffer-modified-p flag))
526 592
527 593
528(defun mh-find-seq (name) (assoc name mh-seq-list)) 594(defun mh-find-seq (name) (assoc name mh-seq-list))
529 595
530(defun mh-make-seq (name msgs) (cons name msgs))
531
532(defun mh-seq-to-msgs (seq) 596(defun mh-seq-to-msgs (seq)
533 "Return a list of the messages in SEQUENCE." 597 ;; Return a list of the messages in SEQUENCE.
534 (mh-seq-msgs (mh-find-seq seq))) 598 (mh-seq-msgs (mh-find-seq seq)))
535 599
536 600
@@ -541,10 +605,10 @@ Return non-nil if cursor is at message."
541 (if (and msgs (atom msgs)) (setq msgs (list msgs))) 605 (if (and msgs (atom msgs)) (setq msgs (list msgs)))
542 (if (null entry) 606 (if (null entry)
543 (setq mh-seq-list (cons (mh-make-seq seq msgs) mh-seq-list)) 607 (setq mh-seq-list (cons (mh-make-seq seq msgs) mh-seq-list))
544 (if msgs (setcdr entry (append msgs (cdr entry))))) 608 (if msgs (setcdr entry (append msgs (mh-seq-msgs entry)))))
545 (cond ((not internal-flag) 609 (cond ((not internal-flag)
546 (mh-add-to-sequence seq msgs) 610 (mh-add-to-sequence seq msgs)
547 (mh-notate-seq seq ?% (1+ mh-cmd-note)))))) 611 (mh-notate-seq seq mh-note-seq (1+ mh-cmd-note))))))
548 612
549(autoload 'mh-add-to-sequence "mh-seq") 613(autoload 'mh-add-to-sequence "mh-seq")
550(autoload 'mh-notate-seq "mh-seq") 614(autoload 'mh-notate-seq "mh-seq")
@@ -592,42 +656,42 @@ Return non-nil if cursor is at message."
592 (message "Creating %s" folder-name) 656 (message "Creating %s" folder-name)
593 (call-process "mkdir" nil nil nil (mh-expand-file-name folder-name)) 657 (call-process "mkdir" nil nil nil (mh-expand-file-name folder-name))
594 (message "Creating %s...done" folder-name) 658 (message "Creating %s...done" folder-name)
595 (setq mh-folder-list (cons (list read-name) mh-folder-list))) 659 (setq mh-folder-list (cons (list read-name) mh-folder-list))
660 (run-hooks 'mh-folder-list-change-hook))
596 (new-file-p 661 (new-file-p
597 (error "Folder %s is not created" folder-name)) 662 (error "Folder %s is not created" folder-name))
598 ((and (null (assoc read-name mh-folder-list)) 663 ((and (null (assoc read-name mh-folder-list))
599 (null (assoc (concat read-name "/") mh-folder-list))) 664 (null (assoc (concat read-name "/") mh-folder-list)))
600 (setq mh-folder-list (cons (list read-name) mh-folder-list))))) 665 (setq mh-folder-list (cons (list read-name) mh-folder-list))
666 (run-hooks 'mh-folder-list-change-hook))))
601 folder-name)) 667 folder-name))
602 668
603 669
604(defvar mh-make-folder-list-process nil 670(defvar mh-make-folder-list-process nil) ;The background process collecting the folder list.
605 "The background process collecting the folder list.")
606 671
607(defvar mh-folder-list-temp nil 672(defvar mh-folder-list-temp nil) ;mh-folder-list as it is being built.
608 "mh-folder-list as it is being built.")
609 673
610(defvar mh-folder-list-partial-line "" 674(defvar mh-folder-list-partial-line "") ;Start of last incomplete line from folder process.
611 "Start of last incomplete line from folder process.")
612 675
613(defun mh-set-folder-list () 676(defun mh-set-folder-list ()
614 "Sets mh-folder-list correctly. 677 ;; Sets mh-folder-list correctly.
615A useful function for the command line or for when you need to sync by hand. 678 ;; A useful function for the command line or for when you need to
616Format is in a form suitable for completing read." 679 ;; sync by hand. Format is in a form suitable for completing read.
617 (message "Collecting folder names...") 680 (message "Collecting folder names...")
618 (if (not mh-make-folder-list-process) 681 (if (not mh-make-folder-list-process)
619 (mh-make-folder-list-background)) 682 (mh-make-folder-list-background))
620 (while (eq (process-status mh-make-folder-list-process) 'run) 683 (while (eq (process-status mh-make-folder-list-process) 'run)
621 (accept-process-output mh-make-folder-list-process)) 684 (accept-process-output mh-make-folder-list-process))
622 (setq mh-folder-list mh-folder-list-temp) 685 (setq mh-folder-list mh-folder-list-temp)
686 (run-hooks 'mh-folder-list-change-hook)
623 (setq mh-folder-list-temp nil) 687 (setq mh-folder-list-temp nil)
624 (delete-process mh-make-folder-list-process) 688 (delete-process mh-make-folder-list-process)
625 (setq mh-make-folder-list-process nil) 689 (setq mh-make-folder-list-process nil)
626 (message "Collecting folder names...done")) 690 (message "Collecting folder names...done"))
627 691
628(defun mh-make-folder-list-background () 692(defun mh-make-folder-list-background ()
629 "Start a background process to compute a list of the user's folders. 693 ;; Start a background process to compute a list of the user's folders.
630Call mh-set-folder-list to wait for the result." 694 ;; Call mh-set-folder-list to wait for the result.
631 (cond 695 (cond
632 ((not mh-make-folder-list-process) 696 ((not mh-make-folder-list-process)
633 (mh-find-progs) 697 (mh-find-progs)
@@ -688,16 +752,18 @@ Call mh-set-folder-list to wait for the result."
688 752
689(defun mh-exec-cmd (command &rest args) 753(defun mh-exec-cmd (command &rest args)
690 ;; Execute mh-command COMMAND with ARGS. 754 ;; Execute mh-command COMMAND with ARGS.
755 ;; The side effects are what is desired.
691 ;; Any output is assumed to be an error and is shown to the user. 756 ;; Any output is assumed to be an error and is shown to the user.
757 ;; The output is not read or parsed by mh-e.
692 (save-excursion 758 (save-excursion
693 (set-buffer (get-buffer-create " *mh-temp*")) 759 (set-buffer (get-buffer-create mh-temp-buffer))
694 (erase-buffer) 760 (erase-buffer)
695 (apply 'call-process 761 (apply 'call-process
696 (expand-file-name command mh-progs) nil t nil 762 (expand-file-name command mh-progs) nil t nil
697 (mh-list-to-string args)) 763 (mh-list-to-string args))
698 (if (> (buffer-size) 0) 764 (if (> (buffer-size) 0)
699 (save-window-excursion 765 (save-window-excursion
700 (switch-to-buffer-other-window " *mh-temp*") 766 (switch-to-buffer-other-window mh-temp-buffer)
701 (sit-for 5))))) 767 (sit-for 5)))))
702 768
703 769
@@ -706,7 +772,7 @@ Call mh-set-folder-list to wait for the result."
706 ;; ENV is nil or a string of space-separated "var=value" elements. 772 ;; ENV is nil or a string of space-separated "var=value" elements.
707 ;; Signals an error if process does not complete successfully. 773 ;; Signals an error if process does not complete successfully.
708 (save-excursion 774 (save-excursion
709 (set-buffer (get-buffer-create " *mh-temp*")) 775 (set-buffer (get-buffer-create mh-temp-buffer))
710 (erase-buffer) 776 (erase-buffer)
711 (let ((status 777 (let ((status
712 (if env 778 (if env
@@ -724,10 +790,10 @@ Call mh-set-folder-list to wait for the result."
724 790
725 791
726(defun mh-exec-cmd-daemon (command &rest args) 792(defun mh-exec-cmd-daemon (command &rest args)
727 ;; Execute MH command COMMAND with ARGS. Any output from command is 793 ;; Execute MH command COMMAND with ARGS in the background.
728 ;; displayed in an asynchronous pop-up window. 794 ;; Any output from command is displayed in an asynchronous pop-up window.
729 (save-excursion 795 (save-excursion
730 (set-buffer (get-buffer-create " *mh-temp*")) 796 (set-buffer (get-buffer-create mh-temp-buffer))
731 (erase-buffer)) 797 (erase-buffer))
732 (let* ((process-connection-type nil) 798 (let* ((process-connection-type nil)
733 (process (apply 'start-process 799 (process (apply 'start-process
@@ -738,9 +804,9 @@ Call mh-set-folder-list to wait for the result."
738 804
739(defun mh-process-daemon (process output) 805(defun mh-process-daemon (process output)
740 ;; Process daemon that puts output into a temporary buffer. 806 ;; Process daemon that puts output into a temporary buffer.
741 (set-buffer (get-buffer-create " *mh-temp*")) 807 (set-buffer (get-buffer-create mh-temp-buffer))
742 (insert-before-markers output) 808 (insert-before-markers output)
743 (display-buffer " *mh-temp*")) 809 (display-buffer mh-temp-buffer))
744 810
745 811
746(defun mh-exec-cmd-quiet (raise-error command &rest args) 812(defun mh-exec-cmd-quiet (raise-error command &rest args)
@@ -750,7 +816,7 @@ Call mh-set-folder-list to wait for the result."
750 ;; Returns value of call-process, which is 0 for success, 816 ;; Returns value of call-process, which is 0 for success,
751 ;; unless RAISE-ERROR is non-nil, in which case an error is signaled 817 ;; unless RAISE-ERROR is non-nil, in which case an error is signaled
752 ;; if call-process returns non-0. 818 ;; if call-process returns non-0.
753 (set-buffer (get-buffer-create " *mh-temp*")) 819 (set-buffer (get-buffer-create mh-temp-buffer))
754 (erase-buffer) 820 (erase-buffer)
755 (let ((value 821 (let ((value
756 (apply 'call-process 822 (apply 'call-process
@@ -765,6 +831,7 @@ Call mh-set-folder-list to wait for the result."
765(defun mh-exec-cmd-output (command display &rest args) 831(defun mh-exec-cmd-output (command display &rest args)
766 ;; Execute MH command COMMAND with DISPLAY flag and ARGS. 832 ;; Execute MH command COMMAND with DISPLAY flag and ARGS.
767 ;; Put the output into buffer after point. Set mark after inserted text. 833 ;; Put the output into buffer after point. Set mark after inserted text.
834 ;; Output is expected to be shown to user, not parsed by mh-e.
768 (push-mark (point) t) 835 (push-mark (point) t)
769 (apply 'call-process 836 (apply 'call-process
770 (expand-file-name command mh-progs) nil t display 837 (expand-file-name command mh-progs) nil t display
@@ -782,7 +849,7 @@ Call mh-set-folder-list to wait for the result."
782 ;; Raise error if COMMAND returned non-0 STATUS, otherwise return STATUS. 849 ;; Raise error if COMMAND returned non-0 STATUS, otherwise return STATUS.
783 ;; STATUS is return value from call-process. 850 ;; STATUS is return value from call-process.
784 ;; Program output is in current buffer. 851 ;; Program output is in current buffer.
785 ;; If output is too long ot include in error message, display the bufffer. 852 ;; If output is too long to include in error message, display the buffer.
786 (cond ((eql status 0) ;success 853 (cond ((eql status 0) ;success
787 status) 854 status)
788 ((stringp status) ;kill string 855 ((stringp status) ;kill string
@@ -806,8 +873,8 @@ Call mh-set-folder-list to wait for the result."
806 873
807 874
808(defun mh-expand-file-name (filename &optional default) 875(defun mh-expand-file-name (filename &optional default)
809 "Just like `expand-file-name', but also handles MH folder names. 876 ;; Just like `expand-file-name', but also handles MH folder names.
810Assumes that any filename that starts with '+' is a folder name." 877 ;; Assumes that any filename that starts with '+' is a folder name.
811 (if (mh-folder-name-p filename) 878 (if (mh-folder-name-p filename)
812 (expand-file-name (substring filename 1) mh-user-path) 879 (expand-file-name (substring filename 1) mh-user-path)
813 (expand-file-name filename default))) 880 (expand-file-name filename default)))