aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorEli Zaretskii2011-06-04 10:41:44 +0300
committerEli Zaretskii2011-06-04 10:41:44 +0300
commitfec2107c58835163dc3b08c0a833a5072aa1fca9 (patch)
treefa112f71d61bd4166aa56fb80da80357455906ab /src
parentea9fafe0937ebd99780610a7c1451ca08b013702 (diff)
parent57f97249c8e8673df19219e1f5cba478ea23024d (diff)
downloademacs-fec2107c58835163dc3b08c0a833a5072aa1fca9.tar.gz
emacs-fec2107c58835163dc3b08c0a833a5072aa1fca9.zip
Support bidi reordering of text covered by display properties.
src/bidi.c (bidi_copy_it): Use offsetof instead of emulating it. (bidi_fetch_char, bidi_fetch_char_advance): New functions. (bidi_cache_search, bidi_cache_iterator_state) (bidi_paragraph_init, bidi_resolve_explicit, bidi_resolve_weak) (bidi_level_of_next_char, bidi_move_to_visually_next): Support character positions inside a run of characters covered by a display string. (bidi_paragraph_init, bidi_resolve_explicit_1) (bidi_level_of_next_char): Call bidi_fetch_char and bidi_fetch_char_advance instead of FETCH_CHAR and FETCH_CHAR_ADVANCE. (bidi_init_it): Initialize new members. (LRE_CHAR, RLE_CHAR, PDF_CHAR, LRO_CHAR, RLO_CHAR): Remove macro definitions. (bidi_explicit_dir_char): Lookup character type in bidi_type_table, instead of using explicit *_CHAR codes. (bidi_resolve_explicit, bidi_resolve_weak): Use FETCH_MULTIBYTE_CHAR instead of FETCH_CHAR, as reordering of bidirectional text is supported only in multibyte buffers. (bidi_init_it): Accept additional argument FRAME_WINDOW_P and use it to initialize the frame_window_p member of struct bidi_it. (bidi_cache_iterator_state, bidi_resolve_explicit_1) (bidi_resolve_explicit, bidi_resolve_weak) (bidi_level_of_next_char, bidi_move_to_visually_next): Abort if bidi_it->nchars is non-positive. (bidi_level_of_next_char): Don't try to lookup the cache for the next/previous character if nothing is cached there yet, or if we were just reseat()'ed to a new position. src/xdisp.c (set_cursor_from_row): Set start and stop points according to the row's direction when priming the loop that looks for the glyph on which to display cursor. (single_display_spec_intangible_p): Function deleted. (display_prop_intangible_p): Reimplement to call handle_display_spec instead of single_display_spec_intangible_p. Accept 3 additional arguments needed by handle_display_spec. This fixes incorrect cursor motion across display property with complex values: lists, `(when COND...)' forms, etc. (single_display_spec_string_p): Support property values that are lists with the argument STRING its top-level element. (display_prop_string_p): Fix the condition for processing a property that is a list to be consistent with handle_display_spec. (handle_display_spec): New function, refactored from the last portion of handle_display_prop. (compute_display_string_pos): Accept additional argument FRAME_WINDOW_P. Call handle_display_spec to determine whether the value of a `display' property is a "replacing spec". (handle_single_display_spec): Accept 2 additional arguments BUFPOS and FRAME_WINDOW_P. If IT is NULL, don't set up the iterator from the display property, but just return a value indicating whether the display property will replace the characters it covers. (Fcurrent_bidi_paragraph_direction): Initialize the nchars and frame_window_p members of struct bidi_it. (compute_display_string_pos, compute_display_string_end): New functions. (push_it): Accept second argument POSITION, where pop_it should jump to continue iteration. (reseat_1): Initialize bidi_it.disp_pos. src/keyboard.c (adjust_point_for_property): Adjust the call to display_prop_intangible_p to its new signature. src/dispextern.h (struct bidi_it): New member frame_window_p. (bidi_init_it): Update prototypes. (display_prop_intangible_p): Update prototype. (compute_display_string_pos, compute_display_string_end): Declare prototypes. (struct bidi_it): New members nchars and disp_pos. ch_len is now EMACS_INT.
Diffstat (limited to 'src')
-rw-r--r--src/ChangeLog74
-rw-r--r--src/bidi.c264
-rw-r--r--src/dispextern.h18
-rw-r--r--src/keyboard.c2
-rw-r--r--src/xdisp.c609
5 files changed, 649 insertions, 318 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index 45d8e38738a..4c33bcc4e67 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,77 @@
12011-06-03 Eli Zaretskii <eliz@gnu.org>
2
3 Support bidi reordering of text covered by display properties.
4
5 * bidi.c (bidi_copy_it): Use offsetof instead of emulating it.
6 (bidi_fetch_char, bidi_fetch_char_advance): New functions.
7 (bidi_cache_search, bidi_cache_iterator_state)
8 (bidi_paragraph_init, bidi_resolve_explicit, bidi_resolve_weak)
9 (bidi_level_of_next_char, bidi_move_to_visually_next): Support
10 character positions inside a run of characters covered by a
11 display string.
12 (bidi_paragraph_init, bidi_resolve_explicit_1)
13 (bidi_level_of_next_char): Call bidi_fetch_char and
14 bidi_fetch_char_advance instead of FETCH_CHAR and
15 FETCH_CHAR_ADVANCE.
16 (bidi_init_it): Initialize new members.
17 (LRE_CHAR, RLE_CHAR, PDF_CHAR, LRO_CHAR, RLO_CHAR): Remove macro
18 definitions.
19 (bidi_explicit_dir_char): Lookup character type in bidi_type_table,
20 instead of using explicit *_CHAR codes.
21 (bidi_resolve_explicit, bidi_resolve_weak): Use
22 FETCH_MULTIBYTE_CHAR instead of FETCH_CHAR, as reordering of
23 bidirectional text is supported only in multibyte buffers.
24 (bidi_init_it): Accept additional argument FRAME_WINDOW_P and use
25 it to initialize the frame_window_p member of struct bidi_it.
26 (bidi_cache_iterator_state, bidi_resolve_explicit_1)
27 (bidi_resolve_explicit, bidi_resolve_weak)
28 (bidi_level_of_next_char, bidi_move_to_visually_next): Abort if
29 bidi_it->nchars is non-positive.
30 (bidi_level_of_next_char): Don't try to lookup the cache for the
31 next/previous character if nothing is cached there yet, or if we
32 were just reseat()'ed to a new position.
33
34 * xdisp.c (set_cursor_from_row): Set start and stop points
35 according to the row's direction when priming the loop that looks
36 for the glyph on which to display cursor.
37 (single_display_spec_intangible_p): Function deleted.
38 (display_prop_intangible_p): Reimplement to call
39 handle_display_spec instead of single_display_spec_intangible_p.
40 Accept 3 additional arguments needed by handle_display_spec. This
41 fixes incorrect cursor motion across display property with complex
42 values: lists, `(when COND...)' forms, etc.
43 (single_display_spec_string_p): Support property values that are
44 lists with the argument STRING its top-level element.
45 (display_prop_string_p): Fix the condition for processing a
46 property that is a list to be consistent with handle_display_spec.
47 (handle_display_spec): New function, refactored from the
48 last portion of handle_display_prop.
49 (compute_display_string_pos): Accept additional argument
50 FRAME_WINDOW_P. Call handle_display_spec to determine whether the
51 value of a `display' property is a "replacing spec".
52 (handle_single_display_spec): Accept 2 additional arguments BUFPOS
53 and FRAME_WINDOW_P. If IT is NULL, don't set up the iterator from
54 the display property, but just return a value indicating whether
55 the display property will replace the characters it covers.
56 (Fcurrent_bidi_paragraph_direction): Initialize the nchars and
57 frame_window_p members of struct bidi_it.
58 (compute_display_string_pos, compute_display_string_end): New
59 functions.
60 (push_it): Accept second argument POSITION, where pop_it should
61 jump to continue iteration.
62 (reseat_1): Initialize bidi_it.disp_pos.
63
64 * keyboard.c (adjust_point_for_property): Adjust the call to
65 display_prop_intangible_p to its new signature.
66
67 * dispextern.h (struct bidi_it): New member frame_window_p.
68 (bidi_init_it): Update prototypes.
69 (display_prop_intangible_p): Update prototype.
70 (compute_display_string_pos, compute_display_string_end): Declare
71 prototypes.
72 (struct bidi_it): New members nchars and disp_pos. ch_len is now
73 EMACS_INT.
74
12011-06-02 Paul Eggert <eggert@cs.ucla.edu> 752011-06-02 Paul Eggert <eggert@cs.ucla.edu>
2 76
3 Malloc failure behavior now depends on size of allocation. 77 Malloc failure behavior now depends on size of allocation.
diff --git a/src/bidi.c b/src/bidi.c
index b05fd21e5b6..a41f50d9ca5 100644
--- a/src/bidi.c
+++ b/src/bidi.c
@@ -62,15 +62,8 @@ static int bidi_initialized = 0;
62 62
63static Lisp_Object bidi_type_table, bidi_mirror_table; 63static Lisp_Object bidi_type_table, bidi_mirror_table;
64 64
65/* FIXME: Remove these when bidi_explicit_dir_char uses a lookup table. */
66#define LRM_CHAR 0x200E 65#define LRM_CHAR 0x200E
67#define RLM_CHAR 0x200F 66#define RLM_CHAR 0x200F
68#define LRE_CHAR 0x202A
69#define RLE_CHAR 0x202B
70#define PDF_CHAR 0x202C
71#define LRO_CHAR 0x202D
72#define RLO_CHAR 0x202E
73
74#define BIDI_EOB -1 67#define BIDI_EOB -1
75 68
76/* Local data structures. (Look in dispextern.h for the rest.) */ 69/* Local data structures. (Look in dispextern.h for the rest.) */
@@ -258,7 +251,7 @@ bidi_copy_it (struct bidi_it *to, struct bidi_it *from)
258 int i; 251 int i;
259 252
260 /* Copy everything except the level stack and beyond. */ 253 /* Copy everything except the level stack and beyond. */
261 memcpy (to, from, ((size_t)&((struct bidi_it *)0)->level_stack[0])); 254 memcpy (to, from, offsetof (struct bidi_it, level_stack[0]));
262 255
263 /* Copy the active part of the level stack. */ 256 /* Copy the active part of the level stack. */
264 to->level_stack[0] = from->level_stack[0]; /* level zero is always in use */ 257 to->level_stack[0] = from->level_stack[0]; /* level zero is always in use */
@@ -319,10 +312,17 @@ bidi_cache_search (EMACS_INT charpos, int level, int dir)
319 if (bidi_cache_idx) 312 if (bidi_cache_idx)
320 { 313 {
321 if (charpos < bidi_cache[bidi_cache_last_idx].charpos) 314 if (charpos < bidi_cache[bidi_cache_last_idx].charpos)
322 dir = -1; 315 {
323 else if (charpos > bidi_cache[bidi_cache_last_idx].charpos) 316 dir = -1;
324 dir = 1; 317 i_start = bidi_cache_last_idx - 1;
325 if (dir) 318 }
319 else if (charpos > (bidi_cache[bidi_cache_last_idx].charpos
320 + bidi_cache[bidi_cache_last_idx].nchars - 1))
321 {
322 dir = 1;
323 i_start = bidi_cache_last_idx + 1;
324 }
325 else if (dir)
326 i_start = bidi_cache_last_idx; 326 i_start = bidi_cache_last_idx;
327 else 327 else
328 { 328 {
@@ -334,14 +334,16 @@ bidi_cache_search (EMACS_INT charpos, int level, int dir)
334 { 334 {
335 /* Linear search for now; FIXME! */ 335 /* Linear search for now; FIXME! */
336 for (i = i_start; i >= 0; i--) 336 for (i = i_start; i >= 0; i--)
337 if (bidi_cache[i].charpos == charpos 337 if (bidi_cache[i].charpos <= charpos
338 && charpos < bidi_cache[i].charpos + bidi_cache[i].nchars
338 && (level == -1 || bidi_cache[i].resolved_level <= level)) 339 && (level == -1 || bidi_cache[i].resolved_level <= level))
339 return i; 340 return i;
340 } 341 }
341 else 342 else
342 { 343 {
343 for (i = i_start; i < bidi_cache_idx; i++) 344 for (i = i_start; i < bidi_cache_idx; i++)
344 if (bidi_cache[i].charpos == charpos 345 if (bidi_cache[i].charpos <= charpos
346 && charpos < bidi_cache[i].charpos + bidi_cache[i].nchars
345 && (level == -1 || bidi_cache[i].resolved_level <= level)) 347 && (level == -1 || bidi_cache[i].resolved_level <= level))
346 return i; 348 return i;
347 } 349 }
@@ -426,12 +428,15 @@ bidi_cache_iterator_state (struct bidi_it *bidi_it, int resolved)
426 If we are outside the range of cached positions, the cache is 428 If we are outside the range of cached positions, the cache is
427 useless and must be reset. */ 429 useless and must be reset. */
428 if (idx > 0 && 430 if (idx > 0 &&
429 (bidi_it->charpos > bidi_cache[idx - 1].charpos + 1 431 (bidi_it->charpos > (bidi_cache[idx - 1].charpos
432 + bidi_cache[idx - 1].nchars)
430 || bidi_it->charpos < bidi_cache[0].charpos)) 433 || bidi_it->charpos < bidi_cache[0].charpos))
431 { 434 {
432 bidi_cache_reset (); 435 bidi_cache_reset ();
433 idx = 0; 436 idx = 0;
434 } 437 }
438 if (bidi_it->nchars <= 0)
439 abort ();
435 bidi_copy_it (&bidi_cache[idx], bidi_it); 440 bidi_copy_it (&bidi_cache[idx], bidi_it);
436 if (!resolved) 441 if (!resolved)
437 bidi_cache[idx].resolved_level = -1; 442 bidi_cache[idx].resolved_level = -1;
@@ -548,6 +553,7 @@ bidi_set_sor_type (struct bidi_it *bidi_it, int level_before, int level_after)
548 bidi_it->ignore_bn_limit = 0; /* meaning it's unknown */ 553 bidi_it->ignore_bn_limit = 0; /* meaning it's unknown */
549} 554}
550 555
556/* Perform initializations for reordering a new line of bidi text. */
551static void 557static void
552bidi_line_init (struct bidi_it *bidi_it) 558bidi_line_init (struct bidi_it *bidi_it)
553{ 559{
@@ -565,6 +571,65 @@ bidi_line_init (struct bidi_it *bidi_it)
565 bidi_cache_reset (); 571 bidi_cache_reset ();
566} 572}
567 573
574/* Fetch and return the character at BYTEPOS/CHARPOS. If that
575 character is covered by a display string, treat the entire run of
576 covered characters as a single character u+FFFC, and return their
577 combined length in CH_LEN and NCHARS. DISP_POS specifies the
578 character position of the next display string, or -1 if not yet
579 computed. When the next character is at or beyond that position,
580 the function updates DISP_POS with the position of the next display
581 string. */
582static inline int
583bidi_fetch_char (EMACS_INT bytepos, EMACS_INT charpos, EMACS_INT *disp_pos,
584 int frame_window_p, EMACS_INT *ch_len, EMACS_INT *nchars)
585{
586 int ch;
587
588 /* FIXME: Support strings in addition to buffers. */
589 /* 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. */
591 if (charpos < ZV && charpos > *disp_pos)
592 *disp_pos = compute_display_string_pos (charpos, frame_window_p);
593
594 /* Fetch the character at BYTEPOS. */
595 if (bytepos >= ZV_BYTE)
596 {
597 ch = BIDI_EOB;
598 *ch_len = 1;
599 *nchars = 1;
600 *disp_pos = ZV;
601 }
602 else if (charpos >= *disp_pos)
603 {
604 EMACS_INT disp_end_pos;
605
606 /* We don't expect to find ourselves in the middle of a display
607 property. Hopefully, it will never be needed. */
608 if (charpos > *disp_pos)
609 abort ();
610 /* Return the Unicode Object Replacement Character to represent
611 the entire run of characters covered by the display
612 string. */
613 ch = 0xFFFC;
614 disp_end_pos = compute_display_string_end (*disp_pos);
615 *nchars = disp_end_pos - *disp_pos;
616 *ch_len = CHAR_TO_BYTE (disp_end_pos) - bytepos;
617 }
618 else
619 {
620 ch = FETCH_MULTIBYTE_CHAR (bytepos);
621 *nchars = 1;
622 *ch_len = CHAR_BYTES (ch);
623 }
624
625 /* If we just entered a run of characters covered by a display
626 string, compute the position of the next display string. */
627 if (charpos + *nchars <= ZV && charpos + *nchars > *disp_pos)
628 *disp_pos = compute_display_string_pos (charpos + *nchars, frame_window_p);
629
630 return ch;
631}
632
568/* Find the beginning of this paragraph by looking back in the buffer. 633/* Find the beginning of this paragraph by looking back in the buffer.
569 Value is the byte position of the paragraph's beginning. */ 634 Value is the byte position of the paragraph's beginning. */
570static EMACS_INT 635static EMACS_INT
@@ -576,6 +641,10 @@ bidi_find_paragraph_start (EMACS_INT pos, EMACS_INT pos_byte)
576 while (pos_byte > BEGV_BYTE 641 while (pos_byte > BEGV_BYTE
577 && fast_looking_at (re, pos, pos_byte, limit, limit_byte, Qnil) < 0) 642 && fast_looking_at (re, pos, pos_byte, limit, limit_byte, Qnil) < 0)
578 { 643 {
644 /* FIXME: What if the paragraph beginning is covered by a
645 display string? And what if a display string covering some
646 of the text over which we scan back includes
647 paragraph_start_re? */
579 pos = find_next_newline_no_quit (pos - 1, -1); 648 pos = find_next_newline_no_quit (pos - 1, -1);
580 pos_byte = CHAR_TO_BYTE (pos); 649 pos_byte = CHAR_TO_BYTE (pos);
581 } 650 }
@@ -587,7 +656,7 @@ bidi_find_paragraph_start (EMACS_INT pos, EMACS_INT pos_byte)
587 R2L, just use that. Otherwise, determine the paragraph direction 656 R2L, just use that. Otherwise, determine the paragraph direction
588 from the first strong directional character of the paragraph. 657 from the first strong directional character of the paragraph.
589 658
590 NO_DEFAULT_P non-nil means don't default to L2R if the paragraph 659 NO_DEFAULT_P non-zero means don't default to L2R if the paragraph
591 has no strong directional characters and both DIR and 660 has no strong directional characters and both DIR and
592 bidi_it->paragraph_dir are NEUTRAL_DIR. In that case, search back 661 bidi_it->paragraph_dir are NEUTRAL_DIR. In that case, search back
593 in the buffer until a paragraph is found with a strong character, 662 in the buffer until a paragraph is found with a strong character,
@@ -622,8 +691,9 @@ bidi_paragraph_init (bidi_dir_t dir, struct bidi_it *bidi_it, int no_default_p)
622 } 691 }
623 else if (dir == NEUTRAL_DIR) /* P2 */ 692 else if (dir == NEUTRAL_DIR) /* P2 */
624 { 693 {
625 int ch, ch_len; 694 int ch;
626 EMACS_INT pos; 695 EMACS_INT ch_len, nchars;
696 EMACS_INT pos, disp_pos = -1;
627 bidi_type_t type; 697 bidi_type_t type;
628 698
629 if (!bidi_initialized) 699 if (!bidi_initialized)
@@ -658,12 +728,12 @@ bidi_paragraph_init (bidi_dir_t dir, struct bidi_it *bidi_it, int no_default_p)
658 is non-zero. */ 728 is non-zero. */
659 do { 729 do {
660 bytepos = pstartbyte; 730 bytepos = pstartbyte;
661 ch = FETCH_CHAR (bytepos);
662 ch_len = CHAR_BYTES (ch);
663 pos = BYTE_TO_CHAR (bytepos); 731 pos = BYTE_TO_CHAR (bytepos);
732 ch = bidi_fetch_char (bytepos, pos, &disp_pos, bidi_it->frame_window_p,
733 &ch_len, &nchars);
664 type = bidi_get_type (ch, NEUTRAL_DIR); 734 type = bidi_get_type (ch, NEUTRAL_DIR);
665 735
666 for (pos++, bytepos += ch_len; 736 for (pos += nchars, bytepos += ch_len;
667 /* NOTE: UAX#9 says to search only for L, AL, or R types 737 /* NOTE: UAX#9 says to search only for L, AL, or R types
668 of characters, and ignore RLE, RLO, LRE, and LRO. 738 of characters, and ignore RLE, RLO, LRE, and LRO.
669 However, I'm not sure it makes sense to omit those 4; 739 However, I'm not sure it makes sense to omit those 4;
@@ -683,7 +753,11 @@ bidi_paragraph_init (bidi_dir_t dir, struct bidi_it *bidi_it, int no_default_p)
683 type = NEUTRAL_B; 753 type = NEUTRAL_B;
684 break; 754 break;
685 } 755 }
686 FETCH_CHAR_ADVANCE (ch, pos, bytepos); 756 /* Fetch next character and advance to get past it. */
757 ch = bidi_fetch_char (bytepos, pos, &disp_pos,
758 bidi_it->frame_window_p, &ch_len, &nchars);
759 pos += nchars;
760 bytepos += ch_len;
687 } 761 }
688 if (type == STRONG_R || type == STRONG_AL) /* P3 */ 762 if (type == STRONG_R || type == STRONG_AL) /* P3 */
689 bidi_it->paragraph_dir = R2L; 763 bidi_it->paragraph_dir = R2L;
@@ -702,6 +776,9 @@ bidi_paragraph_init (bidi_dir_t dir, struct bidi_it *bidi_it, int no_default_p)
702 /* Find the beginning of the previous paragraph, if any. */ 776 /* Find the beginning of the previous paragraph, if any. */
703 while (pbyte > BEGV_BYTE && prevpbyte >= pstartbyte) 777 while (pbyte > BEGV_BYTE && prevpbyte >= pstartbyte)
704 { 778 {
779 /* FXIME: What if p is covered by a display
780 string? See also a FIXME inside
781 bidi_find_paragraph_start. */
705 p--; 782 p--;
706 pbyte = CHAR_TO_BYTE (p); 783 pbyte = CHAR_TO_BYTE (p);
707 prevpbyte = bidi_find_paragraph_start (p, pbyte); 784 prevpbyte = bidi_find_paragraph_start (p, pbyte);
@@ -738,14 +815,17 @@ bidi_set_paragraph_end (struct bidi_it *bidi_it)
738 bidi_it->resolved_level = bidi_it->level_stack[0].level; 815 bidi_it->resolved_level = bidi_it->level_stack[0].level;
739} 816}
740 817
741/* Initialize the bidi iterator from buffer position CHARPOS. */ 818/* Initialize the bidi iterator from buffer/string position CHARPOS. */
742void 819void
743bidi_init_it (EMACS_INT charpos, EMACS_INT bytepos, struct bidi_it *bidi_it) 820bidi_init_it (EMACS_INT charpos, EMACS_INT bytepos, int frame_window_p,
821 struct bidi_it *bidi_it)
744{ 822{
745 if (! bidi_initialized) 823 if (! bidi_initialized)
746 bidi_initialize (); 824 bidi_initialize ();
747 bidi_it->charpos = charpos; 825 bidi_it->charpos = charpos;
748 bidi_it->bytepos = bytepos; 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 */
749 bidi_it->first_elt = 1; 829 bidi_it->first_elt = 1;
750 bidi_set_paragraph_end (bidi_it); 830 bidi_set_paragraph_end (bidi_it);
751 bidi_it->new_paragraph = 1; 831 bidi_it->new_paragraph = 1;
@@ -767,6 +847,7 @@ bidi_init_it (EMACS_INT charpos, EMACS_INT bytepos, struct bidi_it *bidi_it)
767 bidi_it->prev_for_neutral.type_after_w1 = 847 bidi_it->prev_for_neutral.type_after_w1 =
768 bidi_it->prev_for_neutral.orig_type = UNKNOWN_BT; 848 bidi_it->prev_for_neutral.orig_type = UNKNOWN_BT;
769 bidi_it->sor = L2R; /* FIXME: should it be user-selectable? */ 849 bidi_it->sor = L2R; /* FIXME: should it be user-selectable? */
850 bidi_it->disp_pos = -1; /* invalid/unknown */
770 bidi_cache_shrink (); 851 bidi_cache_shrink ();
771} 852}
772 853
@@ -829,12 +910,16 @@ bidi_resolve_neutral_1 (bidi_type_t prev_type, bidi_type_t next_type, int lev)
829} 910}
830 911
831static inline int 912static inline int
832bidi_explicit_dir_char (int c) 913bidi_explicit_dir_char (int ch)
833{ 914{
834 /* FIXME: this should be replaced with a lookup table with suitable 915 bidi_type_t ch_type;
835 bits set, like standard C ctype macros do. */ 916
836 return (c == LRE_CHAR || c == LRO_CHAR 917 if (!bidi_initialized)
837 || c == RLE_CHAR || c == RLO_CHAR || c == PDF_CHAR); 918 abort ();
919 ch_type = (bidi_type_t) XINT (CHAR_TABLE_REF (bidi_type_table, ch));
920 return (ch_type == LRE || ch_type == LRO
921 || ch_type == RLE || ch_type == RLO
922 || ch_type == PDF);
838} 923}
839 924
840/* A helper function for bidi_resolve_explicit. It advances to the 925/* A helper function for bidi_resolve_explicit. It advances to the
@@ -850,7 +935,10 @@ bidi_resolve_explicit_1 (struct bidi_it *bidi_it)
850 int new_level; 935 int new_level;
851 bidi_dir_t override; 936 bidi_dir_t override;
852 937
853 if (bidi_it->bytepos < BEGV_BYTE /* after reseat to BEGV? */ 938 /* 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
940 than BEGV_BYTE after reseat to BEGV. */
941 if (bidi_it->bytepos < BEGV_BYTE
854 || bidi_it->first_elt) 942 || bidi_it->first_elt)
855 { 943 {
856 bidi_it->first_elt = 0; 944 bidi_it->first_elt = 0;
@@ -860,7 +948,11 @@ bidi_resolve_explicit_1 (struct bidi_it *bidi_it)
860 } 948 }
861 else if (bidi_it->bytepos < ZV_BYTE) /* don't move at ZV */ 949 else if (bidi_it->bytepos < ZV_BYTE) /* don't move at ZV */
862 { 950 {
863 bidi_it->charpos++; 951 /* Advance to the next character, skipping characters covered by
952 display strings (nchars > 1). */
953 if (bidi_it->nchars <= 0)
954 abort ();
955 bidi_it->charpos += bidi_it->nchars;
864 if (bidi_it->ch_len == 0) 956 if (bidi_it->ch_len == 0)
865 abort (); 957 abort ();
866 bidi_it->bytepos += bidi_it->ch_len; 958 bidi_it->bytepos += bidi_it->ch_len;
@@ -870,17 +962,21 @@ bidi_resolve_explicit_1 (struct bidi_it *bidi_it)
870 override = bidi_it->level_stack[bidi_it->stack_idx].override; 962 override = bidi_it->level_stack[bidi_it->stack_idx].override;
871 new_level = current_level; 963 new_level = current_level;
872 964
873 /* in case it is a unibyte character (not yet implemented) */
874 /* _fetch_multibyte_char_len = 1; */
875 if (bidi_it->bytepos >= ZV_BYTE) 965 if (bidi_it->bytepos >= ZV_BYTE)
876 { 966 {
877 curchar = BIDI_EOB; 967 curchar = BIDI_EOB;
878 bidi_it->ch_len = 1; 968 bidi_it->ch_len = 1;
969 bidi_it->nchars = 1;
970 bidi_it->disp_pos = ZV;
879 } 971 }
880 else 972 else
881 { 973 {
882 curchar = FETCH_CHAR (bidi_it->bytepos); 974 /* Fetch the character at BYTEPOS. If it is covered by a
883 bidi_it->ch_len = CHAR_BYTES (curchar); 975 display string, treat the entire run of covered characters as
976 a single character u+FFFC. */
977 curchar = bidi_fetch_char (bidi_it->bytepos, bidi_it->charpos,
978 &bidi_it->disp_pos, bidi_it->frame_window_p,
979 &bidi_it->ch_len, &bidi_it->nchars);
884 } 980 }
885 bidi_it->ch = curchar; 981 bidi_it->ch = curchar;
886 982
@@ -1006,10 +1102,10 @@ bidi_resolve_explicit_1 (struct bidi_it *bidi_it)
1006} 1102}
1007 1103
1008/* Given an iterator state in BIDI_IT, advance one character position 1104/* Given an iterator state in BIDI_IT, advance one character position
1009 in the buffer to the next character (in the logical order), resolve 1105 in the buffer/string to the next character (in the logical order),
1010 any explicit embeddings and directional overrides, and return the 1106 resolve any explicit embeddings and directional overrides, and
1011 embedding level of the character after resolving explicit 1107 return the embedding level of the character after resolving
1012 directives and ignoring empty embeddings. */ 1108 explicit directives and ignoring empty embeddings. */
1013static int 1109static int
1014bidi_resolve_explicit (struct bidi_it *bidi_it) 1110bidi_resolve_explicit (struct bidi_it *bidi_it)
1015{ 1111{
@@ -1020,8 +1116,8 @@ bidi_resolve_explicit (struct bidi_it *bidi_it)
1020 && bidi_it->type == WEAK_BN 1116 && bidi_it->type == WEAK_BN
1021 && bidi_it->ignore_bn_limit == 0 /* only if not already known */ 1117 && bidi_it->ignore_bn_limit == 0 /* only if not already known */
1022 && bidi_it->bytepos < ZV_BYTE /* not already at EOB */ 1118 && bidi_it->bytepos < ZV_BYTE /* not already at EOB */
1023 && bidi_explicit_dir_char (FETCH_CHAR (bidi_it->bytepos 1119 && bidi_explicit_dir_char (FETCH_MULTIBYTE_CHAR (bidi_it->bytepos
1024 + bidi_it->ch_len))) 1120 + bidi_it->ch_len)))
1025 { 1121 {
1026 /* Avoid pushing and popping embedding levels if the level run 1122 /* Avoid pushing and popping embedding levels if the level run
1027 is empty, as this breaks level runs where it shouldn't. 1123 is empty, as this breaks level runs where it shouldn't.
@@ -1033,14 +1129,18 @@ bidi_resolve_explicit (struct bidi_it *bidi_it)
1033 1129
1034 bidi_copy_it (&saved_it, bidi_it); 1130 bidi_copy_it (&saved_it, bidi_it);
1035 1131
1036 while (bidi_explicit_dir_char (FETCH_CHAR (bidi_it->bytepos 1132 while (bidi_explicit_dir_char (FETCH_MULTIBYTE_CHAR (bidi_it->bytepos
1037 + bidi_it->ch_len))) 1133 + bidi_it->ch_len)))
1038 { 1134 {
1135 /* This advances to the next character, skipping any
1136 characters covered by display strings. */
1039 level = bidi_resolve_explicit_1 (bidi_it); 1137 level = bidi_resolve_explicit_1 (bidi_it);
1040 } 1138 }
1041 1139
1140 if (bidi_it->nchars <= 0)
1141 abort ();
1042 if (level == prev_level) /* empty embedding */ 1142 if (level == prev_level) /* empty embedding */
1043 saved_it.ignore_bn_limit = bidi_it->charpos + 1; 1143 saved_it.ignore_bn_limit = bidi_it->charpos + bidi_it->nchars;
1044 else /* this embedding is non-empty */ 1144 else /* this embedding is non-empty */
1045 saved_it.ignore_bn_limit = -1; 1145 saved_it.ignore_bn_limit = -1;
1046 1146
@@ -1076,8 +1176,8 @@ bidi_resolve_explicit (struct bidi_it *bidi_it)
1076 return new_level; 1176 return new_level;
1077} 1177}
1078 1178
1079/* Advance in the buffer, resolve weak types and return the type of 1179/* Advance in the buffer/string, resolve weak types and return the
1080 the next character after weak type resolution. */ 1180 type of the next character after weak type resolution. */
1081static bidi_type_t 1181static bidi_type_t
1082bidi_resolve_weak (struct bidi_it *bidi_it) 1182bidi_resolve_weak (struct bidi_it *bidi_it)
1083{ 1183{
@@ -1156,7 +1256,8 @@ bidi_resolve_weak (struct bidi_it *bidi_it)
1156 { 1256 {
1157 next_char = 1257 next_char =
1158 bidi_it->bytepos + bidi_it->ch_len >= ZV_BYTE 1258 bidi_it->bytepos + bidi_it->ch_len >= ZV_BYTE
1159 ? BIDI_EOB : FETCH_CHAR (bidi_it->bytepos + bidi_it->ch_len); 1259 ? BIDI_EOB : FETCH_MULTIBYTE_CHAR (bidi_it->bytepos
1260 + bidi_it->ch_len);
1160 type_of_next = bidi_get_type (next_char, override); 1261 type_of_next = bidi_get_type (next_char, override);
1161 1262
1162 if (type_of_next == WEAK_BN 1263 if (type_of_next == WEAK_BN
@@ -1204,11 +1305,14 @@ bidi_resolve_weak (struct bidi_it *bidi_it)
1204 type = WEAK_EN; 1305 type = WEAK_EN;
1205 else /* W5: ET/BN with EN after it. */ 1306 else /* W5: ET/BN with EN after it. */
1206 { 1307 {
1207 EMACS_INT en_pos = bidi_it->charpos + 1; 1308 EMACS_INT en_pos = bidi_it->charpos + bidi_it->nchars;
1208 1309
1310 if (bidi_it->nchars <= 0)
1311 abort ();
1209 next_char = 1312 next_char =
1210 bidi_it->bytepos + bidi_it->ch_len >= ZV_BYTE 1313 bidi_it->bytepos + bidi_it->ch_len >= ZV_BYTE
1211 ? BIDI_EOB : FETCH_CHAR (bidi_it->bytepos + bidi_it->ch_len); 1314 ? BIDI_EOB : FETCH_MULTIBYTE_CHAR (bidi_it->bytepos
1315 + bidi_it->ch_len);
1212 type_of_next = bidi_get_type (next_char, override); 1316 type_of_next = bidi_get_type (next_char, override);
1213 1317
1214 if (type_of_next == WEAK_ET 1318 if (type_of_next == WEAK_ET
@@ -1299,8 +1403,8 @@ bidi_resolve_neutral (struct bidi_it *bidi_it)
1299 /* Arrrgh!! The UAX#9 algorithm is too deeply entrenched in 1403 /* Arrrgh!! The UAX#9 algorithm is too deeply entrenched in
1300 the assumption of batch-style processing; see clauses W4, 1404 the assumption of batch-style processing; see clauses W4,
1301 W5, and especially N1, which require to look far forward 1405 W5, and especially N1, which require to look far forward
1302 (as well as back) in the buffer. May the fleas of a 1406 (as well as back) in the buffer/string. May the fleas of
1303 thousand camels infest the armpits of those who design 1407 a thousand camels infest the armpits of those who design
1304 supposedly general-purpose algorithms by looking at their 1408 supposedly general-purpose algorithms by looking at their
1305 own implementations, and fail to consider other possible 1409 own implementations, and fail to consider other possible
1306 implementations! */ 1410 implementations! */
@@ -1391,8 +1495,9 @@ bidi_resolve_neutral (struct bidi_it *bidi_it)
1391} 1495}
1392 1496
1393/* Given an iterator state in BIDI_IT, advance one character position 1497/* Given an iterator state in BIDI_IT, advance one character position
1394 in the buffer to the next character (in the logical order), resolve 1498 in the buffer/string to the next character (in the logical order),
1395 the bidi type of that next character, and return that type. */ 1499 resolve the bidi type of that next character, and return that
1500 type. */
1396static bidi_type_t 1501static bidi_type_t
1397bidi_type_of_next_char (struct bidi_it *bidi_it) 1502bidi_type_of_next_char (struct bidi_it *bidi_it)
1398{ 1503{
@@ -1416,15 +1521,16 @@ bidi_type_of_next_char (struct bidi_it *bidi_it)
1416} 1521}
1417 1522
1418/* Given an iterator state BIDI_IT, advance one character position in 1523/* Given an iterator state BIDI_IT, advance one character position in
1419 the buffer to the next character (in the logical order), resolve 1524 the buffer/string to the next character (in the current scan
1420 the embedding and implicit levels of that next character, and 1525 direction), resolve the embedding and implicit levels of that next
1421 return the resulting level. */ 1526 character, and return the resulting level. */
1422static int 1527static int
1423bidi_level_of_next_char (struct bidi_it *bidi_it) 1528bidi_level_of_next_char (struct bidi_it *bidi_it)
1424{ 1529{
1425 bidi_type_t type; 1530 bidi_type_t type;
1426 int level, prev_level = -1; 1531 int level, prev_level = -1;
1427 struct bidi_saved_info next_for_neutral; 1532 struct bidi_saved_info next_for_neutral;
1533 EMACS_INT next_char_pos;
1428 1534
1429 if (bidi_it->scan_dir == 1) 1535 if (bidi_it->scan_dir == 1)
1430 { 1536 {
@@ -1466,8 +1572,23 @@ bidi_level_of_next_char (struct bidi_it *bidi_it)
1466 } 1572 }
1467 next_for_neutral = bidi_it->next_for_neutral; 1573 next_for_neutral = bidi_it->next_for_neutral;
1468 1574
1469 /* Perhaps it is already cached. */ 1575 /* Perhaps the character we want is already cached. If it is, the
1470 type = bidi_cache_find (bidi_it->charpos + bidi_it->scan_dir, -1, bidi_it); 1576 call to bidi_cache_find below will return a type other than
1577 UNKNOWN_BT. */
1578 if (bidi_cache_idx && !bidi_it->first_elt)
1579 {
1580 if (bidi_it->scan_dir > 0)
1581 {
1582 if (bidi_it->nchars <= 0)
1583 abort ();
1584 next_char_pos = bidi_it->charpos + bidi_it->nchars;
1585 }
1586 else
1587 next_char_pos = bidi_it->charpos - 1;
1588 type = bidi_cache_find (next_char_pos, -1, bidi_it);
1589 }
1590 else
1591 type = UNKNOWN_BT;
1471 if (type != UNKNOWN_BT) 1592 if (type != UNKNOWN_BT)
1472 { 1593 {
1473 /* Don't lose the information for resolving neutrals! The 1594 /* Don't lose the information for resolving neutrals! The
@@ -1529,14 +1650,16 @@ bidi_level_of_next_char (struct bidi_it *bidi_it)
1529 int clen = bidi_it->ch_len; 1650 int clen = bidi_it->ch_len;
1530 EMACS_INT bpos = bidi_it->bytepos; 1651 EMACS_INT bpos = bidi_it->bytepos;
1531 EMACS_INT cpos = bidi_it->charpos; 1652 EMACS_INT cpos = bidi_it->charpos;
1653 EMACS_INT disp_pos = bidi_it->disp_pos;
1654 EMACS_INT nc = bidi_it->nchars;
1532 bidi_type_t chtype; 1655 bidi_type_t chtype;
1656 int fwp = bidi_it->frame_window_p;
1533 1657
1658 if (bidi_it->nchars <= 0)
1659 abort ();
1534 do { 1660 do {
1535 /*_fetch_multibyte_char_len = 1;*/ 1661 ch = bidi_fetch_char (bpos += clen, cpos += nc, &disp_pos, fwp,
1536 ch = bpos + clen >= ZV_BYTE ? BIDI_EOB : FETCH_CHAR (bpos + clen); 1662 &clen, &nc);
1537 bpos += clen;
1538 cpos++;
1539 clen = (ch == BIDI_EOB ? 1 : CHAR_BYTES (ch));
1540 if (ch == '\n' || ch == BIDI_EOB /* || ch == LINESEP_CHAR */) 1663 if (ch == '\n' || ch == BIDI_EOB /* || ch == LINESEP_CHAR */)
1541 chtype = NEUTRAL_B; 1664 chtype = NEUTRAL_B;
1542 else 1665 else
@@ -1615,8 +1738,8 @@ bidi_level_of_next_char (struct bidi_it *bidi_it)
1615 1738
1616 If this level's other edge is cached, we simply jump to it, filling 1739 If this level's other edge is cached, we simply jump to it, filling
1617 the iterator structure with the iterator state on the other edge. 1740 the iterator structure with the iterator state on the other edge.
1618 Otherwise, we walk the buffer until we come back to the same level 1741 Otherwise, we walk the buffer or string until we come back to the
1619 as LEVEL. 1742 same level as LEVEL.
1620 1743
1621 Note: we are not talking here about a ``level run'' in the UAX#9 1744 Note: we are not talking here about a ``level run'' in the UAX#9
1622 sense of the term, but rather about a ``level'' which includes 1745 sense of the term, but rather about a ``level'' which includes
@@ -1680,6 +1803,7 @@ bidi_move_to_visually_next (struct bidi_it *bidi_it)
1680 sentinel.bytepos--; 1803 sentinel.bytepos--;
1681 sentinel.ch = '\n'; /* doesn't matter, but why not? */ 1804 sentinel.ch = '\n'; /* doesn't matter, but why not? */
1682 sentinel.ch_len = 1; 1805 sentinel.ch_len = 1;
1806 sentinel.nchars = 1;
1683 } 1807 }
1684 bidi_cache_iterator_state (&sentinel, 1); 1808 bidi_cache_iterator_state (&sentinel, 1);
1685 } 1809 }
@@ -1750,14 +1874,17 @@ bidi_move_to_visually_next (struct bidi_it *bidi_it)
1750 && bidi_it->bytepos < ZV_BYTE) 1874 && bidi_it->bytepos < ZV_BYTE)
1751 { 1875 {
1752 EMACS_INT sep_len = 1876 EMACS_INT sep_len =
1753 bidi_at_paragraph_end (bidi_it->charpos + 1, 1877 bidi_at_paragraph_end (bidi_it->charpos + bidi_it->nchars,
1754 bidi_it->bytepos + bidi_it->ch_len); 1878 bidi_it->bytepos + bidi_it->ch_len);
1879 if (bidi_it->nchars <= 0)
1880 abort ();
1755 if (sep_len >= 0) 1881 if (sep_len >= 0)
1756 { 1882 {
1757 bidi_it->new_paragraph = 1; 1883 bidi_it->new_paragraph = 1;
1758 /* Record the buffer position of the last character of the 1884 /* Record the buffer position of the last character of the
1759 paragraph separator. */ 1885 paragraph separator. */
1760 bidi_it->separator_limit = bidi_it->charpos + 1 + sep_len; 1886 bidi_it->separator_limit =
1887 bidi_it->charpos + bidi_it->nchars + sep_len;
1761 } 1888 }
1762 } 1889 }
1763 1890
@@ -1767,7 +1894,8 @@ bidi_move_to_visually_next (struct bidi_it *bidi_it)
1767 last cached position, the cache's job is done and we can 1894 last cached position, the cache's job is done and we can
1768 discard it. */ 1895 discard it. */
1769 if (bidi_it->resolved_level == bidi_it->level_stack[0].level 1896 if (bidi_it->resolved_level == bidi_it->level_stack[0].level
1770 && bidi_it->charpos > bidi_cache[bidi_cache_idx - 1].charpos) 1897 && bidi_it->charpos > (bidi_cache[bidi_cache_idx - 1].charpos
1898 + bidi_cache[bidi_cache_idx - 1].nchars - 1))
1771 bidi_cache_reset (); 1899 bidi_cache_reset ();
1772 /* But as long as we are caching during forward scan, we must 1900 /* But as long as we are caching during forward scan, we must
1773 cache each state, or else the cache integrity will be 1901 cache each state, or else the cache integrity will be
diff --git a/src/dispextern.h b/src/dispextern.h
index e612a8b1eba..15e44e0286e 100644
--- a/src/dispextern.h
+++ b/src/dispextern.h
@@ -1816,12 +1816,16 @@ struct bidi_stack {
1816 bidi_dir_t override; 1816 bidi_dir_t override;
1817}; 1817};
1818 1818
1819/* Data type for iterating over bidi text. */ 1819/* Data type for reordering bidirectional text. */
1820struct bidi_it { 1820struct bidi_it {
1821 EMACS_INT bytepos; /* iterator's position in buffer */ 1821 EMACS_INT bytepos; /* iterator's position in buffer */
1822 EMACS_INT charpos; 1822 EMACS_INT charpos;
1823 int ch; /* character itself */ 1823 int ch; /* character at that position, or u+FFFC
1824 int ch_len; /* length of its multibyte sequence */ 1824 ("object replacement character") for a run
1825 of characters covered by a display string */
1826 EMACS_INT nchars; /* its "length", usually 1; it's > 1 for a run
1827 of characters covered by a display string */
1828 EMACS_INT ch_len; /* its length in bytes */
1825 bidi_type_t type; /* bidi type of this character, after 1829 bidi_type_t type; /* bidi type of this character, after
1826 resolving weak and neutral types */ 1830 resolving weak and neutral types */
1827 bidi_type_t type_after_w1; /* original type, after overrides and W1 */ 1831 bidi_type_t type_after_w1; /* original type, after overrides and W1 */
@@ -1847,7 +1851,9 @@ struct bidi_it {
1847 int first_elt; /* if non-zero, examine current char first */ 1851 int first_elt; /* if non-zero, examine current char first */
1848 bidi_dir_t paragraph_dir; /* current paragraph direction */ 1852 bidi_dir_t paragraph_dir; /* current paragraph direction */
1849 int new_paragraph; /* if non-zero, we expect a new paragraph */ 1853 int new_paragraph; /* if non-zero, we expect a new paragraph */
1854 int frame_window_p; /* non-zero if displaying on a GUI frame */
1850 EMACS_INT separator_limit; /* where paragraph separator should end */ 1855 EMACS_INT separator_limit; /* where paragraph separator should end */
1856 EMACS_INT disp_pos; /* position of display string after ch */
1851}; 1857};
1852 1858
1853/* Value is non-zero when the bidi iterator is at base paragraph 1859/* Value is non-zero when the bidi iterator is at base paragraph
@@ -2944,7 +2950,7 @@ enum tool_bar_item_image
2944 2950
2945/* Defined in bidi.c */ 2951/* Defined in bidi.c */
2946 2952
2947extern void bidi_init_it (EMACS_INT, EMACS_INT, struct bidi_it *); 2953extern void bidi_init_it (EMACS_INT, EMACS_INT, int, struct bidi_it *);
2948extern void bidi_move_to_visually_next (struct bidi_it *); 2954extern void bidi_move_to_visually_next (struct bidi_it *);
2949extern void bidi_paragraph_init (bidi_dir_t, struct bidi_it *, int); 2955extern void bidi_paragraph_init (bidi_dir_t, struct bidi_it *, int);
2950extern int bidi_mirror_char (int); 2956extern int bidi_mirror_char (int);
@@ -2955,7 +2961,7 @@ struct glyph_row *row_containing_pos (struct window *, EMACS_INT,
2955 struct glyph_row *, 2961 struct glyph_row *,
2956 struct glyph_row *, int); 2962 struct glyph_row *, int);
2957int line_bottom_y (struct it *); 2963int line_bottom_y (struct it *);
2958int display_prop_intangible_p (Lisp_Object); 2964int display_prop_intangible_p (Lisp_Object, Lisp_Object, EMACS_INT, EMACS_INT);
2959void resize_echo_area_exactly (void); 2965void resize_echo_area_exactly (void);
2960int resize_mini_window (struct window *, int); 2966int resize_mini_window (struct window *, int);
2961#if defined USE_TOOLKIT_SCROLL_BARS && !defined USE_GTK 2967#if defined USE_TOOLKIT_SCROLL_BARS && !defined USE_GTK
@@ -3005,6 +3011,8 @@ extern void reseat_at_previous_visible_line_start (struct it *);
3005extern Lisp_Object lookup_glyphless_char_display (int, struct it *); 3011extern Lisp_Object lookup_glyphless_char_display (int, struct it *);
3006extern int calc_pixel_width_or_height (double *, struct it *, Lisp_Object, 3012extern int calc_pixel_width_or_height (double *, struct it *, Lisp_Object,
3007 struct font *, int, int *); 3013 struct font *, int, int *);
3014extern EMACS_INT compute_display_string_pos (EMACS_INT, int);
3015extern EMACS_INT compute_display_string_end (EMACS_INT);
3008 3016
3009#ifdef HAVE_WINDOW_SYSTEM 3017#ifdef HAVE_WINDOW_SYSTEM
3010 3018
diff --git a/src/keyboard.c b/src/keyboard.c
index 7bc406aab31..6eb3773af99 100644
--- a/src/keyboard.c
+++ b/src/keyboard.c
@@ -1729,7 +1729,7 @@ adjust_point_for_property (EMACS_INT last_pt, int modified)
1729 && PT > BEGV && PT < ZV 1729 && PT > BEGV && PT < ZV
1730 && !NILP (val = get_char_property_and_overlay 1730 && !NILP (val = get_char_property_and_overlay
1731 (make_number (PT), Qdisplay, Qnil, &overlay)) 1731 (make_number (PT), Qdisplay, Qnil, &overlay))
1732 && display_prop_intangible_p (val) 1732 && display_prop_intangible_p (val, overlay, PT, PT_BYTE)
1733 && (!OVERLAYP (overlay) 1733 && (!OVERLAYP (overlay)
1734 ? get_property_and_range (PT, Qdisplay, &val, &beg, &end, Qnil) 1734 ? get_property_and_range (PT, Qdisplay, &val, &beg, &end, Qnil)
1735 : (beg = OVERLAY_POSITION (OVERLAY_START (overlay)), 1735 : (beg = OVERLAY_POSITION (OVERLAY_START (overlay)),
diff --git a/src/xdisp.c b/src/xdisp.c
index d67cc63be79..958e7510e1d 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -812,7 +812,7 @@ static int try_scrolling (Lisp_Object, int, EMACS_INT, EMACS_INT, int, int);
812static int try_cursor_movement (Lisp_Object, struct text_pos, int *); 812static int try_cursor_movement (Lisp_Object, struct text_pos, int *);
813static int trailing_whitespace_p (EMACS_INT); 813static int trailing_whitespace_p (EMACS_INT);
814static unsigned long int message_log_check_duplicate (EMACS_INT, EMACS_INT); 814static unsigned long int message_log_check_duplicate (EMACS_INT, EMACS_INT);
815static void push_it (struct it *); 815static void push_it (struct it *, struct text_pos *);
816static void pop_it (struct it *); 816static void pop_it (struct it *);
817static void sync_frame_with_window_matrix_rows (struct window *); 817static void sync_frame_with_window_matrix_rows (struct window *);
818static void select_frame_for_redisplay (Lisp_Object); 818static void select_frame_for_redisplay (Lisp_Object);
@@ -884,9 +884,11 @@ static void compute_string_pos (struct text_pos *, struct text_pos,
884 Lisp_Object); 884 Lisp_Object);
885static int face_before_or_after_it_pos (struct it *, int); 885static int face_before_or_after_it_pos (struct it *, int);
886static EMACS_INT next_overlay_change (EMACS_INT); 886static EMACS_INT next_overlay_change (EMACS_INT);
887static int handle_display_spec (struct it *, Lisp_Object, Lisp_Object,
888 Lisp_Object, struct text_pos *, EMACS_INT, int);
887static int handle_single_display_spec (struct it *, Lisp_Object, 889static int handle_single_display_spec (struct it *, Lisp_Object,
888 Lisp_Object, Lisp_Object, 890 Lisp_Object, Lisp_Object,
889 struct text_pos *, int); 891 struct text_pos *, EMACS_INT, int, int);
890static int underlying_face_id (struct it *); 892static int underlying_face_id (struct it *);
891static int in_ellipses_for_invisible_text_p (struct display_pos *, 893static int in_ellipses_for_invisible_text_p (struct display_pos *,
892 struct window *); 894 struct window *);
@@ -2564,7 +2566,7 @@ init_iterator (struct it *it, struct window *w,
2564 it->paragraph_embedding = R2L; 2566 it->paragraph_embedding = R2L;
2565 else 2567 else
2566 it->paragraph_embedding = NEUTRAL_DIR; 2568 it->paragraph_embedding = NEUTRAL_DIR;
2567 bidi_init_it (charpos, bytepos, &it->bidi_it); 2569 bidi_init_it (charpos, bytepos, FRAME_WINDOW_P (it->f), &it->bidi_it);
2568 } 2570 }
2569 2571
2570 /* If a buffer position was specified, set the iterator there, 2572 /* If a buffer position was specified, set the iterator there,
@@ -3085,6 +3087,82 @@ next_overlay_change (EMACS_INT pos)
3085 return endpos; 3087 return endpos;
3086} 3088}
3087 3089
3090/* Return the character position of a display string at or after CHARPOS.
3091 If no display string exists at or after CHARPOS, return ZV. A
3092 display string is either an overlay with `display' property whose
3093 value is a string, or a `display' text property whose value is a
3094 string. FRAME_WINDOW_P is non-zero when we are displaying a window
3095 on a GUI frame. */
3096EMACS_INT
3097compute_display_string_pos (EMACS_INT charpos, int frame_window_p)
3098{
3099 /* FIXME: Support display properties on strings (object = Qnil means
3100 current buffer). */
3101 Lisp_Object object = Qnil;
3102 Lisp_Object pos, spec;
3103 struct text_pos position;
3104 EMACS_INT bufpos;
3105
3106 if (charpos >= ZV)
3107 return ZV;
3108
3109 /* If the character at CHARPOS is where the display string begins,
3110 return CHARPOS. */
3111 pos = make_number (charpos);
3112 CHARPOS (position) = charpos;
3113 BYTEPOS (position) = CHAR_TO_BYTE (charpos);
3114 bufpos = charpos; /* FIXME! support strings as well */
3115 if (!NILP (spec = Fget_char_property (pos, Qdisplay, object))
3116 && (charpos <= BEGV
3117 || !EQ (Fget_char_property (make_number (charpos - 1), Qdisplay,
3118 object),
3119 spec))
3120 && handle_display_spec (NULL, spec, object, Qnil, &position, bufpos,
3121 frame_window_p))
3122 return charpos;
3123
3124 /* Look forward for the first character with a `display' property
3125 that will replace the underlying text when displayed. */
3126 do {
3127 pos = Fnext_single_char_property_change (pos, Qdisplay, object, Qnil);
3128 CHARPOS (position) = XFASTINT (pos);
3129 BYTEPOS (position) = CHAR_TO_BYTE (CHARPOS (position));
3130 if (CHARPOS (position) >= ZV)
3131 break;
3132 spec = Fget_char_property (pos, Qdisplay, object);
3133 bufpos = CHARPOS (position); /* FIXME! support strings as well */
3134 } while (NILP (spec)
3135 || !handle_display_spec (NULL, spec, object, Qnil, &position, bufpos,
3136 frame_window_p));
3137
3138 return CHARPOS (position);
3139}
3140
3141/* Return the character position of the end of the display string that
3142 started at CHARPOS. A display string is either an overlay with
3143 `display' property whose value is a string or a `display' text
3144 property whose value is a string. */
3145EMACS_INT
3146compute_display_string_end (EMACS_INT charpos)
3147{
3148 /* FIXME: Support display properties on strings (object = Qnil means
3149 current buffer). */
3150 Lisp_Object object = Qnil;
3151 Lisp_Object pos = make_number (charpos);
3152
3153 if (charpos >= ZV)
3154 return ZV;
3155
3156 if (NILP (Fget_char_property (pos, Qdisplay, object)))
3157 abort ();
3158
3159 /* Look forward for the first character where the `display' property
3160 changes. */
3161 pos = Fnext_single_char_property_change (pos, Qdisplay, object, Qnil);
3162
3163 return XFASTINT (pos);
3164}
3165
3088 3166
3089 3167
3090/*********************************************************************** 3168/***********************************************************************
@@ -3743,8 +3821,9 @@ setup_for_ellipsis (struct it *it, int len)
3743static enum prop_handled 3821static enum prop_handled
3744handle_display_prop (struct it *it) 3822handle_display_prop (struct it *it)
3745{ 3823{
3746 Lisp_Object prop, object, overlay; 3824 Lisp_Object propval, object, overlay;
3747 struct text_pos *position; 3825 struct text_pos *position;
3826 EMACS_INT bufpos;
3748 /* Nonzero if some property replaces the display of the text itself. */ 3827 /* Nonzero if some property replaces the display of the text itself. */
3749 int display_replaced_p = 0; 3828 int display_replaced_p = 0;
3750 3829
@@ -3752,11 +3831,13 @@ handle_display_prop (struct it *it)
3752 { 3831 {
3753 object = it->string; 3832 object = it->string;
3754 position = &it->current.string_pos; 3833 position = &it->current.string_pos;
3834 bufpos = CHARPOS (it->current.pos);
3755 } 3835 }
3756 else 3836 else
3757 { 3837 {
3758 XSETWINDOW (object, it->w); 3838 XSETWINDOW (object, it->w);
3759 position = &it->current.pos; 3839 position = &it->current.pos;
3840 bufpos = CHARPOS (*position);
3760 } 3841 }
3761 3842
3762 /* Reset those iterator values set from display property values. */ 3843 /* Reset those iterator values set from display property values. */
@@ -3771,9 +3852,9 @@ handle_display_prop (struct it *it)
3771 if (!it->string_from_display_prop_p) 3852 if (!it->string_from_display_prop_p)
3772 it->area = TEXT_AREA; 3853 it->area = TEXT_AREA;
3773 3854
3774 prop = get_char_property_and_overlay (make_number (position->charpos), 3855 propval = get_char_property_and_overlay (make_number (position->charpos),
3775 Qdisplay, object, &overlay); 3856 Qdisplay, object, &overlay);
3776 if (NILP (prop)) 3857 if (NILP (propval))
3777 return HANDLED_NORMALLY; 3858 return HANDLED_NORMALLY;
3778 /* Now OVERLAY is the overlay that gave us this property, or nil 3859 /* Now OVERLAY is the overlay that gave us this property, or nil
3779 if it was a text property. */ 3860 if it was a text property. */
@@ -3781,59 +3862,88 @@ handle_display_prop (struct it *it)
3781 if (!STRINGP (it->string)) 3862 if (!STRINGP (it->string))
3782 object = it->w->buffer; 3863 object = it->w->buffer;
3783 3864
3784 if (CONSP (prop) 3865 display_replaced_p = handle_display_spec (it, propval, object, overlay,
3785 /* Simple properties. */ 3866 position, bufpos,
3786 && !EQ (XCAR (prop), Qimage) 3867 FRAME_WINDOW_P (it->f));
3787 && !EQ (XCAR (prop), Qspace) 3868
3788 && !EQ (XCAR (prop), Qwhen) 3869 return display_replaced_p ? HANDLED_RETURN : HANDLED_NORMALLY;
3789 && !EQ (XCAR (prop), Qslice) 3870}
3790 && !EQ (XCAR (prop), Qspace_width) 3871
3791 && !EQ (XCAR (prop), Qheight) 3872/* Subroutine of handle_display_prop. Returns non-zero if the display
3792 && !EQ (XCAR (prop), Qraise) 3873 specification in SPEC is a replacing specification, i.e. it would
3874 replace the text covered by `display' property with something else,
3875 such as an image or a display string.
3876
3877 See handle_single_display_spec for documentation of arguments.
3878 frame_window_p is non-zero if the window being redisplayed is on a
3879 GUI frame; this argument is used only if IT is NULL, see below.
3880
3881 IT can be NULL, if this is called by the bidi reordering code
3882 through compute_display_string_pos, which see. In that case, this
3883 function only examines SPEC, but does not otherwise "handle" it, in
3884 the sense that it doesn't set up members of IT from the display
3885 spec. */
3886static int
3887handle_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object,
3888 Lisp_Object overlay, struct text_pos *position,
3889 EMACS_INT bufpos, int frame_window_p)
3890{
3891 int replacing_p = 0;
3892
3893 if (CONSP (spec)
3894 /* Simple specerties. */
3895 && !EQ (XCAR (spec), Qimage)
3896 && !EQ (XCAR (spec), Qspace)
3897 && !EQ (XCAR (spec), Qwhen)
3898 && !EQ (XCAR (spec), Qslice)
3899 && !EQ (XCAR (spec), Qspace_width)
3900 && !EQ (XCAR (spec), Qheight)
3901 && !EQ (XCAR (spec), Qraise)
3793 /* Marginal area specifications. */ 3902 /* Marginal area specifications. */
3794 && !(CONSP (XCAR (prop)) && EQ (XCAR (XCAR (prop)), Qmargin)) 3903 && !(CONSP (XCAR (spec)) && EQ (XCAR (XCAR (spec)), Qmargin))
3795 && !EQ (XCAR (prop), Qleft_fringe) 3904 && !EQ (XCAR (spec), Qleft_fringe)
3796 && !EQ (XCAR (prop), Qright_fringe) 3905 && !EQ (XCAR (spec), Qright_fringe)
3797 && !NILP (XCAR (prop))) 3906 && !NILP (XCAR (spec)))
3798 { 3907 {
3799 for (; CONSP (prop); prop = XCDR (prop)) 3908 for (; CONSP (spec); spec = XCDR (spec))
3800 { 3909 {
3801 if (handle_single_display_spec (it, XCAR (prop), object, overlay, 3910 if (handle_single_display_spec (it, XCAR (spec), object, overlay,
3802 position, display_replaced_p)) 3911 position, bufpos, replacing_p,
3912 frame_window_p))
3803 { 3913 {
3804 display_replaced_p = 1; 3914 replacing_p = 1;
3805 /* If some text in a string is replaced, `position' no 3915 /* If some text in a string is replaced, `position' no
3806 longer points to the position of `object'. */ 3916 longer points to the position of `object'. */
3807 if (STRINGP (object)) 3917 if (!it || STRINGP (object))
3808 break; 3918 break;
3809 } 3919 }
3810 } 3920 }
3811 } 3921 }
3812 else if (VECTORP (prop)) 3922 else if (VECTORP (spec))
3813 { 3923 {
3814 int i; 3924 int i;
3815 for (i = 0; i < ASIZE (prop); ++i) 3925 for (i = 0; i < ASIZE (spec); ++i)
3816 if (handle_single_display_spec (it, AREF (prop, i), object, overlay, 3926 if (handle_single_display_spec (it, AREF (spec, i), object, overlay,
3817 position, display_replaced_p)) 3927 position, bufpos, replacing_p,
3928 frame_window_p))
3818 { 3929 {
3819 display_replaced_p = 1; 3930 replacing_p = 1;
3820 /* If some text in a string is replaced, `position' no 3931 /* If some text in a string is replaced, `position' no
3821 longer points to the position of `object'. */ 3932 longer points to the position of `object'. */
3822 if (STRINGP (object)) 3933 if (!it || STRINGP (object))
3823 break; 3934 break;
3824 } 3935 }
3825 } 3936 }
3826 else 3937 else
3827 { 3938 {
3828 if (handle_single_display_spec (it, prop, object, overlay, 3939 if (handle_single_display_spec (it, spec, object, overlay,
3829 position, 0)) 3940 position, bufpos, 0, frame_window_p))
3830 display_replaced_p = 1; 3941 replacing_p = 1;
3831 } 3942 }
3832 3943
3833 return display_replaced_p ? HANDLED_RETURN : HANDLED_NORMALLY; 3944 return replacing_p;
3834} 3945}
3835 3946
3836
3837/* Value is the position of the end of the `display' property starting 3947/* Value is the position of the end of the `display' property starting
3838 at START_POS in OBJECT. */ 3948 at START_POS in OBJECT. */
3839 3949
@@ -3857,10 +3967,12 @@ display_prop_end (struct it *it, Lisp_Object object, struct text_pos start_pos)
3857 3967
3858/* Set up IT from a single `display' property specification SPEC. OBJECT 3968/* Set up IT from a single `display' property specification SPEC. OBJECT
3859 is the object in which the `display' property was found. *POSITION 3969 is the object in which the `display' property was found. *POSITION
3860 is the position at which it was found. DISPLAY_REPLACED_P non-zero 3970 is the position in OBJECT at which the `display' property was found.
3861 means that we previously saw a display specification which already 3971 BUFPOS is the buffer position of OBJECT (different from POSITION if
3862 replaced text display with something else, for example an image; 3972 OBJECT is not a buffer). DISPLAY_REPLACED_P non-zero means that we
3863 we ignore such properties after the first one has been processed. 3973 previously saw a display specification which already replaced text
3974 display with something else, for example an image; we ignore such
3975 properties after the first one has been processed.
3864 3976
3865 OVERLAY is the overlay this `display' property came from, 3977 OVERLAY is the overlay this `display' property came from,
3866 or nil if it was a text property. 3978 or nil if it was a text property.
@@ -3869,17 +3981,22 @@ display_prop_end (struct it *it, Lisp_Object object, struct text_pos start_pos)
3869 cases too, set *POSITION to the position where the `display' 3981 cases too, set *POSITION to the position where the `display'
3870 property ends. 3982 property ends.
3871 3983
3984 If IT is NULL, only examine the property specification in SPEC, but
3985 don't set up IT. In that case, FRAME_WINDOW_P non-zero means SPEC
3986 is intended to be displayed in a window on a GUI frame.
3987
3872 Value is non-zero if something was found which replaces the display 3988 Value is non-zero if something was found which replaces the display
3873 of buffer or string text. */ 3989 of buffer or string text. */
3874 3990
3875static int 3991static int
3876handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object, 3992handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object,
3877 Lisp_Object overlay, struct text_pos *position, 3993 Lisp_Object overlay, struct text_pos *position,
3878 int display_replaced_p) 3994 EMACS_INT bufpos, int display_replaced_p,
3995 int frame_window_p)
3879{ 3996{
3880 Lisp_Object form; 3997 Lisp_Object form;
3881 Lisp_Object location, value; 3998 Lisp_Object location, value;
3882 struct text_pos start_pos, save_pos; 3999 struct text_pos start_pos = *position;
3883 int valid_p; 4000 int valid_p;
3884 4001
3885 /* If SPEC is a list of the form `(when FORM . VALUE)', evaluate FORM. 4002 /* If SPEC is a list of the form `(when FORM . VALUE)', evaluate FORM.
@@ -3903,11 +4020,12 @@ handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object,
3903 buffer or string. Bind `position' to the position in the 4020 buffer or string. Bind `position' to the position in the
3904 object where the property was found, and `buffer-position' 4021 object where the property was found, and `buffer-position'
3905 to the current position in the buffer. */ 4022 to the current position in the buffer. */
4023
4024 if (NILP (object))
4025 XSETBUFFER (object, current_buffer);
3906 specbind (Qobject, object); 4026 specbind (Qobject, object);
3907 specbind (Qposition, make_number (CHARPOS (*position))); 4027 specbind (Qposition, make_number (CHARPOS (*position)));
3908 specbind (Qbuffer_position, 4028 specbind (Qbuffer_position, make_number (bufpos));
3909 make_number (STRINGP (object)
3910 ? IT_CHARPOS (*it) : CHARPOS (*position)));
3911 GCPRO1 (form); 4029 GCPRO1 (form);
3912 form = safe_eval (form); 4030 form = safe_eval (form);
3913 UNGCPRO; 4031 UNGCPRO;
@@ -3922,63 +4040,66 @@ handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object,
3922 && EQ (XCAR (spec), Qheight) 4040 && EQ (XCAR (spec), Qheight)
3923 && CONSP (XCDR (spec))) 4041 && CONSP (XCDR (spec)))
3924 { 4042 {
3925 if (!FRAME_WINDOW_P (it->f)) 4043 if (it)
3926 return 0;
3927
3928 it->font_height = XCAR (XCDR (spec));
3929 if (!NILP (it->font_height))
3930 { 4044 {
3931 struct face *face = FACE_FROM_ID (it->f, it->face_id); 4045 if (!FRAME_WINDOW_P (it->f))
3932 int new_height = -1; 4046 return 0;
3933 4047
3934 if (CONSP (it->font_height) 4048 it->font_height = XCAR (XCDR (spec));
3935 && (EQ (XCAR (it->font_height), Qplus) 4049 if (!NILP (it->font_height))
3936 || EQ (XCAR (it->font_height), Qminus))
3937 && CONSP (XCDR (it->font_height))
3938 && INTEGERP (XCAR (XCDR (it->font_height))))
3939 { 4050 {
3940 /* `(+ N)' or `(- N)' where N is an integer. */ 4051 struct face *face = FACE_FROM_ID (it->f, it->face_id);
3941 int steps = XINT (XCAR (XCDR (it->font_height))); 4052 int new_height = -1;
3942 if (EQ (XCAR (it->font_height), Qplus)) 4053
3943 steps = - steps; 4054 if (CONSP (it->font_height)
3944 it->face_id = smaller_face (it->f, it->face_id, steps); 4055 && (EQ (XCAR (it->font_height), Qplus)
3945 } 4056 || EQ (XCAR (it->font_height), Qminus))
3946 else if (FUNCTIONP (it->font_height)) 4057 && CONSP (XCDR (it->font_height))
3947 { 4058 && INTEGERP (XCAR (XCDR (it->font_height))))
3948 /* Call function with current height as argument. 4059 {
3949 Value is the new height. */ 4060 /* `(+ N)' or `(- N)' where N is an integer. */
3950 Lisp_Object height; 4061 int steps = XINT (XCAR (XCDR (it->font_height)));
3951 height = safe_call1 (it->font_height, 4062 if (EQ (XCAR (it->font_height), Qplus))
3952 face->lface[LFACE_HEIGHT_INDEX]); 4063 steps = - steps;
3953 if (NUMBERP (height)) 4064 it->face_id = smaller_face (it->f, it->face_id, steps);
3954 new_height = XFLOATINT (height); 4065 }
3955 } 4066 else if (FUNCTIONP (it->font_height))
3956 else if (NUMBERP (it->font_height)) 4067 {
3957 { 4068 /* Call function with current height as argument.
3958 /* Value is a multiple of the canonical char height. */ 4069 Value is the new height. */
3959 struct face *f; 4070 Lisp_Object height;
4071 height = safe_call1 (it->font_height,
4072 face->lface[LFACE_HEIGHT_INDEX]);
4073 if (NUMBERP (height))
4074 new_height = XFLOATINT (height);
4075 }
4076 else if (NUMBERP (it->font_height))
4077 {
4078 /* Value is a multiple of the canonical char height. */
4079 struct face *f;
3960 4080
3961 f = FACE_FROM_ID (it->f, 4081 f = FACE_FROM_ID (it->f,
3962 lookup_basic_face (it->f, DEFAULT_FACE_ID)); 4082 lookup_basic_face (it->f, DEFAULT_FACE_ID));
3963 new_height = (XFLOATINT (it->font_height) 4083 new_height = (XFLOATINT (it->font_height)
3964 * XINT (f->lface[LFACE_HEIGHT_INDEX])); 4084 * XINT (f->lface[LFACE_HEIGHT_INDEX]));
3965 } 4085 }
3966 else 4086 else
3967 { 4087 {
3968 /* Evaluate IT->font_height with `height' bound to the 4088 /* Evaluate IT->font_height with `height' bound to the
3969 current specified height to get the new height. */ 4089 current specified height to get the new height. */
3970 int count = SPECPDL_INDEX (); 4090 int count = SPECPDL_INDEX ();
3971 4091
3972 specbind (Qheight, face->lface[LFACE_HEIGHT_INDEX]); 4092 specbind (Qheight, face->lface[LFACE_HEIGHT_INDEX]);
3973 value = safe_eval (it->font_height); 4093 value = safe_eval (it->font_height);
3974 unbind_to (count, Qnil); 4094 unbind_to (count, Qnil);
3975 4095
3976 if (NUMBERP (value)) 4096 if (NUMBERP (value))
3977 new_height = XFLOATINT (value); 4097 new_height = XFLOATINT (value);
3978 } 4098 }
3979 4099
3980 if (new_height > 0) 4100 if (new_height > 0)
3981 it->face_id = face_with_height (it->f, it->face_id, new_height); 4101 it->face_id = face_with_height (it->f, it->face_id, new_height);
4102 }
3982 } 4103 }
3983 4104
3984 return 0; 4105 return 0;
@@ -3989,12 +4110,15 @@ handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object,
3989 && EQ (XCAR (spec), Qspace_width) 4110 && EQ (XCAR (spec), Qspace_width)
3990 && CONSP (XCDR (spec))) 4111 && CONSP (XCDR (spec)))
3991 { 4112 {
3992 if (!FRAME_WINDOW_P (it->f)) 4113 if (it)
3993 return 0; 4114 {
4115 if (!FRAME_WINDOW_P (it->f))
4116 return 0;
3994 4117
3995 value = XCAR (XCDR (spec)); 4118 value = XCAR (XCDR (spec));
3996 if (NUMBERP (value) && XFLOATINT (value) > 0) 4119 if (NUMBERP (value) && XFLOATINT (value) > 0)
3997 it->space_width = value; 4120 it->space_width = value;
4121 }
3998 4122
3999 return 0; 4123 return 0;
4000 } 4124 }
@@ -4005,20 +4129,23 @@ handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object,
4005 { 4129 {
4006 Lisp_Object tem; 4130 Lisp_Object tem;
4007 4131
4008 if (!FRAME_WINDOW_P (it->f)) 4132 if (it)
4009 return 0;
4010
4011 if (tem = XCDR (spec), CONSP (tem))
4012 { 4133 {
4013 it->slice.x = XCAR (tem); 4134 if (!FRAME_WINDOW_P (it->f))
4014 if (tem = XCDR (tem), CONSP (tem)) 4135 return 0;
4136
4137 if (tem = XCDR (spec), CONSP (tem))
4015 { 4138 {
4016 it->slice.y = XCAR (tem); 4139 it->slice.x = XCAR (tem);
4017 if (tem = XCDR (tem), CONSP (tem)) 4140 if (tem = XCDR (tem), CONSP (tem))
4018 { 4141 {
4019 it->slice.width = XCAR (tem); 4142 it->slice.y = XCAR (tem);
4020 if (tem = XCDR (tem), CONSP (tem)) 4143 if (tem = XCDR (tem), CONSP (tem))
4021 it->slice.height = XCAR (tem); 4144 {
4145 it->slice.width = XCAR (tem);
4146 if (tem = XCDR (tem), CONSP (tem))
4147 it->slice.height = XCAR (tem);
4148 }
4022 } 4149 }
4023 } 4150 }
4024 } 4151 }
@@ -4031,36 +4158,43 @@ handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object,
4031 && EQ (XCAR (spec), Qraise) 4158 && EQ (XCAR (spec), Qraise)
4032 && CONSP (XCDR (spec))) 4159 && CONSP (XCDR (spec)))
4033 { 4160 {
4034 if (!FRAME_WINDOW_P (it->f)) 4161 if (it)
4035 return 0; 4162 {
4163 if (!FRAME_WINDOW_P (it->f))
4164 return 0;
4036 4165
4037#ifdef HAVE_WINDOW_SYSTEM 4166#ifdef HAVE_WINDOW_SYSTEM
4038 value = XCAR (XCDR (spec)); 4167 value = XCAR (XCDR (spec));
4039 if (NUMBERP (value)) 4168 if (NUMBERP (value))
4040 { 4169 {
4041 struct face *face = FACE_FROM_ID (it->f, it->face_id); 4170 struct face *face = FACE_FROM_ID (it->f, it->face_id);
4042 it->voffset = - (XFLOATINT (value) 4171 it->voffset = - (XFLOATINT (value)
4043 * (FONT_HEIGHT (face->font))); 4172 * (FONT_HEIGHT (face->font)));
4044 } 4173 }
4045#endif /* HAVE_WINDOW_SYSTEM */ 4174#endif /* HAVE_WINDOW_SYSTEM */
4175 }
4046 4176
4047 return 0; 4177 return 0;
4048 } 4178 }
4049 4179
4050 /* Don't handle the other kinds of display specifications 4180 /* Don't handle the other kinds of display specifications
4051 inside a string that we got from a `display' property. */ 4181 inside a string that we got from a `display' property. */
4052 if (it->string_from_display_prop_p) 4182 if (it && it->string_from_display_prop_p)
4053 return 0; 4183 return 0;
4054 4184
4055 /* Characters having this form of property are not displayed, so 4185 /* Characters having this form of property are not displayed, so
4056 we have to find the end of the property. */ 4186 we have to find the end of the property. */
4057 start_pos = *position; 4187 if (it)
4058 *position = display_prop_end (it, object, start_pos); 4188 {
4189 start_pos = *position;
4190 *position = display_prop_end (it, object, start_pos);
4191 }
4059 value = Qnil; 4192 value = Qnil;
4060 4193
4061 /* Stop the scan at that end position--we assume that all 4194 /* Stop the scan at that end position--we assume that all
4062 text properties change there. */ 4195 text properties change there. */
4063 it->stop_charpos = position->charpos; 4196 if (it)
4197 it->stop_charpos = position->charpos;
4064 4198
4065 /* Handle `(left-fringe BITMAP [FACE])' 4199 /* Handle `(left-fringe BITMAP [FACE])'
4066 and `(right-fringe BITMAP [FACE])'. */ 4200 and `(right-fringe BITMAP [FACE])'. */
@@ -4069,12 +4203,16 @@ handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object,
4069 || EQ (XCAR (spec), Qright_fringe)) 4203 || EQ (XCAR (spec), Qright_fringe))
4070 && CONSP (XCDR (spec))) 4204 && CONSP (XCDR (spec)))
4071 { 4205 {
4072 int face_id = lookup_basic_face (it->f, DEFAULT_FACE_ID);
4073 int fringe_bitmap; 4206 int fringe_bitmap;
4074 4207
4075 if (!FRAME_WINDOW_P (it->f)) 4208 if (it)
4076 /* If we return here, POSITION has been advanced 4209 {
4077 across the text with this property. */ 4210 if (!FRAME_WINDOW_P (it->f))
4211 /* If we return here, POSITION has been advanced
4212 across the text with this property. */
4213 return 0;
4214 }
4215 else if (!frame_window_p)
4078 return 0; 4216 return 0;
4079 4217
4080#ifdef HAVE_WINDOW_SYSTEM 4218#ifdef HAVE_WINDOW_SYSTEM
@@ -4085,46 +4223,47 @@ handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object,
4085 across the text with this property. */ 4223 across the text with this property. */
4086 return 0; 4224 return 0;
4087 4225
4088 if (CONSP (XCDR (XCDR (spec)))) 4226 if (it)
4089 { 4227 {
4090 Lisp_Object face_name = XCAR (XCDR (XCDR (spec))); 4228 int face_id = lookup_basic_face (it->f, DEFAULT_FACE_ID);;
4091 int face_id2 = lookup_derived_face (it->f, face_name,
4092 FRINGE_FACE_ID, 0);
4093 if (face_id2 >= 0)
4094 face_id = face_id2;
4095 }
4096 4229
4097 /* Save current settings of IT so that we can restore them 4230 if (CONSP (XCDR (XCDR (spec))))
4098 when we are finished with the glyph property value. */ 4231 {
4232 Lisp_Object face_name = XCAR (XCDR (XCDR (spec)));
4233 int face_id2 = lookup_derived_face (it->f, face_name,
4234 FRINGE_FACE_ID, 0);
4235 if (face_id2 >= 0)
4236 face_id = face_id2;
4237 }
4099 4238
4100 save_pos = it->position; 4239 /* Save current settings of IT so that we can restore them
4101 it->position = *position; 4240 when we are finished with the glyph property value. */
4102 push_it (it); 4241 push_it (it, position);
4103 it->position = save_pos;
4104 4242
4105 it->area = TEXT_AREA; 4243 it->area = TEXT_AREA;
4106 it->what = IT_IMAGE; 4244 it->what = IT_IMAGE;
4107 it->image_id = -1; /* no image */ 4245 it->image_id = -1; /* no image */
4108 it->position = start_pos; 4246 it->position = start_pos;
4109 it->object = NILP (object) ? it->w->buffer : object; 4247 it->object = NILP (object) ? it->w->buffer : object;
4110 it->method = GET_FROM_IMAGE; 4248 it->method = GET_FROM_IMAGE;
4111 it->from_overlay = Qnil; 4249 it->from_overlay = Qnil;
4112 it->face_id = face_id; 4250 it->face_id = face_id;
4113 4251
4114 /* Say that we haven't consumed the characters with 4252 /* Say that we haven't consumed the characters with
4115 `display' property yet. The call to pop_it in 4253 `display' property yet. The call to pop_it in
4116 set_iterator_to_next will clean this up. */ 4254 set_iterator_to_next will clean this up. */
4117 *position = start_pos; 4255 *position = start_pos;
4118 4256
4119 if (EQ (XCAR (spec), Qleft_fringe)) 4257 if (EQ (XCAR (spec), Qleft_fringe))
4120 { 4258 {
4121 it->left_user_fringe_bitmap = fringe_bitmap; 4259 it->left_user_fringe_bitmap = fringe_bitmap;
4122 it->left_user_fringe_face_id = face_id; 4260 it->left_user_fringe_face_id = face_id;
4123 } 4261 }
4124 else 4262 else
4125 { 4263 {
4126 it->right_user_fringe_bitmap = fringe_bitmap; 4264 it->right_user_fringe_bitmap = fringe_bitmap;
4127 it->right_user_fringe_face_id = face_id; 4265 it->right_user_fringe_face_id = face_id;
4266 }
4128 } 4267 }
4129#endif /* HAVE_WINDOW_SYSTEM */ 4268#endif /* HAVE_WINDOW_SYSTEM */
4130 return 1; 4269 return 1;
@@ -4167,18 +4306,19 @@ handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object,
4167 4306
4168 valid_p = (STRINGP (value) 4307 valid_p = (STRINGP (value)
4169#ifdef HAVE_WINDOW_SYSTEM 4308#ifdef HAVE_WINDOW_SYSTEM
4170 || (FRAME_WINDOW_P (it->f) && valid_image_p (value)) 4309 || ((it ? FRAME_WINDOW_P (it->f) : frame_window_p)
4310 && valid_image_p (value))
4171#endif /* not HAVE_WINDOW_SYSTEM */ 4311#endif /* not HAVE_WINDOW_SYSTEM */
4172 || (CONSP (value) && EQ (XCAR (value), Qspace))); 4312 || (CONSP (value) && EQ (XCAR (value), Qspace)));
4173 4313
4174 if (valid_p && !display_replaced_p) 4314 if (valid_p && !display_replaced_p)
4175 { 4315 {
4316 if (!it)
4317 return 1;
4318
4176 /* Save current settings of IT so that we can restore them 4319 /* Save current settings of IT so that we can restore them
4177 when we are finished with the glyph property value. */ 4320 when we are finished with the glyph property value. */
4178 save_pos = it->position; 4321 push_it (it, position);
4179 it->position = *position;
4180 push_it (it);
4181 it->position = save_pos;
4182 it->from_overlay = overlay; 4322 it->from_overlay = overlay;
4183 4323
4184 if (NILP (location)) 4324 if (NILP (location))
@@ -4235,83 +4375,31 @@ handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object,
4235 return 0; 4375 return 0;
4236} 4376}
4237 4377
4238
4239/* Check if SPEC is a display sub-property value whose text should be
4240 treated as intangible. */
4241
4242static int
4243single_display_spec_intangible_p (Lisp_Object prop)
4244{
4245 /* Skip over `when FORM'. */
4246 if (CONSP (prop) && EQ (XCAR (prop), Qwhen))
4247 {
4248 prop = XCDR (prop);
4249 if (!CONSP (prop))
4250 return 0;
4251 prop = XCDR (prop);
4252 }
4253
4254 if (STRINGP (prop))
4255 return 1;
4256
4257 if (!CONSP (prop))
4258 return 0;
4259
4260 /* Skip over `margin LOCATION'. If LOCATION is in the margins,
4261 we don't need to treat text as intangible. */
4262 if (EQ (XCAR (prop), Qmargin))
4263 {
4264 prop = XCDR (prop);
4265 if (!CONSP (prop))
4266 return 0;
4267
4268 prop = XCDR (prop);
4269 if (!CONSP (prop)
4270 || EQ (XCAR (prop), Qleft_margin)
4271 || EQ (XCAR (prop), Qright_margin))
4272 return 0;
4273 }
4274
4275 return (CONSP (prop)
4276 && (EQ (XCAR (prop), Qimage)
4277 || EQ (XCAR (prop), Qspace)));
4278}
4279
4280
4281/* Check if PROP is a display property value whose text should be 4378/* Check if PROP is a display property value whose text should be
4282 treated as intangible. */ 4379 treated as intangible. OVERLAY is the overlay from which PROP
4380 came, or nil if it came from a text property. CHARPOS and BYTEPOS
4381 specify the buffer position covered by PROP. */
4283 4382
4284int 4383int
4285display_prop_intangible_p (Lisp_Object prop) 4384display_prop_intangible_p (Lisp_Object prop, Lisp_Object overlay,
4385 EMACS_INT charpos, EMACS_INT bytepos)
4286{ 4386{
4287 if (CONSP (prop) 4387 int frame_window_p = FRAME_WINDOW_P (XFRAME (selected_frame));
4288 && CONSP (XCAR (prop)) 4388 struct text_pos position;
4289 && !EQ (Qmargin, XCAR (XCAR (prop))))
4290 {
4291 /* A list of sub-properties. */
4292 while (CONSP (prop))
4293 {
4294 if (single_display_spec_intangible_p (XCAR (prop)))
4295 return 1;
4296 prop = XCDR (prop);
4297 }
4298 }
4299 else if (VECTORP (prop))
4300 {
4301 /* A vector of sub-properties. */
4302 int i;
4303 for (i = 0; i < ASIZE (prop); ++i)
4304 if (single_display_spec_intangible_p (AREF (prop, i)))
4305 return 1;
4306 }
4307 else
4308 return single_display_spec_intangible_p (prop);
4309 4389
4310 return 0; 4390 SET_TEXT_POS (position, charpos, bytepos);
4391 return handle_display_spec (NULL, prop, Qnil, overlay,
4392 &position, charpos, frame_window_p);
4311} 4393}
4312 4394
4313 4395
4314/* Return 1 if PROP is a display sub-property value containing STRING. */ 4396/* Return 1 if PROP is a display sub-property value containing STRING.
4397
4398 Implementation note: this and the following function are really
4399 special cases of handle_display_spec and
4400 handle_single_display_spec, and should ideally use the same code.
4401 Until they do, these two pairs must be consistent and must be
4402 modified in sync. */
4315 4403
4316static int 4404static int
4317single_display_spec_string_p (Lisp_Object prop, Lisp_Object string) 4405single_display_spec_string_p (Lisp_Object prop, Lisp_Object string)
@@ -4325,6 +4413,16 @@ single_display_spec_string_p (Lisp_Object prop, Lisp_Object string)
4325 prop = XCDR (prop); 4413 prop = XCDR (prop);
4326 if (!CONSP (prop)) 4414 if (!CONSP (prop))
4327 return 0; 4415 return 0;
4416 /* Actually, the condition following `when' should be eval'ed,
4417 like handle_single_display_spec does, and we should return
4418 zero if it evaluates to nil. However, this function is
4419 called only when the buffer was already displayed and some
4420 glyph in the glyph matrix was found to come from a display
4421 string. Therefore, the condition was already evaluated, and
4422 the result was non-nil, otherwise the display string wouldn't
4423 have been displayed and we would have never been called for
4424 this property. Thus, we can skip the evaluation and assume
4425 its result is non-nil. */
4328 prop = XCDR (prop); 4426 prop = XCDR (prop);
4329 } 4427 }
4330 4428
@@ -4341,7 +4439,7 @@ single_display_spec_string_p (Lisp_Object prop, Lisp_Object string)
4341 return 0; 4439 return 0;
4342 } 4440 }
4343 4441
4344 return CONSP (prop) && EQ (XCAR (prop), string); 4442 return EQ (prop, string) || (CONSP (prop) && EQ (XCAR (prop), string));
4345} 4443}
4346 4444
4347 4445
@@ -4351,8 +4449,8 @@ static int
4351display_prop_string_p (Lisp_Object prop, Lisp_Object string) 4449display_prop_string_p (Lisp_Object prop, Lisp_Object string)
4352{ 4450{
4353 if (CONSP (prop) 4451 if (CONSP (prop)
4354 && CONSP (XCAR (prop)) 4452 && !EQ (XCAR (prop), Qwhen)
4355 && !EQ (Qmargin, XCAR (XCAR (prop)))) 4453 && !(CONSP (XCAR (prop)) && EQ (Qmargin, XCAR (XCAR (prop)))))
4356 { 4454 {
4357 /* A list of sub-properties. */ 4455 /* A list of sub-properties. */
4358 while (CONSP (prop)) 4456 while (CONSP (prop))
@@ -4852,7 +4950,7 @@ get_overlay_strings_1 (struct it *it, EMACS_INT charpos, int compute_stop_p)
4852 /* When called from handle_stop, there might be an empty display 4950 /* When called from handle_stop, there might be an empty display
4853 string loaded. In that case, don't bother saving it. */ 4951 string loaded. In that case, don't bother saving it. */
4854 if (!STRINGP (it->string) || SCHARS (it->string)) 4952 if (!STRINGP (it->string) || SCHARS (it->string))
4855 push_it (it); 4953 push_it (it, NULL);
4856 4954
4857 /* Set up IT to deliver display elements from the first overlay 4955 /* Set up IT to deliver display elements from the first overlay
4858 string. */ 4956 string. */
@@ -4894,10 +4992,11 @@ get_overlay_strings (struct it *it, EMACS_INT charpos)
4894/* Save current settings of IT on IT->stack. Called, for example, 4992/* Save current settings of IT on IT->stack. Called, for example,
4895 before setting up IT for an overlay string, to be able to restore 4993 before setting up IT for an overlay string, to be able to restore
4896 IT's settings to what they were after the overlay string has been 4994 IT's settings to what they were after the overlay string has been
4897 processed. */ 4995 processed. If POSITION is non-NULL, it is the position to save on
4996 the stack instead of IT->position. */
4898 4997
4899static void 4998static void
4900push_it (struct it *it) 4999push_it (struct it *it, struct text_pos *position)
4901{ 5000{
4902 struct iterator_stack_entry *p; 5001 struct iterator_stack_entry *p;
4903 5002
@@ -4924,7 +5023,7 @@ push_it (struct it *it)
4924 p->u.stretch.object = it->object; 5023 p->u.stretch.object = it->object;
4925 break; 5024 break;
4926 } 5025 }
4927 p->position = it->position; 5026 p->position = position ? *position : it->position;
4928 p->current = it->current; 5027 p->current = it->current;
4929 p->end_charpos = it->end_charpos; 5028 p->end_charpos = it->end_charpos;
4930 p->string_nchars = it->string_nchars; 5029 p->string_nchars = it->string_nchars;
@@ -5382,6 +5481,7 @@ reseat_1 (struct it *it, struct text_pos pos, int set_stop_p)
5382 { 5481 {
5383 it->bidi_it.first_elt = 1; 5482 it->bidi_it.first_elt = 1;
5384 it->bidi_it.paragraph_dir = NEUTRAL_DIR; 5483 it->bidi_it.paragraph_dir = NEUTRAL_DIR;
5484 it->bidi_it.disp_pos = -1;
5385 } 5485 }
5386 5486
5387 if (set_stop_p) 5487 if (set_stop_p)
@@ -12688,11 +12788,30 @@ set_cursor_from_row (struct window *w, struct glyph_row *row,
12688 GLYPH_BEFORE and GLYPH_AFTER, and it came from a string 12788 GLYPH_BEFORE and GLYPH_AFTER, and it came from a string
12689 positioned between POS_BEFORE and POS_AFTER in the 12789 positioned between POS_BEFORE and POS_AFTER in the
12690 buffer. */ 12790 buffer. */
12691 struct glyph *stop = glyph_after; 12791 struct glyph *start, *stop;
12692 EMACS_INT pos = pos_before; 12792 EMACS_INT pos = pos_before;
12693 12793
12694 x = -1; 12794 x = -1;
12695 for (glyph = glyph_before + incr; 12795
12796 /* GLYPH_BEFORE and GLYPH_AFTER are the glyphs that
12797 correspond to POS_BEFORE and POS_AFTER, respectively. We
12798 need START and STOP in the order that corresponds to the
12799 row's direction as given by its reversed_p flag. If the
12800 directionality of characters between POS_BEFORE and
12801 POS_AFTER is the opposite of the row's base direction,
12802 these characters will have been reordered for display,
12803 and we need to reverse START and STOP. */
12804 if (!row->reversed_p)
12805 {
12806 start = min (glyph_before, glyph_after);
12807 stop = max (glyph_before, glyph_after);
12808 }
12809 else
12810 {
12811 start = max (glyph_before, glyph_after);
12812 stop = min (glyph_before, glyph_after);
12813 }
12814 for (glyph = start + incr;
12696 row->reversed_p ? glyph > stop : glyph < stop; ) 12815 row->reversed_p ? glyph > stop : glyph < stop; )
12697 { 12816 {
12698 12817
@@ -17111,7 +17230,7 @@ cursor_row_p (struct glyph_row *row)
17111static int 17230static int
17112push_display_prop (struct it *it, Lisp_Object prop) 17231push_display_prop (struct it *it, Lisp_Object prop)
17113{ 17232{
17114 push_it (it); 17233 push_it (it, NULL);
17115 17234
17116 if (STRINGP (prop)) 17235 if (STRINGP (prop))
17117 { 17236 {
@@ -18040,6 +18159,8 @@ See also `bidi-paragraph-direction'. */)
18040 bytepos--; 18159 bytepos--;
18041 itb.charpos = pos; 18160 itb.charpos = pos;
18042 itb.bytepos = bytepos; 18161 itb.bytepos = bytepos;
18162 itb.nchars = -1;
18163 itb.frame_window_p = FRAME_WINDOW_P (SELECTED_FRAME ()); /* guesswork */
18043 itb.first_elt = 1; 18164 itb.first_elt = 1;
18044 itb.separator_limit = -1; 18165 itb.separator_limit = -1;
18045 itb.paragraph_dir = NEUTRAL_DIR; 18166 itb.paragraph_dir = NEUTRAL_DIR;