Commit | Line | Data |
---|---|---|
537ab246 BG |
1 | ;;; rmailedit.el --- "RMAIL edit mode" Edit the current message |
2 | ||
ba318903 | 3 | ;; Copyright (C) 1985, 1994, 2001-2014 Free Software Foundation, Inc. |
537ab246 | 4 | |
34dc21db | 5 | ;; Maintainer: emacs-devel@gnu.org |
537ab246 | 6 | ;; Keywords: mail |
bd78fa1d | 7 | ;; Package: rmail |
537ab246 BG |
8 | |
9 | ;; This file is part of GNU Emacs. | |
10 | ||
11 | ;; GNU Emacs is free software: you can redistribute it and/or modify | |
12 | ;; it under the terms of the GNU General Public License as published by | |
13 | ;; the Free Software Foundation, either version 3 of the License, or | |
14 | ;; (at your option) any later version. | |
15 | ||
16 | ;; GNU Emacs is distributed in the hope that it will be useful, | |
17 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | |
18 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
19 | ;; GNU General Public License for more details. | |
20 | ||
21 | ;; You should have received a copy of the GNU General Public License | |
22 | ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. | |
23 | ||
24 | ;;; Commentary: | |
25 | ||
26 | ;;; Code: | |
27 | ||
a8e8f947 | 28 | (require 'rmail) |
537ab246 BG |
29 | |
30 | (defcustom rmail-edit-mode-hook nil | |
31 | "List of functions to call when editing an RMAIL message." | |
32 | :type 'hook | |
33 | :version "21.1" | |
34 | :group 'rmail-edit) | |
35 | ||
537ab246 | 36 | |
befa8175 SM |
37 | (defvar rmail-edit-map |
38 | (let ((map (make-sparse-keymap))) | |
39 | ;; Make a keymap that inherits text-mode-map. | |
40 | (set-keymap-parent map text-mode-map) | |
41 | (define-key map "\C-c\C-c" 'rmail-cease-edit) | |
42 | (define-key map "\C-c\C-]" 'rmail-abort-edit) | |
43 | map)) | |
44 | ||
04c17bea | 45 | (declare-function rmail-summary-disable "rmailsum" ()) |
537ab246 BG |
46 | |
47 | (defun rmail-edit-mode () | |
24683c51 GM |
48 | "Major mode for editing the contents of an Rmail message. |
49 | The editing commands are the same as in Text mode, together with | |
50 | two commands to return to regular Rmail: | |
51 | * \\[rmail-abort-edit] cancels any changes and returns to Rmail | |
537ab246 | 52 | * \\[rmail-cease-edit] makes them permanent. |
24683c51 | 53 | This function runs the hooks `text-mode-hook' and `rmail-edit-mode-hook'. |
537ab246 BG |
54 | \\{rmail-edit-map}" |
55 | (if (rmail-summary-exists) | |
befa8175 | 56 | (with-current-buffer rmail-summary-buffer |
537ab246 | 57 | (rmail-summary-disable))) |
24683c51 GM |
58 | ;; Prevent change-major-mode-hook from unswapping the buffers. |
59 | (let ((rmail-buffer-swapped nil)) | |
537ab246 BG |
60 | (delay-mode-hooks (text-mode)) |
61 | (use-local-map rmail-edit-map) | |
62 | (setq major-mode 'rmail-edit-mode) | |
63 | (setq mode-name "RMAIL Edit") | |
64 | (if (boundp 'mode-line-modified) | |
65 | (setq mode-line-modified (default-value 'mode-line-modified)) | |
66 | (setq mode-line-format (default-value 'mode-line-format))) | |
a4f69701 CY |
67 | ;; Don't turn off auto-saving based on the size of the buffer |
68 | ;; because that code does not understand buffer-swapping. | |
69 | (make-local-variable 'auto-save-include-big-deletions) | |
70 | (setq auto-save-include-big-deletions t) | |
52b9c461 GM |
71 | ;; If someone uses C-x C-s, don't clobber the rmail file (bug#2625). |
72 | (add-hook 'write-region-annotate-functions | |
73 | 'rmail-write-region-annotate nil t) | |
537ab246 BG |
74 | (run-mode-hooks 'rmail-edit-mode-hook))) |
75 | ||
a8e8f947 GM |
76 | ;; Rmail Edit mode is suitable only for specially formatted data. |
77 | (put 'rmail-edit-mode 'mode-class 'special) | |
24683c51 | 78 | \f |
a8e8f947 GM |
79 | |
80 | (defvar rmail-old-text) | |
6ad1cdde | 81 | (defvar rmail-old-mime-state) |
a8e8f947 GM |
82 | (defvar rmail-old-pruned nil |
83 | "Non-nil means the message being edited originally had pruned headers.") | |
537ab246 BG |
84 | (put 'rmail-old-pruned 'permanent-local t) |
85 | ||
1945c7a7 RS |
86 | (defvar rmail-old-headers nil |
87 | "Holds the headers of this message before editing started.") | |
88 | (put 'rmail-old-headers 'permanent-local t) | |
89 | ||
6ad1cdde GM |
90 | ;; Everything we use from here is a defsubst. |
91 | (eval-when-compile | |
92 | (require 'rmailmm)) | |
93 | ||
537ab246 BG |
94 | ;;;###autoload |
95 | (defun rmail-edit-current-message () | |
96 | "Edit the contents of this message." | |
97 | (interactive) | |
a8e8f947 | 98 | (if (zerop rmail-total-messages) |
537ab246 | 99 | (error "No messages in this buffer")) |
f5b574ad | 100 | (rmail-modify-format) |
1945c7a7 RS |
101 | (make-local-variable 'rmail-old-pruned) |
102 | (setq rmail-old-pruned (rmail-msg-is-pruned)) | |
537ab246 | 103 | (rmail-edit-mode) |
6ad1cdde GM |
104 | (set (make-local-variable 'rmail-old-mime-state) |
105 | (and rmail-enable-mime | |
106 | ;; If you use something else, you are on your own. | |
107 | (eq rmail-mime-feature 'rmailmm) | |
108 | (rmail-mime-message-p) | |
109 | (let ((entity (get-text-property (point-min) 'rmail-mime-entity))) | |
110 | ;; rmailmm has got its hands on the message. | |
111 | ;; Even if the message is in `raw' state, boundaries etc | |
112 | ;; are still missing. All we can do is insert the real | |
113 | ;; raw message. (Bug#9840) | |
fefa2990 GM |
114 | ;; FIXME? Since the 2012-09-17 changes to rmail-mime, |
115 | ;; can we just use that function now? | |
6ad1cdde GM |
116 | (when (and entity |
117 | (not (equal "text/plain" | |
118 | (car (rmail-mime-entity-type entity))))) | |
119 | (let ((inhibit-read-only t)) | |
120 | (erase-buffer) | |
121 | (insert-buffer-substring | |
122 | rmail-view-buffer | |
123 | (aref (rmail-mime-entity-header entity) 0) | |
124 | (aref (rmail-mime-entity-body entity) 1))) | |
125 | (goto-char (point-min)) | |
126 | ;; t = decoded; raw = raw. | |
127 | (aref (aref (rmail-mime-entity-display entity) 0) 0))))) | |
1945c7a7 RS |
128 | (make-local-variable 'rmail-old-text) |
129 | (setq rmail-old-text | |
130 | (save-restriction | |
131 | (widen) | |
132 | (buffer-substring (point-min) (point-max)))) | |
133 | (make-local-variable 'rmail-old-headers) | |
134 | (setq rmail-old-headers (rmail-edit-headers-alist t)) | |
537ab246 BG |
135 | (setq buffer-read-only nil) |
136 | (setq buffer-undo-list nil) | |
e97389b9 | 137 | ;; Whether the buffer is initially marked as modified or not |
a8e8f947 | 138 | ;; depends on whether or not the underlying rmail buffer was so marked. |
e97389b9 GM |
139 | ;; Given the way this works, it has to. |
140 | ;; If you kill the edit buffer, you've killed your rmail buffer. | |
537ab246 BG |
141 | (force-mode-line-update) |
142 | (if (and (eq (key-binding "\C-c\C-c") 'rmail-cease-edit) | |
143 | (eq (key-binding "\C-c\C-]") 'rmail-abort-edit)) | |
144 | (message "Editing: Type C-c C-c to return to Rmail, C-c C-] to abort") | |
145 | (message "%s" (substitute-command-keys | |
146 | "Editing: Type \\[rmail-cease-edit] to return to Rmail, \\[rmail-abort-edit] to abort")))) | |
147 | ||
a8e8f947 GM |
148 | |
149 | (declare-function rmail-summary-enable "rmailsum" ()) | |
150 | ||
537ab246 BG |
151 | (defun rmail-cease-edit () |
152 | "Finish editing message; switch back to Rmail proper." | |
153 | (interactive) | |
154 | (if (rmail-summary-exists) | |
befa8175 | 155 | (with-current-buffer rmail-summary-buffer |
537ab246 BG |
156 | (rmail-summary-enable))) |
157 | (widen) | |
0b44494a GM |
158 | (goto-char (point-min)) |
159 | ;; This is far from ideal. The edit may have inadvertently | |
160 | ;; removed the blank line at the end of the headers, but there | |
161 | ;; are almost certainly other blank lines. | |
162 | (or (search-forward "\n\n" nil t) | |
163 | (error "There must be a blank line at the end of the headers")) | |
537ab246 | 164 | ;; Disguise any "From " lines so they don't start a new message. |
0b44494a | 165 | (goto-char (point-min)) |
6ad1cdde GM |
166 | ;; This tries to skip the mbox From. FIXME less fragile to go to EOH? |
167 | (if (or rmail-old-mime-state | |
168 | (not rmail-old-pruned)) | |
169 | (forward-line 1)) | |
54c8b5ba GM |
170 | ;; When editing a non-MIME message, rmail-show-message-1 has unescaped |
171 | ;; ^>*From lines according to rmail-mbox-format. We are editing | |
172 | ;; the message as it was displayed, and need to put the escapes when done. | |
173 | ;; When editing a MIME message, we are editing the "raw" message. | |
174 | ;; ^>*From lines have not been escaped, but we still need to ensure | |
175 | ;; a "^From " line is escaped so as not to break later parsing (?). | |
176 | ;; With ^>+From lines, we have no way of knowing whether the person | |
177 | ;; doing the editing escaped them or not, so it seems best to leave | |
178 | ;; them alone. (This all assumes you are using rmailmm rather than | |
179 | ;; something else that behaves differently.) | |
180 | (let ((fromline (if (or (eq 'mboxo rmail-mbox-format) | |
181 | rmail-mime-decoded) | |
182 | "^From " | |
183 | "^>*From ")) | |
184 | case-fold-search) | |
185 | (while (re-search-forward fromline nil t) | |
186 | (beginning-of-line) | |
187 | (insert ">") | |
188 | (forward-line))) | |
da5f6330 GM |
189 | ;; Make sure buffer ends with a blank line so as not to run this |
190 | ;; message together with the following one. | |
0b44494a GM |
191 | (goto-char (point-max)) |
192 | (rmail-ensure-blank-line) | |
537ab246 | 193 | (let ((old rmail-old-text) |
a8e8f947 | 194 | (pruned rmail-old-pruned) |
6ad1cdde | 195 | (mime-state rmail-old-mime-state) |
ff4abce9 EZ |
196 | ;; People who know what they are doing might have modified the |
197 | ;; buffer's encoding if editing the message included inserting | |
198 | ;; characters that were unencodable by the original message's | |
199 | ;; encoding. Make note of the new encoding and use it for | |
200 | ;; encoding the edited message. | |
201 | (edited-coding buffer-file-coding-system) | |
1945c7a7 | 202 | new-headers |
537ab246 | 203 | character-coding is-text-message coding-system |
782c80e8 | 204 | headers-end limit) |
ff4abce9 EZ |
205 | ;; Make sure `edited-coding' can safely encode the edited message. |
206 | (setq edited-coding | |
207 | (select-safe-coding-system (point-min) (point-max) edited-coding)) | |
537ab246 BG |
208 | ;; Go back to Rmail mode, but carefully. |
209 | (force-mode-line-update) | |
befa8175 SM |
210 | (let ((rmail-buffer-swapped nil)) ; Prevent change-major-mode-hook |
211 | ; from unswapping the buffers. | |
537ab246 BG |
212 | (kill-all-local-variables) |
213 | (rmail-mode-1) | |
214 | (if (boundp 'tool-bar-map) | |
215 | (set (make-local-variable 'tool-bar-map) rmail-tool-bar-map)) | |
216 | (setq buffer-undo-list t) | |
217 | (rmail-variables)) | |
218 | ;; If text has really changed, mark message as edited. | |
54c8b5ba | 219 | ;; FIXME we should do the comparison before escaping From lines. |
537ab246 BG |
220 | (unless (and (= (length old) (- (point-max) (point-min))) |
221 | (string= old (buffer-substring (point-min) (point-max)))) | |
222 | (setq old nil) | |
223 | (goto-char (point-min)) | |
224 | (search-forward "\n\n") | |
25ab0302 GM |
225 | (setq headers-end (point-marker)) |
226 | (goto-char (point-min)) | |
227 | (save-restriction | |
228 | (narrow-to-region (point) headers-end) | |
229 | ;; If they changed the message's encoding, rewrite the charset= | |
230 | ;; header for them, so that subsequent rmail-show-message | |
231 | ;; decodes it correctly. | |
232 | (let* ((buffer-read-only nil) | |
233 | (new-coding (coding-system-base edited-coding)) | |
234 | (mime-charset (symbol-name | |
235 | (or (coding-system-get new-coding :mime-charset) | |
236 | (if (coding-system-equal new-coding | |
237 | 'undecided) | |
238 | 'us-ascii | |
239 | new-coding)))) | |
240 | old-coding mime-beg mime-end content-type) | |
241 | (if (re-search-forward rmail-mime-charset-pattern nil 'move) | |
242 | (setq mime-beg (match-beginning 1) | |
243 | mime-end (match-end 1) | |
244 | old-coding (coding-system-from-name (match-string 1))) | |
245 | (setq content-type (mail-fetch-field "Content-Type"))) | |
246 | (cond | |
247 | ;; No match for rmail-mime-charset-pattern, but there was some | |
248 | ;; other Content-Type. We should not insert another. (Bug#4624) | |
249 | (content-type) | |
250 | ((null old-coding) | |
251 | ;; If there was no charset= spec, insert one. | |
252 | (backward-char 1) | |
253 | (insert "Content-type: text/plain; charset=" mime-charset "\n")) | |
254 | ((not (coding-system-equal (coding-system-base old-coding) | |
255 | new-coding)) | |
256 | (goto-char mime-end) | |
257 | (delete-region mime-beg mime-end) | |
258 | (insert mime-charset))))) | |
1945c7a7 | 259 | (setq new-headers (rmail-edit-headers-alist t)) |
537ab246 | 260 | (rmail-swap-buffers-maybe) |
aaaaa276 | 261 | (narrow-to-region (rmail-msgbeg rmail-current-message) |
782c80e8 | 262 | (rmail-msgend rmail-current-message)) |
0b44494a GM |
263 | (goto-char (point-min)) |
264 | (setq limit (search-forward "\n\n")) | |
782c80e8 | 265 | (save-restriction |
782c80e8 EZ |
266 | ;; All 3 of the functions we call below assume the buffer was |
267 | ;; narrowed to just the headers of the message. | |
0b44494a | 268 | (narrow-to-region (point-min) limit) |
782c80e8 EZ |
269 | (setq character-coding |
270 | (mail-fetch-field "content-transfer-encoding") | |
271 | is-text-message (rmail-is-text-p) | |
ff4abce9 EZ |
272 | coding-system (if (and edited-coding |
273 | (not (coding-system-equal | |
274 | (coding-system-base edited-coding) | |
275 | 'undecided))) | |
276 | edited-coding | |
277 | (rmail-get-coding-system)))) | |
537ab246 BG |
278 | (if character-coding |
279 | (setq character-coding (downcase character-coding))) | |
280 | ||
782c80e8 | 281 | (goto-char limit) |
aaaaa276 EZ |
282 | (let ((inhibit-read-only t)) |
283 | (let ((data-buffer (current-buffer)) | |
284 | (end (copy-marker (point) t))) | |
285 | (with-current-buffer rmail-view-buffer | |
286 | (encode-coding-region headers-end (point-max) coding-system | |
287 | data-buffer)) | |
288 | (delete-region end (point-max))) | |
537ab246 | 289 | |
1945c7a7 RS |
290 | ;; Apply to the mbox buffer any changes in header fields |
291 | ;; that the user made while editing in the view buffer. | |
292 | (rmail-edit-update-headers (rmail-edit-diff-headers | |
293 | rmail-old-headers new-headers)) | |
294 | ||
a8e8f947 | 295 | ;; Re-apply content-transfer-encoding, if any, on the message body. |
537ab246 BG |
296 | (cond |
297 | ((string= character-coding "quoted-printable") | |
aaaaa276 | 298 | (mail-quote-printable-region (point) (point-max))) |
537ab246 | 299 | ((and (string= character-coding "base64") is-text-message) |
aaaaa276 | 300 | (base64-encode-region (point) (point-max))) |
782c80e8 | 301 | ((and (eq character-coding 'uuencode) is-text-message) |
a8e8f947 GM |
302 | (error "uuencoded messages are not supported")))) |
303 | (rmail-set-attribute rmail-edited-attr-index t)) | |
537ab246 | 304 | ;;??? BROKEN perhaps. |
a8e8f947 GM |
305 | ;;; (if (boundp 'rmail-summary-vector) |
306 | ;;; (aset rmail-summary-vector (1- rmail-current-message) nil)) | |
0b44494a | 307 | (rmail-show-message) |
6ad1cdde GM |
308 | (rmail-toggle-header (if pruned 1 0)) |
309 | ;; Restore mime display state. | |
310 | (and mime-state (rmail-mime nil mime-state))) | |
537ab246 BG |
311 | (run-hooks 'rmail-mode-hook)) |
312 | ||
313 | (defun rmail-abort-edit () | |
314 | "Abort edit of current message; restore original contents." | |
315 | (interactive) | |
316 | (widen) | |
317 | (delete-region (point-min) (point-max)) | |
318 | (insert rmail-old-text) | |
319 | (rmail-cease-edit) | |
320 | (rmail-highlight-headers)) | |
1945c7a7 RS |
321 | \f |
322 | (defun rmail-edit-headers-alist (&optional widen markers) | |
323 | "Return an alist of the headers of the message in the current buffer. | |
324 | Each element has the form (HEADER-NAME . ENTIRE-STRING). | |
325 | ENTIRE-STRING includes the name of the header field (which is HEADER-NAME) | |
326 | and has a final newline. | |
327 | If part of the text is not valid as a header field, HEADER-NAME | |
328 | is an integer and we use consecutive integers. | |
329 | ||
330 | If WIDEN is non-nil, operate on the entire buffer. | |
331 | ||
332 | If MARKERS is non-nil, the value looks like | |
333 | \(HEADER-NAME ENTIRE-STRING BEG-MARKER END-MARKER)." | |
334 | (let (header-alist (no-good-header-count 1)) | |
335 | (save-excursion | |
336 | (save-restriction | |
337 | (if widen (widen)) | |
338 | (goto-char (point-min)) | |
339 | (search-forward "\n\n") | |
340 | (narrow-to-region (point-min) (1- (point))) | |
341 | (goto-char (point-min)) | |
342 | (while (not (eobp)) | |
343 | (let ((start (point)) | |
344 | name header) | |
345 | ;; Match the name. | |
346 | (if (looking-at "[ \t]*\\([^:\n \t]\\(\\|[^:\n]*[^:\n \t]\\)\\)[ \t]*:") | |
347 | (setq name (match-string-no-properties 1)) | |
348 | (setq name no-good-header-count | |
349 | no-good-header-count (1+ no-good-header-count))) | |
350 | (forward-line 1) | |
351 | (while (looking-at "[ \t]") | |
352 | (forward-line 1)) | |
353 | (setq header (buffer-substring-no-properties start (point))) | |
354 | (if markers | |
355 | (push (list header (copy-marker start) (point-marker)) | |
356 | header-alist) | |
357 | (push (cons name header) header-alist)))))) | |
358 | (nreverse header-alist))) | |
359 | ||
360 | ||
361 | (defun rmail-edit-diff-headers (old-headers new-headers) | |
362 | "Compare OLD-HEADERS and NEW-HEADERS and return field differences. | |
363 | The value is a list of three lists, (INSERTED DELETED CHANGED). | |
364 | ||
365 | INSERTED's elements describe inserted header fields | |
366 | and each looks like (AFTER-WHAT INSERT-WHAT) | |
367 | INSERT-WHAT is the header field to insert (a member of NEW-HEADERS). | |
368 | AFTER-WHAT is the field to insert it after (a member of NEW-HEADERS) | |
369 | or else nil to insert it at the beginning. | |
370 | ||
371 | DELETED's elements are elements of OLD-HEADERS. | |
372 | CHANGED's elements have the form (OLD . NEW) | |
373 | where OLD is a element of OLD-HEADERS and NEW is an element of NEW-HEADERS." | |
374 | ||
375 | (let ((reverse-new (reverse new-headers)) | |
376 | inserted deleted changed) | |
377 | (dolist (old old-headers) | |
378 | (let ((new (assoc (car old) new-headers))) | |
379 | ;; If it's in OLD-HEADERS and has no new counterpart, | |
380 | ;; it is a deletion. | |
381 | (if (null new) | |
382 | (push old deleted) | |
383 | ;; If it has a new counterpart, maybe it was changed. | |
384 | (unless (equal (cdr old) (cdr new)) | |
385 | (push (cons old new) changed)) | |
386 | ;; Remove the new counterpart, since it has been spoken for. | |
387 | (setq new-headers (remq new new-headers))))) | |
388 | ;; Look at the new headers with no old counterpart. | |
389 | (dolist (new new-headers) | |
390 | (let ((prev (cadr (member new reverse-new)))) | |
59a6d249 RS |
391 | ;; Mark each one as an insertion. |
392 | ;; Record the previous new header, to insert it after that. | |
393 | (push (list prev new) inserted))) | |
1945c7a7 RS |
394 | ;; It is crucial to return the insertions in buffer order |
395 | ;; so that `rmail-edit-update-headers' can insert a field | |
396 | ;; after a new field. | |
397 | (list (nreverse inserted) | |
398 | (nreverse deleted) | |
399 | (nreverse changed)))) | |
400 | ||
401 | (defun rmail-edit-update-headers (header-diff) | |
402 | "Edit the mail headers in the buffer based on HEADER-DIFF. | |
403 | HEADER-DIFF should be a return value from `rmail-edit-diff-headers'." | |
404 | (let ((buf-headers (rmail-edit-headers-alist nil t))) | |
405 | ;; Change all the fields scheduled for being changed. | |
406 | (dolist (chg (nth 2 header-diff)) | |
407 | (let* ((match (assoc (cdar chg) buf-headers)) | |
408 | (end (marker-position (nth 2 match)))) | |
409 | (goto-char end) | |
410 | ;; Insert the new, then delete the old. | |
411 | ;; That avoids collapsing markers. | |
412 | (insert-before-markers (cddr chg)) | |
413 | (delete-region (nth 1 match) end) | |
414 | ;; Remove the old field from BUF-HEADERS. | |
415 | (setq buf-headers (delq match buf-headers)) | |
416 | ;; Update BUF-HEADERS to show the changed field. | |
417 | (push (list (cddr chg) (point-marker) | |
418 | (copy-marker (- (point) (length (cddr chg)))) | |
419 | (point-marker)) | |
420 | buf-headers))) | |
421 | ;; Delete all the fields scheduled for deletion. | |
422 | ;; We do deletion after changes | |
423 | ;; because when two fields look alike and get replaced by one, | |
424 | ;; the first of them is considered changed | |
425 | ;; and the second is considered deleted. | |
426 | (dolist (del (nth 1 header-diff)) | |
427 | (let ((match (assoc (cdr del) buf-headers))) | |
428 | (delete-region (nth 1 match) (nth 2 match)))) | |
429 | ;; Insert all the fields scheduled for insertion. | |
430 | (dolist (ins (nth 0 header-diff)) | |
431 | (let* ((new (cadr ins)) | |
432 | (after (car ins)) | |
433 | (match (assoc (cdr after) buf-headers))) | |
434 | (goto-char (if match (nth 2 match) (point-min))) | |
435 | (insert (cdr new)) | |
436 | ;; Update BUF-HEADERS to show the inserted field. | |
437 | (push (list (cdr new) | |
438 | (copy-marker (- (point) (length (cdr new)))) | |
439 | (point-marker)) | |
440 | buf-headers))) | |
441 | ;; Disconnect the markers | |
442 | (dolist (hdr buf-headers) | |
443 | (set-marker (nth 1 hdr) nil) | |
444 | (set-marker (nth 2 hdr) nil)))) | |
537ab246 BG |
445 | |
446 | (provide 'rmailedit) | |
447 | ||
35426db4 GM |
448 | ;; Local Variables: |
449 | ;; generated-autoload-file: "rmail.el" | |
450 | ;; End: | |
451 | ||
537ab246 | 452 | ;;; rmailedit.el ends here |