*** empty log message ***
[gnus] / lisp / message.el
index a399e16..0e69aac 100644 (file)
@@ -47,6 +47,9 @@
 (defvar message-max-buffers 10
   "*How many buffers to keep before starting to kill them off.")
 
+(defvar message-send-rename-function nil
+  "Function called to rename the buffer after sending it.")
+
 ;;;###autoload
 (defvar message-fcc-handler-function 'rmail-output
   "*A function called to save outgoing articles.
@@ -139,14 +142,16 @@ nil means let mailer mail back a message to report errors.")
 
 ;;;###autoload
 (defvar message-generate-new-buffers t
-  "*Non-nil means that a new message buffer will be created whenever `mail-setup' is called.")
+  "*Non-nil means that a new message buffer will be created whenever `mail-setup' is called.
+If this is a function, call that function with three parameters:  The type,
+the to address and the group name.  (Any of these may be nil.)  The function
+should return the new buffer name.")
 
 ;;;###autoload
 (defvar message-kill-buffer-on-exit nil
   "*Non-nil means that the message buffer will be killed after sending a message.")
 
 (defvar gnus-local-organization)
-;;;###autoload
 (defvar message-user-organization 
   (or (and (boundp 'gnus-local-organization)
           gnus-local-organization)
@@ -510,17 +515,24 @@ The cdr of ech entry is a function for applying the face to a region.")
 (defun message-tokenize-header (header &optional separator)
   "Split HEADER into a list of header elements.
 \",\" is used as the separator."
-  (let* ((beg 0)
-        (separator (or separator ","))
-        (regexp
-         (format "[ \t]*\\([^%s]+\\)?\\([%s]+\\|\\'\\)" separator separator))
-        elems)
-    (while (and (string-match regexp header beg)
-               (< beg (length header)))
-      (when (match-beginning 1)
-       (push (match-string 1 header) elems))
-      (setq beg (match-end 0)))
-    (nreverse elems)))
+  (let ((regexp (format "[%s]+" (or separator ",")))
+       (beg 1)
+       quoted elems)
+    (save-excursion
+      (message-set-work-buffer)
+      (insert header)
+      (goto-char (point-min))
+      (while (not (eobp))
+       (forward-char 1)
+       (cond ((and (> (point) beg)
+                   (or (eobp)
+                       (and (looking-at regexp)
+                            (not quoted))))
+              (push (buffer-substring beg (point)) elems)
+              (setq beg (match-end 0)))
+             ((= (following-char) ?\")
+              (setq quoted (not quoted)))))
+      (nreverse elems))))
 
 (defun message-fetch-field (header)
   "The same as `mail-fetch-field', only remove all newlines."
@@ -797,9 +809,11 @@ C-c C-r  message-ceasar-buffer-body (rot13 the message body)."
   (make-local-variable 'paragraph-start)
   (setq paragraph-start (concat (regexp-quote mail-header-separator)
                                "$\\|[ \t]*[-_][-_][-_]+$\\|"
+                               "-- $\\|"
                                paragraph-start))
   (setq paragraph-separate (concat (regexp-quote mail-header-separator)
                                   "$\\|[ \t]*[-_][-_][-_]+$\\|"
+                                  "-- $\\|"
                                   paragraph-separate))
   (make-local-variable 'message-reply-headers)
   (setq message-reply-headers nil)
@@ -903,7 +917,9 @@ C-c C-r  message-ceasar-buffer-body (rot13 the message body)."
 (defun message-insert-to ()
   "Insert a To header that points to the author of the article being replied to."
   (interactive)
-  (when (message-position-on-field "To")
+  (when (and (message-position-on-field "To")
+            (mail-fetch-field "to")
+            (not (string-match "\\` *\\'" (mail-fetch-field "to"))))
     (insert ", "))
   (insert (or (message-fetch-reply-field "reply-to")
              (message-fetch-reply-field "from") "")))
@@ -911,7 +927,9 @@ C-c C-r  message-ceasar-buffer-body (rot13 the message body)."
 (defun message-insert-newsgroups ()
   "Insert the Newsgroups header from the article being replied to."
   (interactive)
-  (when (message-position-on-field "Newsgroups")
+  (when (and (message-position-on-field "Newsgroups")
+            (mail-fetch-field "newsgroups")
+            (not (string-match "\\` *\\'" (mail-fetch-field "newsgroups"))))
     (insert ","))
   (insert (or (message-fetch-reply-field "newsgroups") "")))
 
@@ -921,9 +939,15 @@ C-c C-r  message-ceasar-buffer-body (rot13 the message body)."
 
 (defun message-insert-signature (&optional force)
   "Insert a signature.  See documentation for the `message-signature' variable."
-  (interactive (list t))
+  (interactive (list 0))
   (let* ((signature 
          (cond ((and (null message-signature)
+                     (eq force 0))
+                (save-excursion
+                  (goto-char (point-max))
+                  (not (re-search-backward
+                        message-signature-separator nil t))))
+               ((and (null message-signature)
                      force)
                 t)
                ((message-functionp message-signature)
@@ -939,13 +963,14 @@ C-c C-r  message-ceasar-buffer-body (rot13 the message body)."
                      (file-exists-p message-signature-file))
                 signature))))
     (when signature
-      ;; Remove blank lines at the end of the message.
+;      ;; Remove blank lines at the end of the message.
       (goto-char (point-max))
-      (skip-chars-backward " \t\n")
-      (end-of-line)
-      (delete-region (point) (point-max))
+;      (skip-chars-backward " \t\n")
+;      (delete-region (point) (point-max))
       ;; Insert the signature.
-      (insert "\n\n-- \n")
+      (unless (bolp)
+       (insert "\n"))
+      (insert "\n-- \n")
       (if (eq signature t)
          (insert-file-contents message-signature-file)
        (insert signature))
@@ -1079,11 +1104,11 @@ prefix, and don't delete any headers."
       (delete-windows-on message-reply-buffer t)
       (insert-buffer message-reply-buffer)
       (funcall message-cite-function)
-      (exchange-point-and-mark)
+      (message-exchange-point-and-mark)
       (unless (bolp)
        (insert ?\n))
       (unless modified
-       (setq message-checksum (message-checksum))))))
+       (setq message-checksum (cons (message-checksum) (buffer-size)))))))
 
 (defun message-cite-original ()    
   (let ((start (point))
@@ -1214,6 +1239,8 @@ the user from the mailer."
              (y-or-n-p "No changes in the buffer; really send? ")))
     ;; Make it possible to undo the coming changes.
     (undo-boundary)
+    (let ((inhibit-read-only t))
+      (put-text-property (point-min) (point-max) 'read-only nil))
     (message-fix-before-sending)
     (run-hooks 'message-send-hook)
     (message "Sending...")
@@ -1393,6 +1420,7 @@ the user from the mailer."
       (message-generate-headers message-required-news-headers)
       ;; Let the user do all of the above.
       (run-hooks 'message-header-hook))
+    (message-cleanup-headers)
     (when (message-check-news-syntax)
       (unwind-protect
          (save-excursion
@@ -1495,7 +1523,14 @@ the user from the mailer."
                (goto-char (point-min))
                (insert "Followup-To: " to "\n"))
              t))
-
+       ;; Check "Shoot me".
+       (or (message-check-element 'shoot)
+           (save-excursion
+             (if (search-forward
+                  ".i-have-a-misconfigured-system-so-shoot-me" nil t)
+                 (y-or-n-p
+                  "You appear to have a misconfigured system.  Really post? ")
+               t)))
        ;; Check for Approved.
        (or (message-check-element 'approved)
            (save-excursion
@@ -1584,7 +1619,6 @@ the user from the mailer."
                      (car headers) header)))))
        ;; Check the From header.
        (or 
-        (message-check-element 'from)
         (save-excursion
           (let* ((case-fold-search t)
                  (from (message-fetch-field "from")))
@@ -1651,7 +1685,8 @@ the user from the mailer."
    ;; Check whether any new text has been added.
    (or (message-check-element 'new-text)
        (not message-checksum)
-       (not (eq (message-checksum) message-checksum))
+       (not (and (eq (message-checksum) (car message-checksum))
+                (eq (buffer-size) (cdr message-checksum))))
        (y-or-n-p
        "It looks like no new text has been added.  Really post? "))
    ;; Check the length of the signature.
@@ -1685,7 +1720,8 @@ the user from the mailer."
       (re-search-forward
        (concat "^" (regexp-quote mail-header-separator) "$"))
       (while (not (eobp))
-       (setq sum (logxor sum (following-char)))
+       (when (not (looking-at "[ \t\n]"))
+         (setq sum (logxor (ash sum 1) (following-char))))
        (forward-char 1)))
     sum))
 
@@ -1713,7 +1749,8 @@ the user from the mailer."
        (if (string-match "^[ \t]*|[ \t]*\\(.*\\)[ \t]*$" file)
            ;; Pipe the article to the program in question.
            (call-process-region (point-min) (point-max) shell-file-name
-                                nil nil nil "-c" (match-string 1 file))
+                                nil nil nil shell-command-switch
+                                (match-string 1 file))
          ;; Save the article.
          (setq file (expand-file-name file))
          (unless (file-exists-p (file-name-directory file))
@@ -1778,7 +1815,7 @@ the user from the mailer."
                            (mail-header-subject message-reply-headers))
                           (message-strip-subject-re psubject))))
                "_-_" ""))
-         "@" (message-make-fqdm) ">"))
+         "@" (message-make-fqdn) ">"))
 
 (defvar message-unique-id-char nil)
 
@@ -1966,34 +2003,37 @@ give as trustworthy answer as possible."
   (when user-mail-address
     (nth 1 (mail-extract-address-components user-mail-address))))
 
