[Date Prev][Date Next][Thread Prev][][Date Index][Thread Index]

w3m-lnum: yet another selection workflow



Hello,

while happily w3m-lnum-follow-ing and such, I noticed a common pattern
over less known web pages.  During selection or just about to do it, I
wish I could have chosen another action.  In this case I have to cancel
current selection and invoke a new one with the desired action.  So far
the commands provided are of the form: first determine action, then
select element.  The nice part is that selection can be confined over
specific type of elements.  But what about the other way around: firstly
select element and then get a list of possible actions!  This is what
I've added this time.  You first do a selection over all anchors and
then a pop-up buffer offers you a list of possible (of course
customizable ;)) actions which may be selected with a key, mouse or by
moving within this buffer and hitting return.  It's also a nice way to
expose anchor functions without much looking/providing key-bindings and
documentation (for newcomers at least).

Another smaller addition is interactive resizing of images.  You know
for example in GNU/Emacs after initially changing font size with C-x
C-+/-, you get immediate chance by just hitting +/-/0 to further refine
font size or get it to initial state.  This is what's added to the lnum
resizing commands/actions for images.

As before, I've only tested (for few weeks now and squashed whatever
bugs found) on GNU/Emacs >= 24.0.90 so compatibility corrections or
whatever other for other Emacsen are welcomed.  I suspect mouse
selection is a weak point but it's somewhat detached from the idea of
link numbering anyway.

I didn't quite know where to put `w3m-resize-image-interactive' as it's
general but at the same time not belonging to w3m-image.el for not being
concerned with external image operations.

I was wondering what key to choose for `w3m-lnum-universal'.  In the end
settled on `w' (not in the lynx or info style keymaps), but other
possibilities like `L' might be good, if someone has better idea, just
say.  Of course by default it's reachable by first hitting `L'.

Here's a cvs diff:


