]> git.eshelyaron.com Git - emacs.git/commitdiff
Merge changes made in Gnus trunk.
authorGnus developers <ding@gnus.org>
Wed, 6 Oct 2010 12:38:45 +0000 (12:38 +0000)
committerKatsumi Yamaoka <yamaoka@jpl.org>
Wed, 6 Oct 2010 12:38:45 +0000 (12:38 +0000)
shr.el: Rearrange function order to be more logical.
gnus-faq.texi: Remove reference to my.gnus.org
message.el (message-change-subject): Remove 404 URL in a comment.
nnir.el: Fix Swish-E URL.
nnir.el: Fix Namazu URL.
nnrss.el (nnrss-check-group): Remove 404 URL in comment.
nnrss.el (nnrss-discover-feed): Remove 404 URL in docstring.
gnus-faq.texi (FAQ 5-5): Fix Flyspell URL.
gnus-faq.texi (FAQ 7-1): Fix getmail URL.
gnus.texi (Comparing Mail Back Ends): Remove broken link and allusion to ReiserFS.
nnimap.el (nnimap-open-connection): Prepare to support open-gnutls-stream.
shr.el (shr-insert): Get 'space transition right.
message.texi: Remove reference to gpg-2comp.

doc/misc/ChangeLog
doc/misc/gnus-faq.texi
doc/misc/gnus.texi
doc/misc/message.texi
lisp/gnus/ChangeLog
lisp/gnus/message.el
lisp/gnus/nnimap.el
lisp/gnus/nnir.el
lisp/gnus/nnrss.el
lisp/gnus/shr.el

index 6abb4be8a399d81eef26bb4f783a198906741735..fb0b7a7851b79cfa7327ea5118137f0524bbdbc3 100644 (file)
@@ -1,3 +1,16 @@
+2010-10-06  Julien Danjou  <julien@danjou.info>
+
+       * message.texi (PGP Compatibility): Remove reference to gpg-2comp,
+       broken link.
+
+       * gnus-faq.texi (FAQ 8-3): Remove references to my.gnus.org.
+
+       * gnus.texi (Comparing Mail Back Ends): Remove broken link and allusion
+       to ReiserFS.
+
+       * gnus-faq.texi (FAQ 5-5): Fix Flyspell URL.
+       (FAQ 7-1): Fix getmail URL.
+
 2010-10-06  Daiki Ueno  <ueno@unixuser.org>
 
        * epa.texi (Caching Passphrases): New section.
index ed74092eb0a4bfbd4ba335cfcaeda17a2d8d6585..d9df9c8db18ae252e85c783129d13a5988ad767a 100644 (file)
@@ -4,9 +4,6 @@
 @c Copyright (C) 1995, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
 @c   2009, 2010 Free Software Foundation, Inc.
 @c
-@c Do not modify this file, it was generated from gnus-faq.xml, available from
-@c <URL:http://my.gnus.org/FAQ/>.
-@c
 @setfilename gnus-faq.info
 @settitle Frequently Asked Questions
 @c %**end of header
 @subheading Abstract
 
 This is the new Gnus Frequently Asked Questions list.
