Function: line-move-visual
line-move-visual is a byte-compiled function defined in simple.el.gz.
Signature
(line-move-visual ARG &optional NOERROR)
Documentation
Move ARG lines forward.
If NOERROR, don't signal an error if we can't move that many lines.
Probably introduced at or before Emacs version 23.1.
Source Code
;; Defined in /usr/src/emacs/lisp/simple.el.gz
;; Display-based alternative to line-move-1.
;; 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)
"Move ARG lines forward.
If NOERROR, don't signal an error if we can't move that many lines."
(let ((opoint (point))
(hscroll (window-hscroll))
(lnum-width (line-number-display-width t))
target-hscroll)
;; Check if the previous command was a line-motion command, or if
;; we were called from some other command.
(if (and (consp temporary-goal-column)
(memq last-command `(next-line previous-line ,this-command)))
;; If so, there's no need to reset `temporary-goal-column',
;; but we may need to hscroll.
(if (or (/= (cdr temporary-goal-column) hscroll)
(> (cdr temporary-goal-column) 0))
(setq target-hscroll (cdr temporary-goal-column)))
;; Otherwise, we should reset `temporary-goal-column'.
(let ((posn (posn-at-point))
x-pos)
(cond
;; Handle the `overflow-newline-into-fringe' case
;; (left-fringe is for the R2L case):
((memq (nth 1 posn) '(right-fringe left-fringe))
(setq temporary-goal-column (cons (window-width) hscroll)))
((car (posn-x-y posn))
(setq x-pos (- (car (posn-x-y posn)) lnum-width))
;; In R2L lines, the X pixel coordinate is measured from the
;; left edge of the window, but columns are still counted
;; from the logical-order beginning of the line, i.e. from
;; the right edge in this case. We need to adjust for that.
(if (eq (current-bidi-paragraph-direction) 'right-to-left)
(setq x-pos (- (window-body-width nil t) 1 x-pos)))
(setq temporary-goal-column
(cons (/ (float x-pos)
(frame-char-width))
hscroll)))
(executing-kbd-macro
;; When we move beyond the first/last character visible in
;; the window, posn-at-point will return nil, so we need to
;; approximate the goal column as below.
(setq temporary-goal-column
(mod (current-column) (window-text-width)))))))
(if target-hscroll
(set-window-hscroll (selected-window) target-hscroll))
;; vertical-motion can move more than it was asked to if it moves
;; across display strings with newlines. We don't want to ring
;; the bell and announce beginning/end of buffer in that case.
(or (and (or (and (>= arg 0)
(>= (vertical-motion
(cons (or goal-column
(if (consp temporary-goal-column)
(car temporary-goal-column)
temporary-goal-column))
arg))
arg))
(and (< arg 0)
(<= (vertical-motion
(cons (or goal-column
(if (consp temporary-goal-column)
(car temporary-goal-column)
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)))))