diff options
| author | Paul Eggert | 2011-07-14 13:40:35 -0700 |
|---|---|---|
| committer | Paul Eggert | 2011-07-14 13:40:35 -0700 |
| commit | 1fd800e53d98ac4ea8ed560db81bd36545788b56 (patch) | |
| tree | 9b200f09414e05c1e059f0d3889c77fe93121883 /src | |
| parent | af1d7677299425547ec39d20810890333a9970a7 (diff) | |
| parent | 2fd0959ded01063e4a62c05e9d2d6b05cf6384c8 (diff) | |
| download | emacs-1fd800e53d98ac4ea8ed560db81bd36545788b56.tar.gz emacs-1fd800e53d98ac4ea8ed560db81bd36545788b56.zip | |
Merge from trunk.
Diffstat (limited to 'src')
| -rw-r--r-- | src/.gdbinit | 16 | ||||
| -rw-r--r-- | src/ChangeLog | 220 | ||||
| -rw-r--r-- | src/bidi.c | 1008 | ||||
| -rw-r--r-- | src/dispextern.h | 44 | ||||
| -rw-r--r-- | src/dispnew.c | 3 | ||||
| -rw-r--r-- | src/indent.c | 3 | ||||
| -rw-r--r-- | src/keyboard.c | 3 | ||||
| -rw-r--r-- | src/search.c | 16 | ||||
| -rw-r--r-- | src/window.c | 45 | ||||
| -rw-r--r-- | src/xdisp.c | 1254 |
10 files changed, 2004 insertions, 608 deletions
diff --git a/src/.gdbinit b/src/.gdbinit index 2cf5663df91..0f51a00ea76 100644 --- a/src/.gdbinit +++ b/src/.gdbinit | |||
| @@ -677,7 +677,7 @@ end | |||
| 677 | 677 | ||
| 678 | define xvectype | 678 | define xvectype |
| 679 | xgetptr $ | 679 | xgetptr $ |
| 680 | set $size = ((struct Lisp_Vector *) $ptr)->size | 680 | set $size = ((struct Lisp_Vector *) $ptr)->header.size |
| 681 | output ($size & PVEC_FLAG) ? (enum pvec_type) ($size & PVEC_TYPE_MASK) : $size & ~gdb_array_mark_flag | 681 | output ($size & PVEC_FLAG) ? (enum pvec_type) ($size & PVEC_TYPE_MASK) : $size & ~gdb_array_mark_flag |
| 682 | echo \n | 682 | echo \n |
| 683 | end | 683 | end |
| @@ -818,7 +818,7 @@ end | |||
| 818 | define xvector | 818 | define xvector |
| 819 | xgetptr $ | 819 | xgetptr $ |
| 820 | print (struct Lisp_Vector *) $ptr | 820 | print (struct Lisp_Vector *) $ptr |
| 821 | output ($->size > 50) ? 0 : ($->contents[0])@($->size & ~gdb_array_mark_flag) | 821 | output ($->header.size > 50) ? 0 : ($->contents[0])@($->header.size & ~gdb_array_mark_flag) |
| 822 | echo \n | 822 | echo \n |
| 823 | end | 823 | end |
| 824 | document xvector | 824 | document xvector |
| @@ -853,7 +853,7 @@ end | |||
| 853 | define xcompiled | 853 | define xcompiled |
| 854 | xgetptr $ | 854 | xgetptr $ |
| 855 | print (struct Lisp_Vector *) $ptr | 855 | print (struct Lisp_Vector *) $ptr |
| 856 | output ($->contents[0])@($->size & 0xff) | 856 | output ($->contents[0])@($->header.size & 0xff) |
| 857 | end | 857 | end |
| 858 | document xcompiled | 858 | document xcompiled |
| 859 | Print $ as a compiled function pointer. | 859 | Print $ as a compiled function pointer. |
| @@ -903,7 +903,7 @@ define xchartable | |||
| 903 | print (struct Lisp_Char_Table *) $ptr | 903 | print (struct Lisp_Char_Table *) $ptr |
| 904 | printf "Purpose: " | 904 | printf "Purpose: " |
| 905 | xprintsym $->purpose | 905 | xprintsym $->purpose |
| 906 | printf " %d extra slots", ($->size & 0x1ff) - 68 | 906 | printf " %d extra slots", ($->header.size & 0x1ff) - 68 |
| 907 | echo \n | 907 | echo \n |
| 908 | end | 908 | end |
| 909 | document xchartable | 909 | document xchartable |
| @@ -927,7 +927,7 @@ end | |||
| 927 | define xboolvector | 927 | define xboolvector |
| 928 | xgetptr $ | 928 | xgetptr $ |
| 929 | print (struct Lisp_Bool_Vector *) $ptr | 929 | print (struct Lisp_Bool_Vector *) $ptr |
| 930 | output ($->size > 256) ? 0 : ($->data[0])@((($->size & ~gdb_array_mark_flag) + 7)/ 8) | 930 | output ($->header.size > 256) ? 0 : ($->data[0])@((($->header.size & ~gdb_array_mark_flag) + 7)/ 8) |
| 931 | echo \n | 931 | echo \n |
| 932 | end | 932 | end |
| 933 | document xboolvector | 933 | document xboolvector |
| @@ -1093,7 +1093,7 @@ define xpr | |||
| 1093 | # end | 1093 | # end |
| 1094 | end | 1094 | end |
| 1095 | if $type == Lisp_Vectorlike | 1095 | if $type == Lisp_Vectorlike |
| 1096 | set $size = ((struct Lisp_Vector *) $ptr)->size | 1096 | set $size = ((struct Lisp_Vector *) $ptr)->header.size |
| 1097 | if ($size & PVEC_FLAG) | 1097 | if ($size & PVEC_FLAG) |
| 1098 | set $vec = (enum pvec_type) ($size & PVEC_TYPE_MASK) | 1098 | set $vec = (enum pvec_type) ($size & PVEC_TYPE_MASK) |
| 1099 | if $vec == PVEC_NORMAL_VECTOR | 1099 | if $vec == PVEC_NORMAL_VECTOR |
| @@ -1202,7 +1202,7 @@ end | |||
| 1202 | 1202 | ||
| 1203 | define xfont | 1203 | define xfont |
| 1204 | xgetptr $ | 1204 | xgetptr $ |
| 1205 | set $size = (((struct Lisp_Vector *) $ptr)->size & 0x1FF) | 1205 | set $size = (((struct Lisp_Vector *) $ptr)->header.size & 0x1FF) |
| 1206 | if $size == FONT_SPEC_MAX | 1206 | if $size == FONT_SPEC_MAX |
| 1207 | print (struct font_spec *) $ptr | 1207 | print (struct font_spec *) $ptr |
| 1208 | else | 1208 | else |
| @@ -1229,7 +1229,7 @@ define xbacktrace | |||
| 1229 | printf "0x%x ", $ptr | 1229 | printf "0x%x ", $ptr |
| 1230 | if $type == Lisp_Vectorlike | 1230 | if $type == Lisp_Vectorlike |
| 1231 | xgetptr (*$bt->function) | 1231 | xgetptr (*$bt->function) |
| 1232 | set $size = ((struct Lisp_Vector *) $ptr)->size | 1232 | set $size = ((struct Lisp_Vector *) $ptr)->header.size |
| 1233 | output ($size & PVEC_FLAG) ? (enum pvec_type) ($size & PVEC_TYPE_MASK) : $size & ~gdb_array_mark_flag | 1233 | output ($size & PVEC_FLAG) ? (enum pvec_type) ($size & PVEC_TYPE_MASK) : $size & ~gdb_array_mark_flag |
| 1234 | else | 1234 | else |
| 1235 | printf "Lisp type %d", $type | 1235 | printf "Lisp type %d", $type |
diff --git a/src/ChangeLog b/src/ChangeLog index 0977b12ab38..ce080f6b239 100644 --- a/src/ChangeLog +++ b/src/ChangeLog | |||
| @@ -182,6 +182,226 @@ | |||
| 182 | 182 | ||
| 183 | 2011-07-14 Lars Magne Ingebrigtsen <larsi@gnus.org> | 183 | 2011-07-14 Lars Magne Ingebrigtsen <larsi@gnus.org> |
| 184 | 184 | ||
| 185 | * data.c (Fcdr, Fcar): Revert the last change, since it didn't | ||
| 186 | really clarify much. | ||
| 187 | |||
| 188 | * search.c (Fre_search_backward): Mention `case-fold-search' in | ||
| 189 | all the re_search_* functions (bug#8138). | ||
| 190 | |||
| 191 | * keyboard.c (Fopen_dribble_file): Document when the file is | ||
| 192 | closed (bug#8056). | ||
| 193 | |||
| 194 | 2011-07-14 Eli Zaretskii <eliz@gnu.org> | ||
| 195 | |||
| 196 | * bidi.c (bidi_dump_cached_states): Fix format of displaying | ||
| 197 | bidi_cache_idx. | ||
| 198 | |||
| 199 | Support bidi reordering of display and overlay strings. | ||
| 200 | * xdisp.c (compute_display_string_pos) | ||
| 201 | (compute_display_string_end): Accept additional argument STRING. | ||
| 202 | (init_iterator, reseat_1): Initialize bidi_it->string.s to NULL. | ||
| 203 | (reseat_to_string): Initialize bidi_it->string.s and | ||
| 204 | bidi_it->string.schars. | ||
| 205 | (Fcurrent_bidi_paragraph_direction): Initialize itb.string.s to | ||
| 206 | NULL (avoids a crash in bidi_paragraph_init). Initialize | ||
| 207 | itb.string.lstring. | ||
| 208 | (init_iterator): Call bidi_init_it only of a valid | ||
| 209 | buffer position was specified. Initialize paragraph_embedding to | ||
| 210 | L2R. | ||
| 211 | (reseat_to_string): Initialize the bidi iterator. | ||
| 212 | (display_string): If we need to ignore text properties of | ||
| 213 | LISP_STRING, set IT->stop_charpos to IT->end_charpos. (The | ||
| 214 | original value of -1 will not work with bidi.) | ||
| 215 | (compute_display_string_pos): First arg is now struct | ||
| 216 | `text_pos *'; all callers changed. Support display properties on | ||
| 217 | Lisp strings. | ||
| 218 | (compute_display_string_end): Support display properties on Lisp | ||
| 219 | strings. | ||
| 220 | (init_iterator, reseat_1, reseat_to_string): Initialize the | ||
| 221 | string.bufpos member to 0 (zero, for compatibility with IT_CHARPOS | ||
| 222 | when iterating on a string not from display properties). | ||
| 223 | (compute_display_string_pos, compute_display_string_end): Fix | ||
| 224 | calculation of the object to scan. Fixes an error when using | ||
| 225 | arrow keys. | ||
| 226 | (next_element_from_buffer): Don't abort when IT_CHARPOS is before | ||
| 227 | base_level_stop; instead, set base_level_stop to BEGV. Fixes | ||
| 228 | crashes in vertical-motion. | ||
| 229 | (next_element_from_buffer): Improve commentary for when | ||
| 230 | the iterator is before prev_stop. | ||
| 231 | (init_iterator): Initialize bidi_p from the default value of | ||
| 232 | bidi-display-reordering, not from buffer-local value. Use the | ||
| 233 | buffer-local value only if initializing for buffer iteration. | ||
| 234 | (handle_invisible_prop): Support invisible properties on strings | ||
| 235 | that are being bidi-reordered. | ||
| 236 | (set_iterator_to_next): Support bidi reordering of C strings and | ||
| 237 | Lisp strings. | ||
| 238 | (next_element_from_string): Support bidi reordering of Lisp | ||
| 239 | strings. | ||
| 240 | (handle_stop_backwards): Support Lisp strings as well. | ||
| 241 | (display_string): Support display of R2L glyph rows. Use | ||
| 242 | IT_STRING_CHARPOS when displaying from a Lisp string. | ||
| 243 | (init_iterator): Don't initialize it->bidi_p for strings | ||
| 244 | here. | ||
| 245 | (reseat_to_string): Initialize it->bidi_p for strings here. | ||
| 246 | (next_element_from_string, next_element_from_c_string) | ||
| 247 | (next_element_from_buffer): Add xassert's for correspondence | ||
| 248 | between IT's object being iterated and it->bidi_it.string | ||
| 249 | structure. | ||
| 250 | (face_before_or_after_it_pos): Support bidi iteration. | ||
| 251 | (next_element_from_c_string): Handle the case of the first string | ||
| 252 | character that is not the first one in the visual order. | ||
| 253 | (get_visually_first_element): New function, refactored from common | ||
| 254 | parts of next_element_from_buffer, next_element_from_string, and | ||
| 255 | next_element_from_c_string. | ||
| 256 | (tool_bar_lines_needed, redisplay_tool_bar) | ||
| 257 | (display_menu_bar): Force left-to-right direction. Add a FIXME | ||
| 258 | comment for making that be controlled by a user option. | ||
| 259 | (push_it, pop_it): Save and restore the state of the | ||
| 260 | bidi iterator. Save and restore the bidi_p flag. | ||
| 261 | (pop_it): Iterate out of display property for string iteration as | ||
| 262 | well. | ||
| 263 | (iterate_out_of_display_property): Support iteration over strings. | ||
| 264 | (handle_single_display_spec): Set up it->bidi_it for iteration | ||
| 265 | over a display string, and call bidi_init_it. | ||
| 266 | (handle_single_display_spec, next_overlay_string) | ||
| 267 | (get_overlay_strings_1, push_display_prop): Set up the bidi | ||
| 268 | iterator for displaying display or overlay strings. | ||
| 269 | (forward_to_next_line_start): Don't use the shortcut if | ||
| 270 | bidi-iterating. | ||
| 271 | (back_to_previous_visible_line_start): If handle_display_prop | ||
| 272 | pushed the iterator stack, restore the internal state of the bidi | ||
| 273 | iterator by calling bidi_pop_it same number of times. | ||
| 274 | (reseat_at_next_visible_line_start): If ON_NEWLINE_P is non-zero, | ||
| 275 | and we are bidi-iterating, don't decrement the iterator position; | ||
| 276 | instead, set the first_elt flag in the bidi iterator, to produce | ||
| 277 | the same effect. | ||
| 278 | (reseat_1): Remove redundant setting of string_from_display_prop_p. | ||
| 279 | (push_display_prop): xassert that we are iterating a buffer. | ||
| 280 | (push_it, pop_it): Save and restore paragraph_embedding member. | ||
| 281 | (handle_single_display_spec, next_overlay_string) | ||
| 282 | (get_overlay_strings_1, reseat_1, reseat_to_string) | ||
| 283 | (push_display_prop): Set up the `unibyte' member of bidi_it.string | ||
| 284 | correctly. Don't assume unibyte strings are not bidi-reordered. | ||
| 285 | (compute_display_string_pos) | ||
| 286 | (compute_display_string_end): Fix handling the case of C string. | ||
| 287 | (push_it, pop_it): Save and restore from_disp_prop_p. | ||
| 288 | (handle_single_display_spec, push_display_prop): Set the | ||
| 289 | from_disp_prop_p flag. | ||
| 290 | (get_overlay_strings_1): Reset the from_disp_prop_p flag. | ||
| 291 | (pop_it): Call iterate_out_of_display_property only if we are | ||
| 292 | popping after iteration over a string that came from a display | ||
| 293 | property. Fix a typo in popping stretch info. Add an assertion | ||
| 294 | for verifying that the iterator position is in sync with the bidi | ||
| 295 | iterator. | ||
| 296 | (handle_single_display_spec, get_overlay_strings_1) | ||
| 297 | (push_display_prop): Fix initialization of paragraph direction for | ||
| 298 | string when that of the parent object is not yet determined. | ||
| 299 | (reseat_1): Call bidi_init_it to resync the bidi | ||
| 300 | iterator with IT's position. (Bug#7616) | ||
| 301 | (find_row_edges): If ROW->start.pos gives position | ||
| 302 | smaller than min_pos, use it as ROW->minpos. (Bug#7616) | ||
| 303 | (handle_stop, back_to_previous_visible_line_start, reseat_1): | ||
| 304 | Reset the from_disp_prop_p flag. | ||
| 305 | (SAVE_IT, RESTORE_IT): New macros. | ||
| 306 | (pos_visible_p, face_before_or_after_it_pos) | ||
| 307 | (back_to_previous_visible_line_start) | ||
| 308 | (move_it_in_display_line_to, move_it_in_display_line) | ||
| 309 | (move_it_to, move_it_vertically_backward, move_it_by_lines) | ||
| 310 | (try_scrolling, redisplay_window, display_line): Use them when | ||
| 311 | saving a temporary copy of the iterator and restoring it back. | ||
| 312 | (back_to_previous_visible_line_start, reseat_1) | ||
| 313 | (init_iterator): Empty the bidi cache "stack". | ||
| 314 | (move_it_in_display_line_to): If iterator ended up at | ||
| 315 | EOL, but we never saw any buffer positions smaller than | ||
| 316 | to_charpos, return MOVE_POS_MATCH_OR_ZV. Fixes vertical cursor | ||
| 317 | motion in bidi-reordered lines. | ||
| 318 | (move_it_in_display_line_to): Record prev_method and prev_pos | ||
| 319 | immediately before the call to set_iterator_to_next. Fixes cursor | ||
| 320 | motion in bidi-reordered lines with stretch glyphs and strings | ||
| 321 | displayed in margins. (Bug#8133) (Bug#8867) | ||
| 322 | Return MOVE_POS_MATCH_OR_ZV only if iterator position is past | ||
| 323 | TO_CHARPOS. | ||
| 324 | (pos_visible_p): Support positions in bidi-reordered lines. Save | ||
| 325 | and restore bidi cache. | ||
| 326 | |||
| 327 | * bidi.c (bidi_level_of_next_char): clen should be EMACS_NT, not int. | ||
| 328 | (bidi_paragraph_info): Delete unused struct. | ||
| 329 | (bidi_cache_idx, bidi_cache_last_idx): Declare EMACS_INT. | ||
| 330 | (bidi_cache_start): New variable. | ||
| 331 | (bidi_cache_reset): Reset bidi_cache_idx to bidi_cache_start, not | ||
| 332 | to zero. | ||
| 333 | (bidi_cache_fetch_state, bidi_cache_search) | ||
| 334 | (bidi_cache_find_level_change, bidi_cache_iterator_state) | ||
| 335 | (bidi_cache_find, bidi_peek_at_next_level) | ||
| 336 | (bidi_level_of_next_char, bidi_find_other_level_edge) | ||
| 337 | (bidi_move_to_visually_next): Compare cache index with | ||
| 338 | bidi_cache_start rather than with zero. | ||
| 339 | (bidi_fetch_char): Accept new argument STRING; all callers | ||
| 340 | changed. Support iteration over a string. Support strings with | ||
| 341 | display properties. Support unibyte strings. Fix the type of | ||
| 342 | `len' according to what STRING_CHAR_AND_LENGTH expects. | ||
| 343 | (bidi_paragraph_init, bidi_resolve_explicit_1) | ||
| 344 | (bidi_resolve_explicit, bidi_resolve_weak) | ||
| 345 | (bidi_level_of_next_char, bidi_move_to_visually_next): Support | ||
| 346 | iteration over a string. | ||
| 347 | (bidi_set_sor_type, bidi_resolve_explicit_1) | ||
| 348 | (bidi_resolve_explicit, bidi_type_of_next_char): ignore_bn_limit | ||
| 349 | can now be zero (for strings); special values 0 and -1 were | ||
| 350 | changed to -1 and -2, respectively. | ||
| 351 | (bidi_char_at_pos): New function. | ||
| 352 | (bidi_paragraph_init, bidi_resolve_explicit, bidi_resolve_weak): | ||
| 353 | Call it instead of FETCH_MULTIBYTE_CHAR. | ||
| 354 | (bidi_move_to_visually_next): Abort if charpos or bytepos were not | ||
| 355 | initialized to valid values. | ||
| 356 | (bidi_init_it): Don't initialize charpos and bytepos with invalid | ||
| 357 | values. | ||
| 358 | (bidi_level_of_next_char): Allow the sentinel "position" to pass | ||
| 359 | the test for valid cached positions. Fix the logic for looking up | ||
| 360 | the sentinel state in the cache. GCPRO the Lisp string we are | ||
| 361 | iterating. | ||
| 362 | (bidi_push_it, bidi_pop_it): New functions. | ||
| 363 | (bidi_initialize): Initialize the bidi cache start stack pointer. | ||
| 364 | (bidi_cache_ensure_space): New function, refactored from part of | ||
| 365 | bidi_cache_iterator_state. Don't assume the required size is just | ||
| 366 | one BIDI_CACHE_CHUNK away. | ||
| 367 | (bidi_cache_start_stack, bidi_push_it): Use IT_STACK_SIZE. | ||
| 368 | (bidi_count_bytes, bidi_char_at_pos): New functions. | ||
| 369 | (bidi_cache_search): Don't assume bidi_cache_last_idx is | ||
| 370 | always valid if bidi_cache_idx is valid. | ||
| 371 | (bidi_cache_find_level_change): xassert that bidi_cache_last_idx | ||
| 372 | is valid if it's going to be used. | ||
| 373 | (bidi_shelve_cache, bidi_unshelve_cache): New functions. | ||
| 374 | (bidi_cache_fetch_state, bidi_cache_search) | ||
| 375 | (bidi_cache_find_level_change, bidi_cache_ensure_space) | ||
| 376 | (bidi_cache_iterator_state, bidi_cache_find) | ||
| 377 | (bidi_find_other_level_edge, bidi_cache_start_stack): All | ||
| 378 | variables related to cache indices are now EMACS_INT. | ||
| 379 | |||
| 380 | * dispextern.h (struct bidi_string_data): New structure. | ||
| 381 | (struct bidi_it): New member `string'. Make flag members be 1-bit | ||
| 382 | fields, and put them last in the struct. | ||
| 383 | (compute_display_string_pos, compute_display_string_end): Update | ||
| 384 | prototypes. | ||
| 385 | (bidi_push_it, bidi_pop_it): Add prototypes. | ||
| 386 | (struct iterator_stack_entry): New members bidi_p, | ||
| 387 | paragraph_embedding, and from_disp_prop_p. | ||
| 388 | (struct it): Member bidi_p is now a bit field 1 bit wide. | ||
| 389 | (bidi_shelve_cache, bidi_unshelve_cache): Declare | ||
| 390 | prototypes. | ||
| 391 | |||
| 392 | * .gdbinit (xvectype, xvector, xcompiled, xchartable, xboolvector) | ||
| 393 | (xpr, xfont, xbacktrace): Use "header.size" when accessing vectors | ||
| 394 | and vector-like objects. | ||
| 395 | |||
| 396 | * dispnew.c (buffer_posn_from_coords): Save and restore the bidi | ||
| 397 | cache around display iteration. | ||
| 398 | |||
| 399 | * window.c (Fwindow_end, window_scroll_pixel_based) | ||
| 400 | (displayed_window_lines, Frecenter): Save and restore the bidi | ||
| 401 | cache around display iteration. | ||
| 402 | |||
| 403 | 2011-07-14 Lars Magne Ingebrigtsen <larsi@gnus.org> | ||
| 404 | |||
| 185 | * editfns.c (Fdelete_region): Clarify the use of the named | 405 | * editfns.c (Fdelete_region): Clarify the use of the named |
| 186 | parameters (bug#6788). | 406 | parameters (bug#6788). |
| 187 | 407 | ||
diff --git a/src/bidi.c b/src/bidi.c index 469afdb3819..22a5f0829cd 100644 --- a/src/bidi.c +++ b/src/bidi.c | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | /* Low-level bidirectional buffer-scanning functions for GNU Emacs. | 1 | /* Low-level bidirectional buffer/string-scanning functions for GNU Emacs. |
| 2 | Copyright (C) 2000-2001, 2004-2005, 2009-2011 | 2 | Copyright (C) 2000-2001, 2004-2005, 2009-2011 |
| 3 | Free Software Foundation, Inc. | 3 | Free Software Foundation, Inc. |
| 4 | 4 | ||
| @@ -20,7 +20,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ | |||
| 20 | /* Written by Eli Zaretskii <eliz@gnu.org>. | 20 | /* Written by Eli Zaretskii <eliz@gnu.org>. |
| 21 | 21 | ||
| 22 | A sequential implementation of the Unicode Bidirectional algorithm, | 22 | A sequential implementation of the Unicode Bidirectional algorithm, |
| 23 | as per UAX#9, a part of the Unicode Standard. | 23 | (UBA) as per UAX#9, a part of the Unicode Standard. |
| 24 | 24 | ||
| 25 | Unlike the reference and most other implementations, this one is | 25 | Unlike the reference and most other implementations, this one is |
| 26 | designed to be called once for every character in the buffer or | 26 | designed to be called once for every character in the buffer or |
| @@ -35,11 +35,16 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ | |||
| 35 | details about its algorithm that finds the next visual-order | 35 | details about its algorithm that finds the next visual-order |
| 36 | character by resolving their levels on the fly. | 36 | character by resolving their levels on the fly. |
| 37 | 37 | ||
| 38 | The two other entry points are bidi_paragraph_init and | 38 | Two other entry points are bidi_paragraph_init and |
| 39 | bidi_mirror_char. The first determines the base direction of a | 39 | bidi_mirror_char. The first determines the base direction of a |
| 40 | paragraph, while the second returns the mirrored version of its | 40 | paragraph, while the second returns the mirrored version of its |
| 41 | argument character. | 41 | argument character. |
| 42 | 42 | ||
| 43 | A few auxiliary entry points are used to initialize the bidi | ||
| 44 | iterator for iterating an object (buffer or string), push and pop | ||
| 45 | the bidi iterator state, and save and restore the state of the bidi | ||
| 46 | cache. | ||
| 47 | |||
| 43 | If you want to understand the code, you will have to read it | 48 | If you want to understand the code, you will have to read it |
| 44 | together with the relevant portions of UAX#9. The comments include | 49 | together with the relevant portions of UAX#9. The comments include |
| 45 | references to UAX#9 rules, for that very reason. | 50 | references to UAX#9 rules, for that very reason. |
| @@ -66,16 +71,6 @@ static Lisp_Object bidi_type_table, bidi_mirror_table; | |||
| 66 | #define RLM_CHAR 0x200F | 71 | #define RLM_CHAR 0x200F |
| 67 | #define BIDI_EOB -1 | 72 | #define BIDI_EOB -1 |
| 68 | 73 | ||
| 69 | /* Local data structures. (Look in dispextern.h for the rest.) */ | ||
| 70 | |||
| 71 | /* What we need to know about the current paragraph. */ | ||
| 72 | struct bidi_paragraph_info { | ||
| 73 | EMACS_INT start_bytepos; /* byte position where it begins */ | ||
| 74 | EMACS_INT end_bytepos; /* byte position where it ends */ | ||
| 75 | int embedding_level; /* its basic embedding level */ | ||
| 76 | bidi_dir_t base_dir; /* its base direction */ | ||
| 77 | }; | ||
| 78 | |||
| 79 | /* Data type for describing the bidirectional character categories. */ | 74 | /* Data type for describing the bidirectional character categories. */ |
| 80 | typedef enum { | 75 | typedef enum { |
| 81 | UNKNOWN_BC, | 76 | UNKNOWN_BC, |
| @@ -90,43 +85,10 @@ int bidi_ignore_explicit_marks_for_paragraph_level = 1; | |||
| 90 | static Lisp_Object paragraph_start_re, paragraph_separate_re; | 85 | static Lisp_Object paragraph_start_re, paragraph_separate_re; |
| 91 | static Lisp_Object Qparagraph_start, Qparagraph_separate; | 86 | static Lisp_Object Qparagraph_start, Qparagraph_separate; |
| 92 | 87 | ||
| 93 | static void | 88 | |
| 94 | bidi_initialize (void) | 89 | /*********************************************************************** |
| 95 | { | 90 | Utilities |
| 96 | 91 | ***********************************************************************/ | |
| 97 | #include "biditype.h" | ||
| 98 | #include "bidimirror.h" | ||
| 99 | |||
| 100 | int i; | ||
| 101 | |||
| 102 | bidi_type_table = Fmake_char_table (Qnil, make_number (STRONG_L)); | ||
| 103 | staticpro (&bidi_type_table); | ||
| 104 | |||
| 105 | for (i = 0; i < sizeof bidi_type / sizeof bidi_type[0]; i++) | ||
| 106 | char_table_set_range (bidi_type_table, bidi_type[i].from, bidi_type[i].to, | ||
| 107 | make_number (bidi_type[i].type)); | ||
| 108 | |||
| 109 | bidi_mirror_table = Fmake_char_table (Qnil, Qnil); | ||
| 110 | staticpro (&bidi_mirror_table); | ||
| 111 | |||
| 112 | for (i = 0; i < sizeof bidi_mirror / sizeof bidi_mirror[0]; i++) | ||
| 113 | char_table_set (bidi_mirror_table, bidi_mirror[i].from, | ||
| 114 | make_number (bidi_mirror[i].to)); | ||
| 115 | |||
| 116 | Qparagraph_start = intern ("paragraph-start"); | ||
| 117 | staticpro (&Qparagraph_start); | ||
| 118 | paragraph_start_re = Fsymbol_value (Qparagraph_start); | ||
| 119 | if (!STRINGP (paragraph_start_re)) | ||
| 120 | paragraph_start_re = build_string ("\f\\|[ \t]*$"); | ||
| 121 | staticpro (¶graph_start_re); | ||
| 122 | Qparagraph_separate = intern ("paragraph-separate"); | ||
| 123 | staticpro (&Qparagraph_separate); | ||
| 124 | paragraph_separate_re = Fsymbol_value (Qparagraph_separate); | ||
| 125 | if (!STRINGP (paragraph_separate_re)) | ||
| 126 | paragraph_separate_re = build_string ("[ \t\f]*$"); | ||
| 127 | staticpro (¶graph_separate_re); | ||
| 128 | bidi_initialized = 1; | ||
| 129 | } | ||
| 130 | 92 | ||
| 131 | /* Return the bidi type of a character CH, subject to the current | 93 | /* Return the bidi type of a character CH, subject to the current |
| 132 | directional OVERRIDE. */ | 94 | directional OVERRIDE. */ |
| @@ -243,6 +205,77 @@ bidi_mirror_char (int c) | |||
| 243 | return c; | 205 | return c; |
| 244 | } | 206 | } |
| 245 | 207 | ||
| 208 | /* Determine the start-of-run (sor) directional type given the two | ||
| 209 | embedding levels on either side of the run boundary. Also, update | ||
| 210 | the saved info about previously seen characters, since that info is | ||
| 211 | generally valid for a single level run. */ | ||
| 212 | static inline void | ||
| 213 | bidi_set_sor_type (struct bidi_it *bidi_it, int level_before, int level_after) | ||
| 214 | { | ||
| 215 | int higher_level = level_before > level_after ? level_before : level_after; | ||
| 216 | |||
| 217 | /* The prev_was_pdf gork is required for when we have several PDFs | ||
| 218 | in a row. In that case, we want to compute the sor type for the | ||
| 219 | next level run only once: when we see the first PDF. That's | ||
| 220 | because the sor type depends only on the higher of the two levels | ||
| 221 | that we find on the two sides of the level boundary (see UAX#9, | ||
| 222 | clause X10), and so we don't need to know the final embedding | ||
| 223 | level to which we descend after processing all the PDFs. */ | ||
| 224 | if (!bidi_it->prev_was_pdf || level_before < level_after) | ||
| 225 | /* FIXME: should the default sor direction be user selectable? */ | ||
| 226 | bidi_it->sor = (higher_level & 1) != 0 ? R2L : L2R; | ||
| 227 | if (level_before > level_after) | ||
| 228 | bidi_it->prev_was_pdf = 1; | ||
| 229 | |||
| 230 | bidi_it->prev.type = UNKNOWN_BT; | ||
| 231 | bidi_it->last_strong.type = bidi_it->last_strong.type_after_w1 = | ||
| 232 | bidi_it->last_strong.orig_type = UNKNOWN_BT; | ||
| 233 | bidi_it->prev_for_neutral.type = bidi_it->sor == R2L ? STRONG_R : STRONG_L; | ||
| 234 | bidi_it->prev_for_neutral.charpos = bidi_it->charpos; | ||
| 235 | bidi_it->prev_for_neutral.bytepos = bidi_it->bytepos; | ||
| 236 | bidi_it->next_for_neutral.type = bidi_it->next_for_neutral.type_after_w1 = | ||
| 237 | bidi_it->next_for_neutral.orig_type = UNKNOWN_BT; | ||
| 238 | bidi_it->ignore_bn_limit = -1; /* meaning it's unknown */ | ||
| 239 | } | ||
| 240 | |||
| 241 | /* Push the current embedding level and override status; reset the | ||
| 242 | current level to LEVEL and the current override status to OVERRIDE. */ | ||
| 243 | static inline void | ||
| 244 | bidi_push_embedding_level (struct bidi_it *bidi_it, | ||
| 245 | int level, bidi_dir_t override) | ||
| 246 | { | ||
| 247 | bidi_it->stack_idx++; | ||
| 248 | xassert (bidi_it->stack_idx < BIDI_MAXLEVEL); | ||
| 249 | bidi_it->level_stack[bidi_it->stack_idx].level = level; | ||
| 250 | bidi_it->level_stack[bidi_it->stack_idx].override = override; | ||
| 251 | } | ||
| 252 | |||
| 253 | /* Pop the embedding level and directional override status from the | ||
| 254 | stack, and return the new level. */ | ||
| 255 | static inline int | ||
| 256 | bidi_pop_embedding_level (struct bidi_it *bidi_it) | ||
| 257 | { | ||
| 258 | /* UAX#9 says to ignore invalid PDFs. */ | ||
| 259 | if (bidi_it->stack_idx > 0) | ||
| 260 | bidi_it->stack_idx--; | ||
| 261 | return bidi_it->level_stack[bidi_it->stack_idx].level; | ||
| 262 | } | ||
| 263 | |||
| 264 | /* Record in SAVED_INFO the information about the current character. */ | ||
| 265 | static inline void | ||
| 266 | bidi_remember_char (struct bidi_saved_info *saved_info, | ||
| 267 | struct bidi_it *bidi_it) | ||
| 268 | { | ||
| 269 | saved_info->charpos = bidi_it->charpos; | ||
| 270 | saved_info->bytepos = bidi_it->bytepos; | ||
| 271 | saved_info->type = bidi_it->type; | ||
| 272 | bidi_check_type (bidi_it->type); | ||
| 273 | saved_info->type_after_w1 = bidi_it->type_after_w1; | ||
| 274 | bidi_check_type (bidi_it->type_after_w1); | ||
| 275 | saved_info->orig_type = bidi_it->orig_type; | ||
| 276 | bidi_check_type (bidi_it->orig_type); | ||
| 277 | } | ||
| 278 | |||
| 246 | /* Copy the bidi iterator from FROM to TO. To save cycles, this only | 279 | /* Copy the bidi iterator from FROM to TO. To save cycles, this only |
| 247 | copies the part of the level stack that is actually in use. */ | 280 | copies the part of the level stack that is actually in use. */ |
| 248 | static inline void | 281 | static inline void |
| @@ -259,22 +292,37 @@ bidi_copy_it (struct bidi_it *to, struct bidi_it *from) | |||
| 259 | to->level_stack[i] = from->level_stack[i]; | 292 | to->level_stack[i] = from->level_stack[i]; |
| 260 | } | 293 | } |
| 261 | 294 | ||
| 262 | /* Caching the bidi iterator states. */ | 295 | |
| 296 | /*********************************************************************** | ||
| 297 | Caching the bidi iterator states | ||
| 298 | ***********************************************************************/ | ||
| 263 | 299 | ||
| 264 | #define BIDI_CACHE_CHUNK 200 | 300 | #define BIDI_CACHE_CHUNK 200 |
| 265 | static struct bidi_it *bidi_cache; | 301 | static struct bidi_it *bidi_cache; |
| 266 | static size_t bidi_cache_size = 0; | 302 | static size_t bidi_cache_size = 0; |
| 267 | static size_t elsz = sizeof (struct bidi_it); | 303 | static size_t elsz = sizeof (struct bidi_it); |
| 268 | static int bidi_cache_idx; /* next unused cache slot */ | 304 | static EMACS_INT bidi_cache_idx; /* next unused cache slot */ |
| 269 | static int bidi_cache_last_idx; /* slot of last cache hit */ | 305 | static EMACS_INT bidi_cache_last_idx; /* slot of last cache hit */ |
| 270 | 306 | static EMACS_INT bidi_cache_start = 0; /* start of cache for this | |
| 307 | "stack" level */ | ||
| 308 | |||
| 309 | /* Reset the cache state to the empty state. We only reset the part | ||
| 310 | of the cache relevant to iteration of the current object. Previous | ||
| 311 | objects, which are pushed on the display iterator's stack, are left | ||
| 312 | intact. This is called when the cached information is no more | ||
| 313 | useful for the current iteration, e.g. when we were reseated to a | ||
| 314 | new position on the same object. */ | ||
| 271 | static inline void | 315 | static inline void |
| 272 | bidi_cache_reset (void) | 316 | bidi_cache_reset (void) |
| 273 | { | 317 | { |
| 274 | bidi_cache_idx = 0; | 318 | bidi_cache_idx = bidi_cache_start; |
| 275 | bidi_cache_last_idx = -1; | 319 | bidi_cache_last_idx = -1; |
| 276 | } | 320 | } |
| 277 | 321 | ||
| 322 | /* Shrink the cache to its minimal size. Called when we init the bidi | ||
| 323 | iterator for reordering a buffer or a string that does not come | ||
| 324 | from display properties, because that means all the previously | ||
| 325 | cached info is of no further use. */ | ||
| 278 | static inline void | 326 | static inline void |
| 279 | bidi_cache_shrink (void) | 327 | bidi_cache_shrink (void) |
| 280 | { | 328 | { |
| @@ -288,11 +336,11 @@ bidi_cache_shrink (void) | |||
| 288 | } | 336 | } |
| 289 | 337 | ||
| 290 | static inline void | 338 | static inline void |
| 291 | bidi_cache_fetch_state (int idx, struct bidi_it *bidi_it) | 339 | bidi_cache_fetch_state (EMACS_INT idx, struct bidi_it *bidi_it) |
| 292 | { | 340 | { |
| 293 | int current_scan_dir = bidi_it->scan_dir; | 341 | int current_scan_dir = bidi_it->scan_dir; |
| 294 | 342 | ||
| 295 | if (idx < 0 || idx >= bidi_cache_idx) | 343 | if (idx < bidi_cache_start || idx >= bidi_cache_idx) |
| 296 | abort (); | 344 | abort (); |
| 297 | 345 | ||
| 298 | bidi_copy_it (bidi_it, &bidi_cache[idx]); | 346 | bidi_copy_it (bidi_it, &bidi_cache[idx]); |
| @@ -304,13 +352,15 @@ bidi_cache_fetch_state (int idx, struct bidi_it *bidi_it) | |||
| 304 | level less or equal to LEVEL. if LEVEL is -1, disregard the | 352 | level less or equal to LEVEL. if LEVEL is -1, disregard the |
| 305 | resolved levels in cached states. DIR, if non-zero, means search | 353 | resolved levels in cached states. DIR, if non-zero, means search |
| 306 | in that direction from the last cache hit. */ | 354 | in that direction from the last cache hit. */ |
| 307 | static inline int | 355 | static inline EMACS_INT |
| 308 | bidi_cache_search (EMACS_INT charpos, int level, int dir) | 356 | bidi_cache_search (EMACS_INT charpos, int level, int dir) |
| 309 | { | 357 | { |
| 310 | int i, i_start; | 358 | EMACS_INT i, i_start; |
| 311 | 359 | ||
| 312 | if (bidi_cache_idx) | 360 | if (bidi_cache_idx > bidi_cache_start) |
| 313 | { | 361 | { |
| 362 | if (bidi_cache_last_idx == -1) | ||
| 363 | bidi_cache_last_idx = bidi_cache_idx - 1; | ||
| 314 | if (charpos < bidi_cache[bidi_cache_last_idx].charpos) | 364 | if (charpos < bidi_cache[bidi_cache_last_idx].charpos) |
| 315 | { | 365 | { |
| 316 | dir = -1; | 366 | dir = -1; |
| @@ -333,7 +383,7 @@ bidi_cache_search (EMACS_INT charpos, int level, int dir) | |||
| 333 | if (dir < 0) | 383 | if (dir < 0) |
| 334 | { | 384 | { |
| 335 | /* Linear search for now; FIXME! */ | 385 | /* Linear search for now; FIXME! */ |
| 336 | for (i = i_start; i >= 0; i--) | 386 | for (i = i_start; i >= bidi_cache_start; i--) |
| 337 | if (bidi_cache[i].charpos <= charpos | 387 | if (bidi_cache[i].charpos <= charpos |
| 338 | && charpos < bidi_cache[i].charpos + bidi_cache[i].nchars | 388 | && charpos < bidi_cache[i].charpos + bidi_cache[i].nchars |
| 339 | && (level == -1 || bidi_cache[i].resolved_level <= level)) | 389 | && (level == -1 || bidi_cache[i].resolved_level <= level)) |
| @@ -355,8 +405,9 @@ bidi_cache_search (EMACS_INT charpos, int level, int dir) | |||
| 355 | /* Find a cached state where the resolved level changes to a value | 405 | /* Find a cached state where the resolved level changes to a value |
| 356 | that is lower than LEVEL, and return its cache slot index. DIR is | 406 | that is lower than LEVEL, and return its cache slot index. DIR is |
| 357 | the direction to search, starting with the last used cache slot. | 407 | the direction to search, starting with the last used cache slot. |
| 358 | BEFORE, if non-zero, means return the index of the slot that is | 408 | If DIR is zero, we search backwards from the last occupied cache |
| 359 | ``before'' the level change in the search direction. That is, | 409 | slot. BEFORE, if non-zero, means return the index of the slot that |
| 410 | is ``before'' the level change in the search direction. That is, | ||
| 360 | given the cached levels like this: | 411 | given the cached levels like this: |
| 361 | 412 | ||
| 362 | 1122333442211 | 413 | 1122333442211 |
| @@ -366,14 +417,16 @@ bidi_cache_search (EMACS_INT charpos, int level, int dir) | |||
| 366 | C, searching backwards (DIR = -1) for LEVEL = 2 will return the | 417 | C, searching backwards (DIR = -1) for LEVEL = 2 will return the |
| 367 | index of slot B or A, depending whether BEFORE is, respectively, | 418 | index of slot B or A, depending whether BEFORE is, respectively, |
| 368 | non-zero or zero. */ | 419 | non-zero or zero. */ |
| 369 | static int | 420 | static EMACS_INT |
| 370 | bidi_cache_find_level_change (int level, int dir, int before) | 421 | bidi_cache_find_level_change (int level, int dir, int before) |
| 371 | { | 422 | { |
| 372 | if (bidi_cache_idx) | 423 | if (bidi_cache_idx) |
| 373 | { | 424 | { |
| 374 | int i = dir ? bidi_cache_last_idx : bidi_cache_idx - 1; | 425 | EMACS_INT i = dir ? bidi_cache_last_idx : bidi_cache_idx - 1; |
| 375 | int incr = before ? 1 : 0; | 426 | int incr = before ? 1 : 0; |
| 376 | 427 | ||
| 428 | xassert (!dir || bidi_cache_last_idx >= 0); | ||
| 429 | |||
| 377 | if (!dir) | 430 | if (!dir) |
| 378 | dir = -1; | 431 | dir = -1; |
| 379 | else if (!incr) | 432 | else if (!incr) |
| @@ -381,7 +434,7 @@ bidi_cache_find_level_change (int level, int dir, int before) | |||
| 381 | 434 | ||
| 382 | if (dir < 0) | 435 | if (dir < 0) |
| 383 | { | 436 | { |
| 384 | while (i >= incr) | 437 | while (i >= bidi_cache_start + incr) |
| 385 | { | 438 | { |
| 386 | if (bidi_cache[i - incr].resolved_level >= 0 | 439 | if (bidi_cache[i - incr].resolved_level >= 0 |
| 387 | && bidi_cache[i - incr].resolved_level < level) | 440 | && bidi_cache[i - incr].resolved_level < level) |
| @@ -405,9 +458,22 @@ bidi_cache_find_level_change (int level, int dir, int before) | |||
| 405 | } | 458 | } |
| 406 | 459 | ||
| 407 | static inline void | 460 | static inline void |
| 461 | bidi_cache_ensure_space (EMACS_INT idx) | ||
| 462 | { | ||
| 463 | /* Enlarge the cache as needed. */ | ||
| 464 | if (idx >= bidi_cache_size) | ||
| 465 | { | ||
| 466 | while (idx >= bidi_cache_size) | ||
| 467 | bidi_cache_size += BIDI_CACHE_CHUNK; | ||
| 468 | bidi_cache = | ||
| 469 | (struct bidi_it *) xrealloc (bidi_cache, bidi_cache_size * elsz); | ||
| 470 | } | ||
| 471 | } | ||
| 472 | |||
| 473 | static inline void | ||
| 408 | bidi_cache_iterator_state (struct bidi_it *bidi_it, int resolved) | 474 | bidi_cache_iterator_state (struct bidi_it *bidi_it, int resolved) |
| 409 | { | 475 | { |
| 410 | int idx; | 476 | EMACS_INT idx; |
| 411 | 477 | ||
| 412 | /* We should never cache on backward scans. */ | 478 | /* We should never cache on backward scans. */ |
| 413 | if (bidi_it->scan_dir == -1) | 479 | if (bidi_it->scan_dir == -1) |
| @@ -417,23 +483,17 @@ bidi_cache_iterator_state (struct bidi_it *bidi_it, int resolved) | |||
| 417 | if (idx < 0) | 483 | if (idx < 0) |
| 418 | { | 484 | { |
| 419 | idx = bidi_cache_idx; | 485 | idx = bidi_cache_idx; |
| 420 | /* Enlarge the cache as needed. */ | 486 | bidi_cache_ensure_space (idx); |
| 421 | if (idx >= bidi_cache_size) | ||
| 422 | { | ||
| 423 | bidi_cache_size += BIDI_CACHE_CHUNK; | ||
| 424 | bidi_cache = | ||
| 425 | (struct bidi_it *) xrealloc (bidi_cache, bidi_cache_size * elsz); | ||
| 426 | } | ||
| 427 | /* Character positions should correspond to cache positions 1:1. | 487 | /* Character positions should correspond to cache positions 1:1. |
| 428 | If we are outside the range of cached positions, the cache is | 488 | If we are outside the range of cached positions, the cache is |
| 429 | useless and must be reset. */ | 489 | useless and must be reset. */ |
| 430 | if (idx > 0 && | 490 | if (idx > bidi_cache_start && |
| 431 | (bidi_it->charpos > (bidi_cache[idx - 1].charpos | 491 | (bidi_it->charpos > (bidi_cache[idx - 1].charpos |
| 432 | + bidi_cache[idx - 1].nchars) | 492 | + bidi_cache[idx - 1].nchars) |
| 433 | || bidi_it->charpos < bidi_cache[0].charpos)) | 493 | || bidi_it->charpos < bidi_cache[bidi_cache_start].charpos)) |
| 434 | { | 494 | { |
| 435 | bidi_cache_reset (); | 495 | bidi_cache_reset (); |
| 436 | idx = 0; | 496 | idx = bidi_cache_start; |
| 437 | } | 497 | } |
| 438 | if (bidi_it->nchars <= 0) | 498 | if (bidi_it->nchars <= 0) |
| 439 | abort (); | 499 | abort (); |
| @@ -468,9 +528,9 @@ bidi_cache_iterator_state (struct bidi_it *bidi_it, int resolved) | |||
| 468 | static inline bidi_type_t | 528 | static inline bidi_type_t |
| 469 | bidi_cache_find (EMACS_INT charpos, int level, struct bidi_it *bidi_it) | 529 | bidi_cache_find (EMACS_INT charpos, int level, struct bidi_it *bidi_it) |
| 470 | { | 530 | { |
| 471 | int i = bidi_cache_search (charpos, level, bidi_it->scan_dir); | 531 | EMACS_INT i = bidi_cache_search (charpos, level, bidi_it->scan_dir); |
| 472 | 532 | ||
| 473 | if (i >= 0) | 533 | if (i >= bidi_cache_start) |
| 474 | { | 534 | { |
| 475 | bidi_dir_t current_scan_dir = bidi_it->scan_dir; | 535 | bidi_dir_t current_scan_dir = bidi_it->scan_dir; |
| 476 | 536 | ||
| @@ -488,69 +548,245 @@ bidi_cache_find (EMACS_INT charpos, int level, struct bidi_it *bidi_it) | |||
| 488 | static inline int | 548 | static inline int |
| 489 | bidi_peek_at_next_level (struct bidi_it *bidi_it) | 549 | bidi_peek_at_next_level (struct bidi_it *bidi_it) |
| 490 | { | 550 | { |
| 491 | if (bidi_cache_idx == 0 || bidi_cache_last_idx == -1) | 551 | if (bidi_cache_idx == bidi_cache_start || bidi_cache_last_idx == -1) |
| 492 | abort (); | 552 | abort (); |
| 493 | return bidi_cache[bidi_cache_last_idx + bidi_it->scan_dir].resolved_level; | 553 | return bidi_cache[bidi_cache_last_idx + bidi_it->scan_dir].resolved_level; |
| 494 | } | 554 | } |
| 495 | 555 | ||
| 496 | /* Check if buffer position CHARPOS/BYTEPOS is the end of a paragraph. | 556 | |
| 497 | Value is the non-negative length of the paragraph separator | 557 | /*********************************************************************** |
| 498 | following the buffer position, -1 if position is at the beginning | 558 | Pushing and popping the bidi iterator state |
| 499 | of a new paragraph, or -2 if position is neither at beginning nor | 559 | ***********************************************************************/ |
| 500 | at end of a paragraph. */ | 560 | /* 5-slot stack for saving the start of the previous level of the |
| 501 | static EMACS_INT | 561 | cache. xdisp.c maintains a 5-slot stack for its iterator state, |
| 502 | bidi_at_paragraph_end (EMACS_INT charpos, EMACS_INT bytepos) | 562 | and we need the same size of our stack. */ |
| 563 | static EMACS_INT bidi_cache_start_stack[IT_STACK_SIZE]; | ||
| 564 | static int bidi_cache_sp; | ||
| 565 | |||
| 566 | /* Push the bidi iterator state in preparation for reordering a | ||
| 567 | different object, e.g. display string found at certain buffer | ||
| 568 | position. Pushing the bidi iterator boils down to saving its | ||
| 569 | entire state on the cache and starting a new cache "stacked" on top | ||
| 570 | of the current cache. */ | ||
| 571 | void | ||
| 572 | bidi_push_it (struct bidi_it *bidi_it) | ||
| 503 | { | 573 | { |
| 504 | Lisp_Object sep_re; | 574 | /* Save the current iterator state in its entirety after the last |
| 505 | Lisp_Object start_re; | 575 | used cache slot. */ |
| 506 | EMACS_INT val; | 576 | bidi_cache_ensure_space (bidi_cache_idx); |
| 577 | memcpy (&bidi_cache[bidi_cache_idx++], bidi_it, sizeof (struct bidi_it)); | ||
| 507 | 578 | ||
| 508 | sep_re = paragraph_separate_re; | 579 | /* Push the current cache start onto the stack. */ |
| 509 | start_re = paragraph_start_re; | 580 | xassert (bidi_cache_sp < IT_STACK_SIZE); |
| 581 | bidi_cache_start_stack[bidi_cache_sp++] = bidi_cache_start; | ||
| 510 | 582 | ||
| 511 | val = fast_looking_at (sep_re, charpos, bytepos, ZV, ZV_BYTE, Qnil); | 583 | /* Start a new level of cache, and make it empty. */ |
| 512 | if (val < 0) | 584 | bidi_cache_start = bidi_cache_idx; |
| 585 | bidi_cache_last_idx = -1; | ||
| 586 | } | ||
| 587 | |||
| 588 | /* Restore the iterator state saved by bidi_push_it and return the | ||
| 589 | cache to the corresponding state. */ | ||
| 590 | void | ||
| 591 | bidi_pop_it (struct bidi_it *bidi_it) | ||
| 592 | { | ||
| 593 | if (bidi_cache_start <= 0) | ||
| 594 | abort (); | ||
| 595 | |||
| 596 | /* Reset the next free cache slot index to what it was before the | ||
| 597 | call to bidi_push_it. */ | ||
| 598 | bidi_cache_idx = bidi_cache_start - 1; | ||
| 599 | |||
| 600 | /* Restore the bidi iterator state saved in the cache. */ | ||
| 601 | memcpy (bidi_it, &bidi_cache[bidi_cache_idx], sizeof (struct bidi_it)); | ||
| 602 | |||
| 603 | /* Pop the previous cache start from the stack. */ | ||
| 604 | if (bidi_cache_sp <= 0) | ||
| 605 | abort (); | ||
| 606 | bidi_cache_start = bidi_cache_start_stack[--bidi_cache_sp]; | ||
| 607 | |||
| 608 | /* Invalidate the last-used cache slot data. */ | ||
| 609 | bidi_cache_last_idx = -1; | ||
| 610 | } | ||
| 611 | |||
| 612 | /* Stash away a copy of the cache and its control variables. */ | ||
| 613 | void * | ||
| 614 | bidi_shelve_cache (void) | ||
| 615 | { | ||
| 616 | unsigned char *databuf; | ||
| 617 | |||
| 618 | if (bidi_cache_idx == 0) | ||
| 619 | return NULL; | ||
| 620 | |||
| 621 | databuf = xmalloc (sizeof (bidi_cache_idx) | ||
| 622 | + bidi_cache_idx * sizeof (struct bidi_it) | ||
| 623 | + sizeof (bidi_cache_start_stack) | ||
| 624 | + sizeof (bidi_cache_sp) + sizeof (bidi_cache_start) | ||
| 625 | + sizeof (bidi_cache_last_idx)); | ||
| 626 | memcpy (databuf, &bidi_cache_idx, sizeof (bidi_cache_idx)); | ||
| 627 | memcpy (databuf + sizeof (bidi_cache_idx), | ||
| 628 | bidi_cache, bidi_cache_idx * sizeof (struct bidi_it)); | ||
| 629 | memcpy (databuf + sizeof (bidi_cache_idx) | ||
| 630 | + bidi_cache_idx * sizeof (struct bidi_it), | ||
| 631 | bidi_cache_start_stack, sizeof (bidi_cache_start_stack)); | ||
| 632 | memcpy (databuf + sizeof (bidi_cache_idx) | ||
| 633 | + bidi_cache_idx * sizeof (struct bidi_it) | ||
| 634 | + sizeof (bidi_cache_start_stack), | ||
| 635 | &bidi_cache_sp, sizeof (bidi_cache_sp)); | ||
| 636 | memcpy (databuf + sizeof (bidi_cache_idx) | ||
| 637 | + bidi_cache_idx * sizeof (struct bidi_it) | ||
| 638 | + sizeof (bidi_cache_start_stack) + sizeof (bidi_cache_sp), | ||
| 639 | &bidi_cache_start, sizeof (bidi_cache_start)); | ||
| 640 | memcpy (databuf + sizeof (bidi_cache_idx) | ||
| 641 | + bidi_cache_idx * sizeof (struct bidi_it) | ||
| 642 | + sizeof (bidi_cache_start_stack) + sizeof (bidi_cache_sp) | ||
| 643 | + sizeof (bidi_cache_start), | ||
| 644 | &bidi_cache_last_idx, sizeof (bidi_cache_last_idx)); | ||
| 645 | |||
| 646 | return databuf; | ||
| 647 | } | ||
| 648 | |||
| 649 | /* Restore the cache state from a copy stashed away by bidi_shelve_cache. */ | ||
| 650 | void | ||
| 651 | bidi_unshelve_cache (void *databuf) | ||
| 652 | { | ||
| 653 | unsigned char *p = databuf; | ||
| 654 | |||
| 655 | if (!p) | ||
| 513 | { | 656 | { |
| 514 | if (fast_looking_at (start_re, charpos, bytepos, ZV, ZV_BYTE, Qnil) >= 0) | 657 | /* A NULL pointer means an empty cache. */ |
| 515 | val = -1; | 658 | bidi_cache_start = 0; |
| 516 | else | 659 | bidi_cache_sp = 0; |
| 517 | val = -2; | 660 | bidi_cache_reset (); |
| 518 | } | 661 | } |
| 662 | else | ||
| 663 | { | ||
| 664 | memcpy (&bidi_cache_idx, p, sizeof (bidi_cache_idx)); | ||
| 665 | bidi_cache_ensure_space (bidi_cache_idx); | ||
| 666 | memcpy (bidi_cache, p + sizeof (bidi_cache_idx), | ||
| 667 | bidi_cache_idx * sizeof (struct bidi_it)); | ||
| 668 | memcpy (bidi_cache_start_stack, | ||
| 669 | p + sizeof (bidi_cache_idx) | ||
| 670 | + bidi_cache_idx * sizeof (struct bidi_it), | ||
| 671 | sizeof (bidi_cache_start_stack)); | ||
| 672 | memcpy (&bidi_cache_sp, | ||
| 673 | p + sizeof (bidi_cache_idx) | ||
| 674 | + bidi_cache_idx * sizeof (struct bidi_it) | ||
| 675 | + sizeof (bidi_cache_start_stack), | ||
| 676 | sizeof (bidi_cache_sp)); | ||
| 677 | memcpy (&bidi_cache_start, | ||
| 678 | p + sizeof (bidi_cache_idx) | ||
| 679 | + bidi_cache_idx * sizeof (struct bidi_it) | ||
| 680 | + sizeof (bidi_cache_start_stack) + sizeof (bidi_cache_sp), | ||
| 681 | sizeof (bidi_cache_start)); | ||
| 682 | memcpy (&bidi_cache_last_idx, | ||
| 683 | p + sizeof (bidi_cache_idx) | ||
| 684 | + bidi_cache_idx * sizeof (struct bidi_it) | ||
| 685 | + sizeof (bidi_cache_start_stack) + sizeof (bidi_cache_sp) | ||
| 686 | + sizeof (bidi_cache_start), | ||
| 687 | sizeof (bidi_cache_last_idx)); | ||
| 688 | |||
| 689 | xfree (p); | ||
| 690 | } | ||
| 691 | } | ||
| 519 | 692 | ||
| 520 | return val; | 693 | |
| 694 | /*********************************************************************** | ||
| 695 | Initialization | ||
| 696 | ***********************************************************************/ | ||
| 697 | static void | ||
| 698 | bidi_initialize (void) | ||
| 699 | { | ||
| 700 | |||
| 701 | #include "biditype.h" | ||
| 702 | #include "bidimirror.h" | ||
| 703 | |||
| 704 | int i; | ||
| 705 | |||
| 706 | bidi_type_table = Fmake_char_table (Qnil, make_number (STRONG_L)); | ||
| 707 | staticpro (&bidi_type_table); | ||
| 708 | |||
| 709 | for (i = 0; i < sizeof bidi_type / sizeof bidi_type[0]; i++) | ||
| 710 | char_table_set_range (bidi_type_table, bidi_type[i].from, bidi_type[i].to, | ||
| 711 | make_number (bidi_type[i].type)); | ||
| 712 | |||
| 713 | bidi_mirror_table = Fmake_char_table (Qnil, Qnil); | ||
| 714 | staticpro (&bidi_mirror_table); | ||
| 715 | |||
| 716 | for (i = 0; i < sizeof bidi_mirror / sizeof bidi_mirror[0]; i++) | ||
| 717 | char_table_set (bidi_mirror_table, bidi_mirror[i].from, | ||
| 718 | make_number (bidi_mirror[i].to)); | ||
| 719 | |||
| 720 | Qparagraph_start = intern ("paragraph-start"); | ||
| 721 | staticpro (&Qparagraph_start); | ||
| 722 | paragraph_start_re = Fsymbol_value (Qparagraph_start); | ||
| 723 | if (!STRINGP (paragraph_start_re)) | ||
| 724 | paragraph_start_re = build_string ("\f\\|[ \t]*$"); | ||
| 725 | staticpro (¶graph_start_re); | ||
| 726 | Qparagraph_separate = intern ("paragraph-separate"); | ||
| 727 | staticpro (&Qparagraph_separate); | ||
| 728 | paragraph_separate_re = Fsymbol_value (Qparagraph_separate); | ||
| 729 | if (!STRINGP (paragraph_separate_re)) | ||
| 730 | paragraph_separate_re = build_string ("[ \t\f]*$"); | ||
| 731 | staticpro (¶graph_separate_re); | ||
| 732 | |||
| 733 | bidi_cache_sp = 0; | ||
| 734 | |||
| 735 | bidi_initialized = 1; | ||
| 521 | } | 736 | } |
| 522 | 737 | ||
| 523 | /* Determine the start-of-run (sor) directional type given the two | 738 | /* Do whatever UAX#9 clause X8 says should be done at paragraph's |
| 524 | embedding levels on either side of the run boundary. Also, update | 739 | end. */ |
| 525 | the saved info about previously seen characters, since that info is | ||
| 526 | generally valid for a single level run. */ | ||
| 527 | static inline void | 740 | static inline void |
| 528 | bidi_set_sor_type (struct bidi_it *bidi_it, int level_before, int level_after) | 741 | bidi_set_paragraph_end (struct bidi_it *bidi_it) |
| 529 | { | 742 | { |
| 530 | int higher_level = level_before > level_after ? level_before : level_after; | 743 | bidi_it->invalid_levels = 0; |
| 531 | 744 | bidi_it->invalid_rl_levels = -1; | |
| 532 | /* The prev_was_pdf gork is required for when we have several PDFs | 745 | bidi_it->stack_idx = 0; |
| 533 | in a row. In that case, we want to compute the sor type for the | 746 | bidi_it->resolved_level = bidi_it->level_stack[0].level; |
| 534 | next level run only once: when we see the first PDF. That's | 747 | } |
| 535 | because the sor type depends only on the higher of the two levels | ||
| 536 | that we find on the two sides of the level boundary (see UAX#9, | ||
| 537 | clause X10), and so we don't need to know the final embedding | ||
| 538 | level to which we descend after processing all the PDFs. */ | ||
| 539 | if (!bidi_it->prev_was_pdf || level_before < level_after) | ||
| 540 | /* FIXME: should the default sor direction be user selectable? */ | ||
| 541 | bidi_it->sor = (higher_level & 1) != 0 ? R2L : L2R; | ||
| 542 | if (level_before > level_after) | ||
| 543 | bidi_it->prev_was_pdf = 1; | ||
| 544 | 748 | ||
| 545 | bidi_it->prev.type = UNKNOWN_BT; | 749 | /* Initialize the bidi iterator from buffer/string position CHARPOS. */ |
| 750 | void | ||
| 751 | bidi_init_it (EMACS_INT charpos, EMACS_INT bytepos, int frame_window_p, | ||
| 752 | struct bidi_it *bidi_it) | ||
| 753 | { | ||
| 754 | if (! bidi_initialized) | ||
| 755 | bidi_initialize (); | ||
| 756 | if (charpos >= 0) | ||
| 757 | bidi_it->charpos = charpos; | ||
| 758 | if (bytepos >= 0) | ||
| 759 | bidi_it->bytepos = bytepos; | ||
| 760 | bidi_it->frame_window_p = frame_window_p; | ||
| 761 | bidi_it->nchars = -1; /* to be computed in bidi_resolve_explicit_1 */ | ||
| 762 | bidi_it->first_elt = 1; | ||
| 763 | bidi_set_paragraph_end (bidi_it); | ||
| 764 | bidi_it->new_paragraph = 1; | ||
| 765 | bidi_it->separator_limit = -1; | ||
| 766 | bidi_it->type = NEUTRAL_B; | ||
| 767 | bidi_it->type_after_w1 = NEUTRAL_B; | ||
| 768 | bidi_it->orig_type = NEUTRAL_B; | ||
| 769 | bidi_it->prev_was_pdf = 0; | ||
| 770 | bidi_it->prev.type = bidi_it->prev.type_after_w1 = | ||
| 771 | bidi_it->prev.orig_type = UNKNOWN_BT; | ||
| 546 | bidi_it->last_strong.type = bidi_it->last_strong.type_after_w1 = | 772 | bidi_it->last_strong.type = bidi_it->last_strong.type_after_w1 = |
| 547 | bidi_it->last_strong.orig_type = UNKNOWN_BT; | 773 | bidi_it->last_strong.orig_type = UNKNOWN_BT; |
| 548 | bidi_it->prev_for_neutral.type = bidi_it->sor == R2L ? STRONG_R : STRONG_L; | 774 | bidi_it->next_for_neutral.charpos = -1; |
| 549 | bidi_it->prev_for_neutral.charpos = bidi_it->charpos; | 775 | bidi_it->next_for_neutral.type = |
| 550 | bidi_it->prev_for_neutral.bytepos = bidi_it->bytepos; | 776 | bidi_it->next_for_neutral.type_after_w1 = |
| 551 | bidi_it->next_for_neutral.type = bidi_it->next_for_neutral.type_after_w1 = | ||
| 552 | bidi_it->next_for_neutral.orig_type = UNKNOWN_BT; | 777 | bidi_it->next_for_neutral.orig_type = UNKNOWN_BT; |
| 553 | bidi_it->ignore_bn_limit = 0; /* meaning it's unknown */ | 778 | bidi_it->prev_for_neutral.charpos = -1; |
| 779 | bidi_it->prev_for_neutral.type = | ||
| 780 | bidi_it->prev_for_neutral.type_after_w1 = | ||
| 781 | bidi_it->prev_for_neutral.orig_type = UNKNOWN_BT; | ||
| 782 | bidi_it->sor = L2R; /* FIXME: should it be user-selectable? */ | ||
| 783 | bidi_it->disp_pos = -1; /* invalid/unknown */ | ||
| 784 | /* We can only shrink the cache if we are at the bottom level of its | ||
| 785 | "stack". */ | ||
| 786 | if (bidi_cache_start == 0) | ||
| 787 | bidi_cache_shrink (); | ||
| 788 | else | ||
| 789 | bidi_cache_reset (); | ||
| 554 | } | 790 | } |
| 555 | 791 | ||
| 556 | /* Perform initializations for reordering a new line of bidi text. */ | 792 | /* Perform initializations for reordering a new line of bidi text. */ |
| @@ -571,6 +807,57 @@ bidi_line_init (struct bidi_it *bidi_it) | |||
| 571 | bidi_cache_reset (); | 807 | bidi_cache_reset (); |
| 572 | } | 808 | } |
| 573 | 809 | ||
| 810 | |||
| 811 | /*********************************************************************** | ||
| 812 | Fetching characters | ||
| 813 | ***********************************************************************/ | ||
| 814 | |||
| 815 | /* Count bytes in string S between BEG/BEGBYTE and END. BEG and END | ||
| 816 | are zero-based character positions in S, BEGBYTE is byte position | ||
| 817 | corresponding to BEG. UNIBYTE, if non-zero, means S is a unibyte | ||
| 818 | string. */ | ||
| 819 | static inline EMACS_INT | ||
| 820 | bidi_count_bytes (const unsigned char *s, const EMACS_INT beg, | ||
| 821 | const EMACS_INT begbyte, const EMACS_INT end, int unibyte) | ||
| 822 | { | ||
| 823 | EMACS_INT pos = beg; | ||
| 824 | const unsigned char *p = s + begbyte, *start = p; | ||
| 825 | |||
| 826 | if (unibyte) | ||
| 827 | p = s + end; | ||
| 828 | else | ||
| 829 | { | ||
| 830 | if (!CHAR_HEAD_P (*p)) | ||
| 831 | abort (); | ||
| 832 | |||
| 833 | while (pos < end) | ||
| 834 | { | ||
| 835 | p += BYTES_BY_CHAR_HEAD (*p); | ||
| 836 | pos++; | ||
| 837 | } | ||
| 838 | } | ||
| 839 | |||
| 840 | return p - start; | ||
| 841 | } | ||
| 842 | |||
| 843 | /* Fetch and returns the character at byte position BYTEPOS. If S is | ||
| 844 | non-NULL, fetch the character from string S; otherwise fetch the | ||
| 845 | character from the current buffer. UNIBYTE non-zero means S is a | ||
| 846 | unibyte string. */ | ||
| 847 | static inline int | ||
| 848 | bidi_char_at_pos (EMACS_INT bytepos, const unsigned char *s, int unibyte) | ||
| 849 | { | ||
| 850 | if (s) | ||
| 851 | { | ||
| 852 | if (unibyte) | ||
| 853 | return s[bytepos]; | ||
| 854 | else | ||
| 855 | return STRING_CHAR (s + bytepos); | ||
| 856 | } | ||
| 857 | else | ||
| 858 | return FETCH_MULTIBYTE_CHAR (bytepos); | ||
| 859 | } | ||
| 860 | |||
| 574 | /* Fetch and return the character at BYTEPOS/CHARPOS. If that | 861 | /* Fetch and return the character at BYTEPOS/CHARPOS. If that |
| 575 | character is covered by a display string, treat the entire run of | 862 | character is covered by a display string, treat the entire run of |
| 576 | covered characters as a single character u+FFFC, and return their | 863 | covered characters as a single character u+FFFC, and return their |
| @@ -578,26 +865,34 @@ bidi_line_init (struct bidi_it *bidi_it) | |||
| 578 | character position of the next display string, or -1 if not yet | 865 | character position of the next display string, or -1 if not yet |
| 579 | computed. When the next character is at or beyond that position, | 866 | computed. When the next character is at or beyond that position, |
| 580 | the function updates DISP_POS with the position of the next display | 867 | the function updates DISP_POS with the position of the next display |
| 581 | string. */ | 868 | string. STRING->s is the C string to iterate, or NULL if iterating |
| 869 | over a buffer or a Lisp string; in the latter case, STRING->lstring | ||
| 870 | is the Lisp string. */ | ||
| 582 | static inline int | 871 | static inline int |
| 583 | bidi_fetch_char (EMACS_INT bytepos, EMACS_INT charpos, EMACS_INT *disp_pos, | 872 | bidi_fetch_char (EMACS_INT bytepos, EMACS_INT charpos, EMACS_INT *disp_pos, |
| 873 | struct bidi_string_data *string, | ||
| 584 | int frame_window_p, EMACS_INT *ch_len, EMACS_INT *nchars) | 874 | int frame_window_p, EMACS_INT *ch_len, EMACS_INT *nchars) |
| 585 | { | 875 | { |
| 586 | int ch; | 876 | int ch; |
| 877 | EMACS_INT endpos = | ||
| 878 | (string->s || STRINGP (string->lstring)) ? string->schars : ZV; | ||
| 879 | struct text_pos pos; | ||
| 587 | 880 | ||
| 588 | /* FIXME: Support strings in addition to buffers. */ | ||
| 589 | /* If we got past the last known position of display string, compute | 881 | /* If we got past the last known position of display string, compute |
| 590 | the position of the next one. That position could be at BYTEPOS. */ | 882 | the position of the next one. That position could be at CHARPOS. */ |
| 591 | if (charpos < ZV && charpos > *disp_pos) | 883 | if (charpos < endpos && charpos > *disp_pos) |
| 592 | *disp_pos = compute_display_string_pos (charpos, frame_window_p); | 884 | { |
| 885 | SET_TEXT_POS (pos, charpos, bytepos); | ||
| 886 | *disp_pos = compute_display_string_pos (&pos, string, frame_window_p); | ||
| 887 | } | ||
| 593 | 888 | ||
| 594 | /* Fetch the character at BYTEPOS. */ | 889 | /* Fetch the character at BYTEPOS. */ |
| 595 | if (bytepos >= ZV_BYTE) | 890 | if (charpos >= endpos) |
| 596 | { | 891 | { |
| 597 | ch = BIDI_EOB; | 892 | ch = BIDI_EOB; |
| 598 | *ch_len = 1; | 893 | *ch_len = 1; |
| 599 | *nchars = 1; | 894 | *nchars = 1; |
| 600 | *disp_pos = ZV; | 895 | *disp_pos = endpos; |
| 601 | } | 896 | } |
| 602 | else if (charpos >= *disp_pos) | 897 | else if (charpos >= *disp_pos) |
| 603 | { | 898 | { |
| @@ -608,28 +903,105 @@ bidi_fetch_char (EMACS_INT bytepos, EMACS_INT charpos, EMACS_INT *disp_pos, | |||
| 608 | if (charpos > *disp_pos) | 903 | if (charpos > *disp_pos) |
| 609 | abort (); | 904 | abort (); |
| 610 | /* Return the Unicode Object Replacement Character to represent | 905 | /* Return the Unicode Object Replacement Character to represent |
| 611 | the entire run of characters covered by the display | 906 | the entire run of characters covered by the display string. */ |
| 612 | string. */ | ||
| 613 | ch = 0xFFFC; | 907 | ch = 0xFFFC; |
| 614 | disp_end_pos = compute_display_string_end (*disp_pos); | 908 | disp_end_pos = compute_display_string_end (*disp_pos, string); |
| 615 | *nchars = disp_end_pos - *disp_pos; | 909 | *nchars = disp_end_pos - *disp_pos; |
| 616 | *ch_len = CHAR_TO_BYTE (disp_end_pos) - bytepos; | 910 | if (*nchars <= 0) |
| 911 | abort (); | ||
| 912 | if (string->s) | ||
| 913 | *ch_len = bidi_count_bytes (string->s, *disp_pos, bytepos, | ||
| 914 | disp_end_pos, string->unibyte); | ||
| 915 | else if (STRINGP (string->lstring)) | ||
| 916 | *ch_len = bidi_count_bytes (SDATA (string->lstring), *disp_pos, | ||
| 917 | bytepos, disp_end_pos, string->unibyte); | ||
| 918 | else | ||
| 919 | *ch_len = CHAR_TO_BYTE (disp_end_pos) - bytepos; | ||
| 617 | } | 920 | } |
| 618 | else | 921 | else |
| 619 | { | 922 | { |
| 620 | ch = FETCH_MULTIBYTE_CHAR (bytepos); | 923 | if (string->s) |
| 924 | { | ||
| 925 | int len; | ||
| 926 | |||
| 927 | if (!string->unibyte) | ||
| 928 | { | ||
| 929 | ch = STRING_CHAR_AND_LENGTH (string->s + bytepos, len); | ||
| 930 | *ch_len = len; | ||
| 931 | } | ||
| 932 | else | ||
| 933 | { | ||
| 934 | ch = UNIBYTE_TO_CHAR (string->s[bytepos]); | ||
| 935 | *ch_len = 1; | ||
| 936 | } | ||
| 937 | } | ||
| 938 | else if (STRINGP (string->lstring)) | ||
| 939 | { | ||
| 940 | int len; | ||
| 941 | |||
| 942 | if (!string->unibyte) | ||
| 943 | { | ||
| 944 | ch = STRING_CHAR_AND_LENGTH (SDATA (string->lstring) + bytepos, | ||
| 945 | len); | ||
| 946 | *ch_len = len; | ||
| 947 | } | ||
| 948 | else | ||
| 949 | { | ||
| 950 | ch = UNIBYTE_TO_CHAR (SREF (string->lstring, bytepos)); | ||
| 951 | *ch_len = 1; | ||
| 952 | } | ||
| 953 | } | ||
| 954 | else | ||
| 955 | { | ||
| 956 | ch = FETCH_MULTIBYTE_CHAR (bytepos); | ||
| 957 | *ch_len = CHAR_BYTES (ch); | ||
| 958 | } | ||
| 621 | *nchars = 1; | 959 | *nchars = 1; |
| 622 | *ch_len = CHAR_BYTES (ch); | ||
| 623 | } | 960 | } |
| 624 | 961 | ||
| 625 | /* If we just entered a run of characters covered by a display | 962 | /* If we just entered a run of characters covered by a display |
| 626 | string, compute the position of the next display string. */ | 963 | string, compute the position of the next display string. */ |
| 627 | if (charpos + *nchars <= ZV && charpos + *nchars > *disp_pos) | 964 | if (charpos + *nchars <= endpos && charpos + *nchars > *disp_pos) |
| 628 | *disp_pos = compute_display_string_pos (charpos + *nchars, frame_window_p); | 965 | { |
| 966 | SET_TEXT_POS (pos, charpos + *nchars, bytepos + *ch_len); | ||
| 967 | *disp_pos = compute_display_string_pos (&pos, string, frame_window_p); | ||
| 968 | } | ||
| 629 | 969 | ||
| 630 | return ch; | 970 | return ch; |
| 631 | } | 971 | } |
| 632 | 972 | ||
| 973 | |||
| 974 | /*********************************************************************** | ||
| 975 | Determining paragraph direction | ||
| 976 | ***********************************************************************/ | ||
| 977 | |||
| 978 | /* Check if buffer position CHARPOS/BYTEPOS is the end of a paragraph. | ||
| 979 | Value is the non-negative length of the paragraph separator | ||
| 980 | following the buffer position, -1 if position is at the beginning | ||
| 981 | of a new paragraph, or -2 if position is neither at beginning nor | ||
| 982 | at end of a paragraph. */ | ||
| 983 | static EMACS_INT | ||
| 984 | bidi_at_paragraph_end (EMACS_INT charpos, EMACS_INT bytepos) | ||
| 985 | { | ||
| 986 | Lisp_Object sep_re; | ||
| 987 | Lisp_Object start_re; | ||
| 988 | EMACS_INT val; | ||
| 989 | |||
| 990 | sep_re = paragraph_separate_re; | ||
| 991 | start_re = paragraph_start_re; | ||
| 992 | |||
| 993 | val = fast_looking_at (sep_re, charpos, bytepos, ZV, ZV_BYTE, Qnil); | ||
| 994 | if (val < 0) | ||
| 995 | { | ||
| 996 | if (fast_looking_at (start_re, charpos, bytepos, ZV, ZV_BYTE, Qnil) >= 0) | ||
| 997 | val = -1; | ||
| 998 | else | ||
| 999 | val = -2; | ||
| 1000 | } | ||
| 1001 | |||
| 1002 | return val; | ||
| 1003 | } | ||
| 1004 | |||
| 633 | /* Find the beginning of this paragraph by looking back in the buffer. | 1005 | /* Find the beginning of this paragraph by looking back in the buffer. |
| 634 | Value is the byte position of the paragraph's beginning. */ | 1006 | Value is the byte position of the paragraph's beginning. */ |
| 635 | static EMACS_INT | 1007 | static EMACS_INT |
| @@ -670,13 +1042,19 @@ void | |||
| 670 | bidi_paragraph_init (bidi_dir_t dir, struct bidi_it *bidi_it, int no_default_p) | 1042 | bidi_paragraph_init (bidi_dir_t dir, struct bidi_it *bidi_it, int no_default_p) |
| 671 | { | 1043 | { |
| 672 | EMACS_INT bytepos = bidi_it->bytepos; | 1044 | EMACS_INT bytepos = bidi_it->bytepos; |
| 1045 | int string_p = bidi_it->string.s != NULL || STRINGP (bidi_it->string.lstring); | ||
| 673 | EMACS_INT pstartbyte; | 1046 | EMACS_INT pstartbyte; |
| 1047 | /* Note that begbyte is a byte position, while end is a character | ||
| 1048 | position. Yes, this is ugly, but we are trying to avoid costly | ||
| 1049 | calls to BYTE_TO_CHAR and its ilk. */ | ||
| 1050 | EMACS_INT begbyte = string_p ? 0 : BEGV_BYTE; | ||
| 1051 | EMACS_INT end = string_p ? bidi_it->string.schars : ZV; | ||
| 674 | 1052 | ||
| 675 | /* Special case for an empty buffer. */ | 1053 | /* Special case for an empty buffer. */ |
| 676 | if (bytepos == BEGV_BYTE && bytepos == ZV_BYTE) | 1054 | if (bytepos == begbyte && bidi_it->charpos == end) |
| 677 | dir = L2R; | 1055 | dir = L2R; |
| 678 | /* We should never be called at EOB or before BEGV. */ | 1056 | /* We should never be called at EOB or before BEGV. */ |
| 679 | else if (bytepos >= ZV_BYTE || bytepos < BEGV_BYTE) | 1057 | else if (bidi_it->charpos >= end || bytepos < begbyte) |
| 680 | abort (); | 1058 | abort (); |
| 681 | 1059 | ||
| 682 | if (dir == L2R) | 1060 | if (dir == L2R) |
| @@ -695,6 +1073,7 @@ bidi_paragraph_init (bidi_dir_t dir, struct bidi_it *bidi_it, int no_default_p) | |||
| 695 | EMACS_INT ch_len, nchars; | 1073 | EMACS_INT ch_len, nchars; |
| 696 | EMACS_INT pos, disp_pos = -1; | 1074 | EMACS_INT pos, disp_pos = -1; |
| 697 | bidi_type_t type; | 1075 | bidi_type_t type; |
| 1076 | const unsigned char *s; | ||
| 698 | 1077 | ||
| 699 | if (!bidi_initialized) | 1078 | if (!bidi_initialized) |
| 700 | bidi_initialize (); | 1079 | bidi_initialize (); |
| @@ -712,7 +1091,10 @@ bidi_paragraph_init (bidi_dir_t dir, struct bidi_it *bidi_it, int no_default_p) | |||
| 712 | we are potentially in a new paragraph that doesn't yet | 1091 | we are potentially in a new paragraph that doesn't yet |
| 713 | exist. */ | 1092 | exist. */ |
| 714 | pos = bidi_it->charpos; | 1093 | pos = bidi_it->charpos; |
| 715 | if (bytepos > BEGV_BYTE && FETCH_CHAR (bytepos) == '\n') | 1094 | s = STRINGP (bidi_it->string.lstring) ? |
| 1095 | SDATA (bidi_it->string.lstring) : bidi_it->string.s; | ||
| 1096 | if (bytepos > begbyte | ||
| 1097 | && bidi_char_at_pos (bytepos, s, bidi_it->string.unibyte) == '\n') | ||
| 716 | { | 1098 | { |
| 717 | bytepos++; | 1099 | bytepos++; |
| 718 | pos++; | 1100 | pos++; |
| @@ -720,17 +1102,25 @@ bidi_paragraph_init (bidi_dir_t dir, struct bidi_it *bidi_it, int no_default_p) | |||
| 720 | 1102 | ||
| 721 | /* We are either at the beginning of a paragraph or in the | 1103 | /* We are either at the beginning of a paragraph or in the |
| 722 | middle of it. Find where this paragraph starts. */ | 1104 | middle of it. Find where this paragraph starts. */ |
| 723 | pstartbyte = bidi_find_paragraph_start (pos, bytepos); | 1105 | if (string_p) |
| 1106 | { | ||
| 1107 | /* We don't support changes of paragraph direction inside a | ||
| 1108 | string. It is treated as a single paragraph. */ | ||
| 1109 | pstartbyte = 0; | ||
| 1110 | } | ||
| 1111 | else | ||
| 1112 | pstartbyte = bidi_find_paragraph_start (pos, bytepos); | ||
| 724 | bidi_it->separator_limit = -1; | 1113 | bidi_it->separator_limit = -1; |
| 725 | bidi_it->new_paragraph = 0; | 1114 | bidi_it->new_paragraph = 0; |
| 726 | 1115 | ||
| 727 | /* The following loop is run more than once only if NO_DEFAULT_P | 1116 | /* The following loop is run more than once only if NO_DEFAULT_P |
| 728 | is non-zero. */ | 1117 | is non-zero, and only if we are iterating on a buffer. */ |
| 729 | do { | 1118 | do { |
| 730 | bytepos = pstartbyte; | 1119 | bytepos = pstartbyte; |
| 731 | pos = BYTE_TO_CHAR (bytepos); | 1120 | if (!string_p) |
| 732 | ch = bidi_fetch_char (bytepos, pos, &disp_pos, bidi_it->frame_window_p, | 1121 | pos = BYTE_TO_CHAR (bytepos); |
| 733 | &ch_len, &nchars); | 1122 | ch = bidi_fetch_char (bytepos, pos, &disp_pos, &bidi_it->string, |
| 1123 | bidi_it->frame_window_p, &ch_len, &nchars); | ||
| 734 | type = bidi_get_type (ch, NEUTRAL_DIR); | 1124 | type = bidi_get_type (ch, NEUTRAL_DIR); |
| 735 | 1125 | ||
| 736 | for (pos += nchars, bytepos += ch_len; | 1126 | for (pos += nchars, bytepos += ch_len; |
| @@ -744,17 +1134,19 @@ bidi_paragraph_init (bidi_dir_t dir, struct bidi_it *bidi_it, int no_default_p) | |||
| 744 | || type == LRE || type == LRO)); | 1134 | || type == LRE || type == LRO)); |
| 745 | type = bidi_get_type (ch, NEUTRAL_DIR)) | 1135 | type = bidi_get_type (ch, NEUTRAL_DIR)) |
| 746 | { | 1136 | { |
| 747 | if (bytepos >= ZV_BYTE) | 1137 | if (pos >= end) |
| 748 | { | 1138 | { |
| 749 | /* Pretend there's a paragraph separator at end of | 1139 | /* Pretend there's a paragraph separator at end of |
| 750 | buffer. */ | 1140 | buffer/string. */ |
| 751 | type = NEUTRAL_B; | 1141 | type = NEUTRAL_B; |
| 752 | break; | 1142 | break; |
| 753 | } | 1143 | } |
| 754 | if (type == NEUTRAL_B && bidi_at_paragraph_end (pos, bytepos) >= -1) | 1144 | if (!string_p |
| 1145 | && type == NEUTRAL_B | ||
| 1146 | && bidi_at_paragraph_end (pos, bytepos) >= -1) | ||
| 755 | break; | 1147 | break; |
| 756 | /* Fetch next character and advance to get past it. */ | 1148 | /* Fetch next character and advance to get past it. */ |
| 757 | ch = bidi_fetch_char (bytepos, pos, &disp_pos, | 1149 | ch = bidi_fetch_char (bytepos, pos, &disp_pos, &bidi_it->string, |
| 758 | bidi_it->frame_window_p, &ch_len, &nchars); | 1150 | bidi_it->frame_window_p, &ch_len, &nchars); |
| 759 | pos += nchars; | 1151 | pos += nchars; |
| 760 | bytepos += ch_len; | 1152 | bytepos += ch_len; |
| @@ -763,7 +1155,8 @@ bidi_paragraph_init (bidi_dir_t dir, struct bidi_it *bidi_it, int no_default_p) | |||
| 763 | bidi_it->paragraph_dir = R2L; | 1155 | bidi_it->paragraph_dir = R2L; |
| 764 | else if (type == STRONG_L) | 1156 | else if (type == STRONG_L) |
| 765 | bidi_it->paragraph_dir = L2R; | 1157 | bidi_it->paragraph_dir = L2R; |
| 766 | if (no_default_p && bidi_it->paragraph_dir == NEUTRAL_DIR) | 1158 | if (!string_p |
| 1159 | && no_default_p && bidi_it->paragraph_dir == NEUTRAL_DIR) | ||
| 767 | { | 1160 | { |
| 768 | /* If this paragraph is at BEGV, default to L2R. */ | 1161 | /* If this paragraph is at BEGV, default to L2R. */ |
| 769 | if (pstartbyte == BEGV_BYTE) | 1162 | if (pstartbyte == BEGV_BYTE) |
| @@ -786,7 +1179,8 @@ bidi_paragraph_init (bidi_dir_t dir, struct bidi_it *bidi_it, int no_default_p) | |||
| 786 | pstartbyte = prevpbyte; | 1179 | pstartbyte = prevpbyte; |
| 787 | } | 1180 | } |
| 788 | } | 1181 | } |
| 789 | } while (no_default_p && bidi_it->paragraph_dir == NEUTRAL_DIR); | 1182 | } while (!string_p |
| 1183 | && no_default_p && bidi_it->paragraph_dir == NEUTRAL_DIR); | ||
| 790 | } | 1184 | } |
| 791 | else | 1185 | else |
| 792 | abort (); | 1186 | abort (); |
| @@ -804,110 +1198,11 @@ bidi_paragraph_init (bidi_dir_t dir, struct bidi_it *bidi_it, int no_default_p) | |||
| 804 | bidi_line_init (bidi_it); | 1198 | bidi_line_init (bidi_it); |
| 805 | } | 1199 | } |
| 806 | 1200 | ||
| 807 | /* Do whatever UAX#9 clause X8 says should be done at paragraph's | 1201 | |
| 808 | end. */ | 1202 | /*********************************************************************** |
| 809 | static inline void | 1203 | Resolving explicit and implicit levels. |
| 810 | bidi_set_paragraph_end (struct bidi_it *bidi_it) | 1204 | The rest of this file constitutes the core of the UBA implementation. |
| 811 | { | 1205 | ***********************************************************************/ |
| 812 | bidi_it->invalid_levels = 0; | ||
| 813 | bidi_it->invalid_rl_levels = -1; | ||
| 814 | bidi_it->stack_idx = 0; | ||
| 815 | bidi_it->resolved_level = bidi_it->level_stack[0].level; | ||
| 816 | } | ||
| 817 | |||
| 818 | /* Initialize the bidi iterator from buffer/string position CHARPOS. */ | ||
| 819 | void | ||
| 820 | bidi_init_it (EMACS_INT charpos, EMACS_INT bytepos, int frame_window_p, | ||
| 821 | struct bidi_it *bidi_it) | ||
| 822 | { | ||
| 823 | if (! bidi_initialized) | ||
| 824 | bidi_initialize (); | ||
| 825 | bidi_it->charpos = charpos; | ||
| 826 | bidi_it->bytepos = bytepos; | ||
| 827 | bidi_it->frame_window_p = frame_window_p; | ||
| 828 | bidi_it->nchars = -1; /* to be computed in bidi_resolve_explicit_1 */ | ||
| 829 | bidi_it->first_elt = 1; | ||
| 830 | bidi_set_paragraph_end (bidi_it); | ||
| 831 | bidi_it->new_paragraph = 1; | ||
| 832 | bidi_it->separator_limit = -1; | ||
| 833 | bidi_it->type = NEUTRAL_B; | ||
| 834 | bidi_it->type_after_w1 = NEUTRAL_B; | ||
| 835 | bidi_it->orig_type = NEUTRAL_B; | ||
| 836 | bidi_it->prev_was_pdf = 0; | ||
| 837 | bidi_it->prev.type = bidi_it->prev.type_after_w1 = | ||
| 838 | bidi_it->prev.orig_type = UNKNOWN_BT; | ||
| 839 | bidi_it->last_strong.type = bidi_it->last_strong.type_after_w1 = | ||
| 840 | bidi_it->last_strong.orig_type = UNKNOWN_BT; | ||
| 841 | bidi_it->next_for_neutral.charpos = -1; | ||
| 842 | bidi_it->next_for_neutral.type = | ||
| 843 | bidi_it->next_for_neutral.type_after_w1 = | ||
| 844 | bidi_it->next_for_neutral.orig_type = UNKNOWN_BT; | ||
| 845 | bidi_it->prev_for_neutral.charpos = -1; | ||
| 846 | bidi_it->prev_for_neutral.type = | ||
| 847 | bidi_it->prev_for_neutral.type_after_w1 = | ||
| 848 | bidi_it->prev_for_neutral.orig_type = UNKNOWN_BT; | ||
| 849 | bidi_it->sor = L2R; /* FIXME: should it be user-selectable? */ | ||
| 850 | bidi_it->disp_pos = -1; /* invalid/unknown */ | ||
| 851 | bidi_cache_shrink (); | ||
| 852 | } | ||
| 853 | |||
| 854 | /* Push the current embedding level and override status; reset the | ||
| 855 | current level to LEVEL and the current override status to OVERRIDE. */ | ||
| 856 | static inline void | ||
| 857 | bidi_push_embedding_level (struct bidi_it *bidi_it, | ||
| 858 | int level, bidi_dir_t override) | ||
| 859 | { | ||
| 860 | bidi_it->stack_idx++; | ||
| 861 | if (bidi_it->stack_idx >= BIDI_MAXLEVEL) | ||
| 862 | abort (); | ||
| 863 | bidi_it->level_stack[bidi_it->stack_idx].level = level; | ||
| 864 | bidi_it->level_stack[bidi_it->stack_idx].override = override; | ||
| 865 | } | ||
| 866 | |||
| 867 | /* Pop the embedding level and directional override status from the | ||
| 868 | stack, and return the new level. */ | ||
| 869 | static inline int | ||
| 870 | bidi_pop_embedding_level (struct bidi_it *bidi_it) | ||
| 871 | { | ||
| 872 | /* UAX#9 says to ignore invalid PDFs. */ | ||
| 873 | if (bidi_it->stack_idx > 0) | ||
| 874 | bidi_it->stack_idx--; | ||
| 875 | return bidi_it->level_stack[bidi_it->stack_idx].level; | ||
| 876 | } | ||
| 877 | |||
| 878 | /* Record in SAVED_INFO the information about the current character. */ | ||
| 879 | static inline void | ||
| 880 | bidi_remember_char (struct bidi_saved_info *saved_info, | ||
| 881 | struct bidi_it *bidi_it) | ||
| 882 | { | ||
| 883 | saved_info->charpos = bidi_it->charpos; | ||
| 884 | saved_info->bytepos = bidi_it->bytepos; | ||
| 885 | saved_info->type = bidi_it->type; | ||
| 886 | bidi_check_type (bidi_it->type); | ||
| 887 | saved_info->type_after_w1 = bidi_it->type_after_w1; | ||
| 888 | bidi_check_type (bidi_it->type_after_w1); | ||
| 889 | saved_info->orig_type = bidi_it->orig_type; | ||
| 890 | bidi_check_type (bidi_it->orig_type); | ||
| 891 | } | ||
| 892 | |||
| 893 | /* Resolve the type of a neutral character according to the type of | ||
| 894 | surrounding strong text and the current embedding level. */ | ||
| 895 | static inline bidi_type_t | ||
| 896 | bidi_resolve_neutral_1 (bidi_type_t prev_type, bidi_type_t next_type, int lev) | ||
| 897 | { | ||
| 898 | /* N1: European and Arabic numbers are treated as though they were R. */ | ||
| 899 | if (next_type == WEAK_EN || next_type == WEAK_AN) | ||
| 900 | next_type = STRONG_R; | ||
| 901 | if (prev_type == WEAK_EN || prev_type == WEAK_AN) | ||
| 902 | prev_type = STRONG_R; | ||
| 903 | |||
| 904 | if (next_type == prev_type) /* N1 */ | ||
| 905 | return next_type; | ||
| 906 | else if ((lev & 1) == 0) /* N2 */ | ||
| 907 | return STRONG_L; | ||
| 908 | else | ||
| 909 | return STRONG_R; | ||
| 910 | } | ||
| 911 | 1206 | ||
| 912 | static inline int | 1207 | static inline int |
| 913 | bidi_explicit_dir_char (int ch) | 1208 | bidi_explicit_dir_char (int ch) |
| @@ -934,19 +1229,35 @@ bidi_resolve_explicit_1 (struct bidi_it *bidi_it) | |||
| 934 | int current_level; | 1229 | int current_level; |
| 935 | int new_level; | 1230 | int new_level; |
| 936 | bidi_dir_t override; | 1231 | bidi_dir_t override; |
| 1232 | int string_p = bidi_it->string.s != NULL || STRINGP (bidi_it->string.lstring); | ||
| 937 | 1233 | ||
| 938 | /* If reseat()'ed, don't advance, so as to start iteration from the | 1234 | /* If reseat()'ed, don't advance, so as to start iteration from the |
| 939 | position where we were reseated. bidi_it->bytepos can be less | 1235 | position where we were reseated. bidi_it->bytepos can be less |
| 940 | than BEGV_BYTE after reseat to BEGV. */ | 1236 | than BEGV_BYTE after reseat to BEGV. */ |
| 941 | if (bidi_it->bytepos < BEGV_BYTE | 1237 | if (bidi_it->bytepos < (string_p ? 0 : BEGV_BYTE) |
| 942 | || bidi_it->first_elt) | 1238 | || bidi_it->first_elt) |
| 943 | { | 1239 | { |
| 944 | bidi_it->first_elt = 0; | 1240 | bidi_it->first_elt = 0; |
| 945 | if (bidi_it->charpos < BEGV) | 1241 | if (string_p) |
| 946 | bidi_it->charpos = BEGV; | 1242 | { |
| 947 | bidi_it->bytepos = CHAR_TO_BYTE (bidi_it->charpos); | 1243 | const unsigned char *p = |
| 1244 | STRINGP (bidi_it->string.lstring) | ||
| 1245 | ? SDATA (bidi_it->string.lstring) : bidi_it->string.s; | ||
| 1246 | |||
| 1247 | if (bidi_it->charpos < 0) | ||
| 1248 | bidi_it->charpos = 0; | ||
| 1249 | bidi_it->bytepos = bidi_count_bytes (p, 0, 0, bidi_it->charpos, | ||
| 1250 | bidi_it->string.unibyte); | ||
| 1251 | } | ||
| 1252 | else | ||
| 1253 | { | ||
| 1254 | if (bidi_it->charpos < BEGV) | ||
| 1255 | bidi_it->charpos = BEGV; | ||
| 1256 | bidi_it->bytepos = CHAR_TO_BYTE (bidi_it->charpos); | ||
| 1257 | } | ||
| 948 | } | 1258 | } |
| 949 | else if (bidi_it->bytepos < ZV_BYTE) /* don't move at ZV */ | 1259 | /* Don't move at end of buffer/string. */ |
| 1260 | else if (bidi_it->charpos < (string_p ? bidi_it->string.schars : ZV)) | ||
| 950 | { | 1261 | { |
| 951 | /* Advance to the next character, skipping characters covered by | 1262 | /* Advance to the next character, skipping characters covered by |
| 952 | display strings (nchars > 1). */ | 1263 | display strings (nchars > 1). */ |
| @@ -962,12 +1273,12 @@ bidi_resolve_explicit_1 (struct bidi_it *bidi_it) | |||
| 962 | override = bidi_it->level_stack[bidi_it->stack_idx].override; | 1273 | override = bidi_it->level_stack[bidi_it->stack_idx].override; |
| 963 | new_level = current_level; | 1274 | new_level = current_level; |
| 964 | 1275 | ||
| 965 | if (bidi_it->bytepos >= ZV_BYTE) | 1276 | if (bidi_it->charpos >= (string_p ? bidi_it->string.schars : ZV)) |
| 966 | { | 1277 | { |
| 967 | curchar = BIDI_EOB; | 1278 | curchar = BIDI_EOB; |
| 968 | bidi_it->ch_len = 1; | 1279 | bidi_it->ch_len = 1; |
| 969 | bidi_it->nchars = 1; | 1280 | bidi_it->nchars = 1; |
| 970 | bidi_it->disp_pos = ZV; | 1281 | bidi_it->disp_pos = (string_p ? bidi_it->string.schars : ZV); |
| 971 | } | 1282 | } |
| 972 | else | 1283 | else |
| 973 | { | 1284 | { |
| @@ -975,7 +1286,8 @@ bidi_resolve_explicit_1 (struct bidi_it *bidi_it) | |||
| 975 | display string, treat the entire run of covered characters as | 1286 | display string, treat the entire run of covered characters as |
| 976 | a single character u+FFFC. */ | 1287 | a single character u+FFFC. */ |
| 977 | curchar = bidi_fetch_char (bidi_it->bytepos, bidi_it->charpos, | 1288 | curchar = bidi_fetch_char (bidi_it->bytepos, bidi_it->charpos, |
| 978 | &bidi_it->disp_pos, bidi_it->frame_window_p, | 1289 | &bidi_it->disp_pos, &bidi_it->string, |
| 1290 | bidi_it->frame_window_p, | ||
| 979 | &bidi_it->ch_len, &bidi_it->nchars); | 1291 | &bidi_it->ch_len, &bidi_it->nchars); |
| 980 | } | 1292 | } |
| 981 | bidi_it->ch = curchar; | 1293 | bidi_it->ch = curchar; |
| @@ -1000,7 +1312,7 @@ bidi_resolve_explicit_1 (struct bidi_it *bidi_it) | |||
| 1000 | bidi_it->type_after_w1 = type; | 1312 | bidi_it->type_after_w1 = type; |
| 1001 | bidi_check_type (bidi_it->type_after_w1); | 1313 | bidi_check_type (bidi_it->type_after_w1); |
| 1002 | type = WEAK_BN; /* X9/Retaining */ | 1314 | type = WEAK_BN; /* X9/Retaining */ |
| 1003 | if (bidi_it->ignore_bn_limit <= 0) | 1315 | if (bidi_it->ignore_bn_limit <= -1) |
| 1004 | { | 1316 | { |
| 1005 | if (current_level <= BIDI_MAXLEVEL - 4) | 1317 | if (current_level <= BIDI_MAXLEVEL - 4) |
| 1006 | { | 1318 | { |
| @@ -1033,7 +1345,7 @@ bidi_resolve_explicit_1 (struct bidi_it *bidi_it) | |||
| 1033 | bidi_it->type_after_w1 = type; | 1345 | bidi_it->type_after_w1 = type; |
| 1034 | bidi_check_type (bidi_it->type_after_w1); | 1346 | bidi_check_type (bidi_it->type_after_w1); |
| 1035 | type = WEAK_BN; /* X9/Retaining */ | 1347 | type = WEAK_BN; /* X9/Retaining */ |
| 1036 | if (bidi_it->ignore_bn_limit <= 0) | 1348 | if (bidi_it->ignore_bn_limit <= -1) |
| 1037 | { | 1349 | { |
| 1038 | if (current_level <= BIDI_MAXLEVEL - 5) | 1350 | if (current_level <= BIDI_MAXLEVEL - 5) |
| 1039 | { | 1351 | { |
| @@ -1068,7 +1380,7 @@ bidi_resolve_explicit_1 (struct bidi_it *bidi_it) | |||
| 1068 | bidi_it->type_after_w1 = type; | 1380 | bidi_it->type_after_w1 = type; |
| 1069 | bidi_check_type (bidi_it->type_after_w1); | 1381 | bidi_check_type (bidi_it->type_after_w1); |
| 1070 | type = WEAK_BN; /* X9/Retaining */ | 1382 | type = WEAK_BN; /* X9/Retaining */ |
| 1071 | if (bidi_it->ignore_bn_limit <= 0) | 1383 | if (bidi_it->ignore_bn_limit <= -1) |
| 1072 | { | 1384 | { |
| 1073 | if (!bidi_it->invalid_rl_levels) | 1385 | if (!bidi_it->invalid_rl_levels) |
| 1074 | { | 1386 | { |
| @@ -1111,13 +1423,17 @@ bidi_resolve_explicit (struct bidi_it *bidi_it) | |||
| 1111 | { | 1423 | { |
| 1112 | int prev_level = bidi_it->level_stack[bidi_it->stack_idx].level; | 1424 | int prev_level = bidi_it->level_stack[bidi_it->stack_idx].level; |
| 1113 | int new_level = bidi_resolve_explicit_1 (bidi_it); | 1425 | int new_level = bidi_resolve_explicit_1 (bidi_it); |
| 1426 | EMACS_INT eob = bidi_it->string.s ? bidi_it->string.schars : ZV; | ||
| 1427 | const unsigned char *s = STRINGP (bidi_it->string.lstring) | ||
| 1428 | ? SDATA (bidi_it->string.lstring) : bidi_it->string.s; | ||
| 1114 | 1429 | ||
| 1115 | if (prev_level < new_level | 1430 | if (prev_level < new_level |
| 1116 | && bidi_it->type == WEAK_BN | 1431 | && bidi_it->type == WEAK_BN |
| 1117 | && bidi_it->ignore_bn_limit == 0 /* only if not already known */ | 1432 | && bidi_it->ignore_bn_limit == -1 /* only if not already known */ |
| 1118 | && bidi_it->bytepos < ZV_BYTE /* not already at EOB */ | 1433 | && bidi_it->charpos < eob /* not already at EOB */ |
| 1119 | && bidi_explicit_dir_char (FETCH_MULTIBYTE_CHAR (bidi_it->bytepos | 1434 | && bidi_explicit_dir_char (bidi_char_at_pos (bidi_it->bytepos |
| 1120 | + bidi_it->ch_len))) | 1435 | + bidi_it->ch_len, s, |
| 1436 | bidi_it->string.unibyte))) | ||
| 1121 | { | 1437 | { |
| 1122 | /* Avoid pushing and popping embedding levels if the level run | 1438 | /* Avoid pushing and popping embedding levels if the level run |
| 1123 | is empty, as this breaks level runs where it shouldn't. | 1439 | is empty, as this breaks level runs where it shouldn't. |
| @@ -1129,12 +1445,17 @@ bidi_resolve_explicit (struct bidi_it *bidi_it) | |||
| 1129 | 1445 | ||
| 1130 | bidi_copy_it (&saved_it, bidi_it); | 1446 | bidi_copy_it (&saved_it, bidi_it); |
| 1131 | 1447 | ||
| 1132 | while (bidi_explicit_dir_char (FETCH_MULTIBYTE_CHAR (bidi_it->bytepos | 1448 | while (bidi_explicit_dir_char (bidi_char_at_pos (bidi_it->bytepos |
| 1133 | + bidi_it->ch_len))) | 1449 | + bidi_it->ch_len, s, |
| 1450 | bidi_it->string.unibyte))) | ||
| 1134 | { | 1451 | { |
| 1135 | /* This advances to the next character, skipping any | 1452 | /* This advances to the next character, skipping any |
| 1136 | characters covered by display strings. */ | 1453 | characters covered by display strings. */ |
| 1137 | level = bidi_resolve_explicit_1 (bidi_it); | 1454 | level = bidi_resolve_explicit_1 (bidi_it); |
| 1455 | /* If string.lstring was relocated inside bidi_resolve_explicit_1, | ||
| 1456 | a pointer to its data is no longer valid. */ | ||
| 1457 | if (STRINGP (bidi_it->string.lstring)) | ||
| 1458 | s = SDATA (bidi_it->string.lstring); | ||
| 1138 | } | 1459 | } |
| 1139 | 1460 | ||
| 1140 | if (bidi_it->nchars <= 0) | 1461 | if (bidi_it->nchars <= 0) |
| @@ -1142,10 +1463,10 @@ bidi_resolve_explicit (struct bidi_it *bidi_it) | |||
| 1142 | if (level == prev_level) /* empty embedding */ | 1463 | if (level == prev_level) /* empty embedding */ |
| 1143 | saved_it.ignore_bn_limit = bidi_it->charpos + bidi_it->nchars; | 1464 | saved_it.ignore_bn_limit = bidi_it->charpos + bidi_it->nchars; |
| 1144 | else /* this embedding is non-empty */ | 1465 | else /* this embedding is non-empty */ |
| 1145 | saved_it.ignore_bn_limit = -1; | 1466 | saved_it.ignore_bn_limit = -2; |
| 1146 | 1467 | ||
| 1147 | bidi_copy_it (bidi_it, &saved_it); | 1468 | bidi_copy_it (bidi_it, &saved_it); |
| 1148 | if (bidi_it->ignore_bn_limit > 0) | 1469 | if (bidi_it->ignore_bn_limit > -1) |
| 1149 | { | 1470 | { |
| 1150 | /* We pushed a level, but we shouldn't have. Undo that. */ | 1471 | /* We pushed a level, but we shouldn't have. Undo that. */ |
| 1151 | if (!bidi_it->invalid_rl_levels) | 1472 | if (!bidi_it->invalid_rl_levels) |
| @@ -1188,6 +1509,9 @@ bidi_resolve_weak (struct bidi_it *bidi_it) | |||
| 1188 | int next_char; | 1509 | int next_char; |
| 1189 | bidi_type_t type_of_next; | 1510 | bidi_type_t type_of_next; |
| 1190 | struct bidi_it saved_it; | 1511 | struct bidi_it saved_it; |
| 1512 | EMACS_INT eob = | ||
| 1513 | (STRINGP (bidi_it->string.lstring) || bidi_it->string.s) | ||
| 1514 | ? bidi_it->string.schars : ZV; | ||
| 1191 | 1515 | ||
| 1192 | type = bidi_it->type; | 1516 | type = bidi_it->type; |
| 1193 | override = bidi_it->level_stack[bidi_it->stack_idx].override; | 1517 | override = bidi_it->level_stack[bidi_it->stack_idx].override; |
| @@ -1254,10 +1578,15 @@ bidi_resolve_weak (struct bidi_it *bidi_it) | |||
| 1254 | && bidi_it->prev.orig_type == WEAK_EN) | 1578 | && bidi_it->prev.orig_type == WEAK_EN) |
| 1255 | || bidi_it->prev.type_after_w1 == WEAK_AN))) | 1579 | || bidi_it->prev.type_after_w1 == WEAK_AN))) |
| 1256 | { | 1580 | { |
| 1581 | const unsigned char *s = | ||
| 1582 | STRINGP (bidi_it->string.lstring) | ||
| 1583 | ? SDATA (bidi_it->string.lstring) : bidi_it->string.s; | ||
| 1584 | |||
| 1257 | next_char = | 1585 | next_char = |
| 1258 | bidi_it->bytepos + bidi_it->ch_len >= ZV_BYTE | 1586 | bidi_it->charpos + bidi_it->nchars >= eob |
| 1259 | ? BIDI_EOB : FETCH_MULTIBYTE_CHAR (bidi_it->bytepos | 1587 | ? BIDI_EOB |
| 1260 | + bidi_it->ch_len); | 1588 | : bidi_char_at_pos (bidi_it->bytepos + bidi_it->ch_len, s, |
| 1589 | bidi_it->string.unibyte); | ||
| 1261 | type_of_next = bidi_get_type (next_char, override); | 1590 | type_of_next = bidi_get_type (next_char, override); |
| 1262 | 1591 | ||
| 1263 | if (type_of_next == WEAK_BN | 1592 | if (type_of_next == WEAK_BN |
| @@ -1306,13 +1635,17 @@ bidi_resolve_weak (struct bidi_it *bidi_it) | |||
| 1306 | else /* W5: ET/BN with EN after it. */ | 1635 | else /* W5: ET/BN with EN after it. */ |
| 1307 | { | 1636 | { |
| 1308 | EMACS_INT en_pos = bidi_it->charpos + bidi_it->nchars; | 1637 | EMACS_INT en_pos = bidi_it->charpos + bidi_it->nchars; |
| 1638 | const unsigned char *s = | ||
| 1639 | STRINGP (bidi_it->string.lstring) | ||
| 1640 | ? SDATA (bidi_it->string.lstring) : bidi_it->string.s; | ||
| 1309 | 1641 | ||
| 1310 | if (bidi_it->nchars <= 0) | 1642 | if (bidi_it->nchars <= 0) |
| 1311 | abort (); | 1643 | abort (); |
| 1312 | next_char = | 1644 | next_char = |
| 1313 | bidi_it->bytepos + bidi_it->ch_len >= ZV_BYTE | 1645 | bidi_it->charpos + bidi_it->nchars >= eob |
| 1314 | ? BIDI_EOB : FETCH_MULTIBYTE_CHAR (bidi_it->bytepos | 1646 | ? BIDI_EOB |
| 1315 | + bidi_it->ch_len); | 1647 | : bidi_char_at_pos (bidi_it->bytepos + bidi_it->ch_len, s, |
| 1648 | bidi_it->string.unibyte); | ||
| 1316 | type_of_next = bidi_get_type (next_char, override); | 1649 | type_of_next = bidi_get_type (next_char, override); |
| 1317 | 1650 | ||
| 1318 | if (type_of_next == WEAK_ET | 1651 | if (type_of_next == WEAK_ET |
| @@ -1373,6 +1706,25 @@ bidi_resolve_weak (struct bidi_it *bidi_it) | |||
| 1373 | return type; | 1706 | return type; |
| 1374 | } | 1707 | } |
| 1375 | 1708 | ||
| 1709 | /* Resolve the type of a neutral character according to the type of | ||
| 1710 | surrounding strong text and the current embedding level. */ | ||
| 1711 | static inline bidi_type_t | ||
| 1712 | bidi_resolve_neutral_1 (bidi_type_t prev_type, bidi_type_t next_type, int lev) | ||
| 1713 | { | ||
| 1714 | /* N1: European and Arabic numbers are treated as though they were R. */ | ||
| 1715 | if (next_type == WEAK_EN || next_type == WEAK_AN) | ||
| 1716 | next_type = STRONG_R; | ||
| 1717 | if (prev_type == WEAK_EN || prev_type == WEAK_AN) | ||
| 1718 | prev_type = STRONG_R; | ||
| 1719 | |||
| 1720 | if (next_type == prev_type) /* N1 */ | ||
| 1721 | return next_type; | ||
| 1722 | else if ((lev & 1) == 0) /* N2 */ | ||
| 1723 | return STRONG_L; | ||
| 1724 | else | ||
| 1725 | return STRONG_R; | ||
| 1726 | } | ||
| 1727 | |||
| 1376 | static bidi_type_t | 1728 | static bidi_type_t |
| 1377 | bidi_resolve_neutral (struct bidi_it *bidi_it) | 1729 | bidi_resolve_neutral (struct bidi_it *bidi_it) |
| 1378 | { | 1730 | { |
| @@ -1509,11 +1861,11 @@ bidi_type_of_next_char (struct bidi_it *bidi_it) | |||
| 1509 | 1861 | ||
| 1510 | /* Reset the limit until which to ignore BNs if we step out of the | 1862 | /* Reset the limit until which to ignore BNs if we step out of the |
| 1511 | area where we found only empty levels. */ | 1863 | area where we found only empty levels. */ |
| 1512 | if ((bidi_it->ignore_bn_limit > 0 | 1864 | if ((bidi_it->ignore_bn_limit > -1 |
| 1513 | && bidi_it->ignore_bn_limit <= bidi_it->charpos) | 1865 | && bidi_it->ignore_bn_limit <= bidi_it->charpos) |
| 1514 | || (bidi_it->ignore_bn_limit == -1 | 1866 | || (bidi_it->ignore_bn_limit == -2 |
| 1515 | && !bidi_explicit_dir_char (bidi_it->ch))) | 1867 | && !bidi_explicit_dir_char (bidi_it->ch))) |
| 1516 | bidi_it->ignore_bn_limit = 0; | 1868 | bidi_it->ignore_bn_limit = -1; |
| 1517 | 1869 | ||
| 1518 | type = bidi_resolve_neutral (bidi_it); | 1870 | type = bidi_resolve_neutral (bidi_it); |
| 1519 | 1871 | ||
| @@ -1530,12 +1882,16 @@ bidi_level_of_next_char (struct bidi_it *bidi_it) | |||
| 1530 | bidi_type_t type; | 1882 | bidi_type_t type; |
| 1531 | int level, prev_level = -1; | 1883 | int level, prev_level = -1; |
| 1532 | struct bidi_saved_info next_for_neutral; | 1884 | struct bidi_saved_info next_for_neutral; |
| 1533 | EMACS_INT next_char_pos; | 1885 | EMACS_INT next_char_pos = -2; |
| 1534 | 1886 | ||
| 1535 | if (bidi_it->scan_dir == 1) | 1887 | if (bidi_it->scan_dir == 1) |
| 1536 | { | 1888 | { |
| 1889 | EMACS_INT eob = | ||
| 1890 | (bidi_it->string.s || STRINGP (bidi_it->string.lstring)) | ||
| 1891 | ? bidi_it->string.schars : ZV; | ||
| 1892 | |||
| 1537 | /* There's no sense in trying to advance if we hit end of text. */ | 1893 | /* There's no sense in trying to advance if we hit end of text. */ |
| 1538 | if (bidi_it->bytepos >= ZV_BYTE) | 1894 | if (bidi_it->charpos >= eob) |
| 1539 | return bidi_it->resolved_level; | 1895 | return bidi_it->resolved_level; |
| 1540 | 1896 | ||
| 1541 | /* Record the info about the previous character. */ | 1897 | /* Record the info about the previous character. */ |
| @@ -1575,17 +1931,27 @@ bidi_level_of_next_char (struct bidi_it *bidi_it) | |||
| 1575 | /* Perhaps the character we want is already cached. If it is, the | 1931 | /* Perhaps the character we want is already cached. If it is, the |
| 1576 | call to bidi_cache_find below will return a type other than | 1932 | call to bidi_cache_find below will return a type other than |
| 1577 | UNKNOWN_BT. */ | 1933 | UNKNOWN_BT. */ |
| 1578 | if (bidi_cache_idx && !bidi_it->first_elt) | 1934 | if (bidi_cache_idx > bidi_cache_start && !bidi_it->first_elt) |
| 1579 | { | 1935 | { |
| 1936 | int bob = | ||
| 1937 | (bidi_it->string.s || STRINGP (bidi_it->string.lstring)) ? 0 : 1; | ||
| 1938 | |||
| 1580 | if (bidi_it->scan_dir > 0) | 1939 | if (bidi_it->scan_dir > 0) |
| 1581 | { | 1940 | { |
| 1582 | if (bidi_it->nchars <= 0) | 1941 | if (bidi_it->nchars <= 0) |
| 1583 | abort (); | 1942 | abort (); |
| 1584 | next_char_pos = bidi_it->charpos + bidi_it->nchars; | 1943 | next_char_pos = bidi_it->charpos + bidi_it->nchars; |
| 1585 | } | 1944 | } |
| 1586 | else | 1945 | else if (bidi_it->charpos >= bob) |
| 1946 | /* Implementation note: we allow next_char_pos to be as low as | ||
| 1947 | 0 for buffers or -1 for strings, and that is okay because | ||
| 1948 | that's the "position" of the sentinel iterator state we | ||
| 1949 | cached at the beginning of the iteration. */ | ||
| 1587 | next_char_pos = bidi_it->charpos - 1; | 1950 | next_char_pos = bidi_it->charpos - 1; |
| 1588 | type = bidi_cache_find (next_char_pos, -1, bidi_it); | 1951 | if (next_char_pos >= bob - 1) |
| 1952 | type = bidi_cache_find (next_char_pos, -1, bidi_it); | ||
| 1953 | else | ||
| 1954 | type = UNKNOWN_BT; | ||
| 1589 | } | 1955 | } |
| 1590 | else | 1956 | else |
| 1591 | type = UNKNOWN_BT; | 1957 | type = UNKNOWN_BT; |
| @@ -1652,13 +2018,14 @@ bidi_level_of_next_char (struct bidi_it *bidi_it) | |||
| 1652 | EMACS_INT cpos = bidi_it->charpos; | 2018 | EMACS_INT cpos = bidi_it->charpos; |
| 1653 | EMACS_INT disp_pos = bidi_it->disp_pos; | 2019 | EMACS_INT disp_pos = bidi_it->disp_pos; |
| 1654 | EMACS_INT nc = bidi_it->nchars; | 2020 | EMACS_INT nc = bidi_it->nchars; |
| 2021 | struct bidi_string_data bs = bidi_it->string; | ||
| 1655 | bidi_type_t chtype; | 2022 | bidi_type_t chtype; |
| 1656 | int fwp = bidi_it->frame_window_p; | 2023 | int fwp = bidi_it->frame_window_p; |
| 1657 | 2024 | ||
| 1658 | if (bidi_it->nchars <= 0) | 2025 | if (bidi_it->nchars <= 0) |
| 1659 | abort (); | 2026 | abort (); |
| 1660 | do { | 2027 | do { |
| 1661 | ch = bidi_fetch_char (bpos += clen, cpos += nc, &disp_pos, fwp, | 2028 | ch = bidi_fetch_char (bpos += clen, cpos += nc, &disp_pos, &bs, fwp, |
| 1662 | &clen, &nc); | 2029 | &clen, &nc); |
| 1663 | if (ch == '\n' || ch == BIDI_EOB /* || ch == LINESEP_CHAR */) | 2030 | if (ch == '\n' || ch == BIDI_EOB /* || ch == LINESEP_CHAR */) |
| 1664 | chtype = NEUTRAL_B; | 2031 | chtype = NEUTRAL_B; |
| @@ -1756,10 +2123,11 @@ static void | |||
| 1756 | bidi_find_other_level_edge (struct bidi_it *bidi_it, int level, int end_flag) | 2123 | bidi_find_other_level_edge (struct bidi_it *bidi_it, int level, int end_flag) |
| 1757 | { | 2124 | { |
| 1758 | int dir = end_flag ? -bidi_it->scan_dir : bidi_it->scan_dir; | 2125 | int dir = end_flag ? -bidi_it->scan_dir : bidi_it->scan_dir; |
| 1759 | int idx; | 2126 | EMACS_INT idx; |
| 1760 | 2127 | ||
| 1761 | /* Try the cache first. */ | 2128 | /* Try the cache first. */ |
| 1762 | if ((idx = bidi_cache_find_level_change (level, dir, end_flag)) >= 0) | 2129 | if ((idx = bidi_cache_find_level_change (level, dir, end_flag)) |
| 2130 | >= bidi_cache_start) | ||
| 1763 | bidi_cache_fetch_state (idx, bidi_it); | 2131 | bidi_cache_fetch_state (idx, bidi_it); |
| 1764 | else | 2132 | else |
| 1765 | { | 2133 | { |
| @@ -1781,12 +2149,21 @@ bidi_move_to_visually_next (struct bidi_it *bidi_it) | |||
| 1781 | { | 2149 | { |
| 1782 | int old_level, new_level, next_level; | 2150 | int old_level, new_level, next_level; |
| 1783 | struct bidi_it sentinel; | 2151 | struct bidi_it sentinel; |
| 2152 | struct gcpro gcpro1; | ||
| 2153 | |||
| 2154 | if (bidi_it->charpos < 0 || bidi_it->bytepos < 0) | ||
| 2155 | abort (); | ||
| 1784 | 2156 | ||
| 1785 | if (bidi_it->scan_dir == 0) | 2157 | if (bidi_it->scan_dir == 0) |
| 1786 | { | 2158 | { |
| 1787 | bidi_it->scan_dir = 1; /* default to logical order */ | 2159 | bidi_it->scan_dir = 1; /* default to logical order */ |
| 1788 | } | 2160 | } |
| 1789 | 2161 | ||
| 2162 | /* The code below can call eval, and thus cause GC. If we are | ||
| 2163 | iterating a Lisp string, make sure it won't be GCed. */ | ||
| 2164 | if (STRINGP (bidi_it->string.lstring)) | ||
| 2165 | GCPRO1 (bidi_it->string.lstring); | ||
| 2166 | |||
| 1790 | /* If we just passed a newline, initialize for the next line. */ | 2167 | /* If we just passed a newline, initialize for the next line. */ |
| 1791 | if (!bidi_it->first_elt && bidi_it->orig_type == NEUTRAL_B) | 2168 | if (!bidi_it->first_elt && bidi_it->orig_type == NEUTRAL_B) |
| 1792 | bidi_line_init (bidi_it); | 2169 | bidi_line_init (bidi_it); |
| @@ -1794,7 +2171,7 @@ bidi_move_to_visually_next (struct bidi_it *bidi_it) | |||
| 1794 | /* Prepare the sentinel iterator state, and cache it. When we bump | 2171 | /* Prepare the sentinel iterator state, and cache it. When we bump |
| 1795 | into it, scanning backwards, we'll know that the last non-base | 2172 | into it, scanning backwards, we'll know that the last non-base |
| 1796 | level is exhausted. */ | 2173 | level is exhausted. */ |
| 1797 | if (bidi_cache_idx == 0) | 2174 | if (bidi_cache_idx == bidi_cache_start) |
| 1798 | { | 2175 | { |
| 1799 | bidi_copy_it (&sentinel, bidi_it); | 2176 | bidi_copy_it (&sentinel, bidi_it); |
| 1800 | if (bidi_it->first_elt) | 2177 | if (bidi_it->first_elt) |
| @@ -1869,26 +2246,34 @@ bidi_move_to_visually_next (struct bidi_it *bidi_it) | |||
| 1869 | reordering, whereas we _must_ know the paragraph base direction | 2246 | reordering, whereas we _must_ know the paragraph base direction |
| 1870 | _before_ we process the paragraph's text, since the base | 2247 | _before_ we process the paragraph's text, since the base |
| 1871 | direction affects the reordering. */ | 2248 | direction affects the reordering. */ |
| 1872 | if (bidi_it->scan_dir == 1 | 2249 | if (bidi_it->scan_dir == 1 && bidi_it->orig_type == NEUTRAL_B) |
| 1873 | && bidi_it->orig_type == NEUTRAL_B | ||
| 1874 | && bidi_it->bytepos < ZV_BYTE) | ||
| 1875 | { | 2250 | { |
| 1876 | EMACS_INT sep_len = | 2251 | /* The paragraph direction of the entire string, once |
| 1877 | bidi_at_paragraph_end (bidi_it->charpos + bidi_it->nchars, | 2252 | determined, is in effect for the entire string. Setting the |
| 1878 | bidi_it->bytepos + bidi_it->ch_len); | 2253 | separator limit to the end of the string prevents |
| 1879 | if (bidi_it->nchars <= 0) | 2254 | bidi_paragraph_init from being called automatically on this |
| 1880 | abort (); | 2255 | string. */ |
| 1881 | if (sep_len >= 0) | 2256 | if (bidi_it->string.s || STRINGP (bidi_it->string.lstring)) |
| 2257 | bidi_it->separator_limit = bidi_it->string.schars; | ||
| 2258 | else if (bidi_it->bytepos < ZV_BYTE) | ||
| 1882 | { | 2259 | { |
| 1883 | bidi_it->new_paragraph = 1; | 2260 | EMACS_INT sep_len = |
| 1884 | /* Record the buffer position of the last character of the | 2261 | bidi_at_paragraph_end (bidi_it->charpos + bidi_it->nchars, |
| 1885 | paragraph separator. */ | 2262 | bidi_it->bytepos + bidi_it->ch_len); |
| 1886 | bidi_it->separator_limit = | 2263 | if (bidi_it->nchars <= 0) |
| 1887 | bidi_it->charpos + bidi_it->nchars + sep_len; | 2264 | abort (); |
| 2265 | if (sep_len >= 0) | ||
| 2266 | { | ||
| 2267 | bidi_it->new_paragraph = 1; | ||
| 2268 | /* Record the buffer position of the last character of the | ||
| 2269 | paragraph separator. */ | ||
| 2270 | bidi_it->separator_limit = | ||
| 2271 | bidi_it->charpos + bidi_it->nchars + sep_len; | ||
| 2272 | } | ||
| 1888 | } | 2273 | } |
| 1889 | } | 2274 | } |
| 1890 | 2275 | ||
| 1891 | if (bidi_it->scan_dir == 1 && bidi_cache_idx) | 2276 | if (bidi_it->scan_dir == 1 && bidi_cache_idx > bidi_cache_start) |
| 1892 | { | 2277 | { |
| 1893 | /* If we are at paragraph's base embedding level and beyond the | 2278 | /* If we are at paragraph's base embedding level and beyond the |
| 1894 | last cached position, the cache's job is done and we can | 2279 | last cached position, the cache's job is done and we can |
| @@ -1904,6 +2289,9 @@ bidi_move_to_visually_next (struct bidi_it *bidi_it) | |||
| 1904 | else | 2289 | else |
| 1905 | bidi_cache_iterator_state (bidi_it, 1); | 2290 | bidi_cache_iterator_state (bidi_it, 1); |
| 1906 | } | 2291 | } |
| 2292 | |||
| 2293 | if (STRINGP (bidi_it->string.lstring)) | ||
| 2294 | UNGCPRO; | ||
| 1907 | } | 2295 | } |
| 1908 | 2296 | ||
| 1909 | /* This is meant to be called from within the debugger, whenever you | 2297 | /* This is meant to be called from within the debugger, whenever you |
| @@ -1920,7 +2308,7 @@ bidi_dump_cached_states (void) | |||
| 1920 | fprintf (stderr, "The cache is empty.\n"); | 2308 | fprintf (stderr, "The cache is empty.\n"); |
| 1921 | return; | 2309 | return; |
| 1922 | } | 2310 | } |
| 1923 | fprintf (stderr, "Total of %d state%s in cache:\n", | 2311 | fprintf (stderr, "Total of %"pD"d state%s in cache:\n", |
| 1924 | bidi_cache_idx, bidi_cache_idx == 1 ? "" : "s"); | 2312 | bidi_cache_idx, bidi_cache_idx == 1 ? "" : "s"); |
| 1925 | 2313 | ||
| 1926 | for (i = bidi_cache[bidi_cache_idx - 1].charpos; i > 0; i /= 10) | 2314 | for (i = bidi_cache[bidi_cache_idx - 1].charpos; i > 0; i /= 10) |
diff --git a/src/dispextern.h b/src/dispextern.h index c0a67690a5c..dc44c698164 100644 --- a/src/dispextern.h +++ b/src/dispextern.h | |||
| @@ -1820,9 +1820,21 @@ struct bidi_stack { | |||
| 1820 | bidi_dir_t override; | 1820 | bidi_dir_t override; |
| 1821 | }; | 1821 | }; |
| 1822 | 1822 | ||
| 1823 | /* Data type for storing information about a string being iterated on. */ | ||
| 1824 | struct bidi_string_data { | ||
| 1825 | Lisp_Object lstring; /* Lisp string to reorder, or nil */ | ||
| 1826 | const unsigned char *s; /* string data, or NULL if reordering buffer */ | ||
| 1827 | EMACS_INT schars; /* the number of characters in the string, | ||
| 1828 | excluding the terminating null */ | ||
| 1829 | EMACS_INT bufpos; /* buffer position of lstring, or 0 if N/A */ | ||
| 1830 | unsigned from_disp_str : 1; /* 1 means the string comes from a | ||
| 1831 | display property */ | ||
| 1832 | unsigned unibyte : 1; /* 1 means the string is unibyte */ | ||
| 1833 | }; | ||
| 1834 | |||
| 1823 | /* Data type for reordering bidirectional text. */ | 1835 | /* Data type for reordering bidirectional text. */ |
| 1824 | struct bidi_it { | 1836 | struct bidi_it { |
| 1825 | EMACS_INT bytepos; /* iterator's position in buffer */ | 1837 | EMACS_INT bytepos; /* iterator's position in buffer/string */ |
| 1826 | EMACS_INT charpos; | 1838 | EMACS_INT charpos; |
| 1827 | int ch; /* character at that position, or u+FFFC | 1839 | int ch; /* character at that position, or u+FFFC |
| 1828 | ("object replacement character") for a run | 1840 | ("object replacement character") for a run |
| @@ -1852,12 +1864,13 @@ struct bidi_it { | |||
| 1852 | iterator state is saved, pushed, or popped. So only put here | 1864 | iterator state is saved, pushed, or popped. So only put here |
| 1853 | stuff that is not part of the bidi iterator's state! */ | 1865 | stuff that is not part of the bidi iterator's state! */ |
| 1854 | struct bidi_stack level_stack[BIDI_MAXLEVEL]; /* stack of embedding levels */ | 1866 | struct bidi_stack level_stack[BIDI_MAXLEVEL]; /* stack of embedding levels */ |
| 1855 | int first_elt; /* if non-zero, examine current char first */ | 1867 | struct bidi_string_data string; /* string to reorder */ |
| 1856 | bidi_dir_t paragraph_dir; /* current paragraph direction */ | 1868 | bidi_dir_t paragraph_dir; /* current paragraph direction */ |
| 1857 | int new_paragraph; /* if non-zero, we expect a new paragraph */ | ||
| 1858 | int frame_window_p; /* non-zero if displaying on a GUI frame */ | ||
| 1859 | EMACS_INT separator_limit; /* where paragraph separator should end */ | 1869 | EMACS_INT separator_limit; /* where paragraph separator should end */ |
| 1860 | EMACS_INT disp_pos; /* position of display string after ch */ | 1870 | EMACS_INT disp_pos; /* position of display string after ch */ |
| 1871 | unsigned first_elt : 1; /* if non-zero, examine current char first */ | ||
| 1872 | unsigned new_paragraph : 1; /* if non-zero, we expect a new paragraph */ | ||
| 1873 | unsigned frame_window_p : 1; /* non-zero if displaying on a GUI frame */ | ||
| 1861 | }; | 1874 | }; |
| 1862 | 1875 | ||
| 1863 | /* Value is non-zero when the bidi iterator is at base paragraph | 1876 | /* Value is non-zero when the bidi iterator is at base paragraph |
| @@ -2134,6 +2147,10 @@ struct it | |||
| 2134 | Don't handle some `display' properties in these strings. */ | 2147 | Don't handle some `display' properties in these strings. */ |
| 2135 | unsigned string_from_display_prop_p : 1; | 2148 | unsigned string_from_display_prop_p : 1; |
| 2136 | 2149 | ||
| 2150 | /* 1 means we are iterating an object that came from a value of a | ||
| 2151 | `display' property. */ | ||
| 2152 | unsigned from_disp_prop_p : 1; | ||
| 2153 | |||
| 2137 | /* When METHOD == next_element_from_display_vector, | 2154 | /* When METHOD == next_element_from_display_vector, |
| 2138 | this is 1 if we're doing an ellipsis. Otherwise meaningless. */ | 2155 | this is 1 if we're doing an ellipsis. Otherwise meaningless. */ |
| 2139 | unsigned ellipsis_p : 1; | 2156 | unsigned ellipsis_p : 1; |
| @@ -2153,7 +2170,9 @@ struct it | |||
| 2153 | Lisp_Object *dpvec, *dpend; | 2170 | Lisp_Object *dpvec, *dpend; |
| 2154 | 2171 | ||
| 2155 | /* Length in bytes of the char that filled dpvec. A value of zero | 2172 | /* Length in bytes of the char that filled dpvec. A value of zero |
| 2156 | means that no such character is involved. */ | 2173 | means that no such character is involved. A negative value means |
| 2174 | the rest of the line from the current iterator position onwards | ||
| 2175 | is hidden by selective display or ellipsis. */ | ||
| 2157 | int dpvec_char_len; | 2176 | int dpvec_char_len; |
| 2158 | 2177 | ||
| 2159 | /* Face id to use for all characters in display vector. -1 if unused. */ | 2178 | /* Face id to use for all characters in display vector. -1 if unused. */ |
| @@ -2245,10 +2264,13 @@ struct it | |||
| 2245 | Lisp_Object from_overlay; | 2264 | Lisp_Object from_overlay; |
| 2246 | enum glyph_row_area area; | 2265 | enum glyph_row_area area; |
| 2247 | enum it_method method; | 2266 | enum it_method method; |
| 2267 | bidi_dir_t paragraph_embedding; | ||
| 2248 | unsigned multibyte_p : 1; | 2268 | unsigned multibyte_p : 1; |
| 2249 | unsigned string_from_display_prop_p : 1; | 2269 | unsigned string_from_display_prop_p : 1; |
| 2250 | unsigned display_ellipsis_p : 1; | 2270 | unsigned display_ellipsis_p : 1; |
| 2251 | unsigned avoid_cursor_p : 1; | 2271 | unsigned avoid_cursor_p : 1; |
| 2272 | unsigned bidi_p:1; | ||
| 2273 | unsigned from_disp_prop_p : 1; | ||
| 2252 | enum line_wrap_method line_wrap; | 2274 | enum line_wrap_method line_wrap; |
| 2253 | 2275 | ||
| 2254 | /* properties from display property that are reset by another display property. */ | 2276 | /* properties from display property that are reset by another display property. */ |
| @@ -2469,7 +2491,7 @@ struct it | |||
| 2469 | 2491 | ||
| 2470 | /* Non-zero means we need to reorder bidirectional text for display | 2492 | /* Non-zero means we need to reorder bidirectional text for display |
| 2471 | in the visual order. */ | 2493 | in the visual order. */ |
| 2472 | int bidi_p; | 2494 | unsigned bidi_p : 1; |
| 2473 | 2495 | ||
| 2474 | /* For iterating over bidirectional text. */ | 2496 | /* For iterating over bidirectional text. */ |
| 2475 | struct bidi_it bidi_it; | 2497 | struct bidi_it bidi_it; |
| @@ -2951,6 +2973,10 @@ extern void bidi_init_it (EMACS_INT, EMACS_INT, int, struct bidi_it *); | |||
| 2951 | extern void bidi_move_to_visually_next (struct bidi_it *); | 2973 | extern void bidi_move_to_visually_next (struct bidi_it *); |
| 2952 | extern void bidi_paragraph_init (bidi_dir_t, struct bidi_it *, int); | 2974 | extern void bidi_paragraph_init (bidi_dir_t, struct bidi_it *, int); |
| 2953 | extern int bidi_mirror_char (int); | 2975 | extern int bidi_mirror_char (int); |
| 2976 | extern void bidi_push_it (struct bidi_it *); | ||
| 2977 | extern void bidi_pop_it (struct bidi_it *); | ||
| 2978 | extern void *bidi_shelve_cache (void); | ||
| 2979 | extern void bidi_unshelve_cache (void *); | ||
| 2954 | 2980 | ||
| 2955 | /* Defined in xdisp.c */ | 2981 | /* Defined in xdisp.c */ |
| 2956 | 2982 | ||
| @@ -3008,8 +3034,10 @@ extern void reseat_at_previous_visible_line_start (struct it *); | |||
| 3008 | extern Lisp_Object lookup_glyphless_char_display (int, struct it *); | 3034 | extern Lisp_Object lookup_glyphless_char_display (int, struct it *); |
| 3009 | extern int calc_pixel_width_or_height (double *, struct it *, Lisp_Object, | 3035 | extern int calc_pixel_width_or_height (double *, struct it *, Lisp_Object, |
| 3010 | struct font *, int, int *); | 3036 | struct font *, int, int *); |
| 3011 | extern EMACS_INT compute_display_string_pos (EMACS_INT, int); | 3037 | extern EMACS_INT compute_display_string_pos (struct text_pos *, |
| 3012 | extern EMACS_INT compute_display_string_end (EMACS_INT); | 3038 | struct bidi_string_data *, int); |
| 3039 | extern EMACS_INT compute_display_string_end (EMACS_INT, | ||
| 3040 | struct bidi_string_data *); | ||
| 3013 | 3041 | ||
| 3014 | #ifdef HAVE_WINDOW_SYSTEM | 3042 | #ifdef HAVE_WINDOW_SYSTEM |
| 3015 | 3043 | ||
diff --git a/src/dispnew.c b/src/dispnew.c index d52bbdf1d3e..b2f416701c3 100644 --- a/src/dispnew.c +++ b/src/dispnew.c | |||
| @@ -5243,10 +5243,12 @@ buffer_posn_from_coords (struct window *w, int *x, int *y, struct display_pos *p | |||
| 5243 | struct image *img = 0; | 5243 | struct image *img = 0; |
| 5244 | #endif | 5244 | #endif |
| 5245 | int x0, x1, to_x; | 5245 | int x0, x1, to_x; |
| 5246 | void *itdata = NULL; | ||
| 5246 | 5247 | ||
| 5247 | /* We used to set current_buffer directly here, but that does the | 5248 | /* We used to set current_buffer directly here, but that does the |
| 5248 | wrong thing with `face-remapping-alist' (bug#2044). */ | 5249 | wrong thing with `face-remapping-alist' (bug#2044). */ |
| 5249 | Fset_buffer (w->buffer); | 5250 | Fset_buffer (w->buffer); |
| 5251 | itdata = bidi_shelve_cache (); | ||
| 5250 | SET_TEXT_POS_FROM_MARKER (startp, w->start); | 5252 | SET_TEXT_POS_FROM_MARKER (startp, w->start); |
| 5251 | CHARPOS (startp) = min (ZV, max (BEGV, CHARPOS (startp))); | 5253 | CHARPOS (startp) = min (ZV, max (BEGV, CHARPOS (startp))); |
| 5252 | BYTEPOS (startp) = min (ZV_BYTE, max (BEGV_BYTE, BYTEPOS (startp))); | 5254 | BYTEPOS (startp) = min (ZV_BYTE, max (BEGV_BYTE, BYTEPOS (startp))); |
| @@ -5280,6 +5282,7 @@ buffer_posn_from_coords (struct window *w, int *x, int *y, struct display_pos *p | |||
| 5280 | argument is ZV to prevent move_it_in_display_line from matching | 5282 | argument is ZV to prevent move_it_in_display_line from matching |
| 5281 | based on buffer positions. */ | 5283 | based on buffer positions. */ |
| 5282 | move_it_in_display_line (&it, ZV, to_x, MOVE_TO_X); | 5284 | move_it_in_display_line (&it, ZV, to_x, MOVE_TO_X); |
| 5285 | bidi_unshelve_cache (itdata); | ||
| 5283 | 5286 | ||
| 5284 | Fset_buffer (old_current_buffer); | 5287 | Fset_buffer (old_current_buffer); |
| 5285 | 5288 | ||
diff --git a/src/indent.c b/src/indent.c index 02eeb7f17d4..c36b83daa02 100644 --- a/src/indent.c +++ b/src/indent.c | |||
| @@ -1989,6 +1989,7 @@ whether or not it is currently displayed in some window. */) | |||
| 1989 | struct gcpro gcpro1, gcpro2, gcpro3; | 1989 | struct gcpro gcpro1, gcpro2, gcpro3; |
| 1990 | Lisp_Object lcols = Qnil; | 1990 | Lisp_Object lcols = Qnil; |
| 1991 | double cols IF_LINT (= 0); | 1991 | double cols IF_LINT (= 0); |
| 1992 | void *itdata = NULL; | ||
| 1992 | 1993 | ||
| 1993 | /* Allow LINES to be of the form (HPOS . VPOS) aka (COLUMNS . LINES). */ | 1994 | /* Allow LINES to be of the form (HPOS . VPOS) aka (COLUMNS . LINES). */ |
| 1994 | if (CONSP (lines) && (NUMBERP (XCAR (lines)))) | 1995 | 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/keyboard.c b/src/keyboard.c index 926ebc30b71..7e144b80a09 100644 --- a/src/keyboard.c +++ b/src/keyboard.c | |||
| @@ -10643,7 +10643,8 @@ DEFUN ("recursion-depth", Frecursion_depth, Srecursion_depth, 0, 0, 0, | |||
| 10643 | DEFUN ("open-dribble-file", Fopen_dribble_file, Sopen_dribble_file, 1, 1, | 10643 | DEFUN ("open-dribble-file", Fopen_dribble_file, Sopen_dribble_file, 1, 1, |
| 10644 | "FOpen dribble file: ", | 10644 | "FOpen dribble file: ", |
| 10645 | doc: /* Start writing all keyboard characters to a dribble file called FILE. | 10645 | doc: /* Start writing all keyboard characters to a dribble file called FILE. |
| 10646 | If FILE is nil, close any open dribble file. */) | 10646 | If FILE is nil, close any open dribble file. |
| 10647 | The file will be closed when Emacs exits. */) | ||
| 10647 | (Lisp_Object file) | 10648 | (Lisp_Object file) |
| 10648 | { | 10649 | { |
| 10649 | if (dribble) | 10650 | if (dribble) |
diff --git a/src/search.c b/src/search.c index d29a51c695b..a56df784cd2 100644 --- a/src/search.c +++ b/src/search.c | |||
| @@ -2284,6 +2284,10 @@ The match found must start at or after that position. | |||
| 2284 | Optional third argument, if t, means if fail just return nil (no error). | 2284 | Optional third argument, if t, means if fail just return nil (no error). |
| 2285 | If not nil and not t, move to limit of search and return nil. | 2285 | If not nil and not t, move to limit of search and return nil. |
| 2286 | Optional fourth argument is repeat count--search for successive occurrences. | 2286 | Optional fourth argument is repeat count--search for successive occurrences. |
| 2287 | |||
| 2288 | Search case-sensitivity is determined by the value of the variable | ||
| 2289 | `case-fold-search', which see. | ||
| 2290 | |||
| 2287 | See also the functions `match-beginning', `match-end', `match-string', | 2291 | See also the functions `match-beginning', `match-end', `match-string', |
| 2288 | and `replace-match'. */) | 2292 | and `replace-match'. */) |
| 2289 | (Lisp_Object regexp, Lisp_Object bound, Lisp_Object noerror, Lisp_Object count) | 2293 | (Lisp_Object regexp, Lisp_Object bound, Lisp_Object noerror, Lisp_Object count) |
| @@ -2300,6 +2304,10 @@ The match found must not extend after that position. | |||
| 2300 | Optional third argument, if t, means if fail just return nil (no error). | 2304 | Optional third argument, if t, means if fail just return nil (no error). |
| 2301 | If not nil and not t, move to limit of search and return nil. | 2305 | If not nil and not t, move to limit of search and return nil. |
| 2302 | Optional fourth argument is repeat count--search for successive occurrences. | 2306 | Optional fourth argument is repeat count--search for successive occurrences. |
| 2307 | |||
| 2308 | Search case-sensitivity is determined by the value of the variable | ||
| 2309 | `case-fold-search', which see. | ||
| 2310 | |||
| 2303 | See also the functions `match-beginning', `match-end', `match-string', | 2311 | See also the functions `match-beginning', `match-end', `match-string', |
| 2304 | and `replace-match'. */) | 2312 | and `replace-match'. */) |
| 2305 | (Lisp_Object regexp, Lisp_Object bound, Lisp_Object noerror, Lisp_Object count) | 2313 | (Lisp_Object regexp, Lisp_Object bound, Lisp_Object noerror, Lisp_Object count) |
| @@ -2319,6 +2327,10 @@ The match found must start at or after that position. | |||
| 2319 | Optional third argument, if t, means if fail just return nil (no error). | 2327 | Optional third argument, if t, means if fail just return nil (no error). |
| 2320 | If not nil and not t, move to limit of search and return nil. | 2328 | If not nil and not t, move to limit of search and return nil. |
| 2321 | Optional fourth argument is repeat count--search for successive occurrences. | 2329 | Optional fourth argument is repeat count--search for successive occurrences. |
| 2330 | |||
| 2331 | Search case-sensitivity is determined by the value of the variable | ||
| 2332 | `case-fold-search', which see. | ||
| 2333 | |||
| 2322 | See also the functions `match-beginning', `match-end', `match-string', | 2334 | See also the functions `match-beginning', `match-end', `match-string', |
| 2323 | and `replace-match'. */) | 2335 | and `replace-match'. */) |
| 2324 | (Lisp_Object regexp, Lisp_Object bound, Lisp_Object noerror, Lisp_Object count) | 2336 | (Lisp_Object regexp, Lisp_Object bound, Lisp_Object noerror, Lisp_Object count) |
| @@ -2336,6 +2348,10 @@ The match found must not extend after that position. | |||
| 2336 | Optional third argument, if t, means if fail just return nil (no error). | 2348 | Optional third argument, if t, means if fail just return nil (no error). |
| 2337 | If not nil and not t, move to limit of search and return nil. | 2349 | If not nil and not t, move to limit of search and return nil. |
| 2338 | Optional fourth argument is repeat count--search for successive occurrences. | 2350 | Optional fourth argument is repeat count--search for successive occurrences. |
| 2351 | |||
| 2352 | Search case-sensitivity is determined by the value of the variable | ||
| 2353 | `case-fold-search', which see. | ||
| 2354 | |||
| 2339 | See also the functions `match-beginning', `match-end', `match-string', | 2355 | See also the functions `match-beginning', `match-end', `match-string', |
| 2340 | and `replace-match'. */) | 2356 | and `replace-match'. */) |
| 2341 | (Lisp_Object regexp, Lisp_Object bound, Lisp_Object noerror, Lisp_Object count) | 2357 | (Lisp_Object regexp, Lisp_Object bound, Lisp_Object noerror, Lisp_Object count) |
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 | { |
diff --git a/src/xdisp.c b/src/xdisp.c index 123d2fa984c..2aa70d29ff1 100644 --- a/src/xdisp.c +++ b/src/xdisp.c | |||
| @@ -129,9 +129,13 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ | |||
| 129 | argument. | 129 | argument. |
| 130 | 130 | ||
| 131 | Iteration over things to be displayed is then simple. It is | 131 | Iteration over things to be displayed is then simple. It is |
| 132 | started by initializing an iterator with a call to init_iterator. | 132 | started by initializing an iterator with a call to init_iterator, |
| 133 | Calls to get_next_display_element fill the iterator structure with | 133 | passing it the buffer position where to start iteration. For |
| 134 | relevant information about the next thing to display. Calls to | 134 | iteration over strings, pass -1 as the position to init_iterator, |
| 135 | and call reseat_to_string when the string is ready, to initialize | ||
| 136 | the iterator for that string. Thereafter, calls to | ||
| 137 | get_next_display_element fill the iterator structure with relevant | ||
| 138 | information about the next thing to display. Calls to | ||
| 135 | set_iterator_to_next move the iterator to the next thing. | 139 | set_iterator_to_next move the iterator to the next thing. |
| 136 | 140 | ||
| 137 | Besides this, an iterator also contains information about the | 141 | Besides this, an iterator also contains information about the |
| @@ -590,6 +594,29 @@ int current_mode_line_height, current_header_line_height; | |||
| 590 | 594 | ||
| 591 | #define TEXT_PROP_DISTANCE_LIMIT 100 | 595 | #define TEXT_PROP_DISTANCE_LIMIT 100 |
| 592 | 596 | ||
| 597 | /* SAVE_IT and RESTORE_IT are called when we save a snapshot of the | ||
| 598 | iterator state and later restore it. This is needed because the | ||
| 599 | bidi iterator on bidi.c keeps a stacked cache of its states, which | ||
| 600 | is really a singleton. When we use scratch iterator objects to | ||
| 601 | move around the buffer, we can cause the bidi cache to be pushed or | ||
| 602 | popped, and therefore we need to restore the cache state when we | ||
| 603 | return to the original iterator. */ | ||
| 604 | #define SAVE_IT(ITCOPY,ITORIG,CACHE) \ | ||
| 605 | do { \ | ||
| 606 | if (CACHE) \ | ||
| 607 | xfree (CACHE); \ | ||
| 608 | ITCOPY = ITORIG; \ | ||
| 609 | CACHE = bidi_shelve_cache(); \ | ||
| 610 | } while (0) | ||
| 611 | |||
| 612 | #define RESTORE_IT(pITORIG,pITCOPY,CACHE) \ | ||
| 613 | do { \ | ||
| 614 | if (pITORIG != pITCOPY) \ | ||
| 615 | *(pITORIG) = *(pITCOPY); \ | ||
| 616 | bidi_unshelve_cache (CACHE); \ | ||
| 617 | CACHE = NULL; \ | ||
| 618 | } while (0) | ||
| 619 | |||
| 593 | #if GLYPH_DEBUG | 620 | #if GLYPH_DEBUG |
| 594 | 621 | ||
| 595 | /* Non-zero means print traces of redisplay if compiled with | 622 | /* Non-zero means print traces of redisplay if compiled with |
| @@ -1195,6 +1222,7 @@ pos_visible_p (struct window *w, EMACS_INT charpos, int *x, int *y, | |||
| 1195 | int *rtop, int *rbot, int *rowh, int *vpos) | 1222 | int *rtop, int *rbot, int *rowh, int *vpos) |
| 1196 | { | 1223 | { |
| 1197 | struct it it; | 1224 | struct it it; |
| 1225 | void *itdata = bidi_shelve_cache (); | ||
| 1198 | struct text_pos top; | 1226 | struct text_pos top; |
| 1199 | int visible_p = 0; | 1227 | int visible_p = 0; |
| 1200 | struct buffer *old_buffer = NULL; | 1228 | struct buffer *old_buffer = NULL; |
| @@ -1225,13 +1253,21 @@ pos_visible_p (struct window *w, EMACS_INT charpos, int *x, int *y, | |||
| 1225 | move_it_to (&it, charpos, -1, it.last_visible_y-1, -1, | 1253 | move_it_to (&it, charpos, -1, it.last_visible_y-1, -1, |
| 1226 | (charpos >= 0 ? MOVE_TO_POS : 0) | MOVE_TO_Y); | 1254 | (charpos >= 0 ? MOVE_TO_POS : 0) | MOVE_TO_Y); |
| 1227 | 1255 | ||
| 1228 | if (charpos >= 0 && IT_CHARPOS (it) >= charpos) | 1256 | if (charpos >= 0 |
| 1257 | && (((!it.bidi_p || it.bidi_it.scan_dir == 1) | ||
| 1258 | && IT_CHARPOS (it) >= charpos) | ||
| 1259 | /* When scanning backwards under bidi iteration, move_it_to | ||
| 1260 | stops at or _before_ CHARPOS, because it stops at or to | ||
| 1261 | the _right_ of the character at CHARPOS. */ | ||
| 1262 | || (it.bidi_p && it.bidi_it.scan_dir == -1 | ||
| 1263 | && IT_CHARPOS (it) <= charpos))) | ||
| 1229 | { | 1264 | { |
| 1230 | /* We have reached CHARPOS, or passed it. How the call to | 1265 | /* We have reached CHARPOS, or passed it. How the call to |
| 1231 | move_it_to can overshoot: (i) If CHARPOS is on invisible | 1266 | move_it_to can overshoot: (i) If CHARPOS is on invisible text |
| 1232 | text, move_it_to stops at the end of the invisible text, | 1267 | or covered by a display property, move_it_to stops at the end |
| 1233 | after CHARPOS. (ii) If CHARPOS is in a display vector, | 1268 | of the invisible text, to the right of CHARPOS. (ii) If |
| 1234 | move_it_to stops on its last glyph. */ | 1269 | CHARPOS is in a display vector, move_it_to stops on its last |
| 1270 | glyph. */ | ||
| 1235 | int top_x = it.current_x; | 1271 | int top_x = it.current_x; |
| 1236 | int top_y = it.current_y; | 1272 | int top_y = it.current_y; |
| 1237 | enum it_method it_method = it.method; | 1273 | enum it_method it_method = it.method; |
| @@ -1280,15 +1316,18 @@ pos_visible_p (struct window *w, EMACS_INT charpos, int *x, int *y, | |||
| 1280 | } | 1316 | } |
| 1281 | else | 1317 | else |
| 1282 | { | 1318 | { |
| 1319 | /* We were asked to provide info about WINDOW_END. */ | ||
| 1283 | struct it it2; | 1320 | struct it it2; |
| 1321 | void *it2data = NULL; | ||
| 1284 | 1322 | ||
| 1285 | it2 = it; | 1323 | SAVE_IT (it2, it, it2data); |
| 1286 | if (IT_CHARPOS (it) < ZV && FETCH_BYTE (IT_BYTEPOS (it)) != '\n') | 1324 | if (IT_CHARPOS (it) < ZV && FETCH_BYTE (IT_BYTEPOS (it)) != '\n') |
| 1287 | move_it_by_lines (&it, 1); | 1325 | move_it_by_lines (&it, 1); |
| 1288 | if (charpos < IT_CHARPOS (it) | 1326 | if (charpos < IT_CHARPOS (it) |
| 1289 | || (it.what == IT_EOB && charpos == IT_CHARPOS (it))) | 1327 | || (it.what == IT_EOB && charpos == IT_CHARPOS (it))) |
| 1290 | { | 1328 | { |
| 1291 | visible_p = 1; | 1329 | visible_p = 1; |
| 1330 | RESTORE_IT (&it2, &it2, it2data); | ||
| 1292 | move_it_to (&it2, charpos, -1, -1, -1, MOVE_TO_POS); | 1331 | move_it_to (&it2, charpos, -1, -1, -1, MOVE_TO_POS); |
| 1293 | *x = it2.current_x; | 1332 | *x = it2.current_x; |
| 1294 | *y = it2.current_y + it2.max_ascent - it2.ascent; | 1333 | *y = it2.current_y + it2.max_ascent - it2.ascent; |
| @@ -1301,7 +1340,10 @@ pos_visible_p (struct window *w, EMACS_INT charpos, int *x, int *y, | |||
| 1301 | WINDOW_HEADER_LINE_HEIGHT (w)))); | 1340 | WINDOW_HEADER_LINE_HEIGHT (w)))); |
| 1302 | *vpos = it2.vpos; | 1341 | *vpos = it2.vpos; |
| 1303 | } | 1342 | } |
| 1343 | else | ||
| 1344 | xfree (it2data); | ||
| 1304 | } | 1345 | } |
| 1346 | bidi_unshelve_cache (itdata); | ||
| 1305 | 1347 | ||
| 1306 | if (old_buffer) | 1348 | if (old_buffer) |
| 1307 | set_buffer_internal_1 (old_buffer); | 1349 | set_buffer_internal_1 (old_buffer); |
| @@ -2339,6 +2381,10 @@ init_iterator (struct it *it, struct window *w, | |||
| 2339 | it->base_face_id = remapped_base_face_id; | 2381 | it->base_face_id = remapped_base_face_id; |
| 2340 | it->string = Qnil; | 2382 | it->string = Qnil; |
| 2341 | IT_STRING_CHARPOS (*it) = IT_STRING_BYTEPOS (*it) = -1; | 2383 | IT_STRING_CHARPOS (*it) = IT_STRING_BYTEPOS (*it) = -1; |
| 2384 | it->paragraph_embedding = L2R; | ||
| 2385 | it->bidi_it.string.lstring = Qnil; | ||
| 2386 | it->bidi_it.string.s = NULL; | ||
| 2387 | it->bidi_it.string.bufpos = 0; | ||
| 2342 | 2388 | ||
| 2343 | /* The window in which we iterate over current_buffer: */ | 2389 | /* The window in which we iterate over current_buffer: */ |
| 2344 | XSETWINDOW (it->window, w); | 2390 | XSETWINDOW (it->window, w); |
| @@ -2395,13 +2441,6 @@ init_iterator (struct it *it, struct window *w, | |||
| 2395 | /* Are multibyte characters enabled in current_buffer? */ | 2441 | /* Are multibyte characters enabled in current_buffer? */ |
| 2396 | it->multibyte_p = !NILP (BVAR (current_buffer, enable_multibyte_characters)); | 2442 | it->multibyte_p = !NILP (BVAR (current_buffer, enable_multibyte_characters)); |
| 2397 | 2443 | ||
| 2398 | /* Do we need to reorder bidirectional text? Not if this is a | ||
| 2399 | unibyte buffer: by definition, none of the single-byte characters | ||
| 2400 | are strong R2L, so no reordering is needed. And bidi.c doesn't | ||
| 2401 | support unibyte buffers anyway. */ | ||
| 2402 | it->bidi_p | ||
| 2403 | = !NILP (BVAR (current_buffer, bidi_display_reordering)) && it->multibyte_p; | ||
| 2404 | |||
| 2405 | /* Non-zero if we should highlight the region. */ | 2444 | /* Non-zero if we should highlight the region. */ |
| 2406 | highlight_region_p | 2445 | highlight_region_p |
| 2407 | = (!NILP (Vtransient_mark_mode) | 2446 | = (!NILP (Vtransient_mark_mode) |
| @@ -2551,21 +2590,6 @@ init_iterator (struct it *it, struct window *w, | |||
| 2551 | it->start_of_box_run_p = 1; | 2590 | it->start_of_box_run_p = 1; |
| 2552 | } | 2591 | } |
| 2553 | 2592 | ||
| 2554 | /* If we are to reorder bidirectional text, init the bidi | ||
| 2555 | iterator. */ | ||
| 2556 | if (it->bidi_p) | ||
| 2557 | { | ||
| 2558 | /* Note the paragraph direction that this buffer wants to | ||
| 2559 | use. */ | ||
| 2560 | if (EQ (BVAR (current_buffer, bidi_paragraph_direction), Qleft_to_right)) | ||
| 2561 | it->paragraph_embedding = L2R; | ||
| 2562 | else if (EQ (BVAR (current_buffer, bidi_paragraph_direction), Qright_to_left)) | ||
| 2563 | it->paragraph_embedding = R2L; | ||
| 2564 | else | ||
| 2565 | it->paragraph_embedding = NEUTRAL_DIR; | ||
| 2566 | bidi_init_it (charpos, bytepos, FRAME_WINDOW_P (it->f), &it->bidi_it); | ||
| 2567 | } | ||
| 2568 | |||
| 2569 | /* If a buffer position was specified, set the iterator there, | 2593 | /* If a buffer position was specified, set the iterator there, |
| 2570 | getting overlays and face properties from that position. */ | 2594 | getting overlays and face properties from that position. */ |
| 2571 | if (charpos >= BUF_BEG (current_buffer)) | 2595 | if (charpos >= BUF_BEG (current_buffer)) |
| @@ -2581,6 +2605,32 @@ init_iterator (struct it *it, struct window *w, | |||
| 2581 | IT_BYTEPOS (*it) = bytepos; | 2605 | IT_BYTEPOS (*it) = bytepos; |
| 2582 | 2606 | ||
| 2583 | it->start = it->current; | 2607 | it->start = it->current; |
| 2608 | /* Do we need to reorder bidirectional text? Not if this is a | ||
| 2609 | unibyte buffer: by definition, none of the single-byte | ||
| 2610 | characters are strong R2L, so no reordering is needed. And | ||
| 2611 | bidi.c doesn't support unibyte buffers anyway. */ | ||
| 2612 | it->bidi_p = | ||
| 2613 | !NILP (BVAR (current_buffer, bidi_display_reordering)) | ||
| 2614 | && it->multibyte_p; | ||
| 2615 | |||
| 2616 | /* If we are to reorder bidirectional text, init the bidi | ||
| 2617 | iterator. */ | ||
| 2618 | if (it->bidi_p) | ||
| 2619 | { | ||
| 2620 | /* Note the paragraph direction that this buffer wants to | ||
| 2621 | use. */ | ||
| 2622 | if (EQ (BVAR (current_buffer, bidi_paragraph_direction), | ||
| 2623 | Qleft_to_right)) | ||
| 2624 | it->paragraph_embedding = L2R; | ||
| 2625 | else if (EQ (BVAR (current_buffer, bidi_paragraph_direction), | ||
| 2626 | Qright_to_left)) | ||
| 2627 | it->paragraph_embedding = R2L; | ||
| 2628 | else | ||
| 2629 | it->paragraph_embedding = NEUTRAL_DIR; | ||
| 2630 | bidi_unshelve_cache (NULL); | ||
| 2631 | bidi_init_it (charpos, IT_BYTEPOS (*it), FRAME_WINDOW_P (it->f), | ||
| 2632 | &it->bidi_it); | ||
| 2633 | } | ||
| 2584 | 2634 | ||
| 2585 | /* Compute faces etc. */ | 2635 | /* Compute faces etc. */ |
| 2586 | reseat (it, it->current.pos, 1); | 2636 | reseat (it, it->current.pos, 1); |
| @@ -2902,6 +2952,7 @@ handle_stop (struct it *it) | |||
| 2902 | { | 2952 | { |
| 2903 | it->ignore_overlay_strings_at_pos_p = 1; | 2953 | it->ignore_overlay_strings_at_pos_p = 1; |
| 2904 | it->string_from_display_prop_p = 0; | 2954 | it->string_from_display_prop_p = 0; |
| 2955 | it->from_disp_prop_p = 0; | ||
| 2905 | handle_overlay_change_p = 0; | 2956 | handle_overlay_change_p = 0; |
| 2906 | } | 2957 | } |
| 2907 | handled = HANDLED_RECOMPUTE_PROPS; | 2958 | handled = HANDLED_RECOMPUTE_PROPS; |
| @@ -3083,37 +3134,50 @@ next_overlay_change (EMACS_INT pos) | |||
| 3083 | return endpos; | 3134 | return endpos; |
| 3084 | } | 3135 | } |
| 3085 | 3136 | ||
| 3086 | /* Return the character position of a display string at or after CHARPOS. | 3137 | /* Return the character position of a display string at or after |
| 3087 | If no display string exists at or after CHARPOS, return ZV. A | 3138 | position specified by POSITION. If no display string exists at or |
| 3088 | display string is either an overlay with `display' property whose | 3139 | after POSITION, return ZV. A display string is either an overlay |
| 3089 | value is a string, or a `display' text property whose value is a | 3140 | with `display' property whose value is a string, or a `display' |
| 3090 | string. FRAME_WINDOW_P is non-zero when we are displaying a window | 3141 | text property whose value is a string. STRING is data about the |
| 3142 | string to iterate; if STRING->lstring is nil, we are iterating a | ||
| 3143 | buffer. FRAME_WINDOW_P is non-zero when we are displaying a window | ||
| 3091 | on a GUI frame. */ | 3144 | on a GUI frame. */ |
| 3092 | EMACS_INT | 3145 | EMACS_INT |
| 3093 | compute_display_string_pos (EMACS_INT charpos, int frame_window_p) | 3146 | compute_display_string_pos (struct text_pos *position, |
| 3147 | struct bidi_string_data *string, int frame_window_p) | ||
| 3094 | { | 3148 | { |
| 3095 | /* FIXME: Support display properties on strings (object = Qnil means | 3149 | /* OBJECT = nil means current buffer. */ |
| 3096 | current buffer). */ | 3150 | Lisp_Object object = |
| 3097 | Lisp_Object object = Qnil; | 3151 | (string && STRINGP (string->lstring)) ? string->lstring : Qnil; |
| 3098 | Lisp_Object pos, spec; | 3152 | Lisp_Object pos, spec; |
| 3099 | struct text_pos position; | 3153 | int string_p = (string && (STRINGP (string->lstring) || string->s)); |
| 3100 | EMACS_INT bufpos; | 3154 | EMACS_INT eob = string_p ? string->schars : ZV; |
| 3101 | 3155 | EMACS_INT begb = string_p ? 0 : BEGV; | |
| 3102 | if (charpos >= ZV) | 3156 | EMACS_INT bufpos, charpos = CHARPOS (*position); |
| 3103 | return ZV; | 3157 | struct text_pos tpos; |
| 3158 | |||
| 3159 | if (charpos >= eob | ||
| 3160 | /* We don't support display properties whose values are strings | ||
| 3161 | that have display string properties. */ | ||
| 3162 | || string->from_disp_str | ||
| 3163 | /* C strings cannot have display properties. */ | ||
| 3164 | || (string->s && !STRINGP (object))) | ||
| 3165 | return eob; | ||
| 3104 | 3166 | ||
| 3105 | /* If the character at CHARPOS is where the display string begins, | 3167 | /* If the character at CHARPOS is where the display string begins, |
| 3106 | return CHARPOS. */ | 3168 | return CHARPOS. */ |
| 3107 | pos = make_number (charpos); | 3169 | pos = make_number (charpos); |
| 3108 | CHARPOS (position) = charpos; | 3170 | if (STRINGP (object)) |
| 3109 | BYTEPOS (position) = CHAR_TO_BYTE (charpos); | 3171 | bufpos = string->bufpos; |
| 3110 | bufpos = charpos; /* FIXME! support strings as well */ | 3172 | else |
| 3173 | bufpos = charpos; | ||
| 3174 | tpos = *position; | ||
| 3111 | if (!NILP (spec = Fget_char_property (pos, Qdisplay, object)) | 3175 | if (!NILP (spec = Fget_char_property (pos, Qdisplay, object)) |
| 3112 | && (charpos <= BEGV | 3176 | && (charpos <= begb |
| 3113 | || !EQ (Fget_char_property (make_number (charpos - 1), Qdisplay, | 3177 | || !EQ (Fget_char_property (make_number (charpos - 1), Qdisplay, |
| 3114 | object), | 3178 | object), |
| 3115 | spec)) | 3179 | spec)) |
| 3116 | && handle_display_spec (NULL, spec, object, Qnil, &position, bufpos, | 3180 | && handle_display_spec (NULL, spec, object, Qnil, &tpos, bufpos, |
| 3117 | frame_window_p)) | 3181 | frame_window_p)) |
| 3118 | return charpos; | 3182 | return charpos; |
| 3119 | 3183 | ||
| @@ -3121,17 +3185,21 @@ compute_display_string_pos (EMACS_INT charpos, int frame_window_p) | |||
| 3121 | that will replace the underlying text when displayed. */ | 3185 | that will replace the underlying text when displayed. */ |
| 3122 | do { | 3186 | do { |
| 3123 | pos = Fnext_single_char_property_change (pos, Qdisplay, object, Qnil); | 3187 | pos = Fnext_single_char_property_change (pos, Qdisplay, object, Qnil); |
| 3124 | CHARPOS (position) = XFASTINT (pos); | 3188 | CHARPOS (tpos) = XFASTINT (pos); |
| 3125 | BYTEPOS (position) = CHAR_TO_BYTE (CHARPOS (position)); | 3189 | if (STRINGP (object)) |
| 3126 | if (CHARPOS (position) >= ZV) | 3190 | BYTEPOS (tpos) = string_char_to_byte (object, CHARPOS (tpos)); |
| 3191 | else | ||
| 3192 | BYTEPOS (tpos) = CHAR_TO_BYTE (CHARPOS (tpos)); | ||
| 3193 | if (CHARPOS (tpos) >= eob) | ||
| 3127 | break; | 3194 | break; |
| 3128 | spec = Fget_char_property (pos, Qdisplay, object); | 3195 | spec = Fget_char_property (pos, Qdisplay, object); |
| 3129 | bufpos = CHARPOS (position); /* FIXME! support strings as well */ | 3196 | if (!STRINGP (object)) |
| 3197 | bufpos = CHARPOS (tpos); | ||
| 3130 | } while (NILP (spec) | 3198 | } while (NILP (spec) |
| 3131 | || !handle_display_spec (NULL, spec, object, Qnil, &position, bufpos, | 3199 | || !handle_display_spec (NULL, spec, object, Qnil, &tpos, bufpos, |
| 3132 | frame_window_p)); | 3200 | frame_window_p)); |
| 3133 | 3201 | ||
| 3134 | return CHARPOS (position); | 3202 | return CHARPOS (tpos); |
| 3135 | } | 3203 | } |
| 3136 | 3204 | ||
| 3137 | /* Return the character position of the end of the display string that | 3205 | /* Return the character position of the end of the display string that |
| @@ -3139,15 +3207,17 @@ compute_display_string_pos (EMACS_INT charpos, int frame_window_p) | |||
| 3139 | `display' property whose value is a string or a `display' text | 3207 | `display' property whose value is a string or a `display' text |
| 3140 | property whose value is a string. */ | 3208 | property whose value is a string. */ |
| 3141 | EMACS_INT | 3209 | EMACS_INT |
| 3142 | compute_display_string_end (EMACS_INT charpos) | 3210 | compute_display_string_end (EMACS_INT charpos, struct bidi_string_data *string) |
| 3143 | { | 3211 | { |
| 3144 | /* FIXME: Support display properties on strings (object = Qnil means | 3212 | /* OBJECT = nil means current buffer. */ |
| 3145 | current buffer). */ | 3213 | Lisp_Object object = |
| 3146 | Lisp_Object object = Qnil; | 3214 | (string && STRINGP (string->lstring)) ? string->lstring : Qnil; |
| 3147 | Lisp_Object pos = make_number (charpos); | 3215 | Lisp_Object pos = make_number (charpos); |
| 3216 | EMACS_INT eob = | ||
| 3217 | (STRINGP (object) || (string && string->s)) ? string->schars : ZV; | ||
| 3148 | 3218 | ||
| 3149 | if (charpos >= ZV) | 3219 | if (charpos >= eob || (string->s && !STRINGP (object))) |
| 3150 | return ZV; | 3220 | return eob; |
| 3151 | 3221 | ||
| 3152 | if (NILP (Fget_char_property (pos, Qdisplay, object))) | 3222 | if (NILP (Fget_char_property (pos, Qdisplay, object))) |
| 3153 | abort (); | 3223 | abort (); |
| @@ -3440,21 +3510,23 @@ underlying_face_id (struct it *it) | |||
| 3440 | 3510 | ||
| 3441 | 3511 | ||
| 3442 | /* Compute the face one character before or after the current position | 3512 | /* Compute the face one character before or after the current position |
| 3443 | of IT. BEFORE_P non-zero means get the face in front of IT's | 3513 | of IT, in the visual order. BEFORE_P non-zero means get the face |
| 3444 | position. Value is the id of the face. */ | 3514 | in front (to the left in L2R paragraphs, to the right in R2L |
| 3515 | paragraphs) of IT's screen position. Value is the ID of the face. */ | ||
| 3445 | 3516 | ||
| 3446 | static int | 3517 | static int |
| 3447 | face_before_or_after_it_pos (struct it *it, int before_p) | 3518 | face_before_or_after_it_pos (struct it *it, int before_p) |
| 3448 | { | 3519 | { |
| 3449 | int face_id, limit; | 3520 | int face_id, limit; |
| 3450 | EMACS_INT next_check_charpos; | 3521 | EMACS_INT next_check_charpos; |
| 3451 | struct text_pos pos; | 3522 | struct it it_copy; |
| 3523 | void *it_copy_data = NULL; | ||
| 3452 | 3524 | ||
| 3453 | xassert (it->s == NULL); | 3525 | xassert (it->s == NULL); |
| 3454 | 3526 | ||
| 3455 | if (STRINGP (it->string)) | 3527 | if (STRINGP (it->string)) |
| 3456 | { | 3528 | { |
| 3457 | EMACS_INT bufpos; | 3529 | EMACS_INT bufpos, charpos; |
| 3458 | int base_face_id; | 3530 | int base_face_id; |
| 3459 | 3531 | ||
| 3460 | /* No face change past the end of the string (for the case | 3532 | /* No face change past the end of the string (for the case |
| @@ -3464,16 +3536,59 @@ face_before_or_after_it_pos (struct it *it, int before_p) | |||
| 3464 | || (IT_STRING_CHARPOS (*it) == 0 && before_p)) | 3536 | || (IT_STRING_CHARPOS (*it) == 0 && before_p)) |
| 3465 | return it->face_id; | 3537 | return it->face_id; |
| 3466 | 3538 | ||
| 3467 | /* Set pos to the position before or after IT's current position. */ | 3539 | if (!it->bidi_p) |
| 3468 | if (before_p) | 3540 | { |
| 3469 | pos = string_pos (IT_STRING_CHARPOS (*it) - 1, it->string); | 3541 | /* Set charpos to the position before or after IT's current |
| 3542 | position, in the logical order, which in the non-bidi | ||
| 3543 | case is the same as the visual order. */ | ||
| 3544 | if (before_p) | ||
| 3545 | charpos = IT_STRING_CHARPOS (*it) - 1; | ||
| 3546 | else if (it->what == IT_COMPOSITION) | ||
| 3547 | /* For composition, we must check the character after the | ||
| 3548 | composition. */ | ||
| 3549 | charpos = IT_STRING_CHARPOS (*it) + it->cmp_it.nchars; | ||
| 3550 | else | ||
| 3551 | charpos = IT_STRING_CHARPOS (*it) + 1; | ||
| 3552 | } | ||
| 3470 | else | 3553 | else |
| 3471 | /* For composition, we must check the character after the | 3554 | { |
| 3472 | composition. */ | 3555 | if (before_p) |
| 3473 | pos = (it->what == IT_COMPOSITION | 3556 | { |
| 3474 | ? string_pos (IT_STRING_CHARPOS (*it) | 3557 | /* With bidi iteration, the character before the current |
| 3475 | + it->cmp_it.nchars, it->string) | 3558 | in the visual order cannot be found by simple |
| 3476 | : string_pos (IT_STRING_CHARPOS (*it) + 1, it->string)); | 3559 | iteration, because "reverse" reordering is not |
| 3560 | supported. Instead, we need to use the move_it_* | ||
| 3561 | family of functions. */ | ||
| 3562 | /* Ignore face changes before the first visible | ||
| 3563 | character on this display line. */ | ||
| 3564 | if (it->current_x <= it->first_visible_x) | ||
| 3565 | return it->face_id; | ||
| 3566 | SAVE_IT (it_copy, *it, it_copy_data); | ||
| 3567 | /* Implementation note: Since move_it_in_display_line | ||
| 3568 | works in the iterator geometry, and thinks the first | ||
| 3569 | character is always the leftmost, even in R2L lines, | ||
| 3570 | we don't need to distinguish between the R2L and L2R | ||
| 3571 | cases here. */ | ||
| 3572 | move_it_in_display_line (&it_copy, SCHARS (it_copy.string), | ||
| 3573 | it_copy.current_x - 1, MOVE_TO_X); | ||
| 3574 | charpos = IT_STRING_CHARPOS (it_copy); | ||
| 3575 | RESTORE_IT (it, it, it_copy_data); | ||
| 3576 | } | ||
| 3577 | else | ||
| 3578 | { | ||
| 3579 | /* Set charpos to the string position of the character | ||
| 3580 | that comes after IT's current position in the visual | ||
| 3581 | order. */ | ||
| 3582 | int n = (it->what == IT_COMPOSITION ? it->cmp_it.nchars : 1); | ||
| 3583 | |||
| 3584 | it_copy = *it; | ||
| 3585 | while (n--) | ||
| 3586 | bidi_move_to_visually_next (&it_copy.bidi_it); | ||
| 3587 | |||
| 3588 | charpos = it_copy.bidi_it.charpos; | ||
| 3589 | } | ||
| 3590 | } | ||
| 3591 | xassert (0 <= charpos && charpos <= SCHARS (it->string)); | ||
| 3477 | 3592 | ||
| 3478 | if (it->current.overlay_string_index >= 0) | 3593 | if (it->current.overlay_string_index >= 0) |
| 3479 | bufpos = IT_CHARPOS (*it); | 3594 | bufpos = IT_CHARPOS (*it); |
| @@ -3485,7 +3600,7 @@ face_before_or_after_it_pos (struct it *it, int before_p) | |||
| 3485 | /* Get the face for ASCII, or unibyte. */ | 3600 | /* Get the face for ASCII, or unibyte. */ |
| 3486 | face_id = face_at_string_position (it->w, | 3601 | face_id = face_at_string_position (it->w, |
| 3487 | it->string, | 3602 | it->string, |
| 3488 | CHARPOS (pos), | 3603 | charpos, |
| 3489 | bufpos, | 3604 | bufpos, |
| 3490 | it->region_beg_charpos, | 3605 | it->region_beg_charpos, |
| 3491 | it->region_end_charpos, | 3606 | it->region_end_charpos, |
| @@ -3497,16 +3612,19 @@ face_before_or_after_it_pos (struct it *it, int before_p) | |||
| 3497 | suitable for unibyte text if IT->string is unibyte. */ | 3612 | suitable for unibyte text if IT->string is unibyte. */ |
| 3498 | if (STRING_MULTIBYTE (it->string)) | 3613 | if (STRING_MULTIBYTE (it->string)) |
| 3499 | { | 3614 | { |
| 3500 | const unsigned char *p = SDATA (it->string) + BYTEPOS (pos); | 3615 | struct text_pos pos1 = string_pos (charpos, it->string); |
| 3616 | const unsigned char *p = SDATA (it->string) + BYTEPOS (pos1); | ||
| 3501 | int c, len; | 3617 | int c, len; |
| 3502 | struct face *face = FACE_FROM_ID (it->f, face_id); | 3618 | struct face *face = FACE_FROM_ID (it->f, face_id); |
| 3503 | 3619 | ||
| 3504 | c = string_char_and_length (p, &len); | 3620 | c = string_char_and_length (p, &len); |
| 3505 | face_id = FACE_FOR_CHAR (it->f, face, c, CHARPOS (pos), it->string); | 3621 | face_id = FACE_FOR_CHAR (it->f, face, c, charpos, it->string); |
| 3506 | } | 3622 | } |
| 3507 | } | 3623 | } |
| 3508 | else | 3624 | else |
| 3509 | { | 3625 | { |
| 3626 | struct text_pos pos; | ||
| 3627 | |||
| 3510 | if ((IT_CHARPOS (*it) >= ZV && !before_p) | 3628 | if ((IT_CHARPOS (*it) >= ZV && !before_p) |
| 3511 | || (IT_CHARPOS (*it) <= BEGV && before_p)) | 3629 | || (IT_CHARPOS (*it) <= BEGV && before_p)) |
| 3512 | return it->face_id; | 3630 | return it->face_id; |
| @@ -3514,17 +3632,63 @@ face_before_or_after_it_pos (struct it *it, int before_p) | |||
| 3514 | limit = IT_CHARPOS (*it) + TEXT_PROP_DISTANCE_LIMIT; | 3632 | limit = IT_CHARPOS (*it) + TEXT_PROP_DISTANCE_LIMIT; |
| 3515 | pos = it->current.pos; | 3633 | pos = it->current.pos; |
| 3516 | 3634 | ||
| 3517 | if (before_p) | 3635 | if (!it->bidi_p) |
| 3518 | DEC_TEXT_POS (pos, it->multibyte_p); | 3636 | { |
| 3637 | if (before_p) | ||
| 3638 | DEC_TEXT_POS (pos, it->multibyte_p); | ||
| 3639 | else | ||
| 3640 | { | ||
| 3641 | if (it->what == IT_COMPOSITION) | ||
| 3642 | { | ||
| 3643 | /* For composition, we must check the position after | ||
| 3644 | the composition. */ | ||
| 3645 | pos.charpos += it->cmp_it.nchars; | ||
| 3646 | pos.bytepos += it->len; | ||
| 3647 | } | ||
| 3648 | else | ||
| 3649 | INC_TEXT_POS (pos, it->multibyte_p); | ||
| 3650 | } | ||
| 3651 | } | ||
| 3519 | else | 3652 | else |
| 3520 | { | 3653 | { |
| 3521 | if (it->what == IT_COMPOSITION) | 3654 | if (before_p) |
| 3522 | /* For composition, we must check the position after the | 3655 | { |
| 3523 | composition. */ | 3656 | /* With bidi iteration, the character before the current |
| 3524 | pos.charpos += it->cmp_it.nchars, pos.bytepos += it->len; | 3657 | in the visual order cannot be found by simple |
| 3658 | iteration, because "reverse" reordering is not | ||
| 3659 | supported. Instead, we need to use the move_it_* | ||
| 3660 | family of functions. */ | ||
| 3661 | /* Ignore face changes before the first visible | ||
| 3662 | character on this display line. */ | ||
| 3663 | if (it->current_x <= it->first_visible_x) | ||
| 3664 | return it->face_id; | ||
| 3665 | SAVE_IT (it_copy, *it, it_copy_data); | ||
| 3666 | /* Implementation note: Since move_it_in_display_line | ||
| 3667 | works in the iterator geometry, and thinks the first | ||
| 3668 | character is always the leftmost, even in R2L lines, | ||
| 3669 | we don't need to distinguish between the R2L and L2R | ||
| 3670 | cases here. */ | ||
| 3671 | move_it_in_display_line (&it_copy, ZV, | ||
| 3672 | it_copy.current_x - 1, MOVE_TO_X); | ||
| 3673 | pos = it_copy.current.pos; | ||
| 3674 | RESTORE_IT (it, it, it_copy_data); | ||
| 3675 | } | ||
| 3525 | else | 3676 | else |
| 3526 | INC_TEXT_POS (pos, it->multibyte_p); | 3677 | { |
| 3678 | /* Set charpos to the buffer position of the character | ||
| 3679 | that comes after IT's current position in the visual | ||
| 3680 | order. */ | ||
| 3681 | int n = (it->what == IT_COMPOSITION ? it->cmp_it.nchars : 1); | ||
| 3682 | |||
| 3683 | it_copy = *it; | ||
| 3684 | while (n--) | ||
| 3685 | bidi_move_to_visually_next (&it_copy.bidi_it); | ||
| 3686 | |||
| 3687 | SET_TEXT_POS (pos, | ||
| 3688 | it_copy.bidi_it.charpos, it_copy.bidi_it.bytepos); | ||
| 3689 | } | ||
| 3527 | } | 3690 | } |
| 3691 | xassert (BEGV <= CHARPOS (pos) && CHARPOS (pos) <= ZV); | ||
| 3528 | 3692 | ||
| 3529 | /* Determine face for CHARSET_ASCII, or unibyte. */ | 3693 | /* Determine face for CHARSET_ASCII, or unibyte. */ |
| 3530 | face_id = face_at_buffer_position (it->w, | 3694 | face_id = face_at_buffer_position (it->w, |
| @@ -3575,6 +3739,8 @@ handle_invisible_prop (struct it *it) | |||
| 3575 | if (!NILP (prop) | 3739 | if (!NILP (prop) |
| 3576 | && IT_STRING_CHARPOS (*it) < it->end_charpos) | 3740 | && IT_STRING_CHARPOS (*it) < it->end_charpos) |
| 3577 | { | 3741 | { |
| 3742 | EMACS_INT endpos; | ||
| 3743 | |||
| 3578 | handled = HANDLED_RECOMPUTE_PROPS; | 3744 | handled = HANDLED_RECOMPUTE_PROPS; |
| 3579 | 3745 | ||
| 3580 | /* Get the position at which the next change of the | 3746 | /* Get the position at which the next change of the |
| @@ -3589,12 +3755,37 @@ handle_invisible_prop (struct it *it) | |||
| 3589 | change in the property is at position end_charpos. | 3755 | change in the property is at position end_charpos. |
| 3590 | Move IT's current position to that position. */ | 3756 | Move IT's current position to that position. */ |
| 3591 | if (INTEGERP (end_charpos) | 3757 | if (INTEGERP (end_charpos) |
| 3592 | && XFASTINT (end_charpos) < XFASTINT (limit)) | 3758 | && (endpos = XFASTINT (end_charpos)) < XFASTINT (limit)) |
| 3593 | { | 3759 | { |
| 3594 | struct text_pos old; | 3760 | struct text_pos old; |
| 3761 | EMACS_INT oldpos; | ||
| 3762 | |||
| 3595 | old = it->current.string_pos; | 3763 | old = it->current.string_pos; |
| 3596 | IT_STRING_CHARPOS (*it) = XFASTINT (end_charpos); | 3764 | oldpos = CHARPOS (old); |
| 3597 | compute_string_pos (&it->current.string_pos, old, it->string); | 3765 | if (it->bidi_p) |
| 3766 | { | ||
| 3767 | if (it->bidi_it.first_elt | ||
| 3768 | && it->bidi_it.charpos < SCHARS (it->string)) | ||
| 3769 | bidi_paragraph_init (it->paragraph_embedding, | ||
| 3770 | &it->bidi_it, 1); | ||
| 3771 | /* Bidi-iterate out of the invisible text. */ | ||
| 3772 | do | ||
| 3773 | { | ||
| 3774 | bidi_move_to_visually_next (&it->bidi_it); | ||
| 3775 | } | ||
| 3776 | while (oldpos <= it->bidi_it.charpos | ||
| 3777 | && it->bidi_it.charpos < endpos); | ||
| 3778 | |||
| 3779 | IT_STRING_CHARPOS (*it) = it->bidi_it.charpos; | ||
| 3780 | IT_STRING_BYTEPOS (*it) = it->bidi_it.bytepos; | ||
| 3781 | if (IT_CHARPOS (*it) >= endpos) | ||
| 3782 | it->prev_stop = endpos; | ||
| 3783 | } | ||
| 3784 | else | ||
| 3785 | { | ||
| 3786 | IT_STRING_CHARPOS (*it) = XFASTINT (end_charpos); | ||
| 3787 | compute_string_pos (&it->current.string_pos, old, it->string); | ||
| 3788 | } | ||
| 3598 | } | 3789 | } |
| 3599 | else | 3790 | else |
| 3600 | { | 3791 | { |
| @@ -4244,6 +4435,7 @@ handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object, | |||
| 4244 | it->method = GET_FROM_IMAGE; | 4435 | it->method = GET_FROM_IMAGE; |
| 4245 | it->from_overlay = Qnil; | 4436 | it->from_overlay = Qnil; |
| 4246 | it->face_id = face_id; | 4437 | it->face_id = face_id; |
| 4438 | it->from_disp_prop_p = 1; | ||
| 4247 | 4439 | ||
| 4248 | /* Say that we haven't consumed the characters with | 4440 | /* Say that we haven't consumed the characters with |
| 4249 | `display' property yet. The call to pop_it in | 4441 | `display' property yet. The call to pop_it in |
| @@ -4316,6 +4508,7 @@ handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object, | |||
| 4316 | when we are finished with the glyph property value. */ | 4508 | when we are finished with the glyph property value. */ |
| 4317 | push_it (it, position); | 4509 | push_it (it, position); |
| 4318 | it->from_overlay = overlay; | 4510 | it->from_overlay = overlay; |
| 4511 | it->from_disp_prop_p = 1; | ||
| 4319 | 4512 | ||
| 4320 | if (NILP (location)) | 4513 | if (NILP (location)) |
| 4321 | it->area = TEXT_AREA; | 4514 | it->area = TEXT_AREA; |
| @@ -4333,12 +4526,34 @@ handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object, | |||
| 4333 | it->end_charpos = it->string_nchars = SCHARS (it->string); | 4526 | it->end_charpos = it->string_nchars = SCHARS (it->string); |
| 4334 | it->method = GET_FROM_STRING; | 4527 | it->method = GET_FROM_STRING; |
| 4335 | it->stop_charpos = 0; | 4528 | it->stop_charpos = 0; |
| 4529 | it->prev_stop = 0; | ||
| 4530 | it->base_level_stop = 0; | ||
| 4336 | it->string_from_display_prop_p = 1; | 4531 | it->string_from_display_prop_p = 1; |
| 4337 | /* Say that we haven't consumed the characters with | 4532 | /* Say that we haven't consumed the characters with |
| 4338 | `display' property yet. The call to pop_it in | 4533 | `display' property yet. The call to pop_it in |
| 4339 | set_iterator_to_next will clean this up. */ | 4534 | set_iterator_to_next will clean this up. */ |
| 4340 | if (BUFFERP (object)) | 4535 | if (BUFFERP (object)) |
| 4341 | *position = start_pos; | 4536 | *position = start_pos; |
| 4537 | |||
| 4538 | /* Force paragraph direction to be that of the parent | ||
| 4539 | object. If the parent object's paragraph direction is | ||
| 4540 | not yet determined, default to L2R. */ | ||
| 4541 | if (it->bidi_p && it->bidi_it.paragraph_dir == R2L) | ||
| 4542 | it->paragraph_embedding = it->bidi_it.paragraph_dir; | ||
| 4543 | else | ||
| 4544 | it->paragraph_embedding = L2R; | ||
| 4545 | |||
| 4546 | /* Set up the bidi iterator for this display string. */ | ||
| 4547 | if (it->bidi_p) | ||
| 4548 | { | ||
| 4549 | it->bidi_it.string.lstring = it->string; | ||
| 4550 | it->bidi_it.string.s = NULL; | ||
| 4551 | it->bidi_it.string.schars = it->end_charpos; | ||
| 4552 | it->bidi_it.string.bufpos = bufpos; | ||
| 4553 | it->bidi_it.string.from_disp_str = 1; | ||
| 4554 | it->bidi_it.string.unibyte = !it->multibyte_p; | ||
| 4555 | bidi_init_it (0, 0, FRAME_WINDOW_P (it->f), &it->bidi_it); | ||
| 4556 | } | ||
| 4342 | } | 4557 | } |
| 4343 | else if (CONSP (value) && EQ (XCAR (value), Qspace)) | 4558 | else if (CONSP (value) && EQ (XCAR (value), Qspace)) |
| 4344 | { | 4559 | { |
| @@ -4695,6 +4910,20 @@ next_overlay_string (struct it *it) | |||
| 4695 | it->stop_charpos = 0; | 4910 | it->stop_charpos = 0; |
| 4696 | if (it->cmp_it.stop_pos >= 0) | 4911 | if (it->cmp_it.stop_pos >= 0) |
| 4697 | it->cmp_it.stop_pos = 0; | 4912 | it->cmp_it.stop_pos = 0; |
| 4913 | it->prev_stop = 0; | ||
| 4914 | it->base_level_stop = 0; | ||
| 4915 | |||
| 4916 | /* Set up the bidi iterator for this overlay string. */ | ||
| 4917 | if (it->bidi_p) | ||
| 4918 | { | ||
| 4919 | it->bidi_it.string.lstring = it->string; | ||
| 4920 | it->bidi_it.string.s = NULL; | ||
| 4921 | it->bidi_it.string.schars = SCHARS (it->string); | ||
| 4922 | it->bidi_it.string.bufpos = it->overlay_strings_charpos; | ||
| 4923 | it->bidi_it.string.from_disp_str = it->string_from_display_prop_p; | ||
| 4924 | it->bidi_it.string.unibyte = !it->multibyte_p; | ||
| 4925 | bidi_init_it (0, 0, FRAME_WINDOW_P (it->f), &it->bidi_it); | ||
| 4926 | } | ||
| 4698 | } | 4927 | } |
| 4699 | 4928 | ||
| 4700 | CHECK_IT (it); | 4929 | CHECK_IT (it); |
| @@ -4961,8 +5190,32 @@ get_overlay_strings_1 (struct it *it, EMACS_INT charpos, int compute_stop_p) | |||
| 4961 | it->stop_charpos = 0; | 5190 | it->stop_charpos = 0; |
| 4962 | xassert (STRINGP (it->string)); | 5191 | xassert (STRINGP (it->string)); |
| 4963 | it->end_charpos = SCHARS (it->string); | 5192 | it->end_charpos = SCHARS (it->string); |
| 5193 | it->prev_stop = 0; | ||
| 5194 | it->base_level_stop = 0; | ||
| 4964 | it->multibyte_p = STRING_MULTIBYTE (it->string); | 5195 | it->multibyte_p = STRING_MULTIBYTE (it->string); |
| 4965 | it->method = GET_FROM_STRING; | 5196 | it->method = GET_FROM_STRING; |
| 5197 | it->from_disp_prop_p = 0; | ||
| 5198 | |||
| 5199 | /* Force paragraph direction to be that of the parent | ||
| 5200 | buffer. */ | ||
| 5201 | if (it->bidi_p && it->bidi_it.paragraph_dir == R2L) | ||
| 5202 | it->paragraph_embedding = it->bidi_it.paragraph_dir; | ||
| 5203 | else | ||
| 5204 | it->paragraph_embedding = L2R; | ||
| 5205 | |||
| 5206 | /* Set up the bidi iterator for this overlay string. */ | ||
| 5207 | if (it->bidi_p) | ||
| 5208 | { | ||
| 5209 | EMACS_INT pos = (charpos > 0 ? charpos : IT_CHARPOS (*it)); | ||
| 5210 | |||
| 5211 | it->bidi_it.string.lstring = it->string; | ||
| 5212 | it->bidi_it.string.s = NULL; | ||
| 5213 | it->bidi_it.string.schars = SCHARS (it->string); | ||
| 5214 | it->bidi_it.string.bufpos = pos; | ||
| 5215 | it->bidi_it.string.from_disp_str = it->string_from_display_prop_p; | ||
| 5216 | it->bidi_it.string.unibyte = !it->multibyte_p; | ||
| 5217 | bidi_init_it (0, 0, FRAME_WINDOW_P (it->f), &it->bidi_it); | ||
| 5218 | } | ||
| 4966 | return 1; | 5219 | return 1; |
| 4967 | } | 5220 | } |
| 4968 | 5221 | ||
| @@ -5037,19 +5290,30 @@ push_it (struct it *it, struct text_pos *position) | |||
| 5037 | p->string_from_display_prop_p = it->string_from_display_prop_p; | 5290 | p->string_from_display_prop_p = it->string_from_display_prop_p; |
| 5038 | p->display_ellipsis_p = 0; | 5291 | p->display_ellipsis_p = 0; |
| 5039 | p->line_wrap = it->line_wrap; | 5292 | p->line_wrap = it->line_wrap; |
| 5293 | p->bidi_p = it->bidi_p; | ||
| 5294 | p->paragraph_embedding = it->paragraph_embedding; | ||
| 5295 | p->from_disp_prop_p = it->from_disp_prop_p; | ||
| 5040 | ++it->sp; | 5296 | ++it->sp; |
| 5297 | |||
| 5298 | /* Save the state of the bidi iterator as well. */ | ||
| 5299 | if (it->bidi_p) | ||
| 5300 | bidi_push_it (&it->bidi_it); | ||
| 5041 | } | 5301 | } |
| 5042 | 5302 | ||
| 5043 | static void | 5303 | static void |
| 5044 | iterate_out_of_display_property (struct it *it) | 5304 | iterate_out_of_display_property (struct it *it) |
| 5045 | { | 5305 | { |
| 5306 | int buffer_p = BUFFERP (it->object); | ||
| 5307 | EMACS_INT eob = (buffer_p ? ZV : it->end_charpos); | ||
| 5308 | EMACS_INT bob = (buffer_p ? BEGV : 0); | ||
| 5309 | |||
| 5046 | /* Maybe initialize paragraph direction. If we are at the beginning | 5310 | /* Maybe initialize paragraph direction. If we are at the beginning |
| 5047 | of a new paragraph, next_element_from_buffer may not have a | 5311 | of a new paragraph, next_element_from_buffer may not have a |
| 5048 | chance to do that. */ | 5312 | chance to do that. */ |
| 5049 | if (it->bidi_it.first_elt && it->bidi_it.charpos < ZV) | 5313 | if (it->bidi_it.first_elt && it->bidi_it.charpos < eob) |
| 5050 | bidi_paragraph_init (it->paragraph_embedding, &it->bidi_it, 1); | 5314 | bidi_paragraph_init (it->paragraph_embedding, &it->bidi_it, 1); |
| 5051 | /* prev_stop can be zero, so check against BEGV as well. */ | 5315 | /* prev_stop can be zero, so check against BEGV as well. */ |
| 5052 | while (it->bidi_it.charpos >= BEGV | 5316 | while (it->bidi_it.charpos >= bob |
| 5053 | && it->prev_stop <= it->bidi_it.charpos | 5317 | && it->prev_stop <= it->bidi_it.charpos |
| 5054 | && it->bidi_it.charpos < CHARPOS (it->position)) | 5318 | && it->bidi_it.charpos < CHARPOS (it->position)) |
| 5055 | bidi_move_to_visually_next (&it->bidi_it); | 5319 | bidi_move_to_visually_next (&it->bidi_it); |
| @@ -5063,7 +5327,10 @@ iterate_out_of_display_property (struct it *it) | |||
| 5063 | { | 5327 | { |
| 5064 | SET_TEXT_POS (it->position, | 5328 | SET_TEXT_POS (it->position, |
| 5065 | it->bidi_it.charpos, it->bidi_it.bytepos); | 5329 | it->bidi_it.charpos, it->bidi_it.bytepos); |
| 5066 | it->current.pos = it->position; | 5330 | if (buffer_p) |
| 5331 | it->current.pos = it->position; | ||
| 5332 | else | ||
| 5333 | it->current.string_pos = it->position; | ||
| 5067 | } | 5334 | } |
| 5068 | } | 5335 | } |
| 5069 | 5336 | ||
| @@ -5077,6 +5344,7 @@ static void | |||
| 5077 | pop_it (struct it *it) | 5344 | pop_it (struct it *it) |
| 5078 | { | 5345 | { |
| 5079 | struct iterator_stack_entry *p; | 5346 | struct iterator_stack_entry *p; |
| 5347 | int from_display_prop = it->from_disp_prop_p; | ||
| 5080 | 5348 | ||
| 5081 | xassert (it->sp > 0); | 5349 | xassert (it->sp > 0); |
| 5082 | --it->sp; | 5350 | --it->sp; |
| @@ -5101,22 +5369,10 @@ pop_it (struct it *it) | |||
| 5101 | it->slice = p->u.image.slice; | 5369 | it->slice = p->u.image.slice; |
| 5102 | break; | 5370 | break; |
| 5103 | case GET_FROM_STRETCH: | 5371 | case GET_FROM_STRETCH: |
| 5104 | it->object = p->u.comp.object; | 5372 | it->object = p->u.stretch.object; |
| 5105 | break; | 5373 | break; |
| 5106 | case GET_FROM_BUFFER: | 5374 | case GET_FROM_BUFFER: |
| 5107 | it->object = it->w->buffer; | 5375 | it->object = it->w->buffer; |
| 5108 | if (it->bidi_p) | ||
| 5109 | { | ||
| 5110 | /* Bidi-iterate until we get out of the portion of text, if | ||
| 5111 | any, covered by a `display' text property or an overlay | ||
| 5112 | with `display' property. (We cannot just jump there, | ||
| 5113 | because the internal coherency of the bidi iterator state | ||
| 5114 | can not be preserved across such jumps.) We also must | ||
| 5115 | determine the paragraph base direction if the overlay we | ||
| 5116 | just processed is at the beginning of a new | ||
| 5117 | paragraph. */ | ||
| 5118 | iterate_out_of_display_property (it); | ||
| 5119 | } | ||
| 5120 | break; | 5376 | break; |
| 5121 | case GET_FROM_STRING: | 5377 | case GET_FROM_STRING: |
| 5122 | it->object = it->string; | 5378 | it->object = it->string; |
| @@ -5142,6 +5398,30 @@ pop_it (struct it *it) | |||
| 5142 | it->voffset = p->voffset; | 5398 | it->voffset = p->voffset; |
| 5143 | it->string_from_display_prop_p = p->string_from_display_prop_p; | 5399 | it->string_from_display_prop_p = p->string_from_display_prop_p; |
| 5144 | it->line_wrap = p->line_wrap; | 5400 | it->line_wrap = p->line_wrap; |
| 5401 | it->bidi_p = p->bidi_p; | ||
| 5402 | it->paragraph_embedding = p->paragraph_embedding; | ||
| 5403 | it->from_disp_prop_p = p->from_disp_prop_p; | ||
| 5404 | if (it->bidi_p) | ||
| 5405 | { | ||
| 5406 | bidi_pop_it (&it->bidi_it); | ||
| 5407 | /* Bidi-iterate until we get out of the portion of text, if any, | ||
| 5408 | covered by a `display' text property or by an overlay with | ||
| 5409 | `display' property. (We cannot just jump there, because the | ||
| 5410 | internal coherency of the bidi iterator state can not be | ||
| 5411 | preserved across such jumps.) We also must determine the | ||
| 5412 | paragraph base direction if the overlay we just processed is | ||
| 5413 | at the beginning of a new paragraph. */ | ||
| 5414 | if (from_display_prop | ||
| 5415 | && (it->method == GET_FROM_BUFFER || it->method == GET_FROM_STRING)) | ||
| 5416 | iterate_out_of_display_property (it); | ||
| 5417 | |||
| 5418 | xassert ((BUFFERP (it->object) | ||
| 5419 | && IT_CHARPOS (*it) == it->bidi_it.charpos | ||
| 5420 | && IT_BYTEPOS (*it) == it->bidi_it.bytepos) | ||
| 5421 | || (STRINGP (it->object) | ||
| 5422 | && IT_STRING_CHARPOS (*it) == it->bidi_it.charpos | ||
| 5423 | && IT_STRING_BYTEPOS (*it) == it->bidi_it.bytepos)); | ||
| 5424 | } | ||
| 5145 | } | 5425 | } |
| 5146 | 5426 | ||
| 5147 | 5427 | ||
| @@ -5225,15 +5505,16 @@ forward_to_next_line_start (struct it *it, int *skipped_p) | |||
| 5225 | 5505 | ||
| 5226 | xassert (!STRINGP (it->string)); | 5506 | xassert (!STRINGP (it->string)); |
| 5227 | 5507 | ||
| 5228 | /* If there isn't any `display' property in sight, and no | 5508 | /* If we are not bidi-reordering, and there isn't any `display' |
| 5229 | overlays, we can just use the position of the newline in | 5509 | property in sight, and no overlays, we can just use the |
| 5230 | buffer text. */ | 5510 | position of the newline in buffer text. */ |
| 5231 | if (it->stop_charpos >= limit | 5511 | if (!it->bidi_p |
| 5232 | || ((pos = Fnext_single_property_change (make_number (start), | 5512 | && (it->stop_charpos >= limit |
| 5233 | Qdisplay, | 5513 | || ((pos = Fnext_single_property_change (make_number (start), |
| 5234 | Qnil, make_number (limit)), | 5514 | Qdisplay, Qnil, |
| 5235 | NILP (pos)) | 5515 | make_number (limit)), |
| 5236 | && next_overlay_change (start) == ZV)) | 5516 | NILP (pos)) |
| 5517 | && next_overlay_change (start) == ZV))) | ||
| 5237 | { | 5518 | { |
| 5238 | IT_CHARPOS (*it) = limit; | 5519 | IT_CHARPOS (*it) = limit; |
| 5239 | IT_BYTEPOS (*it) = CHAR_TO_BYTE (limit); | 5520 | IT_BYTEPOS (*it) = CHAR_TO_BYTE (limit); |
| @@ -5291,10 +5572,13 @@ back_to_previous_visible_line_start (struct it *it) | |||
| 5291 | 5572 | ||
| 5292 | { | 5573 | { |
| 5293 | struct it it2; | 5574 | struct it it2; |
| 5575 | void *it2data = NULL; | ||
| 5294 | EMACS_INT pos; | 5576 | EMACS_INT pos; |
| 5295 | EMACS_INT beg, end; | 5577 | EMACS_INT beg, end; |
| 5296 | Lisp_Object val, overlay; | 5578 | Lisp_Object val, overlay; |
| 5297 | 5579 | ||
| 5580 | SAVE_IT (it2, *it, it2data); | ||
| 5581 | |||
| 5298 | /* If newline is part of a composition, continue from start of composition */ | 5582 | /* If newline is part of a composition, continue from start of composition */ |
| 5299 | if (find_composition (IT_CHARPOS (*it), -1, &beg, &end, &val, Qnil) | 5583 | if (find_composition (IT_CHARPOS (*it), -1, &beg, &end, &val, Qnil) |
| 5300 | && beg < IT_CHARPOS (*it)) | 5584 | && beg < IT_CHARPOS (*it)) |
| @@ -5302,20 +5586,25 @@ back_to_previous_visible_line_start (struct it *it) | |||
| 5302 | 5586 | ||
| 5303 | /* If newline is replaced by a display property, find start of overlay | 5587 | /* If newline is replaced by a display property, find start of overlay |
| 5304 | or interval and continue search from that point. */ | 5588 | or interval and continue search from that point. */ |
| 5305 | it2 = *it; | ||
| 5306 | pos = --IT_CHARPOS (it2); | 5589 | pos = --IT_CHARPOS (it2); |
| 5307 | --IT_BYTEPOS (it2); | 5590 | --IT_BYTEPOS (it2); |
| 5308 | it2.sp = 0; | 5591 | it2.sp = 0; |
| 5592 | bidi_unshelve_cache (NULL); | ||
| 5309 | it2.string_from_display_prop_p = 0; | 5593 | it2.string_from_display_prop_p = 0; |
| 5594 | it2.from_disp_prop_p = 0; | ||
| 5310 | if (handle_display_prop (&it2) == HANDLED_RETURN | 5595 | if (handle_display_prop (&it2) == HANDLED_RETURN |
| 5311 | && !NILP (val = get_char_property_and_overlay | 5596 | && !NILP (val = get_char_property_and_overlay |
| 5312 | (make_number (pos), Qdisplay, Qnil, &overlay)) | 5597 | (make_number (pos), Qdisplay, Qnil, &overlay)) |
| 5313 | && (OVERLAYP (overlay) | 5598 | && (OVERLAYP (overlay) |
| 5314 | ? (beg = OVERLAY_POSITION (OVERLAY_START (overlay))) | 5599 | ? (beg = OVERLAY_POSITION (OVERLAY_START (overlay))) |
| 5315 | : get_property_and_range (pos, Qdisplay, &val, &beg, &end, Qnil))) | 5600 | : get_property_and_range (pos, Qdisplay, &val, &beg, &end, Qnil))) |
| 5316 | goto replaced; | 5601 | { |
| 5602 | RESTORE_IT (it, it, it2data); | ||
| 5603 | goto replaced; | ||
| 5604 | } | ||
| 5317 | 5605 | ||
| 5318 | /* Newline is not replaced by anything -- so we are done. */ | 5606 | /* Newline is not replaced by anything -- so we are done. */ |
| 5607 | RESTORE_IT (it, it, it2data); | ||
| 5319 | break; | 5608 | break; |
| 5320 | 5609 | ||
| 5321 | replaced: | 5610 | replaced: |
| @@ -5382,14 +5671,29 @@ reseat_at_next_visible_line_start (struct it *it, int on_newline_p) | |||
| 5382 | { | 5671 | { |
| 5383 | if (IT_STRING_CHARPOS (*it) > 0) | 5672 | if (IT_STRING_CHARPOS (*it) > 0) |
| 5384 | { | 5673 | { |
| 5385 | --IT_STRING_CHARPOS (*it); | 5674 | if (!it->bidi_p) |
| 5386 | --IT_STRING_BYTEPOS (*it); | 5675 | { |
| 5676 | --IT_STRING_CHARPOS (*it); | ||
| 5677 | --IT_STRING_BYTEPOS (*it); | ||
| 5678 | } | ||
| 5679 | else | ||
| 5680 | /* Setting this flag will cause | ||
| 5681 | bidi_move_to_visually_next not to advance, but | ||
| 5682 | instead deliver the current character (newline), | ||
| 5683 | which is what the ON_NEWLINE_P flag wants. */ | ||
| 5684 | it->bidi_it.first_elt = 1; | ||
| 5387 | } | 5685 | } |
| 5388 | } | 5686 | } |
| 5389 | else if (IT_CHARPOS (*it) > BEGV) | 5687 | else if (IT_CHARPOS (*it) > BEGV) |
| 5390 | { | 5688 | { |
| 5391 | --IT_CHARPOS (*it); | 5689 | if (!it->bidi_p) |
| 5392 | --IT_BYTEPOS (*it); | 5690 | { |
| 5691 | --IT_CHARPOS (*it); | ||
| 5692 | --IT_BYTEPOS (*it); | ||
| 5693 | } | ||
| 5694 | /* With bidi iteration, the call to `reseat' will cause | ||
| 5695 | bidi_move_to_visually_next deliver the current character, | ||
| 5696 | the newline, instead of advancing. */ | ||
| 5393 | reseat (it, it->current.pos, 0); | 5697 | reseat (it, it->current.pos, 0); |
| 5394 | } | 5698 | } |
| 5395 | } | 5699 | } |
| @@ -5471,19 +5775,24 @@ reseat_1 (struct it *it, struct text_pos pos, int set_stop_p) | |||
| 5471 | IT_STRING_CHARPOS (*it) = -1; | 5775 | IT_STRING_CHARPOS (*it) = -1; |
| 5472 | IT_STRING_BYTEPOS (*it) = -1; | 5776 | IT_STRING_BYTEPOS (*it) = -1; |
| 5473 | it->string = Qnil; | 5777 | it->string = Qnil; |
| 5474 | it->string_from_display_prop_p = 0; | ||
| 5475 | it->method = GET_FROM_BUFFER; | 5778 | it->method = GET_FROM_BUFFER; |
| 5476 | it->object = it->w->buffer; | 5779 | it->object = it->w->buffer; |
| 5477 | it->area = TEXT_AREA; | 5780 | it->area = TEXT_AREA; |
| 5478 | it->multibyte_p = !NILP (BVAR (current_buffer, enable_multibyte_characters)); | 5781 | it->multibyte_p = !NILP (BVAR (current_buffer, enable_multibyte_characters)); |
| 5479 | it->sp = 0; | 5782 | it->sp = 0; |
| 5480 | it->string_from_display_prop_p = 0; | 5783 | it->string_from_display_prop_p = 0; |
| 5784 | it->from_disp_prop_p = 0; | ||
| 5481 | it->face_before_selective_p = 0; | 5785 | it->face_before_selective_p = 0; |
| 5482 | if (it->bidi_p) | 5786 | if (it->bidi_p) |
| 5483 | { | 5787 | { |
| 5484 | it->bidi_it.first_elt = 1; | 5788 | bidi_init_it (IT_CHARPOS (*it), IT_BYTEPOS (*it), FRAME_WINDOW_P (it->f), |
| 5789 | &it->bidi_it); | ||
| 5790 | bidi_unshelve_cache (NULL); | ||
| 5485 | it->bidi_it.paragraph_dir = NEUTRAL_DIR; | 5791 | it->bidi_it.paragraph_dir = NEUTRAL_DIR; |
| 5486 | it->bidi_it.disp_pos = -1; | 5792 | it->bidi_it.string.s = NULL; |
| 5793 | it->bidi_it.string.lstring = Qnil; | ||
| 5794 | it->bidi_it.string.bufpos = 0; | ||
| 5795 | it->bidi_it.string.unibyte = 0; | ||
| 5487 | } | 5796 | } |
| 5488 | 5797 | ||
| 5489 | if (set_stop_p) | 5798 | if (set_stop_p) |
| @@ -5534,6 +5843,10 @@ reseat_to_string (struct it *it, const char *s, Lisp_Object string, | |||
| 5534 | if (multibyte >= 0) | 5843 | if (multibyte >= 0) |
| 5535 | it->multibyte_p = multibyte > 0; | 5844 | it->multibyte_p = multibyte > 0; |
| 5536 | 5845 | ||
| 5846 | /* Bidirectional reordering of strings is controlled by the default | ||
| 5847 | value of bidi-display-reordering. */ | ||
| 5848 | it->bidi_p = !NILP (BVAR (&buffer_defaults, bidi_display_reordering)); | ||
| 5849 | |||
| 5537 | if (s == NULL) | 5850 | if (s == NULL) |
| 5538 | { | 5851 | { |
| 5539 | xassert (STRINGP (string)); | 5852 | xassert (STRINGP (string)); |
| @@ -5542,6 +5855,18 @@ reseat_to_string (struct it *it, const char *s, Lisp_Object string, | |||
| 5542 | it->end_charpos = it->string_nchars = SCHARS (string); | 5855 | it->end_charpos = it->string_nchars = SCHARS (string); |
| 5543 | it->method = GET_FROM_STRING; | 5856 | it->method = GET_FROM_STRING; |
| 5544 | it->current.string_pos = string_pos (charpos, string); | 5857 | it->current.string_pos = string_pos (charpos, string); |
| 5858 | |||
| 5859 | if (it->bidi_p) | ||
| 5860 | { | ||
| 5861 | it->bidi_it.string.lstring = string; | ||
| 5862 | it->bidi_it.string.s = NULL; | ||
| 5863 | it->bidi_it.string.schars = it->end_charpos; | ||
| 5864 | it->bidi_it.string.bufpos = 0; | ||
| 5865 | it->bidi_it.string.from_disp_str = 0; | ||
| 5866 | it->bidi_it.string.unibyte = !it->multibyte_p; | ||
| 5867 | bidi_init_it (charpos, IT_STRING_BYTEPOS (*it), | ||
| 5868 | FRAME_WINDOW_P (it->f), &it->bidi_it); | ||
| 5869 | } | ||
| 5545 | } | 5870 | } |
| 5546 | else | 5871 | else |
| 5547 | { | 5872 | { |
| @@ -5562,13 +5887,28 @@ reseat_to_string (struct it *it, const char *s, Lisp_Object string, | |||
| 5562 | it->end_charpos = it->string_nchars = strlen (s); | 5887 | it->end_charpos = it->string_nchars = strlen (s); |
| 5563 | } | 5888 | } |
| 5564 | 5889 | ||
| 5890 | if (it->bidi_p) | ||
| 5891 | { | ||
| 5892 | it->bidi_it.string.lstring = Qnil; | ||
| 5893 | it->bidi_it.string.s = s; | ||
| 5894 | it->bidi_it.string.schars = it->end_charpos; | ||
| 5895 | it->bidi_it.string.bufpos = 0; | ||
| 5896 | it->bidi_it.string.from_disp_str = 0; | ||
| 5897 | it->bidi_it.string.unibyte = !it->multibyte_p; | ||
| 5898 | bidi_init_it (charpos, IT_BYTEPOS (*it), FRAME_WINDOW_P (it->f), | ||
| 5899 | &it->bidi_it); | ||
| 5900 | } | ||
| 5565 | it->method = GET_FROM_C_STRING; | 5901 | it->method = GET_FROM_C_STRING; |
| 5566 | } | 5902 | } |
| 5567 | 5903 | ||
| 5568 | /* PRECISION > 0 means don't return more than PRECISION characters | 5904 | /* PRECISION > 0 means don't return more than PRECISION characters |
| 5569 | from the string. */ | 5905 | from the string. */ |
| 5570 | if (precision > 0 && it->end_charpos - charpos > precision) | 5906 | if (precision > 0 && it->end_charpos - charpos > precision) |
| 5571 | it->end_charpos = it->string_nchars = charpos + precision; | 5907 | { |
| 5908 | it->end_charpos = it->string_nchars = charpos + precision; | ||
| 5909 | if (it->bidi_p) | ||
| 5910 | it->bidi_it.string.schars = it->end_charpos; | ||
| 5911 | } | ||
| 5572 | 5912 | ||
| 5573 | /* FIELD_WIDTH > 0 means pad with spaces until FIELD_WIDTH | 5913 | /* FIELD_WIDTH > 0 means pad with spaces until FIELD_WIDTH |
| 5574 | characters have been returned. FIELD_WIDTH == 0 means don't pad, | 5914 | characters have been returned. FIELD_WIDTH == 0 means don't pad, |
| @@ -5576,6 +5916,9 @@ reseat_to_string (struct it *it, const char *s, Lisp_Object string, | |||
| 5576 | padding with `-' at the end of a mode line. */ | 5916 | padding with `-' at the end of a mode line. */ |
| 5577 | if (field_width < 0) | 5917 | if (field_width < 0) |
| 5578 | field_width = INFINITY; | 5918 | field_width = INFINITY; |
| 5919 | /* Implementation note: We deliberately don't enlarge | ||
| 5920 | it->bidi_it.string.schars here to fit it->end_charpos, because | ||
| 5921 | the bidi iterator cannot produce characters out of thin air. */ | ||
| 5579 | if (field_width > it->end_charpos - charpos) | 5922 | if (field_width > it->end_charpos - charpos) |
| 5580 | it->end_charpos = charpos + field_width; | 5923 | it->end_charpos = charpos + field_width; |
| 5581 | 5924 | ||
| @@ -5584,6 +5927,14 @@ reseat_to_string (struct it *it, const char *s, Lisp_Object string, | |||
| 5584 | it->dp = XCHAR_TABLE (Vstandard_display_table); | 5927 | it->dp = XCHAR_TABLE (Vstandard_display_table); |
| 5585 | 5928 | ||
| 5586 | it->stop_charpos = charpos; | 5929 | it->stop_charpos = charpos; |
| 5930 | it->prev_stop = charpos; | ||
| 5931 | it->base_level_stop = 0; | ||
| 5932 | if (it->bidi_p) | ||
| 5933 | { | ||
| 5934 | it->bidi_it.first_elt = 1; | ||
| 5935 | it->bidi_it.paragraph_dir = NEUTRAL_DIR; | ||
| 5936 | it->bidi_it.disp_pos = -1; | ||
| 5937 | } | ||
| 5587 | if (s == NULL && it->multibyte_p) | 5938 | if (s == NULL && it->multibyte_p) |
| 5588 | { | 5939 | { |
| 5589 | EMACS_INT endpos = SCHARS (it->string); | 5940 | EMACS_INT endpos = SCHARS (it->string); |
| @@ -6218,8 +6569,22 @@ set_iterator_to_next (struct it *it, int reseat_p) | |||
| 6218 | 6569 | ||
| 6219 | case GET_FROM_C_STRING: | 6570 | case GET_FROM_C_STRING: |
| 6220 | /* Current display element of IT is from a C string. */ | 6571 | /* Current display element of IT is from a C string. */ |
| 6221 | IT_BYTEPOS (*it) += it->len; | 6572 | if (!it->bidi_p |
| 6222 | IT_CHARPOS (*it) += 1; | 6573 | /* If the string position is beyond string's end, it means |
| 6574 | next_element_from_c_string is padding the string with | ||
| 6575 | blanks, in which case we bypass the bidi iterator, | ||
| 6576 | because it cannot deal with such virtual characters. */ | ||
| 6577 | || IT_CHARPOS (*it) >= it->bidi_it.string.schars) | ||
| 6578 | { | ||
| 6579 | IT_BYTEPOS (*it) += it->len; | ||
| 6580 | IT_CHARPOS (*it) += 1; | ||
| 6581 | } | ||
| 6582 | else | ||
| 6583 | { | ||
| 6584 | bidi_move_to_visually_next (&it->bidi_it); | ||
| 6585 | IT_BYTEPOS (*it) = it->bidi_it.bytepos; | ||
| 6586 | IT_CHARPOS (*it) = it->bidi_it.charpos; | ||
| 6587 | } | ||
| 6223 | break; | 6588 | break; |
| 6224 | 6589 | ||
| 6225 | case GET_FROM_DISPLAY_VECTOR: | 6590 | case GET_FROM_DISPLAY_VECTOR: |
| @@ -6273,23 +6638,95 @@ set_iterator_to_next (struct it *it, int reseat_p) | |||
| 6273 | xassert (it->s == NULL && STRINGP (it->string)); | 6638 | xassert (it->s == NULL && STRINGP (it->string)); |
| 6274 | if (it->cmp_it.id >= 0) | 6639 | if (it->cmp_it.id >= 0) |
| 6275 | { | 6640 | { |
| 6276 | IT_STRING_CHARPOS (*it) += it->cmp_it.nchars; | 6641 | int i; |
| 6277 | IT_STRING_BYTEPOS (*it) += it->cmp_it.nbytes; | 6642 | |
| 6278 | if (it->cmp_it.to < it->cmp_it.nglyphs) | 6643 | if (! it->bidi_p) |
| 6279 | it->cmp_it.from = it->cmp_it.to; | 6644 | { |
| 6645 | IT_STRING_CHARPOS (*it) += it->cmp_it.nchars; | ||
| 6646 | IT_STRING_BYTEPOS (*it) += it->cmp_it.nbytes; | ||
| 6647 | if (it->cmp_it.to < it->cmp_it.nglyphs) | ||
| 6648 | it->cmp_it.from = it->cmp_it.to; | ||
| 6649 | else | ||
| 6650 | { | ||
| 6651 | it->cmp_it.id = -1; | ||
| 6652 | composition_compute_stop_pos (&it->cmp_it, | ||
| 6653 | IT_STRING_CHARPOS (*it), | ||
| 6654 | IT_STRING_BYTEPOS (*it), | ||
| 6655 | it->end_charpos, it->string); | ||
| 6656 | } | ||
| 6657 | } | ||
| 6658 | else if (! it->cmp_it.reversed_p) | ||
| 6659 | { | ||
| 6660 | for (i = 0; i < it->cmp_it.nchars; i++) | ||
| 6661 | bidi_move_to_visually_next (&it->bidi_it); | ||
| 6662 | IT_STRING_BYTEPOS (*it) = it->bidi_it.bytepos; | ||
| 6663 | IT_STRING_CHARPOS (*it) = it->bidi_it.charpos; | ||
| 6664 | |||
| 6665 | if (it->cmp_it.to < it->cmp_it.nglyphs) | ||
| 6666 | it->cmp_it.from = it->cmp_it.to; | ||
| 6667 | else | ||
| 6668 | { | ||
| 6669 | EMACS_INT stop = it->end_charpos; | ||
| 6670 | if (it->bidi_it.scan_dir < 0) | ||
| 6671 | stop = -1; | ||
| 6672 | composition_compute_stop_pos (&it->cmp_it, | ||
| 6673 | IT_STRING_CHARPOS (*it), | ||
| 6674 | IT_STRING_BYTEPOS (*it), stop, | ||
| 6675 | it->string); | ||
| 6676 | } | ||
| 6677 | } | ||
| 6280 | else | 6678 | else |
| 6281 | { | 6679 | { |
| 6282 | it->cmp_it.id = -1; | 6680 | for (i = 0; i < it->cmp_it.nchars; i++) |
| 6283 | composition_compute_stop_pos (&it->cmp_it, | 6681 | bidi_move_to_visually_next (&it->bidi_it); |
| 6284 | IT_STRING_CHARPOS (*it), | 6682 | IT_STRING_BYTEPOS (*it) = it->bidi_it.bytepos; |
| 6285 | IT_STRING_BYTEPOS (*it), | 6683 | IT_STRING_CHARPOS (*it) = it->bidi_it.charpos; |
| 6286 | it->end_charpos, it->string); | 6684 | if (it->cmp_it.from > 0) |
| 6685 | it->cmp_it.to = it->cmp_it.from; | ||
| 6686 | else | ||
| 6687 | { | ||
| 6688 | EMACS_INT stop = it->end_charpos; | ||
| 6689 | if (it->bidi_it.scan_dir < 0) | ||
| 6690 | stop = -1; | ||
| 6691 | composition_compute_stop_pos (&it->cmp_it, | ||
| 6692 | IT_STRING_CHARPOS (*it), | ||
| 6693 | IT_STRING_BYTEPOS (*it), stop, | ||
| 6694 | it->string); | ||
| 6695 | } | ||
| 6287 | } | 6696 | } |
| 6288 | } | 6697 | } |
| 6289 | else | 6698 | else |
| 6290 | { | 6699 | { |
| 6291 | IT_STRING_BYTEPOS (*it) += it->len; | 6700 | if (!it->bidi_p |
| 6292 | IT_STRING_CHARPOS (*it) += 1; | 6701 | /* If the string position is beyond string's end, it |
| 6702 | means next_element_from_string is padding the string | ||
| 6703 | with blanks, in which case we bypass the bidi | ||
| 6704 | iterator, because it cannot deal with such virtual | ||
| 6705 | characters. */ | ||
| 6706 | || IT_STRING_CHARPOS (*it) >= it->bidi_it.string.schars) | ||
| 6707 | { | ||
| 6708 | IT_STRING_BYTEPOS (*it) += it->len; | ||
| 6709 | IT_STRING_CHARPOS (*it) += 1; | ||
| 6710 | } | ||
| 6711 | else | ||
| 6712 | { | ||
| 6713 | int prev_scan_dir = it->bidi_it.scan_dir; | ||
| 6714 | |||
| 6715 | bidi_move_to_visually_next (&it->bidi_it); | ||
| 6716 | IT_STRING_BYTEPOS (*it) = it->bidi_it.bytepos; | ||
| 6717 | IT_STRING_CHARPOS (*it) = it->bidi_it.charpos; | ||
| 6718 | if (prev_scan_dir != it->bidi_it.scan_dir) | ||
| 6719 | { | ||
| 6720 | EMACS_INT stop = it->end_charpos; | ||
| 6721 | |||
| 6722 | if (it->bidi_it.scan_dir < 0) | ||
| 6723 | stop = -1; | ||
| 6724 | composition_compute_stop_pos (&it->cmp_it, | ||
| 6725 | IT_STRING_CHARPOS (*it), | ||
| 6726 | IT_STRING_BYTEPOS (*it), stop, | ||
| 6727 | it->string); | ||
| 6728 | } | ||
| 6729 | } | ||
| 6293 | } | 6730 | } |
| 6294 | 6731 | ||
| 6295 | consider_string_end: | 6732 | consider_string_end: |
| @@ -6395,6 +6832,107 @@ next_element_from_display_vector (struct it *it) | |||
| 6395 | return 1; | 6832 | return 1; |
| 6396 | } | 6833 | } |
| 6397 | 6834 | ||
| 6835 | /* Get the first element of string/buffer in the visual order, after | ||
| 6836 | being reseated to a new position in a string or a buffer. */ | ||
| 6837 | static void | ||
| 6838 | get_visually_first_element (struct it *it) | ||
| 6839 | { | ||
| 6840 | int string_p = STRINGP (it->string) || it->s; | ||
| 6841 | EMACS_INT eob = (string_p ? it->bidi_it.string.schars : ZV); | ||
| 6842 | EMACS_INT bob = (string_p ? 0 : BEGV); | ||
| 6843 | |||
| 6844 | if (STRINGP (it->string)) | ||
| 6845 | { | ||
| 6846 | it->bidi_it.charpos = IT_STRING_CHARPOS (*it); | ||
| 6847 | it->bidi_it.bytepos = IT_STRING_BYTEPOS (*it); | ||
| 6848 | } | ||
| 6849 | else | ||
| 6850 | { | ||
| 6851 | it->bidi_it.charpos = IT_CHARPOS (*it); | ||
| 6852 | it->bidi_it.bytepos = IT_BYTEPOS (*it); | ||
| 6853 | } | ||
| 6854 | |||
| 6855 | if (it->bidi_it.charpos == eob) | ||
| 6856 | { | ||
| 6857 | /* Nothing to do, but reset the FIRST_ELT flag, like | ||
| 6858 | bidi_paragraph_init does, because we are not going to | ||
| 6859 | call it. */ | ||
| 6860 | it->bidi_it.first_elt = 0; | ||
| 6861 | } | ||
| 6862 | else if (it->bidi_it.charpos == bob | ||
| 6863 | || (!string_p | ||
| 6864 | /* FIXME: Should support all Unicode line separators. */ | ||
| 6865 | && (FETCH_CHAR (it->bidi_it.bytepos - 1) == '\n' | ||
| 6866 | || FETCH_CHAR (it->bidi_it.bytepos) == '\n'))) | ||
| 6867 | { | ||
| 6868 | /* If we are at the beginning of a line/string, we can produce | ||
| 6869 | the next element right away. */ | ||
| 6870 | bidi_paragraph_init (it->paragraph_embedding, &it->bidi_it, 1); | ||
| 6871 | bidi_move_to_visually_next (&it->bidi_it); | ||
| 6872 | } | ||
| 6873 | else | ||
| 6874 | { | ||
| 6875 | EMACS_INT orig_bytepos = it->bidi_it.bytepos; | ||
| 6876 | |||
| 6877 | /* We need to prime the bidi iterator starting at the line's or | ||
| 6878 | string's beginning, before we will be able to produce the | ||
| 6879 | next element. */ | ||
| 6880 | if (string_p) | ||
| 6881 | it->bidi_it.charpos = it->bidi_it.bytepos = 0; | ||
| 6882 | else | ||
| 6883 | { | ||
| 6884 | it->bidi_it.charpos = find_next_newline_no_quit (IT_CHARPOS (*it), | ||
| 6885 | -1); | ||
| 6886 | it->bidi_it.bytepos = CHAR_TO_BYTE (it->bidi_it.charpos); | ||
| 6887 | } | ||
| 6888 | bidi_paragraph_init (it->paragraph_embedding, &it->bidi_it, 1); | ||
| 6889 | do | ||
| 6890 | { | ||
| 6891 | /* Now return to buffer/string position where we were asked | ||
| 6892 | to get the next display element, and produce that. */ | ||
| 6893 | bidi_move_to_visually_next (&it->bidi_it); | ||
| 6894 | } | ||
| 6895 | while (it->bidi_it.bytepos != orig_bytepos | ||
| 6896 | && it->bidi_it.charpos < eob); | ||
| 6897 | } | ||
| 6898 | |||
| 6899 | /* Adjust IT's position information to where we ended up. */ | ||
| 6900 | if (STRINGP (it->string)) | ||
| 6901 | { | ||
| 6902 | IT_STRING_CHARPOS (*it) = it->bidi_it.charpos; | ||
| 6903 | IT_STRING_BYTEPOS (*it) = it->bidi_it.bytepos; | ||
| 6904 | } | ||
| 6905 | else | ||
| 6906 | { | ||
| 6907 | IT_CHARPOS (*it) = it->bidi_it.charpos; | ||
| 6908 | IT_BYTEPOS (*it) = it->bidi_it.bytepos; | ||
| 6909 | } | ||
| 6910 | |||
| 6911 | if (STRINGP (it->string) || !it->s) | ||
| 6912 | { | ||
| 6913 | EMACS_INT stop, charpos, bytepos; | ||
| 6914 | |||
| 6915 | if (STRINGP (it->string)) | ||
| 6916 | { | ||
| 6917 | xassert (!it->s); | ||
| 6918 | stop = SCHARS (it->string); | ||
| 6919 | if (stop > it->end_charpos) | ||
| 6920 | stop = it->end_charpos; | ||
| 6921 | charpos = IT_STRING_CHARPOS (*it); | ||
| 6922 | bytepos = IT_STRING_BYTEPOS (*it); | ||
| 6923 | } | ||
| 6924 | else | ||
| 6925 | { | ||
| 6926 | stop = it->end_charpos; | ||
| 6927 | charpos = IT_CHARPOS (*it); | ||
| 6928 | bytepos = IT_BYTEPOS (*it); | ||
| 6929 | } | ||
| 6930 | if (it->bidi_it.scan_dir < 0) | ||
| 6931 | stop = -1; | ||
| 6932 | composition_compute_stop_pos (&it->cmp_it, charpos, bytepos, stop, | ||
| 6933 | it->string); | ||
| 6934 | } | ||
| 6935 | } | ||
| 6398 | 6936 | ||
| 6399 | /* Load IT with the next display element from Lisp string IT->string. | 6937 | /* Load IT with the next display element from Lisp string IT->string. |
| 6400 | IT->current.string_pos is the current position within the string. | 6938 | IT->current.string_pos is the current position within the string. |
| @@ -6407,18 +6945,79 @@ next_element_from_string (struct it *it) | |||
| 6407 | struct text_pos position; | 6945 | struct text_pos position; |
| 6408 | 6946 | ||
| 6409 | xassert (STRINGP (it->string)); | 6947 | xassert (STRINGP (it->string)); |
| 6948 | xassert (!it->bidi_p || it->string == it->bidi_it.string.lstring); | ||
| 6410 | xassert (IT_STRING_CHARPOS (*it) >= 0); | 6949 | xassert (IT_STRING_CHARPOS (*it) >= 0); |
| 6411 | position = it->current.string_pos; | 6950 | position = it->current.string_pos; |
| 6412 | 6951 | ||
| 6952 | /* With bidi reordering, the character to display might not be the | ||
| 6953 | character at IT_STRING_CHARPOS. BIDI_IT.FIRST_ELT non-zero means | ||
| 6954 | that we were reseat()ed to a new string, whose paragraph | ||
| 6955 | direction is not known. */ | ||
| 6956 | if (it->bidi_p && it->bidi_it.first_elt) | ||
| 6957 | { | ||
| 6958 | get_visually_first_element (it); | ||
| 6959 | SET_TEXT_POS (position, IT_STRING_CHARPOS (*it), IT_STRING_BYTEPOS (*it)); | ||
| 6960 | } | ||
| 6961 | |||
| 6413 | /* Time to check for invisible text? */ | 6962 | /* Time to check for invisible text? */ |
| 6414 | if (IT_STRING_CHARPOS (*it) < it->end_charpos | 6963 | if (IT_STRING_CHARPOS (*it) < it->end_charpos) |
| 6415 | && IT_STRING_CHARPOS (*it) == it->stop_charpos) | ||
| 6416 | { | 6964 | { |
| 6417 | handle_stop (it); | 6965 | if (IT_STRING_CHARPOS (*it) >= it->stop_charpos) |
| 6966 | { | ||
| 6967 | if (!(!it->bidi_p | ||
| 6968 | || BIDI_AT_BASE_LEVEL (it->bidi_it) | ||
| 6969 | || IT_STRING_CHARPOS (*it) == it->stop_charpos)) | ||
| 6970 | { | ||
| 6971 | /* With bidi non-linear iteration, we could find | ||
| 6972 | ourselves far beyond the last computed stop_charpos, | ||
| 6973 | with several other stop positions in between that we | ||
| 6974 | missed. Scan them all now, in buffer's logical | ||
| 6975 | order, until we find and handle the last stop_charpos | ||
| 6976 | that precedes our current position. */ | ||
| 6977 | handle_stop_backwards (it, it->stop_charpos); | ||
| 6978 | return GET_NEXT_DISPLAY_ELEMENT (it); | ||
| 6979 | } | ||
| 6980 | else | ||
| 6981 | { | ||
| 6982 | if (it->bidi_p) | ||
| 6983 | { | ||
| 6984 | /* Take note of the stop position we just moved | ||
| 6985 | across, for when we will move back across it. */ | ||
| 6986 | it->prev_stop = it->stop_charpos; | ||
| 6987 | /* If we are at base paragraph embedding level, take | ||
| 6988 | note of the last stop position seen at this | ||
| 6989 | level. */ | ||
| 6990 | if (BIDI_AT_BASE_LEVEL (it->bidi_it)) | ||
| 6991 | it->base_level_stop = it->stop_charpos; | ||
| 6992 | } | ||
| 6993 | handle_stop (it); | ||
| 6418 | 6994 | ||
| 6419 | /* Since a handler may have changed IT->method, we must | 6995 | /* Since a handler may have changed IT->method, we must |
| 6420 | recurse here. */ | 6996 | recurse here. */ |
| 6421 | return GET_NEXT_DISPLAY_ELEMENT (it); | 6997 | return GET_NEXT_DISPLAY_ELEMENT (it); |
| 6998 | } | ||
| 6999 | } | ||
| 7000 | else if (it->bidi_p | ||
| 7001 | /* If we are before prev_stop, we may have overstepped | ||
| 7002 | on our way backwards a stop_pos, and if so, we need | ||
| 7003 | to handle that stop_pos. */ | ||
| 7004 | && IT_STRING_CHARPOS (*it) < it->prev_stop | ||
| 7005 | /* We can sometimes back up for reasons that have nothing | ||
| 7006 | to do with bidi reordering. E.g., compositions. The | ||
| 7007 | code below is only needed when we are above the base | ||
| 7008 | embedding level, so test for that explicitly. */ | ||
| 7009 | && !BIDI_AT_BASE_LEVEL (it->bidi_it)) | ||
| 7010 | { | ||
| 7011 | /* If we lost track of base_level_stop, we have no better place | ||
| 7012 | for handle_stop_backwards to start from than BEGV. This | ||
| 7013 | happens, e.g., when we were reseated to the previous | ||
| 7014 | screenful of text by vertical-motion. */ | ||
| 7015 | if (it->base_level_stop <= 0 | ||
| 7016 | || IT_STRING_CHARPOS (*it) < it->base_level_stop) | ||
| 7017 | it->base_level_stop = 0; | ||
| 7018 | handle_stop_backwards (it, it->base_level_stop); | ||
| 7019 | return GET_NEXT_DISPLAY_ELEMENT (it); | ||
| 7020 | } | ||
| 6422 | } | 7021 | } |
| 6423 | 7022 | ||
| 6424 | if (it->current.overlay_string_index >= 0) | 7023 | if (it->current.overlay_string_index >= 0) |
| @@ -6432,7 +7031,10 @@ next_element_from_string (struct it *it) | |||
| 6432 | return 0; | 7031 | return 0; |
| 6433 | } | 7032 | } |
| 6434 | else if (CHAR_COMPOSED_P (it, IT_STRING_CHARPOS (*it), | 7033 | else if (CHAR_COMPOSED_P (it, IT_STRING_CHARPOS (*it), |
| 6435 | IT_STRING_BYTEPOS (*it), SCHARS (it->string)) | 7034 | IT_STRING_BYTEPOS (*it), |
| 7035 | it->bidi_it.scan_dir < 0 | ||
| 7036 | ? -1 | ||
| 7037 | : SCHARS (it->string)) | ||
| 6436 | && next_element_from_composition (it)) | 7038 | && next_element_from_composition (it)) |
| 6437 | { | 7039 | { |
| 6438 | return 1; | 7040 | return 1; |
| @@ -6467,7 +7069,10 @@ next_element_from_string (struct it *it) | |||
| 6467 | CHARPOS (position) = BYTEPOS (position) = -1; | 7069 | CHARPOS (position) = BYTEPOS (position) = -1; |
| 6468 | } | 7070 | } |
| 6469 | else if (CHAR_COMPOSED_P (it, IT_STRING_CHARPOS (*it), | 7071 | else if (CHAR_COMPOSED_P (it, IT_STRING_CHARPOS (*it), |
| 6470 | IT_STRING_BYTEPOS (*it), it->string_nchars) | 7072 | IT_STRING_BYTEPOS (*it), |
| 7073 | it->bidi_it.scan_dir < 0 | ||
| 7074 | ? -1 | ||
| 7075 | : it->string_nchars) | ||
| 6471 | && next_element_from_composition (it)) | 7076 | && next_element_from_composition (it)) |
| 6472 | { | 7077 | { |
| 6473 | return 1; | 7078 | return 1; |
| @@ -6506,12 +7111,20 @@ next_element_from_c_string (struct it *it) | |||
| 6506 | int success_p = 1; | 7111 | int success_p = 1; |
| 6507 | 7112 | ||
| 6508 | xassert (it->s); | 7113 | xassert (it->s); |
| 7114 | xassert (!it->bidi_p || it->s == it->bidi_it.string.s); | ||
| 6509 | it->what = IT_CHARACTER; | 7115 | it->what = IT_CHARACTER; |
| 6510 | BYTEPOS (it->position) = CHARPOS (it->position) = 0; | 7116 | BYTEPOS (it->position) = CHARPOS (it->position) = 0; |
| 6511 | it->object = Qnil; | 7117 | it->object = Qnil; |
| 6512 | 7118 | ||
| 6513 | /* IT's position can be greater IT->string_nchars in case a field | 7119 | /* With bidi reordering, the character to display might not be the |
| 6514 | width or precision has been specified when the iterator was | 7120 | character at IT_CHARPOS. BIDI_IT.FIRST_ELT non-zero means that |
| 7121 | we were reseated to a new string, whose paragraph direction is | ||
| 7122 | not known. */ | ||
| 7123 | if (it->bidi_p && it->bidi_it.first_elt) | ||
| 7124 | get_visually_first_element (it); | ||
| 7125 | |||
| 7126 | /* IT's position can be greater than IT->string_nchars in case a | ||
| 7127 | field width or precision has been specified when the iterator was | ||
| 6515 | initialized. */ | 7128 | initialized. */ |
| 6516 | if (IT_CHARPOS (*it) >= it->end_charpos) | 7129 | if (IT_CHARPOS (*it) >= it->end_charpos) |
| 6517 | { | 7130 | { |
| @@ -6586,18 +7199,19 @@ next_element_from_stretch (struct it *it) | |||
| 6586 | return 1; | 7199 | return 1; |
| 6587 | } | 7200 | } |
| 6588 | 7201 | ||
| 6589 | /* Scan forward from CHARPOS in the current buffer, until we find a | 7202 | /* Scan forward from CHARPOS in the current buffer/string, until we |
| 6590 | stop position > current IT's position. Then handle the stop | 7203 | find a stop position > current IT's position. Then handle the stop |
| 6591 | position before that. This is called when we bump into a stop | 7204 | position before that. This is called when we bump into a stop |
| 6592 | position while reordering bidirectional text. CHARPOS should be | 7205 | position while reordering bidirectional text. CHARPOS should be |
| 6593 | the last previously processed stop_pos (or BEGV, if none were | 7206 | the last previously processed stop_pos (or BEGV/0, if none were |
| 6594 | processed yet) whose position is less that IT's current | 7207 | processed yet) whose position is less that IT's current |
| 6595 | position. */ | 7208 | position. */ |
| 6596 | 7209 | ||
| 6597 | static void | 7210 | static void |
| 6598 | handle_stop_backwards (struct it *it, EMACS_INT charpos) | 7211 | handle_stop_backwards (struct it *it, EMACS_INT charpos) |
| 6599 | { | 7212 | { |
| 6600 | EMACS_INT where_we_are = IT_CHARPOS (*it); | 7213 | int bufp = !STRINGP (it->string); |
| 7214 | EMACS_INT where_we_are = (bufp ? IT_CHARPOS (*it) : IT_STRING_CHARPOS (*it)); | ||
| 6601 | struct display_pos save_current = it->current; | 7215 | struct display_pos save_current = it->current; |
| 6602 | struct text_pos save_position = it->position; | 7216 | struct text_pos save_position = it->position; |
| 6603 | struct text_pos pos1; | 7217 | struct text_pos pos1; |
| @@ -6608,8 +7222,13 @@ handle_stop_backwards (struct it *it, EMACS_INT charpos) | |||
| 6608 | do | 7222 | do |
| 6609 | { | 7223 | { |
| 6610 | it->prev_stop = charpos; | 7224 | it->prev_stop = charpos; |
| 6611 | SET_TEXT_POS (pos1, charpos, CHAR_TO_BYTE (charpos)); | 7225 | if (bufp) |
| 6612 | reseat_1 (it, pos1, 0); | 7226 | { |
| 7227 | SET_TEXT_POS (pos1, charpos, CHAR_TO_BYTE (charpos)); | ||
| 7228 | reseat_1 (it, pos1, 0); | ||
| 7229 | } | ||
| 7230 | else | ||
| 7231 | it->current.string_pos = string_pos (charpos, it->string); | ||
| 6613 | compute_stop_pos (it); | 7232 | compute_stop_pos (it); |
| 6614 | /* We must advance forward, right? */ | 7233 | /* We must advance forward, right? */ |
| 6615 | if (it->stop_charpos <= it->prev_stop) | 7234 | if (it->stop_charpos <= it->prev_stop) |
| @@ -6638,6 +7257,10 @@ next_element_from_buffer (struct it *it) | |||
| 6638 | int success_p = 1; | 7257 | int success_p = 1; |
| 6639 | 7258 | ||
| 6640 | xassert (IT_CHARPOS (*it) >= BEGV); | 7259 | xassert (IT_CHARPOS (*it) >= BEGV); |
| 7260 | xassert (NILP (it->string) && !it->s); | ||
| 7261 | xassert (!it->bidi_p | ||
| 7262 | || (it->bidi_it.string.lstring == Qnil | ||
| 7263 | && it->bidi_it.string.s == NULL)); | ||
| 6641 | 7264 | ||
| 6642 | /* With bidi reordering, the character to display might not be the | 7265 | /* With bidi reordering, the character to display might not be the |
| 6643 | character at IT_CHARPOS. BIDI_IT.FIRST_ELT non-zero means that | 7266 | character at IT_CHARPOS. BIDI_IT.FIRST_ELT non-zero means that |
| @@ -6645,59 +7268,8 @@ next_element_from_buffer (struct it *it) | |||
| 6645 | a different paragraph. */ | 7268 | a different paragraph. */ |
| 6646 | if (it->bidi_p && it->bidi_it.first_elt) | 7269 | if (it->bidi_p && it->bidi_it.first_elt) |
| 6647 | { | 7270 | { |
| 6648 | it->bidi_it.charpos = IT_CHARPOS (*it); | 7271 | get_visually_first_element (it); |
| 6649 | it->bidi_it.bytepos = IT_BYTEPOS (*it); | ||
| 6650 | if (it->bidi_it.bytepos == ZV_BYTE) | ||
| 6651 | { | ||
| 6652 | /* Nothing to do, but reset the FIRST_ELT flag, like | ||
| 6653 | bidi_paragraph_init does, because we are not going to | ||
| 6654 | call it. */ | ||
| 6655 | it->bidi_it.first_elt = 0; | ||
| 6656 | } | ||
| 6657 | else if (it->bidi_it.bytepos == BEGV_BYTE | ||
| 6658 | /* FIXME: Should support all Unicode line separators. */ | ||
| 6659 | || FETCH_CHAR (it->bidi_it.bytepos - 1) == '\n' | ||
| 6660 | || FETCH_CHAR (it->bidi_it.bytepos) == '\n') | ||
| 6661 | { | ||
| 6662 | /* If we are at the beginning of a line, we can produce the | ||
| 6663 | next element right away. */ | ||
| 6664 | bidi_paragraph_init (it->paragraph_embedding, &it->bidi_it, 1); | ||
| 6665 | bidi_move_to_visually_next (&it->bidi_it); | ||
| 6666 | } | ||
| 6667 | else | ||
| 6668 | { | ||
| 6669 | EMACS_INT orig_bytepos = IT_BYTEPOS (*it); | ||
| 6670 | |||
| 6671 | /* We need to prime the bidi iterator starting at the line's | ||
| 6672 | beginning, before we will be able to produce the next | ||
| 6673 | element. */ | ||
| 6674 | IT_CHARPOS (*it) = find_next_newline_no_quit (IT_CHARPOS (*it), -1); | ||
| 6675 | IT_BYTEPOS (*it) = CHAR_TO_BYTE (IT_CHARPOS (*it)); | ||
| 6676 | it->bidi_it.charpos = IT_CHARPOS (*it); | ||
| 6677 | it->bidi_it.bytepos = IT_BYTEPOS (*it); | ||
| 6678 | bidi_paragraph_init (it->paragraph_embedding, &it->bidi_it, 1); | ||
| 6679 | do | ||
| 6680 | { | ||
| 6681 | /* Now return to buffer position where we were asked to | ||
| 6682 | get the next display element, and produce that. */ | ||
| 6683 | bidi_move_to_visually_next (&it->bidi_it); | ||
| 6684 | } | ||
| 6685 | while (it->bidi_it.bytepos != orig_bytepos | ||
| 6686 | && it->bidi_it.bytepos < ZV_BYTE); | ||
| 6687 | } | ||
| 6688 | |||
| 6689 | it->bidi_it.first_elt = 0; /* paranoia: bidi.c does this */ | ||
| 6690 | /* Adjust IT's position information to where we ended up. */ | ||
| 6691 | IT_CHARPOS (*it) = it->bidi_it.charpos; | ||
| 6692 | IT_BYTEPOS (*it) = it->bidi_it.bytepos; | ||
| 6693 | SET_TEXT_POS (it->position, IT_CHARPOS (*it), IT_BYTEPOS (*it)); | 7272 | SET_TEXT_POS (it->position, IT_CHARPOS (*it), IT_BYTEPOS (*it)); |
| 6694 | { | ||
| 6695 | EMACS_INT stop = it->end_charpos; | ||
| 6696 | if (it->bidi_it.scan_dir < 0) | ||
| 6697 | stop = -1; | ||
| 6698 | composition_compute_stop_pos (&it->cmp_it, IT_CHARPOS (*it), | ||
| 6699 | IT_BYTEPOS (*it), stop, Qnil); | ||
| 6700 | } | ||
| 6701 | } | 7273 | } |
| 6702 | 7274 | ||
| 6703 | if (IT_CHARPOS (*it) >= it->stop_charpos) | 7275 | if (IT_CHARPOS (*it) >= it->stop_charpos) |
| @@ -6756,17 +7328,23 @@ next_element_from_buffer (struct it *it) | |||
| 6756 | } | 7328 | } |
| 6757 | } | 7329 | } |
| 6758 | else if (it->bidi_p | 7330 | else if (it->bidi_p |
| 7331 | /* If we are before prev_stop, we may have overstepped on | ||
| 7332 | our way backwards a stop_pos, and if so, we need to | ||
| 7333 | handle that stop_pos. */ | ||
| 7334 | && IT_CHARPOS (*it) < it->prev_stop | ||
| 6759 | /* We can sometimes back up for reasons that have nothing | 7335 | /* We can sometimes back up for reasons that have nothing |
| 6760 | to do with bidi reordering. E.g., compositions. The | 7336 | to do with bidi reordering. E.g., compositions. The |
| 6761 | code below is only needed when we are above the base | 7337 | code below is only needed when we are above the base |
| 6762 | embedding level, so test for that explicitly. */ | 7338 | embedding level, so test for that explicitly. */ |
| 6763 | && !BIDI_AT_BASE_LEVEL (it->bidi_it) | 7339 | && !BIDI_AT_BASE_LEVEL (it->bidi_it)) |
| 6764 | && IT_CHARPOS (*it) < it->prev_stop) | 7340 | { |
| 6765 | { | 7341 | /* If we lost track of base_level_stop, we have no better place |
| 6766 | if (it->base_level_stop <= 0) | 7342 | for handle_stop_backwards to start from than BEGV. This |
| 7343 | happens, e.g., when we were reseated to the previous | ||
| 7344 | screenful of text by vertical-motion. */ | ||
| 7345 | if (it->base_level_stop <= 0 | ||
| 7346 | || IT_CHARPOS (*it) < it->base_level_stop) | ||
| 6767 | it->base_level_stop = BEGV; | 7347 | it->base_level_stop = BEGV; |
| 6768 | if (IT_CHARPOS (*it) < it->base_level_stop) | ||
| 6769 | abort (); | ||
| 6770 | handle_stop_backwards (it, it->base_level_stop); | 7348 | handle_stop_backwards (it, it->base_level_stop); |
| 6771 | return GET_NEXT_DISPLAY_ELEMENT (it); | 7349 | return GET_NEXT_DISPLAY_ELEMENT (it); |
| 6772 | } | 7350 | } |
| @@ -6970,9 +7548,11 @@ move_it_in_display_line_to (struct it *it, | |||
| 6970 | enum move_it_result result = MOVE_UNDEFINED; | 7548 | enum move_it_result result = MOVE_UNDEFINED; |
| 6971 | struct glyph_row *saved_glyph_row; | 7549 | struct glyph_row *saved_glyph_row; |
| 6972 | struct it wrap_it, atpos_it, atx_it; | 7550 | struct it wrap_it, atpos_it, atx_it; |
| 7551 | void *wrap_data = NULL, *atpos_data = NULL, *atx_data = NULL; | ||
| 6973 | int may_wrap = 0; | 7552 | int may_wrap = 0; |
| 6974 | enum it_method prev_method = it->method; | 7553 | enum it_method prev_method = it->method; |
| 6975 | EMACS_INT prev_pos = IT_CHARPOS (*it); | 7554 | EMACS_INT prev_pos = IT_CHARPOS (*it); |
| 7555 | int saw_smaller_pos = prev_pos < to_charpos; | ||
| 6976 | 7556 | ||
| 6977 | /* Don't produce glyphs in produce_glyphs. */ | 7557 | /* Don't produce glyphs in produce_glyphs. */ |
| 6978 | saved_glyph_row = it->glyph_row; | 7558 | saved_glyph_row = it->glyph_row; |
| @@ -7013,15 +7593,16 @@ move_it_in_display_line_to (struct it *it, | |||
| 7013 | ((IT)->current_x = x, (IT)->max_ascent = ascent, \ | 7593 | ((IT)->current_x = x, (IT)->max_ascent = ascent, \ |
| 7014 | (IT)->max_descent = descent) | 7594 | (IT)->max_descent = descent) |
| 7015 | 7595 | ||
| 7016 | /* Stop if we move beyond TO_CHARPOS (after an image or stretch | 7596 | /* Stop if we move beyond TO_CHARPOS (after an image or a |
| 7017 | glyph). */ | 7597 | display string or stretch glyph). */ |
| 7018 | if ((op & MOVE_TO_POS) != 0 | 7598 | if ((op & MOVE_TO_POS) != 0 |
| 7019 | && BUFFERP (it->object) | 7599 | && BUFFERP (it->object) |
| 7020 | && it->method == GET_FROM_BUFFER | 7600 | && it->method == GET_FROM_BUFFER |
| 7021 | && ((!it->bidi_p && IT_CHARPOS (*it) > to_charpos) | 7601 | && ((!it->bidi_p && IT_CHARPOS (*it) > to_charpos) |
| 7022 | || (it->bidi_p | 7602 | || (it->bidi_p |
| 7023 | && (prev_method == GET_FROM_IMAGE | 7603 | && (prev_method == GET_FROM_IMAGE |
| 7024 | || prev_method == GET_FROM_STRETCH) | 7604 | || prev_method == GET_FROM_STRETCH |
| 7605 | || prev_method == GET_FROM_STRING) | ||
| 7025 | /* Passed TO_CHARPOS from left to right. */ | 7606 | /* Passed TO_CHARPOS from left to right. */ |
| 7026 | && ((prev_pos < to_charpos | 7607 | && ((prev_pos < to_charpos |
| 7027 | && IT_CHARPOS (*it) > to_charpos) | 7608 | && IT_CHARPOS (*it) > to_charpos) |
| @@ -7038,12 +7619,9 @@ move_it_in_display_line_to (struct it *it, | |||
| 7038 | /* If wrap_it is valid, the current position might be in a | 7619 | /* If wrap_it is valid, the current position might be in a |
| 7039 | word that is wrapped. So, save the iterator in | 7620 | word that is wrapped. So, save the iterator in |
| 7040 | atpos_it and continue to see if wrapping happens. */ | 7621 | atpos_it and continue to see if wrapping happens. */ |
| 7041 | atpos_it = *it; | 7622 | SAVE_IT (atpos_it, *it, atpos_data); |
| 7042 | } | 7623 | } |
| 7043 | 7624 | ||
| 7044 | prev_method = it->method; | ||
| 7045 | if (it->method == GET_FROM_BUFFER) | ||
| 7046 | prev_pos = IT_CHARPOS (*it); | ||
| 7047 | /* Stop when ZV reached. | 7625 | /* Stop when ZV reached. |
| 7048 | We used to stop here when TO_CHARPOS reached as well, but that is | 7626 | We used to stop here when TO_CHARPOS reached as well, but that is |
| 7049 | too soon if this glyph does not fit on this line. So we handle it | 7627 | too soon if this glyph does not fit on this line. So we handle it |
| @@ -7075,18 +7653,18 @@ move_it_in_display_line_to (struct it *it, | |||
| 7075 | already found, we are done. */ | 7653 | already found, we are done. */ |
| 7076 | if (atpos_it.sp >= 0) | 7654 | if (atpos_it.sp >= 0) |
| 7077 | { | 7655 | { |
| 7078 | *it = atpos_it; | 7656 | RESTORE_IT (it, &atpos_it, atpos_data); |
| 7079 | result = MOVE_POS_MATCH_OR_ZV; | 7657 | result = MOVE_POS_MATCH_OR_ZV; |
| 7080 | goto done; | 7658 | goto done; |
| 7081 | } | 7659 | } |
| 7082 | if (atx_it.sp >= 0) | 7660 | if (atx_it.sp >= 0) |
| 7083 | { | 7661 | { |
| 7084 | *it = atx_it; | 7662 | RESTORE_IT (it, &atx_it, atx_data); |
| 7085 | result = MOVE_X_REACHED; | 7663 | result = MOVE_X_REACHED; |
| 7086 | goto done; | 7664 | goto done; |
| 7087 | } | 7665 | } |
| 7088 | /* Otherwise, we can wrap here. */ | 7666 | /* Otherwise, we can wrap here. */ |
| 7089 | wrap_it = *it; | 7667 | SAVE_IT (wrap_it, *it, wrap_data); |
| 7090 | may_wrap = 0; | 7668 | may_wrap = 0; |
| 7091 | } | 7669 | } |
| 7092 | } | 7670 | } |
| @@ -7107,6 +7685,9 @@ move_it_in_display_line_to (struct it *it, | |||
| 7107 | 7685 | ||
| 7108 | if (it->area != TEXT_AREA) | 7686 | if (it->area != TEXT_AREA) |
| 7109 | { | 7687 | { |
| 7688 | prev_method = it->method; | ||
| 7689 | if (it->method == GET_FROM_BUFFER) | ||
| 7690 | prev_pos = IT_CHARPOS (*it); | ||
| 7110 | set_iterator_to_next (it, 1); | 7691 | set_iterator_to_next (it, 1); |
| 7111 | if (IT_CHARPOS (*it) < CHARPOS (this_line_min_pos)) | 7692 | if (IT_CHARPOS (*it) < CHARPOS (this_line_min_pos)) |
| 7112 | SET_TEXT_POS (this_line_min_pos, | 7693 | SET_TEXT_POS (this_line_min_pos, |
| @@ -7154,7 +7735,7 @@ move_it_in_display_line_to (struct it *it, | |||
| 7154 | goto buffer_pos_reached; | 7735 | goto buffer_pos_reached; |
| 7155 | if (atpos_it.sp < 0) | 7736 | if (atpos_it.sp < 0) |
| 7156 | { | 7737 | { |
| 7157 | atpos_it = *it; | 7738 | SAVE_IT (atpos_it, *it, atpos_data); |
| 7158 | IT_RESET_X_ASCENT_DESCENT (&atpos_it); | 7739 | IT_RESET_X_ASCENT_DESCENT (&atpos_it); |
| 7159 | } | 7740 | } |
| 7160 | } | 7741 | } |
| @@ -7168,7 +7749,7 @@ move_it_in_display_line_to (struct it *it, | |||
| 7168 | } | 7749 | } |
| 7169 | if (atx_it.sp < 0) | 7750 | if (atx_it.sp < 0) |
| 7170 | { | 7751 | { |
| 7171 | atx_it = *it; | 7752 | SAVE_IT (atx_it, *it, atx_data); |
| 7172 | IT_RESET_X_ASCENT_DESCENT (&atx_it); | 7753 | IT_RESET_X_ASCENT_DESCENT (&atx_it); |
| 7173 | } | 7754 | } |
| 7174 | } | 7755 | } |
| @@ -7212,12 +7793,15 @@ move_it_in_display_line_to (struct it *it, | |||
| 7212 | if (it->line_wrap == WORD_WRAP | 7793 | if (it->line_wrap == WORD_WRAP |
| 7213 | && atpos_it.sp < 0) | 7794 | && atpos_it.sp < 0) |
| 7214 | { | 7795 | { |
| 7215 | atpos_it = *it; | 7796 | SAVE_IT (atpos_it, *it, atpos_data); |
| 7216 | atpos_it.current_x = x_before_this_char; | 7797 | atpos_it.current_x = x_before_this_char; |
| 7217 | atpos_it.hpos = hpos_before_this_char; | 7798 | atpos_it.hpos = hpos_before_this_char; |
| 7218 | } | 7799 | } |
| 7219 | } | 7800 | } |
| 7220 | 7801 | ||
| 7802 | prev_method = it->method; | ||
| 7803 | if (it->method == GET_FROM_BUFFER) | ||
| 7804 | prev_pos = IT_CHARPOS (*it); | ||
| 7221 | set_iterator_to_next (it, 1); | 7805 | set_iterator_to_next (it, 1); |
| 7222 | if (IT_CHARPOS (*it) < CHARPOS (this_line_min_pos)) | 7806 | if (IT_CHARPOS (*it) < CHARPOS (this_line_min_pos)) |
| 7223 | SET_TEXT_POS (this_line_min_pos, | 7807 | SET_TEXT_POS (this_line_min_pos, |
| @@ -7257,7 +7841,7 @@ move_it_in_display_line_to (struct it *it, | |||
| 7257 | 7841 | ||
| 7258 | if (wrap_it.sp >= 0) | 7842 | if (wrap_it.sp >= 0) |
| 7259 | { | 7843 | { |
| 7260 | *it = wrap_it; | 7844 | RESTORE_IT (it, &wrap_it, wrap_data); |
| 7261 | atpos_it.sp = -1; | 7845 | atpos_it.sp = -1; |
| 7262 | atx_it.sp = -1; | 7846 | atx_it.sp = -1; |
| 7263 | } | 7847 | } |
| @@ -7274,7 +7858,7 @@ move_it_in_display_line_to (struct it *it, | |||
| 7274 | goto buffer_pos_reached; | 7858 | goto buffer_pos_reached; |
| 7275 | if (it->line_wrap == WORD_WRAP && atpos_it.sp < 0) | 7859 | if (it->line_wrap == WORD_WRAP && atpos_it.sp < 0) |
| 7276 | { | 7860 | { |
| 7277 | atpos_it = *it; | 7861 | SAVE_IT (atpos_it, *it, atpos_data); |
| 7278 | IT_RESET_X_ASCENT_DESCENT (&atpos_it); | 7862 | IT_RESET_X_ASCENT_DESCENT (&atpos_it); |
| 7279 | } | 7863 | } |
| 7280 | } | 7864 | } |
| @@ -7311,10 +7895,20 @@ move_it_in_display_line_to (struct it *it, | |||
| 7311 | /* Is this a line end? If yes, we're done. */ | 7895 | /* Is this a line end? If yes, we're done. */ |
| 7312 | if (ITERATOR_AT_END_OF_LINE_P (it)) | 7896 | if (ITERATOR_AT_END_OF_LINE_P (it)) |
| 7313 | { | 7897 | { |
| 7314 | result = MOVE_NEWLINE_OR_CR; | 7898 | /* If we are past TO_CHARPOS, but never saw any character |
| 7899 | positions smaller than TO_CHARPOS, return | ||
| 7900 | MOVE_POS_MATCH_OR_ZV, like the unidirectional display | ||
| 7901 | did. */ | ||
| 7902 | if ((op & MOVE_TO_POS) != 0 | ||
| 7903 | && !saw_smaller_pos | ||
| 7904 | && IT_CHARPOS (*it) > to_charpos) | ||
| 7905 | result = MOVE_POS_MATCH_OR_ZV; | ||
| 7906 | else | ||
| 7907 | result = MOVE_NEWLINE_OR_CR; | ||
| 7315 | break; | 7908 | break; |
| 7316 | } | 7909 | } |
| 7317 | 7910 | ||
| 7911 | prev_method = it->method; | ||
| 7318 | if (it->method == GET_FROM_BUFFER) | 7912 | if (it->method == GET_FROM_BUFFER) |
| 7319 | prev_pos = IT_CHARPOS (*it); | 7913 | prev_pos = IT_CHARPOS (*it); |
| 7320 | /* The current display element has been consumed. Advance | 7914 | /* The current display element has been consumed. Advance |
| @@ -7322,6 +7916,8 @@ move_it_in_display_line_to (struct it *it, | |||
| 7322 | set_iterator_to_next (it, 1); | 7916 | set_iterator_to_next (it, 1); |
| 7323 | if (IT_CHARPOS (*it) < CHARPOS (this_line_min_pos)) | 7917 | if (IT_CHARPOS (*it) < CHARPOS (this_line_min_pos)) |
| 7324 | SET_TEXT_POS (this_line_min_pos, IT_CHARPOS (*it), IT_BYTEPOS (*it)); | 7918 | SET_TEXT_POS (this_line_min_pos, IT_CHARPOS (*it), IT_BYTEPOS (*it)); |
| 7919 | if (IT_CHARPOS (*it) < to_charpos) | ||
| 7920 | saw_smaller_pos = 1; | ||
| 7325 | 7921 | ||
| 7326 | /* Stop if lines are truncated and IT's current x-position is | 7922 | /* Stop if lines are truncated and IT's current x-position is |
| 7327 | past the right edge of the window now. */ | 7923 | past the right edge of the window now. */ |
| @@ -7354,12 +7950,19 @@ move_it_in_display_line_to (struct it *it, | |||
| 7354 | /* If we scanned beyond to_pos and didn't find a point to wrap at, | 7950 | /* If we scanned beyond to_pos and didn't find a point to wrap at, |
| 7355 | restore the saved iterator. */ | 7951 | restore the saved iterator. */ |
| 7356 | if (atpos_it.sp >= 0) | 7952 | if (atpos_it.sp >= 0) |
| 7357 | *it = atpos_it; | 7953 | RESTORE_IT (it, &atpos_it, atpos_data); |
| 7358 | else if (atx_it.sp >= 0) | 7954 | else if (atx_it.sp >= 0) |
| 7359 | *it = atx_it; | 7955 | RESTORE_IT (it, &atx_it, atx_data); |
| 7360 | 7956 | ||
| 7361 | done: | 7957 | done: |
| 7362 | 7958 | ||
| 7959 | if (atpos_data) | ||
| 7960 | xfree (atpos_data); | ||
| 7961 | if (atx_data) | ||
| 7962 | xfree (atx_data); | ||
| 7963 | if (wrap_data) | ||
| 7964 | xfree (wrap_data); | ||
| 7965 | |||
| 7363 | /* Restore the iterator settings altered at the beginning of this | 7966 | /* Restore the iterator settings altered at the beginning of this |
| 7364 | function. */ | 7967 | function. */ |
| 7365 | it->glyph_row = saved_glyph_row; | 7968 | it->glyph_row = saved_glyph_row; |
| @@ -7375,8 +7978,12 @@ move_it_in_display_line (struct it *it, | |||
| 7375 | if (it->line_wrap == WORD_WRAP | 7978 | if (it->line_wrap == WORD_WRAP |
| 7376 | && (op & MOVE_TO_X)) | 7979 | && (op & MOVE_TO_X)) |
| 7377 | { | 7980 | { |
| 7378 | struct it save_it = *it; | 7981 | struct it save_it; |
| 7379 | int skip = move_it_in_display_line_to (it, to_charpos, to_x, op); | 7982 | void *save_data = NULL; |
| 7983 | int skip; | ||
| 7984 | |||
| 7985 | SAVE_IT (save_it, *it, save_data); | ||
| 7986 | skip = move_it_in_display_line_to (it, to_charpos, to_x, op); | ||
| 7380 | /* When word-wrap is on, TO_X may lie past the end | 7987 | /* When word-wrap is on, TO_X may lie past the end |
| 7381 | of a wrapped line. Then it->current is the | 7988 | of a wrapped line. Then it->current is the |
| 7382 | character on the next line, so backtrack to the | 7989 | character on the next line, so backtrack to the |
| @@ -7384,10 +7991,12 @@ move_it_in_display_line (struct it *it, | |||
| 7384 | if (skip == MOVE_LINE_CONTINUED) | 7991 | if (skip == MOVE_LINE_CONTINUED) |
| 7385 | { | 7992 | { |
| 7386 | int prev_x = max (it->current_x - 1, 0); | 7993 | int prev_x = max (it->current_x - 1, 0); |
| 7387 | *it = save_it; | 7994 | RESTORE_IT (it, &save_it, save_data); |
| 7388 | move_it_in_display_line_to | 7995 | move_it_in_display_line_to |
| 7389 | (it, -1, prev_x, MOVE_TO_X); | 7996 | (it, -1, prev_x, MOVE_TO_X); |
| 7390 | } | 7997 | } |
| 7998 | else | ||
| 7999 | xfree (save_data); | ||
| 7391 | } | 8000 | } |
| 7392 | else | 8001 | else |
| 7393 | move_it_in_display_line_to (it, to_charpos, to_x, op); | 8002 | move_it_in_display_line_to (it, to_charpos, to_x, op); |
| @@ -7402,14 +8011,15 @@ move_it_in_display_line (struct it *it, | |||
| 7402 | description of enum move_operation_enum. | 8011 | description of enum move_operation_enum. |
| 7403 | 8012 | ||
| 7404 | If TO_CHARPOS is in invisible text, e.g. a truncated part of a | 8013 | If TO_CHARPOS is in invisible text, e.g. a truncated part of a |
| 7405 | screen line, this function will set IT to the next position > | 8014 | screen line, this function will set IT to the next position that is |
| 7406 | TO_CHARPOS. */ | 8015 | displayed to the right of TO_CHARPOS on the screen. */ |
| 7407 | 8016 | ||
| 7408 | void | 8017 | void |
| 7409 | move_it_to (struct it *it, EMACS_INT to_charpos, int to_x, int to_y, int to_vpos, int op) | 8018 | move_it_to (struct it *it, EMACS_INT to_charpos, int to_x, int to_y, int to_vpos, int op) |
| 7410 | { | 8019 | { |
| 7411 | enum move_it_result skip, skip2 = MOVE_X_REACHED; | 8020 | enum move_it_result skip, skip2 = MOVE_X_REACHED; |
| 7412 | int line_height, line_start_x = 0, reached = 0; | 8021 | int line_height, line_start_x = 0, reached = 0; |
| 8022 | void *backup_data = NULL; | ||
| 7413 | 8023 | ||
| 7414 | for (;;) | 8024 | for (;;) |
| 7415 | { | 8025 | { |
| @@ -7462,7 +8072,7 @@ move_it_to (struct it *it, EMACS_INT to_charpos, int to_x, int to_y, int to_vpos | |||
| 7462 | struct it it_backup; | 8072 | struct it it_backup; |
| 7463 | 8073 | ||
| 7464 | if (it->line_wrap == WORD_WRAP) | 8074 | if (it->line_wrap == WORD_WRAP) |
| 7465 | it_backup = *it; | 8075 | SAVE_IT (it_backup, *it, backup_data); |
| 7466 | 8076 | ||
| 7467 | /* TO_Y specified means stop at TO_X in the line containing | 8077 | /* TO_Y specified means stop at TO_X in the line containing |
| 7468 | TO_Y---or at TO_CHARPOS if this is reached first. The | 8078 | TO_Y---or at TO_CHARPOS if this is reached first. The |
| @@ -7496,7 +8106,7 @@ move_it_to (struct it *it, EMACS_INT to_charpos, int to_x, int to_y, int to_vpos | |||
| 7496 | reached = 6; | 8106 | reached = 6; |
| 7497 | break; | 8107 | break; |
| 7498 | } | 8108 | } |
| 7499 | it_backup = *it; | 8109 | SAVE_IT (it_backup, *it, backup_data); |
| 7500 | TRACE_MOVE ((stderr, "move_it: from %d\n", IT_CHARPOS (*it))); | 8110 | TRACE_MOVE ((stderr, "move_it: from %d\n", IT_CHARPOS (*it))); |
| 7501 | skip2 = move_it_in_display_line_to (it, to_charpos, -1, | 8111 | skip2 = move_it_in_display_line_to (it, to_charpos, -1, |
| 7502 | op & MOVE_TO_POS); | 8112 | op & MOVE_TO_POS); |
| @@ -7510,7 +8120,7 @@ move_it_to (struct it *it, EMACS_INT to_charpos, int to_x, int to_y, int to_vpos | |||
| 7510 | /* If TO_Y is in this line and TO_X was reached | 8120 | /* If TO_Y is in this line and TO_X was reached |
| 7511 | above, we scanned too far. We have to restore | 8121 | above, we scanned too far. We have to restore |
| 7512 | IT's settings to the ones before skipping. */ | 8122 | IT's settings to the ones before skipping. */ |
| 7513 | *it = it_backup; | 8123 | RESTORE_IT (it, &it_backup, backup_data); |
| 7514 | reached = 6; | 8124 | reached = 6; |
| 7515 | } | 8125 | } |
| 7516 | else | 8126 | else |
| @@ -7537,7 +8147,7 @@ move_it_to (struct it *it, EMACS_INT to_charpos, int to_x, int to_y, int to_vpos | |||
| 7537 | && it->line_wrap == WORD_WRAP) | 8147 | && it->line_wrap == WORD_WRAP) |
| 7538 | { | 8148 | { |
| 7539 | int prev_x = max (it->current_x - 1, 0); | 8149 | int prev_x = max (it->current_x - 1, 0); |
| 7540 | *it = it_backup; | 8150 | RESTORE_IT (it, &it_backup, backup_data); |
| 7541 | skip = move_it_in_display_line_to | 8151 | skip = move_it_in_display_line_to |
| 7542 | (it, -1, prev_x, MOVE_TO_X); | 8152 | (it, -1, prev_x, MOVE_TO_X); |
| 7543 | } | 8153 | } |
| @@ -7644,6 +8254,9 @@ move_it_to (struct it *it, EMACS_INT to_charpos, int to_x, int to_y, int to_vpos | |||
| 7644 | last_max_ascent = it->max_ascent; | 8254 | last_max_ascent = it->max_ascent; |
| 7645 | } | 8255 | } |
| 7646 | 8256 | ||
| 8257 | if (backup_data) | ||
| 8258 | xfree (backup_data); | ||
| 8259 | |||
| 7647 | TRACE_MOVE ((stderr, "move_it_to: reached %d\n", reached)); | 8260 | TRACE_MOVE ((stderr, "move_it_to: reached %d\n", reached)); |
| 7648 | } | 8261 | } |
| 7649 | 8262 | ||
| @@ -7661,6 +8274,7 @@ move_it_vertically_backward (struct it *it, int dy) | |||
| 7661 | { | 8274 | { |
| 7662 | int nlines, h; | 8275 | int nlines, h; |
| 7663 | struct it it2, it3; | 8276 | struct it it2, it3; |
| 8277 | void *it2data = NULL, *it3data = NULL; | ||
| 7664 | EMACS_INT start_pos; | 8278 | EMACS_INT start_pos; |
| 7665 | 8279 | ||
| 7666 | move_further_back: | 8280 | move_further_back: |
| @@ -7689,7 +8303,7 @@ move_it_vertically_backward (struct it *it, int dy) | |||
| 7689 | start of the next line so that we get its height. We need this | 8303 | start of the next line so that we get its height. We need this |
| 7690 | height to be able to tell whether we reached the specified | 8304 | height to be able to tell whether we reached the specified |
| 7691 | y-distance. */ | 8305 | y-distance. */ |
| 7692 | it2 = *it; | 8306 | SAVE_IT (it2, *it, it2data); |
| 7693 | it2.max_ascent = it2.max_descent = 0; | 8307 | it2.max_ascent = it2.max_descent = 0; |
| 7694 | do | 8308 | do |
| 7695 | { | 8309 | { |
| @@ -7698,7 +8312,7 @@ move_it_vertically_backward (struct it *it, int dy) | |||
| 7698 | } | 8312 | } |
| 7699 | while (!IT_POS_VALID_AFTER_MOVE_P (&it2)); | 8313 | while (!IT_POS_VALID_AFTER_MOVE_P (&it2)); |
| 7700 | xassert (IT_CHARPOS (*it) >= BEGV); | 8314 | xassert (IT_CHARPOS (*it) >= BEGV); |
| 7701 | it3 = it2; | 8315 | SAVE_IT (it3, it2, it3data); |
| 7702 | 8316 | ||
| 7703 | move_it_to (&it2, start_pos, -1, -1, -1, MOVE_TO_POS); | 8317 | move_it_to (&it2, start_pos, -1, -1, -1, MOVE_TO_POS); |
| 7704 | xassert (IT_CHARPOS (*it) >= BEGV); | 8318 | xassert (IT_CHARPOS (*it) >= BEGV); |
| @@ -7717,8 +8331,10 @@ move_it_vertically_backward (struct it *it, int dy) | |||
| 7717 | { | 8331 | { |
| 7718 | /* DY == 0 means move to the start of the screen line. The | 8332 | /* DY == 0 means move to the start of the screen line. The |
| 7719 | value of nlines is > 0 if continuation lines were involved. */ | 8333 | value of nlines is > 0 if continuation lines were involved. */ |
| 8334 | RESTORE_IT (it, it, it2data); | ||
| 7720 | if (nlines > 0) | 8335 | if (nlines > 0) |
| 7721 | move_it_by_lines (it, nlines); | 8336 | move_it_by_lines (it, nlines); |
| 8337 | xfree (it3data); | ||
| 7722 | } | 8338 | } |
| 7723 | else | 8339 | else |
| 7724 | { | 8340 | { |
| @@ -7726,9 +8342,13 @@ move_it_vertically_backward (struct it *it, int dy) | |||
| 7726 | Note that H has been subtracted in front of the if-statement. */ | 8342 | Note that H has been subtracted in front of the if-statement. */ |
| 7727 | int target_y = it->current_y + h - dy; | 8343 | int target_y = it->current_y + h - dy; |
| 7728 | int y0 = it3.current_y; | 8344 | int y0 = it3.current_y; |
| 7729 | int y1 = line_bottom_y (&it3); | 8345 | int y1; |
| 7730 | int line_height = y1 - y0; | 8346 | int line_height; |
| 7731 | 8347 | ||
| 8348 | RESTORE_IT (&it3, &it3, it3data); | ||
| 8349 | y1 = line_bottom_y (&it3); | ||
| 8350 | line_height = y1 - y0; | ||
| 8351 | RESTORE_IT (it, it, it2data); | ||
| 7732 | /* If we did not reach target_y, try to move further backward if | 8352 | /* If we did not reach target_y, try to move further backward if |
| 7733 | we can. If we moved too far backward, try to move forward. */ | 8353 | we can. If we moved too far backward, try to move forward. */ |
| 7734 | if (target_y < it->current_y | 8354 | if (target_y < it->current_y |
| @@ -7855,6 +8475,7 @@ move_it_by_lines (struct it *it, int dvpos) | |||
| 7855 | else | 8475 | else |
| 7856 | { | 8476 | { |
| 7857 | struct it it2; | 8477 | struct it it2; |
| 8478 | void *it2data = NULL; | ||
| 7858 | EMACS_INT start_charpos, i; | 8479 | EMACS_INT start_charpos, i; |
| 7859 | 8480 | ||
| 7860 | /* Start at the beginning of the screen line containing IT's | 8481 | /* Start at the beginning of the screen line containing IT's |
| @@ -7890,7 +8511,7 @@ move_it_by_lines (struct it *it, int dvpos) | |||
| 7890 | 8511 | ||
| 7891 | /* Above call may have moved too far if continuation lines | 8512 | /* Above call may have moved too far if continuation lines |
| 7892 | are involved. Scan forward and see if it did. */ | 8513 | are involved. Scan forward and see if it did. */ |
| 7893 | it2 = *it; | 8514 | SAVE_IT (it2, *it, it2data); |
| 7894 | it2.vpos = it2.current_y = 0; | 8515 | it2.vpos = it2.current_y = 0; |
| 7895 | move_it_to (&it2, start_charpos, -1, -1, -1, MOVE_TO_POS); | 8516 | move_it_to (&it2, start_charpos, -1, -1, -1, MOVE_TO_POS); |
| 7896 | it->vpos -= it2.vpos; | 8517 | it->vpos -= it2.vpos; |
| @@ -7901,12 +8522,18 @@ move_it_by_lines (struct it *it, int dvpos) | |||
| 7901 | if (it2.vpos > -dvpos) | 8522 | if (it2.vpos > -dvpos) |
| 7902 | { | 8523 | { |
| 7903 | int delta = it2.vpos + dvpos; | 8524 | int delta = it2.vpos + dvpos; |
| 7904 | it2 = *it; | 8525 | |
| 8526 | RESTORE_IT (&it2, &it2, it2data); | ||
| 8527 | SAVE_IT (it2, *it, it2data); | ||
| 7905 | move_it_to (it, -1, -1, -1, it->vpos + delta, MOVE_TO_VPOS); | 8528 | move_it_to (it, -1, -1, -1, it->vpos + delta, MOVE_TO_VPOS); |
| 7906 | /* Move back again if we got too far ahead. */ | 8529 | /* Move back again if we got too far ahead. */ |
| 7907 | if (IT_CHARPOS (*it) >= start_charpos) | 8530 | if (IT_CHARPOS (*it) >= start_charpos) |
| 7908 | *it = it2; | 8531 | RESTORE_IT (it, &it2, it2data); |
| 8532 | else | ||
| 8533 | xfree (it2data); | ||
| 7909 | } | 8534 | } |
| 8535 | else | ||
| 8536 | RESTORE_IT (it, it, it2data); | ||
| 7910 | } | 8537 | } |
| 7911 | } | 8538 | } |
| 7912 | 8539 | ||
| @@ -10393,7 +11020,7 @@ display_tool_bar_line (struct it *it, int height) | |||
| 10393 | ++i; | 11020 | ++i; |
| 10394 | } | 11021 | } |
| 10395 | 11022 | ||
| 10396 | /* Stop at line ends. */ | 11023 | /* Stop at line end. */ |
| 10397 | if (ITERATOR_AT_END_OF_LINE_P (it)) | 11024 | if (ITERATOR_AT_END_OF_LINE_P (it)) |
| 10398 | break; | 11025 | break; |
| 10399 | 11026 | ||
| @@ -10476,6 +11103,7 @@ tool_bar_lines_needed (struct frame *f, int *n_rows) | |||
| 10476 | it.first_visible_x = 0; | 11103 | it.first_visible_x = 0; |
| 10477 | it.last_visible_x = FRAME_TOTAL_COLS (f) * FRAME_COLUMN_WIDTH (f); | 11104 | it.last_visible_x = FRAME_TOTAL_COLS (f) * FRAME_COLUMN_WIDTH (f); |
| 10478 | reseat_to_string (&it, NULL, f->desired_tool_bar_string, 0, 0, 0, -1); | 11105 | reseat_to_string (&it, NULL, f->desired_tool_bar_string, 0, 0, 0, -1); |
| 11106 | it.paragraph_embedding = L2R; | ||
| 10479 | 11107 | ||
| 10480 | while (!ITERATOR_AT_END_P (&it)) | 11108 | while (!ITERATOR_AT_END_P (&it)) |
| 10481 | { | 11109 | { |
| @@ -10558,6 +11186,14 @@ redisplay_tool_bar (struct frame *f) | |||
| 10558 | /* Build a string that represents the contents of the tool-bar. */ | 11186 | /* Build a string that represents the contents of the tool-bar. */ |
| 10559 | build_desired_tool_bar_string (f); | 11187 | build_desired_tool_bar_string (f); |
| 10560 | reseat_to_string (&it, NULL, f->desired_tool_bar_string, 0, 0, 0, -1); | 11188 | reseat_to_string (&it, NULL, f->desired_tool_bar_string, 0, 0, 0, -1); |
| 11189 | /* FIXME: This should be controlled by a user option. But it | ||
| 11190 | doesn't make sense to have an R2L tool bar if the menu bar cannot | ||
| 11191 | be drawn also R2L, and making the menu bar R2L is tricky due | ||
| 11192 | toolkit-specific code that implements it. If an R2L tool bar is | ||
| 11193 | ever supported, display_tool_bar_line should also be augmented to | ||
| 11194 | call unproduce_glyphs like display_line and display_string | ||
| 11195 | do. */ | ||
| 11196 | it.paragraph_embedding = L2R; | ||
| 10561 | 11197 | ||
| 10562 | if (f->n_tool_bar_rows == 0) | 11198 | if (f->n_tool_bar_rows == 0) |
| 10563 | { | 11199 | { |
| @@ -13245,14 +13881,18 @@ try_scrolling (Lisp_Object window, int just_this_one_p, | |||
| 13245 | which was computed as distance from window bottom to | 13881 | which was computed as distance from window bottom to |
| 13246 | point. This matters when lines at window top and lines | 13882 | point. This matters when lines at window top and lines |
| 13247 | below window bottom have different height. */ | 13883 | below window bottom have different height. */ |
| 13248 | struct it it1 = it; | 13884 | struct it it1; |
| 13885 | void *it1data = NULL; | ||
| 13249 | /* We use a temporary it1 because line_bottom_y can modify | 13886 | /* We use a temporary it1 because line_bottom_y can modify |
| 13250 | its argument, if it moves one line down; see there. */ | 13887 | its argument, if it moves one line down; see there. */ |
| 13251 | int start_y = line_bottom_y (&it1); | 13888 | int start_y; |
| 13252 | 13889 | ||
| 13890 | SAVE_IT (it1, it, it1data); | ||
| 13891 | start_y = line_bottom_y (&it1); | ||
| 13253 | do { | 13892 | do { |
| 13893 | RESTORE_IT (&it, &it, it1data); | ||
| 13254 | move_it_by_lines (&it, 1); | 13894 | move_it_by_lines (&it, 1); |
| 13255 | it1 = it; | 13895 | SAVE_IT (it1, it, it1data); |
| 13256 | } while (line_bottom_y (&it1) - start_y < amount_to_scroll); | 13896 | } while (line_bottom_y (&it1) - start_y < amount_to_scroll); |
| 13257 | } | 13897 | } |
| 13258 | 13898 | ||
| @@ -14360,10 +15000,13 @@ redisplay_window (Lisp_Object window, int just_this_one_p) | |||
| 14360 | && BEGV <= CHARPOS (startp) && CHARPOS (startp) <= ZV) | 15000 | && BEGV <= CHARPOS (startp) && CHARPOS (startp) <= ZV) |
| 14361 | { | 15001 | { |
| 14362 | struct it it1; | 15002 | struct it it1; |
| 15003 | void *it1data = NULL; | ||
| 14363 | 15004 | ||
| 15005 | SAVE_IT (it1, it, it1data); | ||
| 14364 | start_display (&it1, w, startp); | 15006 | start_display (&it1, w, startp); |
| 14365 | move_it_vertically (&it1, margin); | 15007 | move_it_vertically (&it1, margin); |
| 14366 | margin_pos = IT_CHARPOS (it1); | 15008 | margin_pos = IT_CHARPOS (it1); |
| 15009 | RESTORE_IT (&it, &it, it1data); | ||
| 14367 | } | 15010 | } |
| 14368 | scrolling_up = PT > margin_pos; | 15011 | scrolling_up = PT > margin_pos; |
| 14369 | aggressive = | 15012 | aggressive = |
| @@ -17229,6 +17872,8 @@ cursor_row_p (struct glyph_row *row) | |||
| 17229 | static int | 17872 | static int |
| 17230 | push_display_prop (struct it *it, Lisp_Object prop) | 17873 | push_display_prop (struct it *it, Lisp_Object prop) |
| 17231 | { | 17874 | { |
| 17875 | xassert (it->method == GET_FROM_BUFFER); | ||
| 17876 | |||
| 17232 | push_it (it, NULL); | 17877 | push_it (it, NULL); |
| 17233 | 17878 | ||
| 17234 | if (STRINGP (prop)) | 17879 | if (STRINGP (prop)) |
| @@ -17246,6 +17891,29 @@ push_display_prop (struct it *it, Lisp_Object prop) | |||
| 17246 | it->end_charpos = it->string_nchars = SCHARS (it->string); | 17891 | it->end_charpos = it->string_nchars = SCHARS (it->string); |
| 17247 | it->method = GET_FROM_STRING; | 17892 | it->method = GET_FROM_STRING; |
| 17248 | it->stop_charpos = 0; | 17893 | it->stop_charpos = 0; |
| 17894 | it->prev_stop = 0; | ||
| 17895 | it->base_level_stop = 0; | ||
| 17896 | it->string_from_display_prop_p = 1; | ||
| 17897 | it->from_disp_prop_p = 1; | ||
| 17898 | |||
| 17899 | /* Force paragraph direction to be that of the parent | ||
| 17900 | buffer. */ | ||
| 17901 | if (it->bidi_p && it->bidi_it.paragraph_dir == R2L) | ||
| 17902 | it->paragraph_embedding = it->bidi_it.paragraph_dir; | ||
| 17903 | else | ||
| 17904 | it->paragraph_embedding = L2R; | ||
| 17905 | |||
| 17906 | /* Set up the bidi iterator for this display string. */ | ||
| 17907 | if (it->bidi_p) | ||
| 17908 | { | ||
| 17909 | it->bidi_it.string.lstring = it->string; | ||
| 17910 | it->bidi_it.string.s = NULL; | ||
| 17911 | it->bidi_it.string.schars = it->end_charpos; | ||
| 17912 | it->bidi_it.string.bufpos = IT_CHARPOS (*it); | ||
| 17913 | it->bidi_it.string.from_disp_str = 1; | ||
| 17914 | it->bidi_it.string.unibyte = !it->multibyte_p; | ||
| 17915 | bidi_init_it (0, 0, FRAME_WINDOW_P (it->f), &it->bidi_it); | ||
| 17916 | } | ||
| 17249 | } | 17917 | } |
| 17250 | else if (CONSP (prop) && EQ (XCAR (prop), Qspace)) | 17918 | else if (CONSP (prop) && EQ (XCAR (prop), Qspace)) |
| 17251 | { | 17919 | { |
| @@ -17292,6 +17960,7 @@ static void | |||
| 17292 | handle_line_prefix (struct it *it) | 17960 | handle_line_prefix (struct it *it) |
| 17293 | { | 17961 | { |
| 17294 | Lisp_Object prefix; | 17962 | Lisp_Object prefix; |
| 17963 | |||
| 17295 | if (it->continuation_lines_width > 0) | 17964 | if (it->continuation_lines_width > 0) |
| 17296 | { | 17965 | { |
| 17297 | prefix = get_it_property (it, Qwrap_prefix); | 17966 | prefix = get_it_property (it, Qwrap_prefix); |
| @@ -17317,9 +17986,9 @@ handle_line_prefix (struct it *it) | |||
| 17317 | 17986 | ||
| 17318 | 17987 | ||
| 17319 | /* Remove N glyphs at the start of a reversed IT->glyph_row. Called | 17988 | /* Remove N glyphs at the start of a reversed IT->glyph_row. Called |
| 17320 | only for R2L lines from display_line, when it decides that too many | 17989 | only for R2L lines from display_line and display_string, when they |
| 17321 | glyphs were produced by PRODUCE_GLYPHS, and the line needs to be | 17990 | decide that too many glyphs were produced by PRODUCE_GLYPHS, and |
| 17322 | continued. */ | 17991 | the line/string needs to be continued on the next glyph row. */ |
| 17323 | static void | 17992 | static void |
| 17324 | unproduce_glyphs (struct it *it, int n) | 17993 | unproduce_glyphs (struct it *it, int n) |
| 17325 | { | 17994 | { |
| @@ -17349,12 +18018,13 @@ find_row_edges (struct it *it, struct glyph_row *row, | |||
| 17349 | lines' rows is implemented for bidi-reordered rows. */ | 18018 | lines' rows is implemented for bidi-reordered rows. */ |
| 17350 | 18019 | ||
| 17351 | /* ROW->minpos is the value of min_pos, the minimal buffer position | 18020 | /* ROW->minpos is the value of min_pos, the minimal buffer position |
| 17352 | we have in ROW. */ | 18021 | we have in ROW, or ROW->start.pos if that is smaller. */ |
| 17353 | if (min_pos <= ZV) | 18022 | if (min_pos <= ZV && min_pos < row->start.pos.charpos) |
| 17354 | SET_TEXT_POS (row->minpos, min_pos, min_bpos); | 18023 | SET_TEXT_POS (row->minpos, min_pos, min_bpos); |
| 17355 | else | 18024 | else |
| 17356 | /* We didn't find _any_ valid buffer positions in any of the | 18025 | /* We didn't find buffer positions smaller than ROW->start, or |
| 17357 | glyphs, so we must trust the iterator's computed positions. */ | 18026 | didn't find _any_ valid buffer positions in any of the glyphs, |
| 18027 | so we must trust the iterator's computed positions. */ | ||
| 17358 | row->minpos = row->start.pos; | 18028 | row->minpos = row->start.pos; |
| 17359 | if (max_pos <= 0) | 18029 | if (max_pos <= 0) |
| 17360 | { | 18030 | { |
| @@ -17429,6 +18099,7 @@ display_line (struct it *it) | |||
| 17429 | struct glyph_row *row = it->glyph_row; | 18099 | struct glyph_row *row = it->glyph_row; |
| 17430 | Lisp_Object overlay_arrow_string; | 18100 | Lisp_Object overlay_arrow_string; |
| 17431 | struct it wrap_it; | 18101 | struct it wrap_it; |
| 18102 | void *wrap_data = NULL; | ||
| 17432 | int may_wrap = 0, wrap_x IF_LINT (= 0); | 18103 | int may_wrap = 0, wrap_x IF_LINT (= 0); |
| 17433 | int wrap_row_used = -1; | 18104 | int wrap_row_used = -1; |
| 17434 | int wrap_row_ascent IF_LINT (= 0), wrap_row_height IF_LINT (= 0); | 18105 | int wrap_row_ascent IF_LINT (= 0), wrap_row_height IF_LINT (= 0); |
| @@ -17583,7 +18254,7 @@ display_line (struct it *it) | |||
| 17583 | may_wrap = 1; | 18254 | may_wrap = 1; |
| 17584 | else if (may_wrap) | 18255 | else if (may_wrap) |
| 17585 | { | 18256 | { |
| 17586 | wrap_it = *it; | 18257 | SAVE_IT (wrap_it, *it, wrap_data); |
| 17587 | wrap_x = x; | 18258 | wrap_x = x; |
| 17588 | wrap_row_used = row->used[TEXT_AREA]; | 18259 | wrap_row_used = row->used[TEXT_AREA]; |
| 17589 | wrap_row_ascent = row->ascent; | 18260 | wrap_row_ascent = row->ascent; |
| @@ -17753,7 +18424,7 @@ display_line (struct it *it) | |||
| 17753 | if (row->reversed_p) | 18424 | if (row->reversed_p) |
| 17754 | unproduce_glyphs (it, | 18425 | unproduce_glyphs (it, |
| 17755 | row->used[TEXT_AREA] - wrap_row_used); | 18426 | row->used[TEXT_AREA] - wrap_row_used); |
| 17756 | *it = wrap_it; | 18427 | RESTORE_IT (it, &wrap_it, wrap_data); |
| 17757 | it->continuation_lines_width += wrap_x; | 18428 | it->continuation_lines_width += wrap_x; |
| 17758 | row->used[TEXT_AREA] = wrap_row_used; | 18429 | row->used[TEXT_AREA] = wrap_row_used; |
| 17759 | row->ascent = wrap_row_ascent; | 18430 | row->ascent = wrap_row_ascent; |
| @@ -18159,6 +18830,8 @@ See also `bidi-paragraph-direction'. */) | |||
| 18159 | itb.charpos = pos; | 18830 | itb.charpos = pos; |
| 18160 | itb.bytepos = bytepos; | 18831 | itb.bytepos = bytepos; |
| 18161 | itb.nchars = -1; | 18832 | itb.nchars = -1; |
| 18833 | itb.string.s = NULL; | ||
| 18834 | itb.string.lstring = Qnil; | ||
| 18162 | itb.frame_window_p = FRAME_WINDOW_P (SELECTED_FRAME ()); /* guesswork */ | 18835 | itb.frame_window_p = FRAME_WINDOW_P (SELECTED_FRAME ()); /* guesswork */ |
| 18163 | itb.first_elt = 1; | 18836 | itb.first_elt = 1; |
| 18164 | itb.separator_limit = -1; | 18837 | itb.separator_limit = -1; |
| @@ -18248,6 +18921,11 @@ display_menu_bar (struct window *w) | |||
| 18248 | } | 18921 | } |
| 18249 | #endif /* not USE_X_TOOLKIT */ | 18922 | #endif /* not USE_X_TOOLKIT */ |
| 18250 | 18923 | ||
| 18924 | /* FIXME: This should be controlled by a user option. See the | ||
| 18925 | comments in redisplay_tool_bar and display_mode_line about | ||
| 18926 | this. */ | ||
| 18927 | it.paragraph_embedding = L2R; | ||
| 18928 | |||
| 18251 | if (! mode_line_inverse_video) | 18929 | if (! mode_line_inverse_video) |
| 18252 | /* Force the menu-bar to be displayed in the default face. */ | 18930 | /* Force the menu-bar to be displayed in the default face. */ |
| 18253 | it.base_face_id = it.face_id = DEFAULT_FACE_ID; | 18931 | it.base_face_id = it.face_id = DEFAULT_FACE_ID; |
| @@ -18425,6 +19103,11 @@ display_mode_line (struct window *w, enum face_id face_id, Lisp_Object format) | |||
| 18425 | /* Force the mode-line to be displayed in the default face. */ | 19103 | /* Force the mode-line to be displayed in the default face. */ |
| 18426 | it.base_face_id = it.face_id = DEFAULT_FACE_ID; | 19104 | it.base_face_id = it.face_id = DEFAULT_FACE_ID; |
| 18427 | 19105 | ||
| 19106 | /* FIXME: This should be controlled by a user option. But | ||
| 19107 | supporting such an option is not trivial, since the mode line is | ||
| 19108 | made up of many separate strings. */ | ||
| 19109 | it.paragraph_embedding = L2R; | ||
| 19110 | |||
| 18428 | record_unwind_protect (unwind_format_mode_line, | 19111 | record_unwind_protect (unwind_format_mode_line, |
| 18429 | format_mode_line_unwind_data (NULL, Qnil, 0)); | 19112 | format_mode_line_unwind_data (NULL, Qnil, 0)); |
| 18430 | 19113 | ||
| @@ -19970,6 +20653,7 @@ display_string (const char *string, Lisp_Object lisp_string, Lisp_Object face_st | |||
| 19970 | int hpos_at_start = it->hpos; | 20653 | int hpos_at_start = it->hpos; |
| 19971 | int saved_face_id = it->face_id; | 20654 | int saved_face_id = it->face_id; |
| 19972 | struct glyph_row *row = it->glyph_row; | 20655 | struct glyph_row *row = it->glyph_row; |
| 20656 | EMACS_INT it_charpos; | ||
| 19973 | 20657 | ||
| 19974 | /* Initialize the iterator IT for iteration over STRING beginning | 20658 | /* Initialize the iterator IT for iteration over STRING beginning |
| 19975 | with index START. */ | 20659 | with index START. */ |
| @@ -19978,10 +20662,10 @@ display_string (const char *string, Lisp_Object lisp_string, Lisp_Object face_st | |||
| 19978 | if (string && STRINGP (lisp_string)) | 20662 | if (string && STRINGP (lisp_string)) |
| 19979 | /* LISP_STRING is the one returned by decode_mode_spec. We should | 20663 | /* LISP_STRING is the one returned by decode_mode_spec. We should |
| 19980 | ignore its text properties. */ | 20664 | ignore its text properties. */ |
| 19981 | it->stop_charpos = -1; | 20665 | it->stop_charpos = it->end_charpos; |
| 19982 | 20666 | ||
| 19983 | /* If displaying STRING, set up the face of the iterator | 20667 | /* If displaying STRING, set up the face of the iterator from |
| 19984 | from LISP_STRING, if that's given. */ | 20668 | FACE_STRING, if that's given. */ |
| 19985 | if (STRINGP (face_string)) | 20669 | if (STRINGP (face_string)) |
| 19986 | { | 20670 | { |
| 19987 | EMACS_INT endptr; | 20671 | EMACS_INT endptr; |
| @@ -20015,6 +20699,11 @@ display_string (const char *string, Lisp_Object lisp_string, Lisp_Object face_st | |||
| 20015 | row->phys_height = it->max_phys_ascent + it->max_phys_descent; | 20699 | row->phys_height = it->max_phys_ascent + it->max_phys_descent; |
| 20016 | row->extra_line_spacing = it->max_extra_line_spacing; | 20700 | row->extra_line_spacing = it->max_extra_line_spacing; |
| 20017 | 20701 | ||
| 20702 | if (STRINGP (it->string)) | ||
| 20703 | it_charpos = IT_STRING_CHARPOS (*it); | ||
| 20704 | else | ||
| 20705 | it_charpos = IT_CHARPOS (*it); | ||
| 20706 | |||
| 20018 | /* This condition is for the case that we are called with current_x | 20707 | /* This condition is for the case that we are called with current_x |
| 20019 | past last_visible_x. */ | 20708 | past last_visible_x. */ |
| 20020 | while (it->current_x < max_x) | 20709 | while (it->current_x < max_x) |
| @@ -20027,10 +20716,10 @@ display_string (const char *string, Lisp_Object lisp_string, Lisp_Object face_st | |||
| 20027 | 20716 | ||
| 20028 | /* Produce glyphs. */ | 20717 | /* Produce glyphs. */ |
| 20029 | x_before = it->current_x; | 20718 | x_before = it->current_x; |
| 20030 | n_glyphs_before = it->glyph_row->used[TEXT_AREA]; | 20719 | n_glyphs_before = row->used[TEXT_AREA]; |
| 20031 | PRODUCE_GLYPHS (it); | 20720 | PRODUCE_GLYPHS (it); |
| 20032 | 20721 | ||
| 20033 | nglyphs = it->glyph_row->used[TEXT_AREA] - n_glyphs_before; | 20722 | nglyphs = row->used[TEXT_AREA] - n_glyphs_before; |
| 20034 | i = 0; | 20723 | i = 0; |
| 20035 | x = x_before; | 20724 | x = x_before; |
| 20036 | while (i < nglyphs) | 20725 | while (i < nglyphs) |
| @@ -20044,12 +20733,18 @@ display_string (const char *string, Lisp_Object lisp_string, Lisp_Object face_st | |||
| 20044 | if (CHAR_GLYPH_PADDING_P (*glyph)) | 20733 | if (CHAR_GLYPH_PADDING_P (*glyph)) |
| 20045 | { | 20734 | { |
| 20046 | /* A wide character is unbreakable. */ | 20735 | /* A wide character is unbreakable. */ |
| 20047 | it->glyph_row->used[TEXT_AREA] = n_glyphs_before; | 20736 | if (row->reversed_p) |
| 20737 | unproduce_glyphs (it, row->used[TEXT_AREA] | ||
| 20738 | - n_glyphs_before); | ||
| 20739 | row->used[TEXT_AREA] = n_glyphs_before; | ||
| 20048 | it->current_x = x_before; | 20740 | it->current_x = x_before; |
| 20049 | } | 20741 | } |
| 20050 | else | 20742 | else |
| 20051 | { | 20743 | { |
| 20052 | it->glyph_row->used[TEXT_AREA] = n_glyphs_before + i; | 20744 | if (row->reversed_p) |
| 20745 | unproduce_glyphs (it, row->used[TEXT_AREA] | ||
| 20746 | - (n_glyphs_before + i)); | ||
| 20747 | row->used[TEXT_AREA] = n_glyphs_before + i; | ||
| 20053 | it->current_x = x; | 20748 | it->current_x = x; |
| 20054 | } | 20749 | } |
| 20055 | break; | 20750 | break; |
| @@ -20059,7 +20754,7 @@ display_string (const char *string, Lisp_Object lisp_string, Lisp_Object face_st | |||
| 20059 | /* Glyph is at least partially visible. */ | 20754 | /* Glyph is at least partially visible. */ |
| 20060 | ++it->hpos; | 20755 | ++it->hpos; |
| 20061 | if (x < it->first_visible_x) | 20756 | if (x < it->first_visible_x) |
| 20062 | it->glyph_row->x = x - it->first_visible_x; | 20757 | row->x = x - it->first_visible_x; |
| 20063 | } | 20758 | } |
| 20064 | else | 20759 | else |
| 20065 | { | 20760 | { |
| @@ -20091,6 +20786,10 @@ display_string (const char *string, Lisp_Object lisp_string, Lisp_Object face_st | |||
| 20091 | } | 20786 | } |
| 20092 | 20787 | ||
| 20093 | set_iterator_to_next (it, 1); | 20788 | set_iterator_to_next (it, 1); |
| 20789 | if (STRINGP (it->string)) | ||
| 20790 | it_charpos = IT_STRING_CHARPOS (*it); | ||
| 20791 | else | ||
| 20792 | it_charpos = IT_CHARPOS (*it); | ||
| 20094 | 20793 | ||
| 20095 | /* Stop if truncating at the right edge. */ | 20794 | /* Stop if truncating at the right edge. */ |
| 20096 | if (it->line_wrap == TRUNCATE | 20795 | if (it->line_wrap == TRUNCATE |
| @@ -20098,7 +20797,7 @@ display_string (const char *string, Lisp_Object lisp_string, Lisp_Object face_st | |||
| 20098 | { | 20797 | { |
| 20099 | /* Add truncation mark, but don't do it if the line is | 20798 | /* Add truncation mark, but don't do it if the line is |
| 20100 | truncated at a padding space. */ | 20799 | truncated at a padding space. */ |
| 20101 | if (IT_CHARPOS (*it) < it->string_nchars) | 20800 | if (it_charpos < it->string_nchars) |
| 20102 | { | 20801 | { |
| 20103 | if (!FRAME_WINDOW_P (it->f)) | 20802 | if (!FRAME_WINDOW_P (it->f)) |
| 20104 | { | 20803 | { |
| @@ -20106,9 +20805,20 @@ display_string (const char *string, Lisp_Object lisp_string, Lisp_Object face_st | |||
| 20106 | 20805 | ||
| 20107 | if (it->current_x > it->last_visible_x) | 20806 | if (it->current_x > it->last_visible_x) |
| 20108 | { | 20807 | { |
| 20109 | for (ii = row->used[TEXT_AREA] - 1; ii > 0; --ii) | 20808 | if (!row->reversed_p) |
| 20110 | if (!CHAR_GLYPH_PADDING_P (row->glyphs[TEXT_AREA][ii])) | 20809 | { |
| 20111 | break; | 20810 | for (ii = row->used[TEXT_AREA] - 1; ii > 0; --ii) |
| 20811 | if (!CHAR_GLYPH_PADDING_P (row->glyphs[TEXT_AREA][ii])) | ||
| 20812 | break; | ||
| 20813 | } | ||
| 20814 | else | ||
| 20815 | { | ||
| 20816 | for (ii = 0; ii < row->used[TEXT_AREA]; ii++) | ||
| 20817 | if (!CHAR_GLYPH_PADDING_P (row->glyphs[TEXT_AREA][ii])) | ||
| 20818 | break; | ||
| 20819 | unproduce_glyphs (it, ii + 1); | ||
| 20820 | ii = row->used[TEXT_AREA] - (ii + 1); | ||
| 20821 | } | ||
| 20112 | for (n = row->used[TEXT_AREA]; ii < n; ++ii) | 20822 | for (n = row->used[TEXT_AREA]; ii < n; ++ii) |
| 20113 | { | 20823 | { |
| 20114 | row->used[TEXT_AREA] = ii; | 20824 | row->used[TEXT_AREA] = ii; |
| @@ -20117,7 +20827,7 @@ display_string (const char *string, Lisp_Object lisp_string, Lisp_Object face_st | |||
| 20117 | } | 20827 | } |
| 20118 | produce_special_glyphs (it, IT_TRUNCATION); | 20828 | produce_special_glyphs (it, IT_TRUNCATION); |
| 20119 | } | 20829 | } |
| 20120 | it->glyph_row->truncated_on_right_p = 1; | 20830 | row->truncated_on_right_p = 1; |
| 20121 | } | 20831 | } |
| 20122 | break; | 20832 | break; |
| 20123 | } | 20833 | } |
| @@ -20125,11 +20835,11 @@ display_string (const char *string, Lisp_Object lisp_string, Lisp_Object face_st | |||
| 20125 | 20835 | ||
| 20126 | /* Maybe insert a truncation at the left. */ | 20836 | /* Maybe insert a truncation at the left. */ |
| 20127 | if (it->first_visible_x | 20837 | if (it->first_visible_x |
| 20128 | && IT_CHARPOS (*it) > 0) | 20838 | && it_charpos > 0) |
| 20129 | { | 20839 | { |
| 20130 | if (!FRAME_WINDOW_P (it->f)) | 20840 | if (!FRAME_WINDOW_P (it->f)) |
| 20131 | insert_left_trunc_glyphs (it); | 20841 | insert_left_trunc_glyphs (it); |
| 20132 | it->glyph_row->truncated_on_left_p = 1; | 20842 | row->truncated_on_left_p = 1; |
| 20133 | } | 20843 | } |
| 20134 | 20844 | ||
| 20135 | it->face_id = saved_face_id; | 20845 | it->face_id = saved_face_id; |