-If you have a Web browser, the official hypertext version is at
-@uref{http://my.gnus.org/FAQ/},
-the Docbook source is available from
-@uref{http://sourceforge.net/projects/gnus/, http://sourceforge.net}.
 
 Please submit features and suggestions to the 
-@email{faq-discuss@@my.gnus.org, FAQ discussion list}.
-The list is protected against junk mail with
-@uref{http://smarden.org/qconfirm/index.html, qconfirm}. As
-a subscriber, your submissions will automatically pass.  You can
-also subscribe to the list by sending a blank email to
-@email{faq-discuss-subscribe@@my.gnus.org, faq-discuss-subscribe@@my.gnus.org}
-and @uref{http://mail1.kens.com/cgi-bin/ezmlm-browse?command=monthbythread%26list=faq-discuss, browse
-the archive (BROKEN)}.
+@email{ding@@gnus.org, ding list}.
 
 @node FAQ - Changes
 @subheading Changes
@@ -98,8 +84,6 @@ would like to thank Steve Baur and Per Abrahamsen for doing a wonderful
 job with this FAQ before him. We would like to do the same - thanks,
 Justin!
 
-If you have a Web browser, the official hypertext version is at:
-@uref{http://my.gnus.org/FAQ/}.
 This version is much nicer than the unofficial hypertext
 versions that are archived at Utrecht, Oxford, Smart Pages, Ohio
 State, and other FAQ archives. See the resources question below
@@ -107,7 +91,7 @@ if you want information on obtaining it in another format.
 
 The information contained here was compiled with the assistance
 of the Gnus development mailing list, and any errors or
-misprints are the my.gnus.org team's fault, sorry.
+misprints are the Gnus team's fault, sorry.
 
 @node FAQ 1 - Installation FAQ
 @subsection Installation FAQ
@@ -1042,8 +1026,7 @@ in Gnus Country :-). It's a three step process: First we
 make faces (specifications of how summary-line shall look
 like) for those postings, then we'll give them some
 special score and finally we'll tell Gnus to use the new
-faces. You can find detailed instructions on how to do it on
-@uref{http://my.gnus.org/node/view/224, my.gnus.org}
+faces.
 
 @node FAQ 4-12
 @subsubheading Question 4.12
@@ -1414,7 +1397,7 @@ or @uref{http://aspell.sourceforge.net/, aspell}
 installed and in your Path. Then you need 
 @uref{http://www.kdstevens.com/~stevens/ispell-page.html, ispell.el}
 and for on-the-fly spell-checking 
-@uref{http://www-sop.inria.fr/mimosa/personnel/Manuel.Serrano/flyspell/flyspell.html, flyspell.el}.
+@uref{http://www-sop.inria.fr/members/Manuel.Serrano/flyspell/flyspell.html, flyspell.el}.
 Ispell.el is shipped with Emacs and available through the XEmacs package system, 
 flyspell.el is shipped with Emacs and part of XEmacs text-modes package which is 
 available through the package system, so there should be no need to install them 
@@ -1987,7 +1970,7 @@ server like
 @uref{http://www.isc.org/products/INN/, inn}. 
 Then you want to fetch your Mail, popular choices
 are @uref{http://www.catb.org/~esr/fetchmail/, fetchmail}
-and @uref{http://www.qcc.ca/~charlesc/software/getmail-3.0/, getmail}.
+and @uref{http://pyropus.ca/software/getmail/, getmail}.
 You should tell those to write the mail to your disk and
 Gnus to read it from there. Last but not least the mail
 sending part: This can be done with every MTA like
@@ -2141,12 +2124,8 @@ Which websites should I know?
 
 @subsubheading Answer
 
-The two most important ones are the
+The most important one is the
 @uref{http://www.gnus.org, official Gnus website}.
-and it's sister site 
-@uref{http://my.gnus.org, my.gnus.org (MGO)},
-hosting an archive of lisp snippets, howtos, a (not
-really finished) tutorial and this FAQ.
 
 Tell me about other sites which are interesting.
 
index 6c20e424f04b4eeafbac95ba71eb3759ac258374..bc2adb87a356a9f538f2e2ce797c78f6ff9171ca 100644 (file)
@@ -17401,13 +17401,12 @@ incompatible group parameters, slightly different from those of other
 mail back ends.
 
 @code{nnmaildir} is largely similar to @code{nnml}, with some notable
-differences.  Each message is stored in a separate file, but the
-filename is unrelated to the article number in Gnus.  @code{nnmaildir}
+differences. Each message is stored in a separate file, but the
+filename is unrelated to the article number in Gnus. @code{nnmaildir}
 also stores the equivalent of @code{nnml}'s overview files in one file
-per article, so it uses about twice as many inodes as @code{nnml}.  (Use
-@code{df -i} to see how plentiful your inode supply is.)  If this slows
-you down or takes up very much space, consider switching to
-@uref{http://www.namesys.com/, ReiserFS} or another non-block-structured
+per article, so it uses about twice as many inodes as @code{nnml}.
+(Use @code{df -i} to see how plentiful your inode supply is.) If this
+slows you down or takes up very much space, a non-block-structured
 file system.
 
 Since maildirs don't require locking for delivery, the maildirs you use
index ad56520f8923165bb4a3e77bbf95e99b5338af7e..8e9eca55177bdaf5466aa9c41fc690f2a74e6086 100644 (file)
@@ -1149,11 +1149,8 @@ If you have imported your old PGP 2.x key into GnuPG, and want to send
 signed and encrypted messages to your fellow PGP 2.x users, you'll
 discover that the receiver cannot understand what you send. One
 solution is to use PGP 2.x instead (i.e., if you use @code{pgg}, set
-@code{pgg-default-scheme} to @code{pgp}).  If you do want to use
-GnuPG, you can use a compatibility script called @code{gpg-2comp}
-available from
-@uref{http://muppet.faveve.uni-stuttgart.de/~gero/gpg-2comp/}.  You
-could also convince your fellow PGP 2.x users to convert to GnuPG.
+@code{pgg-default-scheme} to @code{pgp}). You could also convince your
+fellow PGP 2.x users to convert to GnuPG.
 @vindex mml-signencrypt-style-alist
 As a final workaround, you can make the sign and encryption work in
 two steps; separately sign, then encrypt a message.  If you would like
index b6c47cf342031c3e92fcc755b188a66d276a2bc9..3ef57f26e86a450ad3c38909d4777ce2f80e8542 100644 (file)
@@ -1,3 +1,22 @@
+2010-10-06  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * shr.el (shr-insert): Get 'space transition right.
+
+       * nnimap.el (nnimap-open-connection): Prepare to support
+       open-gnutls-stream.
+
+       * shr.el: Rearrange function order to be more logical.
+
+2010-10-06  Julien Danjou  <julien@danjou.info>
+
+       * nnrss.el (nnrss-check-group): Remove 404 URL in comment.
+       (nnrss-discover-feed): Remove 404 URL in docstring.
+
+       * nnir.el: Fix Swish-E URL.
+       Fix Namazu URL.
+
+       * message.el (message-change-subject): Remove 404 URL in a comment.
+
 2010-10-06  Katsumi Yamaoka  <yamaoka@jpl.org>
 
        * gnus-art.el (gnus-mime-view-part-as-type): Make it work when being
index 546f13af815044a43c0009e3bc20b1db6560fc13..d50e037ee00e82876a573c80e07ec7030db8dc6c 100644 (file)
@@ -2151,7 +2151,6 @@ Leading \"Re: \" is not stripped by this function.  Use the function
 
 (defun message-change-subject (new-subject)
   "Ask for NEW-SUBJECT header, append (was: <Old Subject>)."
-  ;; <URL:http://www.landfield.com/usefor/drafts/draft-ietf-usefor-useage--1.02.unpaged>
   (interactive
    (list
     (read-from-minibuffer "New subject: ")))
index d56e2f4b76ed50177907a61ed1e1fae469351f23..7d935e4ecd10b2838cde83fda6a4759d17f4f6c5 100644 (file)
@@ -317,13 +317,16 @@ textual parts.")
                   'starttls))
                '("imap"))
               ((memq nnimap-stream '(ssl tls))
-               (open-tls-stream
-                "*nnimap*" (current-buffer) nnimap-address
-                (setq port
-                      (or nnimap-server-port
-                          (if (netrc-find-service-number "imaps")
-                              "imaps"
-                            "993"))))
+               (funcall (if (and nil
+                                 (fboundp 'open-gnutls-stream))
+                            'open-gnutls-stream
+                          'open-tls-stream)
+                        "*nnimap*" (current-buffer) nnimap-address
+                        (setq port
+                              (or nnimap-server-port
+                                  (if (netrc-find-service-number "imaps")
+                                      "imaps"
+                                    "993"))))
                '("143" "993" "imap" "imaps"))
               (t
                (error "Unknown stream type: %s" nnimap-stream))))
index 7a5380c52bbdcb4c4f7e0831333392fb5e2592dc..3739cb8614fb39fe71334a8b1bc4d6bdb0cddf6a 100644 (file)
@@ -509,8 +509,7 @@ that it is for swish++, not Wais."
   :group 'nnir)
 
 ;; Swish-E.
-;; URL: http://sunsite.berkeley.edu/SWISH-E/
-;; New version: http://www.boe.es/swish-e
+;; URL: http://swish-e.org/
 ;; Variables `nnir-swish-e-index-file', `nnir-swish-e-program' and
 ;; `nnir-swish-e-additional-switches'
 
@@ -596,7 +595,7 @@ arrive at the correct group name, \"mail.misc\"."
   :type '(directory)
   :group 'nnir)
 
-;; Namazu engine, see <URL:http://ww.namazu.org/>
+;; Namazu engine, see <URL:http://www.namazu.org/>
 
 (defcustom nnir-namazu-program "namazu"
   "*Name of Namazu search executable."
index 32b4f4f116f9c75228f19c61350ca9dda1664eee..743fba53e52d4aa482e3c52741b488334b8ff8ad 100644 (file)
@@ -703,9 +703,6 @@ which RSS 2.0 allows."
            (push (list group nnrss-group-max url) nnrss-server-data)))
        (setq changed t))
       (setq xml (nnrss-fetch url)))
-    ;; See
-    ;; http://feeds.archive.org/validator/docs/howto/declare_namespaces.html
-    ;; for more RSS namespaces.
     (setq dc-ns (nnrss-get-namespace-prefix xml "http://purl.org/dc/elements/1.1/")
          rdf-ns (nnrss-get-namespace-prefix xml "http://www.w3.org/1999/02/22-rdf-syntax-ns#")
          rss-ns (nnrss-get-namespace-prefix xml "http://purl.org/rss/1.0/")
@@ -966,7 +963,7 @@ whether they are `offsite' or `onsite'."
 
 (defun nnrss-discover-feed (url)
   "Given a page, find an RSS feed using Mark Pilgrim's
-`ultra-liberal rss locator' (URL `http://diveintomark.org/2002/08/15.html')."
+`ultra-liberal rss locator'."
 
   (let ((parsed-page (nnrss-fetch url)))
 
index c7f94ebc6b3309291bfa77bffddaa38b986fde8d..e0bb868f40e372bac4cdfd418654971e3cb43e4c 100644 (file)
@@ -57,13 +57,17 @@ fit these criteria."
 This is used for cid: URLs, and the function is called with the
 cid: URL as the argument.")
 
+(defvar shr-width 70
+  "Frame width to use for rendering.")
+
+;;; Internal variables.
+
 (defvar shr-folding-mode nil)
 (defvar shr-state nil)
 (defvar shr-start nil)
 (defvar shr-indentation 0)
 (defvar shr-inhibit-images nil)
-
-(defvar shr-width 70)
+(defvar shr-list-mode nil)
 
 (defvar shr-map
   (let ((map (make-sparse-keymap)))
@@ -75,6 +79,64 @@ cid: URL as the argument.")
     (define-key map "\r" 'shr-browse-url)
     map))
 
+;; Public functions and commands.
+
+;;;###autoload
+(defun shr-insert-document (dom)
+  (let ((shr-state nil)
+       (shr-start nil))
+    (shr-descend (shr-transform-dom dom))))
+
+(defun shr-copy-url ()
+  "Copy the URL under point to the kill ring.
+If called twice, then try to fetch the URL and see whether it
+redirects somewhere else."
+  (interactive)
+  (let ((url (get-text-property (point) 'shr-url)))
+    (cond
+     ((not url)
+      (message "No URL under point"))
+     ;; Resolve redirected URLs.
+     ((equal url (car kill-ring))
+      (url-retrieve
+       url
+       (lambda (a)
+        (when (and (consp a)
+                   (eq (car a) :redirect))
+          (with-temp-buffer
+            (insert (cadr a))
+            (goto-char (point-min))
+            ;; Remove common tracking junk from the URL.
+            (when (re-search-forward ".utm_.*" nil t)
+              (replace-match "" t t))
+            (message "Copied %s" (buffer-string))
+            (copy-region-as-kill (point-min) (point-max)))))))
+     ;; Copy the URL to the kill ring.
+     (t
+      (with-temp-buffer
+       (insert url)
+       (copy-region-as-kill (point-min) (point-max))
+       (message "Copied %s" url))))))
+
+(defun shr-show-alt-text ()
+  "Show the ALT text of the image under point."
+  (interactive)
+  (let ((text (get-text-property (point) 'shr-alt)))
+    (if (not text)
+       (message "No image under point")
+      (message "%s" text))))
+
+(defun shr-browse-image ()
+  "Browse the image under point."
+  (interactive)
+  (let ((url (get-text-property (point) 'shr-image)))
+    (if (not url)
+       (message "No image under point")
+      (message "Browsing %s..." url)
+      (browse-url url))))
+
+;;; Utility functions.
+
 (defun shr-transform-dom (dom)
   (let ((result (list (pop dom))))
     (dolist (arg (pop dom))
@@ -87,12 +149,6 @@ cid: URL as the argument.")
        (push (shr-transform-dom sub) result)))
     (nreverse result)))
 
-;;;###autoload
-(defun shr-insert-document (dom)
-  (let ((shr-state nil)
-       (shr-start nil))
-    (shr-descend (shr-transform-dom dom))))
-
 (defun shr-descend (dom)
   (let ((function (intern (concat "shr-tag-" (symbol-name (car dom))) obarray)))
     (if (fboundp function)
@@ -107,10 +163,49 @@ cid: URL as the argument.")
      ((listp (cdr sub))
       (shr-descend sub)))))
 
-(defun shr-tag-p (cont)
-  (shr-ensure-paragraph)
-  (shr-generic cont)
-  (shr-ensure-paragraph))
+(defun shr-insert (text)
+  (when (eq shr-state 'image)
+    (insert "\n")
+    (setq shr-state nil))
+  (cond
+   ((eq shr-folding-mode 'none)
+    (insert text))
+   (t
+    (let ((first t)
+         column)
+      (when (and (string-match "\\`[ \t\n]" text)
+                (not (bolp)))
+       (insert " ")
+       (setq shr-state 'space))
+      (dolist (elem (split-string text))
+       (setq column (current-column))
+       (when (> column 0)
+         (cond
+          ((and (or (not first)
+                    (eq shr-state 'space))
+                (> (+ column (length elem) 1) shr-width))
+           (insert "\n"))
+          ((not first)
+           (insert " "))))
+       (setq first nil)
+       (when (and (bolp)
+                  (> shr-indentation 0))
+         (shr-indent))
+       ;; The shr-start is a special variable that is used to pass
+       ;; upwards the first point in the buffer where the text really
+       ;; starts.
+       (unless shr-start
+         (setq shr-start (point)))
+       (insert elem))
+      (setq shr-state nil)
+      (when (and (string-match "[ \t\n]\\'" text)
+                (not (bolp)))
+       (insert " ")
+       (setq shr-state 'space))))))
+
+(defun shr-ensure-newline ()
+  (unless (zerop (current-column))
+    (insert "\n")))
 
 (defun shr-ensure-paragraph ()
   (unless (bobp)
@@ -125,20 +220,8 @@ cid: URL as the argument.")
          (insert "\n")
        (insert "\n\n")))))
 
-(defun shr-tag-b (cont)
-  (shr-fontize-cont cont 'bold))
-
-(defun shr-tag-i (cont)
-  (shr-fontize-cont cont 'italic))
-
-(defun shr-tag-em (cont)
-  (shr-fontize-cont cont 'bold))
-
-(defun shr-tag-u (cont)
-  (shr-fontize-cont cont 'underline))
-
-(defun shr-tag-s (cont)
-  (shr-fontize-cont cont 'strike-through))
+(defun shr-indent ()
+  (insert (make-string shr-indentation ? )))
 
 (defun shr-fontize-cont (cont &rest types)
   (let (shr-start)
@@ -150,17 +233,6 @@ cid: URL as the argument.")
   (let ((overlay (make-overlay start end)))
     (overlay-put overlay 'face type)))
 
-(defun shr-tag-a (cont)
-  (let ((url (cdr (assq :href cont)))
-       (start (point))
-       shr-start)
-    (shr-generic cont)
-    (widget-convert-button
-     'link (or shr-start start) (point)
-     :help-echo url)
-    (put-text-property (or shr-start start) (point) 'keymap shr-map)
-    (put-text-property (or shr-start start) (point) 'shr-url url)))
-
 (defun shr-browse-url ()
   "Browse the URL under point."
   (interactive)
@@ -169,94 +241,6 @@ cid: URL as the argument.")
        (message "No link under point")
       (browse-url url))))
 
-(defun shr-copy-url ()
-  "Copy the URL under point to the kill ring.
-If called twice, then try to fetch the URL and see whether it
-redirects somewhere else."
-  (interactive)
-  (let ((url (get-text-property (point) 'shr-url)))
-    (cond
-     ((not url)
-      (message "No URL under point"))
-     ;; Resolve redirected URLs.
-     ((equal url (car kill-ring))
-      (url-retrieve
-       url
-       (lambda (a)
-        (when (and (consp a)
-                   (eq (car a) :redirect))
-          (with-temp-buffer
-            (insert (cadr a))
-            (goto-char (point-min))
-            ;; Remove common tracking junk from the URL.
-            (when (re-search-forward ".utm_.*" nil t)
-              (replace-match "" t t))
-            (message "Copied %s" (buffer-string))
-            (copy-region-as-kill (point-min) (point-max)))))))
-     ;; Copy the URL to the kill ring.
-     (t
-      (with-temp-buffer
-       (insert url)
-       (copy-region-as-kill (point-min) (point-max))
-       (message "Copied %s" url))))))
-
-(defun shr-tag-img (cont)
-  (when (and (> (current-column) 0)
-            (not (eq shr-state 'image)))
-    (insert "\n"))
-  (let ((start (point-marker)))
-    (let ((alt (cdr (assq :alt cont)))
-         (url (cdr (assq :src cont))))
-      (when (zerop (length alt))
-       (setq alt "[img]"))
-      (cond
-       ((and (not shr-inhibit-images)
-            (string-match "\\`cid:" url))
-       (let ((url (substring url (match-end 0)))
-             image)
-         (if (or (not shr-content-function)
-                 (not (setq image (funcall shr-content-function url))))
-             (insert alt)
-           (shr-put-image image (point) alt))))
-       ((or shr-inhibit-images
-           (and shr-blocked-images
-                (string-match shr-blocked-images url)))
-       (setq shr-start (point))
-       (let ((shr-state 'space))
-         (if (> (length alt) 8)
-             (shr-insert (substring alt 0 8))
-           (shr-insert alt))))
-       ((url-is-cached (browse-url-url-encode-chars url "[&)$ ]"))
-       (shr-put-image (shr-get-image-data url) (point) alt))
-       (t
-       (insert alt)
-       (ignore-errors
-         (url-retrieve url 'shr-image-fetched
-                       (list (current-buffer) start (point-marker))
-                       t))))
-      (insert " ")
-      (put-text-property start (point) 'keymap shr-map)
-      (put-text-property start (point) 'shr-alt alt)
-      (put-text-property start (point) 'shr-image url)
-      (setq shr-state 'image))))
-
-(defun shr-show-alt-text ()
-  "Show the ALT text of the image under point."
-  (interactive)
-  (let ((text (get-text-property (point) 'shr-alt)))
-    (if (not text)
-       (message "No image under point")
-      (message "%s" text))))
-
-(defun shr-browse-image ()
-  "Browse the image under point."
-  (interactive)
-  (let ((url (get-text-property (point) 'shr-image)))
-    (if (not url)
-       (message "No image under point")
-      (message "Browsing %s..." url)
-      (browse-url url))))
-
 (defun shr-image-fetched (status buffer start end)
   (when (and (buffer-name buffer)
             (not (plist-get status :error)))
@@ -306,64 +290,6 @@ redirects somewhere else."
                     image)))
       image)))
 
-(defun shr-tag-pre (cont)
-  (let ((shr-folding-mode 'none))
-    (shr-ensure-newline)
-    (shr-generic cont)
-    (shr-ensure-newline)))
-
-(defun shr-tag-blockquote (cont)
-  (shr-ensure-paragraph)
-  (let ((shr-indentation (+ shr-indentation 4)))
-    (shr-generic cont))
-  (shr-ensure-paragraph))
-
-(defun shr-ensure-newline ()
-  (unless (zerop (current-column))
-    (insert "\n")))
-
-(defun shr-insert (text)
-  (when (eq shr-state 'image)
-    (insert "\n")
-    (setq shr-state nil))
-  (cond
-   ((eq shr-folding-mode 'none)
-    (insert text))
-   (t
-    (let ((first t)
-         column)
-      (when (and (string-match "\\`[ \t\n]" text)
-                (not (bolp)))
-       (insert " "))
-      (dolist (elem (split-string text))
-       (setq column (current-column))
-       (when (> column 0)
-         (cond
-          ((and (or (not first)
-                    (eq shr-state 'space))
-                (> (+ column (length elem) 1) shr-width))
-           (insert "\n"))
-          ((not first)
-           (insert " "))))
-       (setq first nil)
-       (when (and (bolp)
-                  (> shr-indentation 0))
-         (shr-indent))
-       ;; The shr-start is a special variable that is used to pass
-       ;; upwards the first point in the buffer where the text really
-       ;; starts.
-       (unless shr-start
-         (setq shr-start (point)))
-       (insert elem))
-      (setq shr-state nil)
-      (when (and (string-match "[ \t\n]\\'" text)
-                (not (bolp)))
-       (insert " ")
-       (setq shr-state 'space))))))
-
-(defun shr-indent ()
-  (insert (make-string shr-indentation ? )))
-
 (defun shr-get-image-data (url)
   "Get image data for URL.
 Return a string with image data."
@@ -376,7 +302,95 @@ Return a string with image data."
                (search-forward "\r\n\r\n" nil t))
        (buffer-substring (point) (point-max))))))
 
-(defvar shr-list-mode nil)
+(defun shr-heading (cont &rest types)
+  (shr-ensure-paragraph)
+  (apply #'shr-fontize-cont cont types)
+  (shr-ensure-paragraph))
+
+;;; Tag-specific rendering rules.
+
+(defun shr-tag-p (cont)
+  (shr-ensure-paragraph)
+  (shr-generic cont)
+  (shr-ensure-paragraph))
+
+(defun shr-tag-b (cont)
+  (shr-fontize-cont cont 'bold))
+
+(defun shr-tag-i (cont)
+  (shr-fontize-cont cont 'italic))
+
+(defun shr-tag-em (cont)
+  (shr-fontize-cont cont 'bold))
+
+(defun shr-tag-u (cont)
+  (shr-fontize-cont cont 'underline))
+
+(defun shr-tag-s (cont)
+  (shr-fontize-cont cont 'strike-through))
+
+(defun shr-tag-a (cont)
+  (let ((url (cdr (assq :href cont)))
+       (start (point))
+       shr-start)
+    (shr-generic cont)
+    (widget-convert-button
+     'link (or shr-start start) (point)
+     :help-echo url)
+    (put-text-property (or shr-start start) (point) 'keymap shr-map)
+    (put-text-property (or shr-start start) (point) 'shr-url url)))
+
+(defun shr-tag-img (cont)
+  (when (and (> (current-column) 0)
+            (not (eq shr-state 'image)))
+    (insert "\n"))
+  (let ((start (point-marker)))
+    (let ((alt (cdr (assq :alt cont)))
+         (url (cdr (assq :src cont))))
+      (when (zerop (length alt))
+       (setq alt "[img]"))
+      (cond
+       ((and (not shr-inhibit-images)
+            (string-match "\\`cid:" url))
+       (let ((url (substring url (match-end 0)))
+             image)
+         (if (or (not shr-content-function)
+                 (not (setq image (funcall shr-content-function url))))
+             (insert alt)
+           (shr-put-image image (point) alt))))
+       ((or shr-inhibit-images
+           (and shr-blocked-images
+                (string-match shr-blocked-images url)))
+       (setq shr-start (point))
+       (let ((shr-state 'space))
+         (if (> (length alt) 8)
+             (shr-insert (substring alt 0 8))
+           (shr-insert alt))))
+       ((url-is-cached (browse-url-url-encode-chars url "[&)$ ]"))
+       (shr-put-image (shr-get-image-data url) (point) alt))
+       (t
+       (insert alt)
+       (ignore-errors
+         (url-retrieve url 'shr-image-fetched
+                       (list (current-buffer) start (point-marker))
+                       t))))
+      (insert " ")
+      (put-text-property start (point) 'keymap shr-map)
+      (put-text-property start (point) 'shr-alt alt)
+      (put-text-property start (point) 'shr-image url)
+      (setq shr-state 'image))))
+
+(defun shr-tag-pre (cont)
+  (let ((shr-folding-mode 'none))
+    (shr-ensure-newline)
+    (shr-generic cont)
+    (shr-ensure-newline)))
+
+(defun shr-tag-blockquote (cont)
+  (shr-ensure-paragraph)
+  (let ((shr-indentation (+ shr-indentation 4)))
+    (shr-generic cont))
+  (shr-ensure-paragraph))
 
 (defun shr-tag-ul (cont)
   (shr-ensure-paragraph)
@@ -422,10 +436,7 @@ Return a string with image data."
 (defun shr-tag-h6 (cont)
   (shr-heading cont))
 
-(defun shr-heading (cont &rest types)
-  (shr-ensure-paragraph)
-  (apply #'shr-fontize-cont cont types)
-  (shr-ensure-paragraph))
+;;; Table rendering algorithm.
 
 ;; Table rendering is the only complicated thing here.  We do this by
 ;; first counting how many TDs there are in each TR, and registering