(message-resend): Bind rfc2047-encode-encoded-words.
[gnus] / lisp / message.el
index b0a1f1e..a5e5442 100644 (file)
@@ -724,11 +724,6 @@ might set this variable to '(\"-f\" \"you@some.where\")."
   :type '(choice (function)
                 (repeat string)))
 
-(defvar message-cater-to-broken-inn t
-  "Non-nil means Gnus should not fold the `References' header.
-Folding `References' makes ancient versions of INN create incorrect
-NOV lines.")
-
 (eval-when-compile
   (defvar gnus-post-method)
   (defvar gnus-select-method))
@@ -1484,10 +1479,16 @@ no, only reply back to the author."
          "^|? *---+ +Message text follows: +---+ *|?$")
   "A regexp that matches the separator before the text of a failed message.")
 
+(defvar message-field-fillers
+  '((To message-fill-field-address)
+    (Cc message-fill-field-address)
+    (From message-fill-field-address))
+  "Alist of header names/filler functions.")
+
 (defvar message-header-format-alist
   `((Newsgroups)
-    (To . message-fill-address)
-    (Cc . message-fill-address)
+    (To)
+    (Cc)
     (Subject)
     (In-Reply-To)
     (Fcc)
@@ -1649,6 +1650,8 @@ see `message-narrow-to-headers-or-head'."
 (defun message-narrow-to-field ()
   "Narrow the buffer to the header on the current line."
   (beginning-of-line)
+  (while (looking-at "[ \t]")
+    (forward-line -1))
   (narrow-to-region
    (point)
    (progn
@@ -2130,6 +2133,12 @@ Point is left at the beginning of the narrowed-to region."
             (1+ max)))))
       (message-sort-headers-1))))
 
+(defun message-kill-address ()
+  "Kill the address under point."
+  (interactive)
+  (let ((start (point)))
+    (message-skip-to-next-address)
+    (kill-region start (point))))
 
 \f
 
@@ -2202,11 +2211,11 @@ Point is left at the beginning of the narrowed-to region."
   (define-key message-mode-map "\C-c\C-d" 'message-dont-send)
   (define-key message-mode-map "\C-c\n" 'gnus-delay-article)
 
+  (define-key message-mode-map "\C-c\M-k" 'message-kill-address)
   (define-key message-mode-map "\C-c\C-e" 'message-elide-region)
   (define-key message-mode-map "\C-c\C-v" 'message-delete-not-region)
   (define-key message-mode-map "\C-c\C-z" 'message-kill-to-signature)
   (define-key message-mode-map "\M-\r" 'message-newline-and-reformat)
-  ;;(define-key message-mode-map "\M-q" 'message-fill-paragraph)
   (define-key message-mode-map [remap split-line]  'message-split-line)
 
   (define-key message-mode-map "\C-c\C-a" 'mml-attach-file)
@@ -2870,7 +2879,9 @@ Prefix arg means justify as well."
   (interactive (list (if current-prefix-arg 'full)))
   (if (if (boundp 'filladapt-mode) filladapt-mode)
       nil
-    (message-newline-and-reformat arg t)
+    (if (message-point-in-header-p)
+       (message-fill-field)
+      (message-newline-and-reformat arg t))
     t))
 
 ;; Is it better to use `mail-header-end'?
@@ -4880,55 +4891,25 @@ subscribed address (and not the additional To and Cc header contents)."
              list
            msg-recipients))))))
 
