[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Emacs-diffs] scratch/line-numbers 4caf65d: Fix vertical-motion across t
From: |
Eli Zaretskii |
Subject: |
[Emacs-diffs] scratch/line-numbers 4caf65d: Fix vertical-motion across the place where line-number width changes |
Date: |
Fri, 7 Jul 2017 05:23:00 -0400 (EDT) |
branch: scratch/line-numbers
commit 4caf65d4de591089c82ccf542a31ea5009a3c717
Author: Eli Zaretskii <address@hidden>
Commit: Eli Zaretskii <address@hidden>
Fix vertical-motion across the place where line-number width changes
* src/indent.c (line_number_display_width): New function,
refactored from line-number width calculations in vertical-motion.
(Fvertical_motion): Call line_number_display_width when the width
of line-number display is needed.
(Fline_number_display_width): New defun.
(syms_of_indent): Defsubr it.
* doc/lispref/display.texi (Size of Displayed Text): Document
line-number-display-width.
* etc/NEWS: Mention line-number-display-width.
* lisp/simple.el (last--line-number-width): New internal variable.
(line-move-visual): Use it to adjust temporary-goal-column when
line-number display changes its width.
---
doc/lispref/display.texi | 17 ++++++++++
etc/NEWS | 4 +++
lisp/simple.el | 21 ++++++++++--
src/indent.c | 84 +++++++++++++++++++++++++++++++++++-------------
4 files changed, 101 insertions(+), 25 deletions(-)
diff --git a/doc/lispref/display.texi b/doc/lispref/display.texi
index 4de55fd..08b2b46 100644
--- a/doc/lispref/display.texi
+++ b/doc/lispref/display.texi
@@ -1980,6 +1980,23 @@ selected window. The value includes the line spacing of
the line
(@pxref{Line Height}).
@end defun
+When a buffer is displayed with line numbers (@pxref{Display Custom,,,
+emacs, The GNU Emacs Manual}), it is sometimes useful to know the
+width taken for displaying the line numbers. The following function
+is for Lisp programs which need this information for layout
+calculations.
+
address@hidden line-number-display-width &optional pixelwise
+This function returns the width used for displaying the line numbers
+in the selected window. Optional argument @var{pixelwise}, if
address@hidden, means return the value in pixels; otherwise the value
+is returned in column units of the font defined for the
address@hidden face. If line numbers are not displayed in the
+selected window, the value is zero. Use @code{with-selected-window}
+(@pxref{Selecting Windows}) if you need this information about another
+window.
address@hidden defun
+
@node Line Height
@section Line Height
diff --git a/etc/NEWS b/etc/NEWS
index b50c770..79eb391 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -420,6 +420,10 @@ line by putting the 'display-line-numbers-disable' text
property or
overlay property on the first character of that screen line. This is
intended for add-on packages that need a finer control of the display.
+Lisp programs that need to know how much screen estate is used up for
+line-number display in a window can use the new function
+'line-number-display-width'.
+
Linum mode and all similar packages are henceforth becoming obsolete.
Users and developers are encouraged to switch to this new feature
instead.
diff --git a/lisp/simple.el b/lisp/simple.el
index df664fc..5d1a6db 100644
--- a/lisp/simple.el
+++ b/lisp/simple.el
@@ -5931,6 +5931,10 @@ columns by which window is scrolled from left margin.
When the `track-eol' feature is doing its job, the value is
`most-positive-fixnum'.")
+(defvar last--line-number-width 0
+ "Last value of width used for displaying line numbers.
+Used internally by `line-move-visual'.")
+
(defcustom line-move-ignore-invisible t
"Non-nil means commands that move by lines ignore invisible newlines.
When this option is non-nil, \\[next-line], \\[previous-line],
\\[move-end-of-line], and \\[move-beginning-of-line] behave
@@ -6201,6 +6205,7 @@ not vscroll."
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.
@@ -6208,9 +6213,19 @@ If NOERROR, don't signal an error if we can't move that
many lines."
(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)))
+ (progn
+ (if (or (/= (cdr temporary-goal-column) hscroll)
+ (> (cdr temporary-goal-column) 0))
+ (setq target-hscroll (cdr temporary-goal-column)))
+ ;; Update the COLUMN part of temporary-goal-column if the
+ ;; line-number display changed its width since the last
+ ;; time.
+ (setq temporary-goal-column
+ (cons (+ (car temporary-goal-column)
+ (/ (float (- lnum-width last--line-number-width))
+ (frame-char-width)))
+ (cdr temporary-goal-column)))
+ (setq last--line-number-width lnum-width))
;; Otherwise, we should reset `temporary-goal-column'.
(let ((posn (posn-at-point))
x-pos)
diff --git a/src/indent.c b/src/indent.c
index 70351f9..ba93650 100644
--- a/src/indent.c
+++ b/src/indent.c
@@ -1947,6 +1947,59 @@ vmotion (register ptrdiff_t from, register ptrdiff_t
from_byte,
-1, hscroll, 0, w);
}
+/* Return the width taken by line-number display in window W. */
+static void
+line_number_display_width (struct window *w, int *width, int *pixel_width)
+{
+ if (NILP (Vdisplay_line_numbers))
+ {
+ *width = 0;
+ *pixel_width = 0;
+ }
+ else
+ {
+ struct it it;
+ struct text_pos wstart;
+ bool saved_restriction = false;
+ ptrdiff_t count = SPECPDL_INDEX ();
+ SET_TEXT_POS_FROM_MARKER (wstart, w->start);
+ void *itdata = bidi_shelve_cache ();
+ /* We must start from window's start point, but it could be
+ outside the accessible region. */
+ if (wstart.charpos < BEGV || wstart.charpos > ZV)
+ {
+ record_unwind_protect (save_restriction_restore,
+ save_restriction_save ());
+ Fwiden ();
+ saved_restriction = true;
+ }
+ start_display (&it, w, wstart);
+ move_it_by_lines (&it, 1);
+ *width = it.lnum_width;
+ *pixel_width = it.lnum_pixel_width;
+ if (saved_restriction)
+ unbind_to (count, Qnil);
+ bidi_unshelve_cache (itdata, 0);
+ }
+}
+
+DEFUN ("line-number-display-width", Fline_number_display_width,
+ Sline_number_display_width, 0, 1, 0,
+ doc: /* Return the width used for displaying line numbers in the
selected window.
+If optional argument PIXELWISE is non-nil, return the width in pixels,
+otherwise return the width in columns of the face used to display
+line numbers, `line-number'. */)
+ (Lisp_Object pixelwise)
+{
+ int width, pixel_width;
+ line_number_display_width (XWINDOW (selected_window), &width, &pixel_width);
+ if (!NILP (pixelwise))
+ return make_number (pixel_width);
+ /* FIXME: The "+ 2" part knows that we add a blank on each side of
+ the line number when producing glyphs for display. */
+ return make_number (width + 2);
+}
+
/* In window W (derived from WINDOW), return x coordinate for column
COL (derived from COLUMN). */
static int
@@ -2073,30 +2126,10 @@ whether or not it is currently displayed in some
window. */)
that's what normal window redisplay does. Otherwise C-n/C-p
will sometimes err by one column. */
int lnum_width = 0;
+ int lnum_pixel_width = 0;
if (!NILP (Vdisplay_line_numbers)
&& !EQ (Vdisplay_line_numbers, Qvisual))
- {
- struct text_pos wstart;
- bool saved_restriction = false;
- ptrdiff_t count1 = SPECPDL_INDEX ();
- SET_TEXT_POS_FROM_MARKER (wstart, w->start);
- itdata = bidi_shelve_cache ();
- /* We must start from window's start point, but it could be
- outside the accessible region. */
- if (wstart.charpos < BEGV || wstart.charpos > ZV)
- {
- record_unwind_protect (save_restriction_restore,
- save_restriction_save ());
- Fwiden ();
- saved_restriction = true;
- }
- start_display (&it, w, wstart);
- move_it_by_lines (&it, 1);
- lnum_width = it.lnum_width;
- if (saved_restriction)
- unbind_to (count1, Qnil);
- bidi_unshelve_cache (itdata, 0);
- }
+ line_number_display_width (w, &lnum_width, &lnum_pixel_width);
SET_TEXT_POS (pt, PT, PT_BYTE);
itdata = bidi_shelve_cache ();
start_display (&it, w, pt);
@@ -2277,6 +2310,12 @@ whether or not it is currently displayed in some window.
*/)
an addition to the hscroll amount. */
if (lcols_given)
{
+ /* If we are displaying line numbers, we could cross the
+ line where the width of the line-number display changes,
+ in which case we need to fix up the pixel coordinate
+ accordingly. */
+ if (lnum_pixel_width > 0)
+ to_x += it.lnum_pixel_width - lnum_pixel_width;
move_it_in_display_line (&it, ZV, first_x + to_x, MOVE_TO_X);
/* If we find ourselves in the middle of an overlay string
which includes a newline after current string position,
@@ -2322,6 +2361,7 @@ syms_of_indent (void)
defsubr (&Sindent_to);
defsubr (&Scurrent_column);
defsubr (&Smove_to_column);
+ defsubr (&Sline_number_display_width);
defsubr (&Svertical_motion);
defsubr (&Scompute_motion);
}
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Emacs-diffs] scratch/line-numbers 4caf65d: Fix vertical-motion across the place where line-number width changes,
Eli Zaretskii <=