Function: line-move-finish
line-move-finish is a byte-compiled function defined in simple.el.gz.
Signature
(line-move-finish COLUMN OPOINT FORWARD)
Source Code
;; Defined in /usr/src/emacs/lisp/simple.el.gz
(defun line-move-finish (column opoint forward)
(let ((repeat t))
(while repeat
;; Set REPEAT to t to repeat the whole thing.
(setq repeat nil)
(let (new
(old (point))
(line-beg (line-beginning-position))
(line-end
;; Compute the end of the line
;; ignoring effectively invisible newlines.
(save-excursion
;; Like end-of-line but ignores fields.
(skip-chars-forward "^\n")
(while (and (not (eobp)) (invisible-p (point)))
(goto-char (next-char-property-change (point)))
(skip-chars-forward "^\n"))
(point))))
;; Move to the desired column.
(if (and line-move-visual
(not (or truncate-lines truncate-partial-width-windows)))
;; Under line-move-visual, goal-column should be
;; interpreted in units of the frame's canonical character
;; width, which is exactly what vertical-motion does.
(vertical-motion (cons column 0))
(line-move-to-column (truncate column)))
;; Corner case: suppose we start out in a field boundary in
;; the middle of a continued line. When we get to
;; line-move-finish, point is at the start of a new *screen*
;; line but the same text line; then line-move-to-column would
;; move us backwards. Test using C-n with point on the "x" in
;; (insert "a" (propertize "x" 'field t) (make-string 89 ?y))
(and forward
(< (point) old)
(goto-char old))
(setq new (point))
;; Process intangibility within a line.
;; With inhibit-point-motion-hooks bound to nil, a call to
;; goto-char moves point past intangible text.
;; However, inhibit-point-motion-hooks controls both the
;; intangibility and the point-entered/point-left hooks. The
;; following hack avoids calling the point-* hooks
;; unnecessarily. Note that we move *forward* past intangible
;; text when the initial and final points are the same.
(goto-char new)
(let ((inhibit-point-motion-hooks nil))
(goto-char new)
;; If intangibility moves us to a different (later) place
;; in the same line, use that as the destination.
(if (<= (point) line-end)
(setq new (point))
;; If that position is "too late",
;; try the previous allowable position.
;; See if it is ok.
(backward-char)
(if (if forward
;; If going forward, don't accept the previous
;; allowable position if it is before the target line.
(< line-beg (point))
;; If going backward, don't accept the previous
;; allowable position if it is still after the target line.
(<= (point) line-end))
(setq new (point))
;; As a last resort, use the end of the line.
(setq new line-end))))
;; Now move to the updated destination, processing fields
;; as well as intangibility.
(goto-char opoint)
(let ((inhibit-point-motion-hooks nil))
(goto-char
;; Ignore field boundaries if the initial and final
;; positions have the same `field' property, even if the
;; fields are non-contiguous. This seems to be "nicer"
;; behavior in many situations.
(if (eq (get-char-property new 'field)
(get-char-property opoint 'field))
new
(constrain-to-field new opoint t t
'inhibit-line-move-field-capture))))
;; If all this moved us to a different line,
;; retry everything within that new line.
(when (or (< (point) line-beg) (> (point) line-end))
;; Repeat the intangibility and field processing.
(setq repeat t))))))