Lisp_Object cpos = make_number (charpos);
Lisp_Object spec = Fget_char_property (cpos, Qdisplay, Qnil);
Lisp_Object string = string_from_display_spec (spec);
- int newline_in_string = 0;
-
- if (STRINGP (string))
- {
- const char *s = SSDATA (string);
- const char *e = s + SBYTES (string);
- while (s < e)
- {
- if (*s++ == '\n')
- {
- newline_in_string = 1;
- break;
- }
- }
- }
+ bool newline_in_string
+ = (STRINGP (string)
+ && memchr (SDATA (string), '\n', SBYTES (string)));
/* The tricky code below is needed because there's a
discrepancy between move_it_to and how we set cursor
when the display line ends in a newline from a
struct it it2, it3;
void *it2data = NULL, *it3data = NULL;
ptrdiff_t start_pos;
+ int nchars_per_row
+ = (it->last_visible_x - it->first_visible_x) / FRAME_COLUMN_WIDTH (it->f);
+ ptrdiff_t pos_limit;
move_further_back:
eassert (dy >= 0);
/* Estimate how many newlines we must move back. */
nlines = max (1, dy / FRAME_LINE_HEIGHT (it->f));
+ if (it->line_wrap == TRUNCATE)
+ pos_limit = BEGV;
+ else
+ pos_limit = max (start_pos - nlines * nchars_per_row, BEGV);
- /* Set the iterator's position that many lines back. */
- while (nlines-- && IT_CHARPOS (*it) > BEGV)
+ /* Set the iterator's position that many lines back. But don't go
+ back more than NLINES full screen lines -- this wins a day with
+ buffers which have very long lines. */
+ while (nlines-- && IT_CHARPOS (*it) > pos_limit)
back_to_previous_visible_line_start (it);
/* Reseat the iterator here. When moving backward, we don't want
struct it it2;
void *it2data = NULL;
ptrdiff_t start_charpos, i;
+ int nchars_per_row
+ = (it->last_visible_x - it->first_visible_x) / FRAME_COLUMN_WIDTH (it->f);
+ ptrdiff_t pos_limit;
/* Start at the beginning of the screen line containing IT's
position. This may actually move vertically backwards,
move_it_vertically_backward (it, 0);
dvpos -= it->vpos;
- /* Go back -DVPOS visible lines and reseat the iterator there. */
+ /* Go back -DVPOS buffer lines, but no farther than -DVPOS full
+ screen lines, and reseat the iterator there. */
start_charpos = IT_CHARPOS (*it);
- for (i = -dvpos; i > 0 && IT_CHARPOS (*it) > BEGV; --i)
+ if (it->line_wrap == TRUNCATE)
+ pos_limit = BEGV;
+ else
+ pos_limit = max (start_charpos + dvpos * nchars_per_row, BEGV);
+ for (i = -dvpos; i > 0 && IT_CHARPOS (*it) > pos_limit; --i)
back_to_previous_visible_line_start (it);
reseat (it, it->current.pos, 1);
bset_undo_list (current_buffer, Qt);
oldpoint = message_dolog_marker1;
- set_marker_restricted (oldpoint, make_number (PT), Qnil);
+ set_marker_restricted_both (oldpoint, Qnil, PT, PT_BYTE);
oldbegv = message_dolog_marker2;
- set_marker_restricted (oldbegv, make_number (BEGV), Qnil);
+ set_marker_restricted_both (oldbegv, Qnil, BEGV, BEGV_BYTE);
oldzv = message_dolog_marker3;
- set_marker_restricted (oldzv, make_number (ZV), Qnil);
+ set_marker_restricted_both (oldzv, Qnil, ZV, ZV_BYTE);
GCPRO1 (old_deactivate_mark);
if (PT == Z)
++clear_image_cache_count;
#endif
- w->region_showing = XINT (Fmarker_position (BVAR (XBUFFER (w->buffer), mark)));
-
/* Build desired matrices, and update the display. If
consider_all_windows_p is non-zero, do it for all windows on all
frames. Otherwise do it for selected_window, only. */
else
{
struct text_pos scroll_margin_pos = startp;
+ int y_offset = 0;
/* See if point is inside the scroll margin at the top of the
window. */
if (this_scroll_margin)
{
+ int y_start;
+
start_display (&it, w, startp);
+ y_start = it.current_y;
move_it_vertically (&it, this_scroll_margin);
scroll_margin_pos = it.current.pos;
+ /* If we didn't move enough before hitting ZV, request
+ additional amount of scroll, to move point out of the
+ scroll margin. */
+ if (IT_CHARPOS (it) == ZV
+ && it.current_y - y_start < this_scroll_margin)
+ y_offset = this_scroll_margin - (it.current_y - y_start);
}
if (PT < CHARPOS (scroll_margin_pos))
|| IT_CHARPOS (it) < CHARPOS (scroll_margin_pos))
return SCROLLING_FAILED;
+ /* Additional scroll for when ZV was too close to point. */
+ dy += y_offset;
+
/* Compute new window start. */
start_display (&it, w, startp);
SET_TEXT_POS (start_pos, ZV, ZV_BYTE);
/* Find the start of the continued line. This should be fast
- because scan_buffer is fast (newline cache). */
+ because find_newline is fast (newline cache). */
row = w->desired_matrix->rows + (WINDOW_WANTS_HEADER_LINE_P (w) ? 1 : 0);
init_iterator (&it, w, CHARPOS (start_pos), BYTEPOS (start_pos),
row, DEFAULT_FACE_ID);
}
/* Is IT->w showing the region? */
- it->w->region_showing = it->region_beg_charpos > 0 ? -1 : 0;
+ it->w->region_showing = it->region_beg_charpos > 0 ? it->region_beg_charpos : 0;
/* Clear the result glyph row and enable it. */
prepare_desired_row (row);
ceiling = min (limit_byte - 1, ceiling);
ceiling_addr = BYTE_POS_ADDR (ceiling) + 1;
base = (cursor = BYTE_POS_ADDR (start_byte));
- while (1)
+
+ do
{
if (selective_display)
- while (*cursor != '\n' && *cursor != 015 && ++cursor != ceiling_addr)
- ;
+ {
+ while (*cursor != '\n' && *cursor != 015
+ && ++cursor != ceiling_addr)
+ continue;
+ if (cursor == ceiling_addr)
+ break;
+ }
else
- while (*cursor != '\n' && ++cursor != ceiling_addr)
- ;
+ {
+ cursor = memchr (cursor, '\n', ceiling_addr - cursor);
+ if (! cursor)
+ break;
+ }
+
+ cursor++;
- if (cursor != ceiling_addr)
+ if (--count == 0)
{
- if (--count == 0)
- {
- start_byte += cursor - base + 1;
- *byte_pos_ptr = start_byte;
- return orig_count;
- }
- else
- if (++cursor == ceiling_addr)
- break;
+ start_byte += cursor - base;
+ *byte_pos_ptr = start_byte;
+ return orig_count;
}
- else
- break;
}
- start_byte += cursor - base;
+ while (cursor < ceiling_addr);
+
+ start_byte += ceiling_addr - base;
}
}
else
{
ceiling = BUFFER_FLOOR_OF (start_byte - 1);
ceiling = max (limit_byte, ceiling);
- ceiling_addr = BYTE_POS_ADDR (ceiling) - 1;
+ ceiling_addr = BYTE_POS_ADDR (ceiling);
base = (cursor = BYTE_POS_ADDR (start_byte - 1) + 1);
while (1)
{
if (selective_display)
- while (--cursor != ceiling_addr
- && *cursor != '\n' && *cursor != 015)
- ;
+ {
+ while (--cursor >= ceiling_addr
+ && *cursor != '\n' && *cursor != 015)
+ continue;
+ if (cursor < ceiling_addr)
+ break;
+ }
else
- while (--cursor != ceiling_addr && *cursor != '\n')
- ;
+ {
+ cursor = memrchr (ceiling_addr, '\n', cursor - ceiling_addr);
+ if (! cursor)
+ break;
+ }
- if (cursor != ceiling_addr)
+ if (++count == 0)
{
- if (++count == 0)
- {
- start_byte += cursor - base + 1;
- *byte_pos_ptr = start_byte;
- /* When scanning backwards, we should
- not count the newline posterior to which we stop. */
- return - orig_count - 1;
- }
+ start_byte += cursor - base + 1;
+ *byte_pos_ptr = start_byte;
+ /* When scanning backwards, we should
+ not count the newline posterior to which we stop. */
+ return - orig_count - 1;
}
- else
- break;
}
- /* Here we add 1 to compensate for the last decrement
- of CURSOR, which took it past the valid range. */
- start_byte += cursor - base + 1;
+ start_byte += ceiling_addr - base;
}
}