Index: ChangeLog
===================================================================
RCS file: /storage/cvsroot/emacs-w3m/ChangeLog,v
retrieving revision 1.3384
diff -r1.3384 ChangeLog
0a1,37
> 2011-11-16  Andrey Kotlarski  <m00naticus@xxxxxxxxx>
> 
> 	Add alternative selection->action method.
> 
> 	* w3m-lnum.el: Update comment section.
> 	(w3m-lnum-quick-browsing): Change default value.
> 	(w3m-lnum-actions-general, w3m-lnum-actions-image-alist)
> 	(w3m-lnum-actions-link-alist, w3m-lnum-actions-button-alist)
> 	(w3m-lnum-actions-form-alist): New custom options.
> 	(w3m-lnum-remove-overlays): Add optional parameters for start and end.
> 	(w3m-lnum, w3m-lnum-prompt-str, w3m-lnum-highlight-anchor): Sanitize
> 	variable naming.
> 	(w3m-read-event, w3m-lnum-visit, w3m-lnum-make-action): New macros.
> 	(w3m-lnum-read-interactive): Add optional parameters for previous filter
> 	and selected number.  Return last applied filter along selected value.
> 	Use `w3m-read-event'.  Remove lnum overlays within all buffer on
> 	scroll.
> 	(w3m-with-lnum): Add parameter for initial filter.  Change mode-line
> 	during selection.
> 	(w3m-lnum-get-action): If single image during image selection -
> 	immediately select it.  Accommodate to new return format of
> 	`w3m-lnum-read-interactive'.
> 	(w3m-lnum-follow): Use `w3m-lnum-visit'.
> 	(w3m-lnum-universal-dispatch): New function.
> 	(w3m-lnum-universal): New command.
> 	(w3m-lnum-view-image, w3m-lnum-save-image, w3m-lnum-print-this-url):
> 	Use nth.
> 	(w3m-lnum-zoom-image): Use `w3m-resize-image-interactive'.
> 	(w3m-lnum-zoom-in-image, w3m-lnum-zoom-out-image): Update doc string.
> 	(w3m-lnum-bookmark-add-this-url): Fix bookmarking of current url.
> 	(w3m-lnum-actions-link-alist): Add actions for generic browser and Curl
> 	if present.
> 
> 	* w3m.el (autoload): Autoload `w3m-lnum-universal'.
> 	(w3m-resize-image-interactive): New function.
> 	(w3m-lnum-map): Add key for `w3m-lnum-universal'.
> 
Index: w3m-lnum.el
===================================================================
RCS file: /storage/cvsroot/emacs-w3m/w3m-lnum.el,v
retrieving revision 1.34
diff -r1.34 w3m-lnum.el
31c31
< ;; for quickly navigating to links, form fields images or buttons and
---
> ;; for quickly navigating to links, form fields images or buttons;
33c33,35
< ;; toggling images or pushing buttons.
---
> ;; toggling images or pushing buttons and `w3m-lnum-universal' for
> ;; selecting whatever element and then giving relevant options
> ;; depending on what is selected.
82c84
< (defcustom w3m-lnum-quick-browsing nil
---
> (defcustom w3m-lnum-quick-browsing 'quick-numbers
84,86c86,88
< `quick-numbers' quick selection only when entering numbers.
< `quick-filter' ditto only when filtering.
< `quick-all' always quick selecting."
---
> `quick-numbers' quick selection only when entering numbers
> `quick-filter' ditto only when filtering
> `quick-all' always quick selecting"
95c97
<   "Alist specifying number of additional items to be numbered after
---
>   "Alist specifying number of additional items to be numbered after \
99a102,197
> (defcustom w3m-lnum-actions-general
>   '("----  Default   ----"
>     (?F (lambda (info) (push-mark (point))
> 	  (goto-char (cadr info))) "Move to anchor"))
>   "Alist specifying keycodes and available actions over selected anchor."
>   :group 'w3m
>   :type 'alist)
> 
> (defcustom w3m-lnum-actions-image-alist
>   '("----  Image  ----"
>     (?t (lambda (info) (goto-char (cadr info))
> 	  (w3m-toggle-inline-image)) "Goto image and toggle it")
>     (?T (lambda (info) (save-excursion (goto-char (cadr info))
> 				  (w3m-toggle-inline-image)))
> 	"Toggle")
>     (?O (lambda (info) (w3m-external-view (nth 2 info))) "View externally")
>     (?S (lambda (info) (w3m-download (nth 2 info))) "Save")
>     (?r (lambda (info) (w3m-lnum-remove-overlays) ;some images invoke scrolling
> 	  (goto-char (cadr info))
> 	  (w3m-resize-image-interactive (car info))) "Resize"))
>   "Alist specifying keycodes and available actions over a selected image."
>   :group 'w3m
>   :type 'alist)
> 
> (defcustom w3m-lnum-actions-link-alist
>   '("----  Link   ----"
>     (?g (lambda (info) (w3m-lnum-visit info)) "Visit")
>     (?G (lambda (info) (setq mode-line-format original-mode-line-format)
> 	  (w3m-lnum-remove-overlays)
> 	  (w3m-lnum-visit info t)) "Visit in new session")
>     (?v (lambda (info) (w3m-lnum-visit info nil t)) "Edit and visit")
>     (?V (lambda (info) (setq mode-line-format original-mode-line-format)
> 	  (w3m-lnum-remove-overlays)
> 	  (w3m-lnum-visit info t t))
> 	"Edit and visit in new session")
>     (?e (lambda (info) (w3m-edit-url (car info))) "Edit page")
>     (?s (lambda (info) (save-excursion
> 		    (goto-char (cadr info))
> 		    (w3m-download-this-url))) "Download")
>     (?b (lambda (info)
> 	  (w3m-bookmark-add
> 	   (car info)
> 	   (let ((pos (cadr info)))
> 	     (if (= pos 16)		; 0th anchor selected
> 		 w3m-current-title
> 	       (buffer-substring-no-properties
> 		(previous-single-property-change (1+ pos)
> 						 'w3m-href-anchor)
> 		(next-single-property-change pos
> 					     'w3m-href-anchor))))))
> 	"Add to bookmarks")
>     (?u (lambda (info)
> 	  (let ((url (car info)))
> 	    (kill-new url)
> 	    (w3m-message "%s%s" (let ((im-alt (nth 3 info)))
> 				  (if (zerop (length im-alt)) ""
> 				    (concat im-alt ": ")))
> 			 url)))
> 	"Copy")
>     (?M (lambda (info) (w3m-external-view (car info)))
> 	"Open in external browser"))
>   "Alist specifying keycodes and available actions over a selected link."
>   :group 'w3m
>   :type 'alist)
> 
> (defcustom w3m-lnum-actions-button-alist
>   '("---- Button  ----"
>     (?p (lambda (info) (push-mark (point))
> 	  (goto-char (cadr info))
> 	  (widget-button-press (cadr info) (car info)))
> 	"Goto button and push it")
>     (?P (lambda (info) (widget-button-press (cadr info) (car info)))
> 	"Push"))
>   "Alist specifying keycodes and available actions over a selected button."
>   :group 'w3m
>   :type 'alist)
> 
> (defcustom w3m-lnum-actions-form-alist
>   '("----  Form   ----"
>     (?p (lambda (info) (setq mode-line-format original-mode-line-format)
> 	  (w3m-lnum-remove-overlays)
> 	  (push-mark (point))
> 	  (goto-char (cadr info))
> 	  (let ((w3m-form-new-session t)
> 		(w3m-form-download nil))
> 	    (eval action))) "Goto form and activate it")
>     (?P (lambda (info) (w3m-lnum-remove-overlays)
> 	  (save-excursion
> 	    (goto-char (cadr info))
> 	    (let ((w3m-form-new-session nil)
> 		  (w3m-form-download nil))
> 	      (eval action)))) "Activate"))
>   "Alist specifying keycodes and available actions over a selected form field."
>   :group 'w3m
>   :type 'alist)
> 
105a204
>     (define-key map "w" 'w3m-lnum-universal)
129,135c228,236
< (defun w3m-lnum-remove-overlays ()
<   "Remove numbering and match overlays."
<   (dolist (overlay (overlays-in (max (1- (window-start)) (point-min))
< 				(min (window-end) (point-max))))
<     (if (or (overlay-get overlay 'w3m-lnum-overlay)
< 	    (overlay-get overlay 'w3m-lnum-match))
< 	(delete-overlay overlay))))
---
> (defun w3m-lnum-remove-overlays (&optional start end)
>   "Remove numbering and match overlays between START and END points.
> If missing, clear the current visible window."
>   (let ((start (or start (max (1- (window-start)) (point-min))))
> 	(end (or end (min (window-end) (point-max)))))
>     (dolist (overlay (overlays-in start end))
>       (if (or (overlay-get overlay 'w3m-lnum-overlay)
> 	      (overlay-get overlay 'w3m-lnum-match))
> 	  (delete-overlay overlay)))))
253c354
< (defun w3m-lnum (arg &optional str dont-clear-p)
---
> (defun w3m-lnum (arg &optional filter dont-clear-p)
257c358
< STR is filter string for anchor text.
---
> FILTER is filter string for anchor text.
263c364
< 			    str dont-clear-p)))
---
> 			    filter dont-clear-p)))
265c366
< (defmacro w3m-lnum-prompt-str (num fun start def-anchor str
---
> (defmacro w3m-lnum-prompt-str (num fun start def-anchor filter
272c373
< STR is current string used for filtering.
---
> FILTER is current string used for filtering.
284c385
< 	     " " ,str anchor)))
---
> 	     " " ,filter anchor)))
286,287c387,402
< (defun w3m-lnum-read-interactive (prompt fun type last-index
< 					 &optional def-anchor)
---
> (defmacro w3m-read-event (prompt key)
>   "Read event with PROMPT and return keycode.
> KEY is what XEmacs gives for event-key."
>   (w3m-static-if (featurep 'xemacs)
>       `(progn
> 	 (display-message 'no-log ,prompt)
> 	 (let ((event (next-command-event)))
> 	   (if (key-press-event-p event)
> 	       (or (event-to-character event)
> 		   (characterp
> 		    (setq ,key (event-key event)))
> 		   ,key))))
>     `(read-event ,prompt t)))
> 
> (defun w3m-lnum-read-interactive (prompt fun type last-index &optional
> 					 def-anchor filter def-num)
290a406,407
> FILTER is the initial aplied filter.
> DEF-NUM is the initial selected element, 1 if not given.
296c413
< <CTRL>+<NUMBER> is appended to the filtering string as <NUMBER>.
---
> <CTRL>+<DIGIT> is appended to the filtering string as <DIGIT>.
298c415,416
< <return> on single possible selection."
---
> <return> on single possible selection.
> Return list of selected number and last applied filter."
301,305c419,421
< 	prompt (propertize prompt 'face
< 			   'w3m-lnum-minibuffer-prompt))
<   (let ((num 1)
< 	(str "")
< 	(auto-num t)
---
> 	prompt (propertize prompt 'face 'w3m-lnum-minibuffer-prompt))
>   (let ((filter (or filter ""))
> 	(auto-num (or (null def-num) (= def-num 0)))
307,388c423,434
<     (catch 'select
<       (let ((temp-prompt (w3m-lnum-prompt-str num fun prompt
< 					      def-anchor "" "")))
< 	(while (not (memq		; while not return or escape
< 		     (setq ch
< 			   (w3m-static-if (featurep 'xemacs)
< 			       (progn
< 				 (display-message 'no-log temp-prompt)
< 				 (let ((event (next-command-event)))
< 				   (if (key-press-event-p event)
< 				       (or (event-to-character event)
< 					   (characterp
< 					    (setq key (event-key event)))
< 					   key))))
< 			     (read-event temp-prompt t)))
< 		     '(return 10 13 ?\n ?\r ?\C-g escape 27 ?\e)))
< 	  (cond
< 	   ((memq ch '(backspace 8 ?\C-h))
< 	    (if auto-num
< 		(unless (string-equal str "") ; delete last filter character
< 		  (setq num 1
< 			last-index
< 			(w3m-lnum
< 			 type (setq str (w3m-substring-no-properties
< 					 str 0 (1- (length str)))))
< 			temp-prompt
< 			(w3m-lnum-prompt-str num fun prompt
< 					     def-anchor str "")))
< 	      (setq num (/ num 10))	; delete last digit
< 	      (if (zerop num)
< 		  (setq num 1
< 			auto-num t))
< 	      (setq temp-prompt
< 		    (w3m-lnum-prompt-str num fun prompt
< 					 def-anchor str
< 					 (if auto-num "")))))
< 	   ;; scroll options
< 	   ((memq ch '(32 ?\ ))		; scroll down
< 	    (w3m-lnum-remove-overlays)
< 	    (ignore-errors
< 	      (w3m-scroll-up-1)
< 	      (redisplay))   ; scroll-up sets wrongly window-start/end
< 	    #1=
< 	    (setq last-index (w3m-lnum type str t)
< 		  num (if (zerop last-index) 0 1)
< 		  auto-num t
< 		  temp-prompt (w3m-lnum-prompt-str num fun prompt
< 						   def-anchor
< 						   str "")))
< 	   ((eq ch 'delete)		; scroll up
< 	    (w3m-lnum-remove-overlays)
< 	    (ignore-errors (scroll-down nil))
< 	    #1#)
< 	   ((memq ch '(60 ?<)) (w3m-scroll-right nil))
< 	   ((memq ch '(62 ?>)) (w3m-scroll-left nil))
< 	   ;; iteration options
< 	   ((memq ch '(left up))
< 	    (if (> num 1)
< 		(setq num (1- num)
< 		      auto-num t
< 		      temp-prompt
< 		      (w3m-lnum-prompt-str num fun prompt
< 					   def-anchor str ""))))
< 	   ((memq ch '(right down))
< 	    (if (< num last-index)
< 		(setq num (1+ num)
< 		      auto-num t
< 		      temp-prompt
< 		      (w3m-lnum-prompt-str num fun prompt
< 					   def-anchor str ""))))
< 	   ((and (w3m-static-if (featurep 'xemacs) ; digit
< 		     (characterp ch)
< 		   (numberp ch))
< 		 (< 47 ch) (< ch 58))
< 	    (if auto-num
< 		(if (= ch 48)
< 		    (throw 'select (setq num 0))
< 		  (setq num (- ch 48)
< 			auto-num nil))
< 	      (setq num (+ (* num 10) ch -48)))
< 	    (if (> num last-index)
< 		(if (zerop (setq num (/ num 10)))
---
>     (let ((num (if auto-num 1 def-num)))
>       (catch 'select
> 	(let ((temp-prompt (w3m-lnum-prompt-str num fun prompt
> 						def-anchor filter
> 						(if auto-num ""))))
> 	  (while (not (memq		; while not return or escape
> 		       (setq ch (w3m-read-event temp-prompt key))
> 		       '(return 10 13 ?\n ?\r ?\C-g escape 27 ?\e)))
> 	    (cond
> 	     ((memq ch '(backspace 8 127 ?\C-h))
> 	      (if auto-num
> 		  (unless (string-equal filter "") ; delete last filter character
390,416c436
< 			  auto-num t))
< 	      (and (memq w3m-lnum-quick-browsing
< 			 '(quick-all quick-numbers))
< 		   (> (* num 10) last-index)
< 		   (throw 'select num)))
< 	    (setq temp-prompt
< 		  (w3m-lnum-prompt-str num fun prompt def-anchor
< 				       str (if auto-num ""))))
< 	   (t (setq ch (string (w3m-static-if (featurep 'xemacs)
< 				   (cond
< 				    ((eq ch t) key)
< 				    ((= ch ?\^@) ?\ ) ;<ctrl>+SPACE
< 				    (t ch))
< 				 (cond
< 				  ((= ch 67108896) 32) ;<ctrl>+SPACE
< 				  ((and (< 67108911 ch) ;treat <ctrl>+NUMBER
< 					(< ch 67108922))
< 				   (- ch 67108864)) ; as NUMBER
< 				  (t ch)))))
< 	      (setq last-index (w3m-lnum type
< 					 (setq str (concat str ch))))
< 	      (if (and (= last-index 1)
< 		       (memq w3m-lnum-quick-browsing
< 			     '(quick-all quick-filter)))
< 		  (throw 'select (setq num 1))
< 		(if (zerop last-index) ; filter left nothing, remove new char
< 		    (setq last-index
---
> 			  last-index
418,424c438,449
< 			   type
< 			   (setq str (w3m-substring-no-properties
< 				      str 0 (1- (length str))))
< 			   t)))
< 		(setq num 1
< 		      auto-num t
< 		      temp-prompt
---
> 			   type (setq filter
> 				      (w3m-substring-no-properties
> 				       filter 0
> 				       (1- (length filter)))))
> 			  temp-prompt
> 			  (w3m-lnum-prompt-str num fun prompt
> 					       def-anchor filter "")))
> 		(setq num (/ num 10))	; delete last digit
> 		(if (zerop num)
> 		    (setq num 1
> 			  auto-num t))
> 		(setq temp-prompt
426,429c451,541
< 					   def-anchor str "")))))))
<       (if (memq ch '(?\C-g escape 27 ?\e))
< 	  (keyboard-quit)))
<     num))
---
> 					   def-anchor filter
> 					   (if auto-num "")))))
> 	     ;; scroll options
> 	     ((memq ch '(32 ?\ ))		; scroll down
> 	      (w3m-lnum-remove-overlays (point-min) (point-max))
> 	      (ignore-errors
> 		(w3m-scroll-up-1)
> 		(redisplay)) ; scroll-up sets wrongly window-start/end
> 	      #1=
> 	      (setq last-index (w3m-lnum type filter t)
> 		    num (if (zerop last-index) 0 1)
> 		    auto-num t
> 		    temp-prompt (w3m-lnum-prompt-str num fun prompt
> 						     def-anchor
> 						     filter "")))
> 	     ((eq ch 'delete)		; scroll up
> 	      (w3m-lnum-remove-overlays (point-min) (point-max))
> 	      (ignore-errors (scroll-down nil))
> 	      #1#)
> 	     ((memq ch '(60 ?<)) (w3m-scroll-right nil))
> 	     ((memq ch '(62 ?>)) (w3m-scroll-left nil))
> 	     ;; iteration options
> 	     ((memq ch '(left up))
> 	      (setq num (if (> num 1) (1- num)
> 			  last-index)
> 		    auto-num t
> 		    temp-prompt
> 		    (w3m-lnum-prompt-str num fun prompt def-anchor
> 					 filter "")))
> 	     ((memq ch '(right down))
> 	      (setq num (if (< num last-index)
> 			    (1+ num)
> 			  1)
> 		    auto-num t
> 		    temp-prompt
> 		    (w3m-lnum-prompt-str num fun prompt def-anchor
> 					 filter "")))
> 	     ((and (w3m-static-if (featurep 'xemacs) ; digit
> 		       (characterp ch)
> 		     (numberp ch))
> 		   (< 47 ch) (< ch 58))
> 	      (if auto-num
> 		  (if (= ch 48) (throw 'select (setq num 0))
> 		    (setq num (- ch 48)
> 			  auto-num nil))
> 		(setq num (+ (* num 10) ch -48)))
> 	      (if (> num last-index)
> 		  (if (zerop (setq num (/ num 10)))
> 		      (setq num 1
> 			    auto-num t))
> 		(and (memq w3m-lnum-quick-browsing
> 			   '(quick-all quick-numbers))
> 		     (> (* num 10) last-index)
> 		     (throw 'select num)))
> 	      (setq temp-prompt
> 		    (w3m-lnum-prompt-str num fun prompt def-anchor
> 					 filter (if auto-num ""))))
> 	     (t (setq ch (string (w3m-static-if (featurep 'xemacs)
> 				     (cond
> 				      ((eq ch t) key)
> 				      ((= ch ?\^@) ?\ ) ;<ctrl>+SPACE
> 				      (t ch))
> 				   (cond
> 				    ((= ch 67108896) 32) ;<ctrl>+SPACE
> 				    ((and (< 67108911 ch) ;treat <ctrl>+DIGIT
> 					  (< ch 67108922))
> 				     (- ch 67108864)) ; as DIGIT
> 				    (t ch)))))
> 		(setq last-index (w3m-lnum type
> 					   (setq filter
> 						 (concat filter ch))))
> 		(if (and (= last-index 1)
> 			 (memq w3m-lnum-quick-browsing
> 			       '(quick-all quick-filter)))
> 		    (throw 'select (setq num 1))
> 		  (if (zerop last-index) ; filter left nothing, remove new char
> 		      (setq last-index
> 			    (w3m-lnum
> 			     type
> 			     (setq filter (w3m-substring-no-properties
> 					   filter 0
> 					   (1- (length filter))))
> 			     t)))
> 		  (setq num 1
> 			auto-num t
> 			temp-prompt
> 			(w3m-lnum-prompt-str num fun prompt def-anchor
> 					     filter "")))))))
> 	(if (memq ch '(?\C-g escape 27 ?\e))
> 	    (keyboard-quit)))
>       (list num filter))))
431,432c543,544
< (defmacro w3m-with-lnum (type &rest body)
<   "Within TYPE anchor numbering execute BODY.
---
> (defmacro w3m-with-lnum (type filter &rest body)
>   "Within TYPE anchor numbering with FILTER execute BODY.
434,438c546,558
< Then clear numbering overlays.
< Within BODY, `last-index' is bound to the last used index number."
<   `(unwind-protect (let ((last-index (w3m-lnum ,type)))
< 		     ,@body)
<      (w3m-lnum-remove-overlays)))
---
> Then clear numbering overlays.  Within BODY, `last-index' is bound to
> the last used index number."
>   `(let ((original-mode-line-format mode-line-format))
>      (unwind-protect (progn
> 		       (setq mode-line-format
> 			     "RET: select | BACKSPACE: correction | \
> chars, C-digit, C-SPACE: add chars, digits or space to string \
> filter | arrows: move selection | SPACE,DEL,<,>: scroll | \
> ESC, C-g: quit")
> 		       (let ((last-index (w3m-lnum ,type ,filter)))
> 			 ,@body))
>        (setq mode-line-format original-mode-line-format)
>        (w3m-lnum-remove-overlays))))
443,444c563,565
<   (let (newly-marked)
<     (dolist (overlay (overlays-in (max (1- (window-start)) (point-min))
---
>   (let (marked-label)
>     (dolist (overlay (overlays-in (max (1- (window-start))
> 				       (point-min))
462,463c583,584
< 	  (or newly-marked
< 	      (setq newly-marked
---
> 	  (or marked-label
> 	      (setq marked-label
469c590
<     newly-marked))
---
>     marked-label))
472c593
<   "For the first overlay matching CONDITION throw through FOUND-TAG
---
>   "For the first overlay matching CONDITION throw through FOUND-TAG \
496,497c617,618
<   "Turn on link numbers and return list of url or action, position and
< image url if such of PROMPT selected anchor.
---
>   "Turn on link numbers and return list of url or action, position \
> and image url if such of PROMPT selected anchor.
504,520c625,644
<    type
<    (if (and (zerop last-index)
< 	    (not (= type 2)))
<        (if (y-or-n-p (concat "No items found. Select default? ["
< 			     w3m-current-url "] "))
< 	   (list w3m-current-url 16 nil nil)
< 	 (keyboard-quit))
<      (let ((num (w3m-lnum-read-interactive (or prompt
< 					       "Anchor number: ")
< 					   'w3m-lnum-highlight-anchor
< 					   type last-index
< 					   (unless (= type 2)
< 					     w3m-current-url))))
<        (if (and (zerop num)
< 		(not (= type 2)))
< 	   (list w3m-current-url 16 nil nil)
< 	 (w3m-lnum-get-anchor-info num))))))
---
>    type ""
>    (if (and (= type 2)			; image lack of selection
> 	    (= last-index 1))
>        (if (y-or-n-p "Single image found. Select it?")
> 	   (w3m-lnum-get-anchor-info 1))
>      (if (and (zerop last-index)
> 	      (not (= type 2)))
> 	 (if (y-or-n-p (concat "No items found. Select default? ["
> 			       w3m-current-url "] "))
> 	     (list w3m-current-url 16 nil nil)
> 	   (keyboard-quit))
>        (let ((num (car (w3m-lnum-read-interactive
> 			(or prompt "Anchor number: ")
> 			'w3m-lnum-highlight-anchor
> 			type last-index (unless (= type 2)
> 					  w3m-current-url)))))
> 	 (if (and (zerop num)
> 		  (not (= type 2)))
> 	     (list w3m-current-url 16 nil nil)
> 	   (w3m-lnum-get-anchor-info num)))))))
531a656,672
> (defmacro w3m-lnum-visit (info &optional new-session edit)
>   "Visit URL determined with selection INFO.
> If NEW-SESSION, visit in new buffer.
> If EDIT, edit URL before visiting."
>   (if new-session
>       `(w3m-goto-url-new-session
> 	,(if edit `(read-string "Visit url in new session: "
> 				(car ,info))
> 	   `(car ,info)))
>     `(progn (push-mark (point))
> 	    (goto-char (cadr ,info))
> 	    (w3m-history-store-position)
> 	    (w3m-goto-url
> 	     ,(if edit `(read-string "Visit url in new session: "
> 				     (car ,info))
> 		`(car ,info))))))
> 
557,561c698,699
< 					   (not (car (cddr info)))))
< 			(push-mark (point))
< 			(goto-char (cadr info))
< 			(w3m-history-store-position)
< 			(w3m-goto-url action))
---
> 					   (not (nth 2 info))))
> 			(w3m-lnum-visit info))
566,567c704,705
< 					   (not (car (cddr info)))))
< 			(w3m-goto-url-new-session action))
---
> 					   (not (nth 2 info))))
> 			(w3m-lnum-visit info t))
572,575c710
< 			(push-mark (point))
< 			(goto-char (cadr info))
< 			(w3m-history-store-position)
< 			(w3m-goto-url (read-string "Visit url: " action)))
---
> 			(w3m-lnum-visit info nil t))
577,578c712
< 			(w3m-goto-url-new-session
< 			 (read-string "Visit url in new session: " action)))))
---
> 			(w3m-lnum-visit info t t))))
595a730,882
> 
> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
> ;;; universal
> 
> (defmacro w3m-lnum-make-action (text cmd)
>   "Return a TEXT propertized as a link that invokes CMD when clicked."
>   `(propertize ,text 'action ,cmd 'mouse-face 'highlight))
> 
> (defun w3m-lnum-universal-dispatch (info label action-alist)
>   "Print available options for determined by INFO element.
> LABEL is identifier to be echoed in the minibuffer.
> ACTION-ALIST is an alist of available options where each element
> is in the following format: (keycode function docstring).
> Function has to take one argument that is selection info."
>   (let ((action-alist (append action-alist w3m-lnum-actions-general))
> 	char key default-option selection-made)
>     (save-window-excursion
>       (let ((original-mode-line-format mode-line-format))
> 	(unwind-protect
> 	    (let ((selection-buffer (get-buffer-create
> 				     "*Emacs-w3m action selection*")))
> 	      (set-buffer selection-buffer)
> 	      (setq mode-line-format "RET, left click: select | \
> <down>,TAB/<up>,BACKTAB: move to next/previous action")
> 	      (setq buffer-read-only nil)
> 	      (mapc (lambda (option)
> 		      (if (consp option)
> 			  (insert
> 			   (w3m-lnum-make-action
> 			    (concat "[    " (char-to-string
> 					     (car option)) "    ] "
> 					     (nth 2 option))
> 			    (cadr option))
> 			   "\n")
> 			(insert option "\n")))
> 		    action-alist)
> 	      (insert (w3m-lnum-make-action
> 		       "[Backspace] Back to selection"
> 		       (lambda (info) 'restart-selection))
> 		      "\n")
> 	      (insert (w3m-lnum-make-action "[   ESC   ] Quit"
> 					    (lambda (info) nil)))
> 	      (setq buffer-read-only t)
> 	      (goto-char (point-min))
> 	      (while (not (get-text-property (point) 'action))
> 		(forward-line))		; go over first action
> 	      (pop-to-buffer selection-buffer)
> 	      (setq char (w3m-read-event
> 			  (concat
> 			   (propertize
> 			    "Select action: " 'face
> 			    'w3m-lnum-minibuffer-prompt)
> 			   "[" label "]")
> 			  key))
> 	      (while (and (not selection-made)
> 			  (or (consp char)
> 			      (memq char '(up down tab backtab
> 					      return 10 13 ?\n ?\r))))
> 		(if (consp char)		; mouse click?!
> 		    (progn (mouse-set-point char)	; move to mouse point
> 			   (let ((action (get-text-property (point)
> 							    'action)))
> 			     (if action (setq selection-made action))))
> 		  (cond ((memq char '(up backtab)) ; move to previous action
> 			 (when (/= (forward-line -1) 0)
> 			   (goto-char (point-max)) ; ...or start from bottom
> 			   (move-beginning-of-line nil))
> 			 (while (and (not (get-text-property (point) 'action))
> 				     (= (forward-line -1) 0))))
> 			((memq char '(down tab)) ; move to next action
> 			 (forward-line)
> 			 (if (= (point) (point-max))
> 			     (goto-char (point-min))) ; or move to top
> 			 (while (and (not (get-text-property (point) 'action))
> 				     (/= (point) (point-max)))
> 			   (forward-line)))
> 			((memq char '(return 10 13 ?\n ?\r)) ; <return> select
> 			 (let ((action (get-text-property (point)
> 							  'action)))
> 			   (if action (setq selection-made action))))))
> 		(unless selection-made
> 		  (setq char (w3m-read-event
> 			      (concat (propertize
> 				       "Select action: " 'face
> 				       'w3m-lnum-minibuffer-prompt)
> 				      "[" label "]")
> 			      key)))))
> 	  (setq mode-line-format original-mode-line-format)
> 	  (kill-buffer))))
>     (unless (memq char '(?\C-g escape 27 ?\e))
>       (cond (selection-made (funcall selection-made info))
> 	    ((memq char '(backspace 8 ?\C-h)) ; require new selection
> 	     'restart-selection)
> 	    (t (let ((dispatch (assoc-default char action-alist 'eq)))
> 		 (if dispatch (funcall (car dispatch) info)
> 		   (w3m-message "Invalid selection"))))))))
> 
> ;;;###autoload
> (defun w3m-lnum-universal ()
>   "Turn on link numbers, ask for one and offer actions over it \
> depending on selection type.
> Actions may be selected either by hitting corresponding key,
> pressing <return> over the action line or left clicking."
>   (interactive)
>   (let ((filter "")
> 	(label w3m-current-url)
> 	num)
>     (while
> 	(eq 'restart-selection
> 	    (w3m-with-lnum
> 	     3 filter
> 	     (let ((info
> 		    (if (zerop last-index)
> 			(list w3m-current-url 16 nil nil)
> 		      (let ((selection (w3m-lnum-read-interactive
> 					"Anchor number: "
> 					'w3m-lnum-highlight-anchor
> 					3 last-index w3m-current-url
> 					filter
> 					(if (eq num 1) nil num))))
> 			(setq num (car selection)
> 			      filter (cadr selection))
> 			(if (zerop num)
> 			    (progn (setq label w3m-current-url)
> 				   (list w3m-current-url 16 nil nil))
> 			  (setq label (w3m-lnum-highlight-anchor num))
> 			  (w3m-lnum-get-anchor-info num))))))
> 	       (if info
> 		   (let ((action (car info)))
> 		     (cond ((null action) ; image
> 			    (w3m-lnum-universal-dispatch
> 			     info label
> 			     w3m-lnum-actions-image-alist))
> 			   ((stringp action)		   ; url
> 			    (if (or (stringp (nth 2 info)) ; image url
> 				    (stringp (nth 3 info)))
> 				(w3m-lnum-universal-dispatch
> 				 info label
> 				 (append w3m-lnum-actions-link-alist
> 					 w3m-lnum-actions-image-alist))
> 			      (w3m-lnum-universal-dispatch
> 			       info label
> 			       w3m-lnum-actions-link-alist)))
> 			   ((eq (car action) 'w3m-form-submit) ; button
> 			    (w3m-lnum-universal-dispatch
> 			     info label
> 			     w3m-lnum-actions-button-alist))
> 			   (t (w3m-lnum-universal-dispatch ; form field
> 			       info label
> 			       w3m-lnum-actions-form-alist))))
> 		 (w3m-message "No valid anchor selected"))))))))
> 
> 
636c923
< 	   (w3m-external-view (car (cddr im))))
---
> 	   (w3m-external-view (nth 2 im)))
648c935
< 	   (w3m-download (car (cddr im))))
---
> 	   (w3m-download (nth 2 im)))
652c939
<   "Zoom image under the point.
---
>   "Zoom image under point and interactively resize after that.
656c943,944
< for one.  If IN zoom in, otherwise zoom out."
---
> for one, then interactively resize.
> If IN zoom in, otherwise zoom out."
663,667c951,958
<        (cond
< 	(im (w3m-resize-inline-image-internal
< 	     im
< 	     (,(if in '+ '-) 100 (or ,rate w3m-resize-image-scale))))
< 	((setq im (w3m-lnum-get-action
---
>        (if im
> 	   (progn
> 	     (let ((percent (,(if in '+ '-) 100
> 			     (or ,rate w3m-resize-image-scale))))
> 	       (w3m-resize-inline-image-internal im percent)
> 	       (w3m-resize-image-interactive im ,rate
> 					     (/ percent 100.0))))
> 	 (setq im (w3m-lnum-get-action
671,674c962,967
< 	   (w3m-resize-inline-image-internal
< 	    (car im)
< 	    (,(if in '+ '-) 100 (or ,rate w3m-resize-image-scale)))))
< 	(t (w3m-message "No image at point"))))))
---
> 	   (let ((percent (,(if in '+ '-) 100
> 			   (or ,rate w3m-resize-image-scale))))
> 	     (w3m-resize-inline-image-internal
> 	      (car im) percent)
> 	     (w3m-resize-image-interactive (car im) ,rate
> 					   (/ percent 100.0))))))))
677c970
<   "Zoom in an image on the point.
---
>   "Zoom in an image under point and interactively resize after that.
679c972
< enlarged by \(30 means enlarging the image by 130%).  The default
---
> enlarged by (30 means enlarging the image by 130%).  The default
681c974,975
< image under point, activate numbering and ask for one."
---
> image under point, activate numbering and ask for one, then
> interactively resize."
686,690c980,985
<   "Zoom out an image on the point.
< Numeric prefix RATE specifies how many percent the image is shrunk by
< \(30 means shrinking the image by 70%).  The default is the value of
< the `w3m-resize-image-scale' variable.
< If no image under point, activate numbering and ask for one."
---
>   "Zoom out an image on unter point and interactively resize after that.
> Numeric prefix RATE specifies how many percent the image is
> shrunk by (30 means shrinking the image by 70%).  The default is
> the value of the `w3m-resize-image-scale' variable.  If no image
> under point, activate numbering and ask for one, then
> interactively resize."
728c1023
< 	    (w3m-message "%s%s" (let ((im-alt (cadr (cddr link))))
---
> 	    (w3m-message "%s%s" (let ((im-alt (nth 3 link)))
751c1046
<   "Add link under cursor to bookmark.
---
>   "Add link under cursor to bookmarks.
762c1057
< 	  (message "Added"))
---
> 	  (w3m-message "Added"))
766,769c1061,1067
<        (buffer-substring-no-properties
< 	(previous-single-property-change (1+ (cadr url))
< 					 'w3m-href-anchor)
< 	(next-single-property-change (cadr url) 'w3m-href-anchor)))
---
>        (let ((pos (cadr url)))
> 	 (if (= pos 16)		; 0th anchor selected
> 	     w3m-current-title
> 	   (buffer-substring-no-properties
> 	    (previous-single-property-change (1+ pos)
> 					     'w3m-href-anchor)
> 	    (next-single-property-change pos 'w3m-href-anchor)))))
772a1071,1096
> 
> ;;; add link action for generic browser
> (if browse-url-generic-program
>     (setq w3m-lnum-actions-link-alist
> 	  (append w3m-lnum-actions-link-alist
> 		  `((?m (lambda (info) (browse-url-generic (car info)))
> 			,(concat "Open with "
> 				 browse-url-generic-program))))))
> 
> ;;; add link action for curl if present
> (if (executable-find "curl")
>     (setq w3m-lnum-actions-link-alist
> 	  (append w3m-lnum-actions-link-alist
> 		  '((?D (lambda (info)
> 			  (let ((olddir default-directory))
> 			    (cd (read-directory-name
> 				 "Save to: " (getenv "HOME")
> 				 nil t))
> 			    (async-shell-command (concat "curl -O '"
> 							 (car info)
> 							 "'")
> 						 "*Curl*")
> 			    (cd olddir)))
> 			"Download with Curl")))))
> 
> 
Index: w3m.el
===================================================================
RCS file: /storage/cvsroot/emacs-w3m/w3m.el,v
retrieving revision 1.1540
diff -r1.1540 w3m.el
161a162
>   (autoload 'w3m-lnum-universal "w3m-lnum" nil t)
211c212
<     (let ((rev "$Revision: 1.1540 $"))
---
>     (let ((rev "$Revision: 1.1541 $"))
4116a4118,4155
> (defun w3m-resize-image-interactive (image &optional rate changed-rate)
>   "Interactively resize IMAGE.
> If RATE is not given, use `w3m-resize-image-scale'.
> CHANGED-RATE is currently changed rate / 100."
>   (let ((char (read-char-exclusive
> 	       (propertize
> 		"Resize: [+ =] enlarge [-] shrink [0] original [q] quit"
> 		'face 'w3m-lnum-minibuffer-prompt)))
> 	(changed-rate (or changed-rate 1)))
>     (w3m-static-if (featurep 'xemacs)
> 	(setq char (char-octet char)))
>     (while (memq char '(?+ ?- ?= ?0))
>       (cond ((memq char '(?+ ?=))
> 	     (let ((percent (+ 100 (or rate
> 				       w3m-resize-image-scale))))
> 	       (w3m-resize-inline-image-internal image percent)
> 	       (setq changed-rate (* changed-rate
> 				     (/ percent 100.0)))))
> 	    ((eq char ?-)
> 	     (let ((percent (- 100 (if rate
> 				       (if (> rate 99) 99
> 					 rate)
> 				     w3m-resize-image-scale))))
> 	       (w3m-resize-inline-image-internal image percent)
> 	       (setq changed-rate (* changed-rate
> 				     (/ percent 100.0)))))
> 	    ((eq char ?0)
> 	     (w3m-resize-inline-image-internal image
> 					       (/ 100.0 changed-rate))
> 	     (setq changed-rate 1)))
>       (setq char
> 	    (read-char-exclusive
> 	     (propertize
> 	      "Resize: [+ =] enlarge [-] shrink [0] original [q] quit"
> 	      'face 'w3m-lnum-minibuffer-prompt)))
>       (w3m-static-if (featurep 'xemacs)
> 	  (setq char (char-octet char))))))
> 
7771a7811
>     (define-key map "f" 'w3m-lnum-follow)
7772a7813
>     (define-key map "w" 'w3m-lnum-universal)
7777d7817
<     (define-key map "f" 'w3m-lnum-follow)