]> git.eshelyaron.com Git - emacs.git/commitdiff
Empty the bidi cache "stack" when it->sp is zeroed.
authorEli Zaretskii <eliz@gnu.org>
Tue, 5 Jul 2011 17:06:29 +0000 (20:06 +0300)
committerEli Zaretskii <eliz@gnu.org>
Tue, 5 Jul 2011 17:06:29 +0000 (20:06 +0300)
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".

src/ChangeLog
src/bidi.c
src/dispnew.c
src/indent.c
src/window.c
src/xdisp.c

index fdb6657e13598ed80753f2ceb9ebf20f21ee1f40..55ff323ab57993346342a823dd63e14b9295b490 100644 (file)
@@ -1,3 +1,20 @@
+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>
 
        * bidi.c (bidi_shelve_cache, bidi_unshelve_cache): New functions.
index be34f0352def7fbee3bb1bff22fb3ed9f51df3e5..962afef435fbdbc171f39091bbc5c037cd5247aa 100644 (file)
@@ -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,
index 0457d650b3a13cb76f4ef487d5f3c441305ef181..69b32a5cd798dde0b8be7efc78e79aabdd175f57 100644 (file)
@@ -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);
 
index 0fdc45a33a4fc1dd33045e08ab4b7f34e8b738d7..a73284c665740b27ac45ade3d240f5af90c6a1f4 100644 (file)
@@ -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))
index 4dbee41c5f4d4d7219d520234b6d95aa19e668c7..094cfcfbda3ac8b0f2c94637f29d080fcec24e16 100644 (file)
@@ -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
        {
index c1f4d44dbc51920c19a9a342531ab7756c992050..0281370008cf92edf0221dbb754ed77213aaf896 100644 (file)
@@ -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;