/* Display generation from window structure and buffer text.
Copyright (C) 1985, 1986, 1987, 1988, 1993, 1994, 1995,
1997, 1998, 1999, 2000, 2001, 2002, 2003,
- 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+ 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
This file is part of GNU Emacs.
move_it_to (&it, charpos, -1, it.last_visible_y-1, -1,
(charpos >= 0 ? MOVE_TO_POS : 0) | MOVE_TO_Y);
- /* Note that we may overshoot because of invisible text. */
if (charpos >= 0 && IT_CHARPOS (it) >= charpos)
{
+ /* We have reached CHARPOS, or passed it. How the call to
+ move_it_to can overshoot: (i) If CHARPOS is on invisible
+ text, move_it_to stops at the end of the invisible text,
+ after CHARPOS. (ii) If CHARPOS is in a display vector,
+ move_it_to stops on its last glyph. */
int top_x = it.current_x;
int top_y = it.current_y;
+ enum it_method it_method = it.method;
+ /* Calling line_bottom_y may change it.method. */
int bottom_y = (last_height = 0, line_bottom_y (&it));
int window_top_y = WINDOW_HEADER_LINE_HEIGHT (w);
if (top_y < window_top_y)
visible_p = bottom_y > window_top_y;
else if (top_y < it.last_visible_y)
- visible_p = 1;
+ visible_p = 1;
if (visible_p)
{
- if (it.method == GET_FROM_BUFFER)
+ if (it_method == GET_FROM_BUFFER)
{
Lisp_Object window, prop;
struct glyph *end = glyph + row->used[TEXT_AREA];
int x = row->x;
- for (; glyph < end && glyph->charpos < charpos; glyph++)
+ for (; glyph < end
+ && (!BUFFERP (glyph->object)
+ || glyph->charpos < charpos);
+ glyph++)
x += glyph->pixel_width;
-
top_x = x;
}
}
+ else if (it_method == GET_FROM_DISPLAY_VECTOR)
+ {
+ /* We stopped on the last glyph of a display vector.
+ Try and recompute. Hack alert! */
+ if (charpos < 2 || top.charpos >= charpos)
+ top_x = it.glyph_row->x;
+ else
+ {
+ struct it it2;
+ start_display (&it2, w, top);
+ move_it_to (&it2, charpos - 1, -1, -1, -1, MOVE_TO_POS);
+ get_next_display_element (&it2);
+ PRODUCE_GLYPHS (&it2);
+ if (ITERATOR_AT_END_OF_LINE_P (&it2)
+ || it2.current_x > it2.last_visible_x)
+ top_x = it.glyph_row->x;
+ else
+ {
+ top_x = it2.current_x;
+ top_y = it2.current_y;
+ }
+ }
+ }
*x = top_x;
*y = max (top_y + max (0, it.max_ascent - it.ascent), window_top_y);
p->voffset = it->voffset;
p->string_from_display_prop_p = it->string_from_display_prop_p;
p->display_ellipsis_p = 0;
+ p->line_wrap = it->line_wrap;
++it->sp;
}
it->font_height = p->font_height;
it->voffset = p->voffset;
it->string_from_display_prop_p = p->string_from_display_prop_p;
+ it->line_wrap = p->line_wrap;
}
break;
}
else if (BUFFERP (it->object)
- && it->method == GET_FROM_BUFFER
+ && (it->method == GET_FROM_BUFFER
+ || it->method == GET_FROM_STRETCH)
&& IT_CHARPOS (*it) >= to_charpos)
skip = MOVE_POS_MATCH_OR_ZV;
else
if (display_line (&it))
last_text_row = it.glyph_row - 1;
- /* Give up If point isn't in a row displayed or reused. */
- if (w->cursor.vpos < 0)
- {
- clear_glyph_matrix (w->desired_matrix);
- return 0;
- }
-
/* If point is in a reused row, adjust y and vpos of the cursor
position. */
if (pt_row)
w->cursor.y -= first_reusable_row->y - start_row->y;
}
+ /* Give up if point isn't in a row displayed or reused. (This
+ also handles the case where w->cursor.vpos < nrows_scrolled
+ after the calls to display_line, which can happen with scroll
+ margins. See bug#1295.) */
+ if (w->cursor.vpos < 0)
+ {
+ clear_glyph_matrix (w->desired_matrix);
+ return 0;
+ }
+
/* Scroll the display. */
run.current_y = first_reusable_row->y;
run.desired_y = WINDOW_HEADER_LINE_HEIGHT (w);
if (row < bottom_row)
{
struct glyph *glyph = row->glyphs[TEXT_AREA] + w->cursor.hpos;
- while (glyph->charpos < PT)
+ struct glyph *end = glyph + row->used[TEXT_AREA];
+
+ for (; glyph < end
+ && (!BUFFERP (glyph->object)
+ || glyph->charpos < PT);
+ glyph++)
{
w->cursor.hpos++;
w->cursor.x += glyph->pixel_width;
- glyph++;
}
}
}
fprintf (stderr,
"[%d-%d]",
glyph->u.cmp.from, glyph->u.cmp.to);
- fprintf (stderr, " . %4d %1.1d%1.1d\n"
+ fprintf (stderr, " . %4d %1.1d%1.1d\n",
glyph->face_id,
glyph->left_box_line_p,
glyph->right_box_line_p);
prefix = Vline_prefix;
}
if (! NILP (prefix))
- push_display_prop (it, prefix);
+ {
+ push_display_prop (it, prefix);
+ /* If the prefix is wider than the window, and we try to wrap
+ it, it would acquire its own wrap prefix, and so on till the
+ iterator stack overflows. So, don't wrap the prefix. */
+ it->line_wrap = TRUNCATE;
+ }
}
\f
last = s->row->glyphs[s->area] + end;
s->cmp_id = glyph->u.cmp.id;
s->cmp_from = glyph->u.cmp.from;
- s->cmp_to = glyph->u.cmp.to;
+ s->cmp_to = glyph->u.cmp.to + 1;
s->face = FACE_FROM_ID (s->f, face_id);
lgstring = composition_gstring_from_id (s->cmp_id);
s->font = XFONT_OBJECT (LGSTRING_FONT (lgstring));
glyph++;
while (glyph < last
&& glyph->u.cmp.automatic
- && glyph->u.cmp.id == s->cmp_id)
- s->cmp_to = (glyph++)->u.cmp.to;
+ && glyph->u.cmp.id == s->cmp_id
+ && s->cmp_to == glyph->u.cmp.from)
+ s->cmp_to = (glyph++)->u.cmp.to + 1;
for (i = s->cmp_from; i < s->cmp_to; i++)
{
struct font_metrics metrics;
composition_gstring_width (gstring, glyph->u.cmp.from,
- glyph->u.cmp.to, &metrics);
+ glyph->u.cmp.to + 1, &metrics);
if (metrics.rbearing > metrics.width)
*right = metrics.rbearing;
if (metrics.lbearing < 0)
glyph->u.cmp.automatic = 1;
glyph->u.cmp.id = it->cmp_it.id;
glyph->u.cmp.from = it->cmp_it.from;
- glyph->u.cmp.to = it->cmp_it.to;
+ glyph->u.cmp.to = it->cmp_it.to - 1;
}
glyph->avoid_cursor_p = it->avoid_cursor_p;
glyph->multibyte_p = it->multibyte_p;
DEFVAR_LISP ("window-scroll-functions", &Vwindow_scroll_functions,
doc: /* List of functions to call before redisplaying a window with scrolling.
-Each function is called with two arguments, the window
-and its new display-start position. Note that the value of `window-end'
-is not valid when these functions are called. */);
+Each function is called with two arguments, the window and its new
+display-start position. Note that these functions are also called by
+`set-window-buffer'. Also note that the value of `window-end' is not
+valid when these functions are called. */);
Vwindow_scroll_functions = Qnil;
DEFVAR_LISP ("window-text-change-functions",