aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorEli Zaretskii2017-06-23 17:13:01 +0300
committerEli Zaretskii2017-06-23 17:13:01 +0300
commitd4eddb08e505ff9b4d956f00f225e3baf0d15462 (patch)
tree9b371636d3f457c439adff7923a857f08a873cc4 /src
parent7277c0fca7dab9f1b311c3eba5c42fd17acc3593 (diff)
downloademacs-d4eddb08e505ff9b4d956f00f225e3baf0d15462.tar.gz
emacs-d4eddb08e505ff9b4d956f00f225e3baf0d15462.zip
Fix display of indicate-empty-lines when line numbers are displayed
* src/xdisp.c (row_text_area_empty): New function. (display_line): Call row_text_area_empty to verify that a glyph row's text area is devoid of any glyphs that came from a buffer or a string. This fixes a bug with empty-lines indication disappearing when line numbers or line-prefix are displayed. (display_line): Delete the argument FORCE; all callers changed. Remove the condition for actually producing the glyphs for the line number, as even if the number didn't change we need to produce empty space.
Diffstat (limited to 'src')
-rw-r--r--src/xdisp.c298
1 files changed, 158 insertions, 140 deletions
diff --git a/src/xdisp.c b/src/xdisp.c
index ebf5edc4d05..136e8391d46 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -833,7 +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 void maybe_produce_line_number (struct it *);
837static bool display_line (struct it *, int); 837static bool display_line (struct it *, int);
838static int display_mode_lines (struct window *); 838static int display_mode_lines (struct window *);
839static int display_mode_line (struct window *, enum face_id, Lisp_Object); 839static int display_mode_line (struct window *, enum face_id, Lisp_Object);
@@ -8658,7 +8658,7 @@ move_it_in_display_line_to (struct it *it,
8658 /* If line numbers are being displayed, produce a line number. */ 8658 /* If line numbers are being displayed, produce a line number. */
8659 if (!NILP (Vdisplay_line_numbers) 8659 if (!NILP (Vdisplay_line_numbers)
8660 && it->current_x == it->first_visible_x) 8660 && it->current_x == it->first_visible_x)
8661 maybe_produce_line_number (it, true); 8661 maybe_produce_line_number (it);
8662 /* If there's a line-/wrap-prefix, handle it. */ 8662 /* If there's a line-/wrap-prefix, handle it. */
8663 if (it->method == GET_FROM_BUFFER) 8663 if (it->method == GET_FROM_BUFFER)
8664 handle_line_prefix (it); 8664 handle_line_prefix (it);
@@ -20693,14 +20693,13 @@ find_row_edges (struct it *it, struct glyph_row *row,
20693 20693
20694/* Produce the line-number glyphs for the current glyph_row. If 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 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 20696 glyphs. */
20697 number didn't change since the last time this function was called;
20698 this is used by move_it_in_display_line_to. */
20699static void 20697static void
20700maybe_produce_line_number (struct it *it, bool force) 20698maybe_produce_line_number (struct it *it)
20701{ 20699{
20702 ptrdiff_t last_line = it->lnum; 20700 ptrdiff_t last_line = it->lnum;
20703 ptrdiff_t start_from, bytepos; 20701 ptrdiff_t start_from, bytepos;
20702 ptrdiff_t this_line;
20704 20703
20705 /* FIXME: Maybe reuse the data in it->w->base_line_number. */ 20704 /* FIXME: Maybe reuse the data in it->w->base_line_number. */
20706 if (!last_line) 20705 if (!last_line)
@@ -20717,8 +20716,6 @@ maybe_produce_line_number (struct it *it, bool force)
20717 start_from = BEGV_BYTE; 20716 start_from = BEGV_BYTE;
20718 } 20717 }
20719 20718
20720 ptrdiff_t this_line;
20721
20722 this_line = 20719 this_line =
20723 last_line + display_count_lines (start_from, 20720 last_line + display_count_lines (start_from,
20724 IT_BYTEPOS (*it), IT_CHARPOS (*it), 20721 IT_BYTEPOS (*it), IT_CHARPOS (*it),
@@ -20726,148 +20723,168 @@ maybe_produce_line_number (struct it *it, bool force)
20726 eassert (this_line > 0 || (this_line == 0 && start_from == BEGV_BYTE)); 20723 eassert (this_line > 0 || (this_line == 0 && start_from == BEGV_BYTE));
20727 eassert (bytepos == IT_BYTEPOS (*it)); 20724 eassert (bytepos == IT_BYTEPOS (*it));
20728 20725
20729 /* Produce the glyphs for the line number if needed. */ 20726 /* Produce the glyphs for the line number. */
20730 if (force 20727 if (this_line != last_line || !last_line)
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))
20735 { 20728 {
20736 if (this_line != last_line || !last_line) 20729 it->lnum = this_line;
20737 { 20730 it->lnum_bytepos = IT_BYTEPOS (*it);
20738 it->lnum = this_line; 20731 }
20739 it->lnum_bytepos = IT_BYTEPOS (*it);
20740 }
20741 20732
20742 void *itdata = bidi_shelve_cache (); 20733 void *itdata = bidi_shelve_cache ();
20743 struct it tem_it; 20734 struct it tem_it;
20744 char lnum_buf[INT_STRLEN_BOUND (ptrdiff_t) + 1]; 20735 char lnum_buf[INT_STRLEN_BOUND (ptrdiff_t) + 1];
20745 bool beyond_zv = IT_BYTEPOS (*it) >= ZV_BYTE ? true : false; 20736 bool beyond_zv = IT_BYTEPOS (*it) >= ZV_BYTE ? true : false;
20746 ptrdiff_t lnum_offset = -1; /* to produce 1-based line numbers */ 20737 ptrdiff_t lnum_offset = -1; /* to produce 1-based line numbers */
20747 /* Compute point's line number if needed. */ 20738 /* Compute point's line number if needed. */
20748 if (EQ (Vdisplay_line_numbers, Qrelative) && !it->pt_lnum) 20739 if (EQ (Vdisplay_line_numbers, Qrelative) && !it->pt_lnum)
20749 { 20740 {
20750 ptrdiff_t ignored; 20741 ptrdiff_t ignored;
20751 if (PT_BYTE > it->lnum_bytepos) 20742 if (PT_BYTE > it->lnum_bytepos)
20752 it->pt_lnum = 20743 it->pt_lnum =
20753 this_line + display_count_lines (it->lnum_bytepos, PT_BYTE, PT, 20744 this_line + display_count_lines (it->lnum_bytepos, PT_BYTE, PT,
20754 &ignored); 20745 &ignored);
20755 else 20746 else
20756 it->pt_lnum = display_count_lines (BEGV_BYTE, PT_BYTE, PT, 20747 it->pt_lnum = display_count_lines (BEGV_BYTE, PT_BYTE, PT,
20757 &ignored); 20748 &ignored);
20758 } 20749 }
20759 /* Compute the required width if needed. */ 20750 /* Compute the required width if needed. */
20760 if (!it->lnum_width) 20751 if (!it->lnum_width)
20752 {
20753 if (NATNUMP (Vdisplay_line_width))
20754 it->lnum_width = XFASTINT (Vdisplay_line_width);
20755 else
20761 { 20756 {
20762 if (NATNUMP (Vdisplay_line_width)) 20757 /* Max line number to be displayed cannot be more than
20763 it->lnum_width = XFASTINT (Vdisplay_line_width); 20758 the one corresponding to the last row of the desired
20764 else 20759 matrix. */
20765 { 20760 ptrdiff_t max_lnum;
20766 /* Max line number to be displayed cannot be more than
20767 the one corresponding to the last row of the desired
20768 matrix. */
20769 ptrdiff_t max_lnum;
20770 20761
20771 if (EQ (Vdisplay_line_numbers, Qrelative)) 20762 if (EQ (Vdisplay_line_numbers, Qrelative))
20772 /* We subtract one more because the current line is 20763 /* We subtract one more because the current line is
20773 always zero under relative line-number display. */ 20764 always zero under relative line-number display. */
20774 max_lnum = it->w->desired_matrix->nrows - 2; 20765 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 }
20780 eassert (it->lnum_width > 0);
20781 }
20782 if (EQ (Vdisplay_line_numbers, Qrelative))
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));
20791 strcat (lnum_buf, " ");
20792
20793 /* Setup for producing the glyphs. */
20794 init_iterator (&tem_it, it->w, -1, -1, &scratch_glyph_row,
20795 /* FIXME: Use specialized face. */
20796 DEFAULT_FACE_ID);
20797 scratch_glyph_row.reversed_p = false;
20798 scratch_glyph_row.used[TEXT_AREA] = 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);
20801 tem_it.bidi_it.type = WEAK_EN;
20802 /* According to UAX#9, EN goes up 2 levels in L2R paragraph and
20803 1 level in R2L paragraphs. Emulate that, assuming we are in
20804 an L2R paragraph. */
20805 tem_it.bidi_it.resolved_level = 2;
20806
20807 /* Produce glyphs for the line number in a scratch glyph_row. */
20808 int n_glyphs_before;
20809 for (const char *p = lnum_buf; *p; p++)
20810 {
20811 /* For continuation lines and lines after ZV, instead of a
20812 line number, produce a blank prefix of the same width. */
20813 if (beyond_zv || it->continuation_lines_width > 0)
20814 tem_it.c = tem_it.char_to_display = ' ';
20815 else 20766 else
20816 tem_it.c = tem_it.char_to_display = *p; 20767 max_lnum =
20817 tem_it.len = 1; 20768 this_line + it->w->desired_matrix->nrows - 1 - it->vpos;
20818 n_glyphs_before = scratch_glyph_row.used[TEXT_AREA]; 20769 it->lnum_width = log10 (max_lnum) + 1;
20819 /* Make sure these glyphs will have a "position" of -1. */ 20770 }
20820 SET_TEXT_POS (tem_it.position, -1, -1); 20771 eassert (it->lnum_width > 0);
20821 PRODUCE_GLYPHS (&tem_it); 20772 }
20822 20773 if (EQ (Vdisplay_line_numbers, Qrelative))
20823 /* Stop producing glyphs if we don't have enough space on 20774 lnum_offset = it->pt_lnum;
20824 this line. FIXME: should we refrain from producing the 20775
20825 line number at all in that case? */ 20776 /* In L2R rows we need to append the blank separator, in R2L
20826 if (tem_it.current_x > tem_it.last_visible_x) 20777 rows we need to prepend it. But this function is usually
20827 { 20778 called when no display elements were produced from the
20828 scratch_glyph_row.used[TEXT_AREA] = n_glyphs_before; 20779 following line, so the paragraph direction might be unknown.
20829 break; 20780 Therefore we cheat and add 2 blanks, one on either side. */
20830 } 20781 pint2str (lnum_buf, it->lnum_width + 1, eabs (this_line - lnum_offset));
20782 strcat (lnum_buf, " ");
20783
20784 /* Setup for producing the glyphs. */
20785 init_iterator (&tem_it, it->w, -1, -1, &scratch_glyph_row,
20786 /* FIXME: Use specialized face. */
20787 DEFAULT_FACE_ID);
20788 scratch_glyph_row.reversed_p = false;
20789 scratch_glyph_row.used[TEXT_AREA] = 0;
20790 SET_TEXT_POS (tem_it.position, 0, 0);
20791 tem_it.face_id = merge_faces (it->f, Qline_number, 0, DEFAULT_FACE_ID);
20792 tem_it.bidi_it.type = WEAK_EN;
20793 /* According to UAX#9, EN goes up 2 levels in L2R paragraph and
20794 1 level in R2L paragraphs. Emulate that, assuming we are in
20795 an L2R paragraph. */
20796 tem_it.bidi_it.resolved_level = 2;
20797
20798 /* Produce glyphs for the line number in a scratch glyph_row. */
20799 int n_glyphs_before;
20800 for (const char *p = lnum_buf; *p; p++)
20801 {
20802 /* For continuation lines and lines after ZV, instead of a
20803 line number, produce a blank prefix of the same width. */
20804 if (beyond_zv || it->continuation_lines_width > 0)
20805 tem_it.c = tem_it.char_to_display = ' ';
20806 else
20807 tem_it.c = tem_it.char_to_display = *p;
20808 tem_it.len = 1;
20809 n_glyphs_before = scratch_glyph_row.used[TEXT_AREA];
20810 /* Make sure these glyphs will have a "position" of -1. */
20811 SET_TEXT_POS (tem_it.position, -1, -1);
20812 PRODUCE_GLYPHS (&tem_it);
20813
20814 /* Stop producing glyphs if we don't have enough space on
20815 this line. FIXME: should we refrain from producing the
20816 line number at all in that case? */
20817 if (tem_it.current_x > tem_it.last_visible_x)
20818 {
20819 scratch_glyph_row.used[TEXT_AREA] = n_glyphs_before;
20820 break;
20831 } 20821 }
20822 }
20832 20823
20833 /* Copy the produced glyphs into IT's glyph_row. */ 20824 /* Copy the produced glyphs into IT's glyph_row. */
20834 struct glyph *g = scratch_glyph_row.glyphs[TEXT_AREA]; 20825 struct glyph *g = scratch_glyph_row.glyphs[TEXT_AREA];
20835 struct glyph *e = g + scratch_glyph_row.used[TEXT_AREA]; 20826 struct glyph *e = g + scratch_glyph_row.used[TEXT_AREA];
20836 struct glyph *p = it->glyph_row ? it->glyph_row->glyphs[TEXT_AREA] : NULL; 20827 struct glyph *p = it->glyph_row ? it->glyph_row->glyphs[TEXT_AREA] : NULL;
20837 short *u = it->glyph_row ? &it->glyph_row->used[TEXT_AREA] : NULL; 20828 short *u = it->glyph_row ? &it->glyph_row->used[TEXT_AREA] : NULL;
20838 20829
20839 for ( ; g < e; g++) 20830 for ( ; g < e; g++)
20831 {
20832 it->current_x += g->pixel_width;
20833 /* The following is important when this function is called
20834 from move_it_in_display_line_to: HPOS is incremented only
20835 when we are in the visible portion of the glyph row. */
20836 if (it->current_x > it->first_visible_x)
20837 it->hpos++;
20838 if (p)
20840 { 20839 {
20841 it->current_x += g->pixel_width; 20840 *p++ = *g;
20842 /* The following is important when this function is called 20841 (*u)++;
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++;
20847 if (p)
20848 {
20849 *p++ = *g;
20850 (*u)++;
20851 }
20852 } 20842 }
20843 }
20853 20844
20854 /* Update IT->glyph_row's metrics. */ 20845 /* Update IT->glyph_row's metrics. */
20855 if (it->glyph_row) 20846 if (it->glyph_row)
20856 { 20847 {
20857 struct glyph_row *row = it->glyph_row; 20848 struct glyph_row *row = it->glyph_row;
20858 20849
20859 row->ascent = max (row->ascent, tem_it.max_ascent); 20850 row->ascent = max (row->ascent, tem_it.max_ascent);
20860 row->height = max (row->height, 20851 row->height = max (row->height,
20861 tem_it.max_ascent + tem_it.max_descent); 20852 tem_it.max_ascent + tem_it.max_descent);
20862 row->phys_ascent = max (row->phys_ascent, tem_it.max_phys_ascent); 20853 row->phys_ascent = max (row->phys_ascent, tem_it.max_phys_ascent);
20863 row->phys_height = max (row->phys_height, 20854 row->phys_height = max (row->phys_height,
20864 tem_it.max_phys_ascent + tem_it.max_phys_descent); 20855 tem_it.max_phys_ascent + tem_it.max_phys_descent);
20865 row->extra_line_spacing = max (row->extra_line_spacing, 20856 row->extra_line_spacing = max (row->extra_line_spacing,
20866 tem_it.max_extra_line_spacing); 20857 tem_it.max_extra_line_spacing);
20867 } 20858 }
20868 20859
20869 bidi_unshelve_cache (itdata, false); 20860 bidi_unshelve_cache (itdata, false);
20861}
20862
20863/* Return true if ROW has no glyphs except those inserted by the
20864 display engine. This is needed for indicate-empty-lines and
20865 similar features when the glyph row starts with glyphs which didn't
20866 come from buffer or string. */
20867static bool
20868row_text_area_empty (struct glyph_row *row)
20869{
20870 if (!row->reversed_p)
20871 {
20872 for (struct glyph *g = row->glyphs[TEXT_AREA];
20873 g < row->glyphs[TEXT_AREA] + row->used[TEXT_AREA];
20874 g++)
20875 if (!NILP (g->object) || g->charpos > 0)
20876 return false;
20870 } 20877 }
20878 else
20879 {
20880 for (struct glyph *g = row->glyphs[TEXT_AREA] + row->used[TEXT_AREA] - 1;
20881 g > row->glyphs[TEXT_AREA];
20882 g--)
20883 if (!NILP ((g - 1)->object) || (g - 1)->charpos > 0)
20884 return false;
20885 }
20886
20887 return true;
20871} 20888}
20872 20889
20873/* Construct the glyph row IT->glyph_row in the desired matrix of 20890/* Construct the glyph row IT->glyph_row in the desired matrix of
@@ -20978,13 +20995,13 @@ display_line (struct it *it, int cursor_vpos)
20978 20995
20979 /* Produce line number, if needed. */ 20996 /* Produce line number, if needed. */
20980 if (!NILP (Vdisplay_line_numbers)) 20997 if (!NILP (Vdisplay_line_numbers))
20981 maybe_produce_line_number (it, false); 20998 maybe_produce_line_number (it);
20982 } 20999 }
20983 else if (it->area == TEXT_AREA) 21000 else if (it->area == TEXT_AREA)
20984 { 21001 {
20985 /* Line numbers should precede the line-prefix or wrap-prefix. */ 21002 /* Line numbers should precede the line-prefix or wrap-prefix. */
20986 if (!NILP (Vdisplay_line_numbers)) 21003 if (!NILP (Vdisplay_line_numbers))
20987 maybe_produce_line_number (it, false); 21004 maybe_produce_line_number (it);
20988 21005
20989 /* We only do this when not calling move_it_in_display_line_to 21006 /* We only do this when not calling move_it_in_display_line_to
20990 above, because that function calls itself handle_line_prefix. */ 21007 above, because that function calls itself handle_line_prefix. */
@@ -21055,7 +21072,8 @@ display_line (struct it *it, int cursor_vpos)
21055 row->exact_window_width_line_p = true; 21072 row->exact_window_width_line_p = true;
21056 else if ((append_space_for_newline (it, true) 21073 else if ((append_space_for_newline (it, true)
21057 && row->used[TEXT_AREA] == 1) 21074 && row->used[TEXT_AREA] == 1)
21058 || row->used[TEXT_AREA] == 0) 21075 || row->used[TEXT_AREA] == 0
21076 || row_text_area_empty (row))
21059 { 21077 {
21060 row->glyphs[TEXT_AREA]->charpos = -1; 21078 row->glyphs[TEXT_AREA]->charpos = -1;
21061 row->displays_text_p = false; 21079 row->displays_text_p = false;
@@ -21146,7 +21164,7 @@ display_line (struct it *it, int cursor_vpos)
21146 { 21164 {
21147 /* Line numbers should precede the line-prefix or wrap-prefix. */ 21165 /* Line numbers should precede the line-prefix or wrap-prefix. */
21148 if (!NILP (Vdisplay_line_numbers)) 21166 if (!NILP (Vdisplay_line_numbers))
21149 maybe_produce_line_number (it, false); 21167 maybe_produce_line_number (it);
21150 21168
21151 pending_handle_line_prefix = false; 21169 pending_handle_line_prefix = false;
21152 handle_line_prefix (it); 21170 handle_line_prefix (it);