(autoload 'gnus-button-mailto "gnus-msg")
(autoload 'gnus-button-reply "gnus-msg" nil t)
(autoload 'parse-time-string "parse-time" nil nil)
+(autoload 'mm-extern-cache-contents "mm-extern")
(defgroup gnus-article nil
"Article display."
:group 'gnus-article-washing)
(defcustom gnus-save-all-headers t
- "*If non-nil, don't remove any headers before saving."
+ "*If non-nil, don't remove any headers before saving.
+This will be overridden by the `:headers' property that the symbol of
+the saver function, which is specified by `gnus-default-article-saver',
+might have."
:group 'gnus-article-saving
:type 'boolean)
"Headers to keep if `gnus-save-all-headers' is nil.
If `gnus-save-all-headers' is non-nil, this variable will be ignored.
If that variable is nil, however, all headers that match this regexp
-will be kept while the rest will be deleted before saving."
+will be kept while the rest will be deleted before saving. This and
+`gnus-save-all-headers' will be overridden by the `:headers' property
+that the symbol of the saver function, which is specified by
+`gnus-default-article-saver', might have."
:group 'gnus-article-saving
:type 'regexp)
(defcustom gnus-default-article-saver 'gnus-summary-save-in-rmail
"A function to save articles in your favourite format.
-The function must be interactively callable (in other words, it must
-be an Emacs command).
+The function will be called by way of the `gnus-summary-save-article'
+command, and friends such as `gnus-summary-save-article-rmail'.
Gnus provides the following functions:
* gnus-summary-save-in-file (article format)
* gnus-summary-save-body-in-file (article body)
* gnus-summary-save-in-vm (use VM's folder format)
-* gnus-summary-write-to-file (article format -- overwrite)."
+* gnus-summary-write-to-file (article format -- overwrite)
+* gnus-summary-write-body-to-file (article body -- overwrite)
+
+The symbol of each function may have the following properties:
+
+* :decode
+The value non-nil means save decoded articles. This is meaningful
+only with `gnus-summary-save-in-file', `gnus-summary-save-body-in-file',
+`gnus-summary-write-to-file', and `gnus-summary-write-body-to-file'.
+
+* :function
+The value specifies an alternative function which appends, not
+overwrites, articles to a file. This implies that when saving many
+articles at a time, `gnus-prompt-before-saving' is bound to t and all
+articles are saved in a single file. This is meaningful only with
+`gnus-summary-write-to-file' and `gnus-summary-write-body-to-file'.
+
+* :headers
+The value specifies the symbol of a variable of which the value
+specifies headers to be saved. If it is omitted,
+`gnus-save-all-headers' and `gnus-saved-headers' control what
+headers should be saved."
:group 'gnus-article-saving
:type '(radio (function-item gnus-summary-save-in-rmail)
(function-item gnus-summary-save-in-mail)
(function-item gnus-summary-save-body-in-file)
(function-item gnus-summary-save-in-vm)
(function-item gnus-summary-write-to-file)
+ (function-item gnus-summary-write-body-to-file)
(function)))
+(defcustom gnus-article-save-coding-system
+ (or (and (mm-coding-system-p 'utf-8) 'utf-8)
+ (and (mm-coding-system-p 'iso-2022-7bit) 'iso-2022-7bit)
+ (and (mm-coding-system-p 'emacs-mule) 'emacs-mule)
+ (and (mm-coding-system-p 'escape-quoted) 'escape-quoted))
+ "Coding system used to save decoded articles to a file.
+
+The recommended coding systems are `utf-8', `iso-2022-7bit' and so on,
+which can safely encode any characters in text. This is used by the
+commands including:
+
+* gnus-summary-save-article-file
+* gnus-summary-save-article-body-file
+* gnus-summary-write-article-file
+* gnus-summary-write-article-body-file
+
+and the functions to which you may set `gnus-default-article-saver':
+
+* gnus-summary-save-in-file
+* gnus-summary-save-body-in-file
+* gnus-summary-write-to-file
+* gnus-summary-write-body-to-file
+
+Those commands and functions save just text displayed in the article
+buffer to a file if the value of this variable is non-nil. Note that
+buttonized MIME parts will be lost in a saved file in that case.
+Otherwise, raw articles will be saved."
+ :group 'gnus-article-saving
+ :type `(choice
+ :format "%{%t%}:\n %[Value Menu%] %v"
+ (const :tag "Save raw articles" nil)
+ ,@(delq nil
+ (mapcar
+ (lambda (arg) (if (mm-coding-system-p (nth 3 arg)) arg))
+ '((const :tag "UTF-8" utf-8)
+ (const :tag "iso-2022-7bit" iso-2022-7bit)
+ (const :tag "Emacs internal" emacs-mule)
+ (const :tag "escape-quoted" escape-quoted))))
+ (symbol :tag "Coding system")))
+
(defcustom gnus-rmail-save-name 'gnus-plain-save-name
"A function generating a file name to save articles in Rmail format.
The function is called with NEWSGROUP, HEADERS, and optional LAST-FILE."
(defvar gnus-decode-header-function 'mail-decode-encoded-word-region
"Function used to decode headers.")
+(defvar gnus-decode-address-function 'mail-decode-encoded-address-region
+ "Function used to decode addresses.")
+
(defvar gnus-article-dumbquotes-map
'(("\200" "EUR")
("\202" ",")
'string<))))
(gnus-article-hide-header "reply-to")))))
((eq elem 'date)
- (let ((date (message-fetch-field "date")))
+ (let ((date (with-current-buffer gnus-original-article-buffer
+ ;; If date in `gnus-article-buffer' is localized
+ ;; (`gnus-treat-date-user-defined'),
+ ;; `days-between' might fail.
+ (message-fetch-field "date"))))
(when (and date
(< (days-between (current-time-string) date)
4))
(error))
gnus-newsgroup-ignored-charsets))
ct cte ctl charset format)
- (save-excursion
- (save-restriction
- (article-narrow-to-head)
- (setq ct (message-fetch-field "Content-Type" t)
- cte (message-fetch-field "Content-Transfer-Encoding" t)
- ctl (and ct (ignore-errors
- (mail-header-parse-content-type ct)))
- charset (cond
- (prompt
- (mm-read-coding-system "Charset to decode: "))
- (ctl
- (mail-content-type-get ctl 'charset)))
- format (and ctl (mail-content-type-get ctl 'format)))
- (when cte
- (setq cte (mail-header-strip cte)))
- (if (and ctl (not (string-match "/" (car ctl))))
- (setq ctl nil))
- (goto-char (point-max)))
- (forward-line 1)
- (save-restriction
- (narrow-to-region (point) (point-max))
- (when (and (eq mail-parse-charset 'gnus-decoded)
- (eq (mm-body-7-or-8) '8bit))
- ;; The text code could have been decoded.
- (setq charset mail-parse-charset))
- (when (and (or (not ctl)
- (equal (car ctl) "text/plain"))
- (not format)) ;; article with format will decode later.
- (mm-decode-body
- charset (and cte (intern (downcase
- (gnus-strip-whitespace cte))))
- (car ctl)))))))
+ (save-excursion
+ (save-restriction
+ (article-narrow-to-head)
+ (setq ct (message-fetch-field "Content-Type" t)
+ cte (message-fetch-field "Content-Transfer-Encoding" t)
+ ctl (and ct (mail-header-parse-content-type ct))
+ charset (cond
+ (prompt
+ (mm-read-coding-system "Charset to decode: "))
+ (ctl
+ (mail-content-type-get ctl 'charset)))
+ format (and ctl (mail-content-type-get ctl 'format)))
+ (when cte
+ (setq cte (mail-header-strip cte)))
+ (if (and ctl (not (string-match "/" (car ctl))))
+ (setq ctl nil))
+ (goto-char (point-max)))
+ (forward-line 1)
+ (save-restriction
+ (narrow-to-region (point) (point-max))
+ (when (and (eq mail-parse-charset 'gnus-decoded)
+ (eq (mm-body-7-or-8) '8bit))
+ ;; The text code could have been decoded.
+ (setq charset mail-parse-charset))
+ (when (and (or (not ctl)
+ (equal (car ctl) "text/plain"))
+ (not format)) ;; article with format will decode later.
+ (mm-decode-body
+ charset (and cte (intern (downcase
+ (gnus-strip-whitespace cte))))
+ (car ctl)))))))
(defun article-decode-encoded-words ()
"Remove encoded-word encoding from headers."
(set-buffer gnus-summary-buffer)
(error))
gnus-newsgroup-ignored-charsets))
- (inhibit-read-only t))
- (save-restriction
- (article-narrow-to-head)
- (funcall gnus-decode-header-function (point-min) (point-max)))))
+ (inhibit-read-only t)
+ end start)
+ (goto-char (point-min))
+ (when (search-forward "\n\n" nil 'move)
+ (forward-line -1))
+ (setq end (point))
+ (while (not (bobp))
+ (while (progn
+ (forward-line -1)
+ (and (not (bobp))
+ (memq (char-after) '(?\t ? )))))
+ (setq start (point))
+ (if (looking-at "\
+\\(?:Resent-\\)?\\(?:From\\|Cc\\|To\\|Bcc\\|\\(?:In-\\)?Reply-To\\|Sender\
+\\|Mail-Followup-To\\|Mail-Copies-To\\|Approved\\):")
+ (funcall gnus-decode-address-function start end)
+ (funcall gnus-decode-header-function start end))
+ (goto-char (setq end start)))))
(defun article-decode-group-name ()
"Decode group names in `Newsgroups:'."
(setq type
(gnus-fetch-field "content-transfer-encoding"))
(let* ((ct (gnus-fetch-field "content-type"))
- (ctl (and ct
- (ignore-errors
- (mail-header-parse-content-type ct)))))
+ (ctl (and ct (mail-header-parse-content-type ct))))
(setq charset (and ctl
(mail-content-type-get ctl 'charset)))
(if (stringp charset)
(setq type
(gnus-fetch-field "content-transfer-encoding"))
(let* ((ct (gnus-fetch-field "content-type"))
- (ctl (and ct
- (ignore-errors
- (mail-header-parse-content-type ct)))))
+ (ctl (and ct (mail-header-parse-content-type ct))))
(setq charset (and ctl
(mail-content-type-get ctl 'charset)))
(if (stringp charset)
(when (gnus-buffer-live-p gnus-original-article-buffer)
(with-current-buffer gnus-original-article-buffer
(let* ((ct (gnus-fetch-field "content-type"))
- (ctl (and ct
- (ignore-errors
- (mail-header-parse-content-type ct)))))
+ (ctl (and ct (mail-header-parse-content-type ct))))
(setq charset (and ctl
(mail-content-type-get ctl 'charset)))
(when (stringp charset)
(defun gnus-article-wash-html-with-w3m-standalone ()
"Wash the current buffer with w3m."
- (unless (mm-coding-system-p charset)
- ;; The default.
- (setq charset 'iso-8859-1))
- (let ((coding-system-for-write charset)
- (coding-system-for-read charset))
- (call-process-region
- (point-min) (point-max)
- "w3m" t t nil "-dump" "-T" "text/html"
- "-I" (symbol-name charset) "-O" (symbol-name charset))))
+ (if (mm-w3m-standalone-supports-m17n-p)
+ (progn
+ (unless (mm-coding-system-p charset) ;; Bound by `article-wash-html'.
+ ;; The default.
+ (setq charset 'iso-8859-1))
+ (let ((coding-system-for-write charset)
+ (coding-system-for-read charset))
+ (call-process-region
+ (point-min) (point-max)
+ "w3m" t t nil "-dump" "-T" "text/html"
+ "-I" (symbol-name charset) "-O" (symbol-name charset))))
+ (mm-inline-wash-with-stdin nil "w3m" "-dump" "-T" "text/html")))
(defun article-hide-list-identifiers ()
"Remove list identifies from the Subject header.
(article-really-strip-banner
(gnus-parameter-banner gnus-newsgroup-name)))
(when gnus-article-address-banner-alist
- (article-really-strip-banner
- (let ((from (save-restriction
- (widen)
- (article-narrow-to-head)
- (mail-fetch-field "from"))))
- (when (and from
- (setq from
- (caar (mail-header-parse-addresses from))))
- (catch 'found
- (dolist (pair gnus-article-address-banner-alist)
- (when (string-match (car pair) from)
- (throw 'found (cdr pair)))))))))))))
+ ;; Note that the From header is decoded here, so it is
+ ;; required that the *-extract-address-components function
+ ;; supports non-ASCII text.
+ (let ((from (save-restriction
+ (widen)
+ (article-narrow-to-head)
+ (mail-fetch-field "from"))))
+ (when (and from
+ (setq from
+ (cadr (funcall gnus-extract-address-components
+ from))))
+ (catch 'found
+ (dolist (pair gnus-article-address-banner-alist)
+ (when (string-match (car pair) from)
+ (throw 'found
+ (article-really-strip-banner (cdr pair)))))))))))))
(defun article-really-strip-banner (banner)
"Strip the banner specified by the argument."
(defun gnus-article-save (save-buffer file &optional num)
"Save the currently selected article."
- (unless gnus-save-all-headers
- ;; Remove headers according to `gnus-saved-headers'.
+ (when (or (get gnus-default-article-saver :headers)
+ (not gnus-save-all-headers))
+ ;; Remove headers according to `gnus-saved-headers' or the value
+ ;; of the `:headers' property that the saver function might have.
(let ((gnus-visible-headers
- (or gnus-saved-headers gnus-visible-headers))
+ (or (symbol-value (get gnus-default-article-saver :headers))
+ gnus-saved-headers gnus-visible-headers))
(gnus-article-buffer save-buffer))
(save-excursion
(set-buffer save-buffer)
(funcall gnus-default-article-saver filename)))))
(defun gnus-read-save-file-name (prompt &optional filename
- function group headers variable)
+ function group headers variable
+ dir-var)
(let ((default-name
(funcall function group headers (symbol-value variable)))
result)
default-name)
(filename filename)
(t
+ (when (symbol-value dir-var)
+ (setq default-name (expand-file-name
+ (file-name-nondirectory default-name)
+ (symbol-value dir-var))))
(let* ((split-name (gnus-get-split-value gnus-split-methods))
(prompt
(format prompt
;; Possibly translate some characters.
(nnheader-translate-file-chars file))))))
(gnus-make-directory (file-name-directory result))
- (set variable result)))
+ (when variable
+ (set variable result))
+ (when dir-var
+ (set dir-var (file-name-directory result)))
+ result))
(defun gnus-article-archive-name (group)
"Return the first instance of an \"Archive-name\" in the current buffer."
(gnus-output-to-mail filename)))))
filename)
+(put 'gnus-summary-save-in-file :decode t)
+(put 'gnus-summary-save-in-file :headers 'gnus-saved-headers)
(defun gnus-summary-save-in-file (&optional filename overwrite)
"Append this article to file.
Optional argument FILENAME specifies file name.
(gnus-output-to-file filename))))
filename)
+(put 'gnus-summary-write-to-file :decode t)
+(put 'gnus-summary-write-to-file :function 'gnus-summary-save-in-file)
+(put 'gnus-summary-write-to-file :headers 'gnus-saved-headers)
(defun gnus-summary-write-to-file (&optional filename)
"Write this article to a file, overwriting it if the file exists.
Optional argument FILENAME specifies file name.
The directory to save in defaults to `gnus-article-save-directory'."
- (gnus-summary-save-in-file nil t))
+ (setq filename (gnus-read-save-file-name
+ "Save %s in file" filename
+ gnus-file-save-name gnus-newsgroup-name
+ gnus-current-headers nil 'gnus-newsgroup-last-directory))
+ (gnus-summary-save-in-file filename t))
-(defun gnus-summary-save-body-in-file (&optional filename)
+(put 'gnus-summary-save-body-in-file :decode t)
+(defun gnus-summary-save-body-in-file (&optional filename overwrite)
"Append this article body to a file.
Optional argument FILENAME specifies file name.
The directory to save in defaults to `gnus-article-save-directory'."
(widen)
(when (article-goto-body)
(narrow-to-region (point) (point-max)))
+ (when (and overwrite
+ (file-exists-p filename))
+ (delete-file filename))
(gnus-output-to-file filename))))
filename)
+(put 'gnus-summary-write-body-to-file :decode t)
+(put 'gnus-summary-write-body-to-file
+ :function 'gnus-summary-save-body-in-file)
+(defun gnus-summary-write-body-to-file (&optional filename)
+ "Write this article body to a file, overwriting it if the file exists.
+Optional argument FILENAME specifies file name.
+The directory to save in defaults to `gnus-article-save-directory'."
+ (setq filename (gnus-read-save-file-name
+ "Save %s body in file" filename
+ gnus-file-save-name gnus-newsgroup-name
+ gnus-current-headers nil 'gnus-newsgroup-last-directory))
+ (gnus-summary-save-body-in-file filename t))
+
(defun gnus-summary-save-in-pipe (&optional command)
"Pipe this article to subprocess."
(setq command
(make-local-variable 'gnus-article-ignored-charsets)
;; Prevent recent Emacsen from displaying non-break space as "\ ".
(set (make-local-variable 'nobreak-char-display) nil)
+ (setq cursor-in-non-selected-windows nil)
(gnus-set-default-directory)
(buffer-disable-undo)
(setq buffer-read-only t)
(mm-enable-multibyte)
(gnus-run-mode-hooks 'gnus-article-mode-hook))
+;; Internal variables. Are `gnus-button-regexp' and `gnus-button-last' used
+;; at all?
+(defvar gnus-button-regexp nil)
+(defvar gnus-button-marker-list nil
+ "Regexp matching any of the regexps from `gnus-button-alist'.")
+(defvar gnus-button-last nil
+ "The value of `gnus-button-alist' when `gnus-button-regexp' was build.")
+
(defun gnus-article-setup-buffer ()
"Initialize the article buffer."
(let* ((name (if gnus-single-article-buffer "*Article*"
(insert "Content-Type: " (mm-handle-media-type data))
(mml-insert-parameter-string (cdr (mm-handle-type data))
'(charset))
+ ;; Add a filename for the sake of saving the part again.
+ (mml-insert-parameter
+ (mail-header-encode-parameter "name" (file-name-nondirectory file)))
(insert "\n")
(insert "Content-ID: " (message-make-message-id) "\n")
(insert "Content-Transfer-Encoding: binary\n")
(handles gnus-article-mime-handles)
(none "(none)")
(description
- (or
- (mail-decode-encoded-word-string (or (mm-handle-description data)
- none))))
+ (mail-decode-encoded-word-string (or (mm-handle-description data)
+ none)))
(filename
(or (mail-content-type-get (mm-handle-disposition data) 'filename)
none))
(defun gnus-mime-view-part-as-type-internal ()
(gnus-article-check-buffer)
- (let* ((name (mail-content-type-get
- (mm-handle-type (get-text-property (point) 'gnus-data))
- 'name))
+ (let* ((handle (get-text-property (point) 'gnus-data))
+ (name (or
+ ;; Content-Type: foo/bar; name=...
+ (mail-content-type-get (mm-handle-type handle) 'name)
+ ;; Content-Disposition: attachment; filename=...
+ (cdr (assq 'filename (cdr (mm-handle-disposition handle))))))
(def-type (and name (mm-default-file-encoding name))))
(and def-type (cons def-type 0))))
-(defun gnus-mime-view-part-as-type (&optional mime-type)
- "Choose a MIME media type, and view the part as such."
+(defun gnus-mime-view-part-as-type (&optional mime-type pred)
+ "Choose a MIME media type, and view the part as such.
+If non-nil, PRED is a predicate to use during completion to limit the
+available media-types."
(interactive)
(unless mime-type
- (setq mime-type (completing-read
- "View as MIME type: "
- (mapcar #'list (mailcap-mime-types))
- nil nil
- (gnus-mime-view-part-as-type-internal))))
+ (setq mime-type
+ (let ((default (gnus-mime-view-part-as-type-internal)))
+ (completing-read
+ (format "View as MIME type (default %s): "
+ (car default))
+ (mapcar #'list (mailcap-mime-types))
+ pred nil nil nil
+ (car default)))))
(gnus-article-check-buffer)
(let ((handle (get-text-property (point) 'gnus-data)))
(when handle
+ (when (equal (mm-handle-media-type handle) "message/external-body")
+ (unless (mm-handle-cache handle)
+ (mm-extern-cache-contents handle))
+ (setq handle (mm-handle-cache handle)))
(setq handle
(mm-make-handle (mm-handle-buffer handle)
(cons mime-type (cdr (mm-handle-type handle)))
specified charset."
(interactive (list nil current-prefix-arg))
(gnus-article-check-buffer)
- (let* ((handle (or handle (get-text-property (point) 'gnus-data)))
- contents charset
- (b (point))
- (inhibit-read-only t))
+ (let ((handle (or handle (get-text-property (point) 'gnus-data)))
+ (fun (get-text-property (point) 'gnus-callback))
+ (gnus-newsgroup-ignored-charsets 'gnus-all)
+ gnus-newsgroup-charset type charset)
(when handle
(if (mm-handle-undisplayer handle)
(mm-remove-part handle))
- (let ((gnus-newsgroup-charset
- (or (cdr (assq arg
- gnus-summary-show-article-charset-alist))
- (mm-read-coding-system "Charset: ")))
- (gnus-newsgroup-ignored-charsets 'gnus-all))
- (gnus-article-press-button)))))
+ (when fun
+ (setq gnus-newsgroup-charset
+ (or (cdr (assq arg gnus-summary-show-article-charset-alist))
+ (mm-read-coding-system "Charset: ")))
+ ;; Strip the charset parameter from `handle'.
+ (setq type (mm-handle-type
+ (if (equal (mm-handle-media-type handle)
+ "message/external-body")
+ (progn
+ (unless (mm-handle-cache handle)
+ (mm-extern-cache-contents handle))
+ (mm-handle-cache handle))
+ handle))
+ charset (assq 'charset (cdr type)))
+ (delq charset type)
+ (funcall fun handle)))))
(defun gnus-mime-view-part-externally (&optional handle)
"View the MIME part under point with an external viewer."
(mm-inlined-types nil)
(mail-parse-charset gnus-newsgroup-charset)
(mail-parse-ignored-charsets
- (save-excursion (set-buffer gnus-summary-buffer)
- gnus-newsgroup-ignored-charsets)))
- (when handle
- (if (mm-handle-undisplayer handle)
- (mm-remove-part handle)
- (mm-display-part handle)))))
+ (with-current-buffer gnus-summary-buffer
+ gnus-newsgroup-ignored-charsets))
+ (type (mm-handle-media-type handle))
+ (method (mailcap-mime-info type))
+ (mm-enable-external t))
+ (if (not (stringp method))
+ (gnus-mime-view-part-as-type
+ nil (lambda (type) (stringp (mailcap-mime-info type))))
+ (when handle
+ (if (mm-handle-undisplayer handle)
+ (mm-remove-part handle)
+ (mm-display-part handle))))))
(defun gnus-mime-view-part-internally (&optional handle)
"View the MIME part under point with an internal viewer.
(mm-inline-large-images t)
(mail-parse-charset gnus-newsgroup-charset)
(mail-parse-ignored-charsets
- (save-excursion (set-buffer gnus-summary-buffer)
- gnus-newsgroup-ignored-charsets))
+ (with-current-buffer gnus-summary-buffer
+ gnus-newsgroup-ignored-charsets))
(inhibit-read-only t))
- (when handle
- (if (mm-handle-undisplayer handle)
- (mm-remove-part handle)
- (mm-display-part handle)))))
+ (if (not (mm-inlinable-p handle))
+ (gnus-mime-view-part-as-type
+ nil (lambda (type) (mm-inlinable-p handle type)))
+ (when handle
+ (if (mm-handle-undisplayer handle)
+ (mm-remove-part handle)
+ (mm-display-part handle))))))
(defun gnus-mime-action-on-part (&optional action)
"Do something with the MIME attachment at \(point\)."
(article-goto-body)
(narrow-to-region (point-min) (point))
(gnus-article-save-original-date
- (gnus-treat-article 'head)))))))))
+ (gnus-treat-article 'head)))))))
+ ;; Cope with broken MIME messages.
+ (goto-char (point-max))
+ (unless (bolp)
+ (insert "\n"))))
(defcustom gnus-mime-display-multipart-as-mixed nil
"Display \"multipart\" parts as \"multipart/mixed\".
(let ((id (1+ (length gnus-article-mime-handle-alist)))
beg)
(push (cons id handle) gnus-article-mime-handle-alist)
+ (when (and display
+ (equal (mm-handle-media-supertype handle) "message"))
+ (insert-char
+ ?\n
+ (cond ((not (bolp)) 2)
+ ((or (bobp) (eq (char-before (1- (point))) ?\n)) 0)
+ (t 1))))
(when (or (not display)
(not (gnus-unbuttonized-mime-type-p type)))
- ;(gnus-article-insert-newline)
(gnus-insert-mime-button
handle id (list (or display (and not-attachment text))))
(gnus-article-insert-newline)
- ;(gnus-article-insert-newline)
;; Remember modify the number of forward lines.
(setq move t))
(setq beg (point))
;;; Article savers.
(defun gnus-output-to-file (file-name)
- "Append the current article to a file named FILE-NAME."
- (let ((artbuf (current-buffer)))
+ "Append the current article to a file named FILE-NAME.
+If `gnus-article-save-coding-system' is non-nil, it is used to encode
+text and used as the value of the coding cookie which is added to the
+top of a file. Otherwise, this function saves a raw article without
+the coding cookie."
+ (let* ((artbuf (current-buffer))
+ (file-name-coding-system nnmail-pathname-coding-system)
+ (coding gnus-article-save-coding-system)
+ (coding-system-for-read (if coding
+ nil ;; Rely on the coding cookie.
+ mm-text-coding-system))
+ (coding-system-for-write (or coding
+ mm-text-coding-system-for-write
+ mm-text-coding-system))
+ (exists (file-exists-p file-name)))
(with-temp-buffer
+ (when exists
+ (insert-file-contents file-name)
+ (goto-char (point-min))
+ ;; Remove the existing coding cookie.
+ (when (looking-at "X-Gnus-Coding-System: .+\n\n")
+ (delete-region (match-beginning 0) (match-end 0))))
+ (goto-char (point-max))
(insert-buffer-substring artbuf)
;; Append newline at end of the buffer as separator, and then
;; save it to file.
(goto-char (point-max))
(insert "\n")
- (let ((file-name-coding-system nnmail-pathname-coding-system))
- (mm-append-to-file (point-min) (point-max) file-name))
- t)))
+ (when coding
+ ;; If the coding system is not suitable to encode the text,
+ ;; ask a user for a proper one.
+ (when (fboundp 'select-safe-coding-system)
+ (setq coding (coding-system-base
+ (save-window-excursion
+ (select-safe-coding-system (point-min) (point-max)
+ coding))))
+ (setq coding-system-for-write
+ (or (cdr (assq coding '((mule-utf-8 . utf-8))))
+ coding)))
+ (goto-char (point-min))
+ ;; Add the coding cookie.
+ (insert (format "X-Gnus-Coding-System: -*- coding: %s; -*-\n\n"
+ coding-system-for-write)))
+ (if exists
+ (progn
+ (write-region (point-min) (point-max) file-name nil 'no-message)
+ (message "Appended to %s" file-name))
+ (write-region (point-min) (point-max) file-name))))
+ t)
(defun gnus-narrow-to-page (&optional arg)
"Narrow the article buffer to a page.
(boundp 'gnus-article-boring-faces)
(symbol-value 'gnus-article-boring-faces))
(save-excursion
- (catch 'only-boring
- (while (re-search-forward "\\b\\w\\w" nil t)
- (forward-char -1)
- (when (not (gnus-intersection
- (gnus-faces-at (point))
- (symbol-value 'gnus-article-boring-faces)))
- (throw 'only-boring nil)))
- (throw 'only-boring t)))))
+ (let ((inhibit-point-motion-hooks t))
+ (catch 'only-boring
+ (while (re-search-forward "\\b\\w\\w" nil t)
+ (forward-char -1)
+ (when (not (gnus-intersection
+ (gnus-faces-at (point))
+ (symbol-value 'gnus-article-boring-faces)))
+ (throw 'only-boring nil)))
+ (throw 'only-boring t))))))
(defun gnus-article-refer-article ()
"Read article specified by message-id around point."
;; Regexp suggested by Felix Wiemann in <87oeuomcz9.fsf@news2.ososo.de>
(defcustom gnus-button-valid-localpart-regexp
- "[a-z0-9$%(*-=?[_][^<>\")!;:,{}\n\t ]*"
+ "[a-z0-9$%(*-=?[_][^<>\")!;:,{}\n\t @]*"
"Regular expression that matches a localpart of mail addresses or MIDs."
:version "22.1"
:group 'gnus-article-buttons
:inline t
(integer :tag "Regexp group")))))
-(defvar gnus-button-regexp nil)
-(defvar gnus-button-marker-list nil)
-;; Regexp matching any of the regexps from `gnus-button-alist'.
-
-(defvar gnus-button-last nil)
-;; The value of `gnus-button-alist' when `gnus-button-regexp' was build.
-
;;; Commands:
(defun gnus-article-push-button (event)