diff options
| author | Eli Zaretskii | 2011-06-04 10:41:44 +0300 |
|---|---|---|
| committer | Eli Zaretskii | 2011-06-04 10:41:44 +0300 |
| commit | fec2107c58835163dc3b08c0a833a5072aa1fca9 (patch) | |
| tree | fa112f71d61bd4166aa56fb80da80357455906ab /src | |
| parent | ea9fafe0937ebd99780610a7c1451ca08b013702 (diff) | |
| parent | 57f97249c8e8673df19219e1f5cba478ea23024d (diff) | |
| download | emacs-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/ChangeLog | 74 | ||||
| -rw-r--r-- | src/bidi.c | 264 | ||||
| -rw-r--r-- | src/dispextern.h | 18 | ||||
| -rw-r--r-- | src/keyboard.c | 2 | ||||
| -rw-r--r-- | src/xdisp.c | 609 |
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 @@ | |||
| 1 | 2011-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 | |||
| 1 | 2011-06-02 Paul Eggert <eggert@cs.ucla.edu> | 75 | 2011-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 | ||
| 63 | static Lisp_Object bidi_type_table, bidi_mirror_table; | 63 | static 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. */ | ||
| 551 | static void | 557 | static void |
| 552 | bidi_line_init (struct bidi_it *bidi_it) | 558 | bidi_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. */ | ||
| 582 | static inline int | ||
| 583 | bidi_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. */ |
| 570 | static EMACS_INT | 635 | static 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. */ |
| 742 | void | 819 | void |
| 743 | bidi_init_it (EMACS_INT charpos, EMACS_INT bytepos, struct bidi_it *bidi_it) | 820 | bidi_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 | ||
| 831 | static inline int | 912 | static inline int |
| 832 | bidi_explicit_dir_char (int c) | 913 | bidi_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. */ |
| 1013 | static int | 1109 | static int |
| 1014 | bidi_resolve_explicit (struct bidi_it *bidi_it) | 1110 | bidi_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. */ |
| 1081 | static bidi_type_t | 1181 | static bidi_type_t |
| 1082 | bidi_resolve_weak (struct bidi_it *bidi_it) | 1182 | bidi_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. */ | ||
| 1396 | static bidi_type_t | 1501 | static bidi_type_t |
| 1397 | bidi_type_of_next_char (struct bidi_it *bidi_it) | 1502 | bidi_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. */ |
| 1422 | static int | 1527 | static int |
| 1423 | bidi_level_of_next_char (struct bidi_it *bidi_it) | 1528 | bidi_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. */ |
| 1820 | struct bidi_it { | 1820 | struct 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 | ||
| 2947 | extern void bidi_init_it (EMACS_INT, EMACS_INT, struct bidi_it *); | 2953 | extern void bidi_init_it (EMACS_INT, EMACS_INT, int, struct bidi_it *); |
| 2948 | extern void bidi_move_to_visually_next (struct bidi_it *); | 2954 | extern void bidi_move_to_visually_next (struct bidi_it *); |
| 2949 | extern void bidi_paragraph_init (bidi_dir_t, struct bidi_it *, int); | 2955 | extern void bidi_paragraph_init (bidi_dir_t, struct bidi_it *, int); |
| 2950 | extern int bidi_mirror_char (int); | 2956 | extern 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); |
| 2957 | int line_bottom_y (struct it *); | 2963 | int line_bottom_y (struct it *); |
| 2958 | int display_prop_intangible_p (Lisp_Object); | 2964 | int display_prop_intangible_p (Lisp_Object, Lisp_Object, EMACS_INT, EMACS_INT); |
| 2959 | void resize_echo_area_exactly (void); | 2965 | void resize_echo_area_exactly (void); |
| 2960 | int resize_mini_window (struct window *, int); | 2966 | int 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 *); | |||
| 3005 | extern Lisp_Object lookup_glyphless_char_display (int, struct it *); | 3011 | extern Lisp_Object lookup_glyphless_char_display (int, struct it *); |
| 3006 | extern int calc_pixel_width_or_height (double *, struct it *, Lisp_Object, | 3012 | extern int calc_pixel_width_or_height (double *, struct it *, Lisp_Object, |
| 3007 | struct font *, int, int *); | 3013 | struct font *, int, int *); |
| 3014 | extern EMACS_INT compute_display_string_pos (EMACS_INT, int); | ||
| 3015 | extern 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); | |||
| 812 | static int try_cursor_movement (Lisp_Object, struct text_pos, int *); | 812 | static int try_cursor_movement (Lisp_Object, struct text_pos, int *); |
| 813 | static int trailing_whitespace_p (EMACS_INT); | 813 | static int trailing_whitespace_p (EMACS_INT); |
| 814 | static unsigned long int message_log_check_duplicate (EMACS_INT, EMACS_INT); | 814 | static unsigned long int message_log_check_duplicate (EMACS_INT, EMACS_INT); |
| 815 | static void push_it (struct it *); | 815 | static void push_it (struct it *, struct text_pos *); |
| 816 | static void pop_it (struct it *); | 816 | static void pop_it (struct it *); |
| 817 | static void sync_frame_with_window_matrix_rows (struct window *); | 817 | static void sync_frame_with_window_matrix_rows (struct window *); |
| 818 | static void select_frame_for_redisplay (Lisp_Object); | 818 | static 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); |
| 885 | static int face_before_or_after_it_pos (struct it *, int); | 885 | static int face_before_or_after_it_pos (struct it *, int); |
| 886 | static EMACS_INT next_overlay_change (EMACS_INT); | 886 | static EMACS_INT next_overlay_change (EMACS_INT); |
| 887 | static int handle_display_spec (struct it *, Lisp_Object, Lisp_Object, | ||
| 888 | Lisp_Object, struct text_pos *, EMACS_INT, int); | ||
| 887 | static int handle_single_display_spec (struct it *, Lisp_Object, | 889 | static 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); |
| 890 | static int underlying_face_id (struct it *); | 892 | static int underlying_face_id (struct it *); |
| 891 | static int in_ellipses_for_invisible_text_p (struct display_pos *, | 893 | static 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. */ | ||
| 3096 | EMACS_INT | ||
| 3097 | compute_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. */ | ||
| 3145 | EMACS_INT | ||
| 3146 | compute_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) | |||
| 3743 | static enum prop_handled | 3821 | static enum prop_handled |
| 3744 | handle_display_prop (struct it *it) | 3822 | handle_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. */ | ||
| 3886 | static int | ||
| 3887 | handle_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 | ||
| 3875 | static int | 3991 | static int |
| 3876 | handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object, | 3992 | handle_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 | |||
| 4242 | static int | ||
| 4243 | single_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 | ||
| 4284 | int | 4383 | int |
| 4285 | display_prop_intangible_p (Lisp_Object prop) | 4384 | display_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 | ||
| 4316 | static int | 4404 | static int |
| 4317 | single_display_spec_string_p (Lisp_Object prop, Lisp_Object string) | 4405 | single_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 | |||
| 4351 | display_prop_string_p (Lisp_Object prop, Lisp_Object string) | 4449 | display_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 | ||
| 4899 | static void | 4998 | static void |
| 4900 | push_it (struct it *it) | 4999 | push_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) | |||
| 17111 | static int | 17230 | static int |
| 17112 | push_display_prop (struct it *it, Lisp_Object prop) | 17231 | push_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; |