Subject: bug#21835: 25.0.50; cursor height wrong when line-spacing is used

From: Eli Zaretskii <[email-masked]>
Date: Mon, 21 Mar 2016 17:58:45 +0200

> From: Nick Helm <[email-masked]>
> Date: Mon, 21 Mar 2016 17:03:42 +1300
> 
> Could the EOL cursor-height be set to the height of the tallest glyph in the 
> line?

I don't think your problem is the height of the cursor.  I think your
problem is the vertical position of the lower edge of the cursor
block.  You should keep in mind that a glyph can (and normally does)
rise above the base line of the display line, but it can also descent
below that base line.  So the height alone does not determine the
cursor appearance, unless you also specify the vertical position of
its lower edge.

But to answer your question: we already do that, in a way.  The
display engine records the maximum vertical dimensions of the glyphs
in a display line as it lays out each line.  The EOL cursor simply
uses these maximum values, both the max ascent value and the max
descent value; the latter includes the line spacing.

> In Emacs 24, my understanding is that cursor-height = line-height, where
> line-height was determined by adding the height of the tallest glyph in the line
> to the top and bottom vertical spacing.

No, Emacs 24 didn't use the height of the tallest glyph.  It didn't
even track the height of individual glyphs.  Instead, it used a single
global value of height specified by the font.  Some fonts specify very
large value there, so this was changed to provide a better display.  I
explained this up-thread, see

  http://debbugs.gnu.org/cgi/bugreport.cgi?bug=21835#8

> Alternatively, how about setting the EOL cursor-height to the same height as the
> last *displayable* glyph in the line, but with a lower size boundary?

Tried that, it gave much worse results when the last glyph is very
small -- a surprisingly frequent situation, because some fonts have
their SPC glyph specify a small height.  Limitation from below doesn't
work because there are display features, such as the 'line-height'
property, that become broken by such limitations.

And then there are empty lines, of course.

> If there are
> no displayable glyphs in the line or the line is empty, could the height of the
> closest previous displayable glyph be used, even if it's on an earlier line? If
> the buffer is empty or contains no displayable glyphs, use (default line-height 
> -
> line-spacing).

This would slow down redisplay in many important cases, because
redisplay optimizations frequently cause Emacs to lay out a single
display line.  What you suggest would require searching for the last
non-empty line followed by costly layout of that line (to determine
its height) even though that line doesn't need to be redrawn at all.

The case of the empty line is actually one of the main reasons for the
current behavior: we want the cursor on an empty line look the same as
the EOL cursor on a non-empty line, and we want to do that without
examining the glyphs of any other display lines.

The other gotcha is to make sure the hollow cursor, drawn by default
in non-selected windows, will have the same dimensions as the block
cursor on the same character, otherwise switching to a different
window will have unpleasant effect.  These two cursors are drawn using
2 very different methods, so there be dragons.

Anyway, you (or anyone else) are welcome to try different ideas for
making the display of EOL cursor better, the relevant function is
append_space_for_newline in xdisp.c.  Just make sure you cover all the
use cases uncovered by the various bugs referenced in the commits that
changed the code of this function in the past ("git log -L" will show
them).

> If none of that's possible or causes more grief than it's worth, how about also
> letting the user arbitrarily set the cursor height?

I think you can do that already by customizing cursor-type to
'(hbar . N)' where N is some suitable number that produces the cursor
you like.