[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
bug#28936: move_it_in_display_line_to returns MOVE_POS_MATCH_OR_ZV befor
From: |
Keith David Bershatsky |
Subject: |
bug#28936: move_it_in_display_line_to returns MOVE_POS_MATCH_OR_ZV before ZV |
Date: |
Sat, 21 Oct 2017 20:02:58 -0700 |
A couple of observations:
1. `move_it_in_display_line' could use an additional comment at the outset to
let readers know that it is not compatible with moving to X in a horizontal
scrolling and/or truncate lines situation. The existing commentary that it was
intended for external use was insufficient to deter me, and it required a
learning curve on my part to better understand its limited potential use.
2. When IT is on the last line in the buffer containing a few or more
characters, `move_it_in_display_line_to' stops short of the target X and
erroneously returns MOVE_POS_MATCH_OR_ZV when used as follows. I have
display-line-numbers set to a non-nil value in the event that makes a
difference. There is nothing special in terms of text-properties or overlays
present in the buffer.
int target_x = [Some arbitrary X that is a few characters before ZV.];
move_it_in_display_line_to (it, ZV, target_x, MOVE_TO_POS | MOVE_TO_X);
The workaround is to compare the result of MOVE_POS_MATCH_OR_ZV with IT_CHARPOS
to ensure that we are really at a ZV situation.
Here is a working draft of what I am using for my crosshairs (#17684).
int
move_it_in_display_line_to_x (struct it *it, int target_x)
{
struct it saved_it;
void *saved_data = bidi_shelve_cache ();
enum move_it_result rc = MOVE_X_REACHED;
int new_x, prev_x;
/* Advance straight to `it->first_visible_x` if IT is prior thereto. */
if (it->current_x < it->first_visible_x)
move_it_in_display_line_to (it, ZV, it->first_visible_x, MOVE_TO_POS |
MOVE_TO_X);
while (it->current_x + it->pixel_width <= target_x)
{
SAVE_IT (saved_it, *it, saved_data);
new_x = it->current_x + it->pixel_width;
if (new_x == it->current_x)
new_x++;
rc = move_it_in_display_line_to (it, ZV, new_x, MOVE_TO_POS | MOVE_TO_X);
if (ITERATOR_AT_END_OF_LINE_P (it)
|| FETCH_BYTE (IT_BYTEPOS (it)) == '\n'
/* There is a bug in `move_it_in_display_line_to' such that it returns
MOVE_POS_MATCH_OR_ZV before reaching ZV when the latter is at the end
of the line: abcdefg[EOB]. The workaround is to add an extra check
using IT_CHARPOS and comparing it to ZV. */
|| (rc == MOVE_POS_MATCH_OR_ZV
&& IT_CHARPOS (*it) == ZV))
break;
}
/* When word-wrap is on, TO_X may lie past the end of a wrapped line.
Then it->current is the character on the next line, so backtrack to the
space before the wrap point. */
if (it->line_wrap == WORD_WRAP
&& rc == MOVE_LINE_CONTINUED)
{
prev_x = max (it->current_x - 1, 0);
RESTORE_IT (it, &saved_it, saved_data);
move_it_in_display_line_to (it, -1, prev_x, MOVE_TO_X);
}
bidi_unshelve_cache (saved_data, true);
return rc;
}
Thanks,
Keith
- bug#28936: move_it_in_display_line_to returns MOVE_POS_MATCH_OR_ZV before ZV,
Keith David Bershatsky <=
- bug#28936: move_it_in_display_line_to returns MOVE_POS_MATCH_OR_ZV before ZV, Keith David Bershatsky, 2017/10/22
- bug#28936: move_it_in_display_line_to returns MOVE_POS_MATCH_OR_ZV before ZV, Eli Zaretskii, 2017/10/22
- bug#28936: move_it_in_display_line_to returns MOVE_POS_MATCH_OR_ZV before ZV, Keith David Bershatsky, 2017/10/22
- bug#28936: nRe: bug#28936: move_it_in_display_line_to returns MOVE_POS_MATCH_OR_ZV before ZV, Keith David Bershatsky, 2017/10/22
- bug#28936: move_it_in_display_line_to returns MOVE_POS_MATCH_OR_ZV before ZV, Keith David Bershatsky, 2017/10/23