Function: rmail-cease-edit

rmail-cease-edit is an interactive and byte-compiled function defined in rmailedit.el.gz.

Signature

(rmail-cease-edit &optional ABORT)

Documentation

This function has :override advice: hrmail--rmail-cease-edit.

This is an :override advice, which means that rmail-cease-edit isn't run at all, and the documentation below may be irrelevant.

Finish editing message; switch back to Rmail proper. If ABORT, this is the result of aborting an edit.

View in manual

Key Bindings

Source Code

;; Defined in /usr/src/emacs/lisp/mail/rmailedit.el.gz
(defun rmail-cease-edit (&optional abort)
  "Finish editing message; switch back to Rmail proper.
If ABORT, this is the result of aborting an edit."
  (interactive)
  (if (rmail-summary-exists)
      (with-current-buffer rmail-summary-buffer
	(rmail-summary-enable)))
  (widen)
  (goto-char (point-min))
  ;; This is far from ideal.  The edit may have inadvertently
  ;; removed the blank line at the end of the headers, but there
  ;; are almost certainly other blank lines.
  (or (search-forward "\n\n" nil t)
      (error "There must be a blank line at the end of the headers"))
  ;; Disguise any "From " lines so they don't start a new message.
  (goto-char (point-min))
  ;; This tries to skip the mbox From.  FIXME less fragile to go to EOH?
  (if (or rmail-old-mime-state
	  (not rmail-old-pruned))
      (forward-line 1))
  ;; When editing a non-MIME message, rmail-show-message-1 has unescaped
  ;; ^>*From lines according to rmail-mbox-format.  We are editing
  ;; the message as it was displayed, and need to put the escapes when done.
  ;; When editing a MIME message, we are editing the "raw" message.
  ;; ^>*From lines have not been escaped, but we still need to ensure
  ;; a "^From " line is escaped so as not to break later parsing (?).
  ;; With ^>+From lines, we have no way of knowing whether the person
  ;; doing the editing escaped them or not, so it seems best to leave
  ;; them alone.  (This all assumes you are using rmailmm rather than
  ;; something else that behaves differently.)
  (let ((fromline (if (or (eq 'mboxo rmail-mbox-format)
			  rmail-mime-decoded)
		      "^From "
		    "^>*From "))
	case-fold-search)
    (while (re-search-forward fromline nil t)
      (beginning-of-line)
      (insert ">")
      (forward-line)))
  (let ((old rmail-old-text)
	(pruned rmail-old-pruned)
	(mime-state rmail-old-mime-state)
	;; People who know what they are doing might have modified the
	;; buffer's encoding if editing the message included inserting
	;; characters that were unencodable by the original message's
	;; encoding.  Make note of the new encoding and use it for
	;; encoding the edited message.
	(edited-coding buffer-file-coding-system)
	new-headers
	character-coding is-text-message coding-system
	headers-end limit)
    ;; Make sure `edited-coding' can safely encode the edited message.
    (setq edited-coding
	  (select-safe-coding-system (point-min) (point-max) edited-coding))
    ;; Go back to Rmail mode, but carefully.
    (force-mode-line-update)
    (let ((rmail-buffer-swapped nil)) ; Prevent change-major-mode-hook
                                      ; from unswapping the buffers.
      (kill-all-local-variables)
      (rmail-mode-1)
      (if (boundp 'tool-bar-map)
          (setq-local tool-bar-map rmail-tool-bar-map))
      (setq buffer-undo-list t)
      (rmail-variables))
    ;; If text has really changed, mark message as edited.
    ;; FIXME we should do the comparison before escaping From lines.
    (unless (and (= (length old) (- (point-max) (point-min)))
		 (string= old (buffer-substring (point-min) (point-max))))
      (setq old nil)
      (goto-char (point-min))
      (search-forward "\n\n")
      (setq headers-end (point-marker)) ; first character of body
      (save-restriction
	(narrow-to-region (point-min) headers-end)
	;; If they changed the message's encoding, rewrite the charset=
	;; header for them, so that subsequent rmail-show-message
	;; decodes it correctly.
	(let* ((buffer-read-only nil)
	       (new-coding (coding-system-base edited-coding))
	       (mime-charset (symbol-name
			      (or (coding-system-get new-coding :mime-charset)
				  (if (coding-system-equal new-coding
							   'undecided)
				      'us-ascii
				    new-coding))))
	       old-coding mime-beg mime-end content-type)
          ;; If there's no content-type in the edited headers, look for one
          ;; in the original headers and add it to the edited headers
          ;; (Bug #26918)
          (unless (mail-fetch-field "Content-Type")
            (let (old-content-type
                  (msgbeg (rmail-msgbeg rmail-current-message))
                  (msgend (rmail-msgend rmail-current-message)))
              (with-current-buffer rmail-view-buffer ; really the mbox buffer
                (save-restriction
                  (narrow-to-region msgbeg msgend)
                  (goto-char (point-min))
                  (setq limit (search-forward "\n\n"))
                  (narrow-to-region (point-min) limit)
                  (goto-char (point-min))
                  (when (re-search-forward "^content-type:" limit t)
                    (forward-line)
                    (setq old-content-type (buffer-substring
                                            (match-beginning 0) (point))))))
              (when old-content-type
                (save-excursion
                  (goto-char headers-end) ; first char of body
                  (backward-char)         ; add header before second newline
                  (insert old-content-type)
                  ;;Add it to rmail-old-headers as though it had been
                  ;;there originally, to avoid rmail-edit-update-headers
                  ;;an extra copy
                  (let ((header (substring old-content-type 0
                                           (length "content-type"))))
                    (unless (assoc header rmail-old-headers)
                      (push (cons header old-content-type) rmail-old-headers)))
                  ))))
          (goto-char (point-min))
	  (if (re-search-forward rmail-mime-charset-pattern nil 'move)
	      (setq mime-beg (match-beginning 1)
		    mime-end (match-end 1)
		    old-coding (coding-system-from-name (match-string 1)))
	    (setq content-type (mail-fetch-field "Content-Type")))
	  (cond
	   ;; No match for rmail-mime-charset-pattern, but there was some
	   ;; other Content-Type.  We should not insert another.  (Bug#4624)
	   (content-type)
           ;; Don't insert anything if aborting.
           (abort)
	   ((null old-coding)
	    ;; If there was no charset= spec, insert one.
	    (backward-char 1)
	    (insert "Content-type: text/plain; charset=" mime-charset "\n"))
	   ((not (coding-system-equal (coding-system-base old-coding)
				      new-coding))
	    (goto-char mime-end)
	    (delete-region mime-beg mime-end)
	    (insert mime-charset)))))
      (setq new-headers (rmail-edit-headers-alist t))
      (rmail-swap-buffers-maybe)
      (narrow-to-region (rmail-msgbeg rmail-current-message)
			(rmail-msgend rmail-current-message))
      (goto-char (point-min))
      (setq limit (search-forward "\n\n"))
      (save-restriction
	;; All 3 of the functions we call below assume the buffer was
	;; narrowed to just the headers of the message.
	(narrow-to-region (point-min) limit)
	(setq character-coding
	      (mail-fetch-field "content-transfer-encoding")
	      is-text-message (rmail-is-text-p)
	      coding-system (if (and edited-coding
				     (not (coding-system-equal
					   (coding-system-base edited-coding)
					   'undecided)))
				edited-coding
			      (rmail-get-coding-system))))
      (if character-coding
	  (setq character-coding (downcase character-coding)))

      (goto-char limit)
      (let ((inhibit-read-only t)
            (data-buffer (current-buffer))
            (start (copy-marker (point) nil)) ; new body will be between
            (end (copy-marker (point) t)))    ; these two markers
        (if mime-state
            ;; Message is already in encoded state
            (insert-buffer-substring rmail-view-buffer headers-end
                                     (with-current-buffer rmail-view-buffer
                                       (point-max)))
          (with-current-buffer rmail-view-buffer
            (encode-coding-region headers-end (point-max) coding-system
                                  data-buffer)))
	;; Apply to the mbox buffer any changes in header fields
	;; that the user made while editing in the view buffer.
        (rmail-edit-update-headers (rmail-edit-diff-headers
				    rmail-old-headers new-headers))
	;; Re-apply content-transfer-encoding, if any, on the message body.
	(cond
	 (mime-state)		    ; if set, already transfer-encoded
	 ((string= character-coding "quoted-printable")
	  (mail-quote-printable-region start end))
	 ((and (string= character-coding "base64") is-text-message)
	  (base64-encode-region start end))
	 ((and (eq character-coding 'uuencode) is-text-message)
	  (error "uuencoded messages are not supported")))
        ;; After encoding, make sure buffer ends with a blank line so as not to
        ;; run this message together with the following one.
        (goto-char end)
        (rmail-ensure-blank-line)
        ;; Delete previous body.  This must be after all insertions at the end,
        ;; so the marker for the beginning of the next message isn't messed up.
        (delete-region end (point-max)))
      (rmail-set-attribute rmail-edited-attr-index t)
      (if (rmail-summary-exists)
          (let ((msgnum rmail-current-message))
            (with-current-buffer rmail-summary-buffer
              (rmail-summary-update-line msgnum)))))
    (rmail-show-message)
    (rmail-toggle-header (if pruned 1 0))
    ;; Restore mime display state.
    (and mime-state (rmail-mime nil mime-state)))
  (run-hooks 'rmail-mode-hook))