#define min(a, b) ((a) < (b) ? (a) : (b))
#define max(a, b) ((a) > (b) ? (a) : (b))
+#define minmax(floor, val, ceil) \
+ ((val) < (floor) ? (floor) : (val) > (ceil) ? (ceil) : (val))
/* The buffer position of the first character appearing
entirely or partially on the current frame line.
/* Nonzero if overlay arrow has been displayed once in this window. */
static int overlay_arrow_seen;
+/* Nonzero if visible end of buffer has already been displayed once
+ in this window. (We need this variable in case there are overlay
+ strings that get displayed there.) */
+static int zv_strings_seen;
+
/* Nonzero means highlight the region even in nonselected windows. */
static int highlight_nonselected_windows;
{
cursor_vpos = -1;
overlay_arrow_seen = 0;
+ zv_strings_seen = 0;
display_text_line (w, tlbufpos, this_line_vpos, this_line_start_hpos,
pos_tab_offset (w, tlbufpos));
/* If line contains point, is not continued,
{
pos = *compute_motion (tlbufpos, 0,
XINT (w->hscroll) ? 1 - XINT (w->hscroll) : 0,
+ 0,
PT, 2, - (1 << (SHORTBITS - 1)),
window_internal_width (w) - 1,
XINT (w->hscroll),
pos_tab_offset (w, tlbufpos), w);
if (pos.vpos < 1)
{
+ int width = window_internal_width (w) - 1;
FRAME_CURSOR_X (selected_frame)
- = XFASTINT (w->left) + max (pos.hpos, 0);
+ = XFASTINT (w->left) + minmax (0, pos.hpos, width);
FRAME_CURSOR_Y (selected_frame) = this_line_vpos;
goto update;
}
{
/* If point does not appear, move point so it does appear */
pos = *compute_motion (startp, 0,
- ((EQ (window, minibuf_window) && startp == 1)
- ? minibuf_prompt_width : 0)
- +
- (hscroll ? 1 - hscroll : 0),
- ZV, height / 2,
- - (1 << (SHORTBITS - 1)),
- width, hscroll, pos_tab_offset (w, startp), w);
+ (((EQ (window, minibuf_window)
+ && startp == BEG)
+ ? minibuf_prompt_width : 0)
+ + (hscroll ? 1 - hscroll : 0)),
+ 0,
+ ZV, height / 2,
+ - (1 << (SHORTBITS - 1)),
+ width, hscroll, pos_tab_offset (w, startp), w);
BUF_PT (current_buffer) = pos.bufpos;
if (w != XWINDOW (selected_window))
Fset_marker (w->pointm, make_number (PT), Qnil);
{
if (current_buffer == old)
lpoint = PT;
- FRAME_CURSOR_X (f) = max (0, pos.hpos) + XFASTINT (w->left);
+ FRAME_CURSOR_X (f) = (XFASTINT (w->left)
+ + minmax (0, pos.hpos, width));
FRAME_CURSOR_Y (f) = pos.vpos + XFASTINT (w->top);
}
/* If we are highlighting the region,
&& XFASTINT (w->window_end_vpos) < XFASTINT (w->height)
&& !EQ (window, minibuf_window))
{
- pos = *compute_motion (startp, 0, (hscroll ? 1 - hscroll : 0),
+ pos = *compute_motion (startp, 0, (hscroll ? 1 - hscroll : 0), 0,
PT, height, 0, width, hscroll,
pos_tab_offset (w, startp), w);
if (w == XWINDOW (FRAME_SELECTED_WINDOW (f)))
{
/* These variables are supposed to be origin 1 */
- FRAME_CURSOR_X (f) = max (0, pos.hpos) + XFASTINT (w->left);
+ FRAME_CURSOR_X (f) = (XFASTINT (w->left)
+ + minmax (0, pos.hpos, width));
FRAME_CURSOR_Y (f) = pos.vpos + XFASTINT (w->top);
}
/* This doesn't do the trick, because if a window to the right of
{
if (PT > startp)
{
- pos = *vmotion (Z - XFASTINT (w->window_end_pos),
- scroll_step, width, hscroll, window);
+ pos = *vmotion (Z - XFASTINT (w->window_end_pos), scroll_step, w);
if (pos.vpos >= height)
goto scroll_fail;
}
- pos = *vmotion (startp,
- (PT < startp ? - scroll_step : scroll_step),
- width, hscroll, window);
+ pos = *vmotion (startp, (PT < startp ? - scroll_step : scroll_step), w);
if (PT >= pos.bufpos)
{
/* Forget any previously recorded base line for line number display. */
w->base_line_number = Qnil;
- pos = *vmotion (PT, - (height / 2), width, hscroll, window);
+ pos = *vmotion (PT, - (height / 2), w);
try_window (window, pos.bufpos);
startp = marker_position (w->start);
- w->start_at_line_beg
+ w->start_at_line_beg
= (startp == BEGV || FETCH_CHAR (startp - 1) == '\n') ? Qt : Qnil;
done:
Fset_marker (w->start, make_number (pos), Qnil);
cursor_vpos = -1;
overlay_arrow_seen = 0;
+ zv_strings_seen = 0;
val.hpos = XINT (w->hscroll) ? 1 - XINT (w->hscroll) : 0;
while (--height >= 0)
int width = window_internal_width (w) - 1;
int hscroll = XINT (w->hscroll);
int lmargin = hscroll > 0 ? 1 - hscroll : 0;
+ int did_motion;
register int vpos;
register int i, tem;
int last_text_vpos = 0;
return 0; /* Give up if changes go above top of window */
/* Find position before which nothing is changed. */
- bp = *compute_motion (start, 0, lmargin,
+ bp = *compute_motion (start, 0, lmargin, 0,
min (ZV, beg_unchanged + BEG), height, 0,
width, hscroll, pos_tab_offset (w, start), w);
if (bp.vpos >= height)
We don't need to change the frame at all.
But we need to update window_end_pos to account for
any change in buffer size. */
- bp = *compute_motion (start, 0, lmargin,
+ bp = *compute_motion (start, 0, lmargin, 0,
Z, height, 0,
width, hscroll, pos_tab_offset (w, start), w);
XSETFASTINT (w->window_end_vpos, height);
vpos = bp.vpos;
/* Find beginning of that frame line. Must display from there. */
- bp = *vmotion (bp.bufpos, 0, width, hscroll, window);
+ bp = *vmotion (bp.bufpos, 0, w);
pos = bp.bufpos;
val.hpos = lmargin;
if (pos < start)
return -1;
+ did_motion = 0;
/* If about to start displaying at the beginning of a continuation line,
really start with previous frame line, in case it was not
continued when last redisplayed */
/* Likewise if we have to worry about selective display. */
(selective > 0 && bp.bufpos - 1 == beg_unchanged && vpos > 0))
{
- bp = *vmotion (bp.bufpos, -1, width, hscroll, window);
+ bp = *vmotion (bp.bufpos, -1, w);
--vpos;
pos = bp.bufpos;
}
if (bp.contin && bp.hpos != lmargin)
{
val.hpos = bp.prevhpos - width + lmargin;
+ did_motion = 1;
pos--;
}
tem = find_next_newline (tem, 1);
/* Compute the cursor position after that newline. */
- ep = *compute_motion (pos, vpos, val.hpos, tem,
+ ep = *compute_motion (pos, vpos, val.hpos, did_motion, tem,
height, - (1 << (SHORTBITS - 1)),
width, hscroll, pos_tab_offset (w, bp.bufpos), w);
cursor_vpos = -1;
overlay_arrow_seen = 0;
+ zv_strings_seen = 0;
/* If changes do not reach to bottom of window,
figure out how much to scroll the rest of the window */
{
/* Now determine how far up or down the rest of the window has moved */
epto = pos_tab_offset (w, ep.bufpos);
- xp = *compute_motion (ep.bufpos, ep.vpos, ep.hpos,
+ xp = *compute_motion (ep.bufpos, ep.vpos, ep.hpos, 1,
Z - XFASTINT (w->window_end_pos),
10000, 0, width, hscroll, epto, w);
scroll_amount = xp.vpos - XFASTINT (w->window_end_vpos);
{
if (PT <= xp.bufpos)
{
- pp = *compute_motion (ep.bufpos, ep.vpos, ep.hpos,
+ pp = *compute_motion (ep.bufpos, ep.vpos, ep.hpos, 1,
PT, height, - (1 << (SHORTBITS - 1)),
width, hscroll, epto, w);
}
else
{
- pp = *compute_motion (xp.bufpos, xp.vpos, xp.hpos,
+ pp = *compute_motion (xp.bufpos, xp.vpos, xp.hpos, 1,
PT, height, - (1 << (SHORTBITS - 1)),
width, hscroll,
pos_tab_offset (w, xp.bufpos), w);
if (pp.bufpos < PT || pp.vpos == height)
return 0;
cursor_vpos = pp.vpos + top;
- cursor_hpos = pp.hpos + XFASTINT (w->left);
+ cursor_hpos = XFASTINT (w->left) + minmax (0, pp.hpos, width);
}
if (stop_vpos - scroll_amount >= height
|| (delta > 0 && xp.bufpos <= ZV)
|| (delta == 0 && xp.hpos))
{
- val = *vmotion (Z - XFASTINT (w->window_end_pos),
- delta, width, hscroll, window);
+ val = *vmotion (Z - XFASTINT (w->window_end_pos), delta, w);
XSETFASTINT (w->window_end_pos, Z - val.bufpos);
XSETFASTINT (w->window_end_vpos,
XFASTINT (w->window_end_vpos) + val.vpos);
if (cursor_vpos < 0)
{
findpoint:
- val = *compute_motion (start, 0, lmargin, PT, 10000, 10000,
+ val = *compute_motion (start, 0, lmargin, 0, PT, 10000, 10000,
width, hscroll, pos_tab_offset (w, start), w);
/* Admit failure if point is off frame now */
if (val.vpos >= height)
return 0;
}
cursor_vpos = val.vpos + top;
- cursor_hpos = val.hpos + XFASTINT (w->left);
+ cursor_hpos = XFASTINT (w->left) + minmax (0, val.hpos, width);
}
- FRAME_CURSOR_X (f) = max (0, cursor_hpos);
+ FRAME_CURSOR_X (f) = cursor_hpos;
FRAME_CURSOR_Y (f) = cursor_vpos;
if (debug_end_pos)
{
- val = *compute_motion (start, 0, lmargin, ZV,
+ val = *compute_motion (start, 0, lmargin, 0, ZV,
height, - (1 << (SHORTBITS - 1)),
width, hscroll, pos_tab_offset (w, start), w);
if (val.vpos != XFASTINT (w->window_end_vpos))
register int pos = start;
register int c;
register GLYPH *p1;
- int end;
register int pause;
register unsigned char *p;
GLYPH *endp;
register GLYPH *leftmargin;
- register GLYPH *p1prev = 0;
+ register GLYPH *p1prev;
register GLYPH *p1start;
+ int prevpos;
int *charstart;
FRAME_PTR f = XFRAME (w->frame);
int tab_width = XINT (current_buffer->tab_width);
to overlays or text property changes. */
int next_face_change;
-#ifdef USE_TEXT_PROPERTIES
- /* The next location where the `invisible' property changes */
- int next_invisible;
-#endif
-
+ /* The next location where the `invisible' property changes, or an
+ overlay starts or ends. */
+ int next_boundary;
+
/* The face we're currently using. */
int current_face = 0;
int i;
region_beg = region_end = -1;
if (MINI_WINDOW_P (w)
- && start == 1
+ && start == BEG
&& vpos == XFASTINT (w->top))
{
if (! NILP (minibuf_prompt))
minibuf_prompt_width = 0;
}
- end = ZV;
-
/* If we're hscrolled at all, use compute_motion to skip over any
text off the left edge of the window. compute_motion may know
tricks to do this faster than we can. */
if (hpos < 0)
{
struct position *left_edge
- = compute_motion (pos, vpos, hpos,
- end, vpos, 0,
+ = compute_motion (pos, vpos, hpos, 0,
+ ZV, vpos, 0,
width, hscroll, taboffset, w);
/* Retrieve the buffer position and column provided by
or at face change. */
pause = pos;
next_face_change = pos;
-#ifdef USE_TEXT_PROPERTIES
- next_invisible = pos;
-#endif
+ next_boundary = pos;
+ p1prev = p1;
+ prevpos = pos;
while (1)
{
- /* Record which glyph starts a character,
- and the character position of that character. */
- if (p1 >= leftmargin)
- charstart[p1 - p1start] = pos;
-
- if (p1 >= endp)
- break;
-
- p1prev = p1;
if (pos >= pause)
{
- /* Did we hit the end of the visible region of the buffer?
- Stop here. */
- if (pos >= end)
- break;
-
- /* Did we reach point? Record the cursor location. */
- if (pos == PT && cursor_vpos < 0)
+ while (pos == next_boundary)
{
- cursor_vpos = vpos;
- cursor_hpos = p1 - leftmargin;
- }
+ Lisp_Object position, limit, prop, ww;
+
+ /* Display the overlay strings here, unless we're at ZV
+ and have already displayed the appropriate strings
+ on an earlier line. */
+ if (pos < ZV || !zv_strings_seen++)
+ {
+ int ovlen;
+ char *ovstr;
+ ovlen = overlay_strings (pos, w, &ovstr);
+ for (; ovlen; ovlen--, ovstr++)
+ {
+ if (p1 >= leftmargin && p1 < endp)
+ *p1 = MAKE_GLYPH (f, *ovstr, current_face);
+ p1++;
+ }
+ }
+
+ /* Did we reach point? Record the cursor location. */
+ if (pos == PT && cursor_vpos < 0)
+ {
+ cursor_vpos = vpos;
+ cursor_hpos = p1 - leftmargin;
+ }
+
+ if (pos >= ZV)
+ break;
-#ifdef USE_TEXT_PROPERTIES
- /* if the `invisible' property is set to t, we can skip to
- the next property change */
- while (pos == next_invisible && pos < end)
- {
- Lisp_Object position, limit, endpos, prop, ww;
XSETFASTINT (position, pos);
- XSETWINDOW (ww, w);
- prop = Fget_char_property (position, Qinvisible, ww);
+ limit = Fnext_overlay_change (position);
+#ifdef USE_TEXT_PROPERTIES
/* This is just an estimate to give reasonable
performance; nothing should go wrong if it is too small. */
- limit = Fnext_overlay_change (position);
if (XFASTINT (limit) > pos + 50)
XSETFASTINT (limit, pos + 50);
- endpos = Fnext_single_property_change (position, Qinvisible,
- Fcurrent_buffer (),
- limit);
- if (INTEGERP (endpos))
- next_invisible = XINT (endpos);
- else
- next_invisible = end;
+ limit = Fnext_single_property_change (position, Qinvisible,
+ Fcurrent_buffer (), limit);
+#endif
+ next_boundary = XFASTINT (limit);
+ /* if the `invisible' property is set, we can skip to
+ the next property change. */
+ XSETWINDOW (ww, w);
+ prop = Fget_char_property (position, Qinvisible, ww);
if (TEXT_PROP_MEANS_INVISIBLE (prop))
{
- if (pos < PT && next_invisible >= PT)
+ if (pos < PT && next_boundary >= PT)
{
cursor_vpos = vpos;
cursor_hpos = p1 - leftmargin;
}
- pos = next_invisible;
+ pos = next_boundary;
last_invis_skip = pos;
last_invis_prop = prop;
}
}
- if (pos >= end)
+
+ /* Did we reach point? Record the cursor location. */
+ if (pos == PT && cursor_vpos < 0)
+ {
+ cursor_vpos = vpos;
+ cursor_hpos = p1 - leftmargin;
+ }
+
+ /* Did we hit the end of the visible region of the buffer?
+ Stop here. */
+ if (pos >= ZV)
break;
-#endif
#ifdef HAVE_FACES
/* Did we hit a face change? Figure out what face we should
&next_face_change, pos + 50, 0);
#endif
- pause = end;
+ pause = ZV;
-#ifdef USE_TEXT_PROPERTIES
- if (pos < next_invisible && next_invisible < pause)
- pause = next_invisible;
-#endif
+ if (pos < next_boundary && next_boundary < pause)
+ pause = next_boundary;
if (pos < next_face_change && next_face_change < pause)
pause = next_face_change;
p = &FETCH_CHAR (pos);
}
+
+ if (p1 >= endp)
+ break;
+
+ p1prev = p1;
+
c = *p++;
/* Let a display table override all standard display methods. */
if (dp != 0 && VECTORP (DISP_CHAR_VECTOR (dp, c)))
if (last_invis_skip == pos
&& TEXT_PROP_MEANS_INVISIBLE_WITH_ELLIPSIS (last_invis_prop))
invis = 1;
- while (pos + 1 < end
+ while (pos + 1 < ZV
&& selective > 0
&& indented_beyond_p (pos + 1, selective))
{
*p1++ = FAST_MAKE_GLYPH (' ', current_face);
}
#endif
+
+ /* Update charstarts for the newline that ended this line. */
+ /* Do nothing here for a char that's entirely off the left edge
+ or if it starts at the right edge. */
+ if (p1 >= leftmargin && p1prev != endp)
+ {
+ /* Store the newline's position into charstarts
+ for the column where the newline starts.
+ Store -1 for the rest of the glyphs it occupies. */
+ int *p2x = &charstart[(p1prev < leftmargin
+ ? leftmargin : p1prev)
+ - p1start];
+ int *p2 = &charstart[(p1 < endp ? p1 : endp) - p1start];
+
+ *p2x++ = pos;
+ while (p2x < p2)
+ *p2x++ = -1;
+ }
+
break;
}
else if (c == '\t')
*p1++ = FAST_MAKE_GLYPH (' ', current_face);
}
#endif
+
+ /* Update charstarts for the ^M that ended this line. */
+ /* Do nothing here for a char that's entirely off the left edge
+ or if it starts at the right edge. */
+ if (p1 >= leftmargin && p1prev != endp)
+ {
+ /* Store the newline's position into charstarts
+ for the column where the newline starts.
+ Store -1 for the rest of the glyphs it occupies. */
+ int *p2x = &charstart[(p1prev < leftmargin
+ ? leftmargin : p1prev)
+ - p1start];
+ int *p2 = &charstart[(p1 < endp ? p1 : endp) - p1start];
+
+ *p2x++ = pos;
+ while (p2x < p2)
+ *p2x++ = -1;
+ }
break;
}
else if (c < 0200 && ctl_arrow)
p1++;
}
+ prevpos = pos;
+ pos++;
+
+ /* Update charstarts for the character just output. */
+
/* Do nothing here for a char that's entirely off the left edge. */
if (p1 >= leftmargin)
{
- /* For all the glyphs occupied by this character, except for the
- first, store -1 in charstarts. */
+ /* Store the char's position into charstarts
+ for the first glyph occupied by this char.
+ Store -1 for the rest of the glyphs it occupies. */
if (p1 != p1prev)
{
- int *p2x = &charstart[p1prev - p1start];
+ int *p2x = &charstart[(p1prev < leftmargin
+ ? leftmargin : p1prev)
+ - p1start];
int *p2 = &charstart[(p1 < endp ? p1 : endp) - p1start];
- /* The window's left column should always
- contain a character position.
- And don't clobber anything to the left of that. */
- if (p1prev < leftmargin)
- {
- p2x = charstart + (leftmargin - p1start);
- *p2x = pos;
- }
-
- /* This loop skips over the char p2x initially points to. */
- while (++p2x < p2)
- *p2x = -1;
+ if (p2x < p2)
+ *p2x++ = prevpos;
+ while (p2x < p2)
+ *p2x++ = -1;
}
}
-
- pos++;
}
val.hpos = - XINT (w->hscroll);