aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorEli Zaretskii2011-06-11 18:13:17 +0300
committerEli Zaretskii2011-06-11 18:13:17 +0300
commit34c48e575a30f075daedda6b487c7d24181743be (patch)
tree84cf9f68ec8d5de5dab5611748b59059e8e084f6 /src
parent4b988f8b7f1824a0392a3f01c1048782ed8512f9 (diff)
downloademacs-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/ChangeLog15
-rw-r--r--src/xdisp.c380
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
62011-06-10 Eli Zaretskii <eliz@gnu.org> 212011-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);
783static int store_mode_line_noprop (const char *, int, int); 783static int store_mode_line_noprop (const char *, int, int);
784static void handle_stop (struct it *); 784static void handle_stop (struct it *);
785static void handle_stop_backwards (struct it *, EMACS_INT); 785static void handle_stop_backwards (struct it *, EMACS_INT);
786static int single_display_spec_intangible_p (Lisp_Object);
787static void vmessage (const char *, va_list) ATTRIBUTE_FORMAT_PRINTF (1, 0); 786static void vmessage (const char *, va_list) ATTRIBUTE_FORMAT_PRINTF (1, 0);
788static void ensure_echo_area_buffers (void); 787static void ensure_echo_area_buffers (void);
789static Lisp_Object unwind_with_echo_area_buffer (Lisp_Object); 788static 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
6663static void 6873static void
6664handle_stop_backwards (struct it *it, EMACS_INT charpos) 6874handle_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. */
17397static void 17613static void
17398unproduce_glyphs (struct it *it, int n) 17614unproduce_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;