Update to Semi-gnus 6.4.0
[elisp/gnus.git-] / lisp / gnus-art.el
index 7c36420..c00d305 100644 (file)
@@ -1,8 +1,9 @@
-;;; gnus-art.el --- article mode commands for Gnus
+;;; gnus-art.el --- article mode commands for Semi-gnus
 ;; Copyright (C) 1996,97,98 Free Software Foundation, Inc.
 
-;; Author: Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
-;; Keywords: news
+;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
+;;         MORIOKA Tomohiko <morioka@jaist.ac.jp>
+;; Keywords: mail, news, MIME
 
 ;; This file is part of GNU Emacs.
 
@@ -33,6 +34,8 @@
 (require 'gnus-spec)
 (require 'gnus-int)
 (require 'browse-url)
+(require 'alist)
+(require 'mime-view)
 
 (defgroup gnus-article nil
   "Article display."
@@ -104,7 +107,7 @@ If `gnus-visible-headers' is non-nil, this variable will be ignored."
   :group 'gnus-article-hiding)
 
 (defcustom gnus-visible-headers
-  "^From:\\|^Newsgroups:\\|^Subject:\\|^Date:\\|^Followup-To:\\|^Reply-To:\\|^Organization:\\|^Summary:\\|^Keywords:\\|^To:\\|^Cc:\\|^Posted-To:\\|^Mail-Copies-To:\\|^Apparently-To:\\|^Gnus-Warning:\\|^Resent-From:\\|X-Sent:"
+  "From:\\|^Newsgroups:\\|^Subject:\\|^Date:\\|^Followup-To:\\|^Reply-To:\\|^Organization:\\|^Summary:\\|^Keywords:\\|^To:\\|^Cc:\\|^Posted-To:\\|^Mail-Copies-To:\\|^Apparently-To:\\|^Gnus-Warning:\\|^Resent-From:\\|X-Sent:"
   "*All headers that do not match this regexp will be hidden.
 This variable can also be a list of regexp of headers to remain visible.
 If this variable is non-nil, `gnus-ignored-headers' will be ignored."
@@ -127,7 +130,7 @@ this list."
   :group 'gnus-article-hiding)
 
 (defcustom gnus-boring-article-headers '(empty followup-to reply-to)
-  "*Headers that are only to be displayed if they have interesting data.
+  "Headers that are only to be displayed if they have interesting data.
 Possible values in this list are `empty', `newsgroups', `followup-to',
 `reply-to', `date', `long-to', and `many-to'."
   :type '(set (const :tag "Headers with no content." empty)
@@ -140,7 +143,7 @@ Possible values in this list are `empty', `newsgroups', `followup-to',
   :group 'gnus-article-hiding)
 
 (defcustom gnus-signature-separator '("^-- $" "^-- *$")
-  "*Regexp matching signature separator.
+  "Regexp matching signature separator.
 This can also be a list of regexps.  In that case, it will be checked
 from head to tail looking for a separator.  Searches will be done from
 the end of the buffer."
@@ -148,7 +151,7 @@ the end of the buffer."
   :group 'gnus-article-signature)
 
 (defcustom gnus-signature-limit nil
-   "*Provide a limit to what is considered a signature.
+   "Provide a limit to what is considered a signature.
 If it is a number, no signature may not be longer (in characters) than
 that number.  If it is a floating point number, no signature may be
 longer (in lines) than that number.  If it is a function, the function
@@ -162,7 +165,7 @@ regexp.  If it matches, the text in question is not a signature."
   :group 'gnus-article-signature)
 
 (defcustom gnus-hidden-properties '(invisible t intangible t)
-  "*Property list to use for hiding text."
+  "Property list to use for hiding text."
   :type 'sexp
   :group 'gnus-article-hiding)
 
@@ -175,7 +178,7 @@ asynchronously.      The compressed face will be piped to this command."
   :group 'gnus-article-washing)
 
 (defcustom gnus-article-x-face-too-ugly nil
-  "*Regexp matching posters whose face shouldn't be shown automatically."
+  "Regexp matching posters whose face shouldn't be shown automatically."
   :type '(choice regexp (const nil))
   :group 'gnus-article-washing)
 
@@ -196,7 +199,7 @@ asynchronously.      The compressed face will be piped to this command."
         (lambda (spec)
           (list
            (format format (car spec) (cadr spec))
-           2 3 (intern (format "gnus-emphasis-%s" (caddr spec)))))
+           2 3 (intern (format "gnus-emphasis-%s" (nth 2 spec)))))
         types)))
   "*Alist that says how to fontify certain phrases.
 Each item looks like this:
@@ -246,7 +249,7 @@ Esample: (_/*word*/_)."
   :group 'gnus-article-emphasis)
 
 (defcustom gnus-article-time-format "%a, %b %d %Y %T %Z"
-  "*Format for display of Date headers in article bodies.
+  "Format for display of Date headers in article bodies.
 See `format-time-string' for the possible values.
 
 The variable can also be function, which should return a complete Date
@@ -280,7 +283,7 @@ each invocation of the saving commands."
                 (sexp :tag "once" :format "%t\n" :value t)))
 
 (defcustom gnus-saved-headers gnus-visible-headers
-  "*Headers to keep if `gnus-save-all-headers' is nil.
+  "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."
@@ -288,7 +291,7 @@ will be kept while the rest will be deleted before saving."
   :type 'regexp)
 
 (defcustom gnus-default-article-saver 'gnus-summary-save-in-rmail
-  "*A function to save articles in your favourite format.
+  "A function to save articles in your favourite format.
 The function must be interactively callable (in other words, it must
 be an Emacs command).
 
@@ -309,25 +312,25 @@ Gnus provides the following functions:
                (function-item gnus-summary-write-to-file)))
 
 (defcustom gnus-rmail-save-name 'gnus-plain-save-name
-  "*A function generating a file name to save articles in Rmail format.
+  "A function generating a file name to save articles in Rmail format.
 The function is called with NEWSGROUP, HEADERS, and optional LAST-FILE."
   :group 'gnus-article-saving
   :type 'function)
 
 (defcustom gnus-mail-save-name 'gnus-plain-save-name
-  "*A function generating a file name to save articles in Unix mail format.
+  "A function generating a file name to save articles in Unix mail format.
 The function is called with NEWSGROUP, HEADERS, and optional LAST-FILE."
   :group 'gnus-article-saving
   :type 'function)
 
 (defcustom gnus-folder-save-name 'gnus-folder-save-name
-  "*A function generating a file name to save articles in MH folder.
+  "A function generating a file name to save articles in MH folder.
 The function is called with NEWSGROUP, HEADERS, and optional LAST-FOLDER."
   :group 'gnus-article-saving
   :type 'function)
 
 (defcustom gnus-file-save-name 'gnus-numeric-save-name
-  "*A function generating a file name to save articles in article format.
+  "A function generating a file name to save articles in article format.
 The function is called with NEWSGROUP, HEADERS, and optional
 LAST-FILE."
   :group 'gnus-article-saving
@@ -365,13 +368,13 @@ be used as possible file names."
   :group 'gnus-article-mime
   :type 'boolean)
 
-(defcustom gnus-show-mime-method 'metamail-buffer
-  "*Function to process a MIME message.
+(defcustom gnus-show-mime-method 'gnus-article-preview-mime-message
+  "Function to process a MIME message.
 The function is called from the article buffer."
   :group 'gnus-article-mime
   :type 'function)
 
-(defcustom gnus-decode-encoded-word-method 'gnus-article-de-quoted-unreadable
+(defcustom gnus-decode-encoded-word-method 'gnus-article-decode-encoded-word
   "*Function to decode MIME encoded words.
 The function is called from the article buffer."
   :group 'gnus-article-mime
@@ -412,7 +415,7 @@ If you want to run a special decoding program like nkf, use this hook."
   :group 'gnus-article-various)
 
 (defcustom gnus-article-button-face 'bold
-  "*Face used for highlighting buttons in the article buffer.
+  "Face used for highlighting buttons in the article buffer.
 
 An article button is a piece of text that you can activate by pressing
 `RET' or `mouse-2' above it."
@@ -420,7 +423,7 @@ An article button is a piece of text that you can activate by pressing
   :group 'gnus-article-buttons)
 
 (defcustom gnus-article-mouse-face 'highlight
-  "*Face used for mouse highlighting in the article buffer.
+  "Face used for mouse highlighting in the article buffer.
 
 Article buttons will be displayed in this face when the cursor is
 above them."
@@ -428,7 +431,7 @@ above them."
   :group 'gnus-article-buttons)
 
 (defcustom gnus-signature-face 'gnus-signature-face
-  "*Face used for highlighting a signature in the article buffer.
+  "Face used for highlighting a signature in the article buffer.
 Obsolete; use the face `gnus-signature-face' for customizations instead."
   :type 'face
   :group 'gnus-article-highlight
@@ -638,6 +641,7 @@ always hide."
       (save-excursion
        (save-restriction
          (let ((buffer-read-only nil)
+               (case-fold-search t)
                (props (nconc (list 'article-type 'headers)
                              gnus-hidden-properties))
                (max (1+ (length gnus-sorted-header-list)))
@@ -923,84 +927,14 @@ characters to translate to."
                  (process-send-region "article-x-face" beg end)
                  (process-send-eof "article-x-face"))))))))))
 
-(defun gnus-hack-decode-rfc1522 ()
-  "Emergency hack function for avoiding problems when decoding."
-  (let ((buffer-read-only nil))
-    (goto-char (point-min))
-    ;; Remove encoded TABs.
-    (while (search-forward "=09" nil t)
-      (replace-match " " t t))
-    ;; Remove encoded newlines.
-    (goto-char (point-min))
-    (while (search-forward "=10" nil t)
-      (replace-match " " t t))))
-
-(defalias 'gnus-decode-rfc1522 'article-decode-rfc1522)
-(defalias 'gnus-article-decode-rfc1522 'article-decode-rfc1522)
-(defun article-decode-rfc1522 ()
-  "Hack to remove QP encoding from headers."
-  (let ((case-fold-search t)
-       (inhibit-point-motion-hooks t)
-       (buffer-read-only nil)
-       string)
-    (save-restriction
-      (narrow-to-region
-       (goto-char (point-min))
-       (or (search-forward "\n\n" nil t) (point-max)))
-      (goto-char (point-min))
-      (while (re-search-forward
-             "=\\?iso-8859-1\\?q\\?\\([^?\t\n]*\\)\\?=" nil t)
-       (setq string (match-string 1))
-       (save-restriction
-         (narrow-to-region (match-beginning 0) (match-end 0))
-         (delete-region (point-min) (point-max))
-         (insert string)
-         (article-mime-decode-quoted-printable
-          (goto-char (point-min)) (point-max))
-         (subst-char-in-region (point-min) (point-max) ?_ ? )
-         (goto-char (point-max)))
-       (goto-char (point-min))))))
-
-(defun article-de-quoted-unreadable (&optional force)
-  "Do a naive translation of a quoted-printable-encoded article.
-This is in no way, shape or form meant as a replacement for real MIME
-processing, but is simply a stop-gap measure until MIME support is
-written.
-If FORCE, decode the article whether it is marked as quoted-printable
-or not."
-  (interactive (list 'force))
-  (save-excursion
-    (let ((case-fold-search t)
-         (buffer-read-only nil)
-         (type (gnus-fetch-field "content-transfer-encoding")))
-      (gnus-article-decode-rfc1522)
-      (when (or force
-               (and type (string-match "quoted-printable" (downcase type))))
-       (goto-char (point-min))
-       (search-forward "\n\n" nil 'move)
-       (article-mime-decode-quoted-printable (point) (point-max))))))
-
-(defun article-mime-decode-quoted-printable-buffer ()
-  "Decode Quoted-Printable in the current buffer."
-  (article-mime-decode-quoted-printable (point-min) (point-max)))
-
-(defun article-mime-decode-quoted-printable (from to)
-  "Decode Quoted-Printable in the region between FROM and TO."
-  (interactive "r")
-  (goto-char from)
-  (while (search-forward "=" to t)
-    (cond ((eq (following-char) ?\n)
-          (delete-char -1)
-          (delete-char 1))
-         ((looking-at "[0-9A-F][0-9A-F]")
-          (subst-char-in-region
-           (1- (point)) (point) ?=
-           (hexl-hex-string-to-integer
-            (buffer-substring (point) (+ 2 (point)))))
-          (delete-char 2))
-         ((looking-at "=")
-          (delete-char 1))
-         ((gnus-message 3 "Malformed MIME quoted-printable message")))))
+(defun gnus-article-decode-rfc1522 ()
+  "Decode MIME encoded-words in header fields."
+  (let (buffer-read-only)
+    (let ((charset (save-excursion
+                    (set-buffer gnus-summary-buffer)
+                    default-mime-charset)))
+      (eword-decode-header charset)
+      )))
 
 (defun article-hide-pgp (&optional arg)
   "Toggle hiding of any PGP headers and signatures in the current article.
@@ -1449,13 +1383,14 @@ function and want to see what the date was before converting."
 
 (defun article-update-date-lapsed ()
   "Function to be run from a timer to update the lapsed time line."
-  (save-excursion
-    (ignore-errors
-      (when (gnus-buffer-live-p gnus-article-buffer)
-       (set-buffer gnus-article-buffer)
-       (goto-char (point-min))
-       (when (re-search-forward "^X-Sent:" nil t)
-         (article-date-lapsed t))))))
+  (let (deactivate-mark)
+    (save-excursion
+      (ignore-errors
+        (when (gnus-buffer-live-p gnus-article-buffer)
+          (set-buffer gnus-article-buffer)
+          (goto-char (point-min))
+          (when (re-search-forward "^X-Sent:" nil t)
+            (article-date-lapsed t)))))))
 
 (defun gnus-start-date-timer (&optional n)
   "Start a timer to update the X-Sent header in the article buffers.
@@ -1650,7 +1585,6 @@ This format is defined by the `gnus-article-time-format' variable."
   "Append this article to Rmail file.
 Optional argument FILENAME specifies file name.
 Directory to save to is default to `gnus-article-save-directory'."
-  (interactive)
   (setq filename (gnus-read-save-file-name
                  "Save %s in rmail file:" filename
                  gnus-rmail-save-name gnus-newsgroup-name
@@ -1666,7 +1600,6 @@ Directory to save to is default to `gnus-article-save-directory'."
   "Append this article to Unix mail file.
 Optional argument FILENAME specifies file name.
 Directory to save to is default to `gnus-article-save-directory'."
-  (interactive)
   (setq filename (gnus-read-save-file-name
                  "Save %s in Unix mail file:" filename
                  gnus-mail-save-name gnus-newsgroup-name
@@ -1685,7 +1618,6 @@ Directory to save to is default to `gnus-article-save-directory'."
   "Append this article to file.
 Optional argument FILENAME specifies file name.
 Directory to save to is default to `gnus-article-save-directory'."
-  (interactive)
   (setq filename (gnus-read-save-file-name
                  "Save %s in file:" filename
                  gnus-file-save-name gnus-newsgroup-name
@@ -1704,14 +1636,12 @@ Directory to save to is default to `gnus-article-save-directory'."
   "Write this article to a file.
 Optional argument FILENAME specifies file name.
 The directory to save in defaults to `gnus-article-save-directory'."
-  (interactive)
   (gnus-summary-save-in-file nil t))
 
 (defun gnus-summary-save-body-in-file (&optional filename)
   "Append this article body to a file.
 Optional argument FILENAME specifies file name.
 The directory to save in defaults to `gnus-article-save-directory'."
-  (interactive)
   (setq filename (gnus-read-save-file-name
                  "Save %s body in file:" filename
                  gnus-file-save-name gnus-newsgroup-name
@@ -1728,7 +1658,6 @@ The directory to save in defaults to `gnus-article-save-directory'."
 
 (defun gnus-summary-save-in-pipe (&optional command)
   "Pipe this article to subprocess."
-  (interactive)
   (setq command
        (cond ((eq command 'default)
               gnus-last-shell-command)
@@ -1917,12 +1846,9 @@ If variable `gnus-use-long-file-name' is non-nil, it is
        ["Hide citation" gnus-article-hide-citation t]
        ["Treat overstrike" gnus-article-treat-overstrike t]
        ["Remove carriage return" gnus-article-remove-cr t]
-       ["Remove quoted-unreadable" gnus-article-de-quoted-unreadable t]))
+       ))
 
-    (when nil
-      (when (boundp 'gnus-summary-article-menu)
-       (define-key gnus-article-mode-map [menu-bar commands]
-         (cons "Commands" gnus-summary-article-menu))))
+    ;; Note "Commands" menu is defined in gnus-sum.el for consistency
 
     (when (boundp 'gnus-summary-post-menu)
       (define-key gnus-article-mode-map [menu-bar post]
@@ -1948,7 +1874,6 @@ commands:
   (interactive)
   (when (gnus-visual-p 'article-menu 'menu)
     (gnus-article-make-menu-bar))
-  (kill-all-local-variables)
   (gnus-simplify-mode-line)
   (setq mode-name "Article")
   (setq major-mode 'gnus-article-mode)
@@ -1958,9 +1883,9 @@ commands:
   (use-local-map gnus-article-mode-map)
   (gnus-update-format-specifications nil 'article-mode)
   (set (make-local-variable 'page-delimiter) gnus-page-delimiter)
-  (set (make-local-variable 'gnus-page-broken) nil)
-  (set (make-local-variable 'gnus-button-marker-list) nil)
-  (set (make-local-variable 'gnus-article-current-summary) nil)
+  (make-local-variable 'gnus-page-broken) 
+  (make-local-variable 'gnus-button-marker-list) 
+  (make-local-variable 'gnus-article-current-summary) 
   (gnus-set-default-directory)
   (buffer-disable-undo (current-buffer))
   (setq buffer-read-only t)
@@ -2022,6 +1947,41 @@ commands:
        (forward-line line)
        (point)))))
 
+;;; @@ article filters
+;;;
+
+(defun gnus-article-preview-mime-message ()
+  (make-local-variable 'mime-button-mother-dispatcher)
+  (setq mime-button-mother-dispatcher
+       (function gnus-article-push-button))
+  (let ((default-mime-charset
+         (save-excursion
+           (set-buffer gnus-summary-buffer)
+           default-mime-charset))
+       )
+    (save-excursion
+      (mime-view-mode nil nil nil gnus-original-article-buffer
+                     gnus-article-buffer
+                     gnus-article-mode-map)
+      ))
+  (run-hooks 'gnus-mime-article-prepare-hook)
+  )
+
+(defun gnus-article-decode-encoded-word ()
+  "Header filter for gnus-article-mode.
+It is registered to variable `mime-view-content-header-filter-alist'."
+  (let ((charset (save-excursion
+                  (set-buffer gnus-summary-buffer)
+                  default-mime-charset)))
+    (eword-decode-header charset)
+    (goto-char (point-min))
+    (if (search-forward "\n\n" nil t)
+       (decode-mime-charset-region (match-end 0) (point-max) charset))
+    (mime-maybe-hide-echo-buffer)
+    )
+  (gnus-run-hooks 'gnus-mime-article-prepare-hook)
+  )
+
 (defun gnus-article-prepare (article &optional all-headers header)
   "Prepare ARTICLE in article mode buffer.
 ARTICLE should either be an article number or a Message-ID.
@@ -2060,10 +2020,14 @@ If ALL-HEADERS is non-nil, no headers are hidden."
                      (cons gnus-newsgroup-name article))
                (set-buffer gnus-summary-buffer)
                (setq gnus-current-article article)
-               (gnus-summary-mark-article article gnus-canceled-mark))
-             (unless (memq article gnus-newsgroup-sparse)
-               (gnus-error
-                1 "No such article (may have expired or been canceled)")))
+               (if (eq (gnus-article-mark article) gnus-undownloaded-mark)
+                   (progn
+                     (gnus-summary-set-agent-mark article)
+                     (message "Message marked for downloading"))
+                 (gnus-summary-mark-article article gnus-canceled-mark)
+                 (unless (memq article gnus-newsgroup-sparse)
+                   (gnus-error 1 
+                    "No such article (may have expired or been canceled)")))))
          (if (or (eq result 'pseudo) (eq result 'nneething))
              (progn
                (save-excursion
@@ -2107,15 +2071,7 @@ If ALL-HEADERS is non-nil, no headers are hidden."
                ;; <sisolak@trans4.neep.wisc.edu>.
                (gnus-set-global-variables)
                (setq gnus-have-all-headers
-                     (or all-headers gnus-show-all-headers))
-               (and gnus-use-cache
-                    (vectorp (gnus-summary-article-header article))
-                    (gnus-cache-possibly-enter-article
-                     group article
-                     (gnus-summary-article-header article)
-                     (memq article gnus-newsgroup-marked)
-                     (memq article gnus-newsgroup-dormant)
-                     (memq article gnus-newsgroup-unreads)))))
+                     (or all-headers gnus-show-all-headers))))
            (when (or (numberp article)
                      (stringp article))
              ;; Hooks for getting information from the article.
@@ -2127,9 +2083,7 @@ If ALL-HEADERS is non-nil, no headers are hidden."
                (when gnus-show-mime
                  (if (or (not gnus-strict-mime)
                          (gnus-fetch-field "Mime-Version"))
-                     (let ((coding-system-for-write 'binary)
-                           (coding-system-for-read 'binary))
-                       (funcall gnus-show-mime-method))
+                     (funcall gnus-show-mime-method)
                    (funcall gnus-decode-encoded-word-method)))
                ;; Perform the article display hooks.
                (gnus-run-hooks 'gnus-article-display-hook))
@@ -2339,67 +2293,75 @@ Argument LINES specifies lines to be scrolled down."
   "Read a summary buffer key sequence and execute it from the article buffer."
   (interactive "P")
   (let ((nosaves
-        '("q" "Q"  "c" "r" "R" "\C-c\C-f" "m"  "a" "f" "F"
-          "Zc" "ZC" "ZE" "ZQ" "ZZ" "Zn" "ZR" "ZG" "ZN" "ZP"
-          "=" "^" "\M-^" "|"))
-       (nosave-but-article
-        '("A\r"))
-       (nosave-in-article
-        '("\C-d"))
+         '("q" "Q"  "c" "r" "R" "\C-c\C-f" "m"  "a" "f" "F"
+           "Zc" "ZC" "ZE" "ZQ" "ZZ" "Zn" "ZR" "ZG" "ZN" "ZP"
+           "=" "^" "\M-^" "|"))
+        (nosave-but-article
+         '("A\r"))
+        (nosave-in-article
+         '("\C-d"))
         (up-to-top
          '("n" "Gn" "p" "Gp"))
-       keys)
+        keys new-sum-point)
     (save-excursion
       (set-buffer gnus-article-current-summary)
       (let (gnus-pick-mode)
-       (push (or key last-command-event) unread-command-events)
-       (setq keys (read-key-sequence nil))))
+        (push (or key last-command-event) unread-command-events)
+        (setq keys (read-key-sequence nil))))
     (message "")
 
     (if (or (member keys nosaves)
-           (member keys nosave-but-article)
-           (member keys nosave-in-article))
-       (let (func)
-         (save-window-excursion
-           (pop-to-buffer gnus-article-current-summary 'norecord)
-           ;; We disable the pick minor mode commands.
-           (let (gnus-pick-mode)
-             (setq func (lookup-key (current-local-map) keys))))
-         (if (not func)
-             (ding)
-           (unless (member keys nosave-in-article)
-             (set-buffer gnus-article-current-summary))
-           (call-interactively func))
-         (when (member keys nosave-but-article)
-           (pop-to-buffer gnus-article-buffer 'norecord)))
+            (member keys nosave-but-article)
+            (member keys nosave-in-article))
+        (let (func)
+          (save-window-excursion
+            (pop-to-buffer gnus-article-current-summary 'norecord)
+            ;; We disable the pick minor mode commands.
+            (let (gnus-pick-mode)
+              (setq func (lookup-key (current-local-map) keys))))
+          (if (not func)
+              (ding)
+            (unless (member keys nosave-in-article)
+              (set-buffer gnus-article-current-summary))
+            (call-interactively func)
+            (setq new-sum-point (point)))
+          (when (member keys nosave-but-article)
+            (pop-to-buffer gnus-article-buffer 'norecord)))
       ;; These commands should restore window configuration.
       (let ((obuf (current-buffer))
-           (owin (current-window-configuration))
-           (opoint (point))
-           func in-buffer)
-       (if not-restore-window
-           (pop-to-buffer gnus-article-current-summary 'norecord)
-         (switch-to-buffer gnus-article-current-summary 'norecord))
-       (setq in-buffer (current-buffer))
-       ;; We disable the pick minor mode commands.
-       (if (setq func (let (gnus-pick-mode)
-                        (lookup-key (current-local-map) keys)))
-           (call-interactively func)
-         (ding))
-       (when (eq in-buffer (current-buffer))
-         (set-buffer obuf)
-         (unless not-restore-window
-           (set-window-configuration owin))
-          (unless (member keys up-to-top)
+            (owin (current-window-configuration))
+            (opoint (point))
+            (summary gnus-article-current-summary)
+            func in-buffer selected)
+        (if not-restore-window
+            (pop-to-buffer summary 'norecord)
+          (switch-to-buffer summary 'norecord))
+        (setq in-buffer (current-buffer))
+        ;; We disable the pick minor mode commands.
+        (if (setq func (let (gnus-pick-mode)
+                         (lookup-key (current-local-map) keys)))
+            (progn
+              (call-interactively func)
+              (setq new-sum-point (point)))
+          (ding))
+        (when (eq in-buffer (current-buffer))
+          (setq selected (gnus-summary-select-article))
+          (set-buffer obuf)
+          (unless not-restore-window
+            (set-window-configuration owin))
+          (unless (or (not (eq selected 'old)) (member keys up-to-top))
             (set-window-point (get-buffer-window (current-buffer))
-                              opoint)))))))
+                              opoint))
+          (let ((win (get-buffer-window gnus-article-current-summary)))
+            (when win
+              (set-window-point win new-sum-point))))))))
 
 (defun gnus-article-hide (&optional arg force)
   "Hide all the gruft in the current article.
 This means that PGP stuff, signatures, cited text and (some)
 headers will be hidden.
 If given a prefix, show the hidden text instead."
-  (interactive (list current-prefix-arg 'force))
+  (interactive (append (gnus-article-hidden-arg) (list 'force)))
   (gnus-article-hide-headers arg)
   (gnus-article-hide-pgp arg)
   (gnus-article-hide-citation-maybe arg force)
@@ -2438,7 +2400,7 @@ If given a prefix, show the hidden text instead."
          (when (and (numberp article)
                     gnus-summary-buffer
                     (get-buffer gnus-summary-buffer)
-                    (buffer-name (get-buffer gnus-summary-buffer)))
+                    (gnus-buffer-exists-p gnus-summary-buffer))
            (save-excursion
              (set-buffer gnus-summary-buffer)
              (let ((header (gnus-summary-article-header article)))
@@ -2462,8 +2424,8 @@ If given a prefix, show the hidden text instead."
 
                (let ((method (gnus-find-method-for-group
                               gnus-newsgroup-name)))
-                 (if (not (eq (car method) 'nneething))
-                     ()
+                 (when (and (eq (car method) 'nneething)
+                            (vectorp header))
                    (let ((dir (concat (file-name-as-directory (nth 1 method))
                                       (mail-header-subject header))))
                      (when (file-directory-p dir)
@@ -2475,7 +2437,7 @@ If given a prefix, show the hidden text instead."
           ((and (numberp article)
                 gnus-summary-buffer
                 (get-buffer gnus-summary-buffer)
-                (buffer-name (get-buffer gnus-summary-buffer))
+                (gnus-buffer-exists-p gnus-summary-buffer)
                 (eq (cdr (save-excursion
                            (set-buffer gnus-summary-buffer)
                            (assq article gnus-newsgroup-reads)))
@@ -2532,7 +2494,7 @@ If given a prefix, show the hidden text instead."
                        (buffer-name (get-buffer gnus-article-buffer))))
        (save-excursion
          (if (get-buffer gnus-original-article-buffer)
-             (set-buffer (get-buffer gnus-original-article-buffer))
+             (set-buffer gnus-original-article-buffer)
            (set-buffer (get-buffer-create gnus-original-article-buffer))
            (buffer-disable-undo (current-buffer))
            (setq major-mode 'gnus-original-article-mode)
@@ -2560,7 +2522,7 @@ If given a prefix, show the hidden text instead."
 ;;;
 
 (defcustom gnus-article-edit-mode-hook nil
-  "*Hook run in article edit mode buffers."
+  "Hook run in article edit mode buffers."
   :group 'gnus-article-various
   :type 'hook)
 
@@ -2585,7 +2547,6 @@ This is an extended text-mode.
 
 \\{gnus-article-edit-mode-map}"
   (interactive)
-  (kill-all-local-variables)
   (setq major-mode 'gnus-article-edit-mode)
   (setq mode-name "Article Edit")
   (use-local-map gnus-article-edit-mode-map)
@@ -2710,20 +2671,22 @@ groups."
 ;;; Internal Variables:
 
 (defcustom gnus-button-url-regexp "\\b\\(s?https?\\|ftp\\|file\\|gopher\\|news\\|telnet\\|wais\\|mailto\\):\\(//[-a-zA-Z0-9_.]+:[0-9]*\\)?\\([-a-zA-Z0-9_=!?#$@~`%&*+|\\/:;.,]\\|\\w\\)+\\([-a-zA-Z0-9_=#$@~`%&*+|\\/]\\|\\w\\)"
-  "*Regular expression that matches URLs."
+  "Regular expression that matches URLs."
   :group 'gnus-article-buttons
   :type 'regexp)
 
 (defcustom gnus-button-alist
-  `(("<\\(url: ?\\)?news:\\([^>\n\t ]*@[^>\n\t ]*\\)>" 0 t
+  `(("<\\(url:[>\n\t ]*?\\)?news:[>\n\t ]*\\([^>\n\t ]*@[^>\n\t ]*\\)>" 0 t
      gnus-button-message-id 2)
     ("\\bnews:\\([^>\n\t ]*@[^>\n\t ]*\\)" 0 t gnus-button-message-id 1)
-    ("\\(\\b<\\(url: ?\\)?news:\\(//\\)?\\([^>\n\t ]*\\)>\\)" 1 t
+    ("\\(\\b<\\(url:[>\n\t ]*\\)?news:[>\n\t ]*\\(//\\)?\\([^>\n\t ]*\\)>\\)"
+     1 t
      gnus-button-fetch-group 4)
     ("\\bnews:\\(//\\)?\\([^'\">\n\t ]+\\)" 0 t gnus-button-fetch-group 2)
     ("\\bin\\( +article\\| +message\\)? +\\(<\\([^\n @<>]+@[^\n @<>]+\\)>\\)" 2
      t gnus-button-message-id 3)
     ("\\(<URL: *\\)mailto: *\\([^> \n\t]+\\)>" 0 t gnus-url-mailto 2)
+    ("mailto:\\([a-zA-Z.-@_+0-9%]+\\)" 0 t gnus-url-mailto 2)
     ("\\bmailto:\\([^ \n\t]+\\)" 0 t gnus-url-mailto 1)
     ;; This is how URLs _should_ be embedded in text...
     ("<URL: *\\([^>]*\\)>" 0 t gnus-button-embedded-url 1)
@@ -3272,6 +3235,56 @@ forbidden in URL encoding."
     (gnus-article-prev-page)
     (select-window win)))
 
+
+;;; @ for mime-view
+;;;
+
+(defun gnus-content-header-filter ()
+  "Header filter for mime-view.
+It is registered to variable `mime-view-content-header-filter-alist'."
+  (eword-decode-header default-mime-charset))
+
+(defun mime-preview-quitting-method-for-gnus ()
+  (if (not gnus-show-mime)
+      (mime-preview-kill-buffer))
+  (delete-other-windows)
+  (gnus-article-show-summary)
+  (if (or (not gnus-show-mime)
+         (null gnus-have-all-headers))
+      (gnus-summary-select-article nil t)
+    ))
+
+(set-alist 'mime-view-content-header-filter-alist
+          'gnus-original-article-mode
+          #'gnus-content-header-filter)
+
+(set-alist 'mime-raw-representation-type-alist
+          'gnus-original-article-mode 'binary)
+
+(set-alist 'mime-preview-quitting-method-alist
+          'gnus-original-article-mode
+          #'mime-preview-quitting-method-for-gnus)
+
+(set-alist 'mime-view-show-summary-method
+          'gnus-original-article-mode
+          #'mime-preview-quitting-method-for-gnus)
+
+(defun gnus-following-method (buf)
+  (set-buffer buf)
+  (message-followup)
+  (message-yank-original)
+  (kill-buffer buf)
+  (goto-char (point-min))
+  )
+
+(set-alist 'mime-view-following-method-alist
+          'gnus-original-article-mode
+          #'gnus-following-method)
+
+
+;;; @ end
+;;;
+
 (gnus-ems-redefine)
 
 (provide 'gnus-art)