From: Eli Zaretskii Date: Tue, 5 Jul 2011 17:06:29 +0000 (+0300) Subject: Empty the bidi cache "stack" when it->sp is zeroed. X-Git-Tag: emacs-pretest-24.0.90~104^2~275^2~6 X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=57b3e30bb29d904180b651422ab58341debe84cb;p=emacs.git 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". --- diff --git a/src/ChangeLog b/src/ChangeLog index fdb6657e135..55ff323ab57 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,20 @@ +2011-07-05 Eli Zaretskii + + * 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 * bidi.c (bidi_shelve_cache, bidi_unshelve_cache): New functions. diff --git a/src/bidi.c b/src/bidi.c index be34f0352de..962afef435f 100644 --- a/src/bidi.c +++ b/src/bidi.c @@ -458,7 +458,8 @@ bidi_cache_ensure_space (int idx) /* Enlarge the cache as needed. */ if (idx >= bidi_cache_size) { - bidi_cache_size += BIDI_CACHE_CHUNK; + while (idx >= bidi_cache_size) + bidi_cache_size += BIDI_CACHE_CHUNK; bidi_cache = (struct bidi_it *) xrealloc (bidi_cache, bidi_cache_size * elsz); } @@ -656,6 +657,7 @@ bidi_unshelve_cache (void *databuf) else { memcpy (&bidi_cache_idx, p, sizeof (bidi_cache_idx)); + bidi_cache_ensure_space (bidi_cache_idx); memcpy (bidi_cache, p + sizeof (bidi_cache_idx), bidi_cache_idx * sizeof (struct bidi_it)); memcpy (bidi_cache_start_stack, diff --git a/src/dispnew.c b/src/dispnew.c index 0457d650b3a..69b32a5cd79 100644 --- a/src/dispnew.c +++ b/src/dispnew.c @@ -5272,10 +5272,12 @@ buffer_posn_from_coords (struct window *w, int *x, int *y, struct display_pos *p struct image *img = 0; #endif int x0, x1, to_x; + void *itdata = NULL; /* We used to set current_buffer directly here, but that does the wrong thing with `face-remapping-alist' (bug#2044). */ Fset_buffer (w->buffer); + itdata = bidi_shelve_cache (); SET_TEXT_POS_FROM_MARKER (startp, w->start); CHARPOS (startp) = min (ZV, max (BEGV, CHARPOS (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 argument is ZV to prevent move_it_in_display_line from matching based on buffer positions. */ move_it_in_display_line (&it, ZV, to_x, MOVE_TO_X); + bidi_unshelve_cache (itdata); Fset_buffer (old_current_buffer); diff --git a/src/indent.c b/src/indent.c index 0fdc45a33a4..a73284c6657 100644 --- a/src/indent.c +++ b/src/indent.c @@ -1993,6 +1993,7 @@ whether or not it is currently displayed in some window. */) struct gcpro gcpro1; Lisp_Object lcols = Qnil; double cols IF_LINT (= 0); + void *itdata = NULL; /* Allow LINES to be of the form (HPOS . VPOS) aka (COLUMNS . LINES). */ if (CONSP (lines) && (NUMBERP (XCAR (lines)))) @@ -2029,6 +2030,7 @@ whether or not it is currently displayed in some window. */) EMACS_INT it_start; int first_x, it_overshoot_expected IF_LINT (= 0); + itdata = bidi_shelve_cache (); SET_TEXT_POS (pt, PT, PT_BYTE); start_display (&it, w, pt); first_x = it.first_visible_x; @@ -2133,6 +2135,7 @@ whether or not it is currently displayed in some window. */) } SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it)); + bidi_unshelve_cache (itdata); } if (BUFFERP (old_buffer)) diff --git a/src/window.c b/src/window.c index 4dbee41c5f4..094cfcfbda3 100644 --- a/src/window.c +++ b/src/window.c @@ -1162,6 +1162,7 @@ if it isn't already recorded. */) struct text_pos startp; struct it it; struct buffer *old_buffer = NULL; + void *itdata = NULL; /* Cannot use Fvertical_motion because that function doesn't cope with variable-height lines. */ @@ -1183,11 +1184,13 @@ if it isn't already recorded. */) else SET_TEXT_POS_FROM_MARKER (startp, w->start); + itdata = bidi_shelve_cache (); start_display (&it, w, startp); move_it_vertically (&it, window_box_height (w)); if (it.current_y < it.last_visible_y) move_it_past_eol (&it); value = make_number (IT_CHARPOS (it)); + bidi_unshelve_cache (itdata); if (old_buffer) set_buffer_internal (old_buffer); @@ -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. */ int vscrolled = 0; int x, y, rtop, rbot, rowh, vpos; + void *itdata = NULL; 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) 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: vmotion used here is about 10% faster, but would give wrong results for variable height lines. */ @@ -4766,6 +4771,7 @@ window_scroll_pixel_based (Lisp_Object window, int n, int whole, int noerror) } start = it.current.pos; + bidi_unshelve_cache (itdata); } else if (auto_window_vscroll_p) { @@ -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); } + itdata = bidi_shelve_cache (); /* 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. */ if (!NILP (Vscroll_preserve_screen_position)) @@ -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); adjust_glyphs (it.f); } - else if (noerror) - return; - else if (n < 0) /* could happen with empty buffers */ - xsignal0 (Qbeginning_of_buffer); 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 { @@ -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 visible. */ w->vscroll = 0; - else if (noerror) - return; else - xsignal0 (Qbeginning_of_buffer); + { + bidi_unshelve_cache (itdata); + if (noerror) + return; + else + xsignal0 (Qbeginning_of_buffer); + } } /* If control gets here, then we vscrolled. */ @@ -5066,6 +5081,7 @@ window_scroll_pixel_based (Lisp_Object window, int n, int whole, int noerror) SET_PT_BOTH (charpos, bytepos); } } + bidi_unshelve_cache (itdata); } @@ -5468,6 +5484,7 @@ displayed_window_lines (struct window *w) int height = window_box_height (w); struct buffer *old_buffer; int bottom_y; + void *itdata = NULL; if (XBUFFER (w->buffer) != current_buffer) { @@ -5487,9 +5504,11 @@ displayed_window_lines (struct window *w) else SET_TEXT_POS_FROM_MARKER (start, w->start); + itdata = bidi_shelve_cache (); start_display (&it, w, start); move_it_vertically (&it, height); bottom_y = line_bottom_y (&it); + bidi_unshelve_cache (itdata); /* rms: On a non-window display, 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. */) { struct it it; struct text_pos pt; + void *itdata = bidi_shelve_cache (); SET_TEXT_POS (pt, PT, PT_BYTE); start_display (&it, w, pt); move_it_vertically_backward (&it, window_box_height (w) / 2); charpos = IT_CHARPOS (it); bytepos = IT_BYTEPOS (it); + bidi_unshelve_cache (itdata); } else if (iarg < 0) { @@ -5602,6 +5623,7 @@ and redisplay normally--don't erase and redraw the frame. */) int nlines = -iarg; int extra_line_spacing; int h = window_box_height (w); + void *itdata = bidi_shelve_cache (); iarg = - max (-iarg, this_scroll_margin); @@ -5639,7 +5661,10 @@ and redisplay normally--don't erase and redraw the frame. */) h -= nlines * (FRAME_LINE_HEIGHT (it.f) + extra_line_spacing); } if (h <= 0) - return Qnil; + { + bidi_unshelve_cache (itdata); + return Qnil; + } /* Now find the new top line (starting position) of the window. */ start_display (&it, w, pt); @@ -5659,6 +5684,8 @@ and redisplay normally--don't erase and redraw the frame. */) charpos = IT_CHARPOS (it); bytepos = IT_BYTEPOS (it); + + bidi_unshelve_cache (itdata); } else { diff --git a/src/xdisp.c b/src/xdisp.c index c1f4d44dbc5..0281370008c 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -2618,6 +2618,7 @@ init_iterator (struct it *it, struct window *w, it->paragraph_embedding = R2L; else it->paragraph_embedding = NEUTRAL_DIR; + bidi_unshelve_cache (NULL); bidi_init_it (charpos, IT_BYTEPOS (*it), FRAME_WINDOW_P (it->f), &it->bidi_it); } @@ -5562,6 +5563,8 @@ back_to_previous_visible_line_start (struct it *it) EMACS_INT beg, end; Lisp_Object val, overlay; + SAVE_IT (it2, *it, it2data); + /* If newline is part of a composition, continue from start of composition */ if (find_composition (IT_CHARPOS (*it), -1, &beg, &end, &val, Qnil) && beg < IT_CHARPOS (*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 or interval and continue search from that point. */ - SAVE_IT (it2, *it, it2data); pos = --IT_CHARPOS (it2); --IT_BYTEPOS (it2); it2.sp = 0; + bidi_unshelve_cache (NULL); it2.string_from_display_prop_p = 0; it2.from_disp_prop_p = 0; if (handle_display_prop (&it2) == HANDLED_RETURN @@ -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), &it->bidi_it); + bidi_unshelve_cache (NULL); it->bidi_it.paragraph_dir = NEUTRAL_DIR; it->bidi_it.string.s = NULL; it->bidi_it.string.lstring = Qnil;