-(defun message-idna-inside-rhs-p ()
-  "Return t iff point is inside a RHS (heuristically).
-Only works properly if header contains mailbox-list or address-list.
-I.e., calling it on a Subject: header is useless."
-  (save-restriction
-    (narrow-to-region (save-excursion (or (re-search-backward "^[^ \t]" nil t)
-                                         (point-min)))
-                     (save-excursion (or (re-search-forward "^[^ \t]" nil t)
-                                         (point-max))))
-    (if (re-search-backward "[\\\n\r\t ]"
-                           (save-excursion (search-backward "@" nil t)) t)
-       ;; whitespace between @ and point
-       nil
-      (let ((dquote 1) (paren 1))
-       (while (save-excursion (re-search-backward "[^\\]\"" nil t dquote))
-         (incf dquote))
-       (while (save-excursion (re-search-backward "[^\\]\(" nil t paren))
-         (incf paren))
-       (and (= (% dquote 2) 1) (= (% paren 2) 1))))))
-
 (defun message-idna-to-ascii-rhs-1 (header)
   "Interactively potentially IDNA encode domain names in HEADER."
-  (let (rhs ace start startpos endpos ovl)
-    (goto-char (point-min))
-    (while (re-search-forward (concat "^" header) nil t)
-      (while (re-search-forward "@\\([^ \t\r\n>,]+\\)"
-                               (or (save-excursion
-                                     (re-search-forward "^[^ \t]" nil t))
-                                   (point-max))
-                               t)
-       (setq rhs (match-string-no-properties 1)
-             startpos (match-beginning 1)
-             endpos (match-end 1))
-       (when (save-match-data
-               (and (message-idna-inside-rhs-p)
-                    (setq ace (idna-to-ascii rhs))
-                    (not (string= rhs ace))
-                    (if (eq message-use-idna 'ask)
-                        (unwind-protect
-                            (progn
-                              (setq ovl (message-make-overlay startpos
-                                                              endpos))
-                              (message-overlay-put ovl 'face 'highlight)
-                              (y-or-n-p
-                               (format "Replace with `%s'? " ace)))
-                          (message "")
-                          (message-delete-overlay ovl))
-                      message-use-idna)))
-         (replace-match (concat "@" ace)))))))
+  (let ((field (message-fetch-field header))
+       rhs ace  address)
+    (when field
+      (dolist (address (mail-header-parse-addresses field))
+       (setq address (car address)
+             rhs (downcase (cadr (split-string address "@")))
+             ace (downcase (idna-to-ascii rhs)))
+       (when (and (not (equal rhs ace))
+                  (or (not (eq message-use-idna 'ask))
+                      (y-or-n-p (format "Replace %s with %s? " rhs ace))))
+         (goto-char (point-min))
+         (while (re-search-forward (concat "^" header ":") nil t)
+           (message-narrow-to-field)
+           (while (search-forward (concat "@" rhs) nil t)
+             (replace-match (concat "@" ace) t t))
+           (goto-char (point-max))
+           (widen)))))))
 
 (defun message-idna-to-ascii-rhs ()
   "Possibly IDNA encode non-ASCII domain names in From:, To: and Cc: headers.
@@ -5049,8 +5030,9 @@ Headers already prepared in the buffer are not modified."
                      (if formatter
                          (funcall formatter header value)
                        (insert header-string ": " value))
+                     (goto-char (message-fill-field))
                      ;; We check whether the value was ended by a
-                     ;; newline.  If now, we insert one.
+                     ;; newline.  If not, we insert one.
                      (unless (bolp)
                        (insert "\n"))
                      (forward-line -1)))
@@ -5061,7 +5043,8 @@ Headers already prepared in the buffer are not modified."
                ;; empty, we con't insert it anyway.
                (unless optionalp
                  (push header-string message-inserted-headers)
-                 (insert value)))
+                 (insert value)
+                 (message-fill-field)))
              ;; Add the deletable property to the headers that require it.
              (and (memq header message-deletable-headers)
                   (progn (beginning-of-line) (looking-at "[^:]+: "))
@@ -5117,35 +5100,29 @@ Headers already prepared in the buffer are not modified."
 ;;; Setting up a message buffer
 ;;;
 
+(defun message-skip-to-next-address ()
+  (let ((end (save-excursion
+              (message-next-header)
+              (point)))
+       quoted char)
+    (when (looking-at ",")
+      (forward-char 1))
+    (while (and (not (= (point) end))
+               (or (not (eq char ?,))
+                   quoted))
+      (skip-chars-forward "^,\"" (point-max))
+      (when (eq (setq char (following-char)) ?\")
+       (setq quoted (not quoted)))
+      (unless (= (point) end)
+       (forward-char 1)))
+    (skip-chars-forward " \t\n")))
+
 (defun message-fill-address (header value)
-  (save-restriction
-    (narrow-to-region (point) (point))
-    (insert (capitalize (symbol-name header))
-           ": "
-           (if (consp value) (car value) value)
-           "\n")
-    (narrow-to-region (point-min) (1- (point-max)))
-    (let (quoted last)
-      (goto-char (point-min))
-      (while (not (eobp))
-       (skip-chars-forward "^,\"" (point-max))
-       (if (or (eq (char-after) ?,)
-               (eobp))
-           (when (not quoted)
-             (if (and (> (current-column) 78)
-                      last)
-                 (progn
-                   (save-excursion
-                     (goto-char last)
-                     (insert "\n\t"))
-                   (setq last (1+ (point))))
-               (setq last (1+ (point)))))
-         (setq quoted (not quoted)))
-       (unless (eobp)
-         (forward-char 1))))
-    (goto-char (point-max))
-    (widen)
-    (forward-line 1)))
+  (insert (capitalize (symbol-name header))
+         ": "
+         (if (consp value) (car value) value)
+         "\n")
+  (message-fill-field-address))
 
 (defun message-split-line ()
   "Split current line, moving portion beyond point vertically down.
@@ -5155,27 +5132,57 @@ If the current line has `message-yank-prefix', insert it on the new line."
       (split-line message-yank-prefix) ;; Emacs 21.3.50+ supports arg.
     (error
      (split-line))))
-     
-(defun message-fill-header (header value)
+
+(defun message-insert-header (header value)
+  (insert (capitalize (symbol-name header))
+         ": "
+         (if (consp value) (car value) value)))
+
+(defun message-field-name ()
+  (save-excursion
+    (goto-char (point-min))
+    (when (looking-at "\\([^:]+\\):")
+      (intern (capitalize (match-string 1))))))
+
+(defun message-fill-field ()
+  (save-excursion
+    (save-restriction
+      (message-narrow-to-field)
+      (let ((field-name (message-field-name)))
+       (funcall (or (cadr (assq field-name message-field-fillers))
+                    'message-fill-field-general)))
+      (point-max))))
+
+(defun message-fill-field-address ()
+  (while (not (eobp))
+    (message-skip-to-next-address)
+    (let (last)
+      (if (and (> (current-column) 78)
+              last)
+         (progn
+           (save-excursion
+             (goto-char last)
+             (insert "\n\t"))
+           (setq last (1+ (point))))
+       (setq last (1+ (point)))))))
+  
+(defun message-fill-field-general ()
   (let ((begin (point))
        (fill-column 78)
        (fill-prefix "\t"))
-    (insert (capitalize (symbol-name header))
-           ": "
-           (if (consp value) (car value) value)
-           "\n")
-    (save-restriction
-      (narrow-to-region begin (point))
-      (fill-region-as-paragraph begin (point))
-      ;; Tapdance around looong Message-IDs.
-      (forward-line -1)
-      (when (looking-at "[ \t]*$")
-       (message-delete-line))
-      (goto-char begin)
-      (re-search-forward ":" nil t)
-      (when (looking-at "\n[ \t]+")
-       (replace-match " " t t))
-      (goto-char (point-max)))))
+    (while (and (search-forward "\n" nil t)
+               (not (eobp)))
+      (replace-match " " t t))
+    (fill-region-as-paragraph begin (point-max))
+    ;; Tapdance around looong Message-IDs.
+    (forward-line -1)
+    (when (looking-at "[ \t]*$")
+      (message-delete-line))
+    (goto-char begin)
+    (re-search-forward ":" nil t)
+    (when (looking-at "\n[ \t]+")
+      (replace-match " " t t))
+    (goto-char (point-max))))
 
 (defun message-shorten-1 (list cut surplus)
   "Cut SURPLUS elements out of LIST, beginning with CUTth one."
@@ -5184,8 +5191,9 @@ If the current line has `message-yank-prefix', insert it on the new line."
 
 (defun message-shorten-references (header references)
   "Trim REFERENCES to be 21 Message-ID long or less, and fold them.
-If folding is disallowed, also check that the REFERENCES are less
-than 988 characters long, and if they are not, trim them until they are."
+When sending via news, also check that the REFERENCES are less
+than 988 characters long, and if they are not, trim them until
+they are."
   (let ((maxcount 21)
        (count 0)
        (cut 2)
@@ -5207,33 +5215,26 @@ than 988 characters long, and if they are not, trim them until they are."
        (message-shorten-1 refs cut surplus)
        (decf count surplus)))
 
-    ;; If folding is disallowed, make sure the total length (including
-    ;; the spaces between) will be less than MAXSIZE characters.
+    ;; When sending via news, make sure the total folded length will
+    ;; be less than 998 characters.  This is to cater to broken INN
+    ;; 2.3 which counts the total number of characters in a header
+    ;; rather than the physical line length of each line, as it shuld.
     ;;
-    ;; Only disallow folding for News messages. At this point the headers
-    ;; have not been generated, thus we use message-this-is-news directly.
-    (when (and message-this-is-news message-cater-to-broken-inn)
-      (let ((maxsize 988)
-           (totalsize (+ (apply #'+ (mapcar #'length refs))
-                         (1- count)))
-           (surplus 0)
-           (ptr (nthcdr (1- cut) refs)))
-       ;; Decide how many elements to cut off...
-       (while (> totalsize maxsize)
-         (decf totalsize (1+ (length (car ptr))))
-         (incf surplus)
-         (setq ptr (cdr ptr)))
-       ;; ...and do it.
-       (when (> surplus 0)
-         (message-shorten-1 refs cut surplus))))
-
+    ;; This hack should be removed when it's believed than INN 2.3 is
+    ;; no longer widely used.
+    ;;
+    ;; At this point the headers have not been generated, thus we use
+    ;; message-this-is-news directly.
+    (when message-this-is-news
+      (while (< 998
+               (with-temp-buffer
+                 (message-insert-header
+                  header (mapconcat #'identity refs " "))
+                 (buffer-size)))
+       (message-shorten-1 refs cut 1)))
     ;; Finally, collect the references back into a string and insert
     ;; it into the buffer.
-    (let ((refstring (mapconcat #'identity refs " ")))
-      (if (and message-this-is-news message-cater-to-broken-inn)
-         (insert (capitalize (symbol-name header)) ": "
-                 refstring "\n")
-       (message-fill-header header refstring)))))
+    (message-insert-header header (mapconcat #'identity refs " "))))
 
 (defun message-position-point ()
   "Move point to where the user probably wants to find it."
@@ -5461,12 +5462,7 @@ are not included."
   (when message-default-headers
     (insert message-default-headers)
     (or (bolp) (insert ?\n)))
-  (put-text-property
-   (point)
-   (progn
-     (insert mail-header-separator "\n")
-     (1- (point)))
-   'read-only nil)
+  (insert mail-header-separator "\n")
   (forward-line -1)
   (when (message-news-p)
     (when message-default-news-headers
@@ -6342,7 +6338,8 @@ Optional DIGEST will use digest to forward."
        (replace-match "X-From-Line: "))
       ;; Send it.
       (let ((message-inhibit-body-encoding t)
-           message-required-mail-headers)
+           message-required-mail-headers
+           rfc2047-encode-encoded-words)
        (message-send-mail))
       (kill-buffer (current-buffer)))
     (message "Resending message to %s...done" address)))
@@ -6855,4 +6852,5 @@ regexp VARSTR."
 ;; coding: iso-8859-1
 ;; End:
 
+;;; arch-tag: 94b32cac-4504-4b6c-8181-030ebf380ee0
 ;;; message.el ends here