-(defun message-make-fqdm ()
+(defun message-make-fqdn ()
   "Return user's fully qualified domain name."
-  (let ((system-name (system-name)))
+  (let ((system-name (system-name))
+       (user-mail (message-user-mail-address)))
     (cond 
      ((string-match "[^.]\\.[^.]" system-name)
       ;; `system-name' returned the right result.
       system-name)
-     ;; We try `user-mail-address' as a backup.
-     ((string-match "@\\(.*\\)\\'" (message-user-mail-address))
-      (match-string 1 user-mail-address))
      ;; Try `mail-host-address'.
      ((and (boundp 'mail-host-address)
-          mail-host-address)
+          (stringp mail-host-address)
+          (string-match "\\." mail-host-address))
       mail-host-address)
+     ;; We try `user-mail-address' as a backup.
+     ((and (string-match "\\." user-mail)
+          (string-match "@\\(.*\\)\\'" user-mail))
+      (match-string 1 user-mail))
      ;; Default to this bogus thing.
      (t
       (concat system-name ".i-have-a-misconfigured-system-so-shoot-me")))))
 
 (defun message-make-host-name ()
   "Return the name of the host."
-  (let ((fqdm (message-make-fqdm)))
-    (string-match "^[^.]+\\." fqdm)
-    (substring fqdm 0 (1- (match-end 0)))))
+  (let ((fqdn (message-make-fqdn)))
+    (string-match "^[^.]+\\." fqdn)
+    (substring fqdn 0 (1- (match-end 0)))))
 
 (defun message-make-domain ()
   "Return the domain name."
   (or mail-host-address
-      (message-make-fqdm)))
+      (message-make-fqdn)))
 
 (defun message-generate-headers (headers)
   "Prepare article HEADERS.
@@ -2205,17 +2245,25 @@ Headers already prepared in the buffer are not modified."
 
 (defun message-buffer-name (type &optional to group)
   "Return a new (unique) buffer name based on TYPE and TO."
-  (if message-generate-new-buffers
-      (generate-new-buffer-name
-       (concat "*" type
-              (if to
-                  (concat " to "
-                          (or (car (mail-extract-address-components to))
-                              to) "")
-                "")
-              (if group (concat " on " group) "")
-              "*"))
-    (format "*%s message*" type)))
+  (cond
+   ;; Check whether `message-generate-new-buffers' is a function, 
+   ;; and if so, call it.
+   ((message-functionp message-generate-new-buffers)
+    (funcall message-generate-new-buffers type to group))
+   ;; Generate a new buffer name The Message Way.
+   (message-generate-new-buffers
+    (generate-new-buffer-name
+     (concat "*" type
+            (if to
+                (concat " to "
+                        (or (car (mail-extract-address-components to))
+                            to) "")
+              "")
+            (if (and group (not (string= group ""))) (concat " on " group) "")
+            "*")))
+   ;; Use standard name.
+   (t
+    (format "*%s message*" type))))
 
 (defun message-pop-to-buffer (name)
   "Pop to buffer NAME, and warn if it already exists and is modified."
@@ -2245,14 +2293,17 @@ Headers already prepared in the buffer are not modified."
                 (not (buffer-modified-p buffer)))
        (kill-buffer buffer))))
   ;; Rename the buffer.
-  (when (string-match "\\`\\*" (buffer-name))
-    (rename-buffer 
-     (concat "*sent " (substring (buffer-name) (match-end 0))) t))
+  (if message-send-rename-function
+      (funcall message-send-rename-function)
+    (when (string-match "\\`\\*" (buffer-name))
+      (rename-buffer 
+       (concat "*sent " (substring (buffer-name) (match-end 0))) t)))
   ;; Push the current buffer onto the list.
   (when message-max-buffers
     (setq message-buffer-list 
          (nconc message-buffer-list (list (current-buffer))))))
 
