From ba5f83dfe5dea1b9dd3fca5d21384afc92cd2060 Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Sat, 30 May 2015 12:33:08 +0300 Subject: [PATCH] Fix display of cursor at end of empty lines * src/xdisp.c (normal_char_ascent_descent): Accept additional argument: the character to use for metrics in case the font declares too large ascent and descent values. Add 1 pixel to ascent and descent values. (normal_char_height): Accept additional argument: the character to use for metrics in case the font declares too large height value. Call normal_char_ascent_descent instead of doing calculations for a different default character. (estimate_mode_line_height, handle_single_display_spec) (calc_pixel_width_or_height, produce_stretch_glyph) (calc_line_height_property, produce_glyphless_glyph): All callers changed. (append_space_for_newline): Make sure the space glyph produced at end of line has correct ascent and descent values, and the glyph row has correct height, even when it's empty. --- src/xdisp.c | 100 ++++++++++++++++++++++++++++------------------------ 1 file changed, 54 insertions(+), 46 deletions(-) diff --git a/src/xdisp.c b/src/xdisp.c index 1fd84f8ade0..50d7376b28a 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -833,7 +833,9 @@ static void x_draw_bottom_divider (struct window *w); static void notice_overwritten_cursor (struct window *, enum glyph_row_area, int, int, int, int); -static int normal_char_height (struct font *); +static int normal_char_height (struct font *, int); +static void normal_char_ascent_descent (struct font *, int, int *, int *); + static void append_stretch_glyph (struct it *, Lisp_Object, int, int, int); @@ -1762,7 +1764,7 @@ estimate_mode_line_height (struct frame *f, enum face_id face_id) if (face) { if (face->font) - height = normal_char_height (face->font); + height = normal_char_height (face->font, -1); if (face->box_line_width > 0) height += 2 * face->box_line_width; } @@ -4889,7 +4891,7 @@ handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object, { struct face *face = FACE_FROM_ID (it->f, it->face_id); it->voffset = - (XFLOATINT (value) - * (normal_char_height (face->font))); + * (normal_char_height (face->font, -1))); } #endif /* HAVE_WINDOW_SYSTEM */ } @@ -19212,10 +19214,22 @@ append_space_for_newline (struct it *it, bool default_face_p) PRODUCE_GLYPHS (it); - /* Make sure this space glyph has the right ascent value, or - else hollow cursor at end of line will look funny. */ + /* Make sure this space glyph has the right ascent and + descent values, or else cursor at end of line will look + funny. */ g = it->glyph_row->glyphs[TEXT_AREA] + n; - g->ascent = it->glyph_row->ascent; + struct font *font = face->font ? face->font : FRAME_FONT (it->f); + if (n == 0 || it->glyph_row->height < font->pixel_size) + { + normal_char_ascent_descent (font, -1, &it->ascent, &it->descent); + it->max_ascent = it->ascent; + it->max_descent = it->descent; + /* Make sure compute_line_metrics recomputes the row height. */ + it->glyph_row->height = 0; + } + + g->ascent = it->max_ascent; + g->descent = it->max_descent; it->override_ascent = -1; it->constrain_row_ascent_descent_p = false; @@ -23930,7 +23944,7 @@ calc_pixel_width_or_height (double *res, struct it *it, Lisp_Object prop, #ifdef HAVE_WINDOW_SYSTEM if (EQ (prop, Qheight)) return OK_PIXELS (font - ? normal_char_height (font) + ? normal_char_height (font, -1) : FRAME_LINE_HEIGHT (it->f)); if (EQ (prop, Qwidth)) return OK_PIXELS (font @@ -24569,39 +24583,14 @@ get_per_char_metric (struct font *font, XChar2b *char2b) return &metrics; } -/* A subroutine that computes a reasonable "normal character height" - for fonts that claim preposterously large vertical dimensions, but - whose glyphs are actually reasonably sized. */ -static int -normal_char_height (struct font *font) -{ - int default_height = FONT_HEIGHT (font); - - /* If the font claims too large height, use the metrics of the SPC - character instead. Note that this could still fail to produce a - better value if the font or the font driver don't support the - functionality required by get_per_char_metric. */ - if (FONT_TOO_HIGH (font)) - { - XChar2b char2b; - - /* Get metrics of the SPC character. */ - if (get_char_glyph_code (' ', font, &char2b)) - { - struct font_metrics *pcm = get_per_char_metric (font, &char2b); - - if (!(pcm->width == 0 && pcm->rbearing == 0 && pcm->lbearing == 0)) - default_height = pcm->ascent + pcm->descent; - } - } - return default_height; -} - -/* A subroutine that computes "normal" values of ascent and descent - for fonts that claim preposterously large values, but whose glyphs - actually have reasonable dimensions. */ +/* A subroutine that computes "normal" values of ASCENT and DESCENT + for FONT. Values are taken from font-global ones, except for fonts + that claim preposterously large values, but whose glyphs actually + have reasonable dimensions. C is the character to use for metrics + if the font-global values are too large; if C is negative, the + function selects a default character. */ static void -normal_char_ascent_descent (struct font *font, int *ascent, int *descent) +normal_char_ascent_descent (struct font *font, int c, int *ascent, int *descent) { *ascent = FONT_BASE (font); *descent = FONT_DESCENT (font); @@ -24610,20 +24599,39 @@ normal_char_ascent_descent (struct font *font, int *ascent, int *descent) { XChar2b char2b; - /* Get metrics of a reasonably sized ASCII character. */ - if (get_char_glyph_code ('{', font, &char2b)) + /* Get metrics of C, defaulting to a reasonably sized ASCII + character. */ + if (get_char_glyph_code (c >= 0 ? c : '{', font, &char2b)) { struct font_metrics *pcm = get_per_char_metric (font, &char2b); if (!(pcm->width == 0 && pcm->rbearing == 0 && pcm->lbearing == 0)) { - *ascent = pcm->ascent; - *descent = pcm->descent; + /* We add 1 pixel to character dimensions as heuristics + that produces nicer display, e.g. when the face has + the box attribute. */ + *ascent = pcm->ascent + 1; + *descent = pcm->descent + 1; } } } } +/* A subroutine that computes a reasonable "normal character height" + for fonts that claim preposterously large vertical dimensions, but + whose glyphs are actually reasonably sized. C is the charcater + whose metrics to use for those fonts, or -1 for default + character. */ +static int +normal_char_height (struct font *font, int c) +{ + int ascent, descent; + + normal_char_ascent_descent (font, c, &ascent, &descent); + + return ascent + descent; +} + /* EXPORT for RIF: Set *LEFT and *RIGHT to the left and right overhang of GLYPH on frame F. Overhangs of glyphs other than type CHAR_GLYPH are @@ -25923,7 +25931,7 @@ produce_stretch_glyph (struct it *it) /* Compute height. */ if (FRAME_WINDOW_P (it->f)) { - int default_height = normal_char_height (font); + int default_height = normal_char_height (font, ' '); if ((prop = Fplist_get (plist, QCheight), !NILP (prop)) && calc_pixel_width_or_height (&tem, it, prop, font, false, 0)) @@ -26159,7 +26167,7 @@ calc_line_height_property (struct it *it, Lisp_Object val, struct font *font, boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff; } - normal_char_ascent_descent (font, &ascent, &descent); + normal_char_ascent_descent (font, -1, &ascent, &descent); if (override) { @@ -26285,7 +26293,7 @@ produce_glyphless_glyph (struct it *it, bool for_no_font, Lisp_Object acronym) ASCII face. */ face = FACE_FROM_ID (it->f, it->face_id)->ascii_face; font = face->font ? face->font : FRAME_FONT (it->f); - normal_char_ascent_descent (font, &it->ascent, &it->descent); + normal_char_ascent_descent (font, -1, &it->ascent, &it->descent); it->ascent += font->baseline_offset; it->descent -= font->baseline_offset; base_height = it->ascent + it->descent; -- 2.39.2