diff options
| author | Eli Zaretskii | 2011-06-11 18:13:17 +0300 |
|---|---|---|
| committer | Eli Zaretskii | 2011-06-11 18:13:17 +0300 |
| commit | 34c48e575a30f075daedda6b487c7d24181743be (patch) | |
| tree | 84cf9f68ec8d5de5dab5611748b59059e8e084f6 /src | |
| parent | 4b988f8b7f1824a0392a3f01c1048782ed8512f9 (diff) | |
| download | emacs-34c48e575a30f075daedda6b487c7d24181743be.tar.gz emacs-34c48e575a30f075daedda6b487c7d24181743be.zip | |
Initial version of string reordering. Tested only on mode line and
TTY menu bar. Display is buggy.
src/xdisp.c (next_element_from_buffer): Improve commentary for when
the iterator is before prev_stop.
(init_iterator): Initialize bidi_p from the default value of
bidi-display-reordering, not from buffer-local value. Use the
buffer-local value only if initializing for buffer iteration.
(handle_invisible_prop): Support invisible properties on strings
that are being bidi-reordered.
(reseat_to_string): Enable bidi-related code.
(set_iterator_to_next): Support bidi reordering of C strings and
Lisp strings.
(next_element_from_string): Support bidi reordering of Lisp strings.
(handle_stop_backwards): Support Lisp strings as well.
(display_mode_line, display_mode_element): Temporarily force L2R
paragraph direction.
(display_string): Support display of R2L glyph rows. Use
IT_STRING_CHARPOS when displaying from a Lisp string.
Diffstat (limited to 'src')
| -rw-r--r-- | src/ChangeLog | 15 | ||||
| -rw-r--r-- | src/xdisp.c | 380 |
2 files changed, 329 insertions, 66 deletions
diff --git a/src/ChangeLog b/src/ChangeLog index c37881fb304..3ca0241f47c 100644 --- a/src/ChangeLog +++ b/src/ChangeLog | |||
| @@ -2,6 +2,21 @@ | |||
| 2 | 2 | ||
| 3 | * xdisp.c (next_element_from_buffer): Improve commentary for when | 3 | * xdisp.c (next_element_from_buffer): Improve commentary for when |
| 4 | the iterator is before prev_stop. | 4 | the iterator is before prev_stop. |
| 5 | (init_iterator): Initialize bidi_p from the default value of | ||
| 6 | bidi-display-reordering, not from buffer-local value. Use the | ||
| 7 | buffer-local value only if initializing for buffer iteration. | ||
| 8 | (handle_invisible_prop): Support invisible properties on strings | ||
| 9 | that are being bidi-reordered. | ||
| 10 | (reseat_to_string): Enable bidi-related code. | ||
| 11 | (set_iterator_to_next): Support bidi reordering of C strings and | ||
| 12 | Lisp strings. | ||
| 13 | (next_element_from_string): Support bidi reordering of Lisp | ||
| 14 | strings. | ||
| 15 | (handle_stop_backwards): Support Lisp strings as well. | ||
| 16 | (display_mode_line, display_mode_element): Temporarily force L2R | ||
| 17 | paragraph direction. | ||
| 18 | (display_string): Support display of R2L glyph rows. Use | ||
| 19 | IT_STRING_CHARPOS when displaying from a Lisp string. | ||
| 5 | 20 | ||
| 6 | 2011-06-10 Eli Zaretskii <eliz@gnu.org> | 21 | 2011-06-10 Eli Zaretskii <eliz@gnu.org> |
| 7 | 22 | ||
diff --git a/src/xdisp.c b/src/xdisp.c index 8be85d16fb4..efd29895ea2 100644 --- a/src/xdisp.c +++ b/src/xdisp.c | |||
| @@ -783,7 +783,6 @@ static void store_mode_line_noprop_char (char); | |||
| 783 | static int store_mode_line_noprop (const char *, int, int); | 783 | static int store_mode_line_noprop (const char *, int, int); |
| 784 | static void handle_stop (struct it *); | 784 | static void handle_stop (struct it *); |
| 785 | static void handle_stop_backwards (struct it *, EMACS_INT); | 785 | static void handle_stop_backwards (struct it *, EMACS_INT); |
| 786 | static int single_display_spec_intangible_p (Lisp_Object); | ||
| 787 | static void vmessage (const char *, va_list) ATTRIBUTE_FORMAT_PRINTF (1, 0); | 786 | static void vmessage (const char *, va_list) ATTRIBUTE_FORMAT_PRINTF (1, 0); |
| 788 | static void ensure_echo_area_buffers (void); | 787 | static void ensure_echo_area_buffers (void); |
| 789 | static Lisp_Object unwind_with_echo_area_buffer (Lisp_Object); | 788 | static Lisp_Object unwind_with_echo_area_buffer (Lisp_Object); |
| @@ -2406,12 +2405,12 @@ init_iterator (struct it *it, struct window *w, | |||
| 2406 | /* Are multibyte characters enabled in current_buffer? */ | 2405 | /* Are multibyte characters enabled in current_buffer? */ |
| 2407 | it->multibyte_p = !NILP (BVAR (current_buffer, enable_multibyte_characters)); | 2406 | it->multibyte_p = !NILP (BVAR (current_buffer, enable_multibyte_characters)); |
| 2408 | 2407 | ||
| 2409 | /* Do we need to reorder bidirectional text? Not if this is a | 2408 | |
| 2410 | unibyte buffer: by definition, none of the single-byte characters | 2409 | /* Bidirectional reordering of strings is controlled by the default |
| 2411 | are strong R2L, so no reordering is needed. And bidi.c doesn't | 2410 | value of bidi-display-reordering. For buffers, we reconsider |
| 2412 | support unibyte buffers anyway. */ | 2411 | this below. */ |
| 2413 | it->bidi_p | 2412 | it->bidi_p = |
| 2414 | = !NILP (BVAR (current_buffer, bidi_display_reordering)) && it->multibyte_p; | 2413 | !NILP (BVAR (&buffer_defaults, bidi_display_reordering)) && it->multibyte_p; |
| 2415 | 2414 | ||
| 2416 | /* Non-zero if we should highlight the region. */ | 2415 | /* Non-zero if we should highlight the region. */ |
| 2417 | highlight_region_p | 2416 | highlight_region_p |
| @@ -2577,6 +2576,13 @@ init_iterator (struct it *it, struct window *w, | |||
| 2577 | IT_BYTEPOS (*it) = bytepos; | 2576 | IT_BYTEPOS (*it) = bytepos; |
| 2578 | 2577 | ||
| 2579 | it->start = it->current; | 2578 | it->start = it->current; |
| 2579 | /* Do we need to reorder bidirectional text? Not if this is a | ||
| 2580 | unibyte buffer: by definition, none of the single-byte | ||
| 2581 | characters are strong R2L, so no reordering is needed. And | ||
| 2582 | bidi.c doesn't support unibyte buffers anyway. */ | ||
| 2583 | it->bidi_p = | ||
| 2584 | !NILP (BVAR (current_buffer, bidi_display_reordering)) | ||
| 2585 | && it->multibyte_p; | ||
| 2580 | 2586 | ||
| 2581 | /* If we are to reorder bidirectional text, init the bidi | 2587 | /* If we are to reorder bidirectional text, init the bidi |
| 2582 | iterator. */ | 2588 | iterator. */ |
| @@ -3605,6 +3611,8 @@ handle_invisible_prop (struct it *it) | |||
| 3605 | if (!NILP (prop) | 3611 | if (!NILP (prop) |
| 3606 | && IT_STRING_CHARPOS (*it) < it->end_charpos) | 3612 | && IT_STRING_CHARPOS (*it) < it->end_charpos) |
| 3607 | { | 3613 | { |
| 3614 | EMACS_INT endpos; | ||
| 3615 | |||
| 3608 | handled = HANDLED_RECOMPUTE_PROPS; | 3616 | handled = HANDLED_RECOMPUTE_PROPS; |
| 3609 | 3617 | ||
| 3610 | /* Get the position at which the next change of the | 3618 | /* Get the position at which the next change of the |
| @@ -3619,12 +3627,37 @@ handle_invisible_prop (struct it *it) | |||
| 3619 | change in the property is at position end_charpos. | 3627 | change in the property is at position end_charpos. |
| 3620 | Move IT's current position to that position. */ | 3628 | Move IT's current position to that position. */ |
| 3621 | if (INTEGERP (end_charpos) | 3629 | if (INTEGERP (end_charpos) |
| 3622 | && XFASTINT (end_charpos) < XFASTINT (limit)) | 3630 | && (endpos = XFASTINT (end_charpos)) < XFASTINT (limit)) |
| 3623 | { | 3631 | { |
| 3624 | struct text_pos old; | 3632 | struct text_pos old; |
| 3633 | EMACS_INT oldpos; | ||
| 3634 | |||
| 3625 | old = it->current.string_pos; | 3635 | old = it->current.string_pos; |
| 3626 | IT_STRING_CHARPOS (*it) = XFASTINT (end_charpos); | 3636 | oldpos = CHARPOS (old); |
| 3627 | compute_string_pos (&it->current.string_pos, old, it->string); | 3637 | if (it->bidi_p) |
| 3638 | { | ||
| 3639 | if (it->bidi_it.first_elt | ||
| 3640 | && it->bidi_it.charpos < SCHARS (it->string)) | ||
| 3641 | bidi_paragraph_init (it->paragraph_embedding, | ||
| 3642 | &it->bidi_it, 1); | ||
| 3643 | /* Bidi-iterate out of the invisible text. */ | ||
| 3644 | do | ||
| 3645 | { | ||
| 3646 | bidi_move_to_visually_next (&it->bidi_it); | ||
| 3647 | } | ||
| 3648 | while (oldpos <= it->bidi_it.charpos | ||
| 3649 | && it->bidi_it.charpos < endpos); | ||
| 3650 | |||
| 3651 | IT_STRING_CHARPOS (*it) = it->bidi_it.charpos; | ||
| 3652 | IT_STRING_BYTEPOS (*it) = it->bidi_it.bytepos; | ||
| 3653 | if (IT_CHARPOS (*it) >= endpos) | ||
| 3654 | it->prev_stop = endpos; | ||
| 3655 | } | ||
| 3656 | else | ||
| 3657 | { | ||
| 3658 | IT_STRING_CHARPOS (*it) = XFASTINT (end_charpos); | ||
| 3659 | compute_string_pos (&it->current.string_pos, old, it->string); | ||
| 3660 | } | ||
| 3628 | } | 3661 | } |
| 3629 | else | 3662 | else |
| 3630 | { | 3663 | { |
| @@ -5560,12 +5593,6 @@ reseat_to_string (struct it *it, const char *s, Lisp_Object string, | |||
| 5560 | setting of MULTIBYTE, if specified. */ | 5593 | setting of MULTIBYTE, if specified. */ |
| 5561 | if (multibyte >= 0) | 5594 | if (multibyte >= 0) |
| 5562 | it->multibyte_p = multibyte > 0; | 5595 | it->multibyte_p = multibyte > 0; |
| 5563 | #if 0 | ||
| 5564 | /* String reordering is controlled by the default value of | ||
| 5565 | bidi-display-reordering. */ | ||
| 5566 | it->bidi_p = | ||
| 5567 | it->multibyte_p && BVAR (&buffer_defaults, bidi_display_reordering); | ||
| 5568 | #endif | ||
| 5569 | 5596 | ||
| 5570 | if (s == NULL) | 5597 | if (s == NULL) |
| 5571 | { | 5598 | { |
| @@ -5575,7 +5602,7 @@ reseat_to_string (struct it *it, const char *s, Lisp_Object string, | |||
| 5575 | it->end_charpos = it->string_nchars = SCHARS (string); | 5602 | it->end_charpos = it->string_nchars = SCHARS (string); |
| 5576 | it->method = GET_FROM_STRING; | 5603 | it->method = GET_FROM_STRING; |
| 5577 | it->current.string_pos = string_pos (charpos, string); | 5604 | it->current.string_pos = string_pos (charpos, string); |
| 5578 | #if 0 | 5605 | |
| 5579 | if (it->bidi_p) | 5606 | if (it->bidi_p) |
| 5580 | { | 5607 | { |
| 5581 | it->paragraph_embedding = NEUTRAL_DIR; | 5608 | it->paragraph_embedding = NEUTRAL_DIR; |
| @@ -5587,7 +5614,6 @@ reseat_to_string (struct it *it, const char *s, Lisp_Object string, | |||
| 5587 | bidi_init_it (charpos, IT_STRING_BYTEPOS (*it), | 5614 | bidi_init_it (charpos, IT_STRING_BYTEPOS (*it), |
| 5588 | FRAME_WINDOW_P (it->f), &it->bidi_it); | 5615 | FRAME_WINDOW_P (it->f), &it->bidi_it); |
| 5589 | } | 5616 | } |
| 5590 | #endif | ||
| 5591 | } | 5617 | } |
| 5592 | else | 5618 | else |
| 5593 | { | 5619 | { |
| @@ -5601,7 +5627,7 @@ reseat_to_string (struct it *it, const char *s, Lisp_Object string, | |||
| 5601 | { | 5627 | { |
| 5602 | it->current.pos = c_string_pos (charpos, s, 1); | 5628 | it->current.pos = c_string_pos (charpos, s, 1); |
| 5603 | it->end_charpos = it->string_nchars = number_of_chars (s, 1); | 5629 | it->end_charpos = it->string_nchars = number_of_chars (s, 1); |
| 5604 | #if 0 | 5630 | |
| 5605 | if (it->bidi_p) | 5631 | if (it->bidi_p) |
| 5606 | { | 5632 | { |
| 5607 | it->paragraph_embedding = NEUTRAL_DIR; | 5633 | it->paragraph_embedding = NEUTRAL_DIR; |
| @@ -5613,7 +5639,6 @@ reseat_to_string (struct it *it, const char *s, Lisp_Object string, | |||
| 5613 | bidi_init_it (charpos, IT_BYTEPOS (*it), FRAME_WINDOW_P (it->f), | 5639 | bidi_init_it (charpos, IT_BYTEPOS (*it), FRAME_WINDOW_P (it->f), |
| 5614 | &it->bidi_it); | 5640 | &it->bidi_it); |
| 5615 | } | 5641 | } |
| 5616 | #endif | ||
| 5617 | } | 5642 | } |
| 5618 | else | 5643 | else |
| 5619 | { | 5644 | { |
| @@ -5630,10 +5655,8 @@ reseat_to_string (struct it *it, const char *s, Lisp_Object string, | |||
| 5630 | if (precision > 0 && it->end_charpos - charpos > precision) | 5655 | if (precision > 0 && it->end_charpos - charpos > precision) |
| 5631 | { | 5656 | { |
| 5632 | it->end_charpos = it->string_nchars = charpos + precision; | 5657 | it->end_charpos = it->string_nchars = charpos + precision; |
| 5633 | #if 0 | ||
| 5634 | if (it->bidi_p) | 5658 | if (it->bidi_p) |
| 5635 | it->bidi_it.string.schars = it->end_charpos; | 5659 | it->bidi_it.string.schars = it->end_charpos; |
| 5636 | #endif | ||
| 5637 | } | 5660 | } |
| 5638 | 5661 | ||
| 5639 | /* FIELD_WIDTH > 0 means pad with spaces until FIELD_WIDTH | 5662 | /* FIELD_WIDTH > 0 means pad with spaces until FIELD_WIDTH |
| @@ -5653,7 +5676,6 @@ reseat_to_string (struct it *it, const char *s, Lisp_Object string, | |||
| 5653 | it->dp = XCHAR_TABLE (Vstandard_display_table); | 5676 | it->dp = XCHAR_TABLE (Vstandard_display_table); |
| 5654 | 5677 | ||
| 5655 | it->stop_charpos = charpos; | 5678 | it->stop_charpos = charpos; |
| 5656 | #if 0 | ||
| 5657 | it->prev_stop = charpos; | 5679 | it->prev_stop = charpos; |
| 5658 | it->base_level_stop = 0; | 5680 | it->base_level_stop = 0; |
| 5659 | if (it->bidi_p) | 5681 | if (it->bidi_p) |
| @@ -5662,7 +5684,6 @@ reseat_to_string (struct it *it, const char *s, Lisp_Object string, | |||
| 5662 | it->bidi_it.paragraph_dir = NEUTRAL_DIR; | 5684 | it->bidi_it.paragraph_dir = NEUTRAL_DIR; |
| 5663 | it->bidi_it.disp_pos = -1; | 5685 | it->bidi_it.disp_pos = -1; |
| 5664 | } | 5686 | } |
| 5665 | #endif | ||
| 5666 | if (s == NULL && it->multibyte_p) | 5687 | if (s == NULL && it->multibyte_p) |
| 5667 | { | 5688 | { |
| 5668 | EMACS_INT endpos = SCHARS (it->string); | 5689 | EMACS_INT endpos = SCHARS (it->string); |
| @@ -6284,8 +6305,17 @@ set_iterator_to_next (struct it *it, int reseat_p) | |||
| 6284 | 6305 | ||
| 6285 | case GET_FROM_C_STRING: | 6306 | case GET_FROM_C_STRING: |
| 6286 | /* Current display element of IT is from a C string. */ | 6307 | /* Current display element of IT is from a C string. */ |
| 6287 | IT_BYTEPOS (*it) += it->len; | 6308 | if (!it->bidi_p) |
| 6288 | IT_CHARPOS (*it) += 1; | 6309 | { |
| 6310 | IT_BYTEPOS (*it) += it->len; | ||
| 6311 | IT_CHARPOS (*it) += 1; | ||
| 6312 | } | ||
| 6313 | else | ||
| 6314 | { | ||
| 6315 | bidi_move_to_visually_next (&it->bidi_it); | ||
| 6316 | IT_BYTEPOS (*it) = it->bidi_it.bytepos; | ||
| 6317 | IT_CHARPOS (*it) = it->bidi_it.charpos; | ||
| 6318 | } | ||
| 6289 | break; | 6319 | break; |
| 6290 | 6320 | ||
| 6291 | case GET_FROM_DISPLAY_VECTOR: | 6321 | case GET_FROM_DISPLAY_VECTOR: |
| @@ -6339,23 +6369,89 @@ set_iterator_to_next (struct it *it, int reseat_p) | |||
| 6339 | xassert (it->s == NULL && STRINGP (it->string)); | 6369 | xassert (it->s == NULL && STRINGP (it->string)); |
| 6340 | if (it->cmp_it.id >= 0) | 6370 | if (it->cmp_it.id >= 0) |
| 6341 | { | 6371 | { |
| 6342 | IT_STRING_CHARPOS (*it) += it->cmp_it.nchars; | 6372 | int i; |
| 6343 | IT_STRING_BYTEPOS (*it) += it->cmp_it.nbytes; | 6373 | |
| 6344 | if (it->cmp_it.to < it->cmp_it.nglyphs) | 6374 | if (! it->bidi_p) |
| 6345 | it->cmp_it.from = it->cmp_it.to; | 6375 | { |
| 6376 | IT_STRING_CHARPOS (*it) += it->cmp_it.nchars; | ||
| 6377 | IT_STRING_BYTEPOS (*it) += it->cmp_it.nbytes; | ||
| 6378 | if (it->cmp_it.to < it->cmp_it.nglyphs) | ||
| 6379 | it->cmp_it.from = it->cmp_it.to; | ||
| 6380 | else | ||
| 6381 | { | ||
| 6382 | it->cmp_it.id = -1; | ||
| 6383 | composition_compute_stop_pos (&it->cmp_it, | ||
| 6384 | IT_STRING_CHARPOS (*it), | ||
| 6385 | IT_STRING_BYTEPOS (*it), | ||
| 6386 | it->end_charpos, it->string); | ||
| 6387 | } | ||
| 6388 | } | ||
| 6389 | else if (! it->cmp_it.reversed_p) | ||
| 6390 | { | ||
| 6391 | for (i = 0; i < it->cmp_it.nchars; i++) | ||
| 6392 | bidi_move_to_visually_next (&it->bidi_it); | ||
| 6393 | IT_STRING_BYTEPOS (*it) = it->bidi_it.bytepos; | ||
| 6394 | IT_STRING_CHARPOS (*it) = it->bidi_it.charpos; | ||
| 6395 | |||
| 6396 | if (it->cmp_it.to < it->cmp_it.nglyphs) | ||
| 6397 | it->cmp_it.from = it->cmp_it.to; | ||
| 6398 | else | ||
| 6399 | { | ||
| 6400 | EMACS_INT stop = it->end_charpos; | ||
| 6401 | if (it->bidi_it.scan_dir < 0) | ||
| 6402 | stop = -1; | ||
| 6403 | composition_compute_stop_pos (&it->cmp_it, | ||
| 6404 | IT_STRING_CHARPOS (*it), | ||
| 6405 | IT_STRING_BYTEPOS (*it), stop, | ||
| 6406 | it->string); | ||
| 6407 | } | ||
| 6408 | } | ||
| 6346 | else | 6409 | else |
| 6347 | { | 6410 | { |
| 6348 | it->cmp_it.id = -1; | 6411 | for (i = 0; i < it->cmp_it.nchars; i++) |
| 6349 | composition_compute_stop_pos (&it->cmp_it, | 6412 | bidi_move_to_visually_next (&it->bidi_it); |
| 6350 | IT_STRING_CHARPOS (*it), | 6413 | IT_STRING_BYTEPOS (*it) = it->bidi_it.bytepos; |
| 6351 | IT_STRING_BYTEPOS (*it), | 6414 | IT_STRING_CHARPOS (*it) = it->bidi_it.charpos; |
| 6352 | it->end_charpos, it->string); | 6415 | if (it->cmp_it.from > 0) |
| 6416 | it->cmp_it.to = it->cmp_it.from; | ||
| 6417 | else | ||
| 6418 | { | ||
| 6419 | EMACS_INT stop = it->end_charpos; | ||
| 6420 | if (it->bidi_it.scan_dir < 0) | ||
| 6421 | stop = -1; | ||
| 6422 | composition_compute_stop_pos (&it->cmp_it, | ||
| 6423 | IT_STRING_CHARPOS (*it), | ||
| 6424 | IT_STRING_BYTEPOS (*it), stop, | ||
| 6425 | it->string); | ||
| 6426 | } | ||
| 6353 | } | 6427 | } |
| 6354 | } | 6428 | } |
| 6355 | else | 6429 | else |
| 6356 | { | 6430 | { |
| 6357 | IT_STRING_BYTEPOS (*it) += it->len; | 6431 | if (!it->bidi_p) |
| 6358 | IT_STRING_CHARPOS (*it) += 1; | 6432 | { |
| 6433 | IT_STRING_BYTEPOS (*it) += it->len; | ||
| 6434 | IT_STRING_CHARPOS (*it) += 1; | ||
| 6435 | } | ||
| 6436 | else | ||
| 6437 | { | ||
| 6438 | int prev_scan_dir = it->bidi_it.scan_dir; | ||
| 6439 | |||
| 6440 | bidi_move_to_visually_next (&it->bidi_it); | ||
| 6441 | IT_STRING_BYTEPOS (*it) = it->bidi_it.bytepos; | ||
| 6442 | IT_STRING_CHARPOS (*it) = it->bidi_it.charpos; | ||
| 6443 | if (prev_scan_dir != it->bidi_it.scan_dir) | ||
| 6444 | { | ||
| 6445 | EMACS_INT stop = it->end_charpos; | ||
| 6446 | |||
| 6447 | if (it->bidi_it.scan_dir < 0) | ||
| 6448 | stop = -1; | ||
| 6449 | composition_compute_stop_pos (&it->cmp_it, | ||
| 6450 | IT_STRING_CHARPOS (*it), | ||
| 6451 | IT_STRING_BYTEPOS (*it), stop, | ||
| 6452 | it->string); | ||
| 6453 | } | ||
| 6454 | } | ||
| 6359 | } | 6455 | } |
| 6360 | 6456 | ||
| 6361 | consider_string_end: | 6457 | consider_string_end: |
| @@ -6476,15 +6572,123 @@ next_element_from_string (struct it *it) | |||
| 6476 | xassert (IT_STRING_CHARPOS (*it) >= 0); | 6572 | xassert (IT_STRING_CHARPOS (*it) >= 0); |
| 6477 | position = it->current.string_pos; | 6573 | position = it->current.string_pos; |
| 6478 | 6574 | ||
| 6575 | /* With bidi reordering, the character to display might not be the | ||
| 6576 | character at IT_STRING_CHARPOS. BIDI_IT.FIRST_ELT non-zero means | ||
| 6577 | that we were reseat()ed to a new string, whose paragraph | ||
| 6578 | direction is not known. */ | ||
| 6579 | if (it->bidi_p && it->bidi_it.first_elt) | ||
| 6580 | { | ||
| 6581 | it->bidi_it.charpos = CHARPOS (position); | ||
| 6582 | it->bidi_it.bytepos = BYTEPOS (position); | ||
| 6583 | if (it->bidi_it.charpos >= it->string_nchars) | ||
| 6584 | { | ||
| 6585 | /* Nothing to do, but reset the FIRST_ELT flag, like | ||
| 6586 | bidi_paragraph_init does, because we are not going to | ||
| 6587 | call it. */ | ||
| 6588 | it->bidi_it.first_elt = 0; | ||
| 6589 | } | ||
| 6590 | else if (it->bidi_it.charpos <= 0) | ||
| 6591 | { | ||
| 6592 | /* If we are at the beginning of the string, we can produce | ||
| 6593 | the next element right away. */ | ||
| 6594 | bidi_paragraph_init (it->paragraph_embedding, &it->bidi_it, 1); | ||
| 6595 | bidi_move_to_visually_next (&it->bidi_it); | ||
| 6596 | } | ||
| 6597 | else | ||
| 6598 | { | ||
| 6599 | EMACS_INT orig_bytepos = BYTEPOS (position); | ||
| 6600 | |||
| 6601 | /* We need to prime the bidi iterator starting at the string | ||
| 6602 | beginning, before we will be able to produce the next | ||
| 6603 | element. */ | ||
| 6604 | it->bidi_it.charpos = it->bidi_it.bytepos = 0; | ||
| 6605 | bidi_paragraph_init (it->paragraph_embedding, &it->bidi_it, 1); | ||
| 6606 | do | ||
| 6607 | { | ||
| 6608 | /* Now return to buffer position where we were asked to | ||
| 6609 | get the next display element, and produce that. */ | ||
| 6610 | bidi_move_to_visually_next (&it->bidi_it); | ||
| 6611 | } | ||
| 6612 | while (it->bidi_it.bytepos != orig_bytepos | ||
| 6613 | && it->bidi_it.charpos < it->string_nchars); | ||
| 6614 | } | ||
| 6615 | |||
| 6616 | /* Adjust IT's position information to where we ended up. */ | ||
| 6617 | IT_STRING_CHARPOS (*it) = it->bidi_it.charpos; | ||
| 6618 | IT_STRING_BYTEPOS (*it) = it->bidi_it.bytepos; | ||
| 6619 | SET_TEXT_POS (position, IT_STRING_CHARPOS (*it), IT_STRING_BYTEPOS (*it)); | ||
| 6620 | { | ||
| 6621 | EMACS_INT stop = SCHARS (it->string); | ||
| 6622 | |||
| 6623 | if (it->bidi_it.scan_dir < 0) | ||
| 6624 | stop = -1; | ||
| 6625 | else if (stop > it->end_charpos) | ||
| 6626 | stop = it->end_charpos; | ||
| 6627 | composition_compute_stop_pos (&it->cmp_it, IT_STRING_CHARPOS (*it), | ||
| 6628 | IT_STRING_BYTEPOS (*it), stop, | ||
| 6629 | it->string); | ||
| 6630 | } | ||
| 6631 | } | ||
| 6632 | |||
| 6479 | /* Time to check for invisible text? */ | 6633 | /* Time to check for invisible text? */ |
| 6480 | if (IT_STRING_CHARPOS (*it) < it->end_charpos | 6634 | if (IT_STRING_CHARPOS (*it) < it->end_charpos) |
| 6481 | && IT_STRING_CHARPOS (*it) == it->stop_charpos) | ||
| 6482 | { | 6635 | { |
| 6483 | handle_stop (it); | 6636 | if (IT_STRING_CHARPOS (*it) >= it->stop_charpos) |
| 6637 | { | ||
| 6638 | if (!(!it->bidi_p | ||
| 6639 | || BIDI_AT_BASE_LEVEL (it->bidi_it) | ||
| 6640 | || IT_STRING_CHARPOS (*it) == it->stop_charpos)) | ||
| 6641 | { | ||
| 6642 | /* With bidi non-linear iteration, we could find | ||
| 6643 | ourselves far beyond the last computed stop_charpos, | ||
| 6644 | with several other stop positions in between that we | ||
| 6645 | missed. Scan them all now, in buffer's logical | ||
| 6646 | order, until we find and handle the last stop_charpos | ||
| 6647 | that precedes our current position. */ | ||
| 6648 | handle_stop_backwards (it, it->stop_charpos); | ||
| 6649 | return GET_NEXT_DISPLAY_ELEMENT (it); | ||
| 6650 | } | ||
| 6651 | else | ||
| 6652 | { | ||
| 6653 | if (it->bidi_p) | ||
| 6654 | { | ||
| 6655 | /* Take note of the stop position we just moved | ||
| 6656 | across, for when we will move back across it. */ | ||
| 6657 | it->prev_stop = it->stop_charpos; | ||
| 6658 | /* If we are at base paragraph embedding level, take | ||
| 6659 | note of the last stop position seen at this | ||
| 6660 | level. */ | ||
| 6661 | if (BIDI_AT_BASE_LEVEL (it->bidi_it)) | ||
| 6662 | it->base_level_stop = it->stop_charpos; | ||
| 6663 | } | ||
| 6664 | handle_stop (it); | ||
| 6484 | 6665 | ||
| 6485 | /* Since a handler may have changed IT->method, we must | 6666 | /* Since a handler may have changed IT->method, we must |
| 6486 | recurse here. */ | 6667 | recurse here. */ |
| 6487 | return GET_NEXT_DISPLAY_ELEMENT (it); | 6668 | return GET_NEXT_DISPLAY_ELEMENT (it); |
| 6669 | } | ||
| 6670 | } | ||
| 6671 | else if (it->bidi_p | ||
| 6672 | /* If we are before prev_stop, we may have overstepped | ||
| 6673 | on our way backwards a stop_pos, and if so, we need | ||
| 6674 | to handle that stop_pos. */ | ||
| 6675 | && IT_STRING_CHARPOS (*it) < it->prev_stop | ||
| 6676 | /* We can sometimes back up for reasons that have nothing | ||
| 6677 | to do with bidi reordering. E.g., compositions. The | ||
| 6678 | code below is only needed when we are above the base | ||
| 6679 | embedding level, so test for that explicitly. */ | ||
| 6680 | && !BIDI_AT_BASE_LEVEL (it->bidi_it)) | ||
| 6681 | { | ||
| 6682 | /* If we lost track of base_level_stop, we have no better place | ||
| 6683 | for handle_stop_backwards to start from than BEGV. This | ||
| 6684 | happens, e.g., when we were reseated to the previous | ||
| 6685 | screenful of text by vertical-motion. */ | ||
| 6686 | if (it->base_level_stop <= 0 | ||
| 6687 | || IT_STRING_CHARPOS (*it) < it->base_level_stop) | ||
| 6688 | it->base_level_stop = 0; | ||
| 6689 | handle_stop_backwards (it, it->base_level_stop); | ||
| 6690 | return GET_NEXT_DISPLAY_ELEMENT (it); | ||
| 6691 | } | ||
| 6488 | } | 6692 | } |
| 6489 | 6693 | ||
| 6490 | if (it->current.overlay_string_index >= 0) | 6694 | if (it->current.overlay_string_index >= 0) |
| @@ -6498,7 +6702,10 @@ next_element_from_string (struct it *it) | |||
| 6498 | return 0; | 6702 | return 0; |
| 6499 | } | 6703 | } |
| 6500 | else if (CHAR_COMPOSED_P (it, IT_STRING_CHARPOS (*it), | 6704 | else if (CHAR_COMPOSED_P (it, IT_STRING_CHARPOS (*it), |
| 6501 | IT_STRING_BYTEPOS (*it), SCHARS (it->string)) | 6705 | IT_STRING_BYTEPOS (*it), |
| 6706 | it->bidi_it.scan_dir < 0 | ||
| 6707 | ? -1 | ||
| 6708 | : SCHARS (it->string)) | ||
| 6502 | && next_element_from_composition (it)) | 6709 | && next_element_from_composition (it)) |
| 6503 | { | 6710 | { |
| 6504 | return 1; | 6711 | return 1; |
| @@ -6533,7 +6740,10 @@ next_element_from_string (struct it *it) | |||
| 6533 | CHARPOS (position) = BYTEPOS (position) = -1; | 6740 | CHARPOS (position) = BYTEPOS (position) = -1; |
| 6534 | } | 6741 | } |
| 6535 | else if (CHAR_COMPOSED_P (it, IT_STRING_CHARPOS (*it), | 6742 | else if (CHAR_COMPOSED_P (it, IT_STRING_CHARPOS (*it), |
| 6536 | IT_STRING_BYTEPOS (*it), it->string_nchars) | 6743 | IT_STRING_BYTEPOS (*it), |
| 6744 | it->bidi_it.scan_dir < 0 | ||
| 6745 | ? -1 | ||
| 6746 | : it->string_nchars) | ||
| 6537 | && next_element_from_composition (it)) | 6747 | && next_element_from_composition (it)) |
| 6538 | { | 6748 | { |
| 6539 | return 1; | 6749 | return 1; |
| @@ -6652,18 +6862,19 @@ next_element_from_stretch (struct it *it) | |||
| 6652 | return 1; | 6862 | return 1; |
| 6653 | } | 6863 | } |
| 6654 | 6864 | ||
| 6655 | /* Scan forward from CHARPOS in the current buffer, until we find a | 6865 | /* Scan forward from CHARPOS in the current buffer/string, until we |
| 6656 | stop position > current IT's position. Then handle the stop | 6866 | find a stop position > current IT's position. Then handle the stop |
| 6657 | position before that. This is called when we bump into a stop | 6867 | position before that. This is called when we bump into a stop |
| 6658 | position while reordering bidirectional text. CHARPOS should be | 6868 | position while reordering bidirectional text. CHARPOS should be |
| 6659 | the last previously processed stop_pos (or BEGV, if none were | 6869 | the last previously processed stop_pos (or BEGV/0, if none were |
| 6660 | processed yet) whose position is less that IT's current | 6870 | processed yet) whose position is less that IT's current |
| 6661 | position. */ | 6871 | position. */ |
| 6662 | 6872 | ||
| 6663 | static void | 6873 | static void |
| 6664 | handle_stop_backwards (struct it *it, EMACS_INT charpos) | 6874 | handle_stop_backwards (struct it *it, EMACS_INT charpos) |
| 6665 | { | 6875 | { |
| 6666 | EMACS_INT where_we_are = IT_CHARPOS (*it); | 6876 | int bufp = !STRINGP (it->string); |
| 6877 | EMACS_INT where_we_are = (bufp ? IT_CHARPOS (*it) : IT_STRING_CHARPOS (*it)); | ||
| 6667 | struct display_pos save_current = it->current; | 6878 | struct display_pos save_current = it->current; |
| 6668 | struct text_pos save_position = it->position; | 6879 | struct text_pos save_position = it->position; |
| 6669 | struct text_pos pos1; | 6880 | struct text_pos pos1; |
| @@ -6674,8 +6885,13 @@ handle_stop_backwards (struct it *it, EMACS_INT charpos) | |||
| 6674 | do | 6885 | do |
| 6675 | { | 6886 | { |
| 6676 | it->prev_stop = charpos; | 6887 | it->prev_stop = charpos; |
| 6677 | SET_TEXT_POS (pos1, charpos, CHAR_TO_BYTE (charpos)); | 6888 | if (bufp) |
| 6678 | reseat_1 (it, pos1, 0); | 6889 | { |
| 6890 | SET_TEXT_POS (pos1, charpos, CHAR_TO_BYTE (charpos)); | ||
| 6891 | reseat_1 (it, pos1, 0); | ||
| 6892 | } | ||
| 6893 | else | ||
| 6894 | it->current.string_pos = string_pos (charpos, it->string); | ||
| 6679 | compute_stop_pos (it); | 6895 | compute_stop_pos (it); |
| 6680 | /* We must advance forward, right? */ | 6896 | /* We must advance forward, right? */ |
| 6681 | if (it->stop_charpos <= it->prev_stop) | 6897 | if (it->stop_charpos <= it->prev_stop) |
| @@ -17391,9 +17607,9 @@ handle_line_prefix (struct it *it) | |||
| 17391 | 17607 | ||
| 17392 | 17608 | ||
| 17393 | /* Remove N glyphs at the start of a reversed IT->glyph_row. Called | 17609 | /* Remove N glyphs at the start of a reversed IT->glyph_row. Called |
| 17394 | only for R2L lines from display_line, when it decides that too many | 17610 | only for R2L lines from display_line and display_string, when they |
| 17395 | glyphs were produced by PRODUCE_GLYPHS, and the line needs to be | 17611 | decide that too many glyphs were produced by PRODUCE_GLYPHS, and |
| 17396 | continued. */ | 17612 | the line/string needs to be continued on the next glyph row. */ |
| 17397 | static void | 17613 | static void |
| 17398 | unproduce_glyphs (struct it *it, int n) | 17614 | unproduce_glyphs (struct it *it, int n) |
| 17399 | { | 17615 | { |
| @@ -18501,6 +18717,9 @@ display_mode_line (struct window *w, enum face_id face_id, Lisp_Object format) | |||
| 18501 | /* Force the mode-line to be displayed in the default face. */ | 18717 | /* Force the mode-line to be displayed in the default face. */ |
| 18502 | it.base_face_id = it.face_id = DEFAULT_FACE_ID; | 18718 | it.base_face_id = it.face_id = DEFAULT_FACE_ID; |
| 18503 | 18719 | ||
| 18720 | /* FIXME: This should take its value from a user option. */ | ||
| 18721 | it.paragraph_embedding = L2R; | ||
| 18722 | |||
| 18504 | record_unwind_protect (unwind_format_mode_line, | 18723 | record_unwind_protect (unwind_format_mode_line, |
| 18505 | format_mode_line_unwind_data (NULL, Qnil, 0)); | 18724 | format_mode_line_unwind_data (NULL, Qnil, 0)); |
| 18506 | 18725 | ||
| @@ -18606,6 +18825,8 @@ display_mode_element (struct it *it, int depth, int field_width, int precision, | |||
| 18606 | int n = 0, field, prec; | 18825 | int n = 0, field, prec; |
| 18607 | int literal = 0; | 18826 | int literal = 0; |
| 18608 | 18827 | ||
| 18828 | it->paragraph_embedding = L2R; | ||
| 18829 | |||
| 18609 | tail_recurse: | 18830 | tail_recurse: |
| 18610 | if (depth > 100) | 18831 | if (depth > 100) |
| 18611 | elt = build_string ("*too-deep*"); | 18832 | elt = build_string ("*too-deep*"); |
| @@ -20046,6 +20267,7 @@ display_string (const char *string, Lisp_Object lisp_string, Lisp_Object face_st | |||
| 20046 | int hpos_at_start = it->hpos; | 20267 | int hpos_at_start = it->hpos; |
| 20047 | int saved_face_id = it->face_id; | 20268 | int saved_face_id = it->face_id; |
| 20048 | struct glyph_row *row = it->glyph_row; | 20269 | struct glyph_row *row = it->glyph_row; |
| 20270 | EMACS_INT it_charpos; | ||
| 20049 | 20271 | ||
| 20050 | /* Initialize the iterator IT for iteration over STRING beginning | 20272 | /* Initialize the iterator IT for iteration over STRING beginning |
| 20051 | with index START. */ | 20273 | with index START. */ |
| @@ -20091,6 +20313,11 @@ display_string (const char *string, Lisp_Object lisp_string, Lisp_Object face_st | |||
| 20091 | row->phys_height = it->max_phys_ascent + it->max_phys_descent; | 20313 | row->phys_height = it->max_phys_ascent + it->max_phys_descent; |
| 20092 | row->extra_line_spacing = it->max_extra_line_spacing; | 20314 | row->extra_line_spacing = it->max_extra_line_spacing; |
| 20093 | 20315 | ||
| 20316 | if (STRINGP (it->string)) | ||
| 20317 | it_charpos = IT_STRING_CHARPOS (*it); | ||
| 20318 | else | ||
| 20319 | it_charpos = IT_CHARPOS (*it); | ||
| 20320 | |||
| 20094 | /* This condition is for the case that we are called with current_x | 20321 | /* This condition is for the case that we are called with current_x |
| 20095 | past last_visible_x. */ | 20322 | past last_visible_x. */ |
| 20096 | while (it->current_x < max_x) | 20323 | while (it->current_x < max_x) |
| @@ -20103,10 +20330,10 @@ display_string (const char *string, Lisp_Object lisp_string, Lisp_Object face_st | |||
| 20103 | 20330 | ||
| 20104 | /* Produce glyphs. */ | 20331 | /* Produce glyphs. */ |
| 20105 | x_before = it->current_x; | 20332 | x_before = it->current_x; |
| 20106 | n_glyphs_before = it->glyph_row->used[TEXT_AREA]; | 20333 | n_glyphs_before = row->used[TEXT_AREA]; |
| 20107 | PRODUCE_GLYPHS (it); | 20334 | PRODUCE_GLYPHS (it); |
| 20108 | 20335 | ||
| 20109 | nglyphs = it->glyph_row->used[TEXT_AREA] - n_glyphs_before; | 20336 | nglyphs = row->used[TEXT_AREA] - n_glyphs_before; |
| 20110 | i = 0; | 20337 | i = 0; |
| 20111 | x = x_before; | 20338 | x = x_before; |
| 20112 | while (i < nglyphs) | 20339 | while (i < nglyphs) |
| @@ -20120,12 +20347,18 @@ display_string (const char *string, Lisp_Object lisp_string, Lisp_Object face_st | |||
| 20120 | if (CHAR_GLYPH_PADDING_P (*glyph)) | 20347 | if (CHAR_GLYPH_PADDING_P (*glyph)) |
| 20121 | { | 20348 | { |
| 20122 | /* A wide character is unbreakable. */ | 20349 | /* A wide character is unbreakable. */ |
| 20123 | it->glyph_row->used[TEXT_AREA] = n_glyphs_before; | 20350 | if (row->reversed_p) |
| 20351 | unproduce_glyphs (it, row->used[TEXT_AREA] | ||
| 20352 | - n_glyphs_before); | ||
| 20353 | row->used[TEXT_AREA] = n_glyphs_before; | ||
| 20124 | it->current_x = x_before; | 20354 | it->current_x = x_before; |
| 20125 | } | 20355 | } |
| 20126 | else | 20356 | else |
| 20127 | { | 20357 | { |
| 20128 | it->glyph_row->used[TEXT_AREA] = n_glyphs_before + i; | 20358 | if (row->reversed_p) |
| 20359 | unproduce_glyphs (it, row->used[TEXT_AREA] | ||
| 20360 | - (n_glyphs_before + i)); | ||
| 20361 | row->used[TEXT_AREA] = n_glyphs_before + i; | ||
| 20129 | it->current_x = x; | 20362 | it->current_x = x; |
| 20130 | } | 20363 | } |
| 20131 | break; | 20364 | break; |
| @@ -20135,7 +20368,7 @@ display_string (const char *string, Lisp_Object lisp_string, Lisp_Object face_st | |||
| 20135 | /* Glyph is at least partially visible. */ | 20368 | /* Glyph is at least partially visible. */ |
| 20136 | ++it->hpos; | 20369 | ++it->hpos; |
| 20137 | if (x < it->first_visible_x) | 20370 | if (x < it->first_visible_x) |
| 20138 | it->glyph_row->x = x - it->first_visible_x; | 20371 | row->x = x - it->first_visible_x; |
| 20139 | } | 20372 | } |
| 20140 | else | 20373 | else |
| 20141 | { | 20374 | { |
| @@ -20167,6 +20400,10 @@ display_string (const char *string, Lisp_Object lisp_string, Lisp_Object face_st | |||
| 20167 | } | 20400 | } |
| 20168 | 20401 | ||
| 20169 | set_iterator_to_next (it, 1); | 20402 | set_iterator_to_next (it, 1); |
| 20403 | if (STRINGP (it->string)) | ||
| 20404 | it_charpos = IT_STRING_CHARPOS (*it); | ||
| 20405 | else | ||
| 20406 | it_charpos = IT_CHARPOS (*it); | ||
| 20170 | 20407 | ||
| 20171 | /* Stop if truncating at the right edge. */ | 20408 | /* Stop if truncating at the right edge. */ |
| 20172 | if (it->line_wrap == TRUNCATE | 20409 | if (it->line_wrap == TRUNCATE |
| @@ -20174,7 +20411,7 @@ display_string (const char *string, Lisp_Object lisp_string, Lisp_Object face_st | |||
| 20174 | { | 20411 | { |
| 20175 | /* Add truncation mark, but don't do it if the line is | 20412 | /* Add truncation mark, but don't do it if the line is |
| 20176 | truncated at a padding space. */ | 20413 | truncated at a padding space. */ |
| 20177 | if (IT_CHARPOS (*it) < it->string_nchars) | 20414 | if (it_charpos < it->string_nchars) |
| 20178 | { | 20415 | { |
| 20179 | if (!FRAME_WINDOW_P (it->f)) | 20416 | if (!FRAME_WINDOW_P (it->f)) |
| 20180 | { | 20417 | { |
| @@ -20182,9 +20419,20 @@ display_string (const char *string, Lisp_Object lisp_string, Lisp_Object face_st | |||
| 20182 | 20419 | ||
| 20183 | if (it->current_x > it->last_visible_x) | 20420 | if (it->current_x > it->last_visible_x) |
| 20184 | { | 20421 | { |
| 20185 | for (ii = row->used[TEXT_AREA] - 1; ii > 0; --ii) | 20422 | if (!row->reversed_p) |
| 20186 | if (!CHAR_GLYPH_PADDING_P (row->glyphs[TEXT_AREA][ii])) | 20423 | { |
| 20187 | break; | 20424 | for (ii = row->used[TEXT_AREA] - 1; ii > 0; --ii) |
| 20425 | if (!CHAR_GLYPH_PADDING_P (row->glyphs[TEXT_AREA][ii])) | ||
| 20426 | break; | ||
| 20427 | } | ||
| 20428 | else | ||
| 20429 | { | ||
| 20430 | for (ii = 0; ii < row->used[TEXT_AREA]; ii++) | ||
| 20431 | if (!CHAR_GLYPH_PADDING_P (row->glyphs[TEXT_AREA][ii])) | ||
| 20432 | break; | ||
| 20433 | unproduce_glyphs (it, ii + 1); | ||
| 20434 | ii = row->used[TEXT_AREA] - (ii + 1); | ||
| 20435 | } | ||
| 20188 | for (n = row->used[TEXT_AREA]; ii < n; ++ii) | 20436 | for (n = row->used[TEXT_AREA]; ii < n; ++ii) |
| 20189 | { | 20437 | { |
| 20190 | row->used[TEXT_AREA] = ii; | 20438 | row->used[TEXT_AREA] = ii; |
| @@ -20193,7 +20441,7 @@ display_string (const char *string, Lisp_Object lisp_string, Lisp_Object face_st | |||
| 20193 | } | 20441 | } |
| 20194 | produce_special_glyphs (it, IT_TRUNCATION); | 20442 | produce_special_glyphs (it, IT_TRUNCATION); |
| 20195 | } | 20443 | } |
| 20196 | it->glyph_row->truncated_on_right_p = 1; | 20444 | row->truncated_on_right_p = 1; |
| 20197 | } | 20445 | } |
| 20198 | break; | 20446 | break; |
| 20199 | } | 20447 | } |
| @@ -20201,11 +20449,11 @@ display_string (const char *string, Lisp_Object lisp_string, Lisp_Object face_st | |||
| 20201 | 20449 | ||
| 20202 | /* Maybe insert a truncation at the left. */ | 20450 | /* Maybe insert a truncation at the left. */ |
| 20203 | if (it->first_visible_x | 20451 | if (it->first_visible_x |
| 20204 | && IT_CHARPOS (*it) > 0) | 20452 | && it_charpos > 0) |
| 20205 | { | 20453 | { |
| 20206 | if (!FRAME_WINDOW_P (it->f)) | 20454 | if (!FRAME_WINDOW_P (it->f)) |
| 20207 | insert_left_trunc_glyphs (it); | 20455 | insert_left_trunc_glyphs (it); |
| 20208 | it->glyph_row->truncated_on_left_p = 1; | 20456 | row->truncated_on_left_p = 1; |
| 20209 | } | 20457 | } |
| 20210 | 20458 | ||
| 20211 | it->face_id = saved_face_id; | 20459 | it->face_id = saved_face_id; |