aboutsummaryrefslogtreecommitdiffstats
path: root/src/window.c
diff options
context:
space:
mode:
authorEli Zaretskii2011-07-14 20:28:42 +0300
committerEli Zaretskii2011-07-14 20:28:42 +0300
commit0bb2392728c10748f3376f8cef6d9ca53e29f464 (patch)
tree9fec522054a4e27aea4acfd098aa7d3f05dd0e2c /src/window.c
parent6a57fb5f2ba5f040a39fcf4d04ca37619aa754bd (diff)
parentc965adc5e0e9f30a3caeac4b5fa2023f89347b2e (diff)
downloademacs-0bb2392728c10748f3376f8cef6d9ca53e29f464.tar.gz
emacs-0bb2392728c10748f3376f8cef6d9ca53e29f464.zip
Support bidi reordering of overlay and display strings.
Fix bugs #7616, #8133, #8867. src/xdisp.c (compute_display_string_pos) (compute_display_string_end): Accept additional argument STRING. (init_iterator, reseat_1): Initialize bidi_it->string.s to NULL. (reseat_to_string): Initialize bidi_it->string.s and bidi_it->string.schars. (Fcurrent_bidi_paragraph_direction): Initialize itb.string.s to NULL (avoids a crash in bidi_paragraph_init). Initialize itb.string.lstring. (init_iterator): Call bidi_init_it only of a valid buffer position was specified. Initialize paragraph_embedding to L2R. (reseat_to_string): Initialize the bidi iterator. (display_string): If we need to ignore text properties of LISP_STRING, set IT->stop_charpos to IT->end_charpos. (The original value of -1 will not work with bidi.) (compute_display_string_pos): First arg is now struct `text_pos *'; all callers changed. Support display properties on Lisp strings. (compute_display_string_end): Support display properties on Lisp strings. (init_iterator, reseat_1, reseat_to_string): Initialize the string.bufpos member to 0 (zero, for compatibility with IT_CHARPOS when iterating on a string not from display properties). (compute_display_string_pos, compute_display_string_end): Fix calculation of the object to scan. Fixes an error when using arrow keys. (next_element_from_buffer): Don't abort when IT_CHARPOS is before base_level_stop; instead, set base_level_stop to BEGV. Fixes crashes in vertical-motion. (next_element_from_buffer): Improve commentary for when the iterator is before prev_stop. (init_iterator): Initialize bidi_p from the default value of bidi-display-reordering, not from buffer-local value. Use the buffer-local value only if initializing for buffer iteration. (handle_invisible_prop): Support invisible properties on strings that are being bidi-reordered. (set_iterator_to_next): Support bidi reordering of C strings and Lisp strings. (next_element_from_string): Support bidi reordering of Lisp strings. (handle_stop_backwards): Support Lisp strings as well. (display_string): Support display of R2L glyph rows. Use IT_STRING_CHARPOS when displaying from a Lisp string. (init_iterator): Don't initialize it->bidi_p for strings here. (reseat_to_string): Initialize it->bidi_p for strings here. (next_element_from_string, next_element_from_c_string) (next_element_from_buffer): Add xassert's for correspondence between IT's object being iterated and it->bidi_it.string structure. (face_before_or_after_it_pos): Support bidi iteration. (next_element_from_c_string): Handle the case of the first string character that is not the first one in the visual order. (get_visually_first_element): New function, refactored from common parts of next_element_from_buffer, next_element_from_string, and next_element_from_c_string. (tool_bar_lines_needed, redisplay_tool_bar) (display_menu_bar): Force left-to-right direction. Add a FIXME comment for making that be controlled by a user option. (push_it, pop_it): Save and restore the state of the bidi iterator. Save and restore the bidi_p flag. (pop_it): Iterate out of display property for string iteration as well. (iterate_out_of_display_property): Support iteration over strings. (handle_single_display_spec): Set up it->bidi_it for iteration over a display string, and call bidi_init_it. (handle_single_display_spec, next_overlay_string) (get_overlay_strings_1, push_display_prop): Set up the bidi iterator for displaying display or overlay strings. (forward_to_next_line_start): Don't use the shortcut if bidi-iterating. (back_to_previous_visible_line_start): If handle_display_prop pushed the iterator stack, restore the internal state of the bidi iterator by calling bidi_pop_it same number of times. (reseat_at_next_visible_line_start): If ON_NEWLINE_P is non-zero, and we are bidi-iterating, don't decrement the iterator position; instead, set the first_elt flag in the bidi iterator, to produce the same effect. (reseat_1): Remove redundant setting of string_from_display_prop_p. (push_display_prop): xassert that we are iterating a buffer. (push_it, pop_it): Save and restore paragraph_embedding member. (handle_single_display_spec, next_overlay_string) (get_overlay_strings_1, reseat_1, reseat_to_string) (push_display_prop): Set up the `unibyte' member of bidi_it.string correctly. Don't assume unibyte strings are not bidi-reordered. (compute_display_string_pos) (compute_display_string_end): Fix handling the case of C string. (push_it, pop_it): Save and restore from_disp_prop_p. (handle_single_display_spec, push_display_prop): Set the from_disp_prop_p flag. (get_overlay_strings_1): Reset the from_disp_prop_p flag. (pop_it): Call iterate_out_of_display_property only if we are popping after iteration over a string that came from a display property. Fix a typo in popping stretch info. Add an assertion for verifying that the iterator position is in sync with the bidi iterator. (handle_single_display_spec, get_overlay_strings_1) (push_display_prop): Fix initialization of paragraph direction for string when that of the parent object is not yet determined. (reseat_1): Call bidi_init_it to resync the bidi iterator with IT's position. (Bug#7616) (find_row_edges): If ROW->start.pos gives position smaller than min_pos, use it as ROW->minpos. (Bug#7616) (handle_stop, back_to_previous_visible_line_start, reseat_1): Reset the from_disp_prop_p flag. (SAVE_IT, RESTORE_IT): New macros. (pos_visible_p, face_before_or_after_it_pos) (back_to_previous_visible_line_start) (move_it_in_display_line_to, move_it_in_display_line) (move_it_to, move_it_vertically_backward, move_it_by_lines) (try_scrolling, redisplay_window, display_line): Use them when saving a temporary copy of the iterator and restoring it back. (back_to_previous_visible_line_start, reseat_1) (init_iterator): Empty the bidi cache "stack". (move_it_in_display_line_to): If iterator ended up at EOL, but we never saw any buffer positions smaller than to_charpos, return MOVE_POS_MATCH_OR_ZV. Fixes vertical cursor motion in bidi-reordered lines. (move_it_in_display_line_to): Record prev_method and prev_pos immediately before the call to set_iterator_to_next. Fixes cursor motion in bidi-reordered lines with stretch glyphs and strings displayed in margins. (Bug#8133) (Bug#8867) Return MOVE_POS_MATCH_OR_ZV only if iterator position is past TO_CHARPOS. (pos_visible_p): Support positions in bidi-reordered lines. Save and restore bidi cache. src/bidi.c (bidi_level_of_next_char): clen should be EMACS_NT, not int. (bidi_paragraph_info): Delete unused struct. (bidi_cache_idx, bidi_cache_last_idx): Declare EMACS_INT. (bidi_cache_start): New variable. (bidi_cache_reset): Reset bidi_cache_idx to bidi_cache_start, not to zero. (bidi_cache_fetch_state, bidi_cache_search) (bidi_cache_find_level_change, bidi_cache_iterator_state) (bidi_cache_find, bidi_peek_at_next_level) (bidi_level_of_next_char, bidi_find_other_level_edge) (bidi_move_to_visually_next): Compare cache index with bidi_cache_start rather than with zero. (bidi_fetch_char): Accept new argument STRING; all callers changed. Support iteration over a string. Support strings with display properties. Support unibyte strings. Fix the type of `len' according to what STRING_CHAR_AND_LENGTH expects. (bidi_paragraph_init, bidi_resolve_explicit_1) (bidi_resolve_explicit, bidi_resolve_weak) (bidi_level_of_next_char, bidi_move_to_visually_next): Support iteration over a string. (bidi_set_sor_type, bidi_resolve_explicit_1) (bidi_resolve_explicit, bidi_type_of_next_char): ignore_bn_limit can now be zero (for strings); special values 0 and -1 were changed to -1 and -2, respectively. (bidi_char_at_pos): New function. (bidi_paragraph_init, bidi_resolve_explicit, bidi_resolve_weak): Call it instead of FETCH_MULTIBYTE_CHAR. (bidi_move_to_visually_next): Abort if charpos or bytepos were not initialized to valid values. (bidi_init_it): Don't initialize charpos and bytepos with invalid values. (bidi_level_of_next_char): Allow the sentinel "position" to pass the test for valid cached positions. Fix the logic for looking up the sentinel state in the cache. GCPRO the Lisp string we are iterating. (bidi_push_it, bidi_pop_it): New functions. (bidi_initialize): Initialize the bidi cache start stack pointer. (bidi_cache_ensure_space): New function, refactored from part of bidi_cache_iterator_state. Don't assume the required size is just one BIDI_CACHE_CHUNK away. (bidi_cache_start_stack, bidi_push_it): Use IT_STACK_SIZE. (bidi_count_bytes, bidi_char_at_pos): New functions. (bidi_cache_search): Don't assume bidi_cache_last_idx is always valid if bidi_cache_idx is valid. (bidi_cache_find_level_change): xassert that bidi_cache_last_idx is valid if it's going to be used. (bidi_shelve_cache, bidi_unshelve_cache): New functions. (bidi_cache_fetch_state, bidi_cache_search) (bidi_cache_find_level_change, bidi_cache_ensure_space) (bidi_cache_iterator_state, bidi_cache_find) (bidi_find_other_level_edge, bidi_cache_start_stack): All variables related to cache indices are now EMACS_INT. src/dispextern.h (struct bidi_string_data): New structure. (struct bidi_it): New member `string'. Make flag members be 1-bit fields, and put them last in the struct. (compute_display_string_pos, compute_display_string_end): Update prototypes. (bidi_push_it, bidi_pop_it): Add prototypes. (struct iterator_stack_entry): New members bidi_p, paragraph_embedding, and from_disp_prop_p. (struct it): Member bidi_p is now a bit field 1 bit wide. (bidi_shelve_cache, bidi_unshelve_cache): Declare prototypes. src/.gdbinit (xvectype, xvector, xcompiled, xchartable, xboolvector) (xpr, xfont, xbacktrace): Use "header.size" when accessing vectors and vector-like objects. 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. lisp/buff-menu.el (Buffer-menu-buffer+size): Accept an additional argument LRM; if non-nil, append an invisible LRM character to the buffer name. (list-buffers-noselect): Call Buffer-menu-buffer+size with the last argument non-nil, when formatting buffer names. (Buffer-menu-mode, list-buffers-noselect): Force left-to-right paragraph direction. doc/lispref/display.texi (Other Display Specs): Document that `left-fringe' and `right-fringe' display specifications are of the "replacing" kind.
Diffstat (limited to 'src/window.c')
-rw-r--r--src/window.c45
1 files changed, 36 insertions, 9 deletions
diff --git a/src/window.c b/src/window.c
index e390c13dce0..3f5a743f5c6 100644
--- a/src/window.c
+++ b/src/window.c
@@ -1351,6 +1351,7 @@ if it isn't already recorded. */)
1351 struct text_pos startp; 1351 struct text_pos startp;
1352 struct it it; 1352 struct it it;
1353 struct buffer *old_buffer = NULL; 1353 struct buffer *old_buffer = NULL;
1354 void *itdata = NULL;
1354 1355
1355 /* Cannot use Fvertical_motion because that function doesn't 1356 /* Cannot use Fvertical_motion because that function doesn't
1356 cope with variable-height lines. */ 1357 cope with variable-height lines. */
@@ -1372,11 +1373,13 @@ if it isn't already recorded. */)
1372 else 1373 else
1373 SET_TEXT_POS_FROM_MARKER (startp, w->start); 1374 SET_TEXT_POS_FROM_MARKER (startp, w->start);
1374 1375
1376 itdata = bidi_shelve_cache ();
1375 start_display (&it, w, startp); 1377 start_display (&it, w, startp);
1376 move_it_vertically (&it, window_box_height (w)); 1378 move_it_vertically (&it, window_box_height (w));
1377 if (it.current_y < it.last_visible_y) 1379 if (it.current_y < it.last_visible_y)
1378 move_it_past_eol (&it); 1380 move_it_past_eol (&it);
1379 value = make_number (IT_CHARPOS (it)); 1381 value = make_number (IT_CHARPOS (it));
1382 bidi_unshelve_cache (itdata);
1380 1383
1381 if (old_buffer) 1384 if (old_buffer)
1382 set_buffer_internal (old_buffer); 1385 set_buffer_internal (old_buffer);
@@ -4238,6 +4241,7 @@ window_scroll_pixel_based (Lisp_Object window, int n, int whole, int noerror)
4238 /* True if we fiddled the window vscroll field without really scrolling. */ 4241 /* True if we fiddled the window vscroll field without really scrolling. */
4239 int vscrolled = 0; 4242 int vscrolled = 0;
4240 int x, y, rtop, rbot, rowh, vpos; 4243 int x, y, rtop, rbot, rowh, vpos;
4244 void *itdata = NULL;
4241 4245
4242 SET_TEXT_POS_FROM_MARKER (start, w->start); 4246 SET_TEXT_POS_FROM_MARKER (start, w->start);
4243 4247
@@ -4248,6 +4252,7 @@ window_scroll_pixel_based (Lisp_Object window, int n, int whole, int noerror)
4248 4252
4249 if (!pos_visible_p (w, PT, &x, &y, &rtop, &rbot, &rowh, &vpos)) 4253 if (!pos_visible_p (w, PT, &x, &y, &rtop, &rbot, &rowh, &vpos))
4250 { 4254 {
4255 itdata = bidi_shelve_cache ();
4251 /* Move backward half the height of the window. Performance note: 4256 /* Move backward half the height of the window. Performance note:
4252 vmotion used here is about 10% faster, but would give wrong 4257 vmotion used here is about 10% faster, but would give wrong
4253 results for variable height lines. */ 4258 results for variable height lines. */
@@ -4268,6 +4273,7 @@ window_scroll_pixel_based (Lisp_Object window, int n, int whole, int noerror)
4268 } 4273 }
4269 4274
4270 start = it.current.pos; 4275 start = it.current.pos;
4276 bidi_unshelve_cache (itdata);
4271 } 4277 }
4272 else if (auto_window_vscroll_p) 4278 else if (auto_window_vscroll_p)
4273 { 4279 {
@@ -4330,6 +4336,7 @@ window_scroll_pixel_based (Lisp_Object window, int n, int whole, int noerror)
4330 Fset_window_vscroll (window, make_number (0), Qt); 4336 Fset_window_vscroll (window, make_number (0), Qt);
4331 } 4337 }
4332 4338
4339 itdata = bidi_shelve_cache ();
4333 /* If scroll_preserve_screen_position is non-nil, we try to set 4340 /* If scroll_preserve_screen_position is non-nil, we try to set
4334 point in the same window line as it is now, so get that line. */ 4341 point in the same window line as it is now, so get that line. */
4335 if (!NILP (Vscroll_preserve_screen_position)) 4342 if (!NILP (Vscroll_preserve_screen_position))
@@ -4408,12 +4415,16 @@ window_scroll_pixel_based (Lisp_Object window, int n, int whole, int noerror)
4408 - it.current_y + it.max_ascent + it.max_descent); 4415 - it.current_y + it.max_ascent + it.max_descent);
4409 adjust_glyphs (it.f); 4416 adjust_glyphs (it.f);
4410 } 4417 }
4411 else if (noerror)
4412 return;
4413 else if (n < 0) /* could happen with empty buffers */
4414 xsignal0 (Qbeginning_of_buffer);
4415 else 4418 else
4416 xsignal0 (Qend_of_buffer); 4419 {
4420 bidi_unshelve_cache (itdata);
4421 if (noerror)
4422 return;
4423 else if (n < 0) /* could happen with empty buffers */
4424 xsignal0 (Qbeginning_of_buffer);
4425 else
4426 xsignal0 (Qend_of_buffer);
4427 }
4417 } 4428 }
4418 else 4429 else
4419 { 4430 {
@@ -4421,10 +4432,14 @@ window_scroll_pixel_based (Lisp_Object window, int n, int whole, int noerror)
4421 /* The first line was only partially visible, make it fully 4432 /* The first line was only partially visible, make it fully
4422 visible. */ 4433 visible. */
4423 w->vscroll = 0; 4434 w->vscroll = 0;
4424 else if (noerror)
4425 return;
4426 else 4435 else
4427 xsignal0 (Qbeginning_of_buffer); 4436 {
4437 bidi_unshelve_cache (itdata);
4438 if (noerror)
4439 return;
4440 else
4441 xsignal0 (Qbeginning_of_buffer);
4442 }
4428 } 4443 }
4429 4444
4430 /* If control gets here, then we vscrolled. */ 4445 /* If control gets here, then we vscrolled. */
@@ -4568,6 +4583,7 @@ window_scroll_pixel_based (Lisp_Object window, int n, int whole, int noerror)
4568 SET_PT_BOTH (charpos, bytepos); 4583 SET_PT_BOTH (charpos, bytepos);
4569 } 4584 }
4570 } 4585 }
4586 bidi_unshelve_cache (itdata);
4571} 4587}
4572 4588
4573 4589
@@ -4970,6 +4986,7 @@ displayed_window_lines (struct window *w)
4970 int height = window_box_height (w); 4986 int height = window_box_height (w);
4971 struct buffer *old_buffer; 4987 struct buffer *old_buffer;
4972 int bottom_y; 4988 int bottom_y;
4989 void *itdata = NULL;
4973 4990
4974 if (XBUFFER (w->buffer) != current_buffer) 4991 if (XBUFFER (w->buffer) != current_buffer)
4975 { 4992 {
@@ -4989,9 +5006,11 @@ displayed_window_lines (struct window *w)
4989 else 5006 else
4990 SET_TEXT_POS_FROM_MARKER (start, w->start); 5007 SET_TEXT_POS_FROM_MARKER (start, w->start);
4991 5008
5009 itdata = bidi_shelve_cache ();
4992 start_display (&it, w, start); 5010 start_display (&it, w, start);
4993 move_it_vertically (&it, height); 5011 move_it_vertically (&it, height);
4994 bottom_y = line_bottom_y (&it); 5012 bottom_y = line_bottom_y (&it);
5013 bidi_unshelve_cache (itdata);
4995 5014
4996 /* rms: On a non-window display, 5015 /* rms: On a non-window display,
4997 the value of it.vpos at the bottom of the screen 5016 the value of it.vpos at the bottom of the screen
@@ -5090,12 +5109,14 @@ and redisplay normally--don't erase and redraw the frame. */)
5090 { 5109 {
5091 struct it it; 5110 struct it it;
5092 struct text_pos pt; 5111 struct text_pos pt;
5112 void *itdata = bidi_shelve_cache ();
5093 5113
5094 SET_TEXT_POS (pt, PT, PT_BYTE); 5114 SET_TEXT_POS (pt, PT, PT_BYTE);
5095 start_display (&it, w, pt); 5115 start_display (&it, w, pt);
5096 move_it_vertically_backward (&it, window_box_height (w) / 2); 5116 move_it_vertically_backward (&it, window_box_height (w) / 2);
5097 charpos = IT_CHARPOS (it); 5117 charpos = IT_CHARPOS (it);
5098 bytepos = IT_BYTEPOS (it); 5118 bytepos = IT_BYTEPOS (it);
5119 bidi_unshelve_cache (itdata);
5099 } 5120 }
5100 else if (iarg < 0) 5121 else if (iarg < 0)
5101 { 5122 {
@@ -5104,6 +5125,7 @@ and redisplay normally--don't erase and redraw the frame. */)
5104 int nlines = -iarg; 5125 int nlines = -iarg;
5105 int extra_line_spacing; 5126 int extra_line_spacing;
5106 int h = window_box_height (w); 5127 int h = window_box_height (w);
5128 void *itdata = bidi_shelve_cache ();
5107 5129
5108 iarg = - max (-iarg, this_scroll_margin); 5130 iarg = - max (-iarg, this_scroll_margin);
5109 5131
@@ -5141,7 +5163,10 @@ and redisplay normally--don't erase and redraw the frame. */)
5141 h -= nlines * (FRAME_LINE_HEIGHT (it.f) + extra_line_spacing); 5163 h -= nlines * (FRAME_LINE_HEIGHT (it.f) + extra_line_spacing);
5142 } 5164 }
5143 if (h <= 0) 5165 if (h <= 0)
5144 return Qnil; 5166 {
5167 bidi_unshelve_cache (itdata);
5168 return Qnil;
5169 }
5145 5170
5146 /* Now find the new top line (starting position) of the window. */ 5171 /* Now find the new top line (starting position) of the window. */
5147 start_display (&it, w, pt); 5172 start_display (&it, w, pt);
@@ -5161,6 +5186,8 @@ and redisplay normally--don't erase and redraw the frame. */)
5161 5186
5162 charpos = IT_CHARPOS (it); 5187 charpos = IT_CHARPOS (it);
5163 bytepos = IT_BYTEPOS (it); 5188 bytepos = IT_BYTEPOS (it);
5189
5190 bidi_unshelve_cache (itdata);
5164 } 5191 }
5165 else 5192 else
5166 { 5193 {