+(defvar mc-modes-alist)
 (defun message-setup (headers &optional replybuffer actions)
   (when (and (boundp 'mc-modes-alist)
             (not (assq 'message-mode mc-modes-alist)))
@@ -2273,14 +2324,14 @@ Headers already prepared in the buffer are not modified."
        (pop h))
      alist)
    headers)
-  (forward-line -1)
+  (delete-region (point) (progn (forward-line -1) (point)))
   (when message-default-headers
     (insert message-default-headers))
   (put-text-property
    (point)
    (progn
      (insert mail-header-separator "\n")
-     (point))
+     (1- (point)))
    'read-only nil)
   (forward-line -1)
   (when (message-news-p)
@@ -2753,7 +2804,7 @@ you."
     ;; We remove everything before the bounced mail.
     (delete-region 
      (point-min)
-     (if (re-search-forward "[^ \t]*:" nil t)
+     (if (re-search-forward "^[^ \n\t]+:" nil t)
         (match-beginning 0)
        (point)))
     (save-restriction
@@ -2851,6 +2902,8 @@ which specify the range to operate on."
        (if (eq (following-char) (char-after (- (point) 2)))
           (delete-char -2))))))
 
+(fset 'message-exchange-point-and-mark 'exchange-point-and-mark)
+
 ;; Support for toolbar
 (when (string-match "XEmacs\\|Lucid" emacs-version)
   (require 'messagexmas))