Subject: bug#5718: scroll-margin in buffer with small line count.

From: [email-masked]
Date: Sun, 22 Jan 2017 12:21:20 -0500

[email-masked] writes:
>
> I came up with this; it works

Actually, that doesn't work, I must have not compiled before testing.

Eli Zaretskii <[email-masked]> writes:
>> 
>> I'm not entirely clear why there is a branch in that code.
>
> Because of line-spacing, perhaps?  Did you test your code when
> line-spacing is at non-default value?  In general, it is safer to go
> to the next screen line than reason about where it will start.
>
>> +int
>> +partial_line_height (const struct it *it_origin)
>> +{
>> +  struct it it = *it_origin;
>
> When you copy the iterator structure and modify the copy, you need to
> save and restore the bidi cache, using SAVE_IT and RESTORE_IT macros.
> Otherwise, the code which calls this function will work incorrectly if
> it uses the original iterator after the call, because the bidi cache
> is not restored to its state before the call.

I came up with this modified version of partial_line_height, which does
actually work.  Having to do RESTORE_IT (&it, &it, it_data) is a bit
unintuitive though.  I don't understand what the typical use case of
this macro is, if it's going to copy back the new state into the
original `it', then why use a separate `it' in the first place?

By the way, while testing I noticed that `set-window-text-height'
doesn't take `line-spacing' into account, should it?

int
partial_line_height (struct it *it_origin)
{
  int partial_height;
  void *it_data = NULL;
  struct it it;
  SAVE_IT (it, *it_origin, it_data);
  move_it_to (&it, ZV, -1, it.last_visible_y, -1,
              MOVE_TO_POS | MOVE_TO_Y);
  if (it.what == IT_EOB)
    {
      int vis_height = it.last_visible_y - it.current_y;
      int height = it.ascent + it.descent;
      partial_height = (vis_height < height) ? vis_height : 0;
    }
  else
    {
      int last_line_y = it.current_y;
      move_it_by_lines (&it, 1);
      partial_height = (it.current_y > it.last_visible_y)
        ? it.last_visible_y - last_line_y : 0;
    }
  RESTORE_IT (&it, &it, it_data);
  return partial_height;
}