aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorEli Zaretskii2017-06-26 23:20:49 +0300
committerEli Zaretskii2017-06-26 23:20:49 +0300
commitbeb95a8f890da611acc1a4422211deafe512d87d (patch)
tree36773cd5f9f5fab4ef3c204dac1397971c4bceab /src
parent67c8a219e670eed317acdffc68a2888e2c557e79 (diff)
downloademacs-beb95a8f890da611acc1a4422211deafe512d87d.tar.gz
emacs-beb95a8f890da611acc1a4422211deafe512d87d.zip
Initial support for visually-relative line numbers
Works very slowly. * src/xdisp.c (display_count_lines_visually): New function. (maybe_produce_line_number): Support 'visual' mode of line-number display. * src/xdisp.c (maybe_produce_line_number): Update IT's metrics also when glyph_row is NULL. This is important for move_it_* functions. (syms_of_xdisp) <display-line-number-width>: Now buffer-local. (try_window_id, redisplay_window, try_cursor_movement): For 'visual' line-number display, disable the same redisplay optimizations as for 'relative'. * lisp/cus-start.el (standard): Add new value for the customization form of display-line-numbers.
Diffstat (limited to 'src')
-rw-r--r--src/xdisp.c116
1 files changed, 82 insertions, 34 deletions
diff --git a/src/xdisp.c b/src/xdisp.c
index 3283f9ee971..67266fdf315 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -15973,6 +15973,7 @@ try_cursor_movement (Lisp_Object window, struct text_pos startp,
15973 /* When display-line-numbers is in relative mode, moving point 15973 /* When display-line-numbers is in relative mode, moving point
15974 requires to redraw the entire window. */ 15974 requires to redraw the entire window. */
15975 && !EQ (Vdisplay_line_numbers, Qrelative) 15975 && !EQ (Vdisplay_line_numbers, Qrelative)
15976 && !EQ (Vdisplay_line_numbers, Qvisual)
15976 /* When the current line number should be displayed in a 15977 /* When the current line number should be displayed in a
15977 distinct face, moving point cannot be handled in optimized 15978 distinct face, moving point cannot be handled in optimized
15978 way as below. */ 15979 way as below. */
@@ -16841,7 +16842,8 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
16841 safe__call1 (true, Vpre_redisplay_function, Fcons (window, Qnil)); 16842 safe__call1 (true, Vpre_redisplay_function, Fcons (window, Qnil));
16842 16843
16843 if (w->redisplay || XBUFFER (w->contents)->text->redisplay 16844 if (w->redisplay || XBUFFER (w->contents)->text->redisplay
16844 || (EQ (Vdisplay_line_numbers, Qrelative) 16845 || ((EQ (Vdisplay_line_numbers, Qrelative)
16846 || EQ (Vdisplay_line_numbers, Qvisual))
16845 && row != MATRIX_FIRST_TEXT_ROW (w->desired_matrix))) 16847 && row != MATRIX_FIRST_TEXT_ROW (w->desired_matrix)))
16846 { 16848 {
16847 /* Either pre-redisplay-function made changes (e.g. move 16849 /* Either pre-redisplay-function made changes (e.g. move
@@ -18488,6 +18490,7 @@ try_window_id (struct window *w)
18488 /* Give up if display-line-numbers is in relative mode, or when the 18490 /* Give up if display-line-numbers is in relative mode, or when the
18489 current line's number needs to be displayed in a distinct face. */ 18491 current line's number needs to be displayed in a distinct face. */
18490 if (EQ (Vdisplay_line_numbers, Qrelative) 18492 if (EQ (Vdisplay_line_numbers, Qrelative)
18493 || EQ (Vdisplay_line_numbers, Qvisual)
18491 || (!NILP (Vdisplay_line_numbers) 18494 || (!NILP (Vdisplay_line_numbers)
18492 && NILP (Finternal_lisp_face_equal_p (Qline_number, 18495 && NILP (Finternal_lisp_face_equal_p (Qline_number,
18493 Qline_number_current_line, 18496 Qline_number_current_line,
@@ -20740,6 +20743,35 @@ find_row_edges (struct it *it, struct glyph_row *row,
20740 row->maxpos = it->current.pos; 20743 row->maxpos = it->current.pos;
20741} 20744}
20742 20745
20746/* Count the number of screen lines in window W between character
20747 position CHARPOS and the line showing that window's point. */
20748static ptrdiff_t
20749display_count_lines_visually (struct window *w, struct text_pos pos)
20750{
20751 struct it tem_it;
20752 ptrdiff_t to;
20753 struct text_pos from;
20754 ptrdiff_t count = SPECPDL_INDEX ();
20755
20756 if (CHARPOS (pos) <= PT)
20757 {
20758 from = pos;
20759 to = PT;
20760 }
20761 else
20762 {
20763 SET_TEXT_POS (from, PT, PT_BYTE);
20764 to = CHARPOS (pos);
20765 }
20766 start_display (&tem_it, w, from);
20767 /* Need to disable visual mode temporarily, since otherwise the call
20768 to move_it_to will cause infionite recursion. */
20769 specbind (Qdisplay_line_numbers, Qrelative);
20770 move_it_to (&tem_it, to, -1, -1, -1, MOVE_TO_POS);
20771 unbind_to (count, Qnil);
20772 return CHARPOS (pos) <= PT ? -tem_it.vpos : tem_it.vpos;
20773}
20774
20743/* Produce the line-number glyphs for the current glyph_row. If 20775/* Produce the line-number glyphs for the current glyph_row. If
20744 IT->glyph_row is non-NULL, populate the row with the produced 20776 IT->glyph_row is non-NULL, populate the row with the produced
20745 glyphs. */ 20777 glyphs. */
@@ -20750,42 +20782,47 @@ maybe_produce_line_number (struct it *it)
20750 ptrdiff_t start_from, bytepos; 20782 ptrdiff_t start_from, bytepos;
20751 ptrdiff_t this_line; 20783 ptrdiff_t this_line;
20752 bool first_time = false; 20784 bool first_time = false;
20785 void *itdata = bidi_shelve_cache ();
20753 20786
20754 /* FIXME: Maybe reuse the data in it->w->base_line_number. */ 20787 if (EQ (Vdisplay_line_numbers, Qvisual))
20755 if (!last_line) 20788 this_line = display_count_lines_visually (it->w, it->current.pos);
20756 {
20757 start_from = BEGV;
20758 if (!it->lnum_bytepos)
20759 first_time = true;
20760 }
20761 else 20789 else
20762 start_from = it->lnum_bytepos;
20763
20764 /* Paranoia: what if someone changes the narrowing since the last
20765 time display_line was called? Shouldn't really happen, but who
20766 knows what some crazy Lisp invoked by :eval could do? */
20767 if (!(BEGV_BYTE <= start_from && start_from < ZV_BYTE))
20768 { 20790 {
20769 last_line = 0; 20791 if (!last_line)
20770 start_from = BEGV_BYTE; 20792 {
20771 } 20793 /* FIXME: Maybe reuse the data in it->w->base_line_number. */
20794 start_from = BEGV;
20795 if (!it->lnum_bytepos)
20796 first_time = true;
20797 }
20798 else
20799 start_from = it->lnum_bytepos;
20772 20800
20773 this_line = 20801 /* Paranoia: what if someone changes the narrowing since the
20774 last_line + display_count_lines (start_from, 20802 last time display_line was called? Shouldn't really happen,
20775 IT_BYTEPOS (*it), IT_CHARPOS (*it), 20803 but who knows what some crazy Lisp invoked by :eval could do? */
20776 &bytepos); 20804 if (!(BEGV_BYTE <= start_from && start_from < ZV_BYTE))
20777 eassert (this_line > 0 || (this_line == 0 && start_from == BEGV_BYTE)); 20805 {
20778 eassert (bytepos == IT_BYTEPOS (*it)); 20806 last_line = 0;
20807 start_from = BEGV_BYTE;
20808 }
20779 20809
20780 /* Record the line number information. */ 20810 this_line =
20781 if (this_line != last_line || !last_line) 20811 last_line + display_count_lines (start_from,
20782 { 20812 IT_BYTEPOS (*it), IT_CHARPOS (*it),
20783 it->lnum = this_line; 20813 &bytepos);
20784 it->lnum_bytepos = IT_BYTEPOS (*it); 20814 eassert (this_line > 0 || (this_line == 0 && start_from == BEGV_BYTE));
20815 eassert (bytepos == IT_BYTEPOS (*it));
20816
20817 /* Record the line number information. */
20818 if (this_line != last_line || !last_line)
20819 {
20820 it->lnum = this_line;
20821 it->lnum_bytepos = IT_BYTEPOS (*it);
20822 }
20785 } 20823 }
20786 20824
20787 /* Produce the glyphs for the line number. */ 20825 /* Produce the glyphs for the line number. */
20788 void *itdata = bidi_shelve_cache ();
20789 struct it tem_it; 20826 struct it tem_it;
20790 char lnum_buf[INT_STRLEN_BOUND (ptrdiff_t) + 1]; 20827 char lnum_buf[INT_STRLEN_BOUND (ptrdiff_t) + 1];
20791 bool beyond_zv = IT_BYTEPOS (*it) >= ZV_BYTE ? true : false; 20828 bool beyond_zv = IT_BYTEPOS (*it) >= ZV_BYTE ? true : false;
@@ -20795,11 +20832,12 @@ maybe_produce_line_number (struct it *it)
20795 = merge_faces (it->f, Qline_number_current_line, 0, DEFAULT_FACE_ID); 20832 = merge_faces (it->f, Qline_number_current_line, 0, DEFAULT_FACE_ID);
20796 /* Compute point's line number if needed. */ 20833 /* Compute point's line number if needed. */
20797 if ((EQ (Vdisplay_line_numbers, Qrelative) 20834 if ((EQ (Vdisplay_line_numbers, Qrelative)
20835 || EQ (Vdisplay_line_numbers, Qvisual)
20798 || lnum_face_id != current_lnum_face_id) 20836 || lnum_face_id != current_lnum_face_id)
20799 && !it->pt_lnum) 20837 && !it->pt_lnum)
20800 { 20838 {
20801 ptrdiff_t ignored; 20839 ptrdiff_t ignored;
20802 if (PT_BYTE > it->lnum_bytepos) 20840 if (PT_BYTE > it->lnum_bytepos && !EQ (Vdisplay_line_numbers, Qvisual))
20803 it->pt_lnum = 20841 it->pt_lnum =
20804 this_line + display_count_lines (it->lnum_bytepos, PT_BYTE, PT, 20842 this_line + display_count_lines (it->lnum_bytepos, PT_BYTE, PT,
20805 &ignored); 20843 &ignored);
@@ -20819,7 +20857,10 @@ maybe_produce_line_number (struct it *it)
20819 matrix. */ 20857 matrix. */
20820 ptrdiff_t max_lnum; 20858 ptrdiff_t max_lnum;
20821 20859
20822 max_lnum = this_line + it->w->desired_matrix->nrows - 1 - it->vpos; 20860 if (EQ (Vdisplay_line_numbers, Qvisual))
20861 max_lnum = it->pt_lnum + it->w->desired_matrix->nrows - 1;
20862 else
20863 max_lnum = this_line + it->w->desired_matrix->nrows - 1 - it->vpos;
20823 max_lnum = max (1, max_lnum); 20864 max_lnum = max (1, max_lnum);
20824 it->lnum_width = log10 (max_lnum) + 1; 20865 it->lnum_width = log10 (max_lnum) + 1;
20825 } 20866 }
@@ -20827,11 +20868,14 @@ maybe_produce_line_number (struct it *it)
20827 } 20868 }
20828 if (EQ (Vdisplay_line_numbers, Qrelative)) 20869 if (EQ (Vdisplay_line_numbers, Qrelative))
20829 lnum_offset = it->pt_lnum; 20870 lnum_offset = it->pt_lnum;
20871 else if (EQ (Vdisplay_line_numbers, Qvisual))
20872 lnum_offset = 0;
20830 20873
20831 /* Under 'relative', display the absolute line number for the 20874 /* Under 'relative', display the absolute line number for the
20832 current line, as displaying zero gives zero useful information. */ 20875 current line, as displaying zero gives zero useful information. */
20833 ptrdiff_t lnum_to_display = eabs (this_line - lnum_offset); 20876 ptrdiff_t lnum_to_display = eabs (this_line - lnum_offset);
20834 if (EQ (Vdisplay_line_numbers, Qrelative) 20877 if ((EQ (Vdisplay_line_numbers, Qrelative)
20878 || EQ (Vdisplay_line_numbers, Qvisual))
20835 && lnum_to_display == 0) 20879 && lnum_to_display == 0)
20836 lnum_to_display = it->pt_lnum + 1; 20880 lnum_to_display = it->pt_lnum + 1;
20837 /* In L2R rows we need to append the blank separator, in R2L 20881 /* In L2R rows we need to append the blank separator, in R2L
@@ -20872,8 +20916,9 @@ maybe_produce_line_number (struct it *it)
20872 tem_it.face_id = lnum_face_id; 20916 tem_it.face_id = lnum_face_id;
20873 if (beyond_zv 20917 if (beyond_zv
20874 /* Don't display the same line number more than once. */ 20918 /* Don't display the same line number more than once. */
20875 || it->continuation_lines_width > 0 20919 && (!EQ (Vdisplay_line_numbers, Qvisual)
20876 || (this_line == last_line && !first_time)) 20920 && (it->continuation_lines_width > 0
20921 || (this_line == last_line && !first_time))))
20877 tem_it.c = tem_it.char_to_display = ' '; 20922 tem_it.c = tem_it.char_to_display = ' ';
20878 else 20923 else
20879 tem_it.c = tem_it.char_to_display = *p; 20924 tem_it.c = tem_it.char_to_display = *p;
@@ -32494,6 +32539,7 @@ after each newline that comes from buffer text. */);
32494 DEFSYM (Qdisplay_line_numbers, "display-line-numbers"); 32539 DEFSYM (Qdisplay_line_numbers, "display-line-numbers");
32495 Fmake_variable_buffer_local (Qdisplay_line_numbers); 32540 Fmake_variable_buffer_local (Qdisplay_line_numbers);
32496 DEFSYM (Qrelative, "relative"); 32541 DEFSYM (Qrelative, "relative");
32542 DEFSYM (Qvisual, "visual");
32497 32543
32498 DEFVAR_LISP ("display-line-number-width", Vdisplay_line_number_width, 32544 DEFVAR_LISP ("display-line-number-width", Vdisplay_line_number_width,
32499 doc: /* Minimum width of space reserved for line number display. 32545 doc: /* Minimum width of space reserved for line number display.
@@ -32502,6 +32548,8 @@ even if the actual number needs less space.
32502The default value of nil means compute the space dynamically. 32548The default value of nil means compute the space dynamically.
32503Any other value is treated as nil. */); 32549Any other value is treated as nil. */);
32504 Vdisplay_line_number_width = Qnil; 32550 Vdisplay_line_number_width = Qnil;
32551 DEFSYM (Qdisplay_line_number_width, "display-line-number-width");
32552 Fmake_variable_buffer_local (Qdisplay_line_number_width);
32505 32553
32506 DEFVAR_BOOL ("inhibit-eval-during-redisplay", inhibit_eval_during_redisplay, 32554 DEFVAR_BOOL ("inhibit-eval-during-redisplay", inhibit_eval_during_redisplay,
32507 doc: /* Non-nil means don't eval Lisp during redisplay. */); 32555 doc: /* Non-nil means don't eval Lisp during redisplay. */);