diff options
| author | Tom Tromey <tromey@redhat.com> | 2013-07-12 18:44:13 -0600 |
|---|---|---|
| committer | Tom Tromey <tromey@redhat.com> | 2013-07-12 18:44:13 -0600 |
| commit | b34a529f177a6ea32da5cb1254f91bf9d71838db (patch) | |
| tree | 477131abc15d3107b30b635223d87a22550b480b /lisp/simple.el | |
| parent | e6f63071a3f7721f55220514b6d9a8ee8c1232d8 (diff) | |
| parent | 5e301d7651c0691bb2bc7f3fbe711fdbe26ac471 (diff) | |
| download | emacs-b34a529f177a6ea32da5cb1254f91bf9d71838db.tar.gz | |
Merge from trunk
Diffstat (limited to 'lisp/simple.el')
| -rw-r--r-- | lisp/simple.el | 128 |
1 files changed, 104 insertions, 24 deletions
diff --git a/lisp/simple.el b/lisp/simple.el index b4b8ddfabed..9158452fd64 100644 --- a/lisp/simple.el +++ b/lisp/simple.el @@ -4602,6 +4602,12 @@ for it.") (defun next-line (&optional arg try-vscroll) "Move cursor vertically down ARG lines. Interactively, vscroll tall lines if `auto-window-vscroll' is enabled. +Non-interactively, use TRY-VSCROLL to control whether to vscroll tall +lines: if either `auto-window-vscroll' or TRY-VSCROLL is nil, this +function will not vscroll. + +ARG defaults to 1. + If there is no character in the target line exactly under the current column, the cursor is positioned after the character in that line which spans this column, or at the end of the line if it is not long enough. @@ -4646,6 +4652,12 @@ and more reliable (no dependence on goal column, etc.)." (defun previous-line (&optional arg try-vscroll) "Move cursor vertically up ARG lines. Interactively, vscroll tall lines if `auto-window-vscroll' is enabled. +Non-interactively, use TRY-VSCROLL to control whether to vscroll tall +lines: if either `auto-window-vscroll' or TRY-VSCROLL is nil, this +function will not vscroll. + +ARG defaults to 1. + If there is no character in the target line exactly over the current column, the cursor is positioned after the character in that line which spans this column, or at the end of the line if it is not long enough. @@ -4725,33 +4737,76 @@ lines." :group 'editing-basics :version "23.1") +(defun default-font-height () + "Return the height in pixels of the current buffer's default face font." + (cond + ((display-multi-font-p) + (aref (font-info (face-font 'default)) 3)) + (t (frame-char-height)))) + +(defun default-line-height () + "Return the pixel height of current buffer's default-face text line. + +The value includes `line-spacing', if any, defined for the buffer +or the frame." + (let ((dfh (default-font-height)) + (lsp (if (display-graphic-p) + (or line-spacing + (default-value 'line-spacing) + (frame-parameter nil 'line-spacing) + 0) + 0))) + (if (floatp lsp) + (setq lsp (* dfh lsp))) + (+ dfh lsp))) + +(defun window-screen-lines () + "Return the number of screen lines in the text area of the selected window. + +This is different from `window-text-height' in that this function counts +lines in units of the height of the font used by the default face displayed +in the window, not in units of the frame's default font, and also accounts +for `line-spacing', if any, defined for the window's buffer or frame. + +The value is a floating-point number." + (let ((canonical (window-text-height)) + (fch (frame-char-height)) + (dlh (default-line-height))) + (/ (* (float canonical) fch) dlh))) + ;; Returns non-nil if partial move was done. (defun line-move-partial (arg noerror to-end) (if (< arg 0) ;; Move backward (up). ;; If already vscrolled, reduce vscroll - (let ((vs (window-vscroll nil t))) - (when (> vs (frame-char-height)) - (set-window-vscroll nil (- vs (frame-char-height)) t))) + (let ((vs (window-vscroll nil t)) + (dlh (default-line-height))) + (when (> vs dlh) + (set-window-vscroll nil (- vs dlh) t))) ;; Move forward (down). (let* ((lh (window-line-height -1)) + (rowh (car lh)) (vpos (nth 1 lh)) (ypos (nth 2 lh)) (rbot (nth 3 lh)) (this-lh (window-line-height)) - (this-height (nth 0 this-lh)) + (this-height (car this-lh)) (this-ypos (nth 2 this-lh)) - (fch (frame-char-height)) - py vs) + (dlh (default-line-height)) + (wslines (window-screen-lines)) + py vs last-line) + (if (> (mod wslines 1.0) 0.0) + (setq wslines (round (+ wslines 0.5)))) (when (or (null lh) - (>= rbot fch) - (<= ypos (- fch)) + (>= rbot dlh) + (<= ypos (- dlh)) (null this-lh) - (<= this-ypos (- fch))) + (<= this-ypos (- dlh))) (unless lh (let ((wend (pos-visible-in-window-p t nil t))) (setq rbot (nth 3 wend) + rowh (nth 4 wend) vpos (nth 5 wend)))) (unless this-lh (let ((wstart (pos-visible-in-window-p nil nil t))) @@ -4765,35 +4820,57 @@ lines." (if col-row (- (cdr col-row) (window-vscroll)) (cdr (posn-col-row ppos)))))) + ;; VPOS > 0 means the last line is only partially visible. + ;; But if the part that is visible is at least as tall as the + ;; default font, that means the line is actually fully + ;; readable, and something like line-spacing is hidden. So in + ;; that case we accept the last line in the window as still + ;; visible, and consider the margin as starting one line + ;; later. + (if (and vpos (> vpos 0)) + (if (and rowh + (>= rowh (default-font-height)) + (< rowh dlh)) + (setq last-line (min (- wslines scroll-margin) vpos)) + (setq last-line (min (- wslines scroll-margin 1) (1- vpos))))) (cond ;; If last line of window is fully visible, and vscrolling ;; more would make this line invisible, move forward. - ((and (or (< (setq vs (window-vscroll nil t)) fch) + ((and (or (< (setq vs (window-vscroll nil t)) dlh) (null this-height) - (<= this-height fch)) + (<= this-height dlh)) (or (null rbot) (= rbot 0))) nil) ;; If cursor is not in the bottom scroll margin, and the ;; current line is is not too tall, move forward. - ((and (or (null this-height) (<= this-height fch)) + ((and (or (null this-height) (<= this-height dlh)) vpos (> vpos 0) - (< py - (min (- (window-text-height) scroll-margin 1) (1- vpos)))) + (< py last-line)) nil) ;; When already vscrolled, we vscroll some more if we can, ;; or clear vscroll and move forward at end of tall image. ((> vs 0) (when (or (and rbot (> rbot 0)) - (and this-height (> this-height fch))) - (set-window-vscroll nil (+ vs fch) t))) + (and this-height (> this-height dlh))) + (set-window-vscroll nil (+ vs dlh) t))) ;; If cursor just entered the bottom scroll margin, move forward, - ;; but also vscroll one line so redisplay won't recenter. + ;; but also optionally vscroll one line so redisplay won't recenter. ((and vpos (> vpos 0) - (= py (min (- (window-text-height) scroll-margin 1) - (1- vpos)))) - (set-window-vscroll nil (frame-char-height) t) + (= py last-line)) + ;; Don't vscroll if the partially-visible line at window + ;; bottom has the default height (a.k.a. "just one more text + ;; line"): in that case, we do want redisplay to behave + ;; normally, i.e. recenter or whatever. + ;; + ;; Note: ROWH + RBOT from the value returned by + ;; pos-visible-in-window-p give the total height of the + ;; partially-visible glyph row at the end of the window. As + ;; we are dealing with floats, we disregard sub-pixel + ;; discrepancies between that and DLH. + (if (and rowh rbot (>= (- (+ rowh rbot) dlh) 1)) + (set-window-vscroll nil dlh t)) (line-move-1 arg noerror to-end) t) ;; If there are lines above the last line, scroll-up one line. @@ -4802,7 +4879,7 @@ lines." t) ;; Finally, start vscroll. (t - (set-window-vscroll nil (frame-char-height) t))))))) + (set-window-vscroll nil dlh t))))))) ;; This is like line-move-1 except that it also performs @@ -4835,11 +4912,14 @@ lines." (prog1 (line-move-visual arg noerror) ;; If we moved into a tall line, set vscroll to make ;; scrolling through tall images more smooth. - (let ((lh (line-pixel-height))) + (let ((lh (line-pixel-height)) + (dlh (default-line-height))) (if (and (< arg 0) (< (point) (window-start)) - (> lh (frame-char-height))) - (set-window-vscroll nil (- lh (frame-char-height)) t)))) + (> lh dlh)) + (set-window-vscroll + nil + (- lh dlh) t)))) (line-move-1 arg noerror to-end))))) ;; Display-based alternative to line-move-1. |
