-;;; gnus-sum.el --- summary mode commands for Gnus
+;;; gnus-sum.el --- summary mode commands for Semi-gnus
;; Copyright (C) 1996,97,98 Free Software Foundation, Inc.
;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
-;; Keywords: news
+;; MORIOKA Tomohiko <morioka@jaist.ac.jp>
+;; Keywords: mail, news, MIME
;; This file is part of GNU Emacs.
(require 'gnus-int)
(require 'gnus-undo)
(require 'gnus-util)
+(require 'mime-view)
+
(autoload 'gnus-summary-limit-include-cached "gnus-cache" nil t)
+(autoload 'gnus-set-summary-default-charset "gnus-i18n" nil t)
(defcustom gnus-kill-summary-on-exit t
"*If non-nil, kill the summary buffer when you exit from it.
(defcustom gnus-auto-select-first t
"*If nil, don't select the first unread article when entering a group.
If this variable is `best', select the highest-scored unread article
-in the group. If neither nil nor `best', select the first unread
-article.
+in the group. If t, select the first unread article.
+
+This variable can also be a function to place point on a likely
+subject line. Useful values include `gnus-summary-first-unread-subject',
+`gnus-summary-first-unread-article' and
+`gnus-summary-best-unread-article'.
If you want to prevent automatic selection of the first unread article
in some newsgroups, set the variable to nil in
:group 'gnus-group-select
:type '(choice (const :tag "none" nil)
(const best)
- (sexp :menu-tag "first" t)))
+ (sexp :menu-tag "first" t)
+ (function-item gnus-summary-first-unread-subject)
+ (function-item gnus-summary-first-unread-article)
+ (function-item gnus-summary-best-unread-article)))
(defcustom gnus-auto-select-next t
"*If non-nil, offer to go to the next group from the end of the previous.
"*If non-nil, ignore articles with identical Message-ID headers."
:group 'gnus-summary
:type 'boolean)
-
+
(defcustom gnus-single-article-buffer t
"*If non-nil, display all articles in the same buffer.
If nil, each group will get its own article buffer."
:group 'gnus-article-various
:type 'boolean)
-(defcustom gnus-show-mime nil
+(defcustom gnus-show-mime t
"*If non-nil, do mime processing of articles.
The articles will simply be fed to the function given by
-`gnus-show-mime-method'."
+`gnus-article-display-method-for-mime'."
:group 'gnus-article-mime
:type 'boolean)
:group 'gnus-summary-visual
:type 'hook)
-(defcustom gnus-parse-headers-hook nil
+(defcustom gnus-structured-field-decoder
+ #'eword-decode-and-unfold-structured-field
+ "Function to decode non-ASCII characters in structured field for summary."
+ :group 'gnus-various
+ :type 'function)
+
+(defcustom gnus-unstructured-field-decoder
+ (function
+ (lambda (string)
+ (eword-decode-unstructured-field-body
+ (std11-unfold-string string) 'must-unfold)
+ ))
+ "Function to decode non-ASCII characters in unstructured field for summary."
+ :group 'gnus-various
+ :type 'function)
+
+(defcustom gnus-parse-headers-hook
+ '(gnus-set-summary-default-charset)
"*A hook called before parsing the headers."
:group 'gnus-various
:type 'hook)
;; Byte-compiler warning.
(defvar gnus-article-mode-map)
+;; MIME stuff.
+
+(defvar gnus-encoded-word-method-alist
+ '(("chinese" mail-decode-encoded-word-string rfc1843-decode-string)
+ (".*" mail-decode-encoded-word-string))
+ "Alist of regexps (to match group names) and lists of functions to be applied.")
+
+(defun gnus-multi-decode-encoded-word-string (string)
+ "Apply the functions from `gnus-encoded-word-method-alist' that match."
+ (let ((alist gnus-encoded-word-method-alist)
+ elem)
+ (while (setq elem (pop alist))
+ (when (string-match (car elem) gnus-newsgroup-name)
+ (pop elem)
+ (while elem
+ (setq string (funcall (pop elem) string)))
+ (setq alist nil)))
+ string))
+
;; Subject simplification.
(defun gnus-simplify-whitespace (str)
"t" gnus-article-hide-headers
"g" gnus-summary-show-article
"l" gnus-summary-goto-last-article
+ "v" gnus-summary-preview-mime-message
"\C-c\C-v\C-v" gnus-uu-decode-uu-view
"\C-d" gnus-summary-enter-digest-group
"\M-\C-d" gnus-summary-read-document
"L" gnus-summary-lower-score
"\M-i" gnus-symbolic-argument
"h" gnus-summary-select-article-buffer
+ "b" gnus-article-view-part
"V" gnus-summary-score-map
"X" gnus-uu-extract-map
"e" gnus-article-emphasize
"w" gnus-article-fill-cited-article
"c" gnus-article-remove-cr
- "q" gnus-article-de-quoted-unreadable
"f" gnus-article-display-x-face
"l" gnus-summary-stop-page-breaking
"r" gnus-summary-caesar-message
"c" gnus-article-highlight-citation
"s" gnus-article-highlight-signature)
- (gnus-define-keys (gnus-summary-wash-mime-map "M" gnus-summary-wash-map)
- "w" gnus-article-decode-mime-words
- "c" gnus-article-decode-charset)
-
(gnus-define-keys (gnus-summary-wash-time-map "T" gnus-summary-wash-map)
"z" gnus-article-date-ut
"u" gnus-article-date-ut
["Headers" gnus-article-highlight-headers t]
["Signature" gnus-article-highlight-signature t]
["Citation" gnus-article-highlight-citation t])
- ("MIME"
- ["Words" gnus-article-decode-mime-words t]
- ["Charset" gnus-article-decode-charset t]
- ["QP" gnus-article-de-quoted-unreadable t])
("Date"
["Local" gnus-article-date-local t]
["ISO8601" gnus-article-date-iso8601 t]
["Word wrap" gnus-article-fill-cited-article t]
["CR" gnus-article-remove-cr t]
["Show X-Face" gnus-article-display-x-face t]
- ["Quoted-Printable" gnus-article-de-quoted-unreadable t]
["UnHTMLize" gnus-article-treat-html t]
["Rot 13" gnus-summary-caesar-message t]
["Unix pipe" gnus-summary-pipe-message t]
["Wide reply and yank" gnus-summary-wide-reply-with-original t]
["Mail forward" gnus-summary-mail-forward t]
["Post forward" gnus-summary-post-forward t]
- ["Digest and mail" gnus-uu-digest-mail-forward t]
- ["Digest and post" gnus-uu-digest-post-forward t]
+ ["Digest and mail" gnus-summary-mail-digest t]
+ ["Digest and post" gnus-summary-post-digest t]
["Resend message" gnus-summary-resend-message t]
["Send bounced mail" gnus-summary-resend-bounced-mail t]
["Send a mail" gnus-summary-mail-other-window t]
(setq mode-name "Summary")
(make-local-variable 'minor-mode-alist)
(use-local-map gnus-summary-mode-map)
- (buffer-disable-undo (current-buffer))
+ (buffer-disable-undo)
(setq buffer-read-only t) ;Disable modification
(setq truncate-lines t)
(setq selective-display t)
(make-local-hook 'pre-command-hook)
(add-hook 'pre-command-hook 'gnus-set-global-variables nil t)
(gnus-run-hooks 'gnus-summary-mode-hook)
- (mm-enable-multibyte)
(gnus-update-format-specifications nil 'summary 'summary-mode 'summary-dummy)
(gnus-update-summary-mark-positions))
(setq gnus-tmp-name gnus-tmp-from))
(unless (numberp gnus-tmp-lines)
(setq gnus-tmp-lines 0))
- (gnus-put-text-property-excluding-characters-with-faces
+ (gnus-put-text-property
(point)
(progn (eval gnus-summary-line-format-spec) (point))
'gnus-number gnus-tmp-number)
(not no-display)
gnus-newsgroup-unreads
gnus-auto-select-first)
- (unless (if (eq gnus-auto-select-first 'best)
- (gnus-summary-best-unread-article)
- (gnus-summary-first-unread-article))
- (gnus-configure-windows 'summary))
+ (progn
+ (gnus-configure-windows 'summary)
+ (cond
+ ((eq gnus-auto-select-first 'best)
+ (gnus-summary-best-unread-article))
+ ((eq gnus-auto-select-first t)
+ (gnus-summary-first-unread-article))
+ ((gnus-functionp gnus-auto-select-first)
+ (funcall gnus-auto-select-first))))
;; Don't select any articles, just move point to the first
;; article in the group.
(goto-char (point-min))
(gnus-summary-position-point)
(gnus-configure-windows 'summary 'force)
- (gnus-set-mode-line 'summary))
+ (gnus-set-mode-line 'summary))
(when (get-buffer-window gnus-group-buffer t)
;; Gotta use windows, because recenter does weird stuff if
;; the current buffer ain't the displayed window.
(defsubst gnus-nov-parse-line (number dependencies &optional force-new)
(let ((eol (gnus-point-at-eol))
(buffer (current-buffer))
- header)
+ header rawtext decoded)
;; overview: [num subject from date id refs chars lines misc]
(unwind-protect
(setq header
(make-full-mail-header
number ; number
- (rfc2047-decode-string (gnus-nov-field)) ; subject
- (rfc2047-decode-string (gnus-nov-field)) ; from
+ (progn
+ (setq rawtext (gnus-nov-field) ; subject
+ decoded (funcall
+ gnus-unstructured-field-decoder rawtext))
+ (if (string= rawtext decoded)
+ rawtext
+ (put-text-property 0 (length decoded) 'raw-text rawtext decoded)
+ decoded))
+ (progn
+ (setq rawtext (gnus-nov-field) ; from
+ decoded (funcall
+ gnus-structured-field-decoder rawtext))
+ (if (string= rawtext decoded)
+ rawtext
+ (put-text-property 0 (length decoded) 'raw-text rawtext decoded)
+ decoded))
(gnus-nov-field) ; date
(or (gnus-nov-field)
(nnheader-generate-fake-message-id)) ; id
(setq gnus-tmp-name gnus-tmp-from))
(unless (numberp gnus-tmp-lines)
(setq gnus-tmp-lines 0))
- (gnus-put-text-property-excluding-characters-with-faces
+ (gnus-put-text-property
(point)
(progn (eval gnus-summary-line-format-spec) (point))
'gnus-number number)
;; Init the dependencies hash table.
(setq gnus-newsgroup-dependencies
(gnus-make-hashtable (length articles)))
+ (gnus-set-global-variables)
;; Retrieve the headers and read them in.
(gnus-message 5 "Fetching headers for %s..." gnus-newsgroup-name)
(setq gnus-newsgroup-headers
;; We might have to chop a bit of the string off...
(when (> (length mode-string) max-len)
(setq mode-string
- (concat (truncate-string mode-string (- max-len 3))
+ (concat (gnus-truncate-string mode-string (- max-len 3))
"...")))
;; Pad the mode string a bit.
(setq mode-string (format (format "%%-%ds" max-len) mode-string))))
;; Then we add the read articles to the range.
(gnus-add-to-range
ninfo (setq articles (sort articles '<))))))
-
+
(defun gnus-group-make-articles-read (group articles)
"Update the info of GROUP to say that ARTICLES are read."
(let* ((num 0)
(subst-char-in-region (point-min) (point-max) ?\t ? t)
(gnus-run-hooks 'gnus-parse-headers-hook)
(let ((case-fold-search t)
+ rawtext decoded
in-reply-to header p lines chars)
(goto-char (point-min))
;; Search to the beginning of the next header. Error messages
(progn
(goto-char p)
(if (search-forward "\nsubject: " nil t)
- (rfc2047-decode-string (nnheader-header-value))
+ (progn
+ (setq rawtext (nnheader-header-value)
+ decoded (funcall
+ gnus-unstructured-field-decoder rawtext))
+ (if (string-equal rawtext decoded)
+ rawtext
+ (put-text-property 0 (length decoded) 'raw-text rawtext decoded)
+ decoded))
"(none)"))
;; From.
(progn
(goto-char p)
(if (search-forward "\nfrom: " nil t)
- (rfc2047-decode-string (nnheader-header-value))
+ (progn
+ (setq rawtext (nnheader-header-value)
+ decoded (funcall
+ gnus-structured-field-decoder rawtext))
+ (if (string-equal rawtext decoded)
+ rawtext
+ (put-text-property 0 (length decoded) 'raw-text rawtext decoded)
+ decoded))
"(nobody)"))
;; Date.
(progn
number dependencies force-new))))
(push header headers))
(forward-line 1))
- ;(error
- ; (gnus-error 4 "Strange nov line (%d)"
- ; (count-lines (point-min) (point))))
- )
+ (error
+ (gnus-error 4 "Strange nov line (%d)"
+ (count-lines (point-min) (point)))))
(forward-line 1))
;; A common bug in inn is that if you have posted an article and
;; then retrieves the active file, it will answer correctly --
(let ((max (max (point) (mark)))
articles article)
(save-excursion
- (goto-char (min (min (point) (mark))))
+ (goto-char (min (point) (mark)))
(while
(and
(push (setq article (gnus-summary-article-number)) articles)
(gnus-update-read-articles
group (append gnus-newsgroup-unreads gnus-newsgroup-unselected))
;; Set the current article marks.
- (let ((gnus-newsgroup-scored
+ (let ((gnus-newsgroup-scored
(if (and (not gnus-save-score)
(not non-destructive))
nil
(gnus-summary-recenter)
(gnus-summary-position-point))))
+(defun gnus-summary-preview-mime-message (arg)
+ "MIME decode and play this message."
+ (interactive "P")
+ (or gnus-show-mime
+ (let ((gnus-break-pages nil)
+ (gnus-show-mime t))
+ (gnus-summary-select-article t t)
+ ))
+ (select-window (get-buffer-window gnus-article-buffer))
+ )
+
;;; Dead summaries.
(defvar gnus-dead-summary-mode-map nil)
(gnus-summary-display-article (gnus-summary-article-number)))
(gnus-summary-position-point)))
+(defun gnus-summary-first-unread-subject ()
+ "Place the point on the subject line of the first unread article.
+Return nil if there are no unread articles."
+ (interactive)
+ (prog1
+ (when (gnus-summary-first-subject t)
+ (gnus-summary-show-thread)
+ (gnus-summary-first-subject t))
+ (gnus-summary-position-point)))
+
(defun gnus-summary-first-article ()
"Select the first article.
Return nil if there are no articles."
(defsubst gnus-cut-thread (thread)
"Go forwards in the thread until we find an article that we want to display."
(when (or (eq gnus-fetch-old-headers 'some)
- (eq gnus-fetch-old-headers 'invisible)
+ (eq gnus-fetch-old-headers 'invisible)
(eq gnus-build-sparse-threads 'some)
(eq gnus-build-sparse-threads 'more))
;; Deal with old-fetched headers and sparse threads.
(set-buffer buffer)
(gnus-article-delete-invisible-text)
(let ((ps-left-header
- (list
+ (list
(concat "("
(mail-header-subject gnus-current-headers) ")")
(concat "("
(mail-header-from gnus-current-headers) ")")))
- (ps-right-header
- (list
- "/pagenumberstring load"
+ (ps-right-header
+ (list
+ "/pagenumberstring load"
(concat "("
(mail-header-date gnus-current-headers) ")"))))
(gnus-run-hooks 'gnus-ps-print-hook)
(let ((gnus-have-all-headers t)
gnus-article-display-hook
gnus-article-prepare-hook
+ gnus-article-decode-hook
gnus-break-pages
gnus-show-mime
gnus-visual)
(set-buffer copy-buf)
(when (gnus-request-article-this-buffer article gnus-newsgroup-name)
(gnus-request-accept-article
- to-newsgroup select-method (not articles)))))
+ to-newsgroup select-method (not articles) t))))
;; Crosspost the article.
((eq action 'crosspost)
(let ((xref (message-tokenize-header
;;;!!!Why is this necessary?
(set-buffer gnus-summary-buffer)
-
+
(gnus-summary-goto-subject article)
(when (eq action 'move)
(gnus-summary-mark-article article gnus-canceled-mark))))
(defcustom gnus-summary-respool-default-method nil
"Default method for respooling an article.
If nil, use to the current newsgroup method."
- :type `(choice (gnus-select-method :value (nnml ""))
+ :type '(choice (gnus-select-method :value (nnml ""))
(const nil))
:group 'gnus-summary-mail)
(error "Can't read %s" file))
(save-excursion
(set-buffer (gnus-get-buffer-create " *import file*"))
- (buffer-disable-undo (current-buffer))
(erase-buffer)
- (insert-file-contents file)
+ (nnheader-insert-file-contents file)
(goto-char (point-min))
(unless (nnheader-article-p)
;; This doesn't look like an article, so we fudge some headers.
(if (and (not read-only)
(not (gnus-request-replace-article
(cdr gnus-article-current) (car gnus-article-current)
- (current-buffer))))
+ (current-buffer)
+ (not gnus-article-decoded-p))))
(error "Couldn't replace article")
;; Update the summary buffer.
(if (and references
"Mark ARTICLE replied and update the summary line."
(push article gnus-newsgroup-replied)
(let ((buffer-read-only nil))
- (when (gnus-summary-goto-subject article)
+ (when (gnus-summary-goto-subject article nil t)
(gnus-summary-update-secondary-mark article))))
(defun gnus-summary-set-bookmark (article)
(gnus-summary-exit))
buffers)))))
+
+;;; @ for mime-partial
+;;;
+
+(defun gnus-request-partial-message ()
+ (save-excursion
+ (let ((number (gnus-summary-article-number))
+ (group gnus-newsgroup-name)
+ (mother gnus-article-buffer))
+ (set-buffer (get-buffer-create " *Partial Article*"))
+ (erase-buffer)
+ (setq mime-preview-buffer mother)
+ (gnus-request-article-this-buffer number group)
+ (mime-parse-buffer)
+ )))
+
+(autoload 'mime-combine-message/partial-pieces-automatically
+ "mime-partial"
+ "Internal method to combine message/partial messages automatically.")
+
+(mime-add-condition
+ 'action '((type . message)(subtype . partial)
+ (major-mode . gnus-original-article-mode)
+ (method . mime-combine-message/partial-pieces-automatically)
+ (summary-buffer-exp . gnus-summary-buffer)
+ (request-partial-message-method . gnus-request-partial-message)
+ ))
+
+
+;;; @ end
+;;;
+
(gnus-ems-redefine)
(provide 'gnus-sum)