changeset 103072:ce405af23a6e

* simple.el (line-move-visual): If point is stuck moving backwards against a display string, temporarily ignore the goal column (Bug#3020).
author Chong Yidong <cyd@stupidchicken.com>
date Sat, 25 Apr 2009 15:27:45 +0000
parents c190521beded
children 056e34bacfbc
files lisp/ChangeLog lisp/simple.el
diffstat 2 files changed, 27 insertions(+), 16 deletions(-) [+]
line wrap: on
line diff
--- a/lisp/ChangeLog	Sat Apr 25 14:43:35 2009 +0000
+++ b/lisp/ChangeLog	Sat Apr 25 15:27:45 2009 +0000
@@ -1,5 +1,9 @@
 2009-04-25  Chong Yidong  <cyd@stupidchicken.com>
 
+	* simple.el (line-move-visual): If point is stuck moving backwards
+	against a display string, temporarily ignore the goal
+	column (Bug#3020).
+
 	* startup.el (normal-top-level): Implement a work-around to handle
 	changes to face-font-rescale-alist during
 	initialization (Bug#1785).
--- a/lisp/simple.el	Sat Apr 25 14:43:35 2009 +0000
+++ b/lisp/simple.el	Sat Apr 25 15:27:45 2009 +0000
@@ -4056,24 +4056,31 @@
 ;; Arg says how many lines to move.  The value is t if we can move the
 ;; specified number of lines.
 (defun line-move-visual (arg &optional noerror)
-  (unless (and (floatp temporary-goal-column)
-	       (or (memq last-command '(next-line previous-line))
-		   ;; In case we're called from some other command.
-		   (eq last-command this-command)))
-    (let ((posn (posn-at-point))
-	  x)
+  (let ((posn (posn-at-point))
+	(opoint (point))
+	x)
+    ;; Reset temporary-goal-column, unless the previous command was a
+    ;; line-motion command or we were called from some other command.
+    (unless (and (floatp temporary-goal-column)
+		 (memq last-command `(next-line previous-line ,this-command)))
       (cond ((eq (nth 1 posn) 'right-fringe) ; overflow-newline-into-fringe
 	     (setq temporary-goal-column (- (window-width) 1)))
-	    ((setq x (car (nth 2 posn)))
-	     (setq temporary-goal-column (/ (float x) (frame-char-width)))))))
-  (or (= (vertical-motion
-	  (cons (or goal-column (truncate temporary-goal-column)) arg))
-	 arg)
-      (unless noerror
-	(signal (if (< arg 0)
-		    'beginning-of-buffer
-		  'end-of-buffer)
-		nil))))
+	    ((setq x (car (posn-x-y posn)))
+	     (setq temporary-goal-column (/ (float x) (frame-char-width))))))
+    ;; Move using `vertical-motion'.
+    (or (and (= (vertical-motion
+		 (cons (or goal-column (truncate temporary-goal-column)) arg))
+		arg)
+	     (or (>= arg 0)
+		 (/= (point) opoint)
+		 ;; If the goal column lies on a display string,
+		 ;; `vertical-motion' advances the cursor to the end
+		 ;; of the string.  For arg < 0, this can cause the
+		 ;; cursor to get stuck.  (Bug#3020).
+		 (= (vertical-motion arg) arg)))
+	(unless noerror
+	  (signal (if (< arg 0) 'beginning-of-buffer 'end-of-buffer)
+		  nil)))))
 
 ;; This is the guts of next-line and previous-line.
 ;; Arg says how many lines to move.