comparison lisp/gnus/message.el @ 16:0293115a14e9 r19-15b91

Import from CVS: tag r19-15b91
author cvs
date Mon, 13 Aug 2007 08:49:20 +0200
parents ac2d302a0011
children d95e72db5c07
comparison
equal deleted inserted replaced
15:ad457d5f7d04 16:0293115a14e9
1 ;;; message.el --- composing mail and news messages 1 ;;; message.el --- composing mail and news messages
2 ;; Copyright (C) 1996 Free Software Foundation, Inc. 2 ;; Copyright (C) 1996,97 Free Software Foundation, Inc.
3 3
4 ;; Author: Lars Magne Ingebrigtsen <larsi@ifi.uio.no> 4 ;; Author: Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
5 ;; Keywords: mail, news 5 ;; Keywords: mail, news
6 6
7 ;; This file is part of GNU Emacs. 7 ;; This file is part of GNU Emacs.
34 (require 'mailheader) 34 (require 'mailheader)
35 (require 'rmail) 35 (require 'rmail)
36 (require 'nnheader) 36 (require 'nnheader)
37 (require 'timezone) 37 (require 'timezone)
38 (require 'easymenu) 38 (require 'easymenu)
39 (require 'custom)
39 (if (string-match "XEmacs\\|Lucid" emacs-version) 40 (if (string-match "XEmacs\\|Lucid" emacs-version)
40 (require 'mail-abbrevs) 41 (require 'mail-abbrevs)
41 (require 'mailabbrev)) 42 (require 'mailabbrev))
42 43
43 (defvar message-directory "~/Mail/" 44 (defgroup message '((user-mail-address custom-variable)
44 "*Directory from which all other mail file variables are derived.") 45 (user-full-name custom-variable))
45 46 "Mail and news message composing."
46 (defvar message-max-buffers 10 47 :link '(custom-manual "(message)Top")
47 "*How many buffers to keep before starting to kill them off.") 48 :group 'emacs)
48 49
49 (defvar message-send-rename-function nil 50 (put 'user-mail-address 'custom-type 'string)
50 "Function called to rename the buffer after sending it.") 51 (put 'user-full-name 'custom-type 'string)
52
53 (defgroup message-various nil
54 "Various Message Variables"
55 :link '(custom-manual "(message)Various Message Variables")
56 :group 'message)
57
58 (defgroup message-buffers nil
59 "Message Buffers"
60 :link '(custom-manual "(message)Message Buffers")
61 :group 'message)
62
63 (defgroup message-sending nil
64 "Message Sending"
65 :link '(custom-manual "(message)Sending Variables")
66 :group 'message)
67
68 (defgroup message-interface nil
69 "Message Interface"
70 :link '(custom-manual "(message)Interface")
71 :group 'message)
72
73 (defgroup message-forwarding nil
74 "Message Forwarding"
75 :link '(custom-manual "(message)Forwarding")
76 :group 'message-interface)
77
78 (defgroup message-insertion nil
79 "Message Insertion"
80 :link '(custom-manual "(message)Insertion")
81 :group 'message)
82
83 (defgroup message-headers nil
84 "Message Headers"
85 :link '(custom-manual "(message)Message Headers")
86 :group 'message)
87
88 (defgroup message-news nil
89 "Composing News Messages"
90 :group 'message)
91
92 (defgroup message-mail nil
93 "Composing Mail Messages"
94 :group 'message)
95
96 (defcustom message-directory "~/Mail/"
97 "*Directory from which all other mail file variables are derived."
98 :group 'message-various
99 :type 'directory)
100
101 (defcustom message-max-buffers 10
102 "*How many buffers to keep before starting to kill them off."
103 :group 'message-buffers
104 :type 'integer)
105
106 (defcustom message-send-rename-function nil
107 "Function called to rename the buffer after sending it."
108 :group 'message-buffers
109 :type 'function)
51 110
52 ;;;###autoload 111 ;;;###autoload
53 (defvar message-fcc-handler-function 'rmail-output 112 (defcustom message-fcc-handler-function 'message-output
54 "*A function called to save outgoing articles. 113 "*A function called to save outgoing articles.
55 This function will be called with the name of the file to store the 114 This function will be called with the name of the file to store the
56 article in. The default function is `rmail-output' which saves in Unix 115 article in. The default function is `rmail-output' which saves in Unix
57 mailbox format.") 116 mailbox format."
117 :type '(radio (function-item rmail-output)
118 (function :tag "Other"))
119 :group 'message-sending)
120
121 (defcustom message-courtesy-message
122 "The following message is a courtesy copy of an article\nthat has been posted to %s as well.\n\n"
123 "*This is inserted at the start of a mailed copy of a posted message.
124 If the string contains the format spec \"%s\", the Newsgroups
125 the article has been posted to will be inserted there.
126 If this variable is nil, no such courtesy message will be added."
127 :group 'message-sending
128 :type 'string)
129
130 (defcustom message-ignored-bounced-headers "^\\(Received\\|Return-Path\\):"
131 "*Regexp that matches headers to be removed in resent bounced mail."
132 :group 'message-interface
133 :type 'regexp)
58 134
59 ;;;###autoload 135 ;;;###autoload
60 (defvar message-courtesy-message 136 (defcustom message-from-style 'default
61 "The following message is a courtesy copy of an article\nthat has been posted as well.\n\n"
62 "*This is inserted at the start of a mailed copy of a posted message.
63 If this variable is nil, no such courtesy message will be added.")
64
65 ;;;###autoload
66 (defvar message-ignored-bounced-headers "^\\(Received\\|Return-Path\\):"
67 "*Regexp that matches headers to be removed in resent bounced mail.")
68
69 ;;;###autoload
70 (defvar message-from-style 'default
71 "*Specifies how \"From\" headers look. 137 "*Specifies how \"From\" headers look.
72 138
73 If `nil', they contain just the return address like: 139 If `nil', they contain just the return address like:
74 king@grassland.com 140 king@grassland.com
75 If `parens', they look like: 141 If `parens', they look like:
76 king@grassland.com (Elvis Parsley) 142 king@grassland.com (Elvis Parsley)
77 If `angles', they look like: 143 If `angles', they look like:
78 Elvis Parsley <king@grassland.com> 144 Elvis Parsley <king@grassland.com>
79 145
80 Otherwise, most addresses look like `angles', but they look like 146 Otherwise, most addresses look like `angles', but they look like
81 `parens' if `angles' would need quoting and `parens' would not.") 147 `parens' if `angles' would need quoting and `parens' would not."
82 148 :type '(choice (const :tag "simple" nil)
83 ;;;###autoload 149 (const parens)
84 (defvar message-syntax-checks nil 150 (const angles)
151 (const default))
152 :group 'message-headers)
153
154 (defcustom message-syntax-checks nil
155 ;; Guess this one shouldn't be easy to customize...
85 "Controls what syntax checks should not be performed on outgoing posts. 156 "Controls what syntax checks should not be performed on outgoing posts.
86 To disable checking of long signatures, for instance, add 157 To disable checking of long signatures, for instance, add
87 `(signature . disabled)' to this list. 158 `(signature . disabled)' to this list.
88 159
89 Don't touch this variable unless you really know what you're doing. 160 Don't touch this variable unless you really know what you're doing.
90 161
91 Checks include subject-cmsg multiple-headers sendsys message-id from 162 Checks include subject-cmsg multiple-headers sendsys message-id from
92 long-lines control-chars size new-text redirected-followup signature 163 long-lines control-chars size new-text redirected-followup signature
93 approved sender empty empty-headers message-id from subject.") 164 approved sender empty empty-headers message-id from subject
94 165 shorten-followup-to existing-newsgroups."
95 ;;;###autoload 166 :group 'message-news)
96 (defvar message-required-news-headers 167
168 (defcustom message-required-news-headers
97 '(From Newsgroups Subject Date Message-ID 169 '(From Newsgroups Subject Date Message-ID
98 (optional . Organization) Lines 170 (optional . Organization) Lines
99 (optional . X-Newsreader)) 171 (optional . X-Newsreader))
100 "*Headers to be generated or prompted for when posting an article. 172 "Headers to be generated or prompted for when posting an article.
101 RFC977 and RFC1036 require From, Date, Newsgroups, Subject, 173 RFC977 and RFC1036 require From, Date, Newsgroups, Subject,
102 Message-ID. Organization, Lines, In-Reply-To, Expires, and 174 Message-ID. Organization, Lines, In-Reply-To, Expires, and
103 X-Newsreader are optional. If don't you want message to insert some 175 X-Newsreader are optional. If don't you want message to insert some
104 header, remove it from this list.") 176 header, remove it from this list."
105 177 :group 'message-news
106 ;;;###autoload 178 :group 'message-headers
107 (defvar message-required-mail-headers 179 :type '(repeat sexp))
180
181 (defcustom message-required-mail-headers
108 '(From Subject Date (optional . In-Reply-To) Message-ID Lines 182 '(From Subject Date (optional . In-Reply-To) Message-ID Lines
109 (optional . X-Mailer)) 183 (optional . X-Mailer))
110 "*Headers to be generated or prompted for when mailing a message. 184 "Headers to be generated or prompted for when mailing a message.
111 RFC822 required that From, Date, To, Subject and Message-ID be 185 RFC822 required that From, Date, To, Subject and Message-ID be
112 included. Organization, Lines and X-Mailer are optional.") 186 included. Organization, Lines and X-Mailer are optional."
113 187 :group 'message-mail
114 ;;;###autoload 188 :group 'message-headers
115 (defvar message-deletable-headers '(Message-ID Date) 189 :type '(repeat sexp))
116 "*Headers to be deleted if they already exist and were generated by message previously.") 190
117 191 (defcustom message-deletable-headers '(Message-ID Date Lines)
118 ;;;###autoload 192 "Headers to be deleted if they already exist and were generated by message previously."
119 (defvar message-ignored-news-headers 193 :group 'message-headers
120 "^NNTP-Posting-Host:\\|^Xref:\\|^Bcc:\\|^Gcc:\\|^Fcc:" 194 :type 'sexp)
121 "*Regexp of headers to be removed unconditionally before posting.") 195
122 196 (defcustom message-ignored-news-headers
123 ;;;###autoload 197 "^NNTP-Posting-Host:\\|^Xref:\\|^Bcc:\\|^Gcc:\\|^Fcc:\\|^Resent-Fcc:"
124 (defvar message-ignored-mail-headers "^Gcc:\\|^Fcc:" 198 "*Regexp of headers to be removed unconditionally before posting."
125 "*Regexp of headers to be removed unconditionally before mailing.") 199 :group 'message-news
126 200 :group 'message-headers
127 ;;;###autoload 201 :type 'regexp)
128 (defvar message-ignored-supersedes-headers "^Path:\\|^Date\\|^NNTP-Posting-Host:\\|^Xref:\\|^Lines:\\|^Received:\\|^X-From-Line:\\|Return-Path:\\|^Supersedes:" 202
203 (defcustom message-ignored-mail-headers "^Gcc:\\|^Fcc:\\|^Resent-Fcc:"
204 "*Regexp of headers to be removed unconditionally before mailing."
205 :group 'message-mail
206 :group 'message-headers
207 :type 'regexp)
208
209 (defcustom message-ignored-supersedes-headers "^Path:\\|^Date\\|^NNTP-Posting-Host:\\|^Xref:\\|^Lines:\\|^Received:\\|^X-From-Line:\\|Return-Path:\\|^Supersedes:"
129 "*Header lines matching this regexp will be deleted before posting. 210 "*Header lines matching this regexp will be deleted before posting.
130 It's best to delete old Path and Date headers before posting to avoid 211 It's best to delete old Path and Date headers before posting to avoid
131 any confusion.") 212 any confusion."
213 :group 'message-interface
214 :type 'regexp)
132 215
133 ;;;###autoload 216 ;;;###autoload
134 (defvar message-signature-separator "^-- *$" 217 (defcustom message-signature-separator "^-- *$"
135 "Regexp matching the signature separator.") 218 "Regexp matching the signature separator."
136 219 :type 'regexp
137 ;;;###autoload 220 :group 'message-various)
138 (defvar message-interactive nil 221
222 (defcustom message-elide-elipsis "\n[...]\n\n"
223 "*The string which is inserted for elided text.")
224
225 (defcustom message-interactive nil
139 "Non-nil means when sending a message wait for and display errors. 226 "Non-nil means when sending a message wait for and display errors.
140 nil means let mailer mail back a message to report errors.") 227 nil means let mailer mail back a message to report errors."
141 228 :group 'message-sending
142 ;;;###autoload 229 :group 'message-mail
143 (defvar message-generate-new-buffers t 230 :type 'boolean)
231
232 (defcustom message-generate-new-buffers t
144 "*Non-nil means that a new message buffer will be created whenever `mail-setup' is called. 233 "*Non-nil means that a new message buffer will be created whenever `mail-setup' is called.
145 If this is a function, call that function with three parameters: The type, 234 If this is a function, call that function with three parameters: The type,
146 the to address and the group name. (Any of these may be nil.) The function 235 the to address and the group name. (Any of these may be nil.) The function
147 should return the new buffer name.") 236 should return the new buffer name."
148 237 :group 'message-buffers
149 ;;;###autoload 238 :type '(choice (const :tag "off" nil)
150 (defvar message-kill-buffer-on-exit nil 239 (const :tag "on" t)
151 "*Non-nil means that the message buffer will be killed after sending a message.") 240 (function fun)))
241
242 (defcustom message-kill-buffer-on-exit nil
243 "*Non-nil means that the message buffer will be killed after sending a message."
244 :group 'message-buffers
245 :type 'boolean)
152 246
153 (defvar gnus-local-organization) 247 (defvar gnus-local-organization)
154 (defvar message-user-organization 248 (defcustom message-user-organization
155 (or (and (boundp 'gnus-local-organization) 249 (or (and (boundp 'gnus-local-organization)
156 gnus-local-organization) 250 gnus-local-organization)
157 (getenv "ORGANIZATION") 251 (getenv "ORGANIZATION")
158 t) 252 t)
159 "*String to be used as an Organization header. 253 "*String to be used as an Organization header.
160 If t, use `message-user-organization-file'.") 254 If t, use `message-user-organization-file'."
255 :group 'message-headers
256 :type '(choice string
257 (const :tag "consult file" t)))
161 258
162 ;;;###autoload 259 ;;;###autoload
163 (defvar message-user-organization-file "/usr/lib/news/organization" 260 (defcustom message-user-organization-file "/usr/lib/news/organization"
164 "*Local news organization file.") 261 "*Local news organization file."
165 262 :type 'file
166 (defvar message-autosave-directory "~/" 263 :group 'message-headers)
264
265 (defcustom message-autosave-directory "~/"
167 ; (concat (file-name-as-directory message-directory) "drafts/") 266 ; (concat (file-name-as-directory message-directory) "drafts/")
168 "*Directory where message autosaves buffers. 267 "*Directory where message autosaves buffers.
169 If nil, message won't autosave.") 268 If nil, message won't autosave."
170 269 :group 'message-buffers
171 (defvar message-forward-start-separator 270 :type 'directory)
271
272 (defcustom message-forward-start-separator
172 "------- Start of forwarded message -------\n" 273 "------- Start of forwarded message -------\n"
173 "*Delimiter inserted before forwarded messages.") 274 "*Delimiter inserted before forwarded messages."
174 275 :group 'message-forwarding
175 (defvar message-forward-end-separator 276 :type 'string)
277
278 (defcustom message-forward-end-separator
176 "------- End of forwarded message -------\n" 279 "------- End of forwarded message -------\n"
177 "*Delimiter inserted after forwarded messages.") 280 "*Delimiter inserted after forwarded messages."
178 281 :group 'message-forwarding
179 ;;;###autoload 282 :type 'string)
180 (defvar message-signature-before-forwarded-message t 283
181 "*If non-nil, put the signature before any included forwarded message.") 284 (defcustom message-signature-before-forwarded-message t
182 285 "*If non-nil, put the signature before any included forwarded message."
183 ;;;###autoload 286 :group 'message-forwarding
184 (defvar message-included-forward-headers 287 :type 'boolean)
288
289 (defcustom message-included-forward-headers
185 "^From:\\|^Newsgroups:\\|^Subject:\\|^Date:\\|^Followup-To:\\|^Reply-To:\\|^Organization:\\|^Summary:\\|^Keywords:\\|^To:\\|^Cc:\\|^Posted-To:\\|^Mail-Copies-To:\\|^Apparently-To:\\|^Gnus-Warning:\\|^Resent-\\|^Message-ID:\\|^References:" 290 "^From:\\|^Newsgroups:\\|^Subject:\\|^Date:\\|^Followup-To:\\|^Reply-To:\\|^Organization:\\|^Summary:\\|^Keywords:\\|^To:\\|^Cc:\\|^Posted-To:\\|^Mail-Copies-To:\\|^Apparently-To:\\|^Gnus-Warning:\\|^Resent-\\|^Message-ID:\\|^References:"
186 "*Regexp matching headers to be included in forwarded messages.") 291 "*Regexp matching headers to be included in forwarded messages."
187 292 :group 'message-forwarding
188 ;;;###autoload 293 :type 'regexp)
189 (defvar message-ignored-resent-headers "^Return-receipt" 294
190 "*All headers that match this regexp will be deleted when resending a message.") 295 (defcustom message-ignored-resent-headers "^Return-receipt"
191 296 "*All headers that match this regexp will be deleted when resending a message."
192 ;;;###autoload 297 :group 'message-interface
193 (defvar message-ignored-cited-headers "." 298 :type 'regexp)
194 "Delete these headers from the messages you yank.") 299
300 (defcustom message-ignored-cited-headers "."
301 "*Delete these headers from the messages you yank."
302 :group 'message-insertion
303 :type 'regexp)
304
305 (defcustom message-cancel-message "I am canceling my own article."
306 "Message to be inserted in the cancel message."
307 :group 'message-interface
308 :type 'string)
195 309
196 ;; Useful to set in site-init.el 310 ;; Useful to set in site-init.el
197 ;;;###autoload 311 ;;;###autoload
198 (defvar message-send-mail-function 'message-send-mail-with-sendmail 312 (defcustom message-send-mail-function 'message-send-mail-with-sendmail
199 "Function to call to send the current buffer as mail. 313 "Function to call to send the current buffer as mail.
200 The headers should be delimited by a line whose contents match the 314 The headers should be delimited by a line whose contents match the
201 variable `mail-header-separator'. 315 variable `mail-header-separator'.
202 316
203 Legal values include `message-send-mail-with-mh' and 317 Legal values include `message-send-mail-with-sendmail' (the default),
204 `message-send-mail-with-sendmail', which is the default.") 318 `message-send-mail-with-mh' and `message-send-mail-with-qmail'."
205 319 :type '(radio (function-item message-send-mail-with-sendmail)
206 ;;;###autoload 320 (function-item message-send-mail-with-mh)
207 (defvar message-send-news-function 'message-send-news 321 (function-item message-send-mail-with-qmail)
322 (function :tag "Other"))
323 :group 'message-sending
324 :group 'message-mail)
325
326 (defcustom message-send-news-function 'message-send-news
208 "Function to call to send the current buffer as news. 327 "Function to call to send the current buffer as news.
209 The headers should be delimited by a line whose contents match the 328 The headers should be delimited by a line whose contents match the
210 variable `mail-header-separator'.") 329 variable `mail-header-separator'."
211 330 :group 'message-sending
212 ;;;###autoload 331 :group 'message-news
213 (defvar message-reply-to-function nil 332 :type 'function)
333
334 (defcustom message-reply-to-function nil
214 "Function that should return a list of headers. 335 "Function that should return a list of headers.
215 This function should pick out addresses from the To, Cc, and From headers 336 This function should pick out addresses from the To, Cc, and From headers
216 and respond with new To and Cc headers.") 337 and respond with new To and Cc headers."
217 338 :group 'message-interface
218 ;;;###autoload 339 :type 'function)
219 (defvar message-wide-reply-to-function nil 340
341 (defcustom message-wide-reply-to-function nil
220 "Function that should return a list of headers. 342 "Function that should return a list of headers.
221 This function should pick out addresses from the To, Cc, and From headers 343 This function should pick out addresses from the To, Cc, and From headers
222 and respond with new To and Cc headers.") 344 and respond with new To and Cc headers."
223 345 :group 'message-interface
224 ;;;###autoload 346 :type 'function)
225 (defvar message-followup-to-function nil 347
348 (defcustom message-followup-to-function nil
226 "Function that should return a list of headers. 349 "Function that should return a list of headers.
227 This function should pick out addresses from the To, Cc, and From headers 350 This function should pick out addresses from the To, Cc, and From headers
228 and respond with new To and Cc headers.") 351 and respond with new To and Cc headers."
229 352 :group 'message-interface
230 ;;;###autoload 353 :type 'function)
231 (defvar message-use-followup-to 'ask 354
355 (defcustom message-use-followup-to 'ask
232 "*Specifies what to do with Followup-To header. 356 "*Specifies what to do with Followup-To header.
233 If nil, ignore the header. If it is t, use its value, but query before 357 If nil, always ignore the header. If it is t, use its value, but
234 using the \"poster\" value. If it is the symbol `ask', query the user 358 query before using the \"poster\" value. If it is the symbol `ask',
235 whether to ignore the \"poster\" value. If it is the symbol `use', 359 always query the user whether to use the value. If it is the symbol
236 always use the value.") 360 `use', always use the value."
361 :group 'message-interface
362 :type '(choice (const :tag "ignore" nil)
363 (const use)
364 (const ask)))
365
366 ;; stuff relating to broken sendmail in MMDF
367 (defcustom message-sendmail-f-is-evil nil
368 "*Non-nil means that \"-f username\" should not be added to the sendmail
369 command line, because it is even more evil than leaving it out."
370 :group 'message-sending
371 :type 'boolean)
372
373 ;; qmail-related stuff
374 (defcustom message-qmail-inject-program "/var/qmail/bin/qmail-inject"
375 "Location of the qmail-inject program."
376 :group 'message-sending
377 :type 'file)
378
379 (defcustom message-qmail-inject-args nil
380 "Arguments passed to qmail-inject programs.
381 This should be a list of strings, one string for each argument.
382
383 For e.g., if you wish to set the envelope sender address so that bounces
384 go to the right place or to deal with listserv's usage of that address, you
385 might set this variable to '(\"-f\" \"you@some.where\")."
386 :group 'message-sending
387 :type '(repeat string))
237 388
238 (defvar gnus-post-method) 389 (defvar gnus-post-method)
239 (defvar gnus-select-method) 390 (defvar gnus-select-method)
240 ;;;###autoload 391 (defcustom message-post-method
241 (defvar message-post-method
242 (cond ((and (boundp 'gnus-post-method) 392 (cond ((and (boundp 'gnus-post-method)
243 gnus-post-method) 393 gnus-post-method)
244 gnus-post-method) 394 gnus-post-method)
245 ((boundp 'gnus-select-method) 395 ((boundp 'gnus-select-method)
246 gnus-select-method) 396 gnus-select-method)
247 (t '(nnspool ""))) 397 (t '(nnspool "")))
248 "Method used to post news.") 398 "Method used to post news."
249 399 :group 'message-news
250 ;;;###autoload 400 :group 'mesage-sending
251 (defvar message-generate-headers-first nil 401 ;; This should be the `gnus-select-method' widget, but that might
252 "*If non-nil, generate all possible headers before composing.") 402 ;; create a dependence to `gnus.el'.
253 403 :type 'sexp)
254 (defvar message-setup-hook nil 404
405 (defcustom message-generate-headers-first nil
406 "*If non-nil, generate all possible headers before composing."
407 :group 'message-headers
408 :type 'boolean)
409
410 (defcustom message-setup-hook nil
255 "Normal hook, run each time a new outgoing message is initialized. 411 "Normal hook, run each time a new outgoing message is initialized.
256 The function `message-setup' runs this hook.") 412 The function `message-setup' runs this hook."
257 413 :group 'message-various
258 (defvar message-signature-setup-hook nil 414 :type 'hook)
415
416 (defcustom message-signature-setup-hook nil
259 "Normal hook, run each time a new outgoing message is initialized. 417 "Normal hook, run each time a new outgoing message is initialized.
260 It is run after the headers have been inserted and before 418 It is run after the headers have been inserted and before
261 the signature is inserted.") 419 the signature is inserted."
262 420 :group 'message-various
263 (defvar message-mode-hook nil 421 :type 'hook)
264 "Hook run in message mode buffers.") 422
265 423 (defcustom message-mode-hook nil
266 (defvar message-header-hook nil 424 "Hook run in message mode buffers."
267 "Hook run in a message mode buffer narrowed to the headers.") 425 :group 'message-various
268 426 :type 'hook)
269 (defvar message-header-setup-hook nil 427
270 "Hook called narrowed to the headers when setting up a message buffer.") 428 (defcustom message-header-hook nil
429 "Hook run in a message mode buffer narrowed to the headers."
430 :group 'message-various
431 :type 'hook)
432
433 (defcustom message-header-setup-hook nil
434 "Hook called narrowed to the headers when setting up a message
435 buffer."
436 :group 'message-various
437 :type 'hook)
271 438
272 ;;;###autoload 439 ;;;###autoload
273 (defvar message-citation-line-function 'message-insert-citation-line 440 (defcustom message-citation-line-function 'message-insert-citation-line
274 "*Function called to insert the \"Whomever writes:\" line.") 441 "*Function called to insert the \"Whomever writes:\" line."
442 :type 'function
443 :group 'message-insertion)
275 444
276 ;;;###autoload 445 ;;;###autoload
277 (defvar message-yank-prefix "> " 446 (defcustom message-yank-prefix "> "
278 "*Prefix inserted on the lines of yanked messages. 447 "*Prefix inserted on the lines of yanked messages.
279 nil means use indentation.") 448 nil means use indentation."
280 449 :type 'string
281 (defvar message-indentation-spaces 3 450 :group 'message-insertion)
451
452 (defcustom message-indentation-spaces 3
282 "*Number of spaces to insert at the beginning of each cited line. 453 "*Number of spaces to insert at the beginning of each cited line.
283 Used by `message-yank-original' via `message-yank-cite'.") 454 Used by `message-yank-original' via `message-yank-cite'."
455 :group 'message-insertion
456 :type 'integer)
284 457
285 ;;;###autoload 458 ;;;###autoload
286 (defvar message-cite-function 'message-cite-original 459 (defcustom message-cite-function
287 "*Function for citing an original message.") 460 (if (and (boundp 'mail-citation-hook)
461 mail-citation-hook)
462 mail-citation-hook
463 'message-cite-original)
464 "*Function for citing an original message."
465 :type '(radio (function-item message-cite-original)
466 (function-item sc-cite-original)
467 (function :tag "Other"))
468 :group 'message-insertion)
288 469
289 ;;;###autoload 470 ;;;###autoload
290 (defvar message-indent-citation-function 'message-indent-citation 471 (defcustom message-indent-citation-function 'message-indent-citation
291 "*Function for modifying a citation just inserted in the mail buffer. 472 "*Function for modifying a citation just inserted in the mail buffer.
292 This can also be a list of functions. Each function can find the 473 This can also be a list of functions. Each function can find the
293 citation between (point) and (mark t). And each function should leave 474 citation between (point) and (mark t). And each function should leave
294 point and mark around the citation text as modified.") 475 point and mark around the citation text as modified."
476 :type 'function
477 :group 'message-insertion)
295 478
296 (defvar message-abbrevs-loaded nil) 479 (defvar message-abbrevs-loaded nil)
297 480
298 ;;;###autoload 481 ;;;###autoload
299 (defvar message-signature t 482 (defcustom message-signature t
300 "*String to be inserted at the end of the message buffer. 483 "*String to be inserted at the end of the message buffer.
301 If t, the `message-signature-file' file will be inserted instead. 484 If t, the `message-signature-file' file will be inserted instead.
302 If a function, the result from the function will be used instead. 485 If a function, the result from the function will be used instead.
303 If a form, the result from the form will be used instead.") 486 If a form, the result from the form will be used instead."
487 :type 'sexp
488 :group 'message-insertion)
304 489
305 ;;;###autoload 490 ;;;###autoload
306 (defvar message-signature-file "~/.signature" 491 (defcustom message-signature-file "~/.signature"
307 "*File containing the text inserted at end of message. buffer.") 492 "*File containing the text inserted at end of message buffer."
308 493 :type 'file
309 (defvar message-distribution-function nil 494 :group 'message-insertion)
310 "*Function called to return a Distribution header.") 495
311 496 (defcustom message-distribution-function nil
312 (defvar message-expires 14 497 "*Function called to return a Distribution header."
313 "*Number of days before your article expires.") 498 :group 'message-news
314 499 :group 'message-headers
315 (defvar message-user-path nil 500 :type 'function)
501
502 (defcustom message-expires 14
503 "Number of days before your article expires."
504 :group 'message-news
505 :group 'message-headers
506 :link '(custom-manual "(message)News Headers")
507 :type 'integer)
508
509 (defcustom message-user-path nil
316 "If nil, use the NNTP server name in the Path header. 510 "If nil, use the NNTP server name in the Path header.
317 If stringp, use this; if non-nil, use no host name (user name only).") 511 If stringp, use this; if non-nil, use no host name (user name only)."
512 :group 'message-news
513 :group 'message-headers
514 :link '(custom-manual "(message)News Headers")
515 :type '(choice (const :tag "nntp" nil)
516 (string :tag "name")
517 (sexp :tag "none" :format "%t" t)))
318 518
319 (defvar message-reply-buffer nil) 519 (defvar message-reply-buffer nil)
320 (defvar message-reply-headers nil) 520 (defvar message-reply-headers nil)
321 (defvar message-newsreader nil) 521 (defvar message-newsreader nil)
322 (defvar message-mailer nil) 522 (defvar message-mailer nil)
329 (defvar message-kill-actions nil 529 (defvar message-kill-actions nil
330 "A list of actions to be performed before killing a message buffer.") 530 "A list of actions to be performed before killing a message buffer.")
331 (defvar message-postpone-actions nil 531 (defvar message-postpone-actions nil
332 "A list of actions to be performed after postponing a message.") 532 "A list of actions to be performed after postponing a message.")
333 533
334 ;;;###autoload 534 (defcustom message-default-headers ""
335 (defvar message-default-headers nil
336 "*A string containing header lines to be inserted in outgoing messages. 535 "*A string containing header lines to be inserted in outgoing messages.
337 It is inserted before you edit the message, so you can edit or delete 536 It is inserted before you edit the message, so you can edit or delete
338 these lines.") 537 these lines."
339 538 :group 'message-headers
340 ;;;###autoload 539 :type 'string)
341 (defvar message-default-mail-headers nil 540
342 "*A string of header lines to be inserted in outgoing mails.") 541 (defcustom message-default-mail-headers ""
343 542 "*A string of header lines to be inserted in outgoing mails."
344 ;;;###autoload 543 :group 'message-headers
345 (defvar message-default-news-headers nil 544 :group 'message-mail
346 "*A string of header lines to be inserted in outgoing news articles.") 545 :type 'string)
546
547 (defcustom message-default-news-headers ""
548 "*A string of header lines to be inserted in outgoing news
549 articles."
550 :group 'message-headers
551 :group 'message-news
552 :type 'string)
347 553
348 ;; Note: could use /usr/ucb/mail instead of sendmail; 554 ;; Note: could use /usr/ucb/mail instead of sendmail;
349 ;; options -t, and -v if not interactive. 555 ;; options -t, and -v if not interactive.
350 (defvar message-mailer-swallows-blank-line 556 (defcustom message-mailer-swallows-blank-line
351 (if (and (string-match "sparc-sun-sunos\\(\\'\\|[^5]\\)" 557 (if (and (string-match "sparc-sun-sunos\\(\\'\\|[^5]\\)"
352 system-configuration) 558 system-configuration)
353 (file-readable-p "/etc/sendmail.cf") 559 (file-readable-p "/etc/sendmail.cf")
354 (let ((buffer (get-buffer-create " *temp*"))) 560 (let ((buffer (get-buffer-create " *temp*")))
355 (unwind-protect 561 (unwind-protect
359 (goto-char (point-min)) 565 (goto-char (point-min))
360 (let ((case-fold-search nil)) 566 (let ((case-fold-search nil))
361 (re-search-forward "^OR\\>" nil t))) 567 (re-search-forward "^OR\\>" nil t)))
362 (kill-buffer buffer)))) 568 (kill-buffer buffer))))
363 ;; According to RFC822, "The field-name must be composed of printable 569 ;; According to RFC822, "The field-name must be composed of printable
364 ;; ASCII characters (i.e. characters that have decimal values between 570 ;; ASCII characters (i. e., characters that have decimal values between
365 ;; 33 and 126, except colon)", i.e. any chars except ctl chars, 571 ;; 33 and 126, except colon)", i. e., any chars except ctl chars,
366 ;; space, or colon. 572 ;; space, or colon.
367 '(looking-at "[ \t]\\|[][!\"#$%&'()*+,-./0-9;<=>?@A-Z\\\\^_`a-z{|}~]+:")) 573 '(looking-at "[ \t]\\|[][!\"#$%&'()*+,-./0-9;<=>?@A-Z\\\\^_`a-z{|}~]+:"))
368 "Set this non-nil if the system's mailer runs the header and body together. 574 "Set this non-nil if the system's mailer runs the header and body together.
369 \(This problem exists on Sunos 4 when sendmail is run in remote mode.) 575 \(This problem exists on Sunos 4 when sendmail is run in remote mode.)
370 The value should be an expression to test whether the problem will 576 The value should be an expression to test whether the problem will
371 actually occur.") 577 actually occur."
578 :group 'message-sending
579 :type 'sexp)
580
581 (ignore-errors
582 (define-mail-user-agent 'message-user-agent
583 'message-mail 'message-send-and-exit
584 'message-kill-buffer 'message-send-hook))
585
586 (defvar message-delete-mh-headers t
587 "If non-nil, delete the deletable headers before feeding to mh.")
588
589 ;;; Internal variables.
590 ;;; Well, not really internal.
372 591
373 (defvar message-mode-syntax-table 592 (defvar message-mode-syntax-table
374 (let ((table (copy-syntax-table text-mode-syntax-table))) 593 (let ((table (copy-syntax-table text-mode-syntax-table)))
375 (modify-syntax-entry ?% ". " table) 594 (modify-syntax-entry ?% ". " table)
376 table) 595 table)
390 1 'font-lock-comment-face) 609 1 'font-lock-comment-face)
391 (cons (concat "^[ \t]*" 610 (cons (concat "^[ \t]*"
392 "\\([" cite-prefix "]+[" cite-suffix "]*\\)?" 611 "\\([" cite-prefix "]+[" cite-suffix "]*\\)?"
393 "[>|}].*") 612 "[>|}].*")
394 'font-lock-reference-face) 613 'font-lock-reference-face)
395 '("^\\(X-[A-Za-z0-9-]+\\|In-reply-to\\):.*" 614 '("^\\(X-[A-Za-z0-9-]+\\|In-Reply-To\\):.*"
396 . font-lock-string-face))) 615 . font-lock-string-face)))
397 "Additional expressions to highlight in Message mode.") 616 "Additional expressions to highlight in Message mode.")
398 617
399 (defvar message-face-alist 618 (defvar message-face-alist
400 '((bold . bold-region) 619 '((bold . bold-region)
403 (unbold-region b e) 622 (unbold-region b e)
404 (ununderline-region b e)))) 623 (ununderline-region b e))))
405 "Alist of mail and news faces for facemenu. 624 "Alist of mail and news faces for facemenu.
406 The cdr of ech entry is a function for applying the face to a region.") 625 The cdr of ech entry is a function for applying the face to a region.")
407 626
408 (defvar message-send-hook nil 627 (defcustom message-send-hook nil
409 "Hook run before sending messages.") 628 "Hook run before sending messages."
410 629 :group 'message-various
411 (defvar message-sent-hook nil 630 :options '(ispell-message)
412 "Hook run after sending messages.") 631 :type 'hook)
632
633 (defcustom message-send-mail-hook nil
634 "Hook run before sending mail messages."
635 :group 'message-various
636 :type 'hook)
637
638 (defcustom message-send-news-hook nil
639 "Hook run before sending news messages."
640 :group 'message-various
641 :type 'hook)
642
643 (defcustom message-sent-hook nil
644 "Hook run after sending messages."
645 :group 'message-various
646 :type 'hook)
413 647
414 ;;; Internal variables. 648 ;;; Internal variables.
415 649
416 (defvar message-buffer-list nil) 650 (defvar message-buffer-list nil)
651 (defvar message-this-is-news nil)
652 (defvar message-this-is-mail nil)
653
654 ;; Byte-compiler warning
655 (defvar gnus-active-hashtb)
656 (defvar gnus-read-active-file)
417 657
418 ;;; Regexp matching the delimiter of messages in UNIX mail format 658 ;;; Regexp matching the delimiter of messages in UNIX mail format
419 ;;; (UNIX From lines), minus the initial ^. 659 ;;; (UNIX From lines), minus the initial ^.
420 (defvar message-unix-mail-delimiter 660 (defvar message-unix-mail-delimiter
421 (let ((time-zone-regexp 661 (let ((time-zone-regexp
476 (Organization) 716 (Organization)
477 (Distribution) 717 (Distribution)
478 (Lines) 718 (Lines)
479 (Expires) 719 (Expires)
480 (Message-ID) 720 (Message-ID)
481 (References . message-fill-header) 721 (References)
482 (X-Mailer) 722 (X-Mailer)
483 (X-Newsreader)) 723 (X-Newsreader))
484 "Alist used for formatting headers.") 724 "Alist used for formatting headers.")
485 725
486 (eval-and-compile 726 (eval-and-compile
487 (autoload 'message-setup-toolbar "messagexmas") 727 (autoload 'message-setup-toolbar "messagexmas")
488 (autoload 'mh-send-letter "mh-comp")) 728 (autoload 'mh-send-letter "mh-comp")
729 (autoload 'gnus-output-to-mail "gnus-util")
730 (autoload 'gnus-output-to-rmail "gnus-util"))
489 731
490 732
491 733
492 ;;; 734 ;;;
493 ;;; Utility functions. 735 ;;; Utility functions.
507 (end-of-line) 749 (end-of-line)
508 (prog1 750 (prog1
509 (point) 751 (point)
510 (goto-char p)))) 752 (goto-char p))))
511 753
754 (defmacro message-y-or-n-p (question show &rest text)
755 "Ask QUESTION, displaying the rest of the arguments in a temp. buffer if SHOW"
756 `(message-talkative-question 'y-or-n-p ,question ,show ,@text))
757
512 ;; Delete the current line (and the next N lines.); 758 ;; Delete the current line (and the next N lines.);
513 (defmacro message-delete-line (&optional n) 759 (defmacro message-delete-line (&optional n)
514 `(delete-region (progn (beginning-of-line) (point)) 760 `(delete-region (progn (beginning-of-line) (point))
515 (progn (forward-line ,(or n 1)) (point)))) 761 (progn (forward-line ,(or n 1)) (point))))
516 762
517 (defun message-tokenize-header (header &optional separator) 763 (defun message-tokenize-header (header &optional separator)
518 "Split HEADER into a list of header elements. 764 "Split HEADER into a list of header elements.
519 \",\" is used as the separator." 765 \",\" is used as the separator."
520 (let ((regexp (format "[%s]+" (or separator ","))) 766 (if (not header)
521 (beg 1) 767 nil
522 (first t) 768 (let ((regexp (format "[%s]+" (or separator ",")))
523 quoted elems) 769 (beg 1)
524 (save-excursion 770 (first t)
525 (message-set-work-buffer) 771 quoted elems paren)
526 (insert header) 772 (save-excursion
527 (goto-char (point-min)) 773 (message-set-work-buffer)
528 (while (not (eobp)) 774 (insert header)
529 (if first 775 (goto-char (point-min))
530 (setq first nil) 776 (while (not (eobp))
531 (forward-char 1)) 777 (if first
532 (cond ((and (> (point) beg) 778 (setq first nil)
533 (or (eobp) 779 (forward-char 1))
534 (and (looking-at regexp) 780 (cond ((and (> (point) beg)
535 (not quoted)))) 781 (or (eobp)
536 (push (buffer-substring beg (point)) elems) 782 (and (looking-at regexp)
537 (setq beg (match-end 0))) 783 (not quoted)
538 ((= (following-char) ?\") 784 (not paren))))
539 (setq quoted (not quoted))))) 785 (push (buffer-substring beg (point)) elems)
540 (nreverse elems)))) 786 (setq beg (match-end 0)))
787 ((= (following-char) ?\")
788 (setq quoted (not quoted)))
789 ((and (= (following-char) ?\()
790 (not quoted))
791 (setq paren t))
792 ((and (= (following-char) ?\))
793 (not quoted))
794 (setq paren nil))))
795 (nreverse elems)))))
541 796
542 (defun message-fetch-field (header) 797 (defun message-fetch-field (header)
543 "The same as `mail-fetch-field', only remove all newlines." 798 "The same as `mail-fetch-field', only remove all newlines."
544 (let ((value (mail-fetch-field header))) 799 (let ((value (mail-fetch-field header nil t)))
545 (when value 800 (when value
546 (nnheader-replace-chars-in-string value ?\n ? )))) 801 (nnheader-replace-chars-in-string value ?\n ? ))))
547 802
548 (defun message-fetch-reply-field (header) 803 (defun message-fetch-reply-field (header)
549 "Fetch FIELD from the message we're replying to." 804 "Fetch FIELD from the message we're replying to."
628 (point-max))) 883 (point-max)))
629 (goto-char (point-min))) 884 (goto-char (point-min)))
630 885
631 (defun message-news-p () 886 (defun message-news-p ()
632 "Say whether the current buffer contains a news message." 887 "Say whether the current buffer contains a news message."
633 (save-excursion 888 (or message-this-is-news
634 (save-restriction 889 (save-excursion
635 (message-narrow-to-headers) 890 (save-restriction
636 (message-fetch-field "newsgroups")))) 891 (message-narrow-to-headers)
892 (message-fetch-field "newsgroups")))))
637 893
638 (defun message-mail-p () 894 (defun message-mail-p ()
639 "Say whether the current buffer contains a mail message." 895 "Say whether the current buffer contains a mail message."
640 (save-excursion 896 (or message-this-is-mail
641 (save-restriction 897 (save-excursion
642 (message-narrow-to-headers) 898 (save-restriction
643 (or (message-fetch-field "to") 899 (message-narrow-to-headers)
644 (message-fetch-field "cc") 900 (or (message-fetch-field "to")
645 (message-fetch-field "bcc"))))) 901 (message-fetch-field "cc")
902 (message-fetch-field "bcc"))))))
646 903
647 (defun message-next-header () 904 (defun message-next-header ()
648 "Go to the beginning of the next header." 905 "Go to the beginning of the next header."
649 (beginning-of-line) 906 (beginning-of-line)
650 (or (eobp) (forward-char 1)) 907 (or (eobp) (forward-char 1))
661 (message-next-header) 918 (message-next-header)
662 (unless (bobp) 919 (unless (bobp)
663 (forward-char -1))) 920 (forward-char -1)))
664 (lambda () 921 (lambda ()
665 (or (get-text-property (point) 'message-rank) 922 (or (get-text-property (point) 'message-rank)
666 0)))) 923 10000))))
667 924
668 (defun message-sort-headers () 925 (defun message-sort-headers ()
669 "Sort the headers of the current message according to `message-header-format-alist'." 926 "Sort the headers of the current message according to `message-header-format-alist'."
670 (interactive) 927 (interactive)
671 (save-excursion 928 (save-excursion
727 (define-key message-mode-map "\C-c\C-c" 'message-send-and-exit) 984 (define-key message-mode-map "\C-c\C-c" 'message-send-and-exit)
728 (define-key message-mode-map "\C-c\C-s" 'message-send) 985 (define-key message-mode-map "\C-c\C-s" 'message-send)
729 (define-key message-mode-map "\C-c\C-k" 'message-kill-buffer) 986 (define-key message-mode-map "\C-c\C-k" 'message-kill-buffer)
730 (define-key message-mode-map "\C-c\C-d" 'message-dont-send) 987 (define-key message-mode-map "\C-c\C-d" 'message-dont-send)
731 988
989 (define-key message-mode-map "\C-c\C-e" 'message-elide-region)
990
732 (define-key message-mode-map "\t" 'message-tab)) 991 (define-key message-mode-map "\t" 'message-tab))
733 992
734 (easy-menu-define message-mode-menu message-mode-map 993 (easy-menu-define
735 "Message Menu." 994 message-mode-menu message-mode-map "Message Menu."
736 '("Message" 995 '("Message"
737 "Go to Field:" 996 ["Sort Headers" message-sort-headers t]
738 "----" 997 ["Yank Original" message-yank-original t]
739 ["To" message-goto-to t] 998 ["Fill Yanked Message" message-fill-yanked-message t]
740 ["Subject" message-goto-subject t] 999 ["Insert Signature" message-insert-signature t]
741 ["Cc" message-goto-cc t] 1000 ["Caesar (rot13) Message" message-caesar-buffer-body t]
742 ["Reply-to" message-goto-reply-to t] 1001 ["Caesar (rot13) Region" message-caesar-region (mark t)]
743 ["Summary" message-goto-summary t] 1002 ["Elide Region" message-elide-region (mark t)]
744 ["Keywords" message-goto-keywords t] 1003 ["Rename buffer" message-rename-buffer t]
745 ["Newsgroups" message-goto-newsgroups t] 1004 ["Spellcheck" ispell-message t]
746 ["Followup-To" message-goto-followup-to t] 1005 "----"
747 ["Distribution" message-goto-distribution t] 1006 ["Send Message" message-send-and-exit t]
748 ["Body" message-goto-body t] 1007 ["Abort Message" message-dont-send t]))
749 ["Signature" message-goto-signature t] 1008
750 "----" 1009 (easy-menu-define
751 "Miscellaneous Commands:" 1010 message-mode-field-menu message-mode-map ""
752 "----" 1011 '("Field"
753 ["Sort Headers" message-sort-headers t] 1012 ["Fetch To" message-insert-to t]
754 ["Yank Original" message-yank-original t] 1013 ["Fetch Newsgroups" message-insert-newsgroups t]
755 ["Fill Yanked Message" message-fill-yanked-message t] 1014 "----"
756 ["Insert Signature" message-insert-signature t] 1015 ["To" message-goto-to t]
757 ["Caesar (rot13) Message" message-caesar-buffer-body t] 1016 ["Subject" message-goto-subject t]
758 ["Rename buffer" message-rename-buffer t] 1017 ["Cc" message-goto-cc t]
759 ["Spellcheck" ispell-message t] 1018 ["Reply-To" message-goto-reply-to t]
760 "----" 1019 ["Summary" message-goto-summary t]
761 ["Send Message" message-send-and-exit t] 1020 ["Keywords" message-goto-keywords t]
762 ["Abort Message" message-dont-send t])) 1021 ["Newsgroups" message-goto-newsgroups t]
1022 ["Followup-To" message-goto-followup-to t]
1023 ["Distribution" message-goto-distribution t]
1024 ["Body" message-goto-body t]
1025 ["Signature" message-goto-signature t]))
763 1026
764 (defvar facemenu-add-face-function) 1027 (defvar facemenu-add-face-function)
765 (defvar facemenu-remove-face-function) 1028 (defvar facemenu-remove-face-function)
766 1029
767 ;;;###autoload 1030 ;;;###autoload
770 Like Text Mode but with these additional commands: 1033 Like Text Mode but with these additional commands:
771 C-c C-s message-send (send the message) C-c C-c message-send-and-exit 1034 C-c C-s message-send (send the message) C-c C-c message-send-and-exit
772 C-c C-f move to a header field (and create it if there isn't): 1035 C-c C-f move to a header field (and create it if there isn't):
773 C-c C-f C-t move to To C-c C-f C-s move to Subject 1036 C-c C-f C-t move to To C-c C-f C-s move to Subject
774 C-c C-f C-c move to Cc C-c C-f C-b move to Bcc 1037 C-c C-f C-c move to Cc C-c C-f C-b move to Bcc
775 C-c C-f C-f move to Fcc C-c C-f C-r move to Reply-To 1038 C-c C-f C-w move to Fcc C-c C-f C-r move to Reply-To
776 C-c C-f C-u move to Summary C-c C-f C-n move to Newsgroups 1039 C-c C-f C-u move to Summary C-c C-f C-n move to Newsgroups
777 C-c C-f C-k move to Keywords C-c C-f C-d move to Distribution 1040 C-c C-f C-k move to Keywords C-c C-f C-d move to Distribution
778 C-c C-f C-o move to Followup-To 1041 C-c C-f C-f move to Followup-To
779 C-c C-t message-insert-to (add a To header to a news followup) 1042 C-c C-t message-insert-to (add a To header to a news followup)
780 C-c C-n message-insert-newsgroups (add a Newsgroup header to a news reply) 1043 C-c C-n message-insert-newsgroups (add a Newsgroup header to a news reply)
781 C-c C-b message-goto-body (move to beginning of message text). 1044 C-c C-b message-goto-body (move to beginning of message text).
782 C-c C-i message-goto-signature (move to the beginning of the signature). 1045 C-c C-i message-goto-signature (move to the beginning of the signature).
783 C-c C-w message-insert-signature (insert `message-signature-file' file). 1046 C-c C-w message-insert-signature (insert `message-signature-file' file).
784 C-c C-y message-yank-original (insert current message, if any). 1047 C-c C-y message-yank-original (insert current message, if any).
785 C-c C-q message-fill-yanked-message (fill what was yanked). 1048 C-c C-q message-fill-yanked-message (fill what was yanked).
786 C-c C-r message-ceasar-buffer-body (rot13 the message body)." 1049 C-c C-e message-elide-region (elide the text between point and mark).
1050 C-c C-r message-caesar-buffer-body (rot13 the message body)."
787 (interactive) 1051 (interactive)
788 (kill-all-local-variables) 1052 (kill-all-local-variables)
789 (make-local-variable 'message-reply-buffer) 1053 (make-local-variable 'message-reply-buffer)
790 (setq message-reply-buffer nil) 1054 (setq message-reply-buffer nil)
791 (make-local-variable 'message-send-actions) 1055 (make-local-variable 'message-send-actions)
912 1176
913 (defun message-goto-signature () 1177 (defun message-goto-signature ()
914 "Move point to the beginning of the message signature." 1178 "Move point to the beginning of the message signature."
915 (interactive) 1179 (interactive)
916 (goto-char (point-min)) 1180 (goto-char (point-min))
917 (or (re-search-forward message-signature-separator nil t) 1181 (if (re-search-forward message-signature-separator nil t)
918 (goto-char (point-max)))) 1182 (forward-line 1)
1183 (goto-char (point-max))))
919 1184
920 1185
921 1186
922 (defun message-insert-to () 1187 (defun message-insert-to ()
923 "Insert a To header that points to the author of the article being replied to." 1188 "Insert a To header that points to the author of the article being replied to."
924 (interactive) 1189 (interactive)
1190 (let ((co (message-fetch-field "courtesy-copies-to")))
1191 (when (and co
1192 (equal (downcase co) "never"))
1193 (error "The user has requested not to have copies sent via mail")))
925 (when (and (message-position-on-field "To") 1194 (when (and (message-position-on-field "To")
926 (mail-fetch-field "to") 1195 (mail-fetch-field "to")
927 (not (string-match "\\` *\\'" (mail-fetch-field "to")))) 1196 (not (string-match "\\` *\\'" (mail-fetch-field "to"))))
928 (insert ", ")) 1197 (insert ", "))
929 (insert (or (message-fetch-reply-field "reply-to") 1198 (insert (or (message-fetch-reply-field "reply-to")
944 1213
945 (defun message-insert-signature (&optional force) 1214 (defun message-insert-signature (&optional force)
946 "Insert a signature. See documentation for the `message-signature' variable." 1215 "Insert a signature. See documentation for the `message-signature' variable."
947 (interactive (list 0)) 1216 (interactive (list 0))
948 (let* ((signature 1217 (let* ((signature
949 (cond ((and (null message-signature) 1218 (cond
950 (eq force 0)) 1219 ((and (null message-signature)
951 (save-excursion 1220 (eq force 0))
952 (goto-char (point-max)) 1221 (save-excursion
953 (not (re-search-backward 1222 (goto-char (point-max))
954 message-signature-separator nil t)))) 1223 (not (re-search-backward
955 ((and (null message-signature) 1224 message-signature-separator nil t))))
956 force) 1225 ((and (null message-signature)
957 t) 1226 force)
958 ((message-functionp message-signature) 1227 t)
959 (funcall message-signature)) 1228 ((message-functionp message-signature)
960 ((listp message-signature) 1229 (funcall message-signature))
961 (eval message-signature)) 1230 ((listp message-signature)
962 (t message-signature))) 1231 (eval message-signature))
1232 (t message-signature)))
963 (signature 1233 (signature
964 (cond ((stringp signature) 1234 (cond ((stringp signature)
965 signature) 1235 signature)
966 ((and (eq t signature) 1236 ((and (eq t signature)
967 message-signature-file 1237 message-signature-file
968 (file-exists-p message-signature-file)) 1238 (file-exists-p message-signature-file))
969 signature)))) 1239 signature))))
970 (when signature 1240 (when signature
1241 (goto-char (point-max))
971 ;; Insert the signature. 1242 ;; Insert the signature.
972 (goto-char (point-max))
973 (unless (bolp) 1243 (unless (bolp)
974 (insert "\n")) 1244 (insert "\n"))
975 (insert "\n-- \n") 1245 (insert "\n-- \n")
976 (if (eq signature t) 1246 (if (eq signature t)
977 (insert-file-contents message-signature-file) 1247 (insert-file-contents message-signature-file)
978 (insert signature)) 1248 (insert signature))
979 (goto-char (point-max)) 1249 (goto-char (point-max))
980 (or (bolp) (insert "\n"))))) 1250 (or (bolp) (insert "\n")))))
1251
1252 (defun message-elide-region (b e)
1253 "Elide the text between point and mark. An ellipsis (from
1254 message-elide-elipsis) will be inserted where the text was killed."
1255 (interactive "r")
1256 (kill-region b e)
1257 (unless (bolp)
1258 (insert "\n"))
1259 (insert message-elide-elipsis))
981 1260
982 (defvar message-caesar-translation-table nil) 1261 (defvar message-caesar-translation-table nil)
983 1262
984 (defun message-caesar-region (b e &optional n) 1263 (defun message-caesar-region (b e &optional n)
985 "Caesar rotation of region by N, default 13, for decrypting netnews." 1264 "Caesar rotation of region by N, default 13, for decrypting netnews."
1030 (save-restriction 1309 (save-restriction
1031 (when (message-goto-body) 1310 (when (message-goto-body)
1032 (narrow-to-region (point) (point-max))) 1311 (narrow-to-region (point) (point-max)))
1033 (message-caesar-region (point-min) (point-max) rotnum)))) 1312 (message-caesar-region (point-min) (point-max) rotnum))))
1034 1313
1314 (defun message-pipe-buffer-body (program)
1315 "Pipe the message body in the current buffer through PROGRAM."
1316 (save-excursion
1317 (save-restriction
1318 (when (message-goto-body)
1319 (narrow-to-region (point) (point-max)))
1320 (let ((body (buffer-substring (point-min) (point-max))))
1321 (unless (equal 0 (call-process-region
1322 (point-min) (point-max) program t t))
1323 (insert body)
1324 (gnus-message 1 "%s failed." program))))))
1325
1035 (defun message-rename-buffer (&optional enter-string) 1326 (defun message-rename-buffer (&optional enter-string)
1036 "Rename the *message* buffer to \"*message* RECIPIENT\". 1327 "Rename the *message* buffer to \"*message* RECIPIENT\".
1037 If the function is run with a prefix, it will ask for a new buffer 1328 If the function is run with a prefix, it will ask for a new buffer
1038 name, rather than giving an automatic name." 1329 name, rather than giving an automatic name."
1039 (interactive "Pbuffer name: ") 1330 (interactive "Pbuffer name: ")
1040 (save-excursion 1331 (save-excursion
1041 (save-restriction 1332 (save-restriction
1042 (goto-char (point-min)) 1333 (goto-char (point-min))
1043 (narrow-to-region (point) 1334 (narrow-to-region (point)
1044 (search-forward mail-header-separator nil 'end)) 1335 (search-forward mail-header-separator nil 'end))
1045 (let* ((mail-to (if (message-news-p) (message-fetch-field "Newsgroups") 1336 (let* ((mail-to (or
1046 (message-fetch-field "To"))) 1337 (if (message-news-p) (message-fetch-field "Newsgroups")
1338 (message-fetch-field "To"))
1339 ""))
1047 (mail-trimmed-to 1340 (mail-trimmed-to
1048 (if (string-match "," mail-to) 1341 (if (string-match "," mail-to)
1049 (concat (substring mail-to 0 (match-beginning 0)) ", ...") 1342 (concat (substring mail-to 0 (match-beginning 0)) ", ...")
1050 mail-to)) 1343 mail-to))
1051 (name-default (concat "*message* " mail-trimmed-to)) 1344 (name-default (concat "*message* " mail-trimmed-to))
1052 (name (if enter-string 1345 (name (if enter-string
1053 (read-string "New buffer name: " name-default) 1346 (read-string "New buffer name: " name-default)
1054 name-default))) 1347 name-default))
1055 (rename-buffer name t) 1348 (default-directory
1056 (setq buffer-auto-save-file-name 1349 (file-name-as-directory message-autosave-directory)))
1057 (format "%s%s" 1350 (rename-buffer name t)))))
1058 (file-name-as-directory message-autosave-directory)
1059 (file-name-nondirectory buffer-auto-save-file-name)))))))
1060 1351
1061 (defun message-fill-yanked-message (&optional justifyp) 1352 (defun message-fill-yanked-message (&optional justifyp)
1062 "Fill the paragraphs of a message yanked into this one. 1353 "Fill the paragraphs of a message yanked into this one.
1063 Numeric argument means justify as well." 1354 Numeric argument means justify as well."
1064 (interactive "P") 1355 (interactive "P")
1082 (narrow-to-region 1373 (narrow-to-region
1083 (goto-char start) 1374 (goto-char start)
1084 (if (search-forward "\n\n" nil t) 1375 (if (search-forward "\n\n" nil t)
1085 (1- (point)) 1376 (1- (point))
1086 (point))) 1377 (point)))
1087 (message-remove-header message-ignored-cited-headers t))) 1378 (message-remove-header message-ignored-cited-headers t)
1379 (goto-char (point-max))))
1380 ;; Delete blank lines at the start of the buffer.
1381 (while (and (point-min)
1382 (eolp)
1383 (not (eobp)))
1384 (message-delete-line))
1385 ;; Delete blank lines at the end of the buffer.
1386 (goto-char (point-max))
1387 (unless (eolp)
1388 (insert "\n"))
1389 (while (and (zerop (forward-line -1))
1390 (looking-at "$"))
1391 (message-delete-line))
1088 ;; Do the indentation. 1392 ;; Do the indentation.
1089 (if (null message-yank-prefix) 1393 (if (null message-yank-prefix)
1090 (indent-rigidly start (mark t) message-indentation-spaces) 1394 (indent-rigidly start (mark t) message-indentation-spaces)
1091 (save-excursion 1395 (save-excursion
1092 (goto-char start) 1396 (goto-char start)
1093 (while (< (point) (mark t)) 1397 (while (< (point) (mark t))
1094 (insert message-yank-prefix) 1398 (insert message-yank-prefix)
1095 (forward-line 1))) 1399 (forward-line 1))))
1096 (goto-char start)))) 1400 (goto-char start)))
1097 1401
1098 (defun message-yank-original (&optional arg) 1402 (defun message-yank-original (&optional arg)
1099 "Insert the message being replied to, if any. 1403 "Insert the message being replied to, if any.
1100 Puts point before the text and mark after. 1404 Puts point before the text and mark after.
1101 Normally indents each nonblank line ARG spaces (default 3). However, 1405 Normally indents each nonblank line ARG spaces (default 3). However,
1116 (unless (bolp) 1420 (unless (bolp)
1117 (insert ?\n)) 1421 (insert ?\n))
1118 (unless modified 1422 (unless modified
1119 (setq message-checksum (cons (message-checksum) (buffer-size))))))) 1423 (setq message-checksum (cons (message-checksum) (buffer-size)))))))
1120 1424
1121 (defun message-cite-original () 1425 (defun message-cite-original ()
1426 "Cite function in the standard Message manner."
1122 (let ((start (point)) 1427 (let ((start (point))
1123 (functions 1428 (functions
1124 (when message-indent-citation-function 1429 (when message-indent-citation-function
1125 (if (listp message-indent-citation-function) 1430 (if (listp message-indent-citation-function)
1126 message-indent-citation-function 1431 message-indent-citation-function
1170 "Remove the signature from the text between point and mark. 1475 "Remove the signature from the text between point and mark.
1171 The text will also be indented the normal way." 1476 The text will also be indented the normal way."
1172 (save-excursion 1477 (save-excursion
1173 (let ((start (point)) 1478 (let ((start (point))
1174 mark) 1479 mark)
1175 (if (not (re-search-forward message-signature-separator (mark t) t)) 1480 (if (not (re-search-forward message-signature-separator (mark t) t))
1176 ;; No signature here, so we just indent the cited text. 1481 ;; No signature here, so we just indent the cited text.
1482 (message-indent-citation)
1483 ;; Find the last non-empty line.
1484 (forward-line -1)
1485 (while (looking-at "[ \t]*$")
1486 (forward-line -1))
1487 (forward-line 1)
1488 (setq mark (set-marker (make-marker) (point)))
1489 (goto-char start)
1177 (message-indent-citation) 1490 (message-indent-citation)
1178 ;; Find the last non-empty line. 1491 ;; Enable undoing the deletion.
1179 (forward-line -1) 1492 (undo-boundary)
1180 (while (looking-at "[ \t]*$") 1493 (delete-region mark (mark t))
1181 (forward-line -1)) 1494 (set-marker mark nil)))))
1182 (forward-line 1)
1183 (setq mark (set-marker (make-marker) (point)))
1184 (goto-char start)
1185 (message-indent-citation)
1186 ;; Enable undoing the deletion.
1187 (undo-boundary)
1188 (delete-region mark (mark t))
1189 (set-marker mark nil)))))
1190 1495
1191 1496
1192 1497
1193 ;;; 1498 ;;;
1194 ;;; Sending messages 1499 ;;; Sending messages
1209 (message-do-actions actions)))) 1514 (message-do-actions actions))))
1210 1515
1211 (defun message-dont-send () 1516 (defun message-dont-send ()
1212 "Don't send the message you have been editing." 1517 "Don't send the message you have been editing."
1213 (interactive) 1518 (interactive)
1214 (message-bury (current-buffer)) 1519 (let ((actions message-postpone-actions))
1215 (message-do-actions message-postpone-actions)) 1520 (message-bury (current-buffer))
1521 (message-do-actions actions)))
1216 1522
1217 (defun message-kill-buffer () 1523 (defun message-kill-buffer ()
1218 "Kill the current buffer." 1524 "Kill the current buffer."
1219 (interactive) 1525 (interactive)
1220 (let ((actions message-kill-actions)) 1526 (let ((actions message-kill-actions))
1293 1599
1294 (defun message-do-actions (actions) 1600 (defun message-do-actions (actions)
1295 "Perform all actions in ACTIONS." 1601 "Perform all actions in ACTIONS."
1296 ;; Now perform actions on successful sending. 1602 ;; Now perform actions on successful sending.
1297 (while actions 1603 (while actions
1298 (condition-case nil 1604 (ignore-errors
1299 (cond 1605 (cond
1300 ;; A simple function. 1606 ;; A simple function.
1301 ((message-functionp (car actions)) 1607 ((message-functionp (car actions))
1302 (funcall (car actions))) 1608 (funcall (car actions)))
1303 ;; Something to be evaled. 1609 ;; Something to be evaled.
1304 (t 1610 (t
1305 (eval (car actions)))) 1611 (eval (car actions)))))
1306 (error))
1307 (pop actions))) 1612 (pop actions)))
1308 1613
1309 (defun message-send-mail (&optional arg) 1614 (defun message-send-mail (&optional arg)
1310 (require 'mail-utils) 1615 (require 'mail-utils)
1311 (let ((tembuf (generate-new-buffer " message temp")) 1616 (let ((tembuf (message-generate-new-buffer-clone-locals " message temp"))
1312 (case-fold-search nil) 1617 (case-fold-search nil)
1313 (news (message-news-p)) 1618 (news (message-news-p))
1314 (mailbuf (current-buffer))) 1619 (mailbuf (current-buffer)))
1315 (save-restriction 1620 (save-restriction
1316 (message-narrow-to-headers) 1621 (message-narrow-to-headers)
1362 (re-search-forward 1667 (re-search-forward
1363 (concat "^" (regexp-quote mail-header-separator) "\n")) 1668 (concat "^" (regexp-quote mail-header-separator) "\n"))
1364 (replace-match "\n") 1669 (replace-match "\n")
1365 (backward-char 1) 1670 (backward-char 1)
1366 (setq delimline (point-marker)) 1671 (setq delimline (point-marker))
1672 (run-hooks 'message-send-mail-hook)
1367 ;; Insert an extra newline if we need it to work around 1673 ;; Insert an extra newline if we need it to work around
1368 ;; Sun's bug that swallows newlines. 1674 ;; Sun's bug that swallows newlines.
1369 (goto-char (1+ delimline)) 1675 (goto-char (1+ delimline))
1370 (when (eval message-mailer-swallows-blank-line) 1676 (when (eval message-mailer-swallows-blank-line)
1371 (newline)) 1677 (newline))
1380 sendmail-program 1686 sendmail-program
1381 "/usr/lib/sendmail") 1687 "/usr/lib/sendmail")
1382 nil errbuf nil "-oi") 1688 nil errbuf nil "-oi")
1383 ;; Always specify who from, 1689 ;; Always specify who from,
1384 ;; since some systems have broken sendmails. 1690 ;; since some systems have broken sendmails.
1385 (list "-f" (user-login-name)) 1691 ;; But some systems are more broken with -f, so
1692 ;; we'll let users override this.
1693 (if (null message-sendmail-f-is-evil)
1694 (list "-f" (user-login-name)))
1386 ;; These mean "report errors by mail" 1695 ;; These mean "report errors by mail"
1387 ;; and "deliver in background". 1696 ;; and "deliver in background".
1388 (if (null message-interactive) '("-oem" "-odb")) 1697 (if (null message-interactive) '("-oem" "-odb"))
1389 ;; Get the addresses from the message 1698 ;; Get the addresses from the message
1390 ;; unless this is a resend. 1699 ;; unless this is a resend.
1404 (error "Sending...failed to %s" 1713 (error "Sending...failed to %s"
1405 (buffer-substring (point-min) (point-max))))) 1714 (buffer-substring (point-min) (point-max)))))
1406 (when (bufferp errbuf) 1715 (when (bufferp errbuf)
1407 (kill-buffer errbuf))))) 1716 (kill-buffer errbuf)))))
1408 1717
1718 (defun message-send-mail-with-qmail ()
1719 "Pass the prepared message buffer to qmail-inject.
1720 Refer to the documentation for the variable `message-send-mail-function'
1721 to find out how to use this."
1722 ;; replace the header delimiter with a blank line
1723 (goto-char (point-min))
1724 (re-search-forward
1725 (concat "^" (regexp-quote mail-header-separator) "\n"))
1726 (replace-match "\n")
1727 (run-hooks 'message-send-mail-hook)
1728 ;; send the message
1729 (case
1730 (apply
1731 'call-process-region 1 (point-max) message-qmail-inject-program
1732 nil nil nil
1733 ;; qmail-inject's default behaviour is to look for addresses on the
1734 ;; command line; if there're none, it scans the headers.
1735 ;; yes, it does The Right Thing w.r.t. Resent-To and it's kin.
1736 ;;
1737 ;; in general, ALL of qmail-inject's defaults are perfect for simply
1738 ;; reading a formatted (i. e., at least a To: or Resent-To header)
1739 ;; message from stdin.
1740 ;;
1741 ;; qmail also has the advantage of not having been raped by
1742 ;; various vendors, so we don't have to allow for that, either --
1743 ;; compare this with message-send-mail-with-sendmail and weep
1744 ;; for sendmail's lost innocence.
1745 ;;
1746 ;; all this is way cool coz it lets us keep the arguments entirely
1747 ;; free for -inject-arguments -- a big win for the user and for us
1748 ;; since we don't have to play that double-guessing game and the user
1749 ;; gets full control (no gestapo'ish -f's, for instance). --sj
1750 message-qmail-inject-args)
1751 ;; qmail-inject doesn't say anything on it's stdout/stderr,
1752 ;; we have to look at the retval instead
1753 (0 nil)
1754 (1 (error "qmail-inject reported permanent failure."))
1755 (111 (error "qmail-inject reported transient failure."))
1756 ;; should never happen
1757 (t (error "qmail-inject reported unknown failure."))))
1758
1409 (defun message-send-mail-with-mh () 1759 (defun message-send-mail-with-mh ()
1410 "Send the prepared message buffer with mh." 1760 "Send the prepared message buffer with mh."
1411 (let ((mh-previous-window-config nil) 1761 (let ((mh-previous-window-config nil)
1412 (name (make-temp-name 1762 (name (make-temp-name
1413 (concat (file-name-as-directory message-autosave-directory) 1763 (concat (file-name-as-directory
1764 (expand-file-name message-autosave-directory))
1414 "msg.")))) 1765 "msg."))))
1415 (setq buffer-file-name name) 1766 (setq buffer-file-name name)
1416 (mh-send-letter) 1767 ;; MH wants to generate these headers itself.
1417 (condition-case () 1768 (when message-delete-mh-headers
1418 (delete-file name) 1769 (let ((headers message-deletable-headers))
1419 (error nil)))) 1770 (while headers
1771 (goto-char (point-min))
1772 (and (re-search-forward
1773 (concat "^" (symbol-name (car headers)) ": *") nil t)
1774 (message-delete-line))
1775 (pop headers))))
1776 (run-hooks 'message-send-mail-hook)
1777 ;; Pass it on to mh.
1778 (mh-send-letter)))
1420 1779
1421 (defun message-send-news (&optional arg) 1780 (defun message-send-news (&optional arg)
1422 (let ((tembuf (generate-new-buffer " *message temp*")) 1781 (let ((tembuf (message-generate-new-buffer-clone-locals " *message temp*"))
1423 (case-fold-search nil) 1782 (case-fold-search nil)
1424 (method (if (message-functionp message-post-method) 1783 (method (if (message-functionp message-post-method)
1425 (funcall message-post-method arg) 1784 (funcall message-post-method arg)
1426 message-post-method)) 1785 message-post-method))
1427 (messbuf (current-buffer)) 1786 (messbuf (current-buffer))
1436 ;; Insert some headers. 1795 ;; Insert some headers.
1437 (message-generate-headers message-required-news-headers) 1796 (message-generate-headers message-required-news-headers)
1438 ;; Let the user do all of the above. 1797 ;; Let the user do all of the above.
1439 (run-hooks 'message-header-hook)) 1798 (run-hooks 'message-header-hook))
1440 (message-cleanup-headers) 1799 (message-cleanup-headers)
1441 (when (message-check-news-syntax) 1800 (if (not (message-check-news-syntax))
1801 (progn
1802 ;;(message "Posting not performed")
1803 nil)
1442 (unwind-protect 1804 (unwind-protect
1443 (save-excursion 1805 (save-excursion
1444 (set-buffer tembuf) 1806 (set-buffer tembuf)
1445 (buffer-disable-undo (current-buffer)) 1807 (buffer-disable-undo (current-buffer))
1446 (erase-buffer) 1808 (erase-buffer)
1447 ;; Avoid copying text props. 1809 ;; Avoid copying text props.
1448 (insert (format 1810 (insert (format
1449 "%s" (save-excursion 1811 "%s" (save-excursion
1450 (set-buffer messbuf) 1812 (set-buffer messbuf)
1451 (buffer-string)))) 1813 (buffer-string))))
1452 ;; Remove some headers. 1814 ;; Remove some headers.
1453 (save-restriction 1815 (save-restriction
1454 (message-narrow-to-headers) 1816 (message-narrow-to-headers)
1455 ;; Remove some headers. 1817 ;; Remove some headers.
1456 (message-remove-header message-ignored-news-headers t)) 1818 (message-remove-header message-ignored-news-headers t))
1457 (goto-char (point-max)) 1819 (goto-char (point-max))
1458 ;; require one newline at the end. 1820 ;; require one newline at the end.
1459 (or (= (preceding-char) ?\n) 1821 (or (= (preceding-char) ?\n)
1460 (insert ?\n)) 1822 (insert ?\n))
1461 (let ((case-fold-search t)) 1823 (let ((case-fold-search t))
1462 ;; Remove the delimeter. 1824 ;; Remove the delimiter.
1463 (goto-char (point-min)) 1825 (goto-char (point-min))
1464 (re-search-forward 1826 (re-search-forward
1465 (concat "^" (regexp-quote mail-header-separator) "\n")) 1827 (concat "^" (regexp-quote mail-header-separator) "\n"))
1466 (replace-match "\n") 1828 (replace-match "\n")
1467 (backward-char 1)) 1829 (backward-char 1))
1830 (run-hooks 'message-send-news-hook)
1468 (require (car method)) 1831 (require (car method))
1469 (funcall (intern (format "%s-open-server" (car method))) 1832 (funcall (intern (format "%s-open-server" (car method)))
1470 (cadr method) (cddr method)) 1833 (cadr method) (cddr method))
1471 (setq result 1834 (setq result
1472 (funcall (intern (format "%s-request-post" (car method)))))) 1835 (funcall (intern (format "%s-request-post" (car method))))))
1480 1843
1481 ;;; 1844 ;;;
1482 ;;; Header generation & syntax checking. 1845 ;;; Header generation & syntax checking.
1483 ;;; 1846 ;;;
1484 1847
1485 (defun message-check-news-syntax () 1848 (defmacro message-check (type &rest forms)
1486 "Check the syntax of the message." 1849 "Eval FORMS if TYPE is to be checked."
1487 (and 1850 `(or (message-check-element ,type)
1488 ;; We narrow to the headers and check them first.
1489 (save-excursion
1490 (save-restriction
1491 (message-narrow-to-headers)
1492 (and
1493 ;; Check for commands in Subject.
1494 (or
1495 (message-check-element 'subject-cmsg)
1496 (save-excursion
1497 (if (string-match "^cmsg " (message-fetch-field "subject"))
1498 (y-or-n-p
1499 "The control code \"cmsg \" is in the subject. Really post? ")
1500 t)))
1501 ;; Check for multiple identical headers.
1502 (or (message-check-element 'multiple-headers)
1503 (save-excursion
1504 (let (found)
1505 (while (and (not found)
1506 (re-search-forward "^[^ \t:]+: " nil t))
1507 (save-excursion
1508 (or (re-search-forward
1509 (concat "^" (setq found
1510 (buffer-substring
1511 (match-beginning 0)
1512 (- (match-end 0) 2))))
1513 nil t)
1514 (setq found nil))))
1515 (if found
1516 (y-or-n-p
1517 (format "Multiple %s headers. Really post? " found))
1518 t))))
1519 ;; Check for Version and Sendsys.
1520 (or (message-check-element 'sendsys)
1521 (save-excursion
1522 (if (re-search-forward "^Sendsys:\\|^Version:" nil t)
1523 (y-or-n-p
1524 (format "The article contains a %s command. Really post? "
1525 (buffer-substring (match-beginning 0)
1526 (1- (match-end 0)))))
1527 t)))
1528 ;; See whether we can shorten Followup-To.
1529 (or (message-check-element 'shorten-followup-to)
1530 (let ((newsgroups (message-fetch-field "newsgroups"))
1531 (followup-to (message-fetch-field "followup-to"))
1532 to)
1533 (when (and newsgroups (string-match "," newsgroups)
1534 (not followup-to)
1535 (not
1536 (zerop
1537 (length
1538 (setq to (completing-read
1539 "Followups to: (default all groups) "
1540 (mapcar (lambda (g) (list g))
1541 (cons "poster"
1542 (message-tokenize-header
1543 newsgroups)))))))))
1544 (goto-char (point-min))
1545 (insert "Followup-To: " to "\n"))
1546 t))
1547 ;; Check "Shoot me".
1548 (or (message-check-element 'shoot)
1549 (save-excursion
1550 (if (re-search-forward
1551 "Message-ID.*.i-have-a-misconfigured-system-so-shoot-me"
1552 nil t)
1553 (y-or-n-p
1554 "You appear to have a misconfigured system. Really post? ")
1555 t)))
1556 ;; Check for Approved.
1557 (or (message-check-element 'approved)
1558 (save-excursion
1559 (if (re-search-forward "^Approved:" nil t)
1560 (y-or-n-p
1561 "The article contains an Approved header. Really post? ")
1562 t)))
1563 ;; Check the Message-Id header.
1564 (or (message-check-element 'message-id)
1565 (save-excursion
1566 (let* ((case-fold-search t)
1567 (message-id (message-fetch-field "message-id")))
1568 (or (not message-id)
1569 (and (string-match "@" message-id)
1570 (string-match "@[^\\.]*\\." message-id))
1571 (y-or-n-p
1572 (format
1573 "The Message-ID looks strange: \"%s\". Really post? "
1574 message-id))))))
1575 ;; Check the Subject header.
1576 (or
1577 (message-check-element 'subject)
1578 (save-excursion
1579 (let* ((case-fold-search t)
1580 (subject (message-fetch-field "subject")))
1581 (or
1582 (and subject
1583 (not (string-match "\\`[ \t]*\\'" subject)))
1584 (progn
1585 (message
1586 "The subject field is empty or missing. Posting is denied.")
1587 nil)))))
1588 ;; Check the Newsgroups & Followup-To headers.
1589 (or
1590 (message-check-element 'existing-newsgroups)
1591 (let* ((case-fold-search t)
1592 (newsgroups (message-fetch-field "newsgroups"))
1593 (followup-to (message-fetch-field "followup-to"))
1594 (groups (message-tokenize-header
1595 (if followup-to
1596 (concat newsgroups "," followup-to)
1597 newsgroups)))
1598 (hashtb (and (boundp 'gnus-active-hashtb)
1599 gnus-active-hashtb))
1600 errors)
1601 (if (not hashtb)
1602 t
1603 (while groups
1604 (when (and (not (boundp (intern (car groups) hashtb)))
1605 (not (equal (car groups) "poster")))
1606 (push (car groups) errors))
1607 (pop groups))
1608 (if (not errors)
1609 t
1610 (y-or-n-p
1611 (format
1612 "Really post to %s unknown group%s: %s "
1613 (if (= (length errors) 1) "this" "these")
1614 (if (= (length errors) 1) "" "s")
1615 (mapconcat 'identity errors ", ")))))))
1616 ;; Check the Newsgroups & Followup-To headers for syntax errors.
1617 (or
1618 (message-check-element 'valid-newsgroups)
1619 (let ((case-fold-search t)
1620 (headers '("Newsgroups" "Followup-To"))
1621 header error)
1622 (while (and headers (not error))
1623 (when (setq header (mail-fetch-field (car headers)))
1624 (if (or
1625 (not
1626 (string-match
1627 "\\`\\([-+_&.a-zA-Z0-9]+\\)?\\(,[-.a-zA-Z0-9]+\\)*\\'"
1628 header))
1629 (memq
1630 nil (mapcar
1631 (lambda (g)
1632 (not (string-match "\\.\\'\\|\\.\\." g)))
1633 (message-tokenize-header header ","))))
1634 (setq error t)))
1635 (unless error
1636 (pop headers)))
1637 (if (not error)
1638 t
1639 (y-or-n-p
1640 (format "The %s header looks odd: \"%s\". Really post? "
1641 (car headers) header)))))
1642 ;; Check the From header.
1643 (or
1644 (save-excursion
1645 (let* ((case-fold-search t)
1646 (from (message-fetch-field "from")))
1647 (cond
1648 ((not from)
1649 (message "There is no From line. Posting is denied.")
1650 nil)
1651 ((not (string-match "@[^\\.]*\\." from))
1652 (message
1653 "Denied posting -- the From looks strange: \"%s\"." from)
1654 nil)
1655 ((string-match "@[^@]*@" from)
1656 (message
1657 "Denied posting -- two \"@\"'s in the From header: %s." from)
1658 nil)
1659 ((string-match "(.*).*(.*)" from)
1660 (message
1661 "Denied posting -- the From header looks strange: \"%s\"."
1662 from)
1663 nil)
1664 (t t))))))))
1665 ;; Check for long lines.
1666 (or (message-check-element 'long-lines)
1667 (save-excursion 1851 (save-excursion
1668 (goto-char (point-min)) 1852 ,@forms)))
1669 (re-search-forward 1853
1670 (concat "^" (regexp-quote mail-header-separator) "$")) 1854 (put 'message-check 'lisp-indent-function 1)
1671 (while (and 1855 (put 'message-check 'edebug-form-spec '(form body))
1672 (progn
1673 (end-of-line)
1674 (< (current-column) 80))
1675 (zerop (forward-line 1))))
1676 (or (bolp)
1677 (eobp)
1678 (y-or-n-p
1679 "You have lines longer than 79 characters. Really post? "))))
1680 ;; Check whether the article is empty.
1681 (or (message-check-element 'empty)
1682 (save-excursion
1683 (goto-char (point-min))
1684 (re-search-forward
1685 (concat "^" (regexp-quote mail-header-separator) "$"))
1686 (forward-line 1)
1687 (let ((b (point)))
1688 (goto-char (point-max))
1689 (re-search-backward message-signature-separator nil t)
1690 (beginning-of-line)
1691 (or (re-search-backward "[^ \n\t]" b t)
1692 (y-or-n-p "Empty article. Really post? ")))))
1693 ;; Check for control characters.
1694 (or (message-check-element 'control-chars)
1695 (save-excursion
1696 (if (re-search-forward "[\000-\007\013\015-\037\200-\237]" nil t)
1697 (y-or-n-p
1698 "The article contains control characters. Really post? ")
1699 t)))
1700 ;; Check excessive size.
1701 (or (message-check-element 'size)
1702 (if (> (buffer-size) 60000)
1703 (y-or-n-p
1704 (format "The article is %d octets long. Really post? "
1705 (buffer-size)))
1706 t))
1707 ;; Check whether any new text has been added.
1708 (or (message-check-element 'new-text)
1709 (not message-checksum)
1710 (not (and (eq (message-checksum) (car message-checksum))
1711 (eq (buffer-size) (cdr message-checksum))))
1712 (y-or-n-p
1713 "It looks like no new text has been added. Really post? "))
1714 ;; Check the length of the signature.
1715 (or
1716 (message-check-element 'signature)
1717 (progn
1718 (goto-char (point-max))
1719 (if (or (not (re-search-backward message-signature-separator nil t))
1720 (search-forward message-forward-end-separator nil t))
1721 t
1722 (if (> (count-lines (point) (point-max)) 5)
1723 (y-or-n-p
1724 (format
1725 "Your .sig is %d lines; it should be max 4. Really post? "
1726 (count-lines (point) (point-max))))
1727 t))))))
1728 1856
1729 (defun message-check-element (type) 1857 (defun message-check-element (type)
1730 "Returns non-nil if this type is not to be checked." 1858 "Returns non-nil if this type is not to be checked."
1731 (if (eq message-syntax-checks 'dont-check-for-anything-just-trust-me) 1859 (if (eq message-syntax-checks 'dont-check-for-anything-just-trust-me)
1732 t 1860 t
1733 (let ((able (assq type message-syntax-checks))) 1861 (let ((able (assq type message-syntax-checks)))
1734 (and (consp able) 1862 (and (consp able)
1735 (eq (cdr able) 'disabled))))) 1863 (eq (cdr able) 'disabled)))))
1864
1865 (defun message-check-news-syntax ()
1866 "Check the syntax of the message."
1867 (save-excursion
1868 (save-restriction
1869 (widen)
1870 (and
1871 ;; We narrow to the headers and check them first.
1872 (save-excursion
1873 (save-restriction
1874 (message-narrow-to-headers)
1875 (message-check-news-header-syntax)))
1876 ;; Check the body.
1877 (message-check-news-body-syntax)))))
1878
1879 (defun message-check-news-header-syntax ()
1880 (and
1881 ;; Check for commands in Subject.
1882 (message-check 'subject-cmsg
1883 (if (string-match "^cmsg " (message-fetch-field "subject"))
1884 (y-or-n-p
1885 "The control code \"cmsg\" is in the subject. Really post? ")
1886 t))
1887 ;; Check for multiple identical headers.
1888 (message-check 'multiple-headers
1889 (let (found)
1890 (while (and (not found)
1891 (re-search-forward "^[^ \t:]+: " nil t))
1892 (save-excursion
1893 (or (re-search-forward
1894 (concat "^"
1895 (regexp-quote
1896 (setq found
1897 (buffer-substring
1898 (match-beginning 0) (- (match-end 0) 2))))
1899 ":")
1900 nil t)
1901 (setq found nil))))
1902 (if found
1903 (y-or-n-p (format "Multiple %s headers. Really post? " found))
1904 t)))
1905 ;; Check for Version and Sendsys.
1906 (message-check 'sendsys
1907 (if (re-search-forward "^Sendsys:\\|^Version:" nil t)
1908 (y-or-n-p
1909 (format "The article contains a %s command. Really post? "
1910 (buffer-substring (match-beginning 0)
1911 (1- (match-end 0)))))
1912 t))
1913 ;; See whether we can shorten Followup-To.
1914 (message-check 'shorten-followup-to
1915 (let ((newsgroups (message-fetch-field "newsgroups"))
1916 (followup-to (message-fetch-field "followup-to"))
1917 to)
1918 (when (and newsgroups
1919 (string-match "," newsgroups)
1920 (not followup-to)
1921 (not
1922 (zerop
1923 (length
1924 (setq to (completing-read
1925 "Followups to: (default all groups) "
1926 (mapcar (lambda (g) (list g))
1927 (cons "poster"
1928 (message-tokenize-header
1929 newsgroups)))))))))
1930 (goto-char (point-min))
1931 (insert "Followup-To: " to "\n"))
1932 t))
1933 ;; Check "Shoot me".
1934 (message-check 'shoot
1935 (if (re-search-forward
1936 "Message-ID.*.i-did-not-set--mail-host-address--so-shoot-me" nil t)
1937 (y-or-n-p "You appear to have a misconfigured system. Really post? ")
1938 t))
1939 ;; Check for Approved.
1940 (message-check 'approved
1941 (if (re-search-forward "^Approved:" nil t)
1942 (y-or-n-p "The article contains an Approved header. Really post? ")
1943 t))
1944 ;; Check the Message-ID header.
1945 (message-check 'message-id
1946 (let* ((case-fold-search t)
1947 (message-id (message-fetch-field "message-id")))
1948 (or (not message-id)
1949 (and (string-match "@" message-id)
1950 (string-match "@[^\\.]*\\." message-id))
1951 (y-or-n-p
1952 (format "The Message-ID looks strange: \"%s\". Really post? "
1953 message-id)))))
1954 ;; Check the Subject header.
1955 (message-check 'subject
1956 (let* ((case-fold-search t)
1957 (subject (message-fetch-field "subject")))
1958 (or
1959 (and subject
1960 (not (string-match "\\`[ \t]*\\'" subject)))
1961 (ignore
1962 (message
1963 "The subject field is empty or missing. Posting is denied.")))))
1964 ;; Check the Newsgroups & Followup-To headers.
1965 (message-check 'existing-newsgroups
1966 (let* ((case-fold-search t)
1967 (newsgroups (message-fetch-field "newsgroups"))
1968 (followup-to (message-fetch-field "followup-to"))
1969 (groups (message-tokenize-header
1970 (if followup-to
1971 (concat newsgroups "," followup-to)
1972 newsgroups)))
1973 (hashtb (and (boundp 'gnus-active-hashtb)
1974 gnus-active-hashtb))
1975 errors)
1976 (if (or (not hashtb)
1977 (not (boundp 'gnus-read-active-file))
1978 (not gnus-read-active-file)
1979 (eq gnus-read-active-file 'some))
1980 t
1981 (while groups
1982 (when (and (not (boundp (intern (car groups) hashtb)))
1983 (not (equal (car groups) "poster")))
1984 (push (car groups) errors))
1985 (pop groups))
1986 (if (not errors)
1987 t
1988 (y-or-n-p
1989 (format
1990 "Really post to %s unknown group%s: %s "
1991 (if (= (length errors) 1) "this" "these")
1992 (if (= (length errors) 1) "" "s")
1993 (mapconcat 'identity errors ", ")))))))
1994 ;; Check the Newsgroups & Followup-To headers for syntax errors.
1995 (message-check 'valid-newsgroups
1996 (let ((case-fold-search t)
1997 (headers '("Newsgroups" "Followup-To"))
1998 header error)
1999 (while (and headers (not error))
2000 (when (setq header (mail-fetch-field (car headers)))
2001 (if (or
2002 (not
2003 (string-match
2004 "\\`\\([-+_&.a-zA-Z0-9]+\\)?\\(,[-+_&.a-zA-Z0-9]+\\)*\\'"
2005 header))
2006 (memq
2007 nil (mapcar
2008 (lambda (g)
2009 (not (string-match "\\.\\'\\|\\.\\." g)))
2010 (message-tokenize-header header ","))))
2011 (setq error t)))
2012 (unless error
2013 (pop headers)))
2014 (if (not error)
2015 t
2016 (y-or-n-p
2017 (format "The %s header looks odd: \"%s\". Really post? "
2018 (car headers) header)))))
2019 ;; Check the From header.
2020 (message-check 'from
2021 (let* ((case-fold-search t)
2022 (from (message-fetch-field "from"))
2023 (ad (nth 1 (mail-extract-address-components from))))
2024 (cond
2025 ((not from)
2026 (message "There is no From line. Posting is denied.")
2027 nil)
2028 ((or (not (string-match "@[^\\.]*\\." ad)) ;larsi@ifi
2029 (string-match "\\.\\." ad) ;larsi@ifi..uio
2030 (string-match "@\\." ad) ;larsi@.ifi.uio
2031 (string-match "\\.$" ad) ;larsi@ifi.uio.
2032 (not (string-match "^[^@]+@[^@]+$" ad)) ;larsi.ifi.uio
2033 (string-match "(.*).*(.*)" from)) ;(lars) (lars)
2034 (message
2035 "Denied posting -- the From looks strange: \"%s\"." from)
2036 nil)
2037 (t t))))))
2038
2039 (defun message-check-news-body-syntax ()
2040 (and
2041 ;; Check for long lines.
2042 (message-check 'long-lines
2043 (goto-char (point-min))
2044 (re-search-forward
2045 (concat "^" (regexp-quote mail-header-separator) "$"))
2046 (while (and
2047 (progn
2048 (end-of-line)
2049 (< (current-column) 80))
2050 (zerop (forward-line 1))))
2051 (or (bolp)
2052 (eobp)
2053 (y-or-n-p
2054 "You have lines longer than 79 characters. Really post? ")))
2055 ;; Check whether the article is empty.
2056 (message-check 'empty
2057 (goto-char (point-min))
2058 (re-search-forward
2059 (concat "^" (regexp-quote mail-header-separator) "$"))
2060 (forward-line 1)
2061 (let ((b (point)))
2062 (goto-char (point-max))
2063 (re-search-backward message-signature-separator nil t)
2064 (beginning-of-line)
2065 (or (re-search-backward "[^ \n\t]" b t)
2066 (y-or-n-p "Empty article. Really post? "))))
2067 ;; Check for control characters.
2068 (message-check 'control-chars
2069 (if (re-search-forward "[\000-\007\013\015-\037\200-\237]" nil t)
2070 (y-or-n-p
2071 "The article contains control characters. Really post? ")
2072 t))
2073 ;; Check excessive size.
2074 (message-check 'size
2075 (if (> (buffer-size) 60000)
2076 (y-or-n-p
2077 (format "The article is %d octets long. Really post? "
2078 (buffer-size)))
2079 t))
2080 ;; Check whether any new text has been added.
2081 (message-check 'new-text
2082 (or
2083 (not message-checksum)
2084 (not (and (eq (message-checksum) (car message-checksum))
2085 (eq (buffer-size) (cdr message-checksum))))
2086 (y-or-n-p
2087 "It looks like no new text has been added. Really post? ")))
2088 ;; Check the length of the signature.
2089 (message-check 'signature
2090 (goto-char (point-max))
2091 (if (or (not (re-search-backward message-signature-separator nil t))
2092 (search-forward message-forward-end-separator nil t))
2093 t
2094 (if (> (count-lines (point) (point-max)) 5)
2095 (y-or-n-p
2096 (format
2097 "Your .sig is %d lines; it should be max 4. Really post? "
2098 (1- (count-lines (point) (point-max)))))
2099 t)))))
1736 2100
1737 (defun message-checksum () 2101 (defun message-checksum ()
1738 "Return a \"checksum\" for the current buffer." 2102 "Return a \"checksum\" for the current buffer."
1739 (let ((sum 0)) 2103 (let ((sum 0))
1740 (save-excursion 2104 (save-excursion
1775 (match-string 1 file)) 2139 (match-string 1 file))
1776 ;; Save the article. 2140 ;; Save the article.
1777 (setq file (expand-file-name file)) 2141 (setq file (expand-file-name file))
1778 (unless (file-exists-p (file-name-directory file)) 2142 (unless (file-exists-p (file-name-directory file))
1779 (make-directory (file-name-directory file) t)) 2143 (make-directory (file-name-directory file) t))
1780 (if (and message-fcc-handler-function 2144 (funcall message-fcc-handler-function file)))
1781 (not (eq message-fcc-handler-function 'rmail-output))) 2145
1782 (funcall message-fcc-handler-function file)
1783 (if (and (file-readable-p file) (mail-file-babyl-p file))
1784 (rmail-output file 1 nil t)
1785 (let ((mail-use-rfc822 t))
1786 (rmail-output file 1 t t))))))
1787 (kill-buffer (current-buffer))))) 2146 (kill-buffer (current-buffer)))))
2147
2148 (defun message-output (filename)
2149 "Append this article to Unix/babyl mail file.."
2150 (if (and (file-readable-p filename)
2151 (mail-file-babyl-p filename))
2152 (gnus-output-to-rmail filename t)
2153 (gnus-output-to-mail filename t)))
1788 2154
1789 (defun message-cleanup-headers () 2155 (defun message-cleanup-headers ()
1790 "Do various automatic cleanups of the headers." 2156 "Do various automatic cleanups of the headers."
1791 ;; Remove empty lines in the header. 2157 ;; Remove empty lines in the header.
1792 (save-restriction 2158 (save-restriction
2001 ;; ... then undo escaping of matching parentheses, 2367 ;; ... then undo escaping of matching parentheses,
2002 ;; including matching nested parentheses. 2368 ;; including matching nested parentheses.
2003 (goto-char fullname-start) 2369 (goto-char fullname-start)
2004 (while (re-search-forward 2370 (while (re-search-forward
2005 "\\(\\=\\|[^\\]\\(\\\\\\\\\\)*\\)\\\\(\\(\\([^\\]\\|\\\\\\\\\\)*\\)\\\\)" 2371 "\\(\\=\\|[^\\]\\(\\\\\\\\\\)*\\)\\\\(\\(\\([^\\]\\|\\\\\\\\\\)*\\)\\\\)"
2006 nil 1) 2372 nil 1)
2007 (replace-match "\\1(\\3)" t) 2373 (replace-match "\\1(\\3)" t)
2008 (goto-char fullname-start))) 2374 (goto-char fullname-start)))
2009 (insert ")"))) 2375 (insert ")")))
2010 (buffer-string)))) 2376 (buffer-string))))
2011 2377
2021 (concat (user-login-name) "@" (message-make-domain)))) 2387 (concat (user-login-name) "@" (message-make-domain))))
2022 2388
2023 (defun message-user-mail-address () 2389 (defun message-user-mail-address ()
2024 "Return the pertinent part of `user-mail-address'." 2390 "Return the pertinent part of `user-mail-address'."
2025 (when user-mail-address 2391 (when user-mail-address
2026 (nth 1 (mail-extract-address-components user-mail-address)))) 2392 (if (string-match " " user-mail-address)
2393 (nth 1 (mail-extract-address-components user-mail-address))
2394 user-mail-address)))
2027 2395
2028 (defun message-make-fqdn () 2396 (defun message-make-fqdn ()
2029 "Return user's fully qualified domain name." 2397 "Return user's fully qualified domain name."
2030 (let ((system-name (system-name)) 2398 (let ((system-name (system-name))
2031 (user-mail (message-user-mail-address))) 2399 (user-mail (message-user-mail-address)))
2042 ((and (string-match "\\." user-mail) 2410 ((and (string-match "\\." user-mail)
2043 (string-match "@\\(.*\\)\\'" user-mail)) 2411 (string-match "@\\(.*\\)\\'" user-mail))
2044 (match-string 1 user-mail)) 2412 (match-string 1 user-mail))
2045 ;; Default to this bogus thing. 2413 ;; Default to this bogus thing.
2046 (t 2414 (t
2047 (concat system-name ".i-have-a-misconfigured-system-so-shoot-me"))))) 2415 (concat system-name ".i-did-not-set--mail-host-address--so-shoot-me")))))
2048 2416
2049 (defun message-make-host-name () 2417 (defun message-make-host-name ()
2050 "Return the name of the host." 2418 "Return the name of the host."
2051 (let ((fqdn (message-make-fqdn))) 2419 (let ((fqdn (message-make-fqdn)))
2052 (string-match "^[^.]+\\." fqdn) 2420 (string-match "^[^.]+\\." fqdn)
2087 (concat "^" (symbol-name (car headers)) ": *") nil t) 2455 (concat "^" (symbol-name (car headers)) ": *") nil t)
2088 (get-text-property (1+ (match-beginning 0)) 'message-deletable) 2456 (get-text-property (1+ (match-beginning 0)) 'message-deletable)
2089 (message-delete-line)) 2457 (message-delete-line))
2090 (pop headers))) 2458 (pop headers)))
2091 ;; Go through all the required headers and see if they are in the 2459 ;; Go through all the required headers and see if they are in the
2092 ;; articles already. If they are not, or are empty, they are 2460 ;; articles already. If they are not, or are empty, they are
2093 ;; inserted automatically - except for Subject, Newsgroups and 2461 ;; inserted automatically - except for Subject, Newsgroups and
2094 ;; Distribution. 2462 ;; Distribution.
2095 (while headers 2463 (while headers
2096 (goto-char (point-min)) 2464 (goto-char (point-min))
2097 (setq elem (pop headers)) 2465 (setq elem (pop headers))
2102 (setq header elem)) 2470 (setq header elem))
2103 (when (or (not (re-search-forward 2471 (when (or (not (re-search-forward
2104 (concat "^" (downcase (symbol-name header)) ":") 2472 (concat "^" (downcase (symbol-name header)) ":")
2105 nil t)) 2473 nil t))
2106 (progn 2474 (progn
2107 ;; The header was found. We insert a space after the 2475 ;; The header was found. We insert a space after the
2108 ;; colon, if there is none. 2476 ;; colon, if there is none.
2109 (if (/= (following-char) ? ) (insert " ") (forward-char 1)) 2477 (if (/= (following-char) ? ) (insert " ") (forward-char 1))
2110 ;; Find out whether the header is empty... 2478 ;; Find out whether the header is empty...
2111 (looking-at "[ \t]*$"))) 2479 (looking-at "[ \t]*$")))
2112 ;; So we find out what value we should insert. 2480 ;; So we find out what value we should insert.
2171 (downcase 2539 (downcase
2172 (cadr (mail-extract-address-components sender))) 2540 (cadr (mail-extract-address-components sender)))
2173 (downcase secure-sender))))) 2541 (downcase secure-sender)))))
2174 (goto-char (point-min)) 2542 (goto-char (point-min))
2175 ;; Rename any old Sender headers to Original-Sender. 2543 ;; Rename any old Sender headers to Original-Sender.
2176 (when (re-search-forward "^Sender:" nil t) 2544 (when (re-search-forward "^\\(Original-\\)*Sender:" nil t)
2177 (beginning-of-line) 2545 (beginning-of-line)
2178 (insert "Original-") 2546 (insert "Original-")
2179 (beginning-of-line)) 2547 (beginning-of-line))
2180 (insert "Sender: " secure-sender "\n")))))) 2548 (insert "Sender: " secure-sender "\n"))))))
2181 2549
2182 (defun message-insert-courtesy-copy () 2550 (defun message-insert-courtesy-copy ()
2183 "Insert a courtesy message in mail copies of combined messages." 2551 "Insert a courtesy message in mail copies of combined messages."
2184 (save-excursion 2552 (let (newsgroups)
2185 (save-restriction 2553 (save-excursion
2186 (message-narrow-to-headers) 2554 (save-restriction
2187 (let ((newsgroups (message-fetch-field "newsgroups"))) 2555 (message-narrow-to-headers)
2188 (when newsgroups 2556 (when (setq newsgroups (message-fetch-field "newsgroups"))
2189 (goto-char (point-max)) 2557 (goto-char (point-max))
2190 (insert "Posted-To: " newsgroups "\n")))) 2558 (insert "Posted-To: " newsgroups "\n")))
2191 (forward-line 1) 2559 (forward-line 1)
2192 (insert message-courtesy-message))) 2560 (when message-courtesy-message
2561 (cond
2562 ((string-match "%s" message-courtesy-message)
2563 (insert (format message-courtesy-message newsgroups)))
2564 (t
2565 (insert message-courtesy-message)))))))
2193 2566
2194 ;;; 2567 ;;;
2195 ;;; Setting up a message buffer 2568 ;;; Setting up a message buffer
2196 ;;; 2569 ;;;
2197 2570
2306 "Kill old message buffers." 2679 "Kill old message buffers."
2307 ;; We might have sent this buffer already. Delete it from the 2680 ;; We might have sent this buffer already. Delete it from the
2308 ;; list of buffers. 2681 ;; list of buffers.
2309 (setq message-buffer-list (delq (current-buffer) message-buffer-list)) 2682 (setq message-buffer-list (delq (current-buffer) message-buffer-list))
2310 (while (and message-max-buffers 2683 (while (and message-max-buffers
2684 message-buffer-list
2311 (>= (length message-buffer-list) message-max-buffers)) 2685 (>= (length message-buffer-list) message-max-buffers))
2312 ;; Kill the oldest buffer -- unless it has been changed. 2686 ;; Kill the oldest buffer -- unless it has been changed.
2313 (let ((buffer (pop message-buffer-list))) 2687 (let ((buffer (pop message-buffer-list)))
2314 (when (and (buffer-name buffer) 2688 (when (and (buffer-name buffer)
2315 (not (buffer-modified-p buffer))) 2689 (not (buffer-modified-p buffer)))
2406 ;;; 2780 ;;;
2407 ;;; Commands for interfacing with message 2781 ;;; Commands for interfacing with message
2408 ;;; 2782 ;;;
2409 2783
2410 ;;;###autoload 2784 ;;;###autoload
2411 (defun message-mail (&optional to subject) 2785 (defun message-mail (&optional to subject
2786 other-headers continue switch-function
2787 yank-action send-actions)
2412 "Start editing a mail message to be sent." 2788 "Start editing a mail message to be sent."
2413 (interactive) 2789 (interactive)
2414 (message-pop-to-buffer (message-buffer-name "mail" to)) 2790 (let ((message-this-is-mail t))
2415 (message-setup `((To . ,(or to "")) (Subject . ,(or subject ""))))) 2791 (message-pop-to-buffer (message-buffer-name "mail" to))
2792 (message-setup
2793 (nconc
2794 `((To . ,(or to "")) (Subject . ,(or subject "")))
2795 (when other-headers (list other-headers))))))
2416 2796
2417 ;;;###autoload 2797 ;;;###autoload
2418 (defun message-news (&optional newsgroups subject) 2798 (defun message-news (&optional newsgroups subject)
2419 "Start editing a news article to be sent." 2799 "Start editing a news article to be sent."
2420 (interactive) 2800 (interactive)
2421 (message-pop-to-buffer (message-buffer-name "news" nil newsgroups)) 2801 (let ((message-this-is-news t))
2422 (message-setup `((Newsgroups . ,(or newsgroups "")) 2802 (message-pop-to-buffer (message-buffer-name "news" nil newsgroups))
2423 (Subject . ,(or subject ""))))) 2803 (message-setup `((Newsgroups . ,(or newsgroups ""))
2804 (Subject . ,(or subject ""))))))
2424 2805
2425 ;;;###autoload 2806 ;;;###autoload
2426 (defun message-reply (&optional to-address wide ignore-reply-to) 2807 (defun message-reply (&optional to-address wide ignore-reply-to)
2427 "Start editing a reply to the article in the current buffer." 2808 "Start editing a reply to the article in the current buffer."
2428 (interactive) 2809 (interactive)
2430 from subject date reply-to to cc 2811 from subject date reply-to to cc
2431 references message-id follow-to 2812 references message-id follow-to
2432 (inhibit-point-motion-hooks t) 2813 (inhibit-point-motion-hooks t)
2433 mct never-mct gnus-warning) 2814 mct never-mct gnus-warning)
2434 (save-restriction 2815 (save-restriction
2435 (narrow-to-region 2816 (message-narrow-to-head)
2436 (goto-char (point-min))
2437 (if (search-forward "\n\n" nil t)
2438 (1- (point))
2439 (point-max)))
2440 ;; Allow customizations to have their say. 2817 ;; Allow customizations to have their say.
2441 (if (not wide) 2818 (if (not wide)
2442 ;; This is a regular reply. 2819 ;; This is a regular reply.
2443 (if (message-functionp message-reply-to-function) 2820 (if (message-functionp message-reply-to-function)
2444 (setq follow-to (funcall message-reply-to-function))) 2821 (setq follow-to (funcall message-reply-to-function)))
2499 (let ((s ccalist)) 2876 (let ((s ccalist))
2500 (while s 2877 (while s
2501 (setq ccalist (delq (assoc (car (pop s)) s) ccalist))))) 2878 (setq ccalist (delq (assoc (car (pop s)) s) ccalist)))))
2502 (setq follow-to (list (cons 'To (cdr (pop ccalist))))) 2879 (setq follow-to (list (cons 'To (cdr (pop ccalist)))))
2503 (when ccalist 2880 (when ccalist
2504 (push (cons 'Cc 2881 (let ((ccs (cons 'Cc (mapconcat
2505 (mapconcat (lambda (addr) (cdr addr)) ccalist ", ")) 2882 (lambda (addr) (cdr addr)) ccalist ", "))))
2506 follow-to))))) 2883 (when (string-match "^ +" (cdr ccs))
2884 (setcdr ccs (substring (cdr ccs) (match-end 0))))
2885 (push ccs follow-to))))))
2507 (widen)) 2886 (widen))
2508 2887
2509 (message-pop-to-buffer (message-buffer-name 2888 (message-pop-to-buffer (message-buffer-name
2510 (if wide "wide reply" "reply") from 2889 (if wide "wide reply" "reply") from
2511 (if wide to-address nil))) 2890 (if wide to-address nil)))
2522 nil)) 2901 nil))
2523 cur))) 2902 cur)))
2524 2903
2525 ;;;###autoload 2904 ;;;###autoload
2526 (defun message-wide-reply (&optional to-address) 2905 (defun message-wide-reply (&optional to-address)
2906 "Make a \"wide\" reply to the message in the current buffer."
2527 (interactive) 2907 (interactive)
2528 (message-reply to-address t)) 2908 (message-reply to-address t))
2529 2909
2530 ;;;###autoload 2910 ;;;###autoload
2531 (defun message-followup () 2911 (defun message-followup (&optional to-newsgroups)
2912 "Follow up to the message in the current buffer.
2913 If TO-NEWSGROUPS, use that as the new Newsgroups line."
2532 (interactive) 2914 (interactive)
2533 (let ((cur (current-buffer)) 2915 (let ((cur (current-buffer))
2534 from subject date reply-to mct 2916 from subject date reply-to mct
2535 references message-id follow-to 2917 references message-id follow-to
2536 (inhibit-point-motion-hooks t) 2918 (inhibit-point-motion-hooks t)
2919 (message-this-is-news t)
2537 followup-to distribution newsgroups gnus-warning) 2920 followup-to distribution newsgroups gnus-warning)
2538 (save-restriction 2921 (save-restriction
2539 (narrow-to-region 2922 (narrow-to-region
2540 (goto-char (point-min)) 2923 (goto-char (point-min))
2541 (if (search-forward "\n\n" nil t) 2924 (if (search-forward "\n\n" nil t)
2556 mct (message-fetch-field "mail-copies-to")) 2939 mct (message-fetch-field "mail-copies-to"))
2557 (when (and (setq gnus-warning (message-fetch-field "gnus-warning")) 2940 (when (and (setq gnus-warning (message-fetch-field "gnus-warning"))
2558 (string-match "<[^>]+>" gnus-warning)) 2941 (string-match "<[^>]+>" gnus-warning))
2559 (setq message-id (match-string 0 gnus-warning))) 2942 (setq message-id (match-string 0 gnus-warning)))
2560 ;; Remove bogus distribution. 2943 ;; Remove bogus distribution.
2561 (and (stringp distribution) 2944 (when (and (stringp distribution)
2562 (string-match "world" distribution) 2945 (let ((case-fold-search t))
2563 (setq distribution nil)) 2946 (string-match "world" distribution)))
2947 (setq distribution nil))
2564 ;; Remove any (buggy) Re:'s that are present and make a 2948 ;; Remove any (buggy) Re:'s that are present and make a
2565 ;; proper one. 2949 ;; proper one.
2566 (when (string-match "^[ \t]*[Rr][Ee]:[ \t]*" subject) 2950 (when (string-match "^[ \t]*[Rr][Ee]:[ \t]*" subject)
2567 (setq subject (substring subject (match-end 0)))) 2951 (setq subject (substring subject (match-end 0))))
2568 (setq subject (concat "Re: " subject)) 2952 (setq subject (concat "Re: " subject))
2571 (message-pop-to-buffer (message-buffer-name "followup" from newsgroups)) 2955 (message-pop-to-buffer (message-buffer-name "followup" from newsgroups))
2572 2956
2573 (message-setup 2957 (message-setup
2574 `((Subject . ,subject) 2958 `((Subject . ,subject)
2575 ,@(cond 2959 ,@(cond
2960 (to-newsgroups
2961 (list (cons 'Newsgroups to-newsgroups)))
2576 (follow-to follow-to) 2962 (follow-to follow-to)
2577 ((and followup-to message-use-followup-to) 2963 ((and followup-to message-use-followup-to)
2578 (list 2964 (list
2579 (cond 2965 (cond
2580 ((equal (downcase followup-to) "poster") 2966 ((equal (downcase followup-to) "poster")
2603 If a message is posted to several newsgroups, Followup-To is often 2989 If a message is posted to several newsgroups, Followup-To is often
2604 used to direct the following discussion to one newsgroup only, 2990 used to direct the following discussion to one newsgroup only,
2605 because discussions that are spread over several newsgroup tend to 2991 because discussions that are spread over several newsgroup tend to
2606 be fragmented and very difficult to follow. 2992 be fragmented and very difficult to follow.
2607 2993
2608 Also, some source/announcment newsgroups are not indented for discussion; 2994 Also, some source/announcement newsgroups are not indented for discussion;
2609 responses here are directed to other newsgroups.")) 2995 responses here are directed to other newsgroups."))
2610 (cons 'Newsgroups followup-to) 2996 (cons 'Newsgroups followup-to)
2611 (cons 'Newsgroups newsgroups)))))) 2997 (cons 'Newsgroups newsgroups))))))
2612 (t 2998 (t
2613 `((Newsgroups . ,newsgroups)))) 2999 `((Newsgroups . ,newsgroups))))
2614 ,@(and distribution (list (cons 'Distribution distribution))) 3000 ,@(and distribution (list (cons 'Distribution distribution)))
2615 (References . ,(concat (or references "") (and references " ") 3001 ,@(if (or references message-id)
2616 (or message-id ""))) 3002 `((References . ,(concat (or references "") (and references " ")
3003 (or message-id "")))))
2617 ,@(when (and mct 3004 ,@(when (and mct
2618 (not (equal (downcase mct) "never"))) 3005 (not (equal (downcase mct) "never")))
2619 (list (cons 'Cc (if (equal (downcase mct) "always") 3006 (list (cons 'Cc (if (equal (downcase mct) "always")
2620 (or reply-to from "") 3007 (or reply-to from "")
2621 mct))))) 3008 mct)))))
2657 "Control: cancel " message-id "\n" 3044 "Control: cancel " message-id "\n"
2658 (if distribution 3045 (if distribution
2659 (concat "Distribution: " distribution "\n") 3046 (concat "Distribution: " distribution "\n")
2660 "") 3047 "")
2661 mail-header-separator "\n" 3048 mail-header-separator "\n"
2662 "This is a cancel message from " from ".\n") 3049 message-cancel-message)
2663 (message "Canceling your article...") 3050 (message "Canceling your article...")
2664 (let ((message-syntax-checks 'dont-check-for-anything-just-trust-me)) 3051 (let ((message-syntax-checks 'dont-check-for-anything-just-trust-me))
2665 (funcall message-send-news-function)) 3052 (funcall message-send-news-function))
2666 (message "Canceling your article...done") 3053 (message "Canceling your article...done")
2667 (kill-buffer buf))))) 3054 (kill-buffer buf)))))
2715 3102
2716 ;;; Forwarding messages. 3103 ;;; Forwarding messages.
2717 3104
2718 (defun message-make-forward-subject () 3105 (defun message-make-forward-subject ()
2719 "Return a Subject header suitable for the message in the current buffer." 3106 "Return a Subject header suitable for the message in the current buffer."
2720 (concat "[" (or (message-fetch-field (if (message-news-p) "newsgroups" "from")) 3107 (save-excursion
2721 "(nowhere)") 3108 (save-restriction
2722 "] " (or (message-fetch-field "Subject") ""))) 3109 (current-buffer)
3110 (message-narrow-to-head)
3111 (concat "[" (or (message-fetch-field
3112 (if (message-news-p) "newsgroups" "from"))
3113 "(nowhere)")
3114 "] " (or (message-fetch-field "Subject") "")))))
2723 3115
2724 ;;;###autoload 3116 ;;;###autoload
2725 (defun message-forward (&optional news) 3117 (defun message-forward (&optional news)
2726 "Forward the current message via mail. 3118 "Forward the current message via mail.
2727 Optional NEWS will use news to forward instead of mail." 3119 Optional NEWS will use news to forward instead of mail."
2728 (interactive "P") 3120 (interactive "P")
2729 (let ((cur (current-buffer)) 3121 (let ((cur (current-buffer))
2730 (subject (message-make-forward-subject))) 3122 (subject (message-make-forward-subject))
3123 art-beg)
2731 (if news (message-news nil subject) (message-mail nil subject)) 3124 (if news (message-news nil subject) (message-mail nil subject))
2732 ;; Put point where we want it before inserting the forwarded 3125 ;; Put point where we want it before inserting the forwarded
2733 ;; message. 3126 ;; message.
2734 (if message-signature-before-forwarded-message 3127 (if message-signature-before-forwarded-message
2735 (goto-char (point-max)) 3128 (goto-char (point-max))
2739 (insert "\n")) 3132 (insert "\n"))
2740 ;; Narrow to the area we are to insert. 3133 ;; Narrow to the area we are to insert.
2741 (narrow-to-region (point) (point)) 3134 (narrow-to-region (point) (point))
2742 ;; Insert the separators and the forwarded buffer. 3135 ;; Insert the separators and the forwarded buffer.
2743 (insert message-forward-start-separator) 3136 (insert message-forward-start-separator)
3137 (setq art-beg (point))
2744 (insert-buffer-substring cur) 3138 (insert-buffer-substring cur)
2745 (goto-char (point-max)) 3139 (goto-char (point-max))
2746 (insert message-forward-end-separator) 3140 (insert message-forward-end-separator)
2747 (set-text-properties (point-min) (point-max) nil) 3141 (set-text-properties (point-min) (point-max) nil)
2748 ;; Remove all unwanted headers. 3142 ;; Remove all unwanted headers.
2749 (goto-char (point-min)) 3143 (goto-char art-beg)
2750 (forward-line 1)
2751 (narrow-to-region (point) (if (search-forward "\n\n" nil t) 3144 (narrow-to-region (point) (if (search-forward "\n\n" nil t)
2752 (1- (point)) 3145 (1- (point))
2753 (point))) 3146 (point)))
2754 (goto-char (point-min)) 3147 (goto-char (point-min))
2755 (message-remove-header message-included-forward-headers t nil t) 3148 (message-remove-header message-included-forward-headers t nil t)
2758 3151
2759 ;;;###autoload 3152 ;;;###autoload
2760 (defun message-resend (address) 3153 (defun message-resend (address)
2761 "Resend the current article to ADDRESS." 3154 "Resend the current article to ADDRESS."
2762 (interactive "sResend message to: ") 3155 (interactive "sResend message to: ")
3156 (message "Resending message to %s..." address)
2763 (save-excursion 3157 (save-excursion
2764 (let ((cur (current-buffer)) 3158 (let ((cur (current-buffer))
2765 beg) 3159 beg)
2766 ;; We first set up a normal mail buffer. 3160 ;; We first set up a normal mail buffer.
2767 (set-buffer (get-buffer-create " *message resend*")) 3161 (set-buffer (get-buffer-create " *message resend*"))
2791 (insert mail-header-separator) 3185 (insert mail-header-separator)
2792 ;; Rename all old ("Also-")Resent headers. 3186 ;; Rename all old ("Also-")Resent headers.
2793 (while (re-search-backward "^\\(Also-\\)?Resent-" beg t) 3187 (while (re-search-backward "^\\(Also-\\)?Resent-" beg t)
2794 (beginning-of-line) 3188 (beginning-of-line)
2795 (insert "Also-")) 3189 (insert "Also-"))
3190 ;; Quote any "From " lines at the beginning.
3191 (goto-char beg)
3192 (when (looking-at "From ")
3193 (replace-match "X-From-Line: "))
2796 ;; Send it. 3194 ;; Send it.
2797 (message-send-mail) 3195 (message-send-mail)
2798 (kill-buffer (current-buffer))))) 3196 (kill-buffer (current-buffer)))
3197 (message "Resending message to %s...done" address)))
2799 3198
2800 ;;;###autoload 3199 ;;;###autoload
2801 (defun message-bounce () 3200 (defun message-bounce ()
2802 "Re-mail the current message. 3201 "Re-mail the current message.
2803 This only makes sense if the current message is a bounce message than 3202 This only makes sense if the current message is a bounce message than
2903 Works by overstriking characters. 3302 Works by overstriking characters.
2904 Called from program, takes two arguments START and END 3303 Called from program, takes two arguments START and END
2905 which specify the range to operate on." 3304 which specify the range to operate on."
2906 (interactive "r") 3305 (interactive "r")
2907 (save-excursion 3306 (save-excursion
2908 (let ((end1 (make-marker))) 3307 (let ((end1 (make-marker)))
2909 (move-marker end1 (max start end)) 3308 (move-marker end1 (max start end))
2910 (goto-char (min start end)) 3309 (goto-char (min start end))
2911 (while (< (point) end1) 3310 (while (< (point) end1)
2912 (or (looking-at "[_\^@- ]") 3311 (or (looking-at "[_\^@- ]")
2913 (insert (following-char) "\b")) 3312 (insert (following-char) "\b"))
2914 (forward-char 1))))) 3313 (forward-char 1)))))
2915 3314
2916 ;;;###autoload 3315 ;;;###autoload
2917 (defun unbold-region (start end) 3316 (defun unbold-region (start end)
2918 "Remove all boldness (overstruck characters) in the region. 3317 "Remove all boldness (overstruck characters) in the region.
2919 Called from program, takes two arguments START and END 3318 Called from program, takes two arguments START and END
2920 which specify the range to operate on." 3319 which specify the range to operate on."
2921 (interactive "r") 3320 (interactive "r")
2922 (save-excursion 3321 (save-excursion
2923 (let ((end1 (make-marker))) 3322 (let ((end1 (make-marker)))
2924 (move-marker end1 (max start end)) 3323 (move-marker end1 (max start end))
2925 (goto-char (min start end)) 3324 (goto-char (min start end))
2926 (while (re-search-forward "\b" end1 t) 3325 (while (re-search-forward "\b" end1 t)
2927 (if (eq (following-char) (char-after (- (point) 2))) 3326 (if (eq (following-char) (char-after (- (point) 2)))
2928 (delete-char -2)))))) 3327 (delete-char -2))))))
2929 3328
2930 (defalias 'message-exchange-point-and-mark 'exchange-point-and-mark) 3329 (defalias 'message-exchange-point-and-mark 'exchange-point-and-mark)
2931 3330
2932 ;; Support for toolbar 3331 ;; Support for toolbar
2933 (when (string-match "XEmacs\\|Lucid" emacs-version) 3332 (when (string-match "XEmacs\\|Lucid" emacs-version)
2948 (message-expand-group) 3347 (message-expand-group)
2949 (tab-to-tab-stop))) 3348 (tab-to-tab-stop)))
2950 3349
2951 (defvar gnus-active-hashtb) 3350 (defvar gnus-active-hashtb)
2952 (defun message-expand-group () 3351 (defun message-expand-group ()
2953 (let* ((b (save-excursion (skip-chars-backward "^, :\t\n") (point))) 3352 (let* ((b (save-excursion
3353 (save-restriction
3354 (narrow-to-region
3355 (save-excursion
3356 (beginning-of-line)
3357 (skip-chars-forward "^:")
3358 (1+ (point)))
3359 (point))
3360 (skip-chars-backward "^, \t\n") (point))))
2954 (completion-ignore-case t) 3361 (completion-ignore-case t)
2955 (string (buffer-substring b (point))) 3362 (string (buffer-substring b (point)))
2956 (hashtb (and (boundp 'gnus-active-hashtb) gnus-active-hashtb)) 3363 (hashtb (and (boundp 'gnus-active-hashtb) gnus-active-hashtb))
2957 (completions (all-completions string hashtb)) 3364 (completions (all-completions string hashtb))
2958 (cur (current-buffer)) 3365 (cur (current-buffer))
2981 (goto-char (point-min)) 3388 (goto-char (point-min))
2982 (pop-to-buffer cur))))))) 3389 (pop-to-buffer cur)))))))
2983 3390
2984 ;;; Help stuff. 3391 ;;; Help stuff.
2985 3392
2986 (defmacro message-y-or-n-p (question show &rest text)
2987 "Ask QUESTION, displaying the rest of the arguments in a temp. buffer if SHOW"
2988 `(message-talkative-question 'y-or-n-p ,question ,show ,@text))
2989
2990 (defun message-talkative-question (ask question show &rest text) 3393 (defun message-talkative-question (ask question show &rest text)
2991 "Call FUNCTION with argument QUESTION, displaying the rest of the arguments in a temporary buffer if SHOW. 3394 "Call FUNCTION with argument QUESTION, displaying the rest of the arguments in a temporary buffer if SHOW.
2992 The following arguments may contain lists of values." 3395 The following arguments may contain lists of values."
2993 (if (and show 3396 (if (and show
2994 (setq text (message-flatten-list text))) 3397 (setq text (message-flatten-list text)))
2999 (mapcar 'princ text) 3402 (mapcar 'princ text)
3000 (goto-char (point-min)))) 3403 (goto-char (point-min))))
3001 (funcall ask question)) 3404 (funcall ask question))
3002 (funcall ask question))) 3405 (funcall ask question)))
3003 3406
3004 (defun message-flatten-list (&rest list) 3407 (defun message-flatten-list (list)
3005 (message-flatten-list-1 list)) 3408 "Return a new, flat list that contains all elements of LIST.
3006 3409
3007 (defun message-flatten-list-1 (list) 3410 \(message-flatten-list '(1 (2 3 (4 5 (6))) 7))
3411 => (1 2 3 4 5 6 7)"
3008 (cond ((consp list) 3412 (cond ((consp list)
3009 (apply 'append (mapcar 'message-flatten-list-1 list))) 3413 (apply 'append (mapcar 'message-flatten-list list)))
3010 (list 3414 (list
3011 (list list)))) 3415 (list list))))
3012 3416
3417 (defun message-generate-new-buffer-clone-locals (name &optional varstr)
3418 "Create and return a buffer with a name based on NAME using generate-new-buffer.
3419 Then clone the local variables and values from the old buffer to the
3420 new one, cloning only the locals having a substring matching the
3421 regexp varstr."
3422 (let ((oldlocals (buffer-local-variables)))
3423 (save-excursion
3424 (set-buffer (generate-new-buffer name))
3425 (mapcar (lambda (dude)
3426 (when (and (car dude)
3427 (or (not varstr)
3428 (string-match varstr (symbol-name (car dude)))))
3429 (ignore-errors
3430 (set (make-local-variable (car dude))
3431 (cdr dude)))))
3432 oldlocals)
3433 (current-buffer))))
3434
3013 (run-hooks 'message-load-hook) 3435 (run-hooks 'message-load-hook)
3014 3436
3015 (provide 'message) 3437 (provide 'message)
3016 3438
3017 ;;; message.el ends here 3439 ;;; message.el ends here