Commit 57b3e30b authored by Eli Zaretskii's avatar Eli Zaretskii

Empty the bidi cache "stack" when it->sp is zeroed.

Solves crashes due to overflow of bidi cache stack.
Make sure cache is saved and restored around all temporary iterations.

 src/dispnew.c (buffer_posn_from_coords): Save and restore the bidi
 cache around display iteration.
 src/window.c (Fwindow_end, window_scroll_pixel_based)
 (displayed_window_lines, Frecenter): Save and restore the bidi
 cache around display iteration.
 src/bidi.c (bidi_unshelve_cache): Ensure we have enough space before
 restoring the shelved cache.
 (bidi_cache_ensure_space): Don't assume the required size is just
 one BIDI_CACHE_CHUNK away.
 src/xdisp.c (back_to_previous_visible_line_start, reseat_1)
 (init_iterator): Empty the bidi cache "stack".
parent ed94e6d7
2011-07-05 Eli Zaretskii <eliz@gnu.org>
* dispnew.c (buffer_posn_from_coords): Save and restore the bidi
cache around display iteration.
* window.c (Fwindow_end, window_scroll_pixel_based)
(displayed_window_lines, Frecenter): Save and restore the bidi
cache around display iteration.
* bidi.c (bidi_unshelve_cache): Ensure we have enough space before
restoring the shelved cache.
(bidi_cache_ensure_space): Don't assume the required size is just
one BIDI_CACHE_CHUNK away.
* xdisp.c (back_to_previous_visible_line_start, reseat_1)
(init_iterator): Empty the bidi cache "stack".
2011-07-03 Eli Zaretskii <eliz@gnu.org> 2011-07-03 Eli Zaretskii <eliz@gnu.org>
* bidi.c (bidi_shelve_cache, bidi_unshelve_cache): New functions. * bidi.c (bidi_shelve_cache, bidi_unshelve_cache): New functions.
......
...@@ -458,7 +458,8 @@ bidi_cache_ensure_space (int idx) ...@@ -458,7 +458,8 @@ bidi_cache_ensure_space (int idx)
/* Enlarge the cache as needed. */ /* Enlarge the cache as needed. */
if (idx >= bidi_cache_size) if (idx >= bidi_cache_size)
{ {
bidi_cache_size += BIDI_CACHE_CHUNK; while (idx >= bidi_cache_size)
bidi_cache_size += BIDI_CACHE_CHUNK;
bidi_cache = bidi_cache =
(struct bidi_it *) xrealloc (bidi_cache, bidi_cache_size * elsz); (struct bidi_it *) xrealloc (bidi_cache, bidi_cache_size * elsz);
} }
...@@ -656,6 +657,7 @@ bidi_unshelve_cache (void *databuf) ...@@ -656,6 +657,7 @@ bidi_unshelve_cache (void *databuf)
else else
{ {
memcpy (&bidi_cache_idx, p, sizeof (bidi_cache_idx)); memcpy (&bidi_cache_idx, p, sizeof (bidi_cache_idx));
bidi_cache_ensure_space (bidi_cache_idx);
memcpy (bidi_cache, p + sizeof (bidi_cache_idx), memcpy (bidi_cache, p + sizeof (bidi_cache_idx),
bidi_cache_idx * sizeof (struct bidi_it)); bidi_cache_idx * sizeof (struct bidi_it));
memcpy (bidi_cache_start_stack, memcpy (bidi_cache_start_stack,
......
...@@ -5272,10 +5272,12 @@ buffer_posn_from_coords (struct window *w, int *x, int *y, struct display_pos *p ...@@ -5272,10 +5272,12 @@ buffer_posn_from_coords (struct window *w, int *x, int *y, struct display_pos *p
struct image *img = 0; struct image *img = 0;
#endif #endif
int x0, x1, to_x; int x0, x1, to_x;
void *itdata = NULL;
/* We used to set current_buffer directly here, but that does the /* We used to set current_buffer directly here, but that does the
wrong thing with `face-remapping-alist' (bug#2044). */ wrong thing with `face-remapping-alist' (bug#2044). */
Fset_buffer (w->buffer); Fset_buffer (w->buffer);
itdata = bidi_shelve_cache ();
SET_TEXT_POS_FROM_MARKER (startp, w->start); SET_TEXT_POS_FROM_MARKER (startp, w->start);
CHARPOS (startp) = min (ZV, max (BEGV, CHARPOS (startp))); CHARPOS (startp) = min (ZV, max (BEGV, CHARPOS (startp)));
BYTEPOS (startp) = min (ZV_BYTE, max (BEGV_BYTE, BYTEPOS (startp))); BYTEPOS (startp) = min (ZV_BYTE, max (BEGV_BYTE, BYTEPOS (startp)));
...@@ -5309,6 +5311,7 @@ buffer_posn_from_coords (struct window *w, int *x, int *y, struct display_pos *p ...@@ -5309,6 +5311,7 @@ buffer_posn_from_coords (struct window *w, int *x, int *y, struct display_pos *p
argument is ZV to prevent move_it_in_display_line from matching argument is ZV to prevent move_it_in_display_line from matching
based on buffer positions. */ based on buffer positions. */
move_it_in_display_line (&it, ZV, to_x, MOVE_TO_X); move_it_in_display_line (&it, ZV, to_x, MOVE_TO_X);
bidi_unshelve_cache (itdata);
Fset_buffer (old_current_buffer); Fset_buffer (old_current_buffer);
......
...@@ -1993,6 +1993,7 @@ whether or not it is currently displayed in some window. */) ...@@ -1993,6 +1993,7 @@ whether or not it is currently displayed in some window. */)
struct gcpro gcpro1; struct gcpro gcpro1;
Lisp_Object lcols = Qnil; Lisp_Object lcols = Qnil;
double cols IF_LINT (= 0); double cols IF_LINT (= 0);
void *itdata = NULL;
/* Allow LINES to be of the form (HPOS . VPOS) aka (COLUMNS . LINES). */ /* Allow LINES to be of the form (HPOS . VPOS) aka (COLUMNS . LINES). */
if (CONSP (lines) && (NUMBERP (XCAR (lines)))) if (CONSP (lines) && (NUMBERP (XCAR (lines))))
...@@ -2029,6 +2030,7 @@ whether or not it is currently displayed in some window. */) ...@@ -2029,6 +2030,7 @@ whether or not it is currently displayed in some window. */)
EMACS_INT it_start; EMACS_INT it_start;
int first_x, it_overshoot_expected IF_LINT (= 0); int first_x, it_overshoot_expected IF_LINT (= 0);
itdata = bidi_shelve_cache ();
SET_TEXT_POS (pt, PT, PT_BYTE); SET_TEXT_POS (pt, PT, PT_BYTE);
start_display (&it, w, pt); start_display (&it, w, pt);
first_x = it.first_visible_x; first_x = it.first_visible_x;
...@@ -2133,6 +2135,7 @@ whether or not it is currently displayed in some window. */) ...@@ -2133,6 +2135,7 @@ whether or not it is currently displayed in some window. */)
} }
SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it)); SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
bidi_unshelve_cache (itdata);
} }
if (BUFFERP (old_buffer)) if (BUFFERP (old_buffer))
......
...@@ -1162,6 +1162,7 @@ if it isn't already recorded. */) ...@@ -1162,6 +1162,7 @@ if it isn't already recorded. */)
struct text_pos startp; struct text_pos startp;
struct it it; struct it it;
struct buffer *old_buffer = NULL; struct buffer *old_buffer = NULL;
void *itdata = NULL;
/* Cannot use Fvertical_motion because that function doesn't /* Cannot use Fvertical_motion because that function doesn't
cope with variable-height lines. */ cope with variable-height lines. */
...@@ -1183,11 +1184,13 @@ if it isn't already recorded. */) ...@@ -1183,11 +1184,13 @@ if it isn't already recorded. */)
else else
SET_TEXT_POS_FROM_MARKER (startp, w->start); SET_TEXT_POS_FROM_MARKER (startp, w->start);
itdata = bidi_shelve_cache ();
start_display (&it, w, startp); start_display (&it, w, startp);
move_it_vertically (&it, window_box_height (w)); move_it_vertically (&it, window_box_height (w));
if (it.current_y < it.last_visible_y) if (it.current_y < it.last_visible_y)
move_it_past_eol (&it); move_it_past_eol (&it);
value = make_number (IT_CHARPOS (it)); value = make_number (IT_CHARPOS (it));
bidi_unshelve_cache (itdata);
if (old_buffer) if (old_buffer)
set_buffer_internal (old_buffer); set_buffer_internal (old_buffer);
...@@ -4736,6 +4739,7 @@ window_scroll_pixel_based (Lisp_Object window, int n, int whole, int noerror) ...@@ -4736,6 +4739,7 @@ window_scroll_pixel_based (Lisp_Object window, int n, int whole, int noerror)
/* True if we fiddled the window vscroll field without really scrolling. */ /* True if we fiddled the window vscroll field without really scrolling. */
int vscrolled = 0; int vscrolled = 0;
int x, y, rtop, rbot, rowh, vpos; int x, y, rtop, rbot, rowh, vpos;
void *itdata = NULL;
SET_TEXT_POS_FROM_MARKER (start, w->start); SET_TEXT_POS_FROM_MARKER (start, w->start);
...@@ -4746,6 +4750,7 @@ window_scroll_pixel_based (Lisp_Object window, int n, int whole, int noerror) ...@@ -4746,6 +4750,7 @@ window_scroll_pixel_based (Lisp_Object window, int n, int whole, int noerror)
if (!pos_visible_p (w, PT, &x, &y, &rtop, &rbot, &rowh, &vpos)) if (!pos_visible_p (w, PT, &x, &y, &rtop, &rbot, &rowh, &vpos))
{ {
itdata = bidi_shelve_cache ();
/* Move backward half the height of the window. Performance note: /* Move backward half the height of the window. Performance note:
vmotion used here is about 10% faster, but would give wrong vmotion used here is about 10% faster, but would give wrong
results for variable height lines. */ results for variable height lines. */
...@@ -4766,6 +4771,7 @@ window_scroll_pixel_based (Lisp_Object window, int n, int whole, int noerror) ...@@ -4766,6 +4771,7 @@ window_scroll_pixel_based (Lisp_Object window, int n, int whole, int noerror)
} }
start = it.current.pos; start = it.current.pos;
bidi_unshelve_cache (itdata);
} }
else if (auto_window_vscroll_p) else if (auto_window_vscroll_p)
{ {
...@@ -4828,6 +4834,7 @@ window_scroll_pixel_based (Lisp_Object window, int n, int whole, int noerror) ...@@ -4828,6 +4834,7 @@ window_scroll_pixel_based (Lisp_Object window, int n, int whole, int noerror)
Fset_window_vscroll (window, make_number (0), Qt); Fset_window_vscroll (window, make_number (0), Qt);
} }
itdata = bidi_shelve_cache ();
/* If scroll_preserve_screen_position is non-nil, we try to set /* If scroll_preserve_screen_position is non-nil, we try to set
point in the same window line as it is now, so get that line. */ point in the same window line as it is now, so get that line. */
if (!NILP (Vscroll_preserve_screen_position)) if (!NILP (Vscroll_preserve_screen_position))
...@@ -4906,12 +4913,16 @@ window_scroll_pixel_based (Lisp_Object window, int n, int whole, int noerror) ...@@ -4906,12 +4913,16 @@ window_scroll_pixel_based (Lisp_Object window, int n, int whole, int noerror)
- it.current_y + it.max_ascent + it.max_descent); - it.current_y + it.max_ascent + it.max_descent);
adjust_glyphs (it.f); adjust_glyphs (it.f);
} }
else if (noerror)
return;
else if (n < 0) /* could happen with empty buffers */
xsignal0 (Qbeginning_of_buffer);
else else
xsignal0 (Qend_of_buffer); {
bidi_unshelve_cache (itdata);
if (noerror)
return;
else if (n < 0) /* could happen with empty buffers */
xsignal0 (Qbeginning_of_buffer);
else
xsignal0 (Qend_of_buffer);
}
} }
else else
{ {
...@@ -4919,10 +4930,14 @@ window_scroll_pixel_based (Lisp_Object window, int n, int whole, int noerror) ...@@ -4919,10 +4930,14 @@ window_scroll_pixel_based (Lisp_Object window, int n, int whole, int noerror)
/* The first line was only partially visible, make it fully /* The first line was only partially visible, make it fully
visible. */ visible. */
w->vscroll = 0; w->vscroll = 0;
else if (noerror)
return;
else else
xsignal0 (Qbeginning_of_buffer); {
bidi_unshelve_cache (itdata);
if (noerror)
return;
else
xsignal0 (Qbeginning_of_buffer);
}
} }
/* If control gets here, then we vscrolled. */ /* If control gets here, then we vscrolled. */
...@@ -5066,6 +5081,7 @@ window_scroll_pixel_based (Lisp_Object window, int n, int whole, int noerror) ...@@ -5066,6 +5081,7 @@ window_scroll_pixel_based (Lisp_Object window, int n, int whole, int noerror)
SET_PT_BOTH (charpos, bytepos); SET_PT_BOTH (charpos, bytepos);
} }
} }
bidi_unshelve_cache (itdata);
} }
...@@ -5468,6 +5484,7 @@ displayed_window_lines (struct window *w) ...@@ -5468,6 +5484,7 @@ displayed_window_lines (struct window *w)
int height = window_box_height (w); int height = window_box_height (w);
struct buffer *old_buffer; struct buffer *old_buffer;
int bottom_y; int bottom_y;
void *itdata = NULL;
if (XBUFFER (w->buffer) != current_buffer) if (XBUFFER (w->buffer) != current_buffer)
{ {
...@@ -5487,9 +5504,11 @@ displayed_window_lines (struct window *w) ...@@ -5487,9 +5504,11 @@ displayed_window_lines (struct window *w)
else else
SET_TEXT_POS_FROM_MARKER (start, w->start); SET_TEXT_POS_FROM_MARKER (start, w->start);
itdata = bidi_shelve_cache ();
start_display (&it, w, start); start_display (&it, w, start);
move_it_vertically (&it, height); move_it_vertically (&it, height);
bottom_y = line_bottom_y (&it); bottom_y = line_bottom_y (&it);
bidi_unshelve_cache (itdata);
/* rms: On a non-window display, /* rms: On a non-window display,
the value of it.vpos at the bottom of the screen the value of it.vpos at the bottom of the screen
...@@ -5588,12 +5607,14 @@ and redisplay normally--don't erase and redraw the frame. */) ...@@ -5588,12 +5607,14 @@ and redisplay normally--don't erase and redraw the frame. */)
{ {
struct it it; struct it it;
struct text_pos pt; struct text_pos pt;
void *itdata = bidi_shelve_cache ();
SET_TEXT_POS (pt, PT, PT_BYTE); SET_TEXT_POS (pt, PT, PT_BYTE);
start_display (&it, w, pt); start_display (&it, w, pt);
move_it_vertically_backward (&it, window_box_height (w) / 2); move_it_vertically_backward (&it, window_box_height (w) / 2);
charpos = IT_CHARPOS (it); charpos = IT_CHARPOS (it);
bytepos = IT_BYTEPOS (it); bytepos = IT_BYTEPOS (it);
bidi_unshelve_cache (itdata);
} }
else if (iarg < 0) else if (iarg < 0)
{ {
...@@ -5602,6 +5623,7 @@ and redisplay normally--don't erase and redraw the frame. */) ...@@ -5602,6 +5623,7 @@ and redisplay normally--don't erase and redraw the frame. */)
int nlines = -iarg; int nlines = -iarg;
int extra_line_spacing; int extra_line_spacing;
int h = window_box_height (w); int h = window_box_height (w);
void *itdata = bidi_shelve_cache ();
iarg = - max (-iarg, this_scroll_margin); iarg = - max (-iarg, this_scroll_margin);
...@@ -5639,7 +5661,10 @@ and redisplay normally--don't erase and redraw the frame. */) ...@@ -5639,7 +5661,10 @@ and redisplay normally--don't erase and redraw the frame. */)
h -= nlines * (FRAME_LINE_HEIGHT (it.f) + extra_line_spacing); h -= nlines * (FRAME_LINE_HEIGHT (it.f) + extra_line_spacing);
} }
if (h <= 0) if (h <= 0)
return Qnil; {
bidi_unshelve_cache (itdata);
return Qnil;
}
/* Now find the new top line (starting position) of the window. */ /* Now find the new top line (starting position) of the window. */
start_display (&it, w, pt); start_display (&it, w, pt);
...@@ -5659,6 +5684,8 @@ and redisplay normally--don't erase and redraw the frame. */) ...@@ -5659,6 +5684,8 @@ and redisplay normally--don't erase and redraw the frame. */)
charpos = IT_CHARPOS (it); charpos = IT_CHARPOS (it);
bytepos = IT_BYTEPOS (it); bytepos = IT_BYTEPOS (it);
bidi_unshelve_cache (itdata);
} }
else else
{ {
......
...@@ -2618,6 +2618,7 @@ init_iterator (struct it *it, struct window *w, ...@@ -2618,6 +2618,7 @@ init_iterator (struct it *it, struct window *w,
it->paragraph_embedding = R2L; it->paragraph_embedding = R2L;
else else
it->paragraph_embedding = NEUTRAL_DIR; it->paragraph_embedding = NEUTRAL_DIR;
bidi_unshelve_cache (NULL);
bidi_init_it (charpos, IT_BYTEPOS (*it), FRAME_WINDOW_P (it->f), bidi_init_it (charpos, IT_BYTEPOS (*it), FRAME_WINDOW_P (it->f),
&it->bidi_it); &it->bidi_it);
} }
...@@ -5562,6 +5563,8 @@ back_to_previous_visible_line_start (struct it *it) ...@@ -5562,6 +5563,8 @@ back_to_previous_visible_line_start (struct it *it)
EMACS_INT beg, end; EMACS_INT beg, end;
Lisp_Object val, overlay; Lisp_Object val, overlay;
SAVE_IT (it2, *it, it2data);
/* If newline is part of a composition, continue from start of composition */ /* If newline is part of a composition, continue from start of composition */
if (find_composition (IT_CHARPOS (*it), -1, &beg, &end, &val, Qnil) if (find_composition (IT_CHARPOS (*it), -1, &beg, &end, &val, Qnil)
&& beg < IT_CHARPOS (*it)) && beg < IT_CHARPOS (*it))
...@@ -5569,10 +5572,10 @@ back_to_previous_visible_line_start (struct it *it) ...@@ -5569,10 +5572,10 @@ back_to_previous_visible_line_start (struct it *it)
/* If newline is replaced by a display property, find start of overlay /* If newline is replaced by a display property, find start of overlay
or interval and continue search from that point. */ or interval and continue search from that point. */
SAVE_IT (it2, *it, it2data);
pos = --IT_CHARPOS (it2); pos = --IT_CHARPOS (it2);
--IT_BYTEPOS (it2); --IT_BYTEPOS (it2);
it2.sp = 0; it2.sp = 0;
bidi_unshelve_cache (NULL);
it2.string_from_display_prop_p = 0; it2.string_from_display_prop_p = 0;
it2.from_disp_prop_p = 0; it2.from_disp_prop_p = 0;
if (handle_display_prop (&it2) == HANDLED_RETURN if (handle_display_prop (&it2) == HANDLED_RETURN
...@@ -5770,6 +5773,7 @@ reseat_1 (struct it *it, struct text_pos pos, int set_stop_p) ...@@ -5770,6 +5773,7 @@ reseat_1 (struct it *it, struct text_pos pos, int set_stop_p)
{ {
bidi_init_it (IT_CHARPOS (*it), IT_BYTEPOS (*it), FRAME_WINDOW_P (it->f), bidi_init_it (IT_CHARPOS (*it), IT_BYTEPOS (*it), FRAME_WINDOW_P (it->f),
&it->bidi_it); &it->bidi_it);
bidi_unshelve_cache (NULL);
it->bidi_it.paragraph_dir = NEUTRAL_DIR; it->bidi_it.paragraph_dir = NEUTRAL_DIR;
it->bidi_it.string.s = NULL; it->bidi_it.string.s = NULL;
it->bidi_it.string.lstring = Qnil; it->bidi_it.string.lstring = Qnil;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment