emacs-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: move_it_vertically_backward question


From: Po Lu
Subject: Re: move_it_vertically_backward question
Date: Tue, 14 Dec 2021 08:53:35 +0800
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/28.0.60 (gnu/linux)

Eli Zaretskii <eliz@gnu.org> writes:

> I'm not sure this is the way to go, judging by what you told on
> help-gnu-emacs.  The main reason is that window-text-pixel-size, which
> you said doesn't do what you want, uses exactly the same technique as
> you are trying to do in this new primitive, and so whatever problems
> you have with window-text-pixel-size, you will bump into them (or
> similar problems) with your new primitive as well.  This stuff is
> always extremely tricky when advanced display features are used, like
> display and overlay strings with embedded newlines, line-prefix, line
> numbers, etc.  There's no easy way around this complexity.

Yes, I understand that much.  This primitive is supposed to solve a
performance problem though: right now, we go through quite a few hoops
to find such a position and return its height, and I've been getting
complaints that the speed of that is unacceptable.

Since there seems to be no faster way to do what I'm trying to,
introducing a new primitive seems to be the way to go.

> Instead, we should understand better why window-text-pixel-size
> doesn't fit your bill, and then extend it so that it does what you
> want in your use cases.

While the performance of `window-text-pixel-size' itself is ample,
finding the target window start is not: we have to find the beginning of
the visual line, then (vertical-motion -1) in a loop calculating the
height with `window-text-pixel-size' until it reaches an appropriate
value.

> The commentary to the function doesn't tell the whole story.  In fact,
> it always undershoots first, because of this:
>
>   /* Estimate how many newlines we must move back.  */
>   nlines = max (1, dy / default_line_pixel_height (it->w));
>
> This is integer division, so it truncates the number of lines.  E.g.,
> in your case, with DY between 17 and 33 you get 1 line, not more.
> Then it moves back by that number of physical lines, which is why you
> get the line before window-start.
>
> And then it can move farther back, but only if the undershoot is
> "large enough":
>
>       /* If we did not reach target_y, try to move further backward if
>        we can.  If we moved too far backward, try to move forward.  */
>       if (target_y < it->current_y
>         /* This is heuristic.  In a window that's 3 lines high, with
>            a line height of 13 pixels each, recentering with point
>            on the bottom line will try to move -39/2 = 19 pixels
>            backward.  Try to avoid moving into the first line.  */
>         && (it->current_y - target_y
>             > min (window_box_height (it->w), line_height * 2 / 3))
>         && IT_CHARPOS (*it) > BEGV)
>       {
>         move_trace ("  not far enough -> move_vert %d\n",
>                     target_y - it->current_y);
>         dy = it->current_y - target_y;
>         goto move_further_back;
>       }

> That "2/3rd of line height" threshold heuristic is the reason why it
> not always moves one more line back.  On my system, the default pixel
> height of a line is 16, so it moves to the second line before
> window-start for DY >= 27, since 2/3rd of 16 is 10.

Hmm.  Is it legal to pass a negative Y argument to `move_it_to'?
Perhaps that can be used instead.

Thanks.


reply via email to

[Prev in Thread] Current Thread [Next in Thread]