aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorEli Zaretskii2017-06-17 17:42:44 +0300
committerEli Zaretskii2017-06-17 17:42:44 +0300
commit7277c0fca7dab9f1b311c3eba5c42fd17acc3593 (patch)
tree6426512a85cc8a16bd274bb93eaf857f440e40db /src
parentdaf78963ee96484df1ecb0c10e7c0040d7b544a5 (diff)
downloademacs-7277c0fca7dab9f1b311c3eba5c42fd17acc3593.tar.gz
emacs-7277c0fca7dab9f1b311c3eba5c42fd17acc3593.zip
Finish up native display of line numbers
* src/xdisp.c (maybe_produce_line_number): Produce a blank before the number, for R2L rows. Increment 'g' in the loop even if glyph_row is NULL. Accept 2nd argument FORCE and produce the line-number glyphs if it is non-zero. (move_it_in_display_line_to): Account for the space taken by the line-number glyphs. Call maybe_produce_line_number with 2nd argument non-zero. (set_cursor_from_row): Fix calculation of cursor X coordinate in R2L rows with display-produced glyphs at the beginning. (syms_of_xdisp) <line-number>: New face symbol. <relative, display-line-width>: New symbols. (maybe_produce_line_number): Use the line-number face for displaying line numbers. Support relative line-number display. Support user-defined width for displaying line numbers. (try_cursor_movement, try_window_id): Disable these optimizations when displaying relative line numbers. * src/dispextern.h (struct it): New member 'pt_lnum'. * lisp/faces.el (line-number): New face. * lisp/cus-start.el (standard): Provide customization forms for display-line-numbers and display-line-width. * lisp/menu-bar.el (menu-bar-showhide-menu): Add menu-bar item to turn display-line-numbers on and off. * etc/NEWS: Document the new feature.
Diffstat (limited to 'src')
-rw-r--r--src/dispextern.h3
-rw-r--r--src/xdisp.c126
2 files changed, 100 insertions, 29 deletions
diff --git a/src/dispextern.h b/src/dispextern.h
index 050c68b8e08..08e5caa893b 100644
--- a/src/dispextern.h
+++ b/src/dispextern.h
@@ -2671,6 +2671,9 @@ struct it
2671 zero if not computed. */ 2671 zero if not computed. */
2672 int lnum_width; 2672 int lnum_width;
2673 2673
2674 /* The line number of point's line, or zero if not computed yet. */
2675 ptrdiff_t pt_lnum;
2676
2674 /* Left fringe bitmap number (enum fringe_bitmap_type). */ 2677 /* Left fringe bitmap number (enum fringe_bitmap_type). */
2675 unsigned left_user_fringe_bitmap : FRINGE_ID_BITS; 2678 unsigned left_user_fringe_bitmap : FRINGE_ID_BITS;
2676 2679
diff --git a/src/xdisp.c b/src/xdisp.c
index dcef242966e..ebf5edc4d05 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -833,6 +833,7 @@ static bool cursor_row_fully_visible_p (struct window *, bool, bool);
833static bool update_menu_bar (struct frame *, bool, bool); 833static bool update_menu_bar (struct frame *, bool, bool);
834static bool try_window_reusing_current_matrix (struct window *); 834static bool try_window_reusing_current_matrix (struct window *);
835static int try_window_id (struct window *); 835static int try_window_id (struct window *);
836static void maybe_produce_line_number (struct it *, bool);
836static bool display_line (struct it *, int); 837static bool display_line (struct it *, int);
837static int display_mode_lines (struct window *); 838static int display_mode_lines (struct window *);
838static int display_mode_line (struct window *, enum face_id, Lisp_Object); 839static int display_mode_line (struct window *, enum face_id, Lisp_Object);
@@ -8652,9 +8653,16 @@ move_it_in_display_line_to (struct it *it,
8652 || (it->method == GET_FROM_DISPLAY_VECTOR \ 8653 || (it->method == GET_FROM_DISPLAY_VECTOR \
8653 && it->dpvec + it->current.dpvec_index + 1 >= it->dpend))) 8654 && it->dpvec + it->current.dpvec_index + 1 >= it->dpend)))
8654 8655
8655 /* If there's a line-/wrap-prefix, handle it. */ 8656 if (it->hpos == 0)
8656 if (it->hpos == 0 && it->method == GET_FROM_BUFFER) 8657 {
8657 handle_line_prefix (it); 8658 /* If line numbers are being displayed, produce a line number. */
8659 if (!NILP (Vdisplay_line_numbers)
8660 && it->current_x == it->first_visible_x)
8661 maybe_produce_line_number (it, true);
8662 /* If there's a line-/wrap-prefix, handle it. */
8663 if (it->method == GET_FROM_BUFFER)
8664 handle_line_prefix (it);
8665 }
8658 8666
8659 if (IT_CHARPOS (*it) < CHARPOS (this_line_min_pos)) 8667 if (IT_CHARPOS (*it) < CHARPOS (this_line_min_pos))
8660 SET_TEXT_POS (this_line_min_pos, IT_CHARPOS (*it), IT_BYTEPOS (*it)); 8668 SET_TEXT_POS (this_line_min_pos, IT_CHARPOS (*it), IT_BYTEPOS (*it));
@@ -14787,15 +14795,12 @@ set_cursor_from_row (struct window *w, struct glyph_row *row,
14787 while (glyph > end + 1 14795 while (glyph > end + 1
14788 && NILP (glyph->object) 14796 && NILP (glyph->object)
14789 && glyph->charpos < 0) 14797 && glyph->charpos < 0)
14790 { 14798 --glyph;
14791 --glyph;
14792 x -= glyph->pixel_width;
14793 }
14794 if (NILP (glyph->object) && glyph->charpos < 0) 14799 if (NILP (glyph->object) && glyph->charpos < 0)
14795 --glyph; 14800 --glyph;
14796 /* By default, in reversed rows we put the cursor on the 14801 /* By default, in reversed rows we put the cursor on the
14797 rightmost (first in the reading order) glyph. */ 14802 rightmost (first in the reading order) glyph. */
14798 for (g = end + 1; g < glyph; g++) 14803 for (x = 0, g = end + 1; g < glyph; g++)
14799 x += g->pixel_width; 14804 x += g->pixel_width;
14800 while (end < glyph 14805 while (end < glyph
14801 && NILP ((end + 1)->object) 14806 && NILP ((end + 1)->object)
@@ -15932,6 +15937,9 @@ try_cursor_movement (Lisp_Object window, struct text_pos startp,
15932 && !windows_or_buffers_changed 15937 && !windows_or_buffers_changed
15933 && !f->cursor_type_changed 15938 && !f->cursor_type_changed
15934 && NILP (Vshow_trailing_whitespace) 15939 && NILP (Vshow_trailing_whitespace)
15940 /* When display-line-numbers is in relative mode, moving point
15941 requires to redraw the entire window. */
15942 && !EQ (Vdisplay_line_numbers, Qrelative)
15935 /* This code is not used for mini-buffer for the sake of the case 15943 /* This code is not used for mini-buffer for the sake of the case
15936 of redisplaying to replace an echo area message; since in 15944 of redisplaying to replace an echo area message; since in
15937 that case the mini-buffer contents per se are usually 15945 that case the mini-buffer contents per se are usually
@@ -18433,6 +18441,10 @@ try_window_id (struct window *w)
18433 if (!NILP (BVAR (XBUFFER (w->contents), extra_line_spacing))) 18441 if (!NILP (BVAR (XBUFFER (w->contents), extra_line_spacing)))
18434 GIVE_UP (23); 18442 GIVE_UP (23);
18435 18443
18444 /* Give up if display-line-numbers is in relative mode. */
18445 if (EQ (Vdisplay_line_numbers, Qrelative))
18446 GIVE_UP (24);
18447
18436 /* Make sure beg_unchanged and end_unchanged are up to date. Do it 18448 /* Make sure beg_unchanged and end_unchanged are up to date. Do it
18437 only if buffer has really changed. The reason is that the gap is 18449 only if buffer has really changed. The reason is that the gap is
18438 initially at Z for freshly visited files. The code below would 18450 initially at Z for freshly visited files. The code below would
@@ -20679,8 +20691,13 @@ find_row_edges (struct it *it, struct glyph_row *row,
20679 row->maxpos = it->current.pos; 20691 row->maxpos = it->current.pos;
20680} 20692}
20681 20693
20694/* Produce the line-number glyphs for the current glyph_row. If
20695 IT->glyph_row is non-NULL, populate the row with the produced
20696 glyphs. FORCE non-zero means produce the glyphs even if the line
20697 number didn't change since the last time this function was called;
20698 this is used by move_it_in_display_line_to. */
20682static void 20699static void
20683maybe_produce_line_number (struct it *it) 20700maybe_produce_line_number (struct it *it, bool force)
20684{ 20701{
20685 ptrdiff_t last_line = it->lnum; 20702 ptrdiff_t last_line = it->lnum;
20686 ptrdiff_t start_from, bytepos; 20703 ptrdiff_t start_from, bytepos;
@@ -20709,9 +20726,12 @@ maybe_produce_line_number (struct it *it)
20709 eassert (this_line > 0 || (this_line == 0 && start_from == BEGV_BYTE)); 20726 eassert (this_line > 0 || (this_line == 0 && start_from == BEGV_BYTE));
20710 eassert (bytepos == IT_BYTEPOS (*it)); 20727 eassert (bytepos == IT_BYTEPOS (*it));
20711 20728
20712 /* If this is a new logical line, produce the glyphs for the line 20729 /* Produce the glyphs for the line number if needed. */
20713 number. */ 20730 if (force
20714 if (this_line != last_line || !last_line || it->continuation_lines_width > 0) 20731 || !last_line
20732 || this_line != last_line
20733 || it->continuation_lines_width > 0
20734 || (EQ (Vdisplay_line_numbers, Qrelative) && PT != it->w->last_point))
20715 { 20735 {
20716 if (this_line != last_line || !last_line) 20736 if (this_line != last_line || !last_line)
20717 { 20737 {
@@ -20723,19 +20743,51 @@ maybe_produce_line_number (struct it *it)
20723 struct it tem_it; 20743 struct it tem_it;
20724 char lnum_buf[INT_STRLEN_BOUND (ptrdiff_t) + 1]; 20744 char lnum_buf[INT_STRLEN_BOUND (ptrdiff_t) + 1];
20725 bool beyond_zv = IT_BYTEPOS (*it) >= ZV_BYTE ? true : false; 20745 bool beyond_zv = IT_BYTEPOS (*it) >= ZV_BYTE ? true : false;
20746 ptrdiff_t lnum_offset = -1; /* to produce 1-based line numbers */
20747 /* Compute point's line number if needed. */
20748 if (EQ (Vdisplay_line_numbers, Qrelative) && !it->pt_lnum)
20749 {
20750 ptrdiff_t ignored;
20751 if (PT_BYTE > it->lnum_bytepos)
20752 it->pt_lnum =
20753 this_line + display_count_lines (it->lnum_bytepos, PT_BYTE, PT,
20754 &ignored);
20755 else
20756 it->pt_lnum = display_count_lines (BEGV_BYTE, PT_BYTE, PT,
20757 &ignored);
20758 }
20726 /* Compute the required width if needed. */ 20759 /* Compute the required width if needed. */
20727 if (!it->lnum_width) 20760 if (!it->lnum_width)
20728 { 20761 {
20729 /* Max line number to be displayed cannot be more than the 20762 if (NATNUMP (Vdisplay_line_width))
20730 one corresponding to the last row of the desired 20763 it->lnum_width = XFASTINT (Vdisplay_line_width);
20731 matrix. */ 20764 else
20732 ptrdiff_t max_lnum = 20765 {
20733 this_line + it->w->desired_matrix->nrows - 1 - it->vpos; 20766 /* Max line number to be displayed cannot be more than
20734 it->lnum_width = log10 (max_lnum) + 1; 20767 the one corresponding to the last row of the desired
20768 matrix. */
20769 ptrdiff_t max_lnum;
20770
20771 if (EQ (Vdisplay_line_numbers, Qrelative))
20772 /* We subtract one more because the current line is
20773 always zero under relative line-number display. */
20774 max_lnum = it->w->desired_matrix->nrows - 2;
20775 else
20776 max_lnum =
20777 this_line + it->w->desired_matrix->nrows - 1 - it->vpos;
20778 it->lnum_width = log10 (max_lnum) + 1;
20779 }
20735 eassert (it->lnum_width > 0); 20780 eassert (it->lnum_width > 0);
20736 } 20781 }
20737 pint2str (lnum_buf, it->lnum_width, this_line + 1); 20782 if (EQ (Vdisplay_line_numbers, Qrelative))
20738 /* Append a blank. */ 20783 lnum_offset = it->pt_lnum;
20784
20785 /* In L2R rows we need to append the blank separator, in R2L
20786 rows we need to prepend it. But this function is usually
20787 called when no display elements were produced from the
20788 following line, so the paragraph direction might be unknown.
20789 Therefore we cheat and add 2 blanks, one on either side. */
20790 pint2str (lnum_buf, it->lnum_width + 1, eabs (this_line - lnum_offset));
20739 strcat (lnum_buf, " "); 20791 strcat (lnum_buf, " ");
20740 20792
20741 /* Setup for producing the glyphs. */ 20793 /* Setup for producing the glyphs. */
@@ -20745,12 +20797,12 @@ maybe_produce_line_number (struct it *it)
20745 scratch_glyph_row.reversed_p = false; 20797 scratch_glyph_row.reversed_p = false;
20746 scratch_glyph_row.used[TEXT_AREA] = 0; 20798 scratch_glyph_row.used[TEXT_AREA] = 0;
20747 SET_TEXT_POS (tem_it.position, 0, 0); 20799 SET_TEXT_POS (tem_it.position, 0, 0);
20800 tem_it.face_id = merge_faces (it->f, Qline_number, 0, DEFAULT_FACE_ID);
20748 tem_it.bidi_it.type = WEAK_EN; 20801 tem_it.bidi_it.type = WEAK_EN;
20749 /* According to UAX#9, EN goes up 2 levels in L2R paragraph and 20802 /* According to UAX#9, EN goes up 2 levels in L2R paragraph and
20750 1 level in R2L paragraphs. Emulate that. */ 20803 1 level in R2L paragraphs. Emulate that, assuming we are in
20804 an L2R paragraph. */
20751 tem_it.bidi_it.resolved_level = 2; 20805 tem_it.bidi_it.resolved_level = 2;
20752 if (it->glyph_row && it->glyph_row->reversed_p)
20753 tem_it.bidi_it.resolved_level = 1;
20754 20806
20755 /* Produce glyphs for the line number in a scratch glyph_row. */ 20807 /* Produce glyphs for the line number in a scratch glyph_row. */
20756 int n_glyphs_before; 20808 int n_glyphs_before;
@@ -20784,13 +20836,17 @@ maybe_produce_line_number (struct it *it)
20784 struct glyph *p = it->glyph_row ? it->glyph_row->glyphs[TEXT_AREA] : NULL; 20836 struct glyph *p = it->glyph_row ? it->glyph_row->glyphs[TEXT_AREA] : NULL;
20785 short *u = it->glyph_row ? &it->glyph_row->used[TEXT_AREA] : NULL; 20837 short *u = it->glyph_row ? &it->glyph_row->used[TEXT_AREA] : NULL;
20786 20838
20787 while (g < e) 20839 for ( ; g < e; g++)
20788 { 20840 {
20789 it->current_x += g->pixel_width; 20841 it->current_x += g->pixel_width;
20790 it->hpos++; 20842 /* The following is important when this function is called
20843 from move_it_in_display_line_to: HPOS is incremented only
20844 when we are in the visible portion of the glyph row. */
20845 if (it->current_x > it->first_visible_x)
20846 it->hpos++;
20791 if (p) 20847 if (p)
20792 { 20848 {
20793 *p++ = *g++; 20849 *p++ = *g;
20794 (*u)++; 20850 (*u)++;
20795 } 20851 }
20796 } 20852 }
@@ -20922,13 +20978,13 @@ display_line (struct it *it, int cursor_vpos)
20922 20978
20923 /* Produce line number, if needed. */ 20979 /* Produce line number, if needed. */
20924 if (!NILP (Vdisplay_line_numbers)) 20980 if (!NILP (Vdisplay_line_numbers))
20925 maybe_produce_line_number (it); 20981 maybe_produce_line_number (it, false);
20926 } 20982 }
20927 else if (it->area == TEXT_AREA) 20983 else if (it->area == TEXT_AREA)
20928 { 20984 {
20929 /* Line numbers should precede the line-prefix or wrap-prefix. */ 20985 /* Line numbers should precede the line-prefix or wrap-prefix. */
20930 if (!NILP (Vdisplay_line_numbers)) 20986 if (!NILP (Vdisplay_line_numbers))
20931 maybe_produce_line_number (it); 20987 maybe_produce_line_number (it, false);
20932 20988
20933 /* We only do this when not calling move_it_in_display_line_to 20989 /* We only do this when not calling move_it_in_display_line_to
20934 above, because that function calls itself handle_line_prefix. */ 20990 above, because that function calls itself handle_line_prefix. */
@@ -21090,7 +21146,7 @@ display_line (struct it *it, int cursor_vpos)
21090 { 21146 {
21091 /* Line numbers should precede the line-prefix or wrap-prefix. */ 21147 /* Line numbers should precede the line-prefix or wrap-prefix. */
21092 if (!NILP (Vdisplay_line_numbers)) 21148 if (!NILP (Vdisplay_line_numbers))
21093 maybe_produce_line_number (it); 21149 maybe_produce_line_number (it, false);
21094 21150
21095 pending_handle_line_prefix = false; 21151 pending_handle_line_prefix = false;
21096 handle_line_prefix (it); 21152 handle_line_prefix (it);
@@ -31778,6 +31834,9 @@ They are still logged to the *Messages* buffer. */);
31778 /* Name of the face used to highlight trailing whitespace. */ 31834 /* Name of the face used to highlight trailing whitespace. */
31779 DEFSYM (Qtrailing_whitespace, "trailing-whitespace"); 31835 DEFSYM (Qtrailing_whitespace, "trailing-whitespace");
31780 31836
31837 /* Name of the face used to display line numbers. */
31838 DEFSYM (Qline_number, "line-number");
31839
31781 /* Name and number of the face used to highlight escape glyphs. */ 31840 /* Name and number of the face used to highlight escape glyphs. */
31782 DEFSYM (Qescape_glyph, "escape-glyph"); 31841 DEFSYM (Qescape_glyph, "escape-glyph");
31783 31842
@@ -32297,6 +32356,15 @@ after each newline that comes from buffer text. */);
32297 Vdisplay_line_numbers = Qnil; 32356 Vdisplay_line_numbers = Qnil;
32298 DEFSYM (Qdisplay_line_numbers, "display-line-numbers"); 32357 DEFSYM (Qdisplay_line_numbers, "display-line-numbers");
32299 Fmake_variable_buffer_local (Qdisplay_line_numbers); 32358 Fmake_variable_buffer_local (Qdisplay_line_numbers);
32359 DEFSYM (Qrelative, "relative");
32360
32361 DEFVAR_LISP ("display-line-width", Vdisplay_line_width,
32362 doc: /* Minimum width of space reserved for line number display.
32363A positive number means reserve that many columns for line numbers,
32364even if the actual number needs less space.
32365The default value of nil means compute the space dynamically.
32366Any other value is treated as nil. */);
32367 Vdisplay_line_width = Qnil;
32300 32368
32301 DEFVAR_BOOL ("inhibit-eval-during-redisplay", inhibit_eval_during_redisplay, 32369 DEFVAR_BOOL ("inhibit-eval-during-redisplay", inhibit_eval_during_redisplay,
32302 doc: /* Non-nil means don't eval Lisp during redisplay. */); 32370 doc: /* Non-nil means don't eval Lisp during redisplay. */);