diff options
| author | Karl Heuer | 1995-04-09 22:29:08 +0000 |
|---|---|---|
| committer | Karl Heuer | 1995-04-09 22:29:08 +0000 |
| commit | b6d4ab054bc16fb43ccb01e8a9663c71749e5b28 (patch) | |
| tree | f216ab997282559d2a759ee132144e323e878e76 | |
| parent | 85e36d2b62818790cc609cfe8a981ed2c50c8354 (diff) | |
| download | emacs-b6d4ab054bc16fb43ccb01e8a9663c71749e5b28.tar.gz emacs-b6d4ab054bc16fb43ccb01e8a9663c71749e5b28.zip | |
New version from author
| -rw-r--r-- | lisp/mail/mh-utils.el | 313 |
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 @@ | |||
| 39 | This directory contains, among other things, | 43 | This directory contains, among other things, |
| 40 | the mhl program and the components file.") | 44 | the 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 | |||
| 60 | overrides `mh-invisible-headers'.") | 69 | overrides `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. |
| 65 | If `mh-visible-headers' is non-nil, it is used instead to specify what | 74 | If `mh-visible-headers' is non-nil, it is used instead to specify what |
| 66 | to keep.") | 75 | to keep.") |
| @@ -87,57 +96,84 @@ with the default format file, to format messages when printing them. | |||
| 87 | The format used should specify a non-zero value for overflowoffset so | 96 | The format used should specify a non-zero value for overflowoffset so |
| 88 | the message continues to conform to RFC 822 and mh-e can parse the headers.") | 97 | the 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. |
| 92 | Called by `\\[mh-refile-msg]' and `\\[mh-to-fcc]' to get a default | 101 | If set to a function, that function is called with no arguments by |
| 93 | when 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 |
| 94 | with point at the start of the message. Should return the folder to offer | 103 | prompting the user for a folder. The function is called from within a |
| 95 | as the refile or Fcc folder, as a string with a leading `+' sign.") | 104 | save-excursion, with point at the start of the message. It should |
| 105 | return the folder to offer as the refile or Fcc folder, as a string | ||
| 106 | with a leading `+' sign. It can also return an empty string to use no | ||
| 107 | default, or NIL to calculate the default the usual way. | ||
| 108 | NOTE: This variable is not an ordinary hook; | ||
| 109 | It 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. | ||
| 119 | First 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. |
| 109 | NIL 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 () |
| 140 | If nil, show buffer contains message processed normally.") | 166 | "When moving to a new message in the Folder window, |
| 167 | also 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). |
| 203 | Force a two-window display with the folder window on top (size | 241 | Force a two-window display with the folder window on top (size |
| 204 | mh-summary-height) and the show buffer below it. | 242 | mh-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. |
| 402 | Non-nil second argument means do not signal an error if message does not exist. | 442 | Optional non-nil second argument means return nil instead of |
| 403 | Non-nil third argument means not to show the message. | 443 | signaling an error if message does not exist. |
| 404 | Return non-nil if cursor is at message." | 444 | Non-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. |
| 615 | A 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 |
| 616 | Format 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. |
| 630 | Call 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. |
| 810 | Assumes 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))) |