diff options
| author | Eli Zaretskii | 2017-06-17 17:42:44 +0300 |
|---|---|---|
| committer | Eli Zaretskii | 2017-06-17 17:42:44 +0300 |
| commit | 7277c0fca7dab9f1b311c3eba5c42fd17acc3593 (patch) | |
| tree | 6426512a85cc8a16bd274bb93eaf857f440e40db /src | |
| parent | daf78963ee96484df1ecb0c10e7c0040d7b544a5 (diff) | |
| download | emacs-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.h | 3 | ||||
| -rw-r--r-- | src/xdisp.c | 126 |
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); | |||
| 833 | static bool update_menu_bar (struct frame *, bool, bool); | 833 | static bool update_menu_bar (struct frame *, bool, bool); |
| 834 | static bool try_window_reusing_current_matrix (struct window *); | 834 | static bool try_window_reusing_current_matrix (struct window *); |
| 835 | static int try_window_id (struct window *); | 835 | static int try_window_id (struct window *); |
| 836 | static void maybe_produce_line_number (struct it *, bool); | ||
| 836 | static bool display_line (struct it *, int); | 837 | static bool display_line (struct it *, int); |
| 837 | static int display_mode_lines (struct window *); | 838 | static int display_mode_lines (struct window *); |
| 838 | static int display_mode_line (struct window *, enum face_id, Lisp_Object); | 839 | static 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. */ | ||
| 20682 | static void | 20699 | static void |
| 20683 | maybe_produce_line_number (struct it *it) | 20700 | maybe_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. | ||
| 32363 | A positive number means reserve that many columns for line numbers, | ||
| 32364 | even if the actual number needs less space. | ||
| 32365 | The default value of nil means compute the space dynamically. | ||
| 32366 | Any 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. */); |