* rfc2047.el (rfc2047-fold-line): New function.
[gnus] / lisp / gnus-art.el
index 8b89e95..291d32d 100644 (file)
@@ -32,6 +32,7 @@
 (require 'gnus-sum)
 (require 'gnus-spec)
 (require 'gnus-int)
+(require 'gnus-win)
 (require 'mm-bodies)
 (require 'mail-parse)
 (require 'mm-decode)
     "^X-Abuse-Info:" "^X-From_:" "^X-Accept-Language:" "^Errors-To:"
     "^X-BeenThere:" "^X-Mailman-Version:" "^List-Help:" "^List-Post:"
     "^List-Subscribe:" "^List-Id:" "^List-Unsubscribe:" "^List-Archive:"
-     "^X-Content-length:" "^X-Posting-Agent:" "^Original-Received:")
+     "^X-Content-length:" "^X-Posting-Agent:" "^Original-Received:"
+     "^X-Request-PGP:" "^X-Fingerprint:" "^X-WRIEnvto:" "^X-WRIEnvfrom:"
+     "^X-Virus-Scanned:" "^X-Delivery-Agent:" "^Posted-Date:" "^X-Gateway:"
+     "^X-Local-Origin:" "^X-Local-Destination:")
   "*All headers that start with this regexp will be hidden.
 This variable can also be a list of regexps of headers to be ignored.
 If `gnus-visible-headers' is non-nil, this variable will be ignored."
@@ -222,12 +226,11 @@ regexp.  If it matches, the text in question is not a signature."
 ;; non-graphical frames in a session.
 (defcustom gnus-article-x-face-command
   (if (featurep 'xemacs)
-      (if (or (featurep 'xface)
-             (featurep 'xpm))
+      (if (or (gnus-image-type-available-p 'xface)
+             (gnus-image-type-available-p 'xpm))
          'gnus-xmas-article-display-xface
        "{ echo '/* Width=48, Height=48 */'; uncompface; } | icontopbm | ee -")
-    (if (and (fboundp 'image-type-available-p)
-            (image-type-available-p 'xbm))
+    (if (gnus-image-type-available-p 'xbm)
        'gnus-article-display-xface
       (if gnus-article-compface-xbm
          "{ echo '/* Width=48, Height=48 */'; uncompface; } | display -"
@@ -237,7 +240,7 @@ display -")))
 If it is a string, the command will be executed in a sub-shell
 asynchronously.         The compressed face will be piped to this command."
   :type `(choice string
-                (function-item 
+                (function-item
                  ,(if (featurep 'xemacs)
                       'gnus-xmas-article-display-xface
                     'gnus-article-display-xface))
@@ -359,6 +362,19 @@ Esample: (_/*word*/_)."
   "Face used for displaying highlighted words."
   :group 'gnus-article-emphasis)
 
+(defface gnus-body-boundary-face
+  '((((class color)
+      (background dark))
+     (:background "white")
+     (:foreground "black"))
+    (((class color)
+      (background light))
+     (:background "black")
+     (:foreground "white"))
+    (t
+     ()))
+  "Face for the body separator.")
+
 (defcustom gnus-article-time-format "%a, %b %d %Y %T %Z"
   "Format for display of Date headers in article bodies.
 See `format-time-string' for the possible values.
@@ -410,6 +426,7 @@ Gnus provides the following functions:
 * gnus-summary-save-in-mail (Unix mail format)
 * gnus-summary-save-in-folder (MH folder)
 * 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)."
   :group 'gnus-article-saving
@@ -417,6 +434,7 @@ Gnus provides the following functions:
                (function-item gnus-summary-save-in-mail)
                (function-item gnus-summary-save-in-folder)
                (function-item gnus-summary-save-in-file)
+               (function-item gnus-summary-save-body-in-file)
                (function-item gnus-summary-save-in-vm)
                (function-item gnus-summary-write-to-file)))
 
@@ -794,7 +812,7 @@ used."
 (defcustom gnus-treat-highlight-signature '(or last (typep "text/x-vcard"))
   "Highlight the signature.
 Valid values are nil, t, `head', `last', an integer or a predicate.
-See the manual for details."
+See Info node `(gnus)Customizing Articles'."
   :group 'gnus-article-treat
   :type gnus-article-treat-custom)
 (put 'gnus-treat-highlight-signature 'highlight t)
@@ -883,13 +901,6 @@ See the manual for details."
   :group 'gnus-article-treat
   :type gnus-article-treat-custom)
 
-(defcustom gnus-treat-hide-citation-maybe nil
-  "Hide cited text.
-Valid values are nil, t, `head', `last', an integer or a predicate.
-See the manual for details."
-  :group 'gnus-article-treat
-  :type gnus-article-treat-custom)
-
 (defcustom gnus-treat-strip-list-identifiers 'head
   "Strip list identifiers from `gnus-list-identifiers`.
 Valid values are nil, t, `head', `last', an integer or a predicate.
@@ -1016,6 +1027,13 @@ See the manual for details."
   :group 'gnus-article-treat
   :type gnus-article-treat-custom)
 
+(defcustom gnus-treat-unfold-headers 'head
+  "Unfold folded header lines.
+Valid values are nil, t, `head', `last', an integer or a predicate.
+See the manual for details."
+  :group 'gnus-article-treat
+  :type gnus-article-treat-custom)
+
 (defcustom gnus-treat-overstrike t
   "Treat overstrike highlighting.
 Valid values are nil, t, `head', `last', an integer or a predicate.
@@ -1052,13 +1070,47 @@ See the manual for details."
   :type gnus-article-treat-custom)
 (put 'gnus-treat-display-smileys 'highlight t)
 
-(defcustom gnus-treat-display-picons (if (featurep 'xemacs) 'head nil)
-  "Display picons.
+(defcustom gnus-treat-from-picon
+  (if (gnus-image-type-available-p 'xpm)
+      'head nil)
+  "Display picons in the From header.
+Valid values are nil, t, `head', `last', an integer or a predicate.
+See the manual for details."
+  :group 'gnus-article-treat
+  :type gnus-article-treat-head-custom)
+(put 'gnus-treat-from-picon 'highlight t)
+
+(defcustom gnus-treat-mail-picon
+  (if (gnus-image-type-available-p 'xpm)
+      'head nil)
+  "Display picons in To and Cc headers.
+Valid values are nil, t, `head', `last', an integer or a predicate.
+See the manual for details."
+  :group 'gnus-article-treat
+  :type gnus-article-treat-head-custom)
+(put 'gnus-treat-mail-picon 'highlight t)
+
+(defcustom gnus-treat-newsgroups-picon
+  (if (gnus-image-type-available-p 'xpm)
+      'head nil)
+  "Display picons in the Newsgroups and Followup-To headers.
 Valid values are nil, t, `head', `last', an integer or a predicate.
 See the manual for details."
   :group 'gnus-article-treat
   :type gnus-article-treat-head-custom)
-(put 'gnus-treat-display-picons 'highlight t)
+(put 'gnus-treat-newsgroups-picon 'highlight t)
+
+(defcustom gnus-treat-body-boundary
+  (if (or gnus-treat-newsgroups-picon
+         gnus-treat-mail-picon
+         gnus-treat-from-picon)
+      'head nil)
+  "Draw a boundary at the end of the headers.
+Valid values are nil, t, `head', `last', an integer or a predicate.
+See the manual for details."
+  :version "21.1"
+  :group 'gnus-article-treat
+  :type gnus-article-treat-custom)
 
 (defcustom gnus-treat-capitalize-sentences nil
   "Capitalize sentence-starting words.
@@ -1131,7 +1183,6 @@ It is a string, such as \"PGP\". If nil, ask user."
     (gnus-treat-fill-article gnus-article-fill-cited-article)
     (gnus-treat-fill-long-lines gnus-article-fill-long-lines)
     (gnus-treat-strip-cr gnus-article-remove-cr)
-    (gnus-treat-emphasize gnus-article-emphasize)
     (gnus-treat-display-xface gnus-article-display-x-face)
     (gnus-treat-date-ut gnus-article-date-ut)
     (gnus-treat-date-local gnus-article-date-local)
@@ -1149,6 +1200,9 @@ It is a string, such as \"PGP\". If nil, ask user."
     (gnus-treat-leading-whitespace gnus-article-remove-leading-whitespace)
     (gnus-treat-strip-pgp gnus-article-hide-pgp)
     (gnus-treat-strip-pem gnus-article-hide-pem)
+    (gnus-treat-from-picon gnus-treat-from-picon)
+    (gnus-treat-mail-picon gnus-treat-mail-picon)
+    (gnus-treat-newsgroups-picon gnus-treat-newsgroups-picon)
     (gnus-treat-highlight-headers gnus-article-highlight-headers)
     (gnus-treat-highlight-citation gnus-article-highlight-citation)
     (gnus-treat-highlight-signature gnus-article-highlight-signature)
@@ -1159,10 +1213,12 @@ It is a string, such as \"PGP\". If nil, ask user."
     (gnus-treat-strip-multiple-blank-lines
      gnus-article-strip-multiple-blank-lines)
     (gnus-treat-overstrike gnus-article-treat-overstrike)
+    (gnus-treat-unfold-headers gnus-article-treat-unfold-headers)
     (gnus-treat-buttonize-head gnus-article-add-buttons-to-head)
     (gnus-treat-display-smileys gnus-smiley-display)
     (gnus-treat-capitalize-sentences gnus-article-capitalize-sentences)
-    (gnus-treat-display-picons gnus-article-display-picons)
+    (gnus-treat-emphasize gnus-article-emphasize)
+    (gnus-treat-body-boundary gnus-article-treat-body-boundary)
     (gnus-treat-play-sounds gnus-earcon-display)))
 
 (defvar gnus-article-mime-handle-alist nil)
@@ -1190,6 +1246,21 @@ Initialized from `text-mode-syntax-table.")
 
 (defvar gnus-inhibit-hiding nil)
 
+;;; Macros for dealing with the article buffer.
+
+(defmacro gnus-with-article-headers (&rest forms)
+  `(save-excursion
+     (set-buffer gnus-article-buffer)
+     (save-restriction
+       (let ((buffer-read-only nil)
+            (inhibit-point-motion-hooks t)
+            (case-fold-search t))
+        (article-narrow-to-head)
+        ,@forms))))
+
+(put 'gnus-with-article-headers 'lisp-indent-function 0)
+(put 'gnus-with-article-headers 'edebug-form-spec '(body))
+
 (defsubst gnus-article-hide-text (b e props)
   "Set text PROPS on the B to E region, extending `intangible' 1 past B."
   (gnus-add-text-properties-when 'article-type nil b e props)
@@ -1537,6 +1608,42 @@ MAP is an alist where the elements are on the form (\"from\" \"to\")."
              (put-text-property
               (point) (1+ (point)) 'face 'underline)))))))))
 
+(defun gnus-article-treat-unfold-headers ()
+  "Unfold folded message headers.
+Only the headers that fit into the current window width will be
+unfolded."
+  (interactive)
+  (gnus-with-article-headers
+    (let (length)
+      (while (not (eobp))
+       (save-restriction
+         (mail-header-narrow-to-field)
+         (let ((header (buffer-substring (point-min) (point-max))))
+           (with-temp-buffer
+             (insert header)
+             (goto-char (point-min))
+             (while (re-search-forward "[\t ]*\n[\t ]+" nil t)
+               (replace-match " " t t)))
+           (setq length (- (point-max) (point-min) 1)))
+         (when (< length (window-width))
+           (while (re-search-forward "[\t ]*\n[\t ]+" nil t)
+             (replace-match " " t t)))
+         (goto-char (point-max)))))))
+
+(defun gnus-article-treat-body-boundary ()
+  "Place a boundary line at the end of the headers."
+  (interactive)
+  (gnus-with-article-headers
+    (goto-char (point-max))
+    (let ((start (point)))
+    (insert "X-Boundary: ")
+    (gnus-add-text-properties start (point) '(invisible t intangible t))
+    (insert (make-string (1- (window-width)) ?-)
+           "\n")
+    ;;(put-text-property (point) (progn (forward-line -1) (point))
+    ;; 'face 'gnus-body-bondary-face)
+    )))
+
 (defun article-fill-long-lines ()
   "Fill lines that are wider than the window width."
   (interactive)
@@ -1665,7 +1772,8 @@ MAP is an alist where the elements are on the form (\"from\" \"to\")."
          ;; We now have the area of the buffer where the X-Face is stored.
          (save-excursion
            (let ((beg (point))
-                 (end (1- (re-search-forward "^\\($\\|[^ \t]\\)" nil t))))
+                 (end (1- (re-search-forward "^\\($\\|[^ \t]\\)" nil t)))
+                 buffer-read-only)
              ;; We display the face.
              (if (symbolp gnus-article-x-face-command)
                  ;; The command is a lisp function, so we call it.
@@ -1762,14 +1870,21 @@ If PROMPT (the prefix), prompt for a coding system to use."
        (method (gnus-find-method-for-group gnus-newsgroup-name)))
     (when (and (or gnus-group-name-charset-method-alist
                   gnus-group-name-charset-group-alist)
-              (gnus-buffer-live-p gnus-original-article-buffer)
-              (mail-fetch-field "Newsgroups"))
-      (nnheader-replace-header "Newsgroups"
-                              (gnus-decode-newsgroups
-                               (with-current-buffer
-                                   gnus-original-article-buffer
-                                 (mail-fetch-field "Newsgroups"))
-                               gnus-newsgroup-name method)))))
+              (gnus-buffer-live-p gnus-original-article-buffer))
+      (when (nnmail-fetch-field "Newsgroups")
+       (nnheader-replace-header "Newsgroups"
+                                (gnus-decode-newsgroups
+                                 (with-current-buffer
+                                     gnus-original-article-buffer
+                                   (nnmail-fetch-field "Newsgroups"))
+                                 gnus-newsgroup-name method)))
+      (when (nnmail-fetch-field "Followup-To")
+       (nnheader-replace-header "Followup-To"
+                                (gnus-decode-newsgroups
+                                 (with-current-buffer
+                                     gnus-original-article-buffer
+                                   (nnmail-fetch-field "Followup-To"))
+                                 gnus-newsgroup-name method))))))
 
 (defun article-de-quoted-unreadable (&optional force read-charset)
   "Translate a quoted-printable-encoded article.
@@ -1873,7 +1988,9 @@ If READ-CHARSET, ask for a coding system."
          (narrow-to-region (point) (point-max))
          (mm-setup-w3)
          (let ((w3-strict-width (window-width))
-               (url-standalone-mode t))
+               (url-standalone-mode t)
+               (w3-honor-stylesheets nil)
+               (w3-delay-image-loads t))
            (condition-case var
                (w3-region (point-min) (point-max))
              (error))))))))
@@ -2017,7 +2134,8 @@ always hide."
        (let ((buffer-read-only nil))
          (when (gnus-article-narrow-to-signature)
            (gnus-article-hide-text-type
-            (point-min) (point-max) 'signature)))))))
+            (point-min) (point-max) 'signature))))))
+  (gnus-set-mode-line 'article))
 
 (defun article-strip-headers-in-body ()
   "Strip offensive headers from bodies."
@@ -2169,7 +2287,7 @@ Put point at the beginning of the signature separator."
 
 (defun gnus-article-check-hidden-text (type arg)
   "Return nil if hiding is necessary.
-Arg can be nil or a number.  Nil and positive means hide, negative
+Arg can be nil or a number.  nil and positive means hide, negative
 means show, 0 means toggle."
   (save-excursion
     (save-restriction
@@ -2209,7 +2327,8 @@ Originally it is hide instead of DUMMY."
      'article-type type
      (point-min) (point-max)
      (cons 'article-type (cons type
-                              gnus-hidden-properties)))))
+                              gnus-hidden-properties)))
+    (setq gnus-article-wash-types (delq type gnus-article-wash-types))))
 
 (defconst article-time-units
   `((year . ,(* 365.25 24 60 60))
@@ -2503,13 +2622,13 @@ This format is defined by the `gnus-article-time-format' variable."
                face (nth 3 elem))
          (while (re-search-forward regexp nil t)
            (when (and (match-beginning visible) (match-beginning invisible))
-             (push 'emphasis gnus-article-wash-types)
              (gnus-article-hide-text
               (match-beginning invisible) (match-end invisible) props)
              (gnus-article-unhide-text-type
               (match-beginning visible) (match-end visible) 'emphasis)
-             (gnus-put-text-property-excluding-newlines
+             (gnus-put-overlay-excluding-newlines
               (match-beginning visible) (match-end visible) 'face face)
+             (push 'emphasis gnus-article-wash-types)
              (goto-char (match-end invisible)))))))))
 
 (defun gnus-article-setup-highlight-words (&optional highlight-words)
@@ -2711,7 +2830,7 @@ Directory to save to is default to `gnus-article-save-directory'."
   filename)
 
 (defun gnus-summary-write-to-file (&optional filename)
-  "Write this article to a file.
+  "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))
@@ -2760,6 +2879,13 @@ The directory to save in defaults to `gnus-article-save-directory'."
       (shell-command-on-region (point-min) (point-max) command nil)))
   (setq gnus-last-shell-command command))
 
