aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorEli Zaretskii2011-07-05 20:06:29 +0300
committerEli Zaretskii2011-07-05 20:06:29 +0300
commit57b3e30bb29d904180b651422ab58341debe84cb (patch)
treecb6561a3ef8100dc64654beb65c70623798839aa /src
parented94e6d7bf6751592ff3dadb2b87f03ffaab3bfa (diff)
downloademacs-57b3e30bb29d904180b651422ab58341debe84cb.tar.gz
emacs-57b3e30bb29d904180b651422ab58341debe84cb.zip
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".
Diffstat (limited to 'src')
-rw-r--r--src/ChangeLog17
-rw-r--r--src/bidi.c4
-rw-r--r--src/dispnew.c3
-rw-r--r--src/indent.c3
-rw-r--r--src/window.c45
-rw-r--r--src/xdisp.c6
6 files changed, 67 insertions, 11 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index fdb6657e135..55ff323ab57 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,20 @@
12011-07-05 Eli Zaretskii <eliz@gnu.org>
2
3 * dispnew.c (buffer_posn_from_coords): Save and restore the bidi
4 cache around display iteration.
5
6 * window.c (Fwindow_end, window_scroll_pixel_based)
7 (displayed_window_lines, Frecenter): Save and restore the bidi
8 cache around display iteration.
9
10 * bidi.c (bidi_unshelve_cache): Ensure we have enough space before
11 restoring the shelved cache.
12 (bidi_cache_ensure_space): Don't assume the required size is just
13 one BIDI_CACHE_CHUNK away.
14
15 * xdisp.c (back_to_previous_visible_line_start, reseat_1)
16 (init_iterator): Empty the bidi cache "stack".
17
12011-07-03 Eli Zaretskii <eliz@gnu.org> 182011-07-03 Eli Zaretskii <eliz@gnu.org>
2 19
3 * bidi.c (bidi_shelve_cache, bidi_unshelve_cache): New functions. 20 * 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)
458 /* Enlarge the cache as needed. */ 458 /* Enlarge the cache as needed. */
459 if (idx >= bidi_cache_size) 459 if (idx >= bidi_cache_size)
460 { 460 {
461 bidi_cache_size += BIDI_CACHE_CHUNK; 461 while (idx >= bidi_cache_size)
462 bidi_cache_size += BIDI_CACHE_CHUNK;
462 bidi_cache = 463 bidi_cache =
463 (struct bidi_it *) xrealloc (bidi_cache, bidi_cache_size * elsz); 464 (struct bidi_it *) xrealloc (bidi_cache, bidi_cache_size * elsz);
464 } 465 }
@@ -656,6 +657,7 @@ bidi_unshelve_cache (void *databuf)
656 else 657 else
657 { 658 {
658 memcpy (&bidi_cache_idx, p, sizeof (bidi_cache_idx)); 659 memcpy (&bidi_cache_idx, p, sizeof (bidi_cache_idx));
660 bidi_cache_ensure_space (bidi_cache_idx);
659 memcpy (bidi_cache, p + sizeof (bidi_cache_idx), 661 memcpy (bidi_cache, p + sizeof (bidi_cache_idx),
660 bidi_cache_idx * sizeof (struct bidi_it)); 662 bidi_cache_idx * sizeof (struct bidi_it));
661 memcpy (bidi_cache_start_stack, 663 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
5272 struct image *img = 0; 5272 struct image *img = 0;
5273#endif 5273#endif
5274 int x0, x1, to_x; 5274 int x0, x1, to_x;
5275 void *itdata = NULL;
5275 5276
5276 /* We used to set current_buffer directly here, but that does the 5277 /* We used to set current_buffer directly here, but that does the
5277 wrong thing with `face-remapping-alist' (bug#2044). */ 5278 wrong thing with `face-remapping-alist' (bug#2044). */
5278 Fset_buffer (w->buffer); 5279 Fset_buffer (w->buffer);
5280 itdata = bidi_shelve_cache ();
5279 SET_TEXT_POS_FROM_MARKER (startp, w->start); 5281 SET_TEXT_POS_FROM_MARKER (startp, w->start);
5280 CHARPOS (startp) = min (ZV, max (BEGV, CHARPOS (startp))); 5282 CHARPOS (startp) = min (ZV, max (BEGV, CHARPOS (startp)));
5281 BYTEPOS (startp) = min (ZV_BYTE, max (BEGV_BYTE, BYTEPOS (startp))); 5283 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 argument is ZV to prevent move_it_in_display_line from matching 5311 argument is ZV to prevent move_it_in_display_line from matching
5310 based on buffer positions. */ 5312 based on buffer positions. */
5311 move_it_in_display_line (&it, ZV, to_x, MOVE_TO_X); 5313 move_it_in_display_line (&it, ZV, to_x, MOVE_TO_X);
5314 bidi_unshelve_cache (itdata);
5312 5315
5313 Fset_buffer (old_current_buffer); 5316 Fset_buffer (old_current_buffer);
5314 5317
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. */)
1993 struct gcpro gcpro1; 1993 struct gcpro gcpro1;
1994 Lisp_Object lcols = Qnil; 1994 Lisp_Object lcols = Qnil;
1995 double cols IF_LINT (= 0); 1995 double cols IF_LINT (= 0);
1996 void *itdata = NULL;
1996 1997
1997 /* Allow LINES to be of the form (HPOS . VPOS) aka (COLUMNS . LINES). */ 1998 /* Allow LINES to be of the form (HPOS . VPOS) aka (COLUMNS . LINES). */
1998 if (CONSP (lines) && (NUMBERP (XCAR (lines)))) 1999 if (CONSP (lines) && (NUMBERP (XCAR (lines))))
@@ -2029,6 +2030,7 @@ whether or not it is currently displayed in some window. */)
2029 EMACS_INT it_start; 2030 EMACS_INT it_start;
2030 int first_x, it_overshoot_expected IF_LINT (= 0); 2031 int first_x, it_overshoot_expected IF_LINT (= 0);
2031 2032
2033 itdata = bidi_shelve_cache ();
2032 SET_TEXT_POS (pt, PT, PT_BYTE); 2034 SET_TEXT_POS (pt, PT, PT_BYTE);
2033 start_display (&it, w, pt); 2035 start_display (&it, w, pt);
2034 first_x = it.first_visible_x; 2036 first_x = it.first_visible_x;
@@ -2133,6 +2135,7 @@ whether or not it is currently displayed in some window. */)
2133 } 2135 }
2134 2136
2135 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it)); 2137 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
2138 bidi_unshelve_cache (itdata);
2136 } 2139 }
2137 2140
2138 if (BUFFERP (old_buffer)) 2141 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. */)
1162 struct text_pos startp; 1162 struct text_pos startp;
1163 struct it it; 1163 struct it it;
1164 struct buffer *old_buffer = NULL; 1164 struct buffer *old_buffer = NULL;
1165 void *itdata = NULL;
1165 1166
1166 /* Cannot use Fvertical_motion because that function doesn't 1167 /* Cannot use Fvertical_motion because that function doesn't
1167 cope with variable-height lines. */ 1168 cope with variable-height lines. */
@@ -1183,11 +1184,13 @@ if it isn't already recorded. */)
1183 else 1184 else
1184 SET_TEXT_POS_FROM_MARKER (startp, w->start); 1185 SET_TEXT_POS_FROM_MARKER (startp, w->start);
1185 1186
1187 itdata = bidi_shelve_cache ();
1186 start_display (&it, w, startp); 1188 start_display (&it, w, startp);
1187 move_it_vertically (&it, window_box_height (w)); 1189 move_it_vertically (&it, window_box_height (w));
1188 if (it.current_y < it.last_visible_y) 1190 if (it.current_y < it.last_visible_y)
1189 move_it_past_eol (&it); 1191 move_it_past_eol (&it);
1190 value = make_number (IT_CHARPOS (it)); 1192 value = make_number (IT_CHARPOS (it));
1193 bidi_unshelve_cache (itdata);
1191 1194
1192 if (old_buffer) 1195 if (old_buffer)
1193 set_buffer_internal (old_buffer); 1196 set_buffer_internal (old_buffer);
@@ -4736,6 +4739,7 @@ window_scroll_pixel_based (Lisp_Object window, int n, int whole, int noerror)
4736 /* True if we fiddled the window vscroll field without really scrolling. */ 4739 /* True if we fiddled the window vscroll field without really scrolling. */
4737 int vscrolled = 0; 4740 int vscrolled = 0;
4738 int x, y, rtop, rbot, rowh, vpos; 4741 int x, y, rtop, rbot, rowh, vpos;
4742 void *itdata = NULL;
4739 4743
4740 SET_TEXT_POS_FROM_MARKER (start, w->start); 4744 SET_TEXT_POS_FROM_MARKER (start, w->start);
4741 4745
@@ -4746,6 +4750,7 @@ window_scroll_pixel_based (Lisp_Object window, int n, int whole, int noerror)
4746 4750
4747 if (!pos_visible_p (w, PT, &x, &y, &rtop, &rbot, &rowh, &vpos)) 4751 if (!pos_visible_p (w, PT, &x, &y, &rtop, &rbot, &rowh, &vpos))
4748 { 4752 {
4753 itdata = bidi_shelve_cache ();
4749 /* Move backward half the height of the window. Performance note: 4754 /* Move backward half the height of the window. Performance note:
4750 vmotion used here is about 10% faster, but would give wrong 4755 vmotion used here is about 10% faster, but would give wrong
4751 results for variable height lines. */ 4756 results for variable height lines. */
@@ -4766,6 +4771,7 @@ window_scroll_pixel_based (Lisp_Object window, int n, int whole, int noerror)
4766 } 4771 }
4767 4772
4768 start = it.current.pos; 4773 start = it.current.pos;
4774 bidi_unshelve_cache (itdata);
4769 } 4775 }
4770 else if (auto_window_vscroll_p) 4776 else if (auto_window_vscroll_p)
4771 { 4777 {
@@ -4828,6 +4834,7 @@ window_scroll_pixel_based (Lisp_Object window, int n, int whole, int noerror)
4828 Fset_window_vscroll (window, make_number (0), Qt); 4834 Fset_window_vscroll (window, make_number (0), Qt);
4829 } 4835 }
4830 4836
4837 itdata = bidi_shelve_cache ();
4831 /* If scroll_preserve_screen_position is non-nil, we try to set 4838 /* If scroll_preserve_screen_position is non-nil, we try to set
4832 point in the same window line as it is now, so get that line. */ 4839 point in the same window line as it is now, so get that line. */
4833 if (!NILP (Vscroll_preserve_screen_position)) 4840 if (!NILP (Vscroll_preserve_screen_position))
@@ -4906,12 +4913,16 @@ window_scroll_pixel_based (Lisp_Object window, int n, int whole, int noerror)
4906 - it.current_y + it.max_ascent + it.max_descent); 4913 - it.current_y + it.max_ascent + it.max_descent);
4907 adjust_glyphs (it.f); 4914 adjust_glyphs (it.f);
4908 } 4915 }
4909 else if (noerror)
4910 return;
4911 else if (n < 0) /* could happen with empty buffers */
4912 xsignal0 (Qbeginning_of_buffer);
4913 else 4916 else
4914 xsignal0 (Qend_of_buffer); 4917 {
4918 bidi_unshelve_cache (itdata);
4919 if (noerror)
4920 return;
4921 else if (n < 0) /* could happen with empty buffers */
4922 xsignal0 (Qbeginning_of_buffer);
4923 else
4924 xsignal0 (Qend_of_buffer);
4925 }
4915 } 4926 }
4916 else 4927 else
4917 { 4928 {
@@ -4919,10 +4930,14 @@ window_scroll_pixel_based (Lisp_Object window, int n, int whole, int noerror)
4919 /* The first line was only partially visible, make it fully 4930 /* The first line was only partially visible, make it fully
4920 visible. */ 4931 visible. */
4921 w->vscroll = 0; 4932 w->vscroll = 0;
4922 else if (noerror)
4923 return;
4924 else 4933 else
4925 xsignal0 (Qbeginning_of_buffer); 4934 {
4935 bidi_unshelve_cache (itdata);
4936 if (noerror)
4937 return;
4938 else
4939 xsignal0 (Qbeginning_of_buffer);
4940 }
4926 } 4941 }
4927 4942
4928 /* If control gets here, then we vscrolled. */ 4943 /* 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 SET_PT_BOTH (charpos, bytepos); 5081 SET_PT_BOTH (charpos, bytepos);
5067 } 5082 }
5068 } 5083 }
5084 bidi_unshelve_cache (itdata);
5069} 5085}
5070 5086
5071 5087
@@ -5468,6 +5484,7 @@ displayed_window_lines (struct window *w)
5468 int height = window_box_height (w); 5484 int height = window_box_height (w);
5469 struct buffer *old_buffer; 5485 struct buffer *old_buffer;
5470 int bottom_y; 5486 int bottom_y;
5487 void *itdata = NULL;
5471 5488
5472 if (XBUFFER (w->buffer) != current_buffer) 5489 if (XBUFFER (w->buffer) != current_buffer)
5473 { 5490 {
@@ -5487,9 +5504,11 @@ displayed_window_lines (struct window *w)
5487 else 5504 else
5488 SET_TEXT_POS_FROM_MARKER (start, w->start); 5505 SET_TEXT_POS_FROM_MARKER (start, w->start);
5489 5506
5507 itdata = bidi_shelve_cache ();
5490 start_display (&it, w, start); 5508 start_display (&it, w, start);
5491 move_it_vertically (&it, height); 5509 move_it_vertically (&it, height);
5492 bottom_y = line_bottom_y (&it); 5510 bottom_y = line_bottom_y (&it);
5511 bidi_unshelve_cache (itdata);
5493 5512
5494 /* rms: On a non-window display, 5513 /* rms: On a non-window display,
5495 the value of it.vpos at the bottom of the screen 5514 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 { 5607 {
5589 struct it it; 5608 struct it it;
5590 struct text_pos pt; 5609 struct text_pos pt;
5610 void *itdata = bidi_shelve_cache ();
5591 5611
5592 SET_TEXT_POS (pt, PT, PT_BYTE); 5612 SET_TEXT_POS (pt, PT, PT_BYTE);
5593 start_display (&it, w, pt); 5613 start_display (&it, w, pt);
5594 move_it_vertically_backward (&it, window_box_height (w) / 2); 5614 move_it_vertically_backward (&it, window_box_height (w) / 2);
5595 charpos = IT_CHARPOS (it); 5615 charpos = IT_CHARPOS (it);
5596 bytepos = IT_BYTEPOS (it); 5616 bytepos = IT_BYTEPOS (it);
5617 bidi_unshelve_cache (itdata);
5597 } 5618 }
5598 else if (iarg < 0) 5619 else if (iarg < 0)
5599 { 5620 {
@@ -5602,6 +5623,7 @@ and redisplay normally--don't erase and redraw the frame. */)
5602 int nlines = -iarg; 5623 int nlines = -iarg;
5603 int extra_line_spacing; 5624 int extra_line_spacing;
5604 int h = window_box_height (w); 5625 int h = window_box_height (w);
5626 void *itdata = bidi_shelve_cache ();
5605 5627
5606 iarg = - max (-iarg, this_scroll_margin); 5628 iarg = - max (-iarg, this_scroll_margin);
5607 5629
@@ -5639,7 +5661,10 @@ and redisplay normally--don't erase and redraw the frame. */)
5639 h -= nlines * (FRAME_LINE_HEIGHT (it.f) + extra_line_spacing); 5661 h -= nlines * (FRAME_LINE_HEIGHT (it.f) + extra_line_spacing);
5640 } 5662 }
5641 if (h <= 0) 5663 if (h <= 0)
5642 return Qnil; 5664 {
5665 bidi_unshelve_cache (itdata);
5666 return Qnil;
5667 }
5643 5668
5644 /* Now find the new top line (starting position) of the window. */ 5669 /* Now find the new top line (starting position) of the window. */
5645 start_display (&it, w, pt); 5670 start_display (&it, w, pt);
@@ -5659,6 +5684,8 @@ and redisplay normally--don't erase and redraw the frame. */)
5659 5684
5660 charpos = IT_CHARPOS (it); 5685 charpos = IT_CHARPOS (it);
5661 bytepos = IT_BYTEPOS (it); 5686 bytepos = IT_BYTEPOS (it);
5687
5688 bidi_unshelve_cache (itdata);
5662 } 5689 }
5663 else 5690 else
5664 { 5691 {
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,
2618 it->paragraph_embedding = R2L; 2618 it->paragraph_embedding = R2L;
2619 else 2619 else
2620 it->paragraph_embedding = NEUTRAL_DIR; 2620 it->paragraph_embedding = NEUTRAL_DIR;
2621 bidi_unshelve_cache (NULL);
2621 bidi_init_it (charpos, IT_BYTEPOS (*it), FRAME_WINDOW_P (it->f), 2622 bidi_init_it (charpos, IT_BYTEPOS (*it), FRAME_WINDOW_P (it->f),
2622 &it->bidi_it); 2623 &it->bidi_it);
2623 } 2624 }
@@ -5562,6 +5563,8 @@ back_to_previous_visible_line_start (struct it *it)
5562 EMACS_INT beg, end; 5563 EMACS_INT beg, end;
5563 Lisp_Object val, overlay; 5564 Lisp_Object val, overlay;
5564 5565
5566 SAVE_IT (it2, *it, it2data);
5567
5565 /* If newline is part of a composition, continue from start of composition */ 5568 /* If newline is part of a composition, continue from start of composition */
5566 if (find_composition (IT_CHARPOS (*it), -1, &beg, &end, &val, Qnil) 5569 if (find_composition (IT_CHARPOS (*it), -1, &beg, &end, &val, Qnil)
5567 && beg < IT_CHARPOS (*it)) 5570 && beg < IT_CHARPOS (*it))
@@ -5569,10 +5572,10 @@ back_to_previous_visible_line_start (struct it *it)
5569 5572
5570 /* If newline is replaced by a display property, find start of overlay 5573 /* If newline is replaced by a display property, find start of overlay
5571 or interval and continue search from that point. */ 5574 or interval and continue search from that point. */
5572 SAVE_IT (it2, *it, it2data);
5573 pos = --IT_CHARPOS (it2); 5575 pos = --IT_CHARPOS (it2);
5574 --IT_BYTEPOS (it2); 5576 --IT_BYTEPOS (it2);
5575 it2.sp = 0; 5577 it2.sp = 0;
5578 bidi_unshelve_cache (NULL);
5576 it2.string_from_display_prop_p = 0; 5579 it2.string_from_display_prop_p = 0;
5577 it2.from_disp_prop_p = 0; 5580 it2.from_disp_prop_p = 0;
5578 if (handle_display_prop (&it2) == HANDLED_RETURN 5581 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 { 5773 {
5771 bidi_init_it (IT_CHARPOS (*it), IT_BYTEPOS (*it), FRAME_WINDOW_P (it->f), 5774 bidi_init_it (IT_CHARPOS (*it), IT_BYTEPOS (*it), FRAME_WINDOW_P (it->f),
5772 &it->bidi_it); 5775 &it->bidi_it);
5776 bidi_unshelve_cache (NULL);
5773 it->bidi_it.paragraph_dir = NEUTRAL_DIR; 5777 it->bidi_it.paragraph_dir = NEUTRAL_DIR;
5774 it->bidi_it.string.s = NULL; 5778 it->bidi_it.string.s = NULL;
5775 it->bidi_it.string.lstring = Qnil; 5779 it->bidi_it.string.lstring = Qnil;