aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEli Zaretskii2017-06-16 22:44:48 +0300
committerEli Zaretskii2017-06-16 22:44:48 +0300
commitdaf78963ee96484df1ecb0c10e7c0040d7b544a5 (patch)
tree645bebe8802594002507f2d71dbd25ccded9cc24
parent7a2038d7c887e4fa08a91950a7494d1dd20c39e1 (diff)
downloademacs-daf78963ee96484df1ecb0c10e7c0040d7b544a5.tar.gz
emacs-daf78963ee96484df1ecb0c10e7c0040d7b544a5.zip
Initial version of native display of line numbers
* src/xdisp.c (syms_of_xdisp) <display-line-numbers>: New buffer-local variable. Include <math.h>. (maybe_produce_line_number): New function. (DISP_INFINITY): Rename from INFINITY, since math.h defines INFINITY. (try_window_reusing_current_matrix): Don't use this method when display-line-numbers is in effect. * src/dispextern.h (struct it): New members 'lnum'.
-rw-r--r--src/dispextern.h18
-rw-r--r--src/xdisp.c176
2 files changed, 187 insertions, 7 deletions
diff --git a/src/dispextern.h b/src/dispextern.h
index d1e4715c329..050c68b8e08 100644
--- a/src/dispextern.h
+++ b/src/dispextern.h
@@ -384,6 +384,7 @@ struct glyph
384 glyph standing for newline at end of line 0 384 glyph standing for newline at end of line 0
385 empty space after the end of the line -1 385 empty space after the end of the line -1
386 overlay arrow on a TTY -1 386 overlay arrow on a TTY -1
387 glyph displaying line number -1
387 glyph at EOB that ends in a newline -1 388 glyph at EOB that ends in a newline -1
388 left truncation glyphs: -1 389 left truncation glyphs: -1
389 right truncation/continuation glyphs next buffer position 390 right truncation/continuation glyphs next buffer position
@@ -2571,7 +2572,12 @@ struct it
2571 Do NOT use !BUFFERP (it.object) as a test whether we are 2572 Do NOT use !BUFFERP (it.object) as a test whether we are
2572 iterating over a string; use STRINGP (it.string) instead. 2573 iterating over a string; use STRINGP (it.string) instead.
2573 2574
2574 Position is the current iterator position in object. */ 2575 Position is the current iterator position in object.
2576
2577 The 'position's CHARPOS is copied to glyph->charpos of the glyph
2578 produced by PRODUCE_GLYPHS, so any artificial value documented
2579 under 'struct glyph's 'charpos' member can also be found in the
2580 'position' member here. */
2575 Lisp_Object object; 2581 Lisp_Object object;
2576 struct text_pos position; 2582 struct text_pos position;
2577 2583
@@ -2655,6 +2661,16 @@ struct it
2655 coordinate is past first_visible_x. */ 2661 coordinate is past first_visible_x. */
2656 int hpos; 2662 int hpos;
2657 2663
2664 /* Current line number, zero-based. */
2665 ptrdiff_t lnum;
2666
2667 /* The byte position corresponding to lnum. */
2668 ptrdiff_t lnum_bytepos;
2669
2670 /* The width in columns needed for display of the line numbers, or
2671 zero if not computed. */
2672 int lnum_width;
2673
2658 /* Left fringe bitmap number (enum fringe_bitmap_type). */ 2674 /* Left fringe bitmap number (enum fringe_bitmap_type). */
2659 unsigned left_user_fringe_bitmap : FRINGE_ID_BITS; 2675 unsigned left_user_fringe_bitmap : FRINGE_ID_BITS;
2660 2676
diff --git a/src/xdisp.c b/src/xdisp.c
index 34ee877e6be..dcef242966e 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -290,6 +290,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
290#include <stdio.h> 290#include <stdio.h>
291#include <stdlib.h> 291#include <stdlib.h>
292#include <limits.h> 292#include <limits.h>
293#include <math.h>
293 294
294#include "lisp.h" 295#include "lisp.h"
295#include "atimer.h" 296#include "atimer.h"
@@ -324,7 +325,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
324#define FRAME_X_OUTPUT(f) ((f)->output_data.x) 325#define FRAME_X_OUTPUT(f) ((f)->output_data.x)
325#endif 326#endif
326 327
327#define INFINITY 10000000 328#define DISP_INFINITY 10000000
328 329
329/* Holds the list (error). */ 330/* Holds the list (error). */
330static Lisp_Object list_of_error; 331static Lisp_Object list_of_error;
@@ -843,6 +844,8 @@ static const char *decode_mode_spec (struct window *, int, int, Lisp_Object *);
843static void display_menu_bar (struct window *); 844static void display_menu_bar (struct window *);
844static ptrdiff_t display_count_lines (ptrdiff_t, ptrdiff_t, ptrdiff_t, 845static ptrdiff_t display_count_lines (ptrdiff_t, ptrdiff_t, ptrdiff_t,
845 ptrdiff_t *); 846 ptrdiff_t *);
847static void pint2str (register char *, register int, register ptrdiff_t);
848
846static int display_string (const char *, Lisp_Object, Lisp_Object, 849static int display_string (const char *, Lisp_Object, Lisp_Object,
847 ptrdiff_t, ptrdiff_t, struct it *, int, int, int, int); 850 ptrdiff_t, ptrdiff_t, struct it *, int, int, int, int);
848static void compute_line_metrics (struct it *); 851static void compute_line_metrics (struct it *);
@@ -6751,7 +6754,7 @@ reseat_to_string (struct it *it, const char *s, Lisp_Object string,
6751 FIELD_WIDTH < 0 means infinite field width. This is useful for 6754 FIELD_WIDTH < 0 means infinite field width. This is useful for
6752 padding with `-' at the end of a mode line. */ 6755 padding with `-' at the end of a mode line. */
6753 if (field_width < 0) 6756 if (field_width < 0)
6754 field_width = INFINITY; 6757 field_width = DISP_INFINITY;
6755 /* Implementation note: We deliberately don't enlarge 6758 /* Implementation note: We deliberately don't enlarge
6756 it->bidi_it.string.schars here to fit it->end_charpos, because 6759 it->bidi_it.string.schars here to fit it->end_charpos, because
6757 the bidi iterator cannot produce characters out of thin air. */ 6760 the bidi iterator cannot produce characters out of thin air. */
@@ -13138,7 +13141,7 @@ hscroll_window_tree (Lisp_Object window)
13138 if (hscl) 13141 if (hscl)
13139 it.first_visible_x = window_hscroll_limited (w, it.f) 13142 it.first_visible_x = window_hscroll_limited (w, it.f)
13140 * FRAME_COLUMN_WIDTH (it.f); 13143 * FRAME_COLUMN_WIDTH (it.f);
13141 it.last_visible_x = INFINITY; 13144 it.last_visible_x = DISP_INFINITY;
13142 move_it_in_display_line_to (&it, pt, -1, MOVE_TO_POS); 13145 move_it_in_display_line_to (&it, pt, -1, MOVE_TO_POS);
13143 /* If the line ends in an overlay string with a newline, 13146 /* If the line ends in an overlay string with a newline,
13144 we might infloop, because displaying the window will 13147 we might infloop, because displaying the window will
@@ -15823,7 +15826,7 @@ compute_window_start_on_continuation_line (struct window *w)
15823 So, we're looking for the display line start with the 15826 So, we're looking for the display line start with the
15824 minimum distance from the old window start. */ 15827 minimum distance from the old window start. */
15825 pos_before_pt = pos = it.current.pos; 15828 pos_before_pt = pos = it.current.pos;
15826 min_distance = INFINITY; 15829 min_distance = DISP_INFINITY;
15827 while ((distance = eabs (CHARPOS (start_pos) - IT_CHARPOS (it))), 15830 while ((distance = eabs (CHARPOS (start_pos) - IT_CHARPOS (it))),
15828 distance < min_distance) 15831 distance < min_distance)
15829 { 15832 {
@@ -17593,6 +17596,12 @@ try_window_reusing_current_matrix (struct window *w)
17593 if (w->vscroll || MATRIX_ROW_PARTIALLY_VISIBLE_P (w, start_row)) 17596 if (w->vscroll || MATRIX_ROW_PARTIALLY_VISIBLE_P (w, start_row))
17594 return false; 17597 return false;
17595 17598
17599 /* Give up if line numbers are being displayed, because reusing the
17600 current matrix might use the wrong width for line-number
17601 display. */
17602 if (!NILP (Vdisplay_line_numbers))
17603 return false;
17604
17596 /* The variable new_start now holds the new window start. The old 17605 /* The variable new_start now holds the new window start. The old
17597 start `start' can be determined from the current matrix. */ 17606 start `start' can be determined from the current matrix. */
17598 SET_TEXT_POS_FROM_MARKER (new_start, w->start); 17607 SET_TEXT_POS_FROM_MARKER (new_start, w->start);
@@ -20670,6 +20679,141 @@ find_row_edges (struct it *it, struct glyph_row *row,
20670 row->maxpos = it->current.pos; 20679 row->maxpos = it->current.pos;
20671} 20680}
20672 20681
20682static void
20683maybe_produce_line_number (struct it *it)
20684{
20685 ptrdiff_t last_line = it->lnum;
20686 ptrdiff_t start_from, bytepos;
20687
20688 /* FIXME: Maybe reuse the data in it->w->base_line_number. */
20689 if (!last_line)
20690 start_from = BEGV;
20691 else
20692 start_from = it->lnum_bytepos;
20693
20694 /* Paranoia: what if someone changes the narrowing since the last
20695 time display_line was called? Shouldn't really happen, but who
20696 knows what some crazy Lisp invoked by :eval could do? */
20697 if (!(BEGV_BYTE <= start_from && start_from < ZV_BYTE))
20698 {
20699 last_line = 0;
20700 start_from = BEGV_BYTE;
20701 }
20702
20703 ptrdiff_t this_line;
20704
20705 this_line =
20706 last_line + display_count_lines (start_from,
20707 IT_BYTEPOS (*it), IT_CHARPOS (*it),
20708 &bytepos);
20709 eassert (this_line > 0 || (this_line == 0 && start_from == BEGV_BYTE));
20710 eassert (bytepos == IT_BYTEPOS (*it));
20711
20712 /* If this is a new logical line, produce the glyphs for the line
20713 number. */
20714 if (this_line != last_line || !last_line || it->continuation_lines_width > 0)
20715 {
20716 if (this_line != last_line || !last_line)
20717 {
20718 it->lnum = this_line;
20719 it->lnum_bytepos = IT_BYTEPOS (*it);
20720 }
20721
20722 void *itdata = bidi_shelve_cache ();
20723 struct it tem_it;
20724 char lnum_buf[INT_STRLEN_BOUND (ptrdiff_t) + 1];
20725 bool beyond_zv = IT_BYTEPOS (*it) >= ZV_BYTE ? true : false;
20726 /* Compute the required width if needed. */
20727 if (!it->lnum_width)
20728 {
20729 /* Max line number to be displayed cannot be more than the
20730 one corresponding to the last row of the desired
20731 matrix. */
20732 ptrdiff_t max_lnum =
20733 this_line + it->w->desired_matrix->nrows - 1 - it->vpos;
20734 it->lnum_width = log10 (max_lnum) + 1;
20735 eassert (it->lnum_width > 0);
20736 }
20737 pint2str (lnum_buf, it->lnum_width, this_line + 1);
20738 /* Append a blank. */
20739 strcat (lnum_buf, " ");
20740
20741 /* Setup for producing the glyphs. */
20742 init_iterator (&tem_it, it->w, -1, -1, &scratch_glyph_row,
20743 /* FIXME: Use specialized face. */
20744 DEFAULT_FACE_ID);
20745 scratch_glyph_row.reversed_p = false;
20746 scratch_glyph_row.used[TEXT_AREA] = 0;
20747 SET_TEXT_POS (tem_it.position, 0, 0);
20748 tem_it.bidi_it.type = WEAK_EN;
20749 /* According to UAX#9, EN goes up 2 levels in L2R paragraph and
20750 1 level in R2L paragraphs. Emulate that. */
20751 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
20755 /* Produce glyphs for the line number in a scratch glyph_row. */
20756 int n_glyphs_before;
20757 for (const char *p = lnum_buf; *p; p++)
20758 {
20759 /* For continuation lines and lines after ZV, instead of a
20760 line number, produce a blank prefix of the same width. */
20761 if (beyond_zv || it->continuation_lines_width > 0)
20762 tem_it.c = tem_it.char_to_display = ' ';
20763 else
20764 tem_it.c = tem_it.char_to_display = *p;
20765 tem_it.len = 1;
20766 n_glyphs_before = scratch_glyph_row.used[TEXT_AREA];
20767 /* Make sure these glyphs will have a "position" of -1. */
20768 SET_TEXT_POS (tem_it.position, -1, -1);
20769 PRODUCE_GLYPHS (&tem_it);
20770
20771 /* Stop producing glyphs if we don't have enough space on
20772 this line. FIXME: should we refrain from producing the
20773 line number at all in that case? */
20774 if (tem_it.current_x > tem_it.last_visible_x)
20775 {
20776 scratch_glyph_row.used[TEXT_AREA] = n_glyphs_before;
20777 break;
20778 }
20779 }
20780
20781 /* Copy the produced glyphs into IT's glyph_row. */
20782 struct glyph *g = scratch_glyph_row.glyphs[TEXT_AREA];
20783 struct glyph *e = g + scratch_glyph_row.used[TEXT_AREA];
20784 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;
20786
20787 while (g < e)
20788 {
20789 it->current_x += g->pixel_width;
20790 it->hpos++;
20791 if (p)
20792 {
20793 *p++ = *g++;
20794 (*u)++;
20795 }
20796 }
20797
20798 /* Update IT->glyph_row's metrics. */
20799 if (it->glyph_row)
20800 {
20801 struct glyph_row *row = it->glyph_row;
20802
20803 row->ascent = max (row->ascent, tem_it.max_ascent);
20804 row->height = max (row->height,
20805 tem_it.max_ascent + tem_it.max_descent);
20806 row->phys_ascent = max (row->phys_ascent, tem_it.max_phys_ascent);
20807 row->phys_height = max (row->phys_height,
20808 tem_it.max_phys_ascent + tem_it.max_phys_descent);
20809 row->extra_line_spacing = max (row->extra_line_spacing,
20810 tem_it.max_extra_line_spacing);
20811 }
20812
20813 bidi_unshelve_cache (itdata, false);
20814 }
20815}
20816
20673/* Construct the glyph row IT->glyph_row in the desired matrix of 20817/* Construct the glyph row IT->glyph_row in the desired matrix of
20674 IT->w from text at the current position of IT. See dispextern.h 20818 IT->w from text at the current position of IT. See dispextern.h
20675 for an overview of struct it. Value is true if 20819 for an overview of struct it. Value is true if
@@ -20775,9 +20919,17 @@ display_line (struct it *it, int cursor_vpos)
20775 are hscrolled to the left of the left edge of the window. */ 20919 are hscrolled to the left of the left edge of the window. */
20776 min_pos = CHARPOS (this_line_min_pos); 20920 min_pos = CHARPOS (this_line_min_pos);
20777 min_bpos = BYTEPOS (this_line_min_pos); 20921 min_bpos = BYTEPOS (this_line_min_pos);
20922
20923 /* Produce line number, if needed. */
20924 if (!NILP (Vdisplay_line_numbers))
20925 maybe_produce_line_number (it);
20778 } 20926 }
20779 else if (it->area == TEXT_AREA) 20927 else if (it->area == TEXT_AREA)
20780 { 20928 {
20929 /* Line numbers should precede the line-prefix or wrap-prefix. */
20930 if (!NILP (Vdisplay_line_numbers))
20931 maybe_produce_line_number (it);
20932
20781 /* We only do this when not calling move_it_in_display_line_to 20933 /* We only do this when not calling move_it_in_display_line_to
20782 above, because that function calls itself handle_line_prefix. */ 20934 above, because that function calls itself handle_line_prefix. */
20783 handle_line_prefix (it); 20935 handle_line_prefix (it);
@@ -20936,6 +21088,10 @@ display_line (struct it *it, int cursor_vpos)
20936 process the prefix now. */ 21088 process the prefix now. */
20937 if (it->area == TEXT_AREA && pending_handle_line_prefix) 21089 if (it->area == TEXT_AREA && pending_handle_line_prefix)
20938 { 21090 {
21091 /* Line numbers should precede the line-prefix or wrap-prefix. */
21092 if (!NILP (Vdisplay_line_numbers))
21093 maybe_produce_line_number (it);
21094
20939 pending_handle_line_prefix = false; 21095 pending_handle_line_prefix = false;
20940 handle_line_prefix (it); 21096 handle_line_prefix (it);
20941 } 21097 }
@@ -22007,7 +22163,7 @@ Value is the new character position of point. */)
22007 reach point, in order to start from its X coordinate. So we 22163 reach point, in order to start from its X coordinate. So we
22008 need to disregard the window's horizontal extent in that case. */ 22164 need to disregard the window's horizontal extent in that case. */
22009 if (it.line_wrap == TRUNCATE) 22165 if (it.line_wrap == TRUNCATE)
22010 it.last_visible_x = INFINITY; 22166 it.last_visible_x = DISP_INFINITY;
22011 22167
22012 if (it.cmp_it.id < 0 22168 if (it.cmp_it.id < 0
22013 && it.method == GET_FROM_STRING 22169 && it.method == GET_FROM_STRING
@@ -22100,7 +22256,7 @@ Value is the new character position of point. */)
22100 { 22256 {
22101 start_display (&it, w, pt); 22257 start_display (&it, w, pt);
22102 if (it.line_wrap == TRUNCATE) 22258 if (it.line_wrap == TRUNCATE)
22103 it.last_visible_x = INFINITY; 22259 it.last_visible_x = DISP_INFINITY;
22104 reseat_at_previous_visible_line_start (&it); 22260 reseat_at_previous_visible_line_start (&it);
22105 it.current_x = it.current_y = it.hpos = 0; 22261 it.current_x = it.current_y = it.hpos = 0;
22106 if (pt_vpos != 0) 22262 if (pt_vpos != 0)
@@ -32134,6 +32290,14 @@ To add a prefix to continuation lines, use `wrap-prefix'. */);
32134 DEFSYM (Qline_prefix, "line-prefix"); 32290 DEFSYM (Qline_prefix, "line-prefix");
32135 Fmake_variable_buffer_local (Qline_prefix); 32291 Fmake_variable_buffer_local (Qline_prefix);
32136 32292
32293 DEFVAR_LISP ("display-line-numbers", Vdisplay_line_numbers,
32294 doc: /* Non-nil means display line numbers.
32295Line numbers are displayed before each non-continuation line, i.e.
32296after each newline that comes from buffer text. */);
32297 Vdisplay_line_numbers = Qnil;
32298 DEFSYM (Qdisplay_line_numbers, "display-line-numbers");
32299 Fmake_variable_buffer_local (Qdisplay_line_numbers);
32300
32137 DEFVAR_BOOL ("inhibit-eval-during-redisplay", inhibit_eval_during_redisplay, 32301 DEFVAR_BOOL ("inhibit-eval-during-redisplay", inhibit_eval_during_redisplay,
32138 doc: /* Non-nil means don't eval Lisp during redisplay. */); 32302 doc: /* Non-nil means don't eval Lisp during redisplay. */);
32139 inhibit_eval_during_redisplay = false; 32303 inhibit_eval_during_redisplay = false;