+(defun gnus-summary-pipe-to-muttprint (&optional command)
+  "Pipe this article to muttprint."
+  (setq command (read-string
+                "Print using command: " gnus-summary-muttprint-program
+                nil gnus-summary-muttprint-program))
+  (gnus-summary-save-in-pipe command))
+
 ;;; Article file names when saving.
 
 (defun gnus-capitalize-newsgroup (newsgroup)
@@ -2899,6 +3025,12 @@ If variable `gnus-use-long-file-name' is non-nil, it is
                  (put-text-property (match-end 0) (point-max)
                                     'face eface)))))))))
 
+(defun article-verify-cancel-lock ()
+  "Verify Cancel-Lock header."
+  (interactive)
+  (if (gnus-buffer-live-p gnus-original-article-buffer)
+      (canlock-verify gnus-original-article-buffer)))
+
 (eval-and-compile
   (mapcar
    (lambda (func)
@@ -2920,6 +3052,7 @@ If variable `gnus-use-long-file-name' is non-nil, it is
                  (apply ',afunc args))))))))
    '(article-hide-headers
      article-verify-x-pgp-sig
+     article-verify-cancel-lock
      article-hide-boring-headers
      article-treat-overstrike
      article-fill-long-lines
@@ -3125,7 +3258,7 @@ commands:
 ;; from the head of the article.
 (defun gnus-article-set-window-start (&optional line)
   (set-window-start
-   (get-buffer-window gnus-article-buffer t)
+   (gnus-get-buffer-window gnus-article-buffer t)
    (save-excursion
      (set-buffer gnus-article-buffer)
      (goto-char (point-min))
@@ -3693,7 +3826,7 @@ If no internal viewer is available, use an external viewer."
                               gnus-newsgroup-ignored-charsets)))
          (save-excursion
            (unwind-protect
-               (let ((win (get-buffer-window (current-buffer) t))
+               (let ((win (gnus-get-buffer-window (current-buffer) t))
                      (beg (point)))
                  (when win
                    (select-window win))
@@ -3703,7 +3836,7 @@ If no internal viewer is available, use an external viewer."
                      ;; This will remove the part.
                      (mm-display-part handle)
                    (save-restriction
-                     (narrow-to-region (point) 
+                     (narrow-to-region (point)
                                        (if (eobp) (point) (1+ (point))))
                      (mm-display-part handle)
                      ;; We narrow to the part itself and
@@ -4081,6 +4214,39 @@ If no internal viewer is available, use an external viewer."
     (when ibegend
       (goto-char point))))
 
+(defconst gnus-article-wash-status-strings
+  (let ((alist '((cite "c" "Possible hidden citation text"
+                      " " "All citation text visible")
+                (headers "h" "Hidden headers"
+                         " " "All headers visible.")
+                (pgp "p" "Encrypted or signed message status hidden"
+                     " " "No hidden encryption nor digital signature status")
+                (signature "s" "Signature has been hidden"
+                           " " "Signature is visible")
+                (overstrike "o" "Overstrike (^H) characters applied"
+                            " " "No overstrike characters applied")
+                (emphasis "e" "/*_Emphasis_*/ characters applied"
+                          " " "No /*_emphasis_*/ characters applied")))
+       result)
+    (dolist (entry alist result)
+      (let ((key (nth 0 entry))
+           (on (copy-sequence (nth 1 entry)))
+           (on-help (nth 2 entry))
+           (off (copy-sequence (nth 3 entry)))
+           (off-help (nth 4 entry)))
+       (put-text-property 0 1 'help-echo on-help on)
+       (put-text-property 0 1 'help-echo off-help off)
+       (push (list key on off) result))))
+  "Alist of strings describing wash status in the mode line.
+Each entry has the form (KEY ON OF), where the KEY is a symbol
+representing the particular washing function, ON is the string to use
+in the article mode line when the washing function is active, and OFF
+is the string to use when it is inactive.")
+
+(defun gnus-gnus-article-wash-status-entry (key value)
+  (let ((entry (assoc key gnus-article-wash-status-strings)))
+    (if value (nth 1 entry) (nth 2 entry))))
+
 (defun gnus-article-wash-status ()
   "Return a string which display status of article washing."
   (save-excursion
@@ -4095,13 +4261,14 @@ If no internal viewer is available, use an external viewer."
          (signature (memq 'signature gnus-article-wash-types))
          (overstrike (memq 'overstrike gnus-article-wash-types))
          (emphasis (memq 'emphasis gnus-article-wash-types)))
-      (format "%c%c%c%c%c%c"
-             (if cite ?c ? )
-             (if (or headers boring) ?h ? )
-             (if (or pgp pem signed encrypted) ?p ? )
-             (if signature ?s ? )
-             (if overstrike ?o ? )
-             (if emphasis ?e ? )))))
+      (concat (gnus-gnus-article-wash-status-entry 'cite cite)
+             (gnus-gnus-article-wash-status-entry 'headers
+                                                  (or headers boring))
+             (gnus-gnus-article-wash-status-entry
+              'pgp (or pgp pem signed encrypted))
+             (gnus-gnus-article-wash-status-entry 'signature signature)
+             (gnus-gnus-article-wash-status-entry 'overstrike overstrike)
+             (gnus-gnus-article-wash-status-entry 'emphasis emphasis)))))
 
 (defalias 'gnus-article-hide-headers-if-wanted 'gnus-article-maybe-hide-headers)
 
@@ -4591,7 +4758,7 @@ If given a prefix, show the hidden text instead."
          (set-buffer gnus-summary-buffer)
          (gnus-summary-update-article do-update-line sparse-header)
          (gnus-summary-goto-subject do-update-line nil t)
-         (set-window-point (get-buffer-window (current-buffer) t)
+         (set-window-point (gnus-get-buffer-window (current-buffer) t)
                            (point))
          (set-buffer buf))))))
 
@@ -5051,14 +5218,21 @@ specified by `gnus-button-alist'."
     (let ((buffer-read-only nil)
          (inhibit-point-motion-hooks t))
       (if (text-property-any end (point-max) 'article-type 'signature)
-         (gnus-remove-text-properties-when
-          'article-type 'signature end (point-max)
-          (cons 'article-type (cons 'signature
-                                    gnus-hidden-properties)))
+         (progn
+           (setq gnus-article-wash-types
+                 (delq 'signature gnus-article-wash-types))
+           (gnus-remove-text-properties-when
+            'article-type 'signature end (point-max)
+            (cons 'article-type (cons 'signature
+                                      gnus-hidden-properties))))
+       (or (memq 'signature gnus-article-wash-types)
+           (push 'signature gnus-article-wash-types))
        (gnus-add-text-properties-when
         'article-type nil end (point-max)
         (cons 'article-type (cons 'signature
-                                  gnus-hidden-properties)))))))
+                                  gnus-hidden-properties)))))
+    (let ((gnus-article-mime-handle-alist-1 gnus-article-mime-handle-alist))
+      (gnus-set-mode-line 'article))))
 
 (defun gnus-button-entry ()
   ;; Return the first entry in `gnus-button-alist' matching this place.
@@ -5135,13 +5309,13 @@ specified by `gnus-button-alist'."
 
 (defun gnus-button-handle-info (url)
   "Fetch an info URL."
-  (if (string-match 
+  (if (string-match
        "^\\([^:/]+\\)?/\\(.*\\)"
        url)
       (gnus-info-find-node
        (concat "(" (or (gnus-url-unhex-string (match-string 1 url))
-                      "Gnus") 
-              ")" 
+                      "Gnus")
+              ")"
               (gnus-url-unhex-string (match-string 2 url))))
     (error "Can't parse %s" url)))
 
@@ -5156,8 +5330,8 @@ specified by `gnus-button-alist'."
   (if (not (string-match "[:/]" address))
       ;; This is just a simple group url.
       (gnus-group-read-ephemeral-group address gnus-select-method)
-    (if (not 
-        (string-match 
+    (if (not
+        (string-match
          "^\\([^:/]+\\)\\(:\\([^/]+\\)\\)?/\\([^/]+\\)\\(/\\([0-9]+\\)\\)?"
          address))
        (error "Can't parse %s" address)
@@ -5189,38 +5363,6 @@ specified by `gnus-button-alist'."
          (setq retval (cons (list key val) retval)))))
     retval))
 
-(defun gnus-url-unhex (x)
-  (if (> x ?9)
-      (if (>= x ?a)
-         (+ 10 (- x ?a))
-       (+ 10 (- x ?A)))
-    (- x ?0)))
-
-(defun gnus-url-unhex-string (str &optional allow-newlines)
-  "Remove %XXX embedded spaces, etc in a url.
-If optional second argument ALLOW-NEWLINES is non-nil, then allow the
-decoding of carriage returns and line feeds in the string, which is normally
-forbidden in URL encoding."
-  (setq str (or (mm-subst-char-in-string ?+ ?  str) ""))
-  (let ((tmp "")
-       (case-fold-search t))
-    (while (string-match "%[0-9a-f][0-9a-f]" str)
-      (let* ((start (match-beginning 0))
-            (ch1 (gnus-url-unhex (elt str (+ start 1))))
-            (code (+ (* 16 ch1)
-                     (gnus-url-unhex (elt str (+ start 2))))))
-       (setq tmp (concat
-                  tmp (substring str 0 start)
-                  (cond
-                   (allow-newlines
-                    (char-to-string code))
-                   ((or (= code ?\n) (= code ?\r))
-                    " ")
-                   (t (char-to-string code))))
-             str (substring str (match-end 0)))))
-    (setq tmp (concat tmp str))
-    tmp))
-
 (defun gnus-url-mailto (url)
   ;; Send mail to someone
   (when (string-match "mailto:/*\\(.*\\)" url)
@@ -5279,7 +5421,7 @@ forbidden in URL encoding."
   "Go to the next page."
   (interactive)
   (let ((win (selected-window)))
-    (select-window (get-buffer-window gnus-article-buffer t))
+    (select-window (gnus-get-buffer-window gnus-article-buffer t))
     (gnus-article-next-page)
     (select-window win)))
 
@@ -5287,7 +5429,7 @@ forbidden in URL encoding."
   "Go to the prev page."
   (interactive)
   (let ((win (selected-window)))
-    (select-window (get-buffer-window gnus-article-buffer t))
+    (select-window (gnus-get-buffer-window gnus-article-buffer t))
     (gnus-article-prev-page)
     (select-window win)))
 
@@ -5303,7 +5445,7 @@ forbidden in URL encoding."
   "Go to the next page."
   (interactive "P")
   (let ((win (selected-window)))
-    (select-window (get-buffer-window gnus-article-buffer t))
+    (select-window (gnus-get-buffer-window gnus-article-buffer t))
     (gnus-article-next-page)
     (select-window win)))
 
@@ -5311,7 +5453,7 @@ forbidden in URL encoding."
   "Go to the prev page."
   (interactive "P")
   (let ((win (selected-window)))
-    (select-window (get-buffer-window gnus-article-buffer t))
+    (select-window (gnus-get-buffer-window gnus-article-buffer t))
     (gnus-article-prev-page)
     (select-window win)))
 
@@ -5667,6 +5809,9 @@ For example:
      (cons (set-marker (make-marker) (point-min))
           (set-marker (make-marker) (point-max))))))
 
+(defun gnus-article-goto-header (header)
+  (re-search-forward (concat "^" header ":") nil t))
+
 (gnus-ems-redefine)
 
 (provide 'gnus-art)