:group 'message-interface
:type 'regexp)
+
+(defcustom message-forward-ignored-headers nil
+ "*All headers that match this regexp will be deleted when forwarding a message."
+ :group 'message-forwarding
+ :type '(choice (const :tag "None" nil)
+ regexp))
+
(defcustom message-ignored-cited-headers "."
"*Delete these headers from the messages you yank."
:group 'message-insertion
:group 'message
:type 'symbol)
+(defcustom message-dont-reply-to-names rmail-dont-reply-to-names
+ "*A regexp specifying names to prune when doing wide replies.
+A value of nil means exclude your own name only."
+ :group 'message
+ :type '(choice (const :tag "Yourself" nil)
+ regexp))
+
;;; Internal variables.
;;; Well, not really internal.
"Face used for displaying MML."
:group 'message-faces)
-(defvar message-font-lock-keywords
- (let* ((cite-prefix "A-Za-z")
- (cite-suffix (concat cite-prefix "0-9_.@-"))
- (content "[ \t]*\\(.+\\(\n[ \t].*\\)*\\)"))
+(defvar message-font-lock-fence-open-regexp "[+|]"
+ "*Regexp that matches fence open string.")
+
+(defvar message-font-lock-fence-close-regexp "|"
+ "*Regexp that matches fence close string.")
+
+(defvar message-font-lock-fence-open-position nil
+ "*Cons of SYMBOL of a function or a variable and a number of OFFSET that
+indicate the fence open position. If it is non-nil,
+`message-font-lock-fence-open-regexp' is not used for searching for the
+fence open position. If SYMBOL is a function, it is called with one argument
+last cursor position and should return the fence open position as a number
+or a marker. If SYMBOL is a variable symbol, the value is examined with
+`symbol-value'. OFFSET is added to the position to compensate the value.
+For example, the following combinations of variable symbol and offset value
+can be used:
+
+Egg v3: '(egg:*region-start* . -1)
+Canna: '(canna:*region-start* . 0)
+")
+
+(defvar message-font-lock-fence-close-position nil
+ "*Cons of SYMBOL of a function or a variable and a number of OFFSET that
+indicate the fence close position. If it is non-nil,
+`message-font-lock-fence-close-regexp' is not used for searching for the
+fence close position. If SYMBOL is a function, it is called with one argument
+last cursor position and should return the fence close position as a number
+or a marker. If SYMBOL is a variable symbol, the value is examined with
+`symbol-value'. OFFSET is added to the position to compensate the value.
+For example, the following combinations of variable symbol and offset value
+can be used:
+
+Egg v3: '(egg:*region-end* . 0)
+Canna: '(canna:*region-end* . 0)
+")
+
+(defvar message-font-lock-cited-text-regexp
+ "^[\t ]*\\([^\000- :>|}\177]*\\)[:>|}].*"
+ "*Regexp that matches cited text. It should have a grouping for the
+citation prefix which is ended at the beginning of citation mark string.")
+
+(defvar message-font-lock-citation-name-max-column 10
+ "*Maximun number of column for citation name for fontifying.")
+
+(defvar message-font-lock-last-position nil
+ "Internal buffer local variable to save the last cursor position
+before fontifying.")
+
+(eval-after-load "font-lock"
+ '(defadvice font-lock-after-change-function
+ (before message-font-lock-save-last-position activate compile)
+ "Save last cursor position before fontifying."
+ (if (eq 'message-mode major-mode)
+ (setq message-font-lock-last-position (point)))))
+
+(defun message-font-lock-cited-text-matcher (limit)
+ "Search for a cited text containing `message-font-lock-cited-text-regexp'
+forward. Argument LIMIT bounds the search. If a cited text is found, it
+returns t and sets match data 1 and 2, otherwise it returns nil. Normally,
+match data 2 has zero length, but if the FENCE (for input method) is detected
+in matched text, result is divided into match data 1 and 2 across the FENCE.
+See also the documentations for the following variables:
+ `message-font-lock-fence-open-regexp'
+ `message-font-lock-fence-close-regexp'
+ `message-font-lock-fence-open-position'
+ `message-font-lock-fence-close-position'
+"
+ (prog1
+ (when (re-search-forward message-font-lock-cited-text-regexp limit t)
+ (let* ((start0 (match-beginning 0))
+ (end0 (match-end 0))
+ (cite-mark (match-end 1))
+ (should-fontify
+ (progn
+ (goto-char cite-mark)
+ (<= (current-column)
+ message-font-lock-citation-name-max-column)))
+ end1 start2)
+ (and
+ should-fontify
+ message-font-lock-last-position
+ (>= message-font-lock-last-position start0)
+ (<= message-font-lock-last-position end0)
+ (cond
+ (message-font-lock-fence-open-position
+ (let* ((symbol (car message-font-lock-fence-open-position))
+ (open
+ (cond ((functionp symbol)
+ (funcall symbol message-font-lock-last-position))
+ ((and (symbolp symbol)
+ (boundp symbol))
+ (symbol-value symbol)))))
+ (when (markerp open)
+ (setq open (marker-position open)))
+ (and (numberp open)
+ (setq open
+ (+ open
+ (cdr message-font-lock-fence-open-position)))
+ (>= message-font-lock-last-position open)
+ (goto-char open)
+ (or (not message-font-lock-fence-open-regexp)
+ (looking-at message-font-lock-fence-open-regexp))
+ (setq end1 open))))
+ (message-font-lock-fence-open-regexp
+ (goto-char message-font-lock-last-position)
+ (when (re-search-backward
+ message-font-lock-fence-open-regexp start0 t)
+ (setq end1 (match-beginning 0)))))
+ (setq should-fontify
+ (and message-font-lock-fence-open-position
+ (not (eq cite-mark end1))))
+ (cond
+ (message-font-lock-fence-close-position
+ (let* ((symbol (car message-font-lock-fence-close-position))
+ (close
+ (cond ((functionp symbol)
+ (funcall symbol message-font-lock-last-position))
+ ((and (symbolp symbol)
+ (boundp symbol))
+ (symbol-value symbol)))))
+ (when (markerp close)
+ (setq close (marker-position close)))
+ (and (numberp close)
+ (setq close
+ (+ close
+ (cdr message-font-lock-fence-close-position)))
+ (<= message-font-lock-last-position close)
+ (setq start2 close))))
+ (message-font-lock-fence-close-regexp
+ (goto-char message-font-lock-last-position)
+ (when (looking-at message-font-lock-fence-close-regexp)
+ (setq start2 (match-end 0)))))
+ (setq should-fontify
+ (and (not (and (not message-font-lock-fence-open-position)
+ (eq cite-mark end1)))
+ (not (eq cite-mark start2)))))
+ (goto-char end0)
+ (when should-fontify
+ (if start2
+ (store-match-data (list start0 end0 start0 end1 start2 end0))
+ (store-match-data (list start0 end0 start0 end0 end0 end0)))
+ t)))
+ (setq message-font-lock-last-position nil)))
+
+(defvar message-font-lock-keywords-1
+ (let ((content "[ \t]*\\(.+\\(\n[ \t].*\\)*\\)"))
`((,(concat "^\\([Tt]o:\\)" content)
(1 'message-header-name-face)
(2 'message-header-to-face nil t))
(not (equal mail-header-separator "")))
`((,(concat "^\\(" (regexp-quote mail-header-separator) "\\)$")
1 'message-separator-face))
- nil)
- (,(concat "^[ \t]*"
- "\\([" cite-prefix "]+[" cite-suffix "]*\\)?"
- "[:>|}].*")
- (0 'message-cited-text-face))
- ("<#/?\\(multipart\\|part\\|external\\).*>"
- (0 'message-mml-face))))
+ nil))))
+
+(defvar message-font-lock-keywords-2
+ (append message-font-lock-keywords-1
+ '((message-font-lock-cited-text-matcher
+ (1 'message-cited-text-face)
+ (2 'message-cited-text-face))
+ ("<#/?\\(multipart\\|part\\|external\\).*>"
+ (0 'message-mml-face)))))
+
+(defvar message-font-lock-keywords message-font-lock-keywords-2
"Additional expressions to highlight in Message mode.")
;; XEmacs does it like this. For Emacs, we have to set the
;; `font-lock-defaults' buffer-local variable.
-(put 'message-mode 'font-lock-defaults '(message-font-lock-keywords t))
+(put 'message-mode 'font-lock-defaults
+ '((message-font-lock-keywords
+ message-font-lock-keywords-1
+ message-font-lock-keywords-2)
+ nil nil nil nil
+ (font-lock-mark-block-function . mark-paragraph)))
(defvar message-face-alist
'((bold . bold-region)
"^ *---+ +Original message +---+ *$\\|"
"^ *--+ +begin message +--+ *$\\|"
"^ *---+ +Original message follows +---+ *$\\|"
+ "^ *---+ +Undelivered message follows +---+ *$\\|"
"^|? *---+ +Message text follows: +---+ *|?$")
"A regexp that matches the separator before the text of a failed message.")
(insert (car headers) ?\n))))
(setq headers (cdr headers))))
+
(defun message-fetch-reply-field (header)
"Fetch FIELD from the message we're replying to."
(let ((buffer (message-eval-parameter message-reply-buffer)))
(message-set-auto-save-file-name)
(unless (string-match "XEmacs" emacs-version)
(set (make-local-variable 'font-lock-defaults)
- '(message-font-lock-keywords t)))
+ '((message-font-lock-keywords
+ message-font-lock-keywords-1
+ message-font-lock-keywords-2)
+ nil nil nil nil
+ (font-lock-mark-block-function . mark-paragraph))))
+ (set (make-local-variable 'message-font-lock-last-position) nil)
(make-local-variable 'adaptive-fill-regexp)
(setq adaptive-fill-regexp
- (concat "[ \t]*[-a-z0-9A-Z]*>+[ \t]*\\|" adaptive-fill-regexp))
+ (concat "[ \t]*[-a-z0-9A-Z]*\\(>[ \t]*\\)+[ \t]*\\|"
+ adaptive-fill-regexp))
(unless (boundp 'adaptive-fill-first-line-regexp)
(setq adaptive-fill-first-line-regexp nil))
(make-local-variable 'adaptive-fill-first-line-regexp)
(setq adaptive-fill-first-line-regexp
- (concat "[ \t]*[-a-z0-9A-Z]*>+[ \t]*\\|"
+ (concat "[ \t]*[-a-z0-9A-Z]*\\(>[ \t]*\\)+[ \t]*\\|"
adaptive-fill-first-line-regexp))
(make-local-variable 'indent-tabs-mode) ;Turn off tabs for indentation.
(setq indent-tabs-mode nil)
quoted)
(save-excursion
(beginning-of-line)
- (setq quoted (looking-at (regexp-quote message-yank-prefix))))
+ (if (looking-at (sc-cite-regexp))
+ (setq quoted (buffer-substring (match-beginning 0) (match-end 0)))))
(insert "\n\n\n\n")
+ (delete-region (point) (re-search-forward "[ \t]*"))
(when quoted
- (insert message-yank-prefix))
+ (insert quoted))
(fill-paragraph nil)
(goto-char point)
(forward-line 2)))
(message-fix-before-sending)
(while (and success
(setq elem (pop alist)))
- (when (and (or (not (funcall (cadr elem)))
- (and (or (not (memq (car elem)
- message-sent-message-via))
- (y-or-n-p
- (format
- "Already sent message via %s; resend? "
- (car elem))))
- (setq success (funcall (caddr elem) arg)))))
+ (when (or (not (funcall (cadr elem)))
+ (and (or (not (memq (car elem)
+ message-sent-message-via))
+ (y-or-n-p
+ (format
+ "Already sent message via %s; resend? "
+ (car elem))))
+ (setq success (funcall (caddr elem) arg))))
(setq sent t))))
- (unless sent
+ (unless (or sent (not success))
(error "No methods specified to send by"))
(prog1
(when (and success sent)
(message-do-fcc)
- ;;(when (fboundp 'mail-hist-put-headers-into-history)
- ;; (mail-hist-put-headers-into-history))
(save-excursion
(run-hooks 'message-sent-hook))
(message "Sending...done")
;; This header didn't exist, so we insert it.
(goto-char (point-max))
(insert (if (stringp header) header (symbol-name header))
- ": " value "\n")
+ ": " value)
+ (unless (bolp)
+ (insert "\n"))
(forward-line -1))
;; The value of this header was empty, so we clear
;; totally and insert the new value.
(delete-region (point) (gnus-point-at-eol))
- (insert value))
+ (insert value)
+ (when (bolp)
+ (delete-char -1)))
;; Add the deletable property to the headers that require it.
(and (memq header message-deletable-headers)
(progn (beginning-of-line) (looking-at "[^:]+: "))
A typical situation where Mail-Followup-To is used is when the author thinks
that further discussion should take place only in "
- (if (string-match "," mft)
- "the specified mailing lists"
- "that mailing list") ".")))
+ (if (string-match "," mft)
+ "the specified mailing lists"
+ "that mailing list") ".")))
(setq follow-to (list (cons 'To mft)))
(when mct
(push (cons 'Cc mct) follow-to)))
(while (re-search-forward "[ \t]+" nil t)
(replace-match " " t t))
;; Remove addresses that match `rmail-dont-reply-to-names'.
- (insert (prog1 (rmail-dont-reply-to (buffer-string))
- (erase-buffer)))
+ (let ((rmail-dont-reply-to-names message-dont-reply-to-names))
+ (insert (prog1 (rmail-dont-reply-to (buffer-string))
+ (erase-buffer))))
(goto-char (point-min))
;; Perhaps Mail-Copies-To: never removed the only address?
(when (eobp)
;;;###autoload
(defun message-resend (address)
"Resend the current article to ADDRESS."
- (interactive "sResend message to: ")
+ (interactive
+ (list
+ (let ((mail-abbrev-mode-regexp ""))
+ (read-from-minibuffer
+ "Resend message to: " nil message-mode-map))))
(message "Resending message to %s..." address)
(save-excursion
(let ((cur (current-buffer))
(if (not (get-buffer message-save-buffer))
(get-buffer-create message-save-buffer))
(let ((filename buffer-file-name)
- (buffer (current-buffer)))
+ (buffer (current-buffer))
+ (reply-headers message-reply-headers))
(set-buffer message-save-buffer)
(erase-buffer)
(insert-buffer buffer)
+ (setq message-reply-headers reply-headers)
+ (message-generate-headers '((optional . In-Reply-To)))
(mime-edit-translate-buffer)
(write-region (point-min) (point-max) filename)
(set-buffer buffer)