diff options
| author | Eli Zaretskii | 2017-06-26 23:20:49 +0300 |
|---|---|---|
| committer | Eli Zaretskii | 2017-06-26 23:20:49 +0300 |
| commit | beb95a8f890da611acc1a4422211deafe512d87d (patch) | |
| tree | 36773cd5f9f5fab4ef3c204dac1397971c4bceab /src | |
| parent | 67c8a219e670eed317acdffc68a2888e2c557e79 (diff) | |
| download | emacs-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.c | 116 |
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. */ | ||
| 20748 | static ptrdiff_t | ||
| 20749 | display_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. | |||
| 32502 | The default value of nil means compute the space dynamically. | 32548 | The default value of nil means compute the space dynamically. |
| 32503 | Any other value is treated as nil. */); | 32549 | Any 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. */); |