X-Git-Url: http://cgit.sxemacs.org/?p=gnus;a=blobdiff_plain;f=lisp%2Fshr.el;h=ce98ab830711bdb7fde7707d87326ef9b2dae435;hp=9381eb548d306fdf096d74e560b1fb8efba83223;hb=789c31bee0f2558e907a9d174afae38fc44092d6;hpb=b8aa284d45434ca73256407dbafc5e5873e9b4ac diff --git a/lisp/shr.el b/lisp/shr.el index 9381eb548..ce98ab830 100644 --- a/lisp/shr.el +++ b/lisp/shr.el @@ -35,6 +35,7 @@ (defgroup shr nil "Simple HTML Renderer" + :version "24.1" :group 'mail) (defcustom shr-max-image-proportion 0.9 @@ -160,7 +161,7 @@ DOM should be a parse tree as generated by (goto-char start) (while (not (eobp)) (end-of-line) - (when (> (current-column) width) + (when (> (shr-previous-newline-padding-width (current-column)) width) (dolist (overlay (overlays-at (point))) (when (overlay-get overlay 'before-string) (overlay-put overlay 'before-string nil)))) @@ -189,7 +190,8 @@ redirects somewhere else." (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-region-as-kill (point-min) (point-max))))) + nil t)) ;; Copy the URL to the kill ring. (t (with-temp-buffer @@ -232,7 +234,7 @@ the URL of the image to the kill buffer instead." (message "Inserting %s..." url) (url-retrieve url 'shr-image-fetched (list (current-buffer) (1- (point)) (point-marker)) - t)))) + t t)))) (defun shr-zoom-image () "Toggle the image size. @@ -331,6 +333,7 @@ size, and full-buffer size." (defun shr-insert (text) (when (and (eq shr-state 'image) + (not (bolp)) (not (string-match "\\`[ \t\n]+\\'" text))) (insert "\n") (setq shr-state nil)) @@ -338,11 +341,11 @@ size, and full-buffer size." ((eq shr-folding-mode 'none) (insert text)) (t - (when (and (string-match "\\`[ \t\n]" text) + (when (and (string-match "\\`[ \t\n ]" text) (not (bolp)) (not (eq (char-after (1- (point))) ? ))) (insert " ")) - (dolist (elem (split-string text)) + (dolist (elem (split-string text "[ \f\t\n\r\v ]+" t)) (when (and (bolp) (> shr-indentation 0)) (shr-indent)) @@ -365,6 +368,7 @@ size, and full-buffer size." (unless shr-start (setq shr-start (point))) (insert elem) + (setq shr-state nil) (let (found) (while (and (> (current-column) shr-width) (progn @@ -374,7 +378,6 @@ size, and full-buffer size." (delete-char -1)) (insert "\n") (unless found - (put-text-property (1- (point)) (point) 'shr-break t) ;; No space is needed at the beginning of a line. (when (eq (following-char) ? ) (delete-char 1))) @@ -382,7 +385,7 @@ size, and full-buffer size." (shr-indent)) (end-of-line)) (insert " "))) - (unless (string-match "[ \t\n]\\'" text) + (unless (string-match "[ \t\n ]\\'" text) (delete-char -1))))) (defun shr-find-fill-point () @@ -441,32 +444,29 @@ size, and full-buffer size." (shr-char-kinsoku-eol-p (following-char))))) (goto-char bp))) ((shr-char-kinsoku-eol-p (preceding-char)) - (if (shr-char-kinsoku-eol-p (following-char)) - ;; There are consecutive kinsoku-eol characters. - (setq failed t) - (let ((count 4)) - (while - (progn - (backward-char 1) - (and (> (setq count (1- count)) 0) - (not (memq (preceding-char) (list ?\C-@ ?\n ? ))) - (or (shr-char-kinsoku-eol-p (preceding-char)) - (shr-char-kinsoku-bol-p (following-char))))))) - (if (setq failed (= (current-column) shr-indentation)) - ;; There's no breakable point that doesn't violate kinsoku, - ;; so we go to the second best position. - (if (looking-at "\\(\\c<+\\)\\c<") - (goto-char (match-end 1)) - (forward-char 1))))) - (t - (if (shr-char-kinsoku-bol-p (preceding-char)) - ;; There are consecutive kinsoku-bol characters. - (setq failed t) - (let ((count 4)) - (while (and (>= (setq count (1- count)) 0) + ;; Find backward the point where kinsoku-eol characters begin. + (let ((count 4)) + (while + (progn + (backward-char 1) + (and (> (setq count (1- count)) 0) + (not (memq (preceding-char) (list ?\C-@ ?\n ? ))) + (or (shr-char-kinsoku-eol-p (preceding-char)) + (shr-char-kinsoku-bol-p (following-char))))))) + (if (setq failed (= (current-column) shr-indentation)) + ;; There's no breakable point that doesn't violate kinsoku, + ;; so we go to the second best position. + (if (looking-at "\\(\\c<+\\)\\c<") + (goto-char (match-end 1)) + (forward-char 1)))) + ((shr-char-kinsoku-bol-p (following-char)) + ;; Find forward the point where kinsoku-bol characters end. + (let ((count 4)) + (while (progn + (forward-char 1) + (and (>= (setq count (1- count)) 0) (shr-char-kinsoku-bol-p (following-char)) - (shr-char-breakable-p (following-char))) - (forward-char 1)))))) + (shr-char-breakable-p (following-char)))))))) (when (eq (following-char) ? ) (forward-char 1)))) (not failed))) @@ -498,7 +498,7 @@ size, and full-buffer size." (if (save-excursion (beginning-of-line) (looking-at " *$")) - (insert "\n") + (delete-region (match-beginning 0) (match-end 0)) (insert "\n\n"))))) (defun shr-indent () @@ -545,7 +545,8 @@ size, and full-buffer size." (if (not url) (message "No link under point") (url-retrieve (shr-encode-url url) - 'shr-store-contents (list url directory))))) + 'shr-store-contents (list url directory) + nil t)))) (defun shr-store-contents (status url directory) (unless (plist-get status :error) @@ -556,26 +557,27 @@ size, and full-buffer size." directory))))) (defun shr-image-fetched (status buffer start end &optional flags) - (when (and (buffer-name buffer) - (not (plist-get status :error))) - (url-store-in-cache (current-buffer)) - (when (or (search-forward "\n\n" nil t) - (search-forward "\r\n\r\n" nil t)) - (let ((data (buffer-substring (point) (point-max)))) - (with-current-buffer buffer - (save-excursion - (let ((alt (buffer-substring start end)) - (properties (text-properties-at start)) - (inhibit-read-only t)) - (delete-region start end) - (goto-char start) - (funcall shr-put-image-function data alt flags) - (while properties - (let ((type (pop properties)) - (value (pop properties))) - (unless (memq type '(display image-size)) - (put-text-property start (point) type value)))))))))) - (kill-buffer (current-buffer))) + (let ((image-buffer (current-buffer))) + (when (and (buffer-name buffer) + (not (plist-get status :error))) + (url-store-in-cache image-buffer) + (when (or (search-forward "\n\n" nil t) + (search-forward "\r\n\r\n" nil t)) + (let ((data (buffer-substring (point) (point-max)))) + (with-current-buffer buffer + (save-excursion + (let ((alt (buffer-substring start end)) + (properties (text-properties-at start)) + (inhibit-read-only t)) + (delete-region start end) + (goto-char start) + (funcall shr-put-image-function data alt flags) + (while properties + (let ((type (pop properties)) + (value (pop properties))) + (unless (memq type '(display image-size)) + (put-text-property start (point) type value)))))))))) + (kill-buffer image-buffer))) (defun shr-put-image (data alt &optional flags) "Put image DATA with a string ALT. Return image." @@ -676,7 +678,7 @@ START, and END. Note that START and END should be markers." (delete-region (point) end)))) (url-retrieve url 'shr-image-fetched (list (current-buffer) start end) - t))))) + t t))))) (defun shr-heading (cont &rest types) (shr-ensure-paragraph) @@ -766,7 +768,7 @@ ones, in case fg and bg are nil." (forward-line 1) (setq end (point)) (narrow-to-region start end) - (let ((width (shr-natural-width)) + (let ((width (shr-buffer-width)) column) (goto-char (point-min)) (while (not (eobp)) @@ -986,13 +988,10 @@ ones, in case fg and bg are nil." (let ((file (url-cache-create-filename (shr-encode-url url)))) (when (file-exists-p file) (delete-file file)))) - (funcall - (if (fboundp 'url-queue-retrieve) - 'url-queue-retrieve - 'url-retrieve) + (url-queue-retrieve (shr-encode-url url) 'shr-image-fetched (list (current-buffer) start (set-marker (make-marker) (1- (point)))) - t))) + t t))) (when (zerop shr-table-depth) ;; We are not in a table. (put-text-property start (point) 'keymap shr-map) (put-text-property start (point) 'shr-alt alt) @@ -1042,7 +1041,12 @@ ones, in case fg and bg are nil." (shr-generic cont))) (defun shr-tag-br (cont) - (unless (bobp) + (when (and (not (bobp)) + ;; Only add a newline if we break the current line, or + ;; the previous line isn't a blank line. + (or (not (bolp)) + (and (> (- (point) 2) (point-min)) + (not (= (char-after (- (point) 2)) ?\n))))) (insert "\n") (shr-indent)) (shr-generic cont)) @@ -1106,7 +1110,10 @@ ones, in case fg and bg are nil." ;; be smaller (if there's little text) or bigger (if there's ;; unbreakable text). (sketch (shr-make-table cont suggested-widths)) - (sketch-widths (shr-table-widths sketch suggested-widths))) + ;; Compute the "natural" width by setting each column to 500 + ;; characters and see how wide they really render. + (natural (shr-make-table cont (make-vector (length columns) 500))) + (sketch-widths (shr-table-widths sketch natural suggested-widths))) ;; This probably won't work very well. (when (> (+ (loop for width across sketch-widths summing (1+ width)) @@ -1244,31 +1251,35 @@ ones, in case fg and bg are nil." shr-table-corner)) (insert "\n")) -(defun shr-table-widths (table suggested-widths) +(defun shr-table-widths (table natural-table suggested-widths) (let* ((length (length suggested-widths)) (widths (make-vector length 0)) (natural-widths (make-vector length 0))) (dolist (row table) (let ((i 0)) (dolist (column row) - (aset widths i (max (aref widths i) - (car column))) - (aset natural-widths i (max (aref natural-widths i) - (cadr column))) + (aset widths i (max (aref widths i) column)) + (setq i (1+ i))))) + (dolist (row natural-table) + (let ((i 0)) + (dolist (column row) + (aset natural-widths i (max (aref natural-widths i) column)) (setq i (1+ i))))) (let ((extra (- (apply '+ (append suggested-widths nil)) (apply '+ (append widths nil)))) (expanded-columns 0)) + ;; We have extra, unused space, so divide this space amongst the + ;; columns. (when (> extra 0) + ;; If the natural width is wider than the rendered width, we + ;; want to allow the column to expand. (dotimes (i length) - ;; If the natural width is wider than the rendered width, we - ;; want to allow the column to expand. (when (> (aref natural-widths i) (aref widths i)) (setq expanded-columns (1+ expanded-columns)))) (dotimes (i length) (when (> (aref natural-widths i) (aref widths i)) (aset widths i (min - (1+ (aref natural-widths i)) + (aref natural-widths i) (+ (/ extra expanded-columns) (aref widths i)))))))) widths)) @@ -1323,10 +1334,13 @@ ones, in case fg and bg are nil." (let ((shr-width width) (shr-indentation 0)) (shr-descend (cons 'td cont))) + ;; Delete padding at the bottom of the TDs. (delete-region (point) - (+ (point) - (skip-chars-backward " \t\n"))) + (progn + (skip-chars-backward " \t\n") + (end-of-line) + (point))) (push (list (cons width cont) (buffer-string) (shr-overlays-in-region (point-min) (point-max))) shr-content-cache))) @@ -1360,19 +1374,14 @@ ones, in case fg and bg are nil." (split-string (buffer-string) "\n") (shr-collect-overlays) (car actual-colors)) - (list max - (shr-natural-width))))))) + max))))) -(defun shr-natural-width () +(defun shr-buffer-width () (goto-char (point-min)) - (let ((current 0) - (max 0)) + (let ((max 0)) (while (not (eobp)) (end-of-line) - (setq current (+ current (current-column))) - (unless (get-text-property (point) 'shr-break) - (setq max (max max current) - current 0)) + (setq max (max max (current-column))) (forward-line 1)) max)) @@ -1422,10 +1431,10 @@ ones, in case fg and bg are nil." (when (memq (car column) '(td th)) (let ((width (cdr (assq :width (cdr column))))) (when (and width - (string-match "\\([0-9]+\\)%" width)) - (aset columns i - (/ (string-to-number (match-string 1 width)) - 100.0)))) + (string-match "\\([0-9]+\\)%" width) + (not (zerop (setq width (string-to-number + (match-string 1 width)))))) + (aset columns i (/ width 100.0)))) (setq i (1+ i))